Effective Strategies to Secure SSH Against Brute Force Attacks on FreeBSD Systems


3 views

Every sysadmin running exposed SSH services has seen those endless failed login attempts in auth logs. On my FreeBSD 13.2 server last month, fail2ban processed over 1.4 million intrusion attempts. This isn't just noise - unsecured SSH is the #1 vector for server compromises.

Before reaching for tools, implement these essentials:

# /etc/ssh/sshd_config
Port 22222  # Change from default 22
PermitRootLogin no
MaxAuthTries 3
LoginGraceTime 30
AllowUsers yourusername

The gold standard for automated protection. FreeBSD installation:

pkg install py38-fail2ban
sysrc fail2ban_enable=YES
service fail2ban start

Configure a custom jail:

# /usr/local/etc/fail2ban/jail.d/ssh.conf
[sshd]
enabled = true
port = 22222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 86400
findtime = 3600

Make your SSH port invisible until you "knock":

# Install knockd
pkg install knock

# Config in /usr/local/etc/knockd.conf
[options]
    logfile = /var/log/knockd.log

[openSSH]
    sequence = 7000,8000,9000
    seq_timeout = 10
    command = /sbin/ipfw add 100 allow tcp from %IP% to any 22222
    tcpflags = syn

[closeSSH]
    sequence = 9000,8000,7000
    seq_timeout = 10
    command = /sbin/ipfw delete 100

For critical systems, add another factor:

pkg install google-authenticator
google-authenticator

# Add to /etc/pam.d/sshd:
auth required pam_google_authenticator.so

Combine with pf firewall rules:

# /etc/pf.conf
table  persist
block in quick proto tcp from  to any port 22222
pass in proto tcp from any to any port 22222 \
    keep state (max-src-conn 5, max-src-conn-rate 3/5)

Use these commands to audit attempts:

# Top attacking IPs
grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -nr

# GeoIP mapping
pkg install GeoIP
geoiplookup $(zgrep "Failed" /var/log/auth.log | awk '{print $11}' | sort -u)

Modern servers face relentless automated attacks targeting SSH ports. My FreeBSD 13.2-RELEASE server logged over 2.3 million failed login attempts last month alone, primarily targeting common usernames like 'root', 'admin', and 'test'. These attacks aren't personal - they're automated scripts scanning the entire IPv4 address space.

The most effective solution I've implemented is Fail2Ban with custom filtering rules. Here's my working configuration for FreeBSD:

# /usr/local/etc/fail2ban/jail.local
[sshd]
enabled  = true
port     = ssh
filter   = sshd
logpath  = /var/log/auth.log
maxretry = 3
findtime = 3600
bantime  = 86400
action   = iptables[name=SSH, port=ssh, protocol=tcp]

This configuration bans IPs after 3 failed attempts within an hour, blocking them for 24 hours. For FreeBSD specifically, you'll need to modify the action line:

action = pf[name=SSH, port=ssh, protocol=tcp]

Port knocking adds an extra authentication layer before SSH becomes visible. Here's a simple implementation using knockd:

# /usr/local/etc/knockd.conf
[options]
    UseSyslog

[openSSH]
    sequence    = 7000,8000,9000
    seq_timeout = 5
    command     = /sbin/ipfw add 1 allow tcp from %IP% to any 22
    tcpflags    = syn

[closeSSH]
    sequence    = 9000,8000,7000
    seq_timeout = 5
    command     = /sbin/ipfw del 1
    tcpflags    = syn

Disabling password authentication entirely is the nuclear option, but extremely effective:

# /etc/ssh/sshd_config
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
PermitRootLogin without-password

Generate SSH keys properly:

ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519

FreeBSD's built-in PF firewall offers excellent rate limiting:

# /etc/pf.conf
table  persist
block quick from 

pass in on $ext_if proto tcp to port ssh \
    keep state (max-src-conn 5, max-src-conn-rate 3/10, \
    overload  flush global)

While changing the default port (22) isn't true security, it does reduce noise. Combine with other measures:

# /etc/ssh/sshd_config
Port 2222
Port 22

Then block port 22 at the firewall level, maintaining emergency access via 2222.

Automated log watching catches patterns missed by other tools. This script identifies suspicious activity:

#!/bin/sh
tail -n0 -F /var/log/auth.log | \
while read line; do
    echo "$line" | grep -q "Failed password" && \
    echo "$line" | mail -s "SSH Login Attempt" admin@example.com
done

For FreeBSD, adjust the log path to /var/log/messages.

For business-critical servers, Cloudflare Spectrum can proxy SSH connections with their global threat intelligence:

# Example Spectrum configuration
{
  "proxy": {
    "tcp": {
      "22": {
        "origin": "your.server.ip:22",
        "protection": {
          "dos": "on",
          "brute_force": "on"
        }
      }
    }
  }
}