Single Packet Authorization
A Comprehensive Guide to Strong Service Hardening with fwknop

Michael Rash
     Founder, cipherdyne.org

Updated: October, 2012


Table of Contents:
1. fwknop Quick Start This section illustrates basic usage of fwknop to harden an SSH daemon with Single Packet Authorization (SPA). For the remainder of this document, two Linux systems will be used for illustration purposes: spaclient (IP: 1.1.1.1) and spaserver (IP: 2.2.2.2). The SSH daemon along with iptables and fwknopd are deployed on the spaserver system, and the SSH and fwknop clients are deployed on the spaclient system. This section assumes that fwknop has been installed properly on both systems, and installation details can be found in the Installing fwknop section below. We'll use the following network diagram to serve as a reference throughout:
fwknop network diagram
Figure 1: Single Packet Authorization - general network diagram

Note that in the diagram above, the spaclient is on a home/office network that is behind a firewall. All packets sent out through this firewall are NAT'd to have source IP 1.1.1.1, and this is the IP that systems on the external Internet will see for communications initiated by the spaclient system.

In general, using fwknop to wrap sshd with a Single Packet Authorization layer involves the following steps:
  1. Define an SPA encryption key in /etc/fwknop/access.conf - this can involve GnuPG keys if you prefer.
  2. Configure the local firewall policy to block all incoming connections to sshd.
  3. Start fwknopd
  4. Use the fwknop client from a remote system to generate a valid encrypted SPA packet as required by the access.conf file on the server.
  5. Access sshd with an ssh client as normal.
If you already have fwknopd installed and configured, basic usage of the fwknop client to access sshd just looks like this:
[spaclient]$ fwknop -A tcp/22 -R -D spaserver
Enter encryption password:
 
[spaclient]$ ssh -l mbr spaserver
mbr@spaserver's password:
 
[spaserver]$ hostname
spaserver
Now, keeping the above outline in mind, the remainder of this Quick Start follows: 1.1 Configuring fwknopd to Protect sshd First, on the spaserver system, configure fwknopd with a shared encryption key. This key allows fwknopd to decrypt SPA packets that have been encrypted with the Rijndael cipher from systems running fwknop clients. All encryption key information and access control directives for the fwknopd server are placed within the /etc/fwknop/access.conf file, so we add our key (along with some additional variables that will be explained later) there:

[spaserver]# cat /etc/fwknop/access.conf
SOURCE: ANY;
OPEN_PORTS: tcp/22; ### for ssh (change for access to other services)
KEY: yourdecryptkey;
FW_ACCESS_TIMEOUT: 30;
With the /etc/fwknop/access.conf setup, it's time to make sure that the /etc/fwknop/fwknopd.conf file is also suitably configured. It is important to configure the fwknopd daemon to sniff on a specific interface, although for Linux systems the default is eth0. If you are running fwknopd on different platform such as FreeBSD or OpenBSD you will want to set the PCAP_INTF to the appropriate interface name. There are many variables in the /etc/fwknop/fwknopd.conf file, but most are set to sensible defaults. As an illustration, here is the PCAP_INTF variable and it is set to eth0:
[spaserver]# grep PCAP_INTF /etc/fwknop/fwknopd.conf
PCAP_INTF eth0;
Now, start the fwknopd daemon:
[spaserver]# service fwknop start
fwknop start/running, process 29134
At this point fwknopd is up and running and sniffing the eth0 Ethernet interface. By default fwknopd does not sniff every packet though - it uses a bpf filter to only sniff for UDP packets to port 62201. This can be changed though by altering the PCAP_FILTER variable in the fwknopd.conf file and restarting fwknopd. To confirm that fwknopd is sniffing the network, after start up it writes a few messages to syslog as follows:
[spaserver]# grep fwknopd /var/log/syslog
Sep 22 10:40:59 spaserver fwknopd[4079]: Starting fwknopd
Sep 22 10:40:59 spaserver fwknopd[4079]: Added jump rule from chain: INPUT to chain: FWKNOP_INPUT
Sep 22 10:40:59 spaserver fwknopd[4079]: PCAP filter is: udp port 62201
Sep 22 10:40:59 spaserver fwknopd[4079]: Starting fwknopd main event loop.
1.2 Default-Drop firewall policy Single Packet Authorization is designed to allow the local firewall to be configured in a "default drop" stance for a protected service such as sshd. On the spaserver system we'll assume that eth0 is the external interface and connections to sshd should be blocked on this interface. The following iptables commands accomplish this, and are compatible with fwknopd.
[spaserver]# iptables -I INPUT 1 -i eth0 -p tcp --dport 22 -j DROP
[spaserver]# iptables -I INPUT 1 -i eth0 -p tcp --dport 22 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
The iptables setup script written for the No Starch Press book "Linux Firewalls: Attack Detection and Response" also configures iptables as described above - i.e. does not allow incoming connections to sshd on eth0, but keeps any connection open that makes it into the established state. (Disclaimer: I wrote this book, but there are many other configuration setup scripts that one can use besides the one developed for the book.) For any production firewall you will want to simply not allow incoming connections to sshd and ensure that connection tracking for established connections is enabled. 1.3 Gaining access to sshd with the fwknop client Now let's move to the fwknop client system spaclient and try to gain access to SSH running on the spaserver system. We verify first that iptables is blocking our attempts to talk to SSH:
[spaclient]$ nmap -P0 -n -p 22 spaserver
 
Starting Nmap 5.00 ( http://nmap.org ) at 2012-09-22 10:50 EDT
Interesting ports on 2.2.2.2:
PORT STATE SERVICE
22/tcp filtered ssh
 
Nmap done: 1 IP address (1 host up) scanned in 2.10 seconds
So, to gain access to SSH, execute the fwknop client (note that most of the output below is for informational purposes since we've included the --verbose command line argument):
[spaclient]$ fwknop -A tcp/22 -R -D spaserver --verbose
Enter encryption password:
 
[+] Resolved external IP (via http://www.cipherdyne.org/cgi-bin/myip) as: 1.1.1.1
Enter encryption password:
 
FKO Field Values:
=================
 
   Random Value: 1805793899630599
       Username: mbr
      Timestamp: 1348325239
    FKO Version: 2.0.3
   Message Type: 1
 Message String: 1.1.1.1,tcp/22
     Nat Access: <NULL>
    Server Auth: <NULL>
 Client Timeout: 0
    Digest Type: 3
 
Encoded Data: 1805793899630599:bWJy:1348325239:2.0.3:1:MS4xLjEuMSx0Y3AvMjI
 
SPA Data Digest: 3MCsRnyNAmxT4NL7DhBDp5Cwl061KodGMJAEaPlvPIA
 
Final Packed/Encrypted/Encoded Data:
 
85yR1UXTnKQRKbIyLgjVJZPEdbhZJr//+ctXyL38a3VMvs2/NDH775WwVRe1EBnhqoEE9pFPrqHv5d8CVfh//FyOoqwveoBs+zbgb1LvoE4f6/9UJFybUWrApsB6z/0U9p1dPCdcbe1blK/H8hUgbOvWrKA7m8j30
 
Generating SPA packet:
protocol: udp
port: 62201
IP/host: 2.2.2.2
send_spa_packet: bytes sent: 161
After fwknopd has received the incoming SPA packet and has validated that 1) the SPA packet has not been replayed, 2) the SPA packet has been encrypted with a key defined in the access.conf file so that it is properly decrypted by fwknopd, and 3) the packet contains a request for access that is authorized, then access is granted to sshd. This is done by adding an ACCEPT rule to the FWKNOP_INPUT chain for the 1.1.1.1 IP to tcp/22 for 30 seconds before deleting it. From the spaserver system, you can see the ACCEPT rule as well as the messages fwknopd writes to syslog as follows:
[spaserver]# fwknopd --fw-list
Listing rules in fwknopd iptables chains...
Chain FWKNOP_INPUT (1 references)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  1.1.1.1              0.0.0.0/0            tcp dpt:22 /* _exp_1348326362 */
 
[spaserver]# grep fwknopd /var/log/syslog
Sep 22 10:50:32 spaserver fwknopd[4079]: (stanza #1) SPA Packet from IP: 1.1.1.1 received with access source match
Sep 22 10:50:32 spaserver fwknopd[4079]: Added Rule to FWKNOP_INPUT for 1.1.1.1, tcp/22 expires at 1348326362
While the ACCEPT rule still exists, you can ssh from the spaclient system into spaserver:
[spaclient]$ ssh -l mbr spaserver
mbr@spaserver's password:
 
[spaserver]$ hostname
spaserver
Once the 30 second expiration time arrives, fwknopd removes the ACCEPT rule for 1.1.1.1 to tcp/22, but the ssh connection remains open through the use of the iptables connection tracking capability. Here is the syslog message that fwknopd writes when the rule is removed:
Sep 22 10:50:02 spaserver fwknopd[4079]: Removed rule 1 from FWKNOP_INPUT with expire time of 1348326362.
After the ACCEPT rule is removed, sshd is once again invisible to scans:
[spaclient]$ nmap -P0 -n -p 22 spaserver
 
Starting Nmap 5.00 ( http://nmap.org ) at 2012-09-22 10:50 EDT
Interesting ports on 2.2.2.2:
PORT STATE SERVICE
22/tcp filtered ssh
 
Nmap done: 1 IP address (1 host up) scanned in 2.10 seconds
As usual, if there are any problems with the Quick Start instructions or you have additional questions, please email <mbr[at]cipherdyne.org>. 2. Introduction This tutorial is a comprehensive guide to the usage, deployment, and theory behind the fwknop project. After reading this document, you will be armed with the requisite knowledge to use fwknop together with a firewall configured in a "default drop" stance to wrap a cryptographically strong passive authentication/authorization layer around arbitrary services. This layer is called Single Packet Authorization (SPA), and can apply to all sorts of services from sshd and OpenVPN to mail protocols like POP and IMAP and even to HTTP. The end goal is to make it infeasible for anyone armed with nmap to even detect services protected in this way - let alone exploit a vulnerability or attempt to brute force a password (as is commonly done against accessible SSH daemons). By using the fwknop client to generate a valid SPA message, access is granted temporarily to the protected service from whatever IP address is encrypted within the SPA packet. An SPA packet is "valid" when it is encrypted by a strong cipher (fwknop supports both Rijndael for symmetric encryption and GnuPG for asymmetric encryption) with an expected key, and has not been replayed as verified by a SHA-256 digest. No two SPA packets are identical because they contain 16 bytes of random data before being encrypted in addition to leveraging natural differences that Rijndael in CBC mode and GnuPG provide from one byte to the next. Once the firewall has been temporarily reconfigured to allow access and a session is established, a state tracking mechanism supported by the firewall can be used to keep a session established even after the rule that allows access is removed.

Users of firewalls find value in the idea that traffic to a service can be blocked from all but a few pre-defined networks according to the firewall policy. Few people question whether this is valuable from a security perspective - firewalls generally enhance security (the occasional firewall vulnerability not withstanding). The PK/SPA strategy extends the notion of filtering traffic for a set of services by adding a lightweight crypto layer to allow temporary access from networks that cannot be anticipated when the firewall policy is written. This provides service concealment by default, and the SPA strategy asserts that there is value in this.

There are many people looking for vulnerabilities in server software, and when a clever person finds a brand new vulnerability, this person has the opportunity to use it for good - disclosing it responsibly to the vendor so that it can be fixed - or ill - using it for malicious purposes. If the person chooses the later and wants to exploit the vulnerability, then one of the first steps is to find a list of targets. If an exploit applies to a piece of server software - say SSH - that typically runs on a particular port (tcp/22 in this case), then a common technique for identifying suitable targets is to use nmap to conduct a port sweep across many networks looking for SSH servers listening on port 22. With SPA deployed, anyone building such a list of targets will not be able to include your system in their list. Both PK and SPA are designed to protect server software behind a default-drop packet filter and are not effective at protecting against client-side exploits (such as an attack for a vulnerability in a web browser). 2.1 What is Port Knocking? Port knocking is defined as the communication of authentication information over closed (or at least logged) ports, together with the dynamic reconfiguration of a default-drop firewall policy to allow access to authenticated connections. The goal of port knocking is to provide a simplistic mechanism by which a remote user can be authenticated before access is granted to a service such as an SSH daemon. The basic architecture is that a port knocking client generates a series of packets to a set of ports which are logged on a port knocking server, and if this series of ports builds a proper sequence then access will be granted to the requested service. Port knocking, in contrast to most Single Packet Authorization implementations, uses packet headers instead of packet payloads to communicate authentication information. A port knock sequence can be a simple shared sequence of ports, or it can be more advanced and involve encryption and passive OS fingerprinting. 2.2 What is Single Packet Authorization? Single Packet Authorization (SPA) is defined similarly to port knocking, except that instead of just using packet headers, SPA communicates authentication information within the payload portion of a packet. Because packet payloads are used, SPA offers many enhancements over PK such as protection from replay attacks, minimal network footprint (in terms of what IDS's may alert on - PK sequences look like port scans after all), the ability to transmit full commands and complex access requests, and better performance. Although SPA is referred to in this document as Single Packet Authorization, fwknop really performs both authentication and authorization, which are not the same thing. "Authentication" is the process of proving who you are, whereas "authorization" is the process of determining whether someone is allowed to perform an operation. 2.3 What is fwknop? fwknop is free and open source software that supports Single Packet Authorization. The fwknop "server" supports iptables firewalls on Linux, ipfw firewalls on FreeBSD and Mac OS X, and pf on OpenBSD. The fwknop client runs on Linux, Mac OS X, *BSD, and Windows systems (either under Cygwin or using the fwknop UI). Current versions of fwknop are written in C, but there are older versions that are written in perl. These older versions support port knocking, but this has been deprecated in favor of SPA in the C versions. When fwknop was first released in 2004, it was the first software implementation that combined port knocking with passive OS fingerprinting to add an additional authentication parameter to port knock sequences. In May of 2005, the first version of fwknop that supported full SPA mode communications (with encrypted and non-replayable payloads) was released, and the development pace has remained strong ever since. A new release is made on average every few months, and there is a healthy list of contributors who suggest features and write patches to the fwknop code. As of November 2008, fwknop is available as a Debian package for Debian and Ubuntu systems (thanks to Franck Joncourt), and as an RPM for Red Hat and Fedora systems (thanks to Mirek Trmac). All fwknop source code is versioned within git, and can be viewed with the gitweb.cgi interface. 2.4 fwknop License (GPL v2) fwknop is released as open source software under the terms of the GNU Public License (GPL) version 2. For reference, the full text of the GPL can be downloaded from the Free Software Foundation. There are no plans at the present time to change the licensing terms of fwknop to a different license (such as GPL v3 or a BSD license), but this may change at any time without notice. However, fwknop will always remain an open source project free for use by anyone.

In March 2005, a patent for SPA was filed with the US Patent and Trademark Office, and the patent appeared in their database in March 2007 although it has not yet been issued. The patent was filed mostly as a defensive measure so that it would be more difficult for a patent troll to inflict damage upon the development of fwknop. Open source projects need to protect themselves as aggressively as possible in an uncertain legal climate that makes frivolous patent litigation an expensive proposition. 3. Installing fwknop 3.1 Downloading the latest fwknop release Many Linux distributions such as Fedora, RHEL, Debian, Ubuntu, Slackware, OpenWRT, and more also make fwknop available through their own standard package management systems (yum, apt-get, etc.). It is frequently a good idea to install fwknop through the package management system that is native to your distribution, but if you want to compile and install from sources, the latest release of the fwknop source code is available at: http://www.cipherdyne.org/fwknop/download/ . 3.2 Supported Platforms The fwknop code is generally quite portable across various platforms, and the table below tracks the current state of support across a broad set of operating systems. Following this table are sections that make notes about fwknop operations on specific operating systems. If you are able to get fwknop to function on a platform that is not listed below, please contact the fwknop developers so that it can be included. On the development side, if you see that a particular fwknop component is not currently supported on your OS of choice (say, GnuPG support on Android), and you develop a patch to add support, please submit the patch so it can be added to the next fwknop release. Your patch will be attributed to you in the CREDITS file.

Component / Technology Fedora/RHEL/CentOS Debian/Ubuntu OpenWRT FreeBSD Mac OS X OpenBSD iPhone Android Windows
fwknop client Y Y Y Y Y Y Y Y Y
fwknopd server Y Y Y Y Y Y N N N
GnuPG Support Y Y Y Y Y Y N N N
fwknopd server-side NAT Y Y Y N N N N N N
Native Windows binary (client) N/A Y
libfko library Y Y Y Y Y Y Y Y Y
perl libfko bindings Y Y Y Y Y Y N N Unknown
python libfko bindings Y Y Y Y Y Y N N Unknown
3.3 Notes on Specific Platforms 3.3.1 Linux Notes Most new features in the fwknop world are prototyped on Linux first and then ported to other operating systems. The fwknop client is usually the easiest part of fwknop to get working on non-Linux systems because it doesn't depend on support for various features within the local firewall and it doesn't have to worry about differences in firewall command syntax (iptables vs. ipfw vs. pf). However, as noted in the Supported Platforms section above, the fwknopd daemon supports many non-Linux platforms. Now, for features that are specific to Linux, the fwknopd daemon relies on the iptables "comment" match in order to store the expiration time for new ACCEPT rules upon receiving a valid SPA packet. At init time, fwknopd verifies whether the comment match is available, and then uses it as follows for new rules. Note that all new rules are added by fwknopd to the FWKNOP_INPUT chain to ensure separation with the rest of the iptables policy.
/sbin/iptables -t filter -A FWKNOP_INPUT -p 6 -s 1.1.1.1 --dport 22 -m comment --comment _exp_1348688232 -j ACCEPT
In terms of other dependencies, if you want the fwknopd daemon to compile and run then you will need to install libpcap. This is usually best achieved by installing a package such as "libpcap-dev" or "libpcap-devel" through your distribution package manager (yum, apt-get, etc.). 3.3.2 FreeBSD Notes The fwknop client, server, and libfko library all function properly on FreeBSD systems. Note that fwknopd maintains rule expiration times via ipfw "// _exp_<expire_time>" comments, and rules added by fwknopd go into set 1 by default (see the IPFW_ACTIVE_SET_NUM variable in the /etc/fwknop/fwknopd.conf file).
/sbin/ipfw add 10000 set 1 pass 6 from 1.1.1.1 to me dst-port 22 setup keep-state // _exp_1346784046
3.3.3 Mac OS X Notes The fwknop client functions equivalently on Mac OS X systems as it does on other systems, but things are slightly different for the fwknopd server due to differences between ipfw on Mac OS X vs. ipfw on FreeBSD. These differences are handled by this patch, which changes how fwknopd deals with ipfw sets on Mac OS X vs. FreeBSD. 3.3.4 OpenBSD Notes On OpenBSD, the fwknopd server makes use of a dedicated pf anchor to which fwknopd will add and delete rules. This anchor must be linked into the pf policy (typically done by adding it into the /etc/pf.conf file), and fwknopd runs a check at init time to ensure that the anchor exists. The PF_ANCHOR_NAME variable in the /etc/fwknop/fwknopd.conf config file controls the name of the anchor, with the default being set as follows:
PF_ANCHOR_NAME fwknop;
For rule expiration, fwknopd leverages the pf "label" capability to mark new rules with an expiration time. 3.3.5 iPhone Notes There is an fwknop iPhone client, but is has not yet been uploaded to the Apple iStore. In addition, it does not yet support the encryption of SPA packets with GnuPG, but Rijndael mode works just fine. 3.3.6 Android Notes There is an fwknop Android client, and similarly to the iPhone the Android client supports Rijndael for SPA packet encryption but not yet GnuPG. 3.3.7 Windows Notes Support on Windows is in the form of a native Windows fwknop client binary along with the libfko code being portable to Windows. The client is also known to work under Cygwin, and there is a UI as well. However, GnuPG support is not yet functional. In addition, there are no current plans to support a Windows firewall in fwknopd, but theoretically it could be developed. 3.4 Installing from Sources As of this writing, the latest release of fwknop is 2.0.3, and compiling and installing fwknop is easily done via the following steps. Note that this will result in fwknopd configuration files being installed in /etc/fwknop/ along with normal binaries in /usr/bin/ and /usr/sbin/ (most command output removed for brevity). Also, the GnuPG signature for the fwknop-2.0.3.tar.gz tarball is verified (always do this!) using the key available here - you'll need to import this key with "$ gpg --import <key file>" if it is not already on your GnuPG keyring.
[spaserver]$ wget http://www.cipherdyne.org/fwknop/download/fwknop-2.0.3.tar.gz
[spaserver]$ wget http://www.cipherdyne.org/fwknop/download/fwknop-2.0.3.tar.gz.asc
[spaserver]$ gpg --verify fwknop-2.0.3.tar.gz.asc
gpg: Signature made Tue 04 Sep 2012 10:49:32 PM EDT using DSA key ID 0D3E7410
gpg: Good signature from "Michael Rash (Signing key for cipherdyne.org projects) <mbr@cipherdyne.org>"
 
[spaserver]$ tar xfz fwknop-2.0.3.tar.gz
[spaserver]$ cd fwknop-2.0.3
[spaserver]$ ./configure --prefix=/usr --sysconfdir=/etc && make
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking target system type... x86_64-unknown-linux-gnu
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
...
/bin/bash ../libtool --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I. -I..     -g -O2 -Wall -fstack-protector-all -fstack-protector -fPIE -pie -D_FORTIFY_SOURCE=2 -MT base64.lo -MD -MP -MF .deps/base64.Tpo -c -o base64.lo base64.c
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -I.. -g -O2 -Wall -fstack-protector-all -fstack-protector -D_FORTIFY_SOURCE=2 -MT base64.lo -MD -MP -MF .deps/base64.Tpo -c base64.c  -fPIC -DPIC -o .libs/base64.o
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -I.. -g -O2 -Wall -fstack-protector-all -fstack-protector -D_FORTIFY_SOURCE=2 -MT base64.lo -MD -MP -MF .deps/base64.Tpo -c base64.c -fPIE -pie -o base64.o >/dev/null 2>&1
...
 
[spaserver]$ su
Password:
 
[spaserver]# make install
Making install in lib
make[1]: Entering directory `/home/mbr/git/fwknop.git/lib'
make[2]: Entering directory `/home/mbr/git/fwknop.git/lib'
test -z "/usr/lib" || /bin/mkdir -p "/usr/lib"
 /bin/bash ../libtool   --mode=install /usr/bin/install -c   libfko.la '/usr/lib'
libtool: install: /usr/bin/install -c .libs/libfko.so.0.0.3 /usr/lib/libfko.so.0.0.3
libtool: install: (cd /usr/lib && { ln -s -f libfko.so.0.0.3 libfko.so.0 || { rm -f libfko.so.0 && ln -s libfko.so.0.0.3 libfko.so.0; }; })
...
 
[spaserver]# which fwknop
/usr/bin/fwknop
 
[spaserver]# fwknop -V
fwknop client 2.0.3, FKO protocol version 2.0.3
 
[spaserver]# which fwknopd
/usr/sbin/fwknopd
 
[spaserver]# fwknopd -V
fwknopd server 2.0.3
Also, before running that last make install, it is recommended to run the fwknop test suite to make sure that fwknop seems to operate normally on your system.

If fwknop is supported by your OS package management system, you may want to install using it instead. For example, on Ubuntu systems, you can install via:
[spaclient]# apt-get install fwknop-client
[spaserver]# apt-get install fwknop-server
3.5 The fwknop Test Suite Given that fwknop supports several different modes of operation - including the usage of various encryption algorithms, cryptographic hashes, and firewall binaries - it is important to automate the testing and verification of proper fwknop execution. This is the job of the fwknop test suite which is bundled within the fwknop sources (see the test/ directory). Nearly every aspect of fwknop operations is examined and verified by the test suite. In this section we'll examine test suite operations and show how it can be used in the development of new fwknop features and functionality. In general, when a new feature is developed, a corresponding test or set of tests is added to the test suite to ensure proper implementation. This same process also applies to bug fixes. 3.5.1 Running the Test Suite When installing fwknop on any system it is recommended to run the test suite to verify that run time aspects of fwknop work properly. The test suite can be executed before the final "make install" step in the installation process. This way, if the test suite indicates there are critical problems after fwknop has been compiled (unlikely assuming that fwknop is being installed on a supported platform), then the installation can be aborted and bugs filed before binaries have been installed in important filesystem locations. After compilation with "./configure --prefix=/usr ... && make" the test suite can be run as follows from the test/ directory. Note that this must be done as root, and in this particular case we also instruct the test suite to recompile fwknop so that it can verify that there are no compilation warnings:
[spaserver]# cd fwknop-2.0.3/test/
[spaserver]# ./test-fwknop.pl --enable-recompile
 
[+] Starting the fwknop test suite...
 
args: --enable-recompile
 
Saved results from previous run to: output.last/
 
[recompilation] recompile and look for compilation warnings.........pass (1)
[build] [client] binary exists......................................pass (2)
[build security] [client] Position Independent Executable (PIE).....pass (3)
[build security] [client] stack protected binary....................pass (4)
[build security] [client] fortify source functions..................pass (5)
[build security] [client] read-only relocations.....................pass (6)
[build security] [client] immediate binding.........................pass (7)
[build] [server] binary exists......................................pass (8)
[build security] [server] Position Independent Executable (PIE).....pass (9)
[build security] [server] stack protected binary....................pass (10)
[build security] [server] fortify source functions..................pass (11)
[build security] [server] read-only relocations.....................pass (12)
[build security] [server] immediate binding.........................pass (13)
[build] [libfko] binary exists......................................pass (14)
[build security] [libfko] stack protected binary....................pass (15)
[build security] [libfko] fortify source functions..................pass (16)
[build security] [libfko] read-only relocations.....................pass (17)
[build security] [libfko] immediate binding.........................pass (18)
...
[Rijndael SPA] [client+server] complete cycle (tcp/22 ssh)..........pass (44)
[Rijndael SPA] [client+server] permissions check cycle (tcp/22).....pass (45)
[Rijndael SPA] [client+server] dual usage access key (tcp/80 http)..pass (46)
[Rijndael SPA] [client+server] packet aging (past) (tcp/22 ssh).....pass (47)
[Rijndael SPA] [client+server] packet aging (future) (tcp/22 ssh)...pass (48)
[Rijndael SPA] [client+server] expired stanza (tcp/22 ssh)..........pass (49)
[Rijndael SPA] [client+server] invalid expire date (tcp/22 ssh).....pass (50)
...
[Rijndael SPA] [client+server] replay attack detection..............pass (81)
[Rijndael SPA] [client+server] replay detection (Rijndael prefix)...pass (82)
[Rijndael SPA] [FUZZING] null port value............................pass (87)
[Rijndael SPA] [FUZZING] long FKO protocol value (enc mode trigger).pass (88)
[Rijndael SPA] [FUZZING] long FKO protocol value (Rijndael trigger).pass (89)
[Rijndael SPA] [FUZZING] null proto value...........................pass (90)
...
[GnuPG (GPG) SPA] [client+server] complete cycle (tcp/22 ssh).......pass (113)
[GnuPG (GPG) SPA] [client+server] multi gpg-IDs (tcp/22 ssh)........pass (114)
[GnuPG (GPG) SPA] [client+server] replay detection (GnuPG prefix)...pass (120)
[GnuPG (GPG) SPA] [client+server] non-base64 altered SPA data.......pass (121)
[GnuPG (GPG) SPA] [client+server] base64 altered SPA data...........pass (122)
[GnuPG (GPG) SPA] [client+server] appended data to SPA pkt..........pass (123)
[GnuPG (GPG) SPA] [client+server] prepended data to SPA pkt.........pass (124)
[GnuPG (GPG) SPA] [server] digest cache structure...................pass (126)
 
[+] passed/failed/executed: 126/0/126 tests
 
There are many more tests than are displayed above, and a complete example of test suite output can be found here. If there are any failures indicated in the test suite output, the most important files to examine are the test.log and the various NNN.test results files (where NNN corresponds to each test number) in the output/ directory. These files help to diagnose any problems with fwknop on the local system. 3.5.2 --diff Mode One of the more useful things the test suite offers is the ability to compare results from one test run to another.
[spaserver]# ./test-fwknop.pl --diff
This is mostly useful when hacking on the fwknop code in order to use the test suite to verify a change (or lack thereof) in functionality. At startup, the test suite copies any existing output/ directory to output.last and then diff's each file between the two runs in --diff mode. In the process, it tries to match output files to each other to account for differences in how the test suite is invoked across the runs (such as if different --include or --exclude criteria is provided). Using this mode, the typical workflow becomes 1) run the test suite, 2) hack on the fwknop code and recompile, 3) run the test suite in --diff mode, 4) commit the changes if everything is in order. This allows the test suit to help validate changes before they make it into the code base. A similar work flow exists for --enable-valgrind mode below. 3.5.3 valgrind Support The test suite is able to run all tests underneath the excellent valgrind dynamic analysis tool with the --enable-valgrind command line argument.
[spaserver]# ./test-fwknop.pl --enable-valgrind
By examining test suite output with valgrind enabled, memory leaks and other bugs become a lot easier to find. Here is some example valgrind output produced by the test suite, and the corresponding fix:
44 bytes in 1 blocks are definitely lost in loss record 2 of 2
    at 0x482BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
    by 0x490EA50: strdup (strdup.c:43)
    by 0x10CD69: incoming_spa (incoming_spa.c:162)
    by 0x10E000: process_packet (process_packet.c:200)
    by 0x4862E63: ??? (in /usr/lib/i386-linux-gnu/libpcap.so.1.1.1)
    by 0x4865667: pcap_dispatch (in /usr/lib/i386-linux-gnu/libpcap.so.1.1.1)
    by 0x10DABF: pcap_capture (pcap_capture.c:226)
    by 0x10A798: main (fwknopd.c:299)
When working on fwknop code, one of the most powerful ways of executing the test suite is successive runs as follows to ensure no compilation warnings under -Wall and with valgrind enabled. Then by applying --diff mode across these runs it becomes easier to verify whether new code is properly developed. Here is an example where a code change got rid of a valgrind warning - you can see the warning removed from the output/42.test file:
[spaserver]# ./test-fwknop.pl --enable-recompile --enable-valgrind
 
--- make code changes ---
 
[spaserver]# ./test-fwknop.pl --enable-recompile --enable-valgrind
[spaserver]# ./test-fwknop.pl --diff
[+] Checking: [Rijndael SPA] [client+server] complete cycle (tcp/22 ssh)
--- output.last/42.test 2012-10-04 21:36:17.660155003 -0400
+++ output/42.test 2012-10-04 21:36:17.692155003 -0400
@@ -5,30 +5,14 @@
Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
Command: ../client/.libs/fwknop -A tcp/22 -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key --verbose --verbose
 
-Invalid read of size 4
-   at 0x4E37DF4: fko_encrypt_spa_data (fko_encryption.c:65)
-   by 0x10B036: main (fwknop.c:292)
- Address 0x583c3fc is 108 bytes inside a block of size 110 alloc'd
-   at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
-   by 0x4E37DA8: fko_encrypt_spa_data (fko_encryption.c:56)
-   by 0x10B036: main (fwknop.c:292)
-
-Invalid read of size 4
-   at 0x4E37E47: fko_encrypt_spa_data (fko_encryption.c:69)
-   by 0x10B036: main (fwknop.c:292)
- Address 0x583c3fc is 108 bytes inside a block of size 110 alloc'd
-   at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
-   by 0x4E37DA8: fko_encrypt_spa_data (fko_encryption.c:56)
-   by 0x10B036: main (fwknop.c:292)
-
 send_spa_packet: bytes sent: 161
3.5.4 Anonymizing Test Suite Output If the test suite has uncovered a problem, the results files can be anonymized (all IP address, hostnames, and other identifying information removed) so that they can be sent around to fwknop developers for comment. This process has been automated with the --Anonymize-results command line argument:
[spaserver]# ./test-fwknop.pl --Anonymize-results
[+] Anonymizing all IP addresses and hostnames from output files...
Creating tar file: test_fwknop.tar.gz
test.log
output/
output/1.test
output/test.log
output/1_fwknopd.test
...
output/init
[+] Anonymized test results file: test_fwknop.tar.gz
Now the test_fwknop.tar.gz can be safely shared with others, though it is recommended to review the information it contains just to be sure that nothing sensitive made it through. The anonymization step sets all IPv4 addresses to "N.N.N.N" and removes hostnames from uname output. Typically the test_fwknop.tar.gz file is sent to an fwknop developer for review whenever a test fails. 4. fwknop Operations This section covers general operations of fwknop. It is assumed that fwknop has been installed on both the spaclient (IP: 1.1.1.1) and spaserver (IP: 2.2.2.2) systems so that proper operations can be illustrated. Also, in this section we generally show fwknopd execution on Ubuntu Linux, but analogous operations apply to other supported platforms. 4.1 Starting and Stopping the fwknopd daemon Depending on which platform fwknop is deployed, starting and stopping the fwknop daemon may be accomplished via different mechanisms. On a Linux system such as Ubuntu that is running upstart, controlling fwknopd is quite easy:
[spaserver]# service fwknop status
fwknop start/running, process 8002
 
[spaserver]# service fwknop stop
fwknop stop/waiting
 
[spaserver]# service fwknop start
fwknop start/running, process 8540
One nice reason to use upstart is built-in process monitoring and the ability to restart a daemon if it ever dies. This eliminates fwknopd as a single point of failure for services that it is guarding. So, if one were to kill the fwknopd daemon on spaserver, we'd see that upstart has restarted it:
[spaserver]# kill `pgrep fwknopd`
[spaserver]# service fwknop status
fwknop start/running, process 32743
 
[spaserver]# grep fwknop /var/log/syslog | tail -n 1
Sep 27 20:17:17 spaserver kernel: [123463.123937] init: fwknop main process ended, respawning
The fwknopd daemon also has a built-in status checking ability to see if an fwknopd process is currently running:
[spaserver]# fwknopd --status
Detected fwknopd is running (pid=8540).
4.2 SPA with Symmetric Keys (via Rijndael) This section illustrates gaining access to two different services, sshd and IMAP over SSL with SPA using symmetric encryption keys via the Rijndael cipher. We configure fwknopd to sniff eth0 via the /etc/fwknop/fwknopd.conf file on the spaserver system just as in the Quick Start section. We also configure the /etc/fwknop/access.conf file with a stanza to define the symmetric encryption key along with a few other parameters. In this case, allow SPA clients to request access to tcp/22 (ssh) or tcp/993 (IMAPS) via the OPEN_PORTS variable, and we also force SPA clients to explicitly include the IP that should be granted access with the REQUIRE_SOURCE_ADDRESS. On the fwknop command line, the allow IP can be set via the -a <IP> argument, or the client can resolve its own IP via http://www.cipherdyne.org/cgi-bin/myip with the -R command line argument.
[spaserver]# grep PCAP_INTF /etc/fwknop/fwknopd.conf
PCAP_INTF eth0;
 
[spaserver]# cat /etc/fwknop/access.conf
SOURCE: ANY;
OPEN_PORTS: tcp/22, tcp/993; ### SSH and IMAP over SSL
KEY: yourdecryptkey;
REQUIRE_SOURCE_ADDRESS: Y;
FW_ACCESS_TIMEOUT: 30;
We assume that iptables is configured in a default-drop stance for both sshd and IMAPS, and that a connection tracking rule exists to allow packets that are part of established TCP connections to make it through. The following commands accomplish this for these two services, but you will probably want to integrate this with any firewall policy interface that you normally use. Some additional information is mentioned in the Default-Drop Firewall Policy section.
[spaserver]# iptables -I INPUT 1 -i eth0 -p tcp --dport 22 -j DROP
[spaserver]# iptables -I INPUT 1 -i eth0 -p tcp --dport 993 -j DROP
[spaserver]# iptables -I INPUT 1 -i eth0 -p tcp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Now, from the spaclient system we run the fwknop client in order to gain access to both sshd and IMAPS (note the usage of -R to automatically resolve the externally facing client IP):
[spaclient]$ fwknop -A tcp/22,tcp/993 -R -D spaserver
Enter encryption password:
 
[spaclient]$ ssh mbr@spaserver
mbr@spaserver's password:
4.3 SPA with Asymmetric Keys (via GnuPG) Some people prefer using the security properties provided by GnuPG as the encryption/decryption method of choice for Single Packet Authorization. This section shows how to leverage GnuPG keys for SPA. First, you will need to first create the necessary GnuPG keys on both the client and server. If you already have a sensitive GnuPG key that you use for email (or other) encryption, you can safely use this key on the client side since it will only be used for message signing by fwknop. On the fwknopd server you will need to create a special GnuPG key that is exclusively used for fwknop communications. The reason stems from the fact that the password used to unlock this key must be stored within the /etc/fwknop/access.conf file since fwknopd must be able to decrypt messages that have been encrypted by an fwknop client with the server's public key. Hence, it is not a good idea to use a highly valuable personal GnuPG key on the server. It is also possible to create GnuPG keys on the server with no password and then set "GPG_ALLOW_NO_PW: Y;" in the access.conf file. While this may sound like a bad idea, in automated environments it makes sense because "there is usually no way to store a password more securely than on the secret keyring itself" according to: http://www.gnupg.org/faq/GnuPG-FAQ.html#how-can-i-use-gnupg-in-an-automated-environment. Using this feature and removing the passphrase from a GnuPG key pair is also useful in some environments where libgpgme is forced to use gpg-agent and/or pinentry to collect a passphrase.

In order for fwknop to support SPA via GnuPG you will need the libgpgme library installed. When compiling fwknop, the autoconf configure script automatically detects whether libgpgme is installed, and if so, it compiles in GnuPG support by default.

Once you have created the requisite keys as shown below, you will need to import and sign each key into its "opposite" system. That is, import and sign the server key into the client's GnuPG key ring, and vice-versa. Because SPA messages must fit within a single IP packet, it is recommended to choose a key size of 2048 bits or less for the fwknopd server GnuPG key. The process of generating the necessary GnuPG keys from the perspectives of both the client and server is outlined below. First we generate GnuPG keys and then export them to ascii files:
[spaserver]# gpg --gen-key
[spaserver]# gpg --list-keys
pub 1024D/ABCD1234 2012-05-01
uid fwknop server key <fwknopd@spaserver>
sub 2048g/EFGH1234 2012-05-01
 
[spaserver]# gpg -a --export ABCD1234 > server.asc
 
---now from the spaclient system---
 
[spaclient]$ gpg --gen-key
[spaclient]$ gpg --list-keys
pub 1024D/1234ABCD 2012-05-01
uid fwknop client key <fwknop@spaclient>
sub 2048g/1234EFGH 2012-05-01
 
[spaclient]$ gpg -a --export 1234ABCD > client.asc
Next, we transfer the ascii files between the two systems. In this example we use scp (which will presumably be firewalled off after fwknop is deployed!), but any other transfer mechanism (ftp, http, etc.) will work:
[spaclient]$ scp client.asc root@spaserver:
[spaclient]$ scp root@spaserver:server.asc .
Now we import and sign each key:
[spaserver]# gpg --import client.asc
[spaserver]# gpg --edit-key 1234ABCD
Command> sign
 
[spaclient]$ gpg --import server.asc
[spaclient]$ gpg --edit-key ABCD1234
Command> sign
On the server side, we need to add several configuration directives to the /etc/fwknop/access.conf file so that fwknopd uses GnuPG to verify and decrypt SPA packets and are signed and encrypted with GnuPG. Note that the server key ID is ABCD1234 and the client key ID is 1234ABCD:
SOURCE: ANY;
OPEN_PORTS: tcp/22, tcp/993;
GPG_REMOTE_ID: 1234ABCD;
GPG_DECRYPT_ID: ABCD1234;
GPG_DECRYPT_PW: <your decryption password>; ### or set GPG_ALLOW_NO_PW and remove the passhprase
GPG_HOME_DIR: /root/.gnupg;
FW_ACCESS_TIMEOUT: 30;
Now, to gain access to sshd, we execute fwknop:
[spaclient]$ fwknop -A tcp/22 --gpg-recip ABCD1234 --gpg-sign 1234ABCD -R -D spaserver
Enter passphrase for signing:
 
[spaclient]$ ssh -l mbr spaserver
mbr@spaserver's password:
4.4 Handling Multiple Services By default, an SPA user can request access to any service within a properly constructed SPA packet (i.e. one that matches the decryption key specified in a corresponding stanza in the /etc/fwknop/access.conf file). That is, a user can request access to sshd over tcp/22 and fwknopd would allow this by default. However, it is easy to restrict a user to only be able to request access to specific services via the OPEN_PORTS variable. For example, if you only want a user to be able to request access to, say, tcp/22 and tcp/993, you could set up an access.conf stanza like this:
[spaserver]# cat /etc/fwknop/access.conf
 
SOURCE: ANY;
OPEN_PORTS: tcp/22, tcp/993;
KEY: somedecryptkey;
REQUIRE_SOURCE_ADDRESS: Y;
REQUIRE_USERNAME: bob;
FW_ACCESS_TIMEOUT: 30;
Now, the user can gain access to both services simultaneously with the following:
[spaclient]$ fwknop -A tcp/22,tcp/993 -R -D spaserver
Enter encryption password:
On the server side, two new ACCEPT rules are added - one for tcp/22 and the other for tcp/993. Both rules are deleted after 30 seconds:
Oct 2 23:11:39 spaserver fwknopd[8540]: (stanza #1) SPA Packet from IP: 1.1.1.1 received with access source match
Oct 2 23:11:39 spaserver fwknopd[8540]: Added Rule to FWKNOP_INPUT for 1.1.1.1, tcp/22,tcp/993 expires at 1349406729
Oct 2 23:11:39 spaserver fwknopd[8540]: Added Rule to FWKNOP_INPUT for 1.1.1.1, tcp/22,tcp/993 expires at 1349406729
Oct 2 23:12:09 spaserver fwknopd[8540]: Removed rule 1 from FWKNOP_INPUT with expire time of 1349406729.
Oct 2 23:12:09 spaserver fwknopd[8540]: Removed rule 1 from FWKNOP_INPUT with expire time of 1349406729.
If the OPEN_PORTS variable is used and the user requests access to a service that is not listed with this variable then fwknopd refuses to grant access. This scenario is illustrated in the next section. 4.5 Handling Multiple Users fwknop supports the ability to have dedicated SPA keys for multiple users - each user can have their own set of SPA keys (asymmetric and/or symmetric). In addition, each user can be restricted to only being able to access a particular service and/or being granted access from a particular set of networks (if these are known up front). All of these access qualifiers along with the encryption keys themselves are placed within the /etc/fwknop/access.conf file. Below is an example access.conf file that configures a combination of Rijndael and GnuPG usage for a set of three remote users: Bob (username: bob), Alice (username: alice), and John (username: john):
[spaserver]# cat /etc/fwknop/access.conf
 
SOURCE: ANY; # for bob
OPEN_PORTS: tcp/22;
KEY: bobdecryptkey;
REQUIRE_SOURCE_ADDRESS: Y;
REQUIRE_USERNAME: bob;
FW_ACCESS_TIMEOUT: 30;
 
SOURCE: ANY; # for alice
GPG_REMOTE_ID: 7234ABCD;
GPG_DECRYPT_ID: EBCD1234;
GPG_ALLOW_NO_PW: Y;
REQUIRE_SOURCE_ADDRESS: Y;
REQUIRE_USERNAME: alice;
FW_ACCESS_TIMEOUT: 30;
 
SOURCE: 3.3.3.0/24, 4.4.0.0/16; # for john
OPEN_PORTS: tcp/80;
KEY: johndecryptkey;
REQUIRE_USERNAME: john;
REQUIRE_SOURCE_ADDRESS: Y;
FW_ACCESS_TIMEOUT: 300;
This results in a number of things: 4.6 Client Automation with the --get-key Option There are some environments where typing in a passphrase to generate an encryption key is not convenient. This is where the --get-key <file> option comes in to specify a path to a file where the passphrase is stored in the filesystem. The fwknop client then just reads this file and does not prompt the user to type in any passphrase. This strategy is used by the test suite to execute the client without requiring manual user input.

Here is an example command line to illustrate --get-key usage:
[spaclient]$ fwknop -A tcp/22 --get-key /some/path/to/fwknop.key -R -D spaserver
The format of the --get-key file is "IP|host: key" like this:
[spaclient]$ cat /some/path/to/fwknop.key
spaserver: somedecryptkey
4.7 SPA Across NAT Gateways From the spaclient system we have already sent SPA packets out through the gateway with external IP 1.1.1.1 as depicted in Figure 1. However, this only applies to client-side Network Address Translation (NAT) for the outgoing SPA packet and associated ssh (or other) connection. How about making use of NAT on the spaserver system to transparently access services running on the subnet behind it?

One of the more important features offered by the fwknopd daemon is the ability to interact with the NAT facilities offered by the local firewall. This is only supported on Linux for iptables firewalls as of fwknop-2.0.3, but NAT support on ipfw and PF is coming soon as well. What this enables is the ability to transparently translate incoming connections from the Internet to services that are running on internal hosts behind the firewall that is running fwknopd. The use case where this makes the most sense is when the user does not want to access sshd on the firewall itself but on a system behind the firewall. Access could be granted to sshd on the firewall and then the user could ssh from there to the internal host, but this is adds unnecessary overhead when fwknopd can just build a NAT rule to have the incoming ssh connection go directly to the internal host.

Let's illustrate this scenario by accessing sshd on 10.2.1.10 behind the spaserver. First, we'll need to reconfigure the /etc/fwknop/fwknopd.conf file to allow SPA clients to request NAT rules with the ENABLE_IPT_FORWARDING variable:
[spaserver]# grep ENABLE_IPT_FORWARDING /etc/fwknop/fwknopd.conf
ENABLE_IPT_FORWARDING Y;
 
[spaserver]# service fwknop restart
fwknop stop/waiting
fwknop start/running, process 12624
Now from spaclient we request access to sshd running on 10.2.1.10:
[spaclient]$ fwknop -A tcp/22 -N 10.2.1.10:22 -R -D spaserver
Enter encryption password:
 
[spaclient]$ ssh -l mbr spaserver
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
12:34:0d:37:23:1e:f5:2b:12:12:12:c5:b9:63:23:23.
Please contact your system administrator.
Add correct host key in /home/mbr/.ssh/known_hosts to get rid of this message.
Offending RSA key in /home/mbr/.ssh/known_hosts:16
  remove with: ssh-keygen -f "/home/mbr/.ssh/known_hosts" -R 2.2.2.2
RSA host key for 2.2.2.2 has changed and you have requested strict checking.
Host key verification failed.
We see the warning above because fwknopd has built iptables DNAT and FORWARD rules to automatically NAT the incoming ssh connection to the 10.2.1.10 system. First we show the syslog message that fwknopd generates for this, and then illustrate the rules themselves with the --fw-list switch:
Oct 7 14:26:55 spaserver fwknopd[12624]: (stanza #1) SPA Packet from IP: 1.1.1.1 received with access source match
Oct 7 14:26:55 spaserver fwknopd[12624]: Added FORWARD Rule to FWKNOP_FORWARD for 1.1.1.1, tcp/22 expires at 1349634445
Oct 7 14:26:55 spaserver fwknopd[12624]: Added DNAT Rule to FWKNOP_PREROUTING for 1.1.1.1, tcp/22 expires at 1349634445
 
[spaserver]# fwknopd --fw-list
Listing rules in fwknopd iptables chains...
 
Chain FWKNOP_INPUT (1 references)
num  target     prot opt source               destination
 
Chain FWKNOP_FORWARD (1 references)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  1.1.1.1              10.1.2.10            tcp dpt:22 /* _exp_1349634445 */
 
Chain FWKNOP_PREROUTING (1 references)
num  target     prot opt source               destination
1    DNAT       tcp  --  1.1.1.1              0.0.0.0/0            tcp dpt:22 /* _exp_1349634445 */ to:10.1.2.10:22
After correcting the ssh key warning, an ssh connection will be allowed transparently through the 2.2.2.2 border firewall into the 10.2.1.10 system. 4.7.1 SPA Ghost Services A further refinement of the server-side NAT concept is to NAT connections from an SPA-authenticated client simultaneously while a service is already bound to a port. That is, in Figure 1 a webserver is deployed at IP 10.1.2.3. Let us assume that the 2.2.2.2 firewall has a policy deployed that automatically translates incoming connections on port 80 to this internal system - i.e. making the Apache instance a public webserver. Fine. Now, instead of having fwknopd on 2.2.2.2 NAT an incoming port 22 connection also to port 22 on 10.1.2.10, let's alter the fwknop client command line to have fwknopd NAT incoming connections to port 80 over to port 22 on 10.1.2.10. This will only be done for the source IP 1.1.1.1, so everyone else on the Internet only ever sees the same Apache webserver while the spaclient system has access to sshd on 10.1.2.10:
[spaclient]$ fwknop -A tcp/80 -N 10.2.1.10:22 -R -D spaserver
Enter encryption password:
 
[spaclient]$ ssh -p 80 -l mbr spaserver
mbr@spaserver's password:
Note that we changed "tcp/22" to "tcp/80" on the fwknop command line, and we also instructed ssh to make the connection over port 80 with "-p 80". Finally, as before, here are the syslog messages and iptables rules that fwknopd adds:
Oct 7 15:26:22 spaserver fwknopd[12624]: (stanza #1) SPA Packet from IP: 1.1.1.1 received with access source match
Oct 7 15:26:22 spaserver fwknopd[12624]: Added FORWARD Rule to FWKNOP_FORWARD for 1.1.1.1, tcp/80 expires at 1349638012
Oct 7 15:26:22 spaserver fwknopd[12624]: Added DNAT Rule to FWKNOP_PREROUTING for 1.1.1.1, tcp/80 expires at 1349638012
 
[spaserver]# fwknopd --fw-list
Listing rules in fwknopd iptables chains...
 
Chain FWKNOP_INPUT (1 references)
num  target     prot opt source               destination
 
Chain FWKNOP_FORWARD (1 references)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  1.1.1.1              10.1.2.10            tcp dpt:22 /* _exp_1349638012 */
 
Chain FWKNOP_PREROUTING (1 references)
num  target     prot opt source               destination
1    DNAT       tcp  --  1.1.1.1              0.0.0.0/0            tcp dpt:80 /* _exp_1349638012 */ to:10.1.2.10:22
The concept of having SPA result in connections for a service being translated through to a different system even though another service is already bound to the destination port on which the connection is made is called SPA "ghost services", and was announced in the blog post "Creating Ghost Services with Single Packet Authorization". 4.8 User Interfaces 4.8.1 iPhone Client Below is a screenshot of the fwknop client running on an iPhone. The code itself is available in the top level iphone/ directory in the fwknop sources. Max Kastanas contributed both the iPhone and Android code.
fwknop iPhone app
4.8.2 Android Client Below are screenshots of the fwknop client running on an Android phone. The code itself is available in the top level android/ directory in the fwknop sources.

fwknop Android app fwknop Android app 4.8.3 Windows Morpheus UI
morpheus-fwknop 0.7
4.8.4 Web Proxy
4.9 SPA Packet Spoofing By default, the fwknop client sends SPA packets over UDP port 62201. This allows the client to easily send SPA packets over the network without requiring any special privileges since it doesn't manipulate raw packet headers by default. However, if the user that is running the client does happen to have admin level access, fwknop can send SPA packets over the network from spoofed source IP addresses. Two command line arguments are required in order to spoof the source IP: "-Q <IP> -P udpraw" as follows:
[spaclient]$ fwknop -A tcp/22 -P udpraw -Q 4.4.4.4 -R -D spaserver
Enter encryption password:
Assuming that the local firewall policy is not setup to stop spoofed packets from being sent over the wire, then the remote fwknopd daemon will see the source IP on the SPA packet as 4.4.4.4. However, with REQUIRE_SOURCE_ADDRESS enabled in the /etc/fwknop/access.conf file, fwknopd will only allow access to the IP address that is encrypted within the SPA packet - not the spoofed source address. In this case, since the -R argument was used, the IP that will be allowed is 1.1.1.1 for the spaclient system:
Oct 2 22:14:56 spaserver fwknopd[12624]: (stanza #1) SPA Packet from IP: 4.4.4.4 received with access source match
Oct 2 22:14:56 spaserver fwknopd[12624]: Added Rule to FWKNOP_INPUT for 1.1.1.1, tcp/22 expires at 1349403326
4.10 Stopping Replay Attacks One of the main reasons to implement Single Packet Authorization as an improvement over port knocking is to make replay attacks a thing of the past. This section illustrates how an attacker might attempt a replay attack and shows that fwknop is not vulnerable - the attack is detected and a warning message is written to syslog. First, from the Quick Start "Gaining access to sshd with the fwknop client" section above, the fwknop client is executed in --verbose mode, and this prints out the raw encrypted SPA payload data that fwknop transmits on the wire. From this output, here is the raw payload data:
85yR1UXTnKQRKbIyLgjVJZPEdbhZJr//+ctXyL38a3VMvs2/NDH775WwVRe1EBnhqoEE9pFPrqHv5d8CVfh//FyOoqwveoBs+zbgb1LvoE4f6/9UJFybUWrApsB6z/0U9p1dPCdcbe1blK/H8hUgbOvWrKA7m8j30
One can also use an Ethernet sniffer such as tcpdump to verify that this data is what the client sends over the wire. Now, from the Quick Start section, this SPA packet was already sent from the spaclient system to the spaserver system in order to gain access to sshd. So, this particular SPA packet has been used once, and therefore should never be seen again on the wire. Let's assume that an attacker was able to monitor and capture the SPA packet above, and that the same attacker thinks that this data might be part of SPA communications. The attacker is certainly free to replay the same packet on the wire and send it to the spaserver system, and this is easily done as follows:
[attacker]$ echo -n "85yR1UXTnKQRKbIyLgjVJZPEdbhZJr//+ctXyL38a3VMvs2/NDH775WwVRe1EBnhqoEE9pFPrqHv5d8CVfh//FyOoqwveoBs+zbgb1LvoE4f6/9UJFybUWrApsB6z/0U9p1dPCdcbe1blK/H8hUgbOvWrKA7m8j30" | nc -u spaserver 62201
On the spaserver system, fwknopd will sniff the replayed SPA packet, and will compare the SHA-256 digest of this packet vs. the SHA-256 digest of all previously seen and properly decrypted SPA packets. If there is a match, then fwknopd knows that a replay attack was attempted (subject to there not being a collision in the SHA-256 calculation, which is exceedingly unlikely). In this case, fwknopd generates the following warning via syslog, and no access is granted to the attacker:
Oct 3 22:07:22 spaserver fwknopd[12624]: Replay detected from source IP: 3.3.3.3, Destination proto/port: 17/62201, Original source IP: 1.1.1.1, Original dst proto/port: 17/62201, Entry created: 10/03/12 20:52:39
Note in the above output that the source IP of the replayed SPA packet is 3.3.3.3. This is the attacker's IP address that we've chosen for the purposes of illustration. It makes no difference what the source IP is of the replayed packet because the SHA-256 digest is computed over the SPA payload data. 4.11 SPA Over Tor Adding strong anonymity to SPA communications via Tor is possible if one agrees to send SPA packet data over established TCP connections. This is a requirement because building a virtual circuit through the Tor network is only done for TCP, and then only for connections that are in the established state. The fwknop "-P tcp" argument instructs the fwknop client to establish a TCP connection with the SPA packet destination, so if this destination happens to be a proxy that can communicate over Tor then we're in business. This is where the socat project comes in. We'll use it to create a socks proxy that interfaces with Tor, and then connect to it with the fwknop client. This requires that the fwknop daemon listen on a TCP port for SPA data, and for this we set "ENABLE_TCP_SERVER Y;" in the /etc/fwknop/fwknopd.conf file on spaserver and restart. By default, in this mode fwknopd listens on TCP port 62201, but this can be changed with the TCPSERV_PORT variable. With fwknopd restarted, we now fire up the socat proxy on spaclient and run fwknop:
[spaclient]$ socat TCP-LISTEN:62201 SOCKS4A:127.0.0.1:2.2.2.2:62201,socksport=9050 &
[1] 20551
 
[spaclient]$ fwknop -A tcp/22 -a 1.1.1.1 -D 127.0.0.1 -P tcp
Enter encryption password:
Behind the scenes, the SPA is sent over Tor to the destination IP 2.2.2.2 (spaserver). The fwknop daemon monitors the SPA packet, and grants access to sshd from 1.1.1.1:
Oct 2 23:11:56 spaserver fwknopd[12624]: (stanza #1) SPA Packet from IP: 96.47.N.N received with access source match
Oct 2 23:11:56 spaserver fwknopd[12624]: Added Rule to FWKNOP_INPUT for 1.1.1.1, tcp/22 expires at 1349403326
The 96.47.N.N IP (partially blanked out) is a live Tor exit router. So, the SPA packet was given strong anonymity by Tor, but the ssh connection itself must be made from 1.1.1.1 directly. This is because the next virtual circuit built through the Tor network by an ssh connection might go through a different exit router, and therefore isn't predictable at the time the SPA packet is sent. However, if you want both the SPA packet and the ssh conneciton to use the same exit router, then you can set the exit router manually in /etc/tor/torrc via the "ExitNodes" directive. In this case, you would want to instruct fwknopd to allow the ssh connection from the same exit router by specifying its IP on the fwknop command line e.g. "-a 96.47.N.N":
[spaclient]$ fwknop -A tcp/22 -a 96.47.N.N -D 127.0.0.1 -P tcp
Enter encryption password:
5. fwknop Design Goals Below are the design choices that guide fwknop development. Other PK/SPA software make different design choices, and whether you prefer fwknop vs. another implementation depends at least partially on whether you agree with the following: 6. fwknop Communications 6.1 SPA Packet Format The fwknop client (and anything that uses the libfko library to generate SPA packets) creates SPA data according to a particular format before it is encrypted. This allows the fwknopd daemon to validate incoming SPA packets and apply appropriate access controls. Every SPA packet has a series of mandatory fields, and depending on the desired access may also contain a series of optional fields. The fwknop client accepts input from the user, populates the SPA packet with data built from this input, encrypts and base64 encodes the packet, and then sends in out on the wire towards the SPA server.

Mandatory SPA Packet Fields:
  1. 16 bytes of random data
  2. Local username
  3. Local time stamp
  4. fwknop version
  5. SPA message type
  6. Access request or command to execute
  7. SPA message digest (SHA-256 by default)
Optional SPA Packet Fields:
  1. NAT access request
  2. Third-party authentication information
  3. Firewall rule timeout
6.2 Raw SPA Packets The default encryption algorithm used by the fwknop client is Rijndael, and by using the --verbose command line argument the raw encrypted data can be seen on stdout before it is base64 encoded. For example, when fwknop is used to build an SPA packet for gaining access to tcp/22 on the fwknopd server system, here is an example of the raw encrypted data (in a hex dump output format) followed by the same data in its base64 encoded form (command output has been removed for brevity):
[spaclient]$ fwknop -A tcp/22 -R -D spaserver --verbose
Enter encryption password:
 
15:58:12.593286 IP 1.1.1.1.33299 > 2.2.2.2.62201: UDP, length 161
    0x0000:  4500 00bd bad1 4000 4011 815c 7f00 0001  E.....@.@..\....
    0x0010:  7f00 0001 8213 f2f9 00a9 febc 612f 755a  ............a/uZ
    0x0020:  7054 3543 5a67 5043 684b 625a 6634 4f6d  pT5CZgPChKbZf4Om
    0x0030:  4b57 3150 5371 7939 4543 3777 4c70 4831  KW1PSqy9EC7wLpH1
    0x0040:  5432 3432 5234 6b70 4d30 4772 4877 7862  T242R4kpM0GrHwxb
    0x0050:  6a37 314b 2b66 7656 3162 6432 776f 6c39  j71K+fvV1bd2wol9
    0x0060:  4679 756c 3849 326b 4d68 654e 4859 614d  Fyul8I2kMheNHYaM
    0x0070:  4266 3244 6e35 436f 6f64 7a53 2b55 3173  Bf2Dn5CoodzS+U1s
    0x0080:  3959 3733 4f65 7545 756d 3761 6335 4873  9Y73OeuEum7ac5Hs
    0x0090:  7766 4854 7078 6a36 344b 3556 5973 544c  wfHTpxj64K5VYsTL
    0x00a0:  7575 2f6e 486b 566d 7947 4448 7678 2b6c  uu/nHkVmyGDHvx+l
    0x00b0:  7333 7664 3445 6261 517a 4569 62         s3vd4EbaQzEib
 
a/uZpT5CZgPChKbZf4OmKW1PSqy9EC7wLpH1T242R4kpM0GrHwxbj71K+fvV1bd2wol9Fyul8I2kMheNHYaM \
Bf2Dn5CoodzS+U1s9Y73OeuEum7ac5HswfHTpxj64K5VYsTLuu/nHkVmyGDHvx+ls3vd4EbaQzEib
SPA packets encrypted with Rijndael are typically on the order of about 200 bytes long or less.

Also supported by fwknop is GnuPG for asymmetric encryption, and SPA packets encrypted with GnuPG are typically much larger - on the order of about 1000 bytes. Similarly to the above output, here is an example of using fwknop to build an SPA packet with GnuPG (command output has again been removed):
[spaclient]$ fwknop --gpg-recip 361BBAD4 --gpg-sign 6A3FAD56 -A tcp/22 -R -D spaserver --verbose
Enter passphrase for signing:
 
16:10:58.674052 IP 1.1.1.1.44954 > 2.2.2.2.62201: UDP, length 1044
    0x0000:  4500 0430 a6f2 4000 4011 91c8 7f00 0001 E..0..@.@.......
    0x0010:  7f00 0001 af9a f2f9 041c 0230 494f 4133 ...........0IOA3
    0x0020:  796f 4831 4c35 4f4e 4543 4541 662f 554e yoH1L5ONECEAf/UN
    0x0030:  506b 5a61 6374 4259 4e53 5955 5964 6c30 PkZactBYNSYUYdl0
    0x0040:  5944 5a46 662f 3234 5764 4468 6344 6d63 YDZFf/24WdDhcDmc
    0x0050:  4a4e 4270 6f77 712f 7451 4978 5963 3253 JNBpowq/tQIxYc2S
    0x0060:  7863 4758 4662 4362 304c 6c77 7476 654d xcGXFbCb0LlwtveM
    0x0070:  6630 6472 6166 6476 4144 7361 4838 6b5a f0drafdvADsaH8kZ
    0x0080:  7854 674f 4932 4877 4555 3756 7478 3766 xTgOI2HwEU7Vtx7f
    0x0090:  6d55 3371 4f44 7938 4c6f 6978 786a 4d44 mU3qODy8LoixxjMD
    0x00a0:  4251 3656 3145 5a4c 5331 6757 6550 5a70 BQ6V1EZLS1gWePZp
    0x00b0:  4b6d 6b37 5358 5a61 6b74 7469 3958 594c Kmk7SXZaktti9XYL
    0x00c0:  4246 4173 5470 4e4b 7175 2b53 4667 6774 BFAsTpNKqu+SFggt
    0x00d0:  6846 4a33 724b 3064 657a 634d 6358 5739 hFJ3rK0dezcMcXW9
    0x00e0:  6e48 5572 5057 6959 6745 6969 5773 6763 nHUrPWiYgEiiWsgc
    0x00f0:  4841 4943 4f34 4178 5058 7767 5374 6162 HAICO4AxPXwgStab
    ...
    0x0370:  632f 3658 694e 5836 4f57 5a31 4b7a 5263 c/6XiNX6OWZ1KzRc
    0x0380:  6e4a 4852 5064 6f4d 6e42 2f6c 7367 4267 nJHRPdoMnB/lsgBg
    0x0390:  4456 3952 5532 3463 6f53 7473 6732 7950 DV9RU24coStsg2yP
    0x03a0:  346f 4a69 5830 664f 4e63 3430 304b 3175 4oJiX0fONc400K1u
    0x03b0:  6c69 7641 6830 2f33 4b5a 7074 754d 5045 livAh0/3KZptuMPE
    0x03c0:  6870 2b4a 7636 4745 6f43 796f 7978 372b hp+Jv6GEoCyoyx7+
    0x03d0:  4e58 7264 4771 4b4c 7757 704b 6369 4167 NXrdGqKLwWpKciAg
    0x03e0:  4974 7975 3854 3244 6255 616c 544c 782b Ityu8T2DbUalTLx+
    0x03f0:  4d73 7168 4d69 4646 7575 3959 744a 2f2f MsqhMiFFuu9YtJ//
    0x0400:  6661 7974 6d77 6d59 5533 6f48 6166 3547 faytmwmYU3oHaf5G
    0x0410:  4330 434c 3044 5861 384a 4c52 572f 746e C0CL0DXa8JLRW/tn
    0x0420:  2f71 6169 7977 4739 7374 664a 6976 4551 /qaiywG9stfJivEQ
 
IOA3yoH1L5ONECEAf/UNPkZactBYNSYUYdl0YDZFf/24WdDhcDmcJNBpowq/tQIxYc2SxcGXFbCb0LlwtveMf0drafdvADsaH8kZxTgOI2 \
HwEU7Vtx7fmU3qODy8LoixxjMDBQ6V1EZLS1gWePZpKmk7SXZaktti9XYLBFAsTpNKqu+SFggthFJ3rK0dezcMcXW9nHUrPWiYgEiiWsgcHAICO4AxPXwgS \
tabnqVrxT6QtVjX9uet2uG8JLkaTNzpmclFA6vyuK2XZAL7975YiOC6wMKaIqtrSjrKIUcfkUru9jDfHODP3GPf8h6t/4qDOFUzSfTVZ5EzegQEyV3MI3Qf \
EUAhdkBKySTamr/Af+M+CyJhJPbbqwy/LYjJM8ypkf75rV1gjGpLH1lgM+X/O6ARloRYYoTNuJyBhKHlJTB25QaXYfOvfBiRjLU7rqEDPC+coUdcrqZbl+i \
/HQMtVVqcrVJrzr6xVuI4ednShmwP3221pt2TgQ6HkP/8j2yMlNyEEYgjXKt+Zdlw3k0ODkFEH7cMIliUSgsOPzGtwO/WvDaVrkZQrZaZjS+lqGwvTn9dkL \
mcEV5iYuDTplmNOUSOX+afWaEH5S3t2P6ttsXhCD4Rzpx1uMDybwvss7ZIvYp91OPi957Pe1rCH3uCAeTzI5qbcR1PIu9X+dRDXpssaehmJLeq+DudZGQq3 \
e2NLAPAFpDH7MAc6AnXWfH2H2/sbXCSVqHPdsRH5yOlCxkW9ZGVnIdYPb9y3005Iz1trAJffLFVNCvLDQAcNA3qmUQHwHn6y2Vt30PiylPeOa6xrLlTmNs+ \
Q0jWOQdGR9q9NwN9I0U1GjIsWKNQJmi7c/6XiNX6OWZ1KzRcnJHRPdoMnB/lsgBgDV9RU24coStsg2yP4oJiX0fONc400K1ulivAh0/3KZptuMPEhp+Jv6G \
EoCyoyx7+NXrdGqKLwWpKciAgItyu8T2DbUalTLx+MsqhMiFFuu9YtJ//faytmwmYU3oHaf5GC0CL0DXa8JLRW/tn/qaiywG9stfJivEQ
7. fwknop Development 7.1 Programming Languages and Style All recent versions of fwknop are developed in C. There are older versions written in perl, but these are no longer maintained. The development process for fwknop uses valgrind to assist in the validation of proper memory handling, security oriented compiler options are enabled, and the C code for libfko is portable to Windows. The fwknop test suite is written in perl for rapid prototyping of testing functionality, there are various supporting shell scripts, the Android client is written in Java, and the iPhone client is written in Objective C. With regard to programming style, all fwknop source code uses spaces for indentation instead of having to worry about tabs. A width of four spaces is used for each level of indentation. 7.2 Source Control (git) All fwknop sources are tracked via git, and you can clone the repository either from github or from cipherdyne.org:
$ git clone https://www.github.com/mrash/fwknop fwknop.git
Cloning into 'fwknop.git'...
remote: Counting objects: 5275, done.
remote: Compressing objects: 100% (1603/1603), done.
remote: Total 5275 (delta 3672), reused 5155 (delta 3552)
Receiving objects: 100% (5275/5275), 2.07 MiB | 3.96 MiB/s, done.
Resolving deltas: 100% (3672/3672), done.
 
---or---
 
$ git clone http://www.cipherdyne.org/git/fwknop.git fwknop.git
Cloning into 'fwknop.git'...
7.3 Older Perl Releases The perl version is no longer maintained, and it doesn't conform to one of the main design goals of not using heavyweight interpreted languages. However, if you really want to run the perl version, all of the older fwknop releases are still available at the download page. Also, the perl sources are checked in under the perl/legacy/fwknop/ directory in git. 7.4 Submitting Patches Being an open source project, patches against fwknop are heartily accepted. Over the years, several people have contributed suggestions, bug fixes, and patches to the fwknop sources. Before submitting a patch, you may want to review the latest public code in the latest release, or view the as yet unreleased sources via the fwknop gitweb.cgi interface (or through git itself). Patches can be submitted to the fwknop mailing list or emailed to <mbr[at]cipherdyne.org>. If you are on Github, a patch can be submitted via a pull request. 7.5 Primary Developers The fwknop project was created by Michael Rash in 2004 originally as a port knocking implementation for iptables firewalls, and SPA mode was offered in 2005. Damien Stuart did the original port of the fwknop perl code to C and implemented the libfko shared library architecture in the process. Today both Michael and Damien are the primary developers of fwknop, and are assisted by many worthy individuals who enjoy contributing to open source software. Damien can be reached at <dstuart[at]dstuart.org> and Michael at <mbr[at]cipherdyne.org>. 7.6 Mailing List The fwknop-discuss mailing list serves as a forum for asking questions, submitting patches, and providing feedback on all things related to fwknop. Theoretical discussions of both port knocking and Single Packet Authorization are also welcomed on this list. The list is generally fairly low traffic, although from time to time there are spikes in the number of emails if there is a software release or if new features are discussed for inclusion in fwknop. New releases are always announced on the mailing list, and this includes pre-releases for upcoming bug fixes and new features in the next major version. 8. References and Further Reading 8.1 Reference List
  1. "An Analysis of Port Knocking and Single Packet Authorization" - this is a Master's Thesis completed in September, 2006 by Sebastien Jeanquier at the Royal Holloway College, University of London about the concepts of port knocking and Single Packet Authorization. This is a standard reference for issues surrounding PK/SPA, and makes an excellent argument for why neither PK nor SPA suffer from the "security through obscurity" problem.
  2. Online fwknop man pages - the complete man pages for fwknop. This is the most comprehensive documentation for the command line arguments supported by the fwknopd daemon and the fwknop client.
  3. Wikipedia on Port Knocking and SPA - this is the latest information that Wikipedia has on PK/SPA, and provides a fairly good introduction to the technology and tradeoffs.
  4. "Single Packet Authorization with fwknop" - this paper was published in the February, 2006 issue of USENIX ;login: Magazine, and is the first article on the fwknop implementation of SPA.
  5. " Enhancing Firewalls: Conveying User and Application Identification to Network Firewalls" - this is a Master's Thesis completed in May, 2007 by Rennie deGraaf at the the University of Calgary.
  6. " Linux Firewalls: Attack Detection and Response with iptables, psad, and fwsnort" - Chapters 12 and 13 of this book published by No Starch Press in October 2007 discuss port knocking and Single Packet Authorization.
  7. " Recent Advances in Single Packet Authorization" - this is the set of slides for a talk given at the HOPE Number Nine conference in New York City in July 2012.
  8. " Port Knocking and Single Packet Authorization: Practical Deployments" - this is the set of slides for a talk given at The Last HOPE conference in New York City in July 2008.
  9. " Zero-day Attack Prevention via Single Packet Authorization" - slides from the Techno Security conference in Myrtle Beach in June 2007.
  10. " Attack Detection and Response with Linux Firewalls" - slides from the ShmooCon conference in Washington D.C. in March 2007.
  11. " Service Cloaking and Anonymous Access; Combining Tor with Single Packet Authorization (SPA)" - slides from the Defcon conference in Las Vegas in August 2006.
8.2 fwknop and fwknopd --help Output Quite a lot of information can be found in the fwknop man pages, but you can also get a sense for some of the major fwknop functionality by looking at the command line --help output. Here is the fwknop client --help information:
[spaclient]$ fwknop --help
fwknop client version 2.0.3
Single Packet Authorization client

Usage: fwknop -A <port list> [-s|-R|-a] -D <spa_server> [options]

 -h, --help                  Print this usage message and exit.
 -A, --access                Provide a list of ports/protocols to open
                             on the server.
 -B, --save-packet           Save the generated packet data to the
                             specified file.
 -a, --allow-ip              Specify IP address to allow within the SPA
                             packet.
 -C, --server-cmd            Specify a command that the fwknop server will
                             execute on behalf of the fwknop client..
 -D, --destination           Specify the IP address of the fwknop server.
 -n, --named-config          Specify an named configuration stanza in the
                             '$HOME/.fwknoprc' file to provide some of all
                             of the configuration parameters.
 -N, --nat-access            Gain NAT access to an internal service
                             protected by the fwknop server.
 -p, --server-port           Set the destination port for outgoing SPA
                             packet.
 -P, --server-proto          Set the protocol (udp, tcp, http, tcpraw,
                             icmp) for the outgoing SPA packet.
                             Note: The 'tcpraw' and 'icmp' modes use raw
                             sockets and thus require root access to use.
 -s, --source-ip             Tell the fwknopd server to accept whatever
                             source IP the SPA packet has as the IP that
                             needs access (not recommended, and the
                             fwknopd server can ignore such requests).
 -S, --source-port           Set the source port for outgoing SPA packet.
 -Q, --spoof-source          Set the source IP for outgoing SPA packet.
 -R, --resolve-ip-http       Resolve the external network IP by
                             connecting to a URL such as the default of:
                             http://www.cipherdyne.org/cgi-bin/myip
                             This can be overridden with the --resolve-url
                             option.
     --resolve-url           Override the default URL used for resolving
                             the source IP address.
 -u, --user-agent            Set the HTTP User-Agent for resolving the
                             external IP via -R, or for sending SPA
                             packets over HTTP.
 -H, --http-proxy            Specify an HTTP proxy host through which the
                             SPA packet will be sent.  The port can also be
                             specified here by following the host/ip with
                             ":".
 -U, --spoof-user            Set the username within outgoing SPA packet.
 -l, --last-cmd              Run the fwknop client with the same command
                             line args as the last time it was executed
                             (args are read from the ~/.fwknop.run file).
 -G, --get-key               Load an encryption key/password from a file.
 -r, --rand-port             Send the SPA packet over a randomly assigned
                             port (requires a broader pcap filter on the
                             server side than the default of udp 62201).
 -T, --test                  Build the SPA packet but do not send it over
                             the network.
 -v, --verbose               Set verbose mode.
 -V, --version               Print version number.
 -m, --digest-type           Specify the message digest algorithm to use.
                             (md5, sha1, or sha256 (default)).
 -f, --fw-timeout            Specify SPA server firewall timeout from the
                             client side.
     --gpg-encryption        Use GPG encryption (default is Rijndael).
     --gpg-recipient-key     Specify the recipient GPG key name or ID.
     --gpg-signer-key        Specify the signer's GPG key name or ID.
     --gpg-home-dir          Specify the GPG home directory.
     --gpg-agent             Use GPG agent if available.
     --no-save-args          Do not save fwknop command line args to the
                             $HOME/fwknop.run file
     --nat-local             Access a local service via a forwarded port
                             on the fwknopd server system.
     --nat-port              Specify the port to forward to access a
                             service via NAT.
     --nat-rand-port         Have the fwknop client assign a random port
                             for NAT access.
     --show-last             Show the last fwknop command line arguments.
     --time-offset-plus      Add time to outgoing SPA packet timestamp.
     --time-offset-minus     Subtract time from outgoing SPA packet
                             timestamp.
And finally, here is the fwknopd daemon --help output:
[spaserver]# fwknopd --help

fwknopd server version 2.0.3
Single Packet Authorization server

Usage: fwknopd [options]

 -h, --help              - Print this usage message and exit.
 -a, --access-file       - Specify an alternate access.conf file.
 -c, --config-file       - Specify an alternate configuration file.
 -C, --packet-limit      - Limit the number of candidate SPA packets to
                           process and exit when this limit is reached.
 -d, --digest-file       - Specify an alternate digest.cache file.
 -D, --dump-config       - Dump the current fwknop configuration values.
 -f, --foreground        - Run fwknopd in the foreground (do not become
                           a background daemon).
 -i, --interface         - Specify interface to listen for incoming SPA
                           packets.
 -K, --kill              - Kill the currently running fwknopd.
     --gpg-home-dir      - Specify the GPG home directory.
 -l, --locale            - Provide a locale setting other than the system
                           default.
 -O, --override-config   - Specify a file with configuration entries that will
                           overide those in fwknopd.conf
 -p, --pid-file          - Specify an alternate fwknopd.pid file.
 -P, --pcap-filter       - Specify a Berkeley packet filter statement to
                           override the PCAP_FILTER variable in fwknopd.conf.
 -R, --restart           - Force the currently running fwknopd to restart.
     --rotate-digest-cache
                         - Rotate the digest cache file by renaming it to
                           '-old', and starting a new one.
 -S, --status            - Display the status of any running fwknopd process.
 -v, --verbose           - Set verbose mode.
 -V, --version           - Print version number.
     --fw-list           - List all firewall rules that fwknop has created
                           and then exit.
     --fw-list-all       - List all firewall rules in the complete policy,
                           including those that have nothing to do with
                           fwknop.
     --fw-flush          - Flush all firewall rules created by fwknop.
Please contact Michael Rash at <mbr[at]cipherdyne.org> with any questions.

### EOF ###