fwknop
implements an authorization scheme known as Single Packet Authorization (SPA) for
Linux systems running iptables, and for Mac OS X and FreeBSD systems running ipfw.
This mechanism requires only a single encrypted and non-replayed
packet to communicate various pieces of information including desired access
through an iptables or ipfw policy. The main application of this program is to
use iptables or ipfw in a default-drop stance to protect services such as
SSH
with an additional layer of security in order to make the exploitation of
vulnerabilities (both 0-day and unpatched code) much more difficult. An
authorization server
fwknopd
passively monitors authorization packets via
libpcap
and hence there is no "server" to which to connect in the traditional sense.
Any service protected by fwknop is inaccessible (by using iptables or ipfw to intercept
packets within the kernel) before authenticating; anyone scanning for
the service will not be able to detect that it is even listening. Single Packet
Authorization offers many advantages over port knocking, including non-replayability
of SPA packets, ability to use asymmetric ciphers (such as Elgamal), and SPA cannot
be broken by simply spoofing packets to duplicate ports within the knock sequence
on the server to break port knocking authentication. SPA packets can easily be
spoofed as well (this is a good thing in this context), and this makes it possible
to make it appear as though, say, www.yahoo.com is trying to authenticate to a
target system but in reality the actual connection will come from a seemingly
unrelated IP. Although the default data collection method in Single Packet
Authorization mode is to use libpcap to sniff packets off the wire, fwknop can also
read packets out of a file that is written by the iptables
ulogd
pcap writer (or a separate sniffer process that is writing packet data to a file).
Authorization packets are either encrypted with the Rijndael block cipher
or via GnuPG and associated asymmetric ciphers. If the symmetric encryption
method is chosen, then the encryption key is shared between the
client and server (see the
/etc/fwknop/access.conf
file). If the GnuPG
method is chosen, then the encryption keys are derived from GnuPG key
rings. SPA packets generated by fwknop running as a client adhere
to the following format (before they are encrypted):
random number (16 bytes)
username
timestamp
software version
mode (command mode (0) or access mode (1))
if command mode => command to execute
else access mode => IP,proto,port
message digest (SHA256 / SHA1 / MD5)
Each of the above fields are separated by a ":" character due to the
variable length of several of the fields, and those that might contain
":" characters are base64 encoded. The message digest (SHA256 by default
in all versions of
fwknop
greater than 1.9.1) allows the server to check message integrity after decryption,
and the 16 bytes of random data ensures (with high probability) that no two messages
are identical. This ensures that replay attacks are not possible against fwknop.
For each packet coming from an
fwknop
client, the
fwknopd
server caches the SHA256 digest calculated over the entire packet and compares against
previous packet digests in order to detect attempted replay attacks. The digest
cache file is located at
/var/log/fwknop/digest.cache
and is not rotated so that the detection of duplicate SPA messages is maximized.
Both syslog and email alerts are generated if a replay is detected (although
this can be tuned via the
ALERTING_METHODS
variable in the
/etc/fwknop/fwknop.conf
file). By default, the
fwknop
client sends authorization packets over UDP
port 62201, but this can be altered with the
--Server-port
argument. The server must first be configured to acquire the SPA data on
the changed protocol-port. Also, fwknop can send the SPA packet over a random
port via the --rand-port argument. See
fwknopd(8)
for further details. See the
EXAMPLES
section for example invocations of the
fwknop
client.
REQUIRED ARGUMENTS
-D, --Destination <IP-address>
Direct the
fwknop
client to authenticate with the
fwknopd
daemon/service at the destination address <IP> . The connection mode is discovered by the
fwknopd
daemon/service when it decrypts and parses the authentication packet.
-A, --Access <port list>
Provide a list of ports and protocols to access on a remote computer running
fwknopd.
The format of this list is '<proto>/<port>...<proto>/<port>,
e.g. "tcp/22,udp/53".
NOTE:
The vast majority of usages for
fwknop
require the -A argument, but sending full commands with the --Server-cmd
argument via an SPA packet to be executed by
fwknopd
does not require this argument.
-R|-a|-s
One of these options (see below) is required to tell the remote
fwknopd
daemon what IP should be let through the local firewall. It is recommend to use
the -R or -a options instead of -s in order to harden SPA communications against
possible MITM attacks.
OPTIONS
-a, --allow-IP <IP-address>
Specify IP address that should be permitted through the destination
fwknopd
server firewall (this IP is encrypted within the SPA packet itself). This is
useful to prevent a Man-In-The-Middle (MTIM) attack where an SPA packet can be
intercepted en-route and sent from a different IP than the original. Hence, if
the
fwknopd
server trusts the source address on the SPA packet IP header then the attacker
gains access. The
-a
option puts the source address within the encrypted
SPA packet, and so thwarts this attack. The
-a
option is also useful to specify the IP that will be granted access when SPA
packet itself is spoofed with the
--Spoof-src
option. Another related option is -R (see below) which instructs the
fwknop
client to automatically resolve the externally routable IP address the local
system is connected to by querying the
http://www.whatismyip.com
website.
-R, --Resolve-external-IP
This is an important option, and instructs the
fwknop
client and the
fwknopd
daemon/service to query
http://www.whatismyip.com
to determine the IP address that should be allowed through the iptables policy
at the remote
fwknopd
server side. This is useful if the
fwknop
client is being used on a system that is behind an obscure NAT address. Note
that you can use the
--URL
option to have fwknop resolve an externally routable address by using the
specific web service instead of http://www.whatismyip.org (see below).
--NAT-access <internalIP:forwardPort>
The
fwknopd
server offers the ability to provide SPA access through an iptables firewall
to an internal service by interfacing with the iptables NAT capabilities. So,
if the fwknopd server is protecting an internal network on RFC 1918 address
space, an external fwknop client can request that the server port forward an
external port to an internal IP, i.e. "--NAT-access 192.168.10.2:55000". In
this case access will be granted to 192.168.10.2 via port 55000 to whatever
service is requested via the --Access argument (usually tcp/22). Hence, after
sending such an SPA packet, one would then do "ssh -p 55000 user@host" and
the connection would be forwarded on through to the internal 192.168.10.2
system automatically. Note that the port "55000" can be randomly generated
via the --NAT-rand-port argument (described later).
--NAT-local
On the
fwknopd
server, a NAT operation can apply to the local system instead of being
forwarded through the system. That is, for iptables firewalls, a connection
to, say, port 55,000 can be translated to port 22 on the local system. By
making use of the --NAT-local argument, the fwknop client can be made to
request such access. This means that any external attacker would only see
a connection over port 55,000 instead of the expected port 22 after the SPA
packet is sent.
--URL <web resolution URL>
This option is used in conjunction with the
-R
option so that fwknop will resolve the externally routable IP address (useful
if fwknop is run on a system being a NAT) via a web service URL supplied on
the command line. A custom web resolution CGI script is available at the URL
below if http://www.whatismyip.org is not available:
http://www.cipherdyne.org/cgi/clientip.cgi
--gpg-agent
Instruct
fwknop
to acquire GnuPG key password from a running
gpg-agent
instance.
--gpg-agent-info <connection info>
Specify the value of the GPG_AGENT_INFO environment variable as returned
by the
gpg-agent --daemon
command. If the
fwknop --gpg-agent
command line argument is used instead of
--gpg-agent-info,
then fwknop assumes that the GPG_AGENT_INFO environment variable has already
been set in the current shell.
--gpg-default-key
Use the key that GnuPG defines as the default, i.e. the key that is specified
by the
default-key
variable in
~/.gnupg/options.
If the
default-key
variable is not defined
within
~/.gnupg/options
, then GnuPG tries to use the first suitable key on
its key ring. If the user does not know the password for this key, then the
standard password error will be thrown by GnuPG and reported back to the
user.
--gpg-home-dir <dir>
Specify the path to the GnuPG directory; normally this path is derived from the
home directory of the user that is running the
fwknop
client. This is useful when a 'root' user wishes to log into a remote machine
whose
sshd
daemon/service does not permit 'root' login.
--gpg-recipient <key ID>
Specify the GnuPG key ID, e.g. "1234ABCD" (see the output of "gpg --list-keys")
of the recipient of the Single Packet Authorization message. This key is imported
by the
fwknopd
server and the associated private key is used to decrypt the SPA packet. The
recipient's key must first be imported into the client GnuPG key ring.
--gpg-signing-key <key ID>
Specify the GnuPG key ID, e.g. "ABCD1234" (see the output of "gpg --list-keys")
to use when signing the SPA message. The user is prompted for
the associated GnuPG password to create the signature. This
adds a cryptographically strong mechanism to allow the
fwknopd
daemon on the remote server to authenticate who created the SPA message.
--gpg-verbose
Instruct
fwknop
to allow all output from the
gpg
process that is used by fwknop in GnuPG mode. This is primarily used for debugging
purposes if it appears that the GnuPG encrypt/decrypt is not performing correctly.
--gpg-use-options
By default the
fwknop
client instructs gpg to not reference any options file in gpg mode, but this
command line argument can be used to re-enable them.
--Home-dir <dir>
Specify the path to the user home directory where files such as .fwknop.hosts
or .fwknop.run should be stored or retrieved.
-l, --last-cmd
Instruct
fwknop
client to run with the same command line arguments that were used in a previous execution.
This option is useful because the clients'
fwknop
command line can be complex and difficult to recall.
--Last-host <host>
Instruct
fwknop
to use the same command line arguments that were used to authenticate to
host.
-q, --quiet
This option instructs the
fwknop
to be as quiet as possible and only print absolutely necessary information to
the terminal.
-s, --source-ip
Instruct the
fwknop
client to form an SPA packet that contains the special-case IP
address "0.0.0.0" which will inform the destination
fwknopd
SPA server to use the source IP address from which the SPA packet originates as
the IP that will be allowed through upon modification of the firewall ruleset.
This option is useful if the fwknop client is deployed on a machine that is
behind a NAT device. The permit-address options
-s
(default),
-R
and
-a
are mutually exclusive.
--Server-port <port>
Specify the port number where
fwknopd
accepts packets via libpcap or ulogd pcap writer. By default fwknopd looks for
authorization packets over UDP port 62201.
--rand-port
Instruct the fwknop client to send an SPA packet over a random destination port
between 10,000 and 65535. The fwknopd server must use a PCAP_FILTER variable
that is configured to accept such packets. For example, the PCAP_FILTER variable
could be set to:
udp dst portrange 10000-65535
--NAT-rand-port
Usually fwknop is used to request access to a specific port such as tcp/22 on a
system running fwknopd. However, by using the --NAT-rand-port argument, it is
possible to request access to a particular service (again, such as tcp/22), but
have this access granted via a random translated port. That is, once the fwknop
client has been executed in this mode and the random port selected by fwknop is
displayed, the destination port used by the follow-on client must be changed to
match this random port. For SSH, this is accomplished via the -p argument.
See the --NAT-local and --NAT-access command line arguments to fwknop for
additional details on gaining access to services via a NAT operation.
--Save-packet
Instruct the
fwknop
client to write a newly created SPA packet out to a file so that it can be
examined off-line. The default path is
~/fwknop_save_packet.<pid>
where <pid> is the process ID of the fwknop client process, but this can be
changed with the --Save-packet-file argument (see below).
--Save-packet-file <file>
Specify the file to write a new SPA packet to in
--Save-packet
mode.
--Save-packet-append
In
--Save-packet
mode fwknop normally overwrite the file used to save a new SPA packet, but
this command line argument instructs fwknop to append a new SPA packet to
the file instead. This is useful for generating large sets of SPA packets
in order to test randomness or encryption properties.
--time-offset-plus <time>
By default, the
fwknopd
daemon on the server side enforces time synchronization between the clocks
running on client and server systems. The fwknop client places the local time
within each SPA packet as a time stamp to be validated by the fwknopd server
after decryption. However, in some circumstances, if the clocks are out of
sync and the user on the client system does not have the required access to
change the local clock setting, it can be difficult to construct and SPA
packet with a time stamp the server will accept. In this situation, the
--time-offset-plus option can allow the user to specify an offset (e.g.
"60sec", "60min", "2days", etc.) that is added to the local time.
--time-offset-minus <time>
This is similar to the --time-offset-plus option (see above), but subtracts
the specified time offset instead of adding it to the local time stamp.
--Show-last-cmd
Display the last command-line arguments used by
fwknop.
--Show-host-cmd <host>
Display the last command-line arguments used to contact a SPA server running on
a specific
host.
--Spoof-proto <protocol>
Send an SPA packet over a raw socket of the specified protocol. Accepted
values are tcp, udp, and icmp. This is useful if you want to send the SPA
packet over an orphaned TCP ACK or an ICMP packet.
--Spoof-src <IP>
Spoof the source address from which the
fwknop
client sends SPA packets. This requires root on the client side access since a raw socket
is required to accomplish this. Note that the
--Spoof-user
argument can be given in this mode in order to pass any
REQUIRE_USERNAME
keyword that might
be specified in
/etc/fwknop/access.conf.
--Spoof-user <user>
Specify the username that is included within SPA packet. This allows
the
fwknop
client to satisfy any non-root
REQUIRE_USERNAME
keyword on the
fwknopd
server (
--Spoof-src
mode requires that the
fwknop
client is executed as root).
--icmp-type <type>
When using the
--Spoof-proto
argument to send an SPA packet over and ICMP packet, the ICMP type may be set
with this command line argument. The default is "8" for an ICMP echo-request
(see also the
--icmp-code
argument below).
--icmp-code <code>
When using the
--Spoof-proto
argument to send an SPA packet over and ICMP packet, the ICMP code may be set
with this command line argument. The default is "0" for an ICMP echo-request
(see also the
--icmp-type
argument above).
--Max-packet-size <size>
Instruct
fwknop
to restrict message length to
size
bytes, and the client will not send an SPA packet that is larger than this
(i.e. perhaps a long command was included in --Server-cmd mode). This alters
the default value of 1500 bytes. See also the
MAX_SNIFF_BYTES variable in
fwknop.conf
on the SPA server.
--HTTP
Have the
fwknop
client send an SPA packet as a web request over HTTP. This requires that the
system running
fwknopd
is also running a webserver to receive the SPA web request. The web request
is built as a modified version of base64-encoded data where the "+" and "/"
chars are replace with "-" and "_" respectively (to avoid URL encoding issues).
--HTTP-proxy <proxy host>
The
HTTP-proxy
option allows the
fwknop
client to send SPA packets through an HTTP proxy when the
--HTTP
option is also used. The expected format for the argument is
http://some.host.com
and an optional port number is supported with the
http://some.host.com:PORT
format.
--HTTP-user-agent <agent string>
Specify the HTTP user-agent whenver the
fwknop
client is used to send an SPA packet over an HTTP request, or when the
--Resolve-external-IP
option is used. The default user-agent is "Fwknop/VERSION", so "Fwknop/1.9.12"
for the 1.9.12 release.
-T, --TCP-sock
Have the
fwknop
client send an SPA packet over an established TCP connection (created by the fwknop
client to the specified listening port on the server with the
--Server-port
argument). This is not normally done, but is useful for compatibility with the Tor
for strong anonymity; see
http://tor.eff.org/.
In this case, the
fwknopd
server uses the
fwknop_serv
daemon to listen on a TCP port (62201 by default).
-h, --help
Display usage information and exit.
-V, --Version
Display version information and exit.
-v, --verbose
Run the
fwknop
client in verbose mode.
--locale <locale>
Provide a locale setting other than the default "C" locale.
--no-locale
Do not set the locale at all so that the default system locale will apply.
--Server-cmd <cmd>
NOTE:
This is for command mode only (i.e. when you want to send a command across
to a system running
fwknopd
and have it execute the command). This option is not needed when trying to
gain access to a service via the SPA mechanism. To use this feature, please
ensure that ENABLE_CMD_EXEC; is set in the file
/etc/fwknop/access.conf
on the
fwknopd
server you are sending the command to.
The --Server-cmd argument allows a complete command (e.g. "ping -c 1 www.yahoo.com",
or "iptables -t nat -A PREROUTING -p tcp -s 65.x.x.x --dport 443 -i eth0 -j DNAT --to 192.168.10.20:443")
to be send to an
fwknop
server, which will execute the command as root. Command execution is enabled only
if the
ENABLE_CMD_EXEC keyword is given in/etc/fwknop/access.conf
(note that commands can easily be restricted with the
CMD_REGEX
keyword as well).
Legacy Port-knock mode only
All of the following options in this section are for the traditional port knocking
mode mode. This is a legacy mode and is
not
the preferred or recommended mode next to Single Packet Authorization ( see
http://www.cipherdyne.org/fwknop/docs/SPA.html
for details on why).
--offset <port>
Specify a port offset to use when running
fwknop
in encrypted knock mode. The default is 61000.
-r, --rotate-proto
Rotate the protocol across tcp and udp for
encrypted sequences. This just adds one more additional layer of obfuscation
to an encrypted sequence.
--Server-mode <mode>
This command line switch provides an interface to
the old port knocking method if
the mode argument is "knock". If the
--Server-mode
argument is not given then the
fwknop
client defaults to using the SPA method which provides much better
security characteristics than port knocking (encrypted or not).
-t, --time-delay <seconds>
Specify a time delay to introduce between successive
connection attempts. This option is used by the
fwknop
client. On the server side,
fwknopd
uses the variables MIN_TIME_DIFF
and MAX_TIME_DIFF to control whether the time delay actually means
something (i.e. if the MIN_TIME_DIFF is 2 seconds for a SOURCE block,
then the argument to the --time-delay option must be at least 2 at the
client side).
-u, --user-rc <rc-file>
The default connection rc file the
fwknop
client uses to know what shared port knocking sequence to send to a destination machine
is defined in the file
~/.fwknoprc.
The path to this file can be changed with the
--user-rc
command line option.
FILES
~/.fwknop.run
Contains the last command line arguments that the
fwknop
client was invoked with.
~/.fwknop.hosts
Contains the last command line arguments for individual hosts that the
fwknop
client has been used to gain access to. By using the
--Last-host
switch, these arguments can be recalled and used.
ENVIRONMENT:
GPG_AGENT_INFO
(only used in --gpg-agent mode).
EXAMPLES:
The following examples illustrate the command line arguments that could
be supplied to the
fwknop
client in a few situations:
Access mode examples
Packet contents printed to stdout at the
fwknop
client when creating a 'access mode' SPA packet:
Use the Single Packet Authorization mode to gain access to tcp/22 (ssh)
and udp/53 running on the system 10.0.0.123 from the IP 192.168.10.4:
$ fwknop -A 'tcp/22,udp/53' -a 192.168.10.4 -D 10.0.0.123
Same as above example, but gain access from whatever source IP is seen
by the fwknop server (useful if the fwknop client is behind a NAT device):
$ fwknop -A 'tcp/22,udp/53' -s -D 10.0.0.123
Same as above example, but use the IP identification website http://www.whatismyip.com/
to derive the client IP address. This is a safer method of acquiring the client IP
address than using the
-s
option because the source IP is put within the encrypted
packet instead of having the
fwknopd
daemon grant the requested access from whatever IP address the SPA packet originates:
$ fwknop -A 'tcp/22,udp/53' -R -D 10.0.0.123
Use the Single Packet Authorization mode to gain access to tcp/22 (ssh)
and udp/53 running on the system 10.0.0.123, and use GnuPG keys to encrypt
and decrypt:
Instruct the fwknop server running at 10.0.0.123 to allow 172.16.5.4 to
connect to TCP/22, but spoof the authorization packet from an IP associated
with www.yahoo.com:
# fwknop --Spoof-src 'www.yahoo.com' -A tcp/22 -a 172.16.5.4 -D 10.0.0.123
Command mode examples
NOTE:
Please ensure that ENABLE_CMD_EXEC; is set in the file
/etc/fwknop/access.conf
on the
fwknopd
server you are attempting to connect to.
Packet contents printed to stdout at the
fwknop
client when creating a 'command mode' SPA packet:
Random data: 4621962433020664
Username: mbr
Timestamp: 1203864394
Version: 1.9.2
Type: 0 (command mode)
Cmd: echo "The commands sent - minus quote charaters around the command" & sleep 10; echo "The End"
SHA256 sum: eN8c8mNArZxF066iulbxlTK4Gt/EO0ALLYwzVzCkXww
Instruct the fwknop server running at 10.0.0.123 to send a single ICMP
echo request to www.yahoo.com:
This connection mode is a legacy mode and is
not
the preferred or recommended mode.
Packet contents printed to stdout at the
fwknop
client when in 'port-knock mode':
<TODO>
Send an encrypted knock sequence to the IP "10.0.0.123" instructing the
fwknop daemon running there to open tcp port 22 to source address
192.168.10.4:
$ fwknop --Server-mode 'knock' -A tcp/22 -a 192.168.10.4 -D 10.0.0.123
Same as above, but this time instruct the remote fwknop daemon to open
tcp port 22 to whatever source address the encrypted sequence originates
from (useful if the fwknop client is behind a NAT device):
$ fwknop --Server-mode 'knock' -A tcp/22 -s -D 10.0.0.123
Same as above, but rotate the knock sequence through the tcp and udp
protocols (remember that iptables must be configured to log both tcp and
udp packets to the default port range of 61000-61255):
$ fwknop --Server-mode 'knock' -A tcp/22 -s -r -D 10.0.0.123
Same as above, but change the base port for the encrypted sequence to
55000 (the default is 61000):
Send a shared knock sequence to the IP 10.11.11.123. The fwknop client
will read the sequence out of the file
~/.fwknoprc
and the server will read the sequence out of
/etc/fwknop/access.conf:
$ fwknop --Server-mode 'knock' -D 10.11.11.123
DEPENDENCIES
fwknop
requires perl. To take advantage of all of the authentication and access management features of the
fwknopd
daemon/service a functioning iptables firewall is required on the underlying
operating system. If fwknop is being run in the legacy port knocking mode,
then iptables must log packets via syslog, and ideally the
--log-tcp-options
argument will be specified in the iptables logging rule so that the
fwknopd
daemon/service will
be able to use a strategy similar to
p0f
to passively fingerprint operating systems.
DIAGNOSTICS
fwknop
can be run in debug mode with the
--debug
command line option. This will
disable daemon mode execution, and print verbose information to the screen
on STDERR as packets are received.
Many people who are active in the open source community have contributed to fwknop.
See the
CREDITS
file in the fwknop sources, or visit
http://www.cipherdyne.org/fwknop/docs/contributors.html
to view the online list of contributors.
The phrase "Single Packet Authorization" was coined by MadHat and Simple
Nomad at the BlackHat Briefings of 2005 (see: http://www.nmrc.org/).
The term "port knocking" was coined by Martin Krzywinski (see:
http://www.portknocking.org/). The original p0f passive OS fingerprinter was
written by Michal Zalewski, and is available here:
http://lcamtuf.coredump.cx/p0f.shtml
BUGS
Send bug reports to mbr@cipherdyne.org. Suggestions and/or comments are
always welcome as well.
DISTRIBUTION
fwknop
is distributed under the GNU General Public License (GPL), and the latest
version may be downloaded from
http://www.cipherdyne.org/