SSH Port Knocking

SSH port hiding via knock sequence - BTS SIO SISR

Objective

Implement a Port Knocking system to protect SSH access. The SSH port will remain closed by default and only open after knocking a specific sequence of ports in the correct order.

This security-through-obscurity technique adds a layer of protection against port scans and SSH brute force attempts.

Prerequisites

  • Debian 11 / Ubuntu server
  • SSH functional and configured
  • Root or sudo access
  • iptables installed (usually present by default)
  • Physical or rescue console access (in case of SSH lockout)
CRITICAL WARNING

Before configuring port knocking, ensure you have:
  • Physical console access or via hypervisor (VirtualBox, ESXi, etc.)
  • Network configuration backup
  • Parallel SSH session open for testing
Risk: locking yourself out in case of configuration error.

Complete Procedure

Step 1: knockd Installation

Update repositories and install knockd:

apt update
apt install knockd -y

Verify installation:

knockd --version

Step 2: knockd Configuration

Edit main configuration file:

nano /etc/knockd.conf

Replace content with following configuration:

[options]
 UseSyslog

[openSSH]
 sequence = 7000,8000,9000
 seq_timeout = 15
 command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
 tcpflags = syn

[closeSSH]
 sequence = 9000,8000,7000
 seq_timeout = 15
 command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
 tcpflags = syn

Save and exit (Ctrl+O, Enter, Ctrl+X)

Detailed configuration explanations:
  • [options]: global configuration section
  • UseSyslog: enables logging in system logs
  • [openSSH]: rule to open SSH port
  • sequence = 7000,8000,9000: port sequence to knock in order
  • seq_timeout = 15: maximum time (in seconds) to complete sequence
  • %IP%: variable automatically replaced by client source IP
  • tcpflags = syn: listens only to TCP SYN packets
  • [closeSSH]: rule to close SSH port (reverse sequence)

Step 3: Network Interface Configuration

Edit configuration file to specify network interface:

nano /etc/default/knockd

Modify following lines:

START_KNOCKD=1
KNOCKD_OPTS="-i eth0"
Note: Replace eth0 with your network interface name.
To identify your interface:
ip a

Common interfaces: eth0, ens33, enp0s3, ens18

Step 4: Firewall Configuration (iptables)

Block SSH port by default:

iptables -A INPUT -p tcp --dport 22 -j DROP

Allow established SSH connections (important to not cut active sessions):

iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Save iptables rules:

apt install iptables-persistent -y
netfilter-persistent save
iptables explanations:
  • -A INPUT: adds rule to INPUT chain (incoming traffic)
  • -p tcp --dport 22: targets TCP port 22 (SSH)
  • -j DROP: silently rejects packets
  • -m state --state ESTABLISHED,RELATED: allows already established connections
  • iptables-persistent: preserves rules after reboot

Step 5: knockd Startup

Enable knockd at system startup:

systemctl enable knockd

Start service:

systemctl start knockd

Check status:

systemctl status knockd
Expected result:
Service should be "active (running)" and listening on specified interface.

Client-Side Usage

knock Client Installation (Linux)

On client machine (Debian/Ubuntu):

apt install knockd -y

Open SSH Port

Knock sequence to open port:

knock SERVER_IP_ADDRESS 7000 8000 9000

Example:

knock 192.168.1.100 7000 8000 9000

SSH connection immediately after:

Close SSH Port

Knock reverse sequence to close:

knock 192.168.1.100 9000 8000 7000

Alternative: nmap (if knock not available)

for PORT in 7000 8000 9000; do nmap -Pn --max-retries 0 -p $PORT 192.168.1.100; done

Alternative: telnet (Windows/Linux)

telnet 192.168.1.100 7000
(Ctrl+C to exit)
telnet 192.168.1.100 8000
(Ctrl+C)
telnet 192.168.1.100 9000
(Ctrl+C)
ssh [email protected]

Automated bash Script

Create script to simplify usage:

nano ~/knock-ssh.sh

Script content:

#!/bin/bash
SERVER="192.168.1.100"
knock $SERVER 7000 8000 9000
sleep 1
ssh user@$SERVER

Make script executable:

chmod +x ~/knock-ssh.sh

Usage:

~/knock-ssh.sh

Verification

knockd Service Verification

systemctl status knockd

Should display "active (running)"

Logs Verification

tail -f /var/log/syslog | grep knockd

Should display knock attempts in real time

iptables Rules Verification

iptables -L INPUT -v -n

Should show dynamic rules added by knockd after successful knock

Test from Remote Machine

  1. Attempt direct SSH connection (should fail):
    ssh [email protected]
    # Should remain blocked or display "Connection refused"
  2. Knock sequence:
    knock 192.168.1.100 7000 8000 9000
  3. Immediate SSH connection (should succeed):

Close Sequence Test

From another SSH session (don't close active session):

knock 192.168.1.100 9000 8000 7000

Attempt new SSH connection from another terminal: should fail

Security and Limitations

Port Knocking Advantages

  • Hides SSH service from automated port scans
  • Reduces SSH brute force attempts
  • Adds additional security layer
  • No modification of standard SSH client required
  • Precise knock attempt logs

Limitations and Drawbacks

Limitations of this technique (BTS SIO level):
  • Security through obscurity (no sequence encryption)
  • Vulnerable to network sniffing (attacker can capture sequence)
  • Complex for non-technical users
  • Lockout risk with misconfiguration
  • No protection against replay attacks
  • Does NOT replace SSH key authentication

Additional Security Recommendations

Port knocking MUST ALWAYS be combined with:
  1. SSH key authentication (disable passwords)
  2. Fail2ban to ban suspicious IPs
  3. SSH port change (e.g., 2222 instead of 22)
  4. SSH user restriction (AllowUsers in sshd_config)
  5. Root SSH account deactivation (PermitRootLogin no)

Hardened SSH Configuration

Edit /etc/ssh/sshd_config:

nano /etc/ssh/sshd_config

Recommended parameters:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AllowUsers user1 user2
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2

Restart SSH:

systemctl restart sshd

Log Monitoring

# SSH logs
tail -f /var/log/auth.log

# knockd logs
tail -f /var/log/syslog | grep knockd

# iptables logs (if enabled)
tail -f /var/log/kern.log

Variant: Port Knocking with OTP Authentication

To go further (outside standard BTS scope), solutions exist combining port knocking and OTP (One-Time Password) like fwknop (Firewall Knock Operator) using SPA (Single Packet Authorization).

More Robust Alternatives

  • VPN (WireGuard, OpenVPN): SSH access via encrypted tunnel
  • SSH Bastion (Jump Host): intermediate server for bouncing
  • SSH via Tor: traffic anonymization
  • 2FA/MFA: two-factor authentication (Google Authenticator, Yubikey)

Troubleshooting

Problem: knockd Does Not Start

journalctl -xe -u knockd

Check:

  • Syntax of /etc/knockd.conf file
  • Network interface name in /etc/default/knockd
  • Configuration file permissions

Problem: Sequence Does Not Work

  • Verify network interface is properly specified
  • Check logs in real time: tail -f /var/log/syslog
  • Test with tcpdump to see if packets arrive:
    tcpdump -i eth0 port 7000 or port 8000 or port 9000

Problem: Locked Out After Configuration

Access via physical console or hypervisor and:

systemctl stop knockd
iptables -F
iptables -P INPUT ACCEPT
systemctl restart sshd

Key Points for BTS Oral Exam

  • Port Knocking: security-through-obscurity technique
  • Principle: knock port sequence to unlock a service
  • knockd: Linux daemon listening to sequences and executing iptables rules
  • Limitations: vulnerable to sniffing, doesn't replace strong authentication
  • Complementarity: must be combined with SSH keys, fail2ban, firewall
  • Usage: protection against automated scans and SSH brute force
  • Alternatives: VPN, SSH bastion, 2FA are more robust