fwknop

最後更新: 2017-02-27

介紹

 

Single Packet Authorization (SPA) - modern replacement for port knocking

fwknopd

written in C

HMAC with KEY

An SPA packet is "valid" when it is authenticated via an HMAC

Encrypted by a strong cipher with an expected key (Rijndael encryption mode)

The fwknop client strips off any trailing "=" characters before sending an SPA packet.

supports iptables, ipfw, pf

iptables 上的特性

daemon relies on the iptables "comment" match in order to store the expiration time for new ACCEPT rules upon receiving a valid SPA packet.

all new rules are added by fwknopd to the FWKNOP_INPUT chain to ensure separation with the rest of the iptables policy.

We assume that iptables is configured in a default-drop stance for port

iptables -I INPUT 1 -i eth0 -p tcp --dport 22 -j DROP

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.

iptables -I INPUT 1 -i eth0 -p tcp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

SPA server will only allow access to the IP that was originally encrypted within the SPA payload

By default, the fwknop client sends SPA packets over UDP port 62201.

功能

Stopping Replay Attack

spaserver 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

/tmp/fwknop/digest.cache

# <digest> <proto> <src_ip> <src_port> <dst_ip> <dst_port> <time>
DIGEST     17      s.s.s.s  58536      d.d.d.d  62201      1519636310

 


Package / Software

 

Android: fwknop2

Window: fwknop-gui (https://incomsystems.biz/fwknop-gui/index.php)

wrt Package:

 - fwknop (libfko)
 - fwknopd (libfko, libpcap, iptables)

# Debian

 - fwknop-client (libfko3)
 - fwknop-server

 


Install on wrt

 

opkg install fwknopd

opkg install luci-app-fwknopd

# Check Version

fwknopd -V

fwknopd server 2.6.6

# Help

fwknopd -h

 


Generate encryption and HMAC keys

 

fwknop --key-gen

[*] Creating initial rc file: /root/.fwknoprc
KEY_BASE64: ??
HMAC_KEY_BASE64: ??

 


Config fwknopd

 

Main Config File:

/etc/config/fwknopd

# 在 /etc/init.d/fwknopd 內 start() function 有 gen_confs
# gen_confs 就是用來 gen /etc/fwknop/access.conf 及 /etc/fwknop/fwknopd.conf
config global
        option uci_enabled '1'

# 建立 fwknopd.conf
config config
        option PCAP_INTF 'eth1'
        option ENABLE_IPT_FORWARDING 'y'

# 建立 access.conf
config access
        option SOURCE 'ANY'
        option keytype 'Base 64 key'
        option hkeytype 'Base 64 key'
        option OPEN_PORTS '3389/tcp'
        option KEY_BASE64 ''
        option HMAC_KEY_BASE64 ''

Show Config

uci show fwknopd

fwknopd.@global[0]=global
fwknopd.@global[0].uci_enabled=1
fwknopd.@access[0]=access
fwknopd.@access[0].SOURCE=ANY
fwknopd.@access[0].keytype=Base 64 key
fwknopd.@access[0].hkeytype=Base 64 key
fwknopd.@access[0].OPEN_PORTS=3389/tcp
fwknopd.@access[0].KEY_BASE64=?
fwknopd.@access[0].HMAC_KEY_BASE64=?
fwknopd.@config[0]=config
fwknopd.@config[0].PCAP_INTF=eth1
fwknopd.@config[0].ENABLE_IPT_FORWARDING=y

Running config

/etc/fwknop/access.conf

/etc/fwknop/fwknopd.conf

Setting

SOURCE (default: ANY)

This defines the IP or IPs that are allowed to send valid SPA packets

The string "ANY" is also accepted if a valid SPA packet should be honored from any source IP.

KEY

defines the primary key used to generate and validate the SPA packet

HMAC_KEY

defines the HMAC message verification key.

FW_ACCESS_TIMEOUT

defines in seconds the length of time that a port will remain open by default. Note that even after the port closes, the established connection will persist until terminated.

MAX_SPA_PACKET_AGE

defines the maximum age in seconds that the server will accept requests. If left blank, it will default to 120 seconds.

PCAP_INTF

dictates which interface Fwknop will listen on.

Define the ethernet interface on which we will sniff packets. (-i eth1)

By default fwknopd does not put the pcap interface into promiscuous mode (ENABLE_PCAP_PROMISC)

OPEN_PORTS

defines the protocol and port to open when a valid SPA packet is received.

If left blank, this information will be derived from the SPA packet.

If populated, this must be in the format of protocol/portnumber e.g. tcp/22 or udp/22.

By default, an SPA user can request access to any service within a properly constructed SPA packet

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.

ENABLE_IPT_FORWARDING (Defaults to "y") <== SPA Across NAT Gateways

Defines whether an SPA packet can trigger port forwarding through to an internal host.

Chain FWKNOP_FORWARD (1 references)
Chain FWKNOP_PREROUTING (1 references)

i.e.

# SSHD on 10.2.1.10 behind the spaserver(spaserver.domain.com)

fwknop -N 10.2.1.10:22 -n spaserver.domain.com

REQUIRE_SOURCE_ADDRESS <Y/N>

Force all SPA packets to contain a real IP address within the encrypted data.

This makes it impossible to use the -s command line argument on the fwknop client command line,

so either -R has to be used to automatically resolve the external address (if the client behind a NAT) or

the client must know the external IP and set it via the -a argument.

log

(stanza #1) SPA Packet from IP: s.s.s.s received with access source match[s.s.s.s] 
(stanza #1) Got 0.0.0.0 when valid source IP was required.

 


Package 有效時間

 

ENABLE_SPA_PACKET_AGING (Default: Y)

This instructs fwknopd to not honor SPA packets that have an old time stamp.

The value for "old" is defined by the "MAX_SPA_PACKET_AGE" (Default: 2 min).

Defines the maximum age (in seconds) that an SPA packet will be accepted.

ENABLE_DIGEST_PERSISTENCE <Y/N>

Track digest sums associated with previous SPA packets processed by fwknopd.

 


Other Setting

 

HMAC_DIGEST_TYPE

# MD5, SHA1, SHA256, SHA384, or SHA512

i.e.

HMAC_DIGEST_TYPE SHA512

當 DIGEST 不對應時

(stanza #1) Error creating fko context: Args contain invalid data: FKO_ERROR_INVALID_DATA_HMAC_COMPAREFAIL

PCAP Setting

PCAP_FILTER 'udp port 62201;'

Define the filter used for PCAP modes; we default to udp port 62201.

PCAP_DISPATCH_COUNT <count>

Sets the number of packets that are processed when the pcap_dispatch() call is made.

The default is zero, since this allows fwknopd to process as many packets as possible in the corresponding callback where the SPA handling routine is called for packets that pass a set of prerequisite checks.

PCAP_LOOP_SLEEP <microseconds>

Sets the number of microseconds to passed as an argument to usleep() in the pcap loop.

 


Start fwknopd

 

# Start

/etc/init.d/fwknopd start

# Status

-S, --status            # Display the status of any running fwknopd process.

Detected fwknopd is running (pid=2276).

Process

/usr/sbin/fwknopd --foreground --syslog-enable -c /var/etc/fwknopd.conf -a /var/etc/access.conf -i eth0.2

 


Debug

 

fwknopd -vtf

-f, --foreground   - Run fwknopd in the foreground

-t, --test             - Test mode, process SPA packets but do not make any firewall modifications.

-v, --verbose      - Set verbose mode.

[*] Ignoring unknown access parameter: 'keytype' in /etc/fwknop/access.conf
[*] Ignoring unknown access parameter: 'hkeytype' in /etc/fwknop/access.conf
Warning: REQUIRE_SOURCE_ADDRESS not enabled for access stanza source: 'ANY'
[*] Invalid protocol in access port entry: 3389/tcp
[*] Fatal invalid OPEN_PORTS in access stanza
...

# Dump the configuration values

fwknopd -D

Current fwknopd config settings:
  0. CONFIG_FILE                  =  '/etc/fwknop/fwknopd.conf'
  1. OVERRIDE_CONFIG              =  '<not set>'
  2. PCAP_INTF                    =  'eth1'
  3. PCAP_FILE                    =  '<not set>'
  4. ENABLE_PCAP_PROMISC          =  'N'
  5. PCAP_FILTER                  =  'udp port 62201'
  6. PCAP_DISPATCH_COUNT          =  '100'
  7. PCAP_LOOP_SLEEP              =  '100000'
  ....

# Checking Rule

# List all firewall rules that fwknop has created

fwknopd --fw-list

num  target     prot opt source               destination
Chain FWKNOP_FORWARD (1 references)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  s.s.s.s              192.168.123.31       tcp dpt:3389 /* _exp_1553593557 */
Chain FWKNOP_PREROUTING (1 references)
num  target     prot opt source               destination
1    DNAT       tcp  --  s.s.s.s              0.0.0.0/0            tcp dpt:33389 /* _exp_1553593557 */ to:192.168.123.31:3389

# Cleanup Rule Create By fwknopd

fwknopd --fw-flush

Deleting any existing firewall rules...

 


iptables 變化

 

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
FWKNOP_INPUT  all  --  0.0.0.0/0            0.0.0.0/0

Chain FORWARD (policy DROP)
target     prot opt source               destination
FWKNOP_FORWARD  all  --  0.0.0.0/0            0.0.0.0/0

Chain FWKNOP_FORWARD (1 references)
target     prot opt source               destination

Chain FWKNOP_INPUT (1 references)
target     prot opt source               destination

當有正確的 SPA packet 到時

Chain FWKNOP_INPUT (1 references)
target     prot opt source    destination
ACCEPT     tcp  --  s.s.s.s   0.0.0.0/0     tcp dpt:2222 /* _exp_1589956920 */

 


UDP (no need libpcap)

 

# This instructs fwknopd to acquire SPA packets via a UDP socket directly without having to use libpcap

# fwknop should be compiled with --enable-udp-server so that libpcap can be removed as a dependency

ENABLE_UDP_SERVER            =  'N'
UDPSERV_PORT                 =  '62201'

 


Client

 

Opts

-n, --named-config=<stanza name>

Specify the name of the configuration stanza in the “$HOME/.fwknoprc” file to pull configuration and command directives.

--stanza-list

Dump a list of the stanzas found in “$HOME/.fwknoprc”.

-A, --access=<port list>

Provide a list of ports and protocols to access on a remote computer running fwknopd.

-D, --destination=<hostname/IP-address>

-G, --get-key=<file>

Load an encryption key/password from the specified file.

--get-hmac-key=<file>

Load an HMAC key/password from the specified file.

--use-hmac

Set HMAC mode for authenticated encryption of SPA communications.

--save-rc-stanza

Save command line arguments to the “$HOME/.fwknoprc”

.fwknoprc

[n.n.n.n]
ACCESS                      tcp/3389
SPA_SERVER                  n.n.n.n
KEY_BASE64                  ?
HMAC_KEY_BASE64             ?
USE_HMAC                    Y
VERBOSE                     Y
RESOLVE_IP_HTTPS            Y

RESOLVE_IP_HTTPS

Set to Y to automatically resolve the externally routable IP associated with the fwknop client.
(https://www.cipherdyne.org/cgi-bin/myip)

 


log

 

fwknopd 成功加 rule

成時

(stanza #1) SPA Packet from IP: s.s.s.s received with access source match
Added access rule to FWKNOP_INPUT for s.s.s.s -> 0.0.0.0/0 tcp/2222, expires at 1519706071

一段時間後

Removed rule 1 from FWKNOP_INPUT with expire time of 1519706071

Checking

iptables -nL | grep 2222

ACCEPT     tcp  --  s.s.s.s        0.0.0.0/0            tcp dpt:2222 /* _exp_1519706158 */

fwknopd 失敗的 log

# 錯 port (fwknopd 不 Allow 加當前的 port)

(stanza #1) SPA Packet from IP: s.s.s.sreceived with access source match[s.s.s.s] 
(stanza #1) One or more requested protocol/ports was denied per access.conf.

# 錯 HMAC

(stanza #1) SPA Packet from IP: s.s.s.s received with access source match[s.s.s.s] 
(stanza #1) Error creating fko context: Args contain invalid data: FKO_ERROR_INVALID_DATA_HMAC_COMPAREFAIL

# 錯 key

(stanza #1) SPA Packet from IP: s.s.s.s received with access source match[s.s.s.s] 
(stanza #1) Error creating fko context: Decryption failed or decrypted data is invalid

Remark

測試次序

HMAC -> KEY

 


Forward

 

FORCE_NAT <IP> <PORT>

For any valid SPA packet, force the requested connection to be NAT'd through to the specified (usually internal) IP and port value.

用圖:

This is useful if there are multiple internal systems running a service such as SSHD,
and you want to give transparent access to only one internal system for each stanza in the access.conf file.
This way, multiple external users can each directly access only one internal system per SPA key.

log

(stanza #1) SPA Packet from IP: s.s.s.s received with access source match
Added FORWARD rule to FWKNOP_FORWARD for s.s.s.s -> 192.168.123.31 tcp/3389, expires at 1519708948
Added DNAT rule to FWKNOP_PREROUTING for s.s.s.s -> 0.0.0.0/0 tcp/3389, expires at 1519708948

ENABLE_DESTINATION_RULE Y

Controls whether fwknopd will set the destination field on the firewall rule to the destination address specified on the incoming SPA packet.

DNAT rules will also have their destination field set.

The default is "N", which sets the destination field to 0.0.0.0/0

Full Example Config

/etc/config/fwknopd

config global

config access

config config

fwknopd.conf

PCAP_INTF eth1
ENABLE_IPT_FORWARDING y

access.conf

SOURCE ANY
KEY_BASE64      ?
HMAC_KEY_BASE64 ?
OPEN_PORTS tcp/33389
FORCE_NAT 192.168.123.31 3389
FW_ACCESS_TIMEOUT 60
REQUIRE_SOURCE_ADDRESS y

REQUIRE_USERNAME STRING

Require a specific username from the client system as encoded in the SPA data.

This variable is optional and if not specified, the username data in the SPA data is ignored.

 * 我地可以用呢個 feild 來分 Service 在那個 Host

 * 手機 Client 不支援 UserName

 


Run Program

 

ENABLE_CMD_EXEC <Y/N>

This instructs fwknopd to accept complete commands that are contained within an authorization packet.

Any such command will be executed on the fwknopd server as the user specified by the "CMD_EXEC_USER" or

as the user that started fwknopd if that is not set.

CMD_EXEC_USER

 


SPA Packet

 

Fields:

    16 bytes of random data          # No two SPA packets are identical because they contain 16 bytes of random data before being encrypted
    Local username
    Local time stamp
    fwknop version
    SPA message type
    Access request or command to execute
    SPA message digest (SHA-256 by default)

Optional SPA Packet Fields:

   NAT access request
   Third-party authentication information
   Firewall rule timeout

Message Type:

  • Open Port
  • Nat Access
  • Local Nat Access
  • Server Command

 


DOC

 

https://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html

https://www.cipherdyne.org/fwknop/docs/manpages/fwknopd.html
 

 

 

Creative Commons license icon Creative Commons license icon