How to Set Up Port Knocking for SSH on RHEL 7

Port knocking is a stealthy technique for controlling access to network services by requiring a client to send connection attempts to a predefined sequence of closed ports before a firewall rule opens the target port. When applied to SSH, it effectively hides port 22 from port scanners and automated brute-force bots — the SSH daemon is completely invisible until the correct knock sequence is performed. On RHEL 7, port knocking is implemented using the knockd daemon from the EPEL repository, combined with iptables rules to enforce the default-deny policy on the SSH port. This guide walks through the complete setup, from installing knockd to testing the sequence and layering it with Fail2Ban for defense-in-depth.

Prerequisites

  • A running RHEL 7 system with root or sudo access
  • An active internet connection or local EPEL mirror
  • SSH access to the server — do not close your existing session until the configuration is verified
  • Basic familiarity with iptables and firewall concepts
  • The firewalld service should be stopped or configured to use iptables backend, as knockd works directly with iptables

Step 1: Enable the EPEL Repository and Install knockd

The knockd package is not available in the default RHEL 7 repositories. You must first enable the Extra Packages for Enterprise Linux (EPEL) repository. If your system is registered with Red Hat Subscription Manager, you can enable the optional channel; otherwise, install the EPEL release RPM directly.

# Install EPEL release for RHEL 7
yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

# Verify the repository is enabled
yum repolist | grep epel

# Install knockd
yum install -y knock-server

The package name on RHEL 7/EPEL is knock-server, which provides both the knockd daemon and the knock client utility. Confirm the installation succeeded:

rpm -qa | grep knock
knock --version

Step 2: Configure the Default-Deny iptables Rule for SSH

Port knocking only works if SSH is blocked by default. Before configuring knockd, add an iptables rule that drops all new incoming connections to port 22. This must be done carefully to avoid locking yourself out — ensure you have an active session or out-of-band console access.

# First, save the current iptables rules as a baseline
iptables-save > /root/iptables-baseline.rules

# Drop all new incoming TCP connections to SSH port 22
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -j DROP

# Verify the rule is in place
iptables -L INPUT -n --line-numbers

To make this rule persistent across reboots, save it with iptables-save and restore it at boot via the iptables service:

yum install -y iptables-services
systemctl enable iptables
iptables-save > /etc/sysconfig/iptables

Step 3: Create the knockd Configuration File

The main configuration file for knockd is /etc/knockd.conf. This file defines one or more sequences. Each sequence specifies the ports to knock, the TCP flags to match, and the commands to execute when the sequence succeeds or times out. Edit the file as follows:

vi /etc/knockd.conf

Add the following configuration:

[options]
    UseSyslog
    logfile = /var/log/knockd.log
    interface = eth0

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

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

Key configuration options explained:

  • sequence: The ordered list of ports to knock. Choose ports that are not in use on your system. Avoid common ports like 80 or 443.
  • seq_timeout: All knocks in the sequence must arrive within this many seconds.
  • tcpflags: Match only SYN packets, which are the initial packets of a TCP connection attempt.
  • %IP%: knockd substitutes the source IP address of the client that completed the knock sequence.
  • interface: Replace eth0 with your actual network interface (check with ip link).

For stronger security, use a longer sequence with higher port numbers and vary the protocols:

[openSSH]
    sequence    = 12345,23456,34567,45678
    seq_timeout = 15
    tcpflags    = syn
    command     = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -m state --state NEW -j ACCEPT

Step 4: Start and Enable the knockd Service

With the configuration file in place, start the knockd service and enable it to start at boot:

systemctl start knockd
systemctl enable knockd
systemctl status knockd

The output should show the service as active and running. Check the log file to confirm knockd is listening:

tail -f /var/log/knockd.log

You should see a line indicating it has started and is watching on the configured interface.

Step 5: Test Port Knocking from a Client

From a separate machine (or using a second terminal with an existing SSH session as a safety net), test the knock sequence using the knock client:

# Install the knock client on the remote machine
yum install -y knock

# Send the opening knock sequence to the server
knock -v 192.168.1.100 7000 8000 9000

# Immediately attempt SSH connection
ssh [email protected]

# After the session, close the firewall rule
knock -v 192.168.1.100 9000 8000 7000

Check the server-side log to see the knock sequence being registered:

tail /var/log/knockd.log
# Example output:
# [2026-05-17 12:00:01] 10.0.0.5: openSSH: Stage 1
# [2026-05-17 12:00:01] 10.0.0.5: openSSH: Stage 2
# [2026-05-17 12:00:02] 10.0.0.5: openSSH: Stage 3
# [2026-05-17 12:00:02] 10.0.0.5: openSSH: OPEN SESAME
# [2026-05-17 12:00:02] 10.0.0.5: running command: /sbin/iptables -I INPUT ...

You can also verify the dynamic iptables rule was inserted:

iptables -L INPUT -n --line-numbers

Step 6: Combining Port Knocking with Fail2Ban

Port knocking reduces exposure significantly, but any client that successfully knocks is then permitted to attempt SSH login. Adding Fail2Ban provides a second layer of defence by banning IPs after repeated failed authentication attempts.

yum install -y fail2ban

# Create a local override configuration
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
vi /etc/fail2ban/jail.local

Ensure the SSH jail is enabled in jail.local:

[sshd]
enabled  = true
port     = ssh
logpath  = /var/log/secure
maxretry = 3
bantime  = 3600
systemctl start fail2ban
systemctl enable fail2ban
systemctl status fail2ban

Security Considerations

Port knocking is a security-through-obscurity technique and should never replace strong SSH hardening. The following additional measures are recommended:

  • Disable password authentication in /etc/ssh/sshd_config — use SSH key pairs only (PasswordAuthentication no).
  • Change the sequence ports regularly, especially if they may have been observed by network monitoring.
  • Use a longer, more complex knock sequence with a mix of UDP and TCP packets to thwart replay attacks.
  • Consider using fwknop (Single Packet Authorization) as a more cryptographically robust alternative to simple port knocking.
  • Monitor /var/log/knockd.log and /var/log/secure regularly for anomalies.
  • Ensure the iptables-save state is updated whenever you make persistent rule changes.

Port knocking on RHEL 7 is a powerful complement to standard SSH hardening. By keeping SSH completely invisible to casual scanners and automated attack tools, and combining the sequence-based access control of knockd with the brute-force mitigation of Fail2Ban, you create a robust, layered access control system that dramatically reduces your server’s attack surface. Regularly audit your knock logs and SSH authentication logs to catch any unusual access patterns early.