Port knocking is a technique often described as security through obscurity. It allows a server administrator to make a service port invisible to the outside world by blocking incoming traffic and only opening the port after a predefined sequence of packets is received.
For example, instead of leaving SSH (TCP port 22) exposed, the server can block it entirely. Only after receiving TCP SYN packets on ports 2222
, 3333
, and 4444
in order will the firewall temporarily allow connections to port 22.
This approach can be useful when you don’t want to expose any ports directly to the public Internet but still need remote access to your machine. On Ubuntu, one common implementation is knockd
, a port knocking daemon that uses libpcap
to sniff packets at a low level.
By default, knockd listens for TCP SYN packets as knocking signals but does not respond to them (to avoid leaking information that could help an attacker guess the sequence). From the client’s perspective, a successful knock before establishing SSH looks like this:
(Server port 22 is blocked)
1. Client sends TCP SYN to port 2222
2. Client sends TCP SYN to port 3333
3. Client sends TCP SYN to port 4444
(Server port 22 is open now)
4. Client performs TCP three-way handshake on port 22 and starts the SSH handshake
Problems can arise if you’re connecting through a VPN. Instead of the silent behavior expected during port knocking, you might see responses from the server too early:
(Server port 22 is blocked)
1. Client send TCP SYN to port 2222
2. Server replies TCP SYN-ACK
3. Client sends TCP RST to port 2222
4. Client sends TCP SYN to port 3333
5. Server replies TCP SYN-ACK
6. Client sends TCP RST to port 3333
7. Client sends TCP SYN to port 4444
8. Server replies TCP SYN-ACK
9. Client sends TCP RST to port 4444
10. Client attempts TCP handshake on port 22 with success and starts SSH handshake afterwards. However, after sending SSH banner to the server, handshake stalls.
11. After timeout, server sends TCP RST to close the connection.
At first glance, this is confusing: why would the server respond with SYN-ACKs during the knocking phase, when it should be silent?
Examining the server’s packet capture tells a different story:
1. Client sends TCP SYN to port 2222
2. Client sends TCP SYN to port 2222 (retransmission)
3. Client sends TCP SYN to port 2222 (retransmission)
4. Client sends TCP SYN to port 2222 (retransmission)
5. Client sends TCP SYN to port 2222 (retransmission)
6. Client sends TCP SYN to port 2222 (retransmission)
(Server never sees packets for ports 3333 and 4444)
From the server’s perspective, the client looks like it keeps retrying the first knock, but in reality the client never retransmitted. Instead, the VPN infrastructure interfered.
The VPN likely misinterpreted the knocking traffic: It noticed the first SYN went unanswered and tried to "help" by retransmitting. It even injected SYN-ACKs, pretending to be the server. It then suppressed the following SYN packets (3333, 4444), possibly flagging the sequence as suspicious port scanning behavior. As a result, the knocking sequence broke down and SSH never completed.
Since TCP SYN packets can be mishandled by VPN providers, one workaround is to switch to UDP-based knocking. UDP is connectionless and less likely to be filtered or manipulated in this way.
Server side configuration (/etc/knockd.conf
or similar):
sequence = 2222:udp,3333:udp,4444:udp
client side command:
knock -v $IP -u 2222 3333 4444
Switching to UDP often resolves these issues, allowing the knocking sequence to pass through VPN infrastructure cleanly.
Takeaway: Port knocking can effectively hide your services from casual scans, but when VPNs sit in the middle, unexpected behavior may break the sequence. If TCP knocking causes trouble, try UDP.
Comments NOTHING