Port Knocking


Why consider skipping knockd? Your mileage may vary, but I've encountered bugs, as highlighted in the following links:

To avoid the hassle of finding workarounds for potential issues with updates, I've resorted to directly managing the associated firewall chains.

Start by ensuring that SSH is not allowed in /etc/ufw/user.rules:

ufw status numbered | egrep "22 .* ALLOW"

If port 22 or any other port configured for sshd is found, execute:

ufw delete <rule number>

Now, update /etc/ufw/before.rules to include the following rules:

    
  # should follow right after the default FILTER chain
  
    :TRAFFIC - [0:0]
    :SSH-INPUT - [0:0]
    :SSH-INPUT-TWO - [0:0]
    -A INPUT -j TRAFFIC
    -A TRAFFIC -m state --state ESTABLISHED,RELATED -j ACCEPT
    -A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 22 -m recent --rcheck --seconds 15 --name SSH2 -j ACCEPT
    -A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH2 --remove -j DROP
    -A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 333 -m recent --rcheck --name SSH1 -j SSH-INPUT-TWO
    -A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH1 --remove -j DROP
    -A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 222 -m recent --rcheck --name SSH0 -j SSH-INPUT
    -A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH0 --remove -j DROP
    -A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 111 -m recent --name SSH0 --set -j DROP
    -A SSH-INPUT -m recent --name SSH1 --set -j DROP
    -A SSH-INPUT-TWO -m recent --name SSH2 --set -j DROP
    -A TRAFFIC -j DROP

These chains dynamically allow SSH access for 15 seconds upon detecting tcp packets on ports 111, 222, 333 in that sequence in the recent history for related connections. After reloading the rules with ufw reload, you are good to go.

You can use any client to send the packet sequence (111, 222, 333), or create a custom solution using nmap:

File ~/bin/knock:

    
#!/bin/bash
      HOST=$1
      shift
      for ARG in "$@"
      do
          nmap -Pn --host-timeout 200 --max-retries 0 -p $ARG $HOST
      done

Usage:

    
    ~/bin/knock <domain|ip> 111 222 333
      ssh user@<domain|ip>

If you've already taken basic security measures such as using fail2ban to thwart brute force SSH attacks and are looking to further strengthen your security, considering options like knockd or rolling your own port knocking solution can be a worthwhilestep. This is just the starting point for staying ahead of bad actors.