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.