Port knocking is a security technique that hides your SSH port from network scanners by keeping it firewalled until a specific sequence of connection attempts is made. On RHEL 9, combining knockd with nftables lets you expose SSH only to clients who know the secret knock sequence, dramatically reducing brute-force exposure. This tutorial walks through installing knockd, configuring a knock sequence, hardening the firewall, and testing the full workflow. By the end, port 22 will be invisible to scanners but fully accessible to authorized users who knock correctly.

Prerequisites

  • RHEL 9 server with a non-root sudo user
  • SSH access to the server before beginning (do not lock yourself out)
  • EPEL repository available or internet access to enable it
  • A second terminal or out-of-band access as a safety net during configuration

Step 1 — Install knockd

knockd is available in the EPEL repository. Install EPEL first, then install the knock-server package, which provides both the knockd daemon and the knock client utility.

dnf install -y epel-release
dnf install -y knock-server

Verify the installation:

knockd --version
which knock

Step 2 — Configure the Knock Sequence

Edit /etc/knockd.conf to define an open sequence (ports 7000, 8000, 9000 TCP) and a close sequence (ports 9000, 8000, 7000 TCP). The commands use nftables to add or remove a rule allowing port 22.

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

[openSSH]
    sequence    = 7000,8000,9000
    seq_timeout = 10
    tcpflags    = syn
    command     = /sbin/nft add rule inet filter input tcp dport 22 ip saddr %IP% accept
    cmd_timeout = 30

[closeSSH]
    sequence    = 9000,8000,7000
    seq_timeout = 10
    tcpflags    = syn
    command     = /sbin/nft delete rule inet filter input tcp dport 22 ip saddr %IP% accept

Save the file. The %IP% placeholder is replaced by knockd with the connecting client’s IP address, so only the knocking host gains access.

Step 3 — Block Port 22 by Default with nftables

Before enabling knockd, ensure port 22 is blocked by default in your nftables ruleset. Back up the current ruleset first.

# Back up current rules
nft list ruleset > /root/nftables-backup-$(date +%F).nft

# Ensure the filter table and input chain exist with a default drop policy
# View the current ruleset
nft list ruleset

# Remove any existing rule that unconditionally allows port 22
# Example: if handle 5 allows port 22, delete it:
# nft delete rule inet filter input handle 5

# Confirm port 22 is no longer open by listing the chain
nft list chain inet filter input

If you use firewalld, disable it or configure it to pass through to nftables manually managed rules to avoid conflicts:

systemctl stop firewalld
systemctl disable firewalld

Step 4 — Configure knockd to Listen on the Correct Interface

Tell knockd which network interface to monitor. Edit /etc/sysconfig/knockd (or the systemd service override) to set the interface:

# Edit the knockd sysconfig file
cat > /etc/sysconfig/knockd << 'EOF'
KNOCKD_OPTS="-i eth0"
EOF

Replace eth0 with your actual interface name (use ip link show to find it, e.g., ens3, enp1s0).

Step 5 — Enable and Start the knockd Service

Enable knockd to start on boot and start it now:

systemctl enable --now knockd
systemctl status knockd

Check the log to confirm knockd is watching the interface:

tail -f /var/log/knockd.log

Step 6 — Test the Port Knock from a Client

From a remote client machine that has the knock package installed, send the knock sequence, then attempt SSH:

# Install knock client on the client machine (RHEL/Fedora)
dnf install -y knock

# Send the open sequence to the server
knock SERVER_IP 7000 8000 9000

# Immediately SSH (the 30-second window is open)
ssh user@SERVER_IP

# After your session, close the port from the client
knock SERVER_IP 9000 8000 7000

To verify SSH is blocked without knocking, attempt a direct connection before sending the sequence — it should time out. Check /var/log/knockd.log on the server to see the knock events recorded.

Conclusion

You have configured port knocking on RHEL 9 using knockd and nftables. SSH is now invisible to port scanners and inaccessible to attackers who do not know the knock sequence, while remaining fully usable by authorized clients who send the correct sequence. Rotate your knock sequences periodically and consider using UDP knocks or longer sequences for additional obscurity.

Next steps: How to Configure Suricata IDS/IPS on RHEL 9, How to Set Up Two-Factor Authentication for SSH on RHEL 9, and How to Harden nftables Firewall Rules on RHEL 9.