Name: nf2fa Description: Port knocking meets two-factor authentication (2fa) Start date: 1st Feb 2018 Author: Catalin(ux) M. BOIE Code: https://rocketgit.com/user/catalinux/nf2fa See also: fwknop, "Single Packet Authorization (SPA)" . How it works? By default your firewall will drop all packets. With a special packet, which will contain a code generated by your mobile device, you will be able to open the firewall only from your connecting IP. Also you will be able to close the firewall as soon as you do not need it open anymore. . Why you need this program? - Because classic port knocking can be replicated from anywhere, if the attacker can sniff the traffic. - With a digital signature program, you need some code on the client side, which may not be available for all platforms. - This program allows hosts to be completely silent, to not answer any request from outside: no code exposed to attacks and no log pollution. . Installation & configuration After installation, edit the configuration file (/etc/nf2fa.conf) and set the desired parameters. Then, start the daemon. You will run 'nf2fa enroll' command to enroll a new device. You will need to type a password and then confirm it. Install FreeIPA or Google Authenticator on your mobile device and scan the QR code shown on the screen. Now your user is enrolled. This procedure will set the same key on both server and mobile device. Now, your 2fa application will be able to generate some time based tokens (6 digit codes). Check below how to setup your firewall. The rules will force control packets to hit nf2fa daemon and will trigger the validation. On another machine, you will need to run the special ping/nc command to open the firewall. For this, you will need the password entered at enroll time and the 6 digits token. See below the examples. Please note that the time must be in sync on both server and mobile device because the tokens are time dependent. . Firewall preparation For iptables: # Connections already marked by nf2fad are accepted -A INPUT -i ethX -m connmark --mark 0x77777777 -j ACCEPT # Packets marked by nf2fad but with no connection tracking marking, # will trigger the saving into connection tracking table -A INPUT -i ethX -m mark --mark 0x77777777 -j CONNMARK --save-mark # We need this rule again, to not hit again nf2fad. -A INPUT -i ethX -m connmark --mark 0x77777777 -j ACCEPT # CONTROL_CHANNEL(S)_SECTION: These are the control channels: -A INPUT -i ethX -p icmp --icmp-type echo-request -j NFQUEUE --queue-num 4444 -A INPUT -i ethX -p udp --dport 1 -j NFQUEUE --queue-num 4444 # ALLOW_SECTION: Now, what ports to allow. # Next rule will pass port 22 (for example) to nf2fa and the connection will # be marked if allowed. You may add here other ports as well. -A INPUT -i ethX -p tcp --dport 22 -j NFQUEUE --queue-num 4444 For ip6tables: -A INPUT -i ethX -p ipv6-icmp --icmpv6-type echo-request -j NFQUEUE --queue-num 4444 -A INPUT -i ethX -p udp --dport 1 -j NFQUEUE --queue-num 4444 -A INPUT -i ethX -p tcp --dport 22 -j NFQUEUE --queue-num 4444 Notes: - Above, only SSH port was activated, but you may add any other protocol or ports. - These should be the first rules. If you add rules allowing ESTABLISHED conns before these, you will not be able to close the firewall or renew the timer. - Of course, you must have final DROP rule which drops anything. . Example enrollment: $ nf2fac enroll MySpecialPhone1 Password (only 0-9 and a-f): Password (confirmation): Key is QDCAXNGWJWCIOSI5 (id 001). Scan the QR code below or type the key. █████████████████████████████████████████ ██ ▄▄▄▄▄ █▄ ███▄█▄█▄█▀▄ ██ ▀█▀▄█ ▄▄▄▄▄ ██ ██ █ █ █▄ █▄ ▀▄ █▄▀ ▄█▀ ▀▄██ █ █ ██ ██ █▄▄▄█ █▀ ▄▄▄▄▀ ▄█▀█▄ ██ █▄█▀█ █▄▄▄█ ██ ██▄▄▄▄▄▄▄█▄▀ ▀▄█▄█ █▄█▄▀▄█ ▀ ▀ █▄▄▄▄▄▄▄██ ██▄▀▄█▀▀▄ ▀ █▀▀▄█▄ ██ ▄██ ▀█▀█ █▀ ▀ ██ ███▀█▀ ▀▄█ ▀ ▄█ ▄▀ █▀▀ ▄▄█▄▄▀ █▀▀ ▄▀██▄██ ██▄ ▀▀ ▄▄▄▀▀▄▀█▄▄▀██▀ ███▀▄▀▀ ▄▄ ▄█▄▄▀▄██ ██▀▄▄ ▄▄ ▀▄▄▄█▀▄ █▀▄▄▀█▄▀ ▄▄▀█▄▀ ▄▄███ ██▀▄█ ▄ ▄ █ ▄██ █▀ ██▀ ▄█ ▄▀█ █▀ ██ ██▀▄▀▄█ ▄█ ▀ ▀ ▄██ ▀▀▄ ▄█▄ ▄ ▀▀▀█ ▀ ██ ██▄█▀▄▄▀▄ ▄ ▀ ▀ ▀▀█ ███▀▄▀ ▀▀▀ ███▄████ ██▄ ▀█ ▄ ▀▄█▀ █▄▄▀▄ ▄▄▄ ▄▄▀▄▄ ▀▄▄ ▀▄▄███ ██▄█ ▄▄▄▄ ██▀ ▄ █ ██ ██ ▄▄ ▄██▀█▄ ██ ██▄▄▄ ▄▀█ ▄▄▀ ▄▀ ▄▀▄█▄█▀ █▄ ▄█▄▄ █▀█ ██ ██▄▄▄▄██▄█ ▀ ▀ ▄█▀ ██▀██▄▀██▄▀ ▄▄▄ ▀▄▄▀██ ██ ▄▄▄▄▄ █▄▀▄▄▀▄▄ ▄▀▀ ▄▀▄ ▄▀▄▀ █▄█ ▀▄ ▄██ ██ █ █ ██ ▄█▀▀ ▄▄▄▄ ██ ▄██ ▄▄ ███▀██ ██ █▄▄▄█ █▄▀█▀▀▄▀▄▄█ ▄▄▀▄█▄▀▀▀▄▀█▄▀▄▄▄██ ██▄▄▄▄▄▄▄█▄▄▄██▄█▄███▄██▄███▄█▄█▄█▄███▄██ █████████████████████████████████████████ . List enrollments: $ nf2fac list Sample output: No Enroll time Name 000 2018-02-13 22:46 key1 Last access from IP 192.168.79.155 on 2018-02-13 23:36 001 2018-02-13 23:44 key2 Last access from IP 192.168.79.155 on 2018-02-14 00:44 002 2018-03-04 09:13 aaa 003 2018-03-04 09:15 aaa . Un-enrolling $ nf2fac unenroll 003 Sample outputs: Successfully un-enrolled. or: Error: key id not found! . How to send commands from the client: $ ping -c1 destination -p aaPP...PPIIIIIICC Where: aa is the start of the command (just type two 'a' letters) PP...PP is the password entered at enrollment phase IIIIII is the 6 digit pin generated by the 2fa application CC is the command 11 - open firewall cc - close firewall Sample: # Unlocking my IP PASSWORD="12fa45" PIN="082653" $ ping -c1 172.30.43.4 -p aa${PASSWORD}${PIN}11 # Locking my IP PASSWORD="12fa45" PIN="539252" $ ping -c1 172.30.43.4 -p aa${PASSWORD}${PIN}cc If an answer is received, the command executed with success. On timeout, an error occurred. Note that you can send any type of packet, not only ICMP. Here, we will use UDP: # On the server (we use here port 1): # -A INPUT -i ethX -p udp --dport 1 -j NFQUEUE --queue-num 4444 PASSWORD="12fa45" PIN="539252" $ echo "aa${PASSWORD}$PIN}11" | nc --udp -4 172.30.43.4 1 # No answer will be received