Michael Rash, Security Researcher

Port Forwarding via Single Packet Authorization

Digg How to Safely Connect to Your Closed Internal Systems via SPA and NAT Port Forwarding via Single Packet Authorization Most port knocking or Single Packet Authorization implementations offer the ability to passively authenticate clients for access only to a locally running server (such as SSHD). That is, the daemon that monitors a firewall log or that sniffs the wire for port knock sequences or SPA packets can only reconfigure a local firewall to allow the client to access a local socket. This is usually accomplished by allowing the client to connect to the server port by putting an ACCEPT rule in the INPUT chain for iptables firewalls, or adding a pass rule for ipfw firewalls for the client source IP address. For local servers, this works well enough, but suppose that you ultimately want to access an SSH daemon that is running on an internal system? If the SPA software is deployed on a Linux gateway that is protecting a non-routable internal network and has a routable external IP address, it is inconvenient to first have to login to the gateway and then login to the internal system.
       Since the 1.9.2 release, fwknop has supported the creation of inbound port forwarding rules for iptables firewalls via the DNAT target in the PREROUTING chain after receiving a valid SPA packet. This allows direct access to internal systems on non-routable address space from the open Internet. Here is an example - suppose that you are running fwknop on Linux gateway system that is protecting an internal network and has an external routable address of Now, suppose that you are on travel somewhere (so your source IP address is not predictable), and you would like to access an SSH server that is running on the internal system Finally, because fwknop is deployed, iptables is configured in a default-DROP stance against all attempts to connect with any SSH daemon; nmap cannot even tell that there is any SSH server listening. Access is granted only after a valid SPA packet is passively sniffed by the fwknopd daemon.

With inbound NAT support configured in fwknop (the config is mentioned below), here is an illustration of fwknop usage in order to gain direct access to SSHD on the from an external network (note that the -R argument instructs the fwknop client to automatically resolve the current IP address - in this case):
[externalhost]$ fwknop -A tcp/22 --Forward-access,5001 \
-R -D

[+] Starting fwknop client (SPA mode)...
    Resolving external IP via:
    Got external address:

[+] Enter an encryption key. This key must match a key in the file
    /etc/fwknop/access.conf on the remote system.

Encryption Key:

[+] Building encrypted Single Packet Authorization (SPA) message...
[+] Packet fields:

        Random data:    6862733471944039
        Username:       root
        Timestamp:      1207404612
        Version:        1.9.3
        Type:           2 (FORWARD access mode)
        Forward access:,5001
        SHA256 digest:  hE4zGafLtQiQiFrep+cSq/wVO7SQhwh65hmLr+ehtrw

[+] Sending 206 byte message to over udp/62201...
Now, port 5001 on the external IP address is forwarded through to the SSH server on the internal system, but only for the client IP [externalhost]$ ssh -p 5001 mbr@
Graphically, this scenario is illustrated by the following picture. The dotted lines represent the SPA packet from the fwknop client (which only needs to be sniffed by the fwknopd daemon running on the Linux gateway), and the solid arrows represent the SSH connection from the external client through to the internal SSH server.

DNAT SPA access to internal SPA server
On the Linux gateway system that is running the fwknop daemon, executing the following command illustrates the additions to the iptables policy to allow the SSH connection to be forwarded to the internal system. These firewall rules are automatically deleted after a 30 second timeout (this is tunable), but any existing SSH connection remains open through the use of the iptables connection tracking capability.
[gateway]# fwknopd --fw-list
[+] Listing rules in fwknop chains...
Chain FWKNOP_INPUT (1 references)
 pkts bytes target prot opt in out source   destination

Chain FWKNOP_FORWARD (1 references)
 pkts bytes target prot opt in out source     destination
   19  2740 ACCEPT tcp  --  *  *    tcp dpt:22

Chain FWKNOP_PREROUTING (1 references)
 pkts bytes target prot opt in out source     destination
    1    60 DNAT   tcp  --  *  *    tcp \
dpt:5001 to:
Finally, the /etc/fwknop/access.conf is configured like so to facilitate this example, and the ENABLE_IPT_FORWARDING variable is also enabled in the /etc/fwknop/fwknop.conf file: SOURCE: ANY;
OPEN_PORTS: tcp/22;
KEY: aesdemokey;
In addition to explaining the inbound NAT support offered by fwknop, this blog post also announces the 1.9.3 release of fwknop. Here is the complete ChangeLog:
  • Added MASQUERADE and SNAT support to complement inbound DNAT connections for SPA packets that request --Forward-access to internal systems. This functionality is only enabled when both ENABLE_IPT_FORWARDING and ENABLE_IPT_SNAT are set, and is configured by two new variables IPT_MASQUERADE_ACCESS and IPT_SNAT_ACCESS which define the iptables interface to creating SNAT rules. The SNAT supplements of DNAT rules are not usually necessary because internal systems usually have a route back out to the Internet, but this feature accommodates those systems that do not have such a route. By default, the MASQUERADE target is used if ENABLE_IPT_SNAT is enabled because this means that the external IP does not have to be manually defined. However, the external IP can be defined by the SNAT_TRANSLATE_IP variable.
  • Added hex_dump() feature for fwknop client so that raw encrypted SPA packet data can be displayed in --verbose mode.
  • When ENABLE_IPT_FORWARDING is set, added a check for the value of the /proc/sys/net/ipv4/ip_forward file to ensure that the local system allows packets to be forwarded. Unless ENABLE_PROC_IP_FORWARD is disabled, then fwknopd will automatically set the ip_forward file to "1" if it is set to "0" (again, only if ENABLE_IPT_FORWARDING is enabled).
  • Minor bugfix to remove sys_log() call in legacy port knocking mode.
  • Minor bugfix to expand both the Id and Revision tags via the svn:keywords directive.