How to Automatically Block Failed SSH Login Attempts in Cygwin on Windows Server 2008


36 views

If you're running Cygwin's SSH daemon on Windows Server 2008, you've probably noticed relentless brute force attacks in your Event Viewer logs. These attacks typically show:

  • 5-6 failed login attempts per second
  • Multiple IP addresses rotating
  • Dictionary-based username/password combinations

Manually adding IPs to the Windows Firewall is:

  • Time-consuming
  • Reactive rather than proactive
  • Ineffective against distributed attacks

The most effective approach is to install Fail2Ban, which can:

# Install required packages
apt-cyg install python python-setuptools git
git clone https://github.com/fail2ban/fail2ban.git
cd fail2ban
python setup.py install

Create a custom jail configuration:

[cygwin-ssh]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600

Since Cygwin logs differently than Linux, create a custom filter:

[Definition]
failregex = ^.*sshd.*Failed password for .* from <HOST> port \d+.*$
ignoreregex =

For those preferring PowerShell, here's a script to parse Event Viewer:

# PowerShell script to block repeated offenders
$failedLogins = Get-WinEvent -LogName "Application" | 
    Where-Object {$_.Id -eq 0} | 
    Group-Object -Property {$_.Properties[0].Value}

foreach ($ip in $failedLogins | Where-Object Count -gt 3) {
    New-NetFirewallRule -DisplayName "Block SSH $($ip.Name)" -Direction Inbound -Action Block -RemoteAddress $ip.Name
}

Regularly check your blocked IPs with:

# View current bans
fail2ban-client status cygwin-ssh

# Unban an IP if needed
fail2ban-client set cygwin-ssh unbanip 192.168.1.1

When running Cygwin's SSHD service on Windows Server 2008, you'll inevitably face brute force attacks. The default configuration makes your server a tempting target for automated login attempts. The Windows Event Viewer shows these failed attempts piling up at alarming rates - sometimes 5-6 per second from various IPs.

Manually adding each malicious IP to the firewall is impractical. The volume of attacks makes this approach unsustainable. We need an automated solution that can:

  • Parse Windows Event Logs for failed SSH attempts
  • Identify repeat offenders
  • Add firewall rules dynamically
  • Optionally whitelist known good IPs

Here's a PowerShell script that monitors failed logins and blocks suspicious IPs automatically. Save this as SSH-Blocker.ps1:


# SSH-Blocker.ps1 - Automated IP blocking for Cygwin SSHD
$maxAttempts = 5 # Block after this many failures
$blockDuration = 24 # Hours to block the IP
$logPath = 'C:\cygwin\var\log\sshd.log' # Cygwin SSH log path

# Parse logs and find offenders
$failedAttempts = Select-String -Path $logPath -Pattern 'Failed password' | 
    ForEach-Object {
        if ($_ -match 'from (\d+\.\d+\.\d+\.\d+)') {
            $matches[1]
        }
    }

# Count and filter IPs
$offenders = $failedAttempts | Group-Object | 
    Where-Object { $_.Count -ge $maxAttempts } |
    Select-Object -ExpandProperty Name

# Add firewall rules for offenders
foreach ($ip in $offenders) {
    $ruleName = "Block SSH $ip"
    if (-not (Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue)) {
        New-NetFirewallRule -DisplayName $ruleName -Direction Inbound -Action Block 
            -RemoteAddress $ip -Protocol TCP -LocalPort 22
        Write-Host "Blocked IP: $ip"
    }
}

For a more robust solution, consider setting up Fail2Ban within Cygwin:


# Install Fail2Ban in Cygwin
apt-cyg install fail2ban

# Configure /etc/fail2ban/jail.local
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/sshd.log
maxretry = 5
bantime = 86400

When implementing these solutions, remember that Windows Firewall rules take precedence. Ensure your automated solution:

  • Doesn't conflict with existing rules
  • Properly handles rule expiration if desired
  • Logs its actions for review

Set up scheduled tasks to run your blocking script regularly. For the PowerShell solution, create a scheduled task to run every 5 minutes:


# Create scheduled task via PowerShell
$action = New-ScheduledTaskAction -Execute 'Powershell.exe' 
    -Argument '-NoProfile -ExecutionPolicy Bypass -File "C:\scripts\SSH-Blocker.ps1"'
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 5)
Register-ScheduledTask -TaskName "SSH Brute Force Blocker" -Action $action -Trigger $trigger -RunLevel Highest