最後更新: 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