Tuesday, November 29, 2011

Firewall improvement with fwknop

fwknop is an improvement upon the older technique of port-knocking. Quite simply, it looks like an ordinary failed attempt to connect blocked by a closed firewall...but something about the packet identifies it as trustable, and causes the host system to do an action (like briefly open a firewall port).

There are safeguards to prevent the packet from being spoofed, and until the packet is received my SSH port stays safely blocked by the firewall - preventing the use of clever undiscovered exploits.

This is pretty cool because it means that my ssh port can be safely closed behind a firewall, yet still accessible to me (and only me) on the internet.

There are a whole bunch of moving pieces here (firewall, ports, services, client, keys), so I'll talk a lot of detail about the installation and configuration, the some options, then try an example or two. I haven't even touched the options for using my GPG-key for knocking!

Planning: Ahead of time, fill in this list:
  • I want the knock to occur on UDP port #: (default 62201)
  • I want be able to open ports for the following services: (example: sshd)
  • Those services run on ports: (example: tcp/22)
  • I want my knock password (key) to be: (8 characters min -or- GPG)
  • I want to be notified of a successful knock by: (log/email/none)
  • The interface I want to protect is: (only one, usually the same internet-facing interface described in your firewall)
Install and configure fwknop on the server:
  1. Server Install:
    apt-get install fwknop-server   # Debian
  2. Enable fwknopd to autostart upon boot. Edit /etc/default/fwknop-server
    START_DAEMON="no"  #From
    START_DAEMON="yes" #To
  3. Customize the server setup by editing /etc/fwknop/fwknop.conf:
    EMAIL_ADDRESSES             root@localhost;  # From
    EMAIL_ADDRESSES             MyLoginAccountName@localhost;  #to
    PCAP_INTF                   eth0;  # From
    PCAP_INTF                   ppp0;  # To
    PCAP_FILTER                 udp port 62201;                         # From
    PCAP_FILTER                 udp port <some other port number>; # To
    PCAP_INTF should be the same internet-facing interface used in your firewall (for example, ppp0). You can only choose ONE interface. In this case, ppp0 protects the internet-facing interface only so it does not protect against, say, hackers on the LAN wifi.
    PCAP_FILTER is the udp port to listen for the knock on. Remember that PCAP_FILTER port number - you'll need that again on the client.
  4. Set the server access controls and keys by editing /etc/fwknop/access.conf:
    # Change all three of the following, if needed.
    OPEN_PORTS: tcp/22,tcp/23,tcp/24,udp/85;
    KEY: <Your-8-digit-key>;
    OPEN_PORTS is the list of ports fwknopd is permitted to open. The client will request a specific port on the list. Remember that 8-digit key, you'll need it again on the client.
  5. Edit the firewall to close all fwknop-protected ports. The fwknopd daemon will tell iptables to open the port as needed.
    iptables -A INPUT -i lan0 -p tcp -dport 22 -j ACCEPT
    iptables -A INPUT -i ppp0 -p tcp -dport 22 -j REJECT
    The first line opens the firewall for ssh from the LAN (not protected by fwknopd). The second line closes the firewall for ssh from the internet-facing ppp0. If the default policy is already DROP or REJECT, you don't need a separate entry at all and the second line can be deleted. fwknopd can open a port regardless of the default policy or any explicit closure rule.
  6. Restart fwknopd (and optionally the firewall) to load the new config(s):
    fwknopd -Restart
Optional Server Notes:
  1. E-mail spamming of successful knocks: I got tired of that pretty fast, so I moved the notifications to a log:
    • In /etc/fwknop/fwknop.conf, change ALERTING_METHODS from ALL; to noemail;
    • Create a new file /etc/rsyslog.d/fwknop.conf:
      # Log fwknopd actions to syslog, auth.log, and iptables.log
      :msg, contains, "fwkno" -/var/log/auth.log
      :msg, contains, "fwkno" -/var/log/iptables.log #my own custom iptables-related log
    • Restart rsyslogd to reload the new config: service rsyslog restart
  2. Server Testing Tip: To prevent locking yourself out of the server (and feeling like a chump), here's a way to test fwknop without erroneously locking yourself out:
    • Edit /etc/ssh/sshd.conf to add a second ssh port (let's say port 2233)
    • Restart sshd to load the new config: service ssh restart
    • Use netstat -tulpn to ensure sshd is really listening on both ports
    • Edit your firewall so the new port (2233) is either explicitly closed or closed by the default policy (it doesn't matter which as long as it's closed). If necessary, reload your firewall to apply the changes.
    • Configure fwknopd to listen on your LAN interface, and only to control the ssh test port.
    • Do your testing and experimenting. Your original ssh port is unaffected.
    • When testing is complete, edit /etc/ssh/sshd.conf to remove the testing port, remove any testing-port related lines in your firewall, and edit /etc/fwknopd/access.conf to remove the test port.
Install and configure fwknop on the client:
  1. Client Install:
    sudo apt-get install fwknop-client   # Ubuntu
  2. Usage with manually-entered key:
    $fwknop --Server-port 12345 --Access 'tcp/22' -R --Destination myserver.dyndns.org
    Enter your key: <Your 8-digit key>
    $ssh -p 22 myserver.dyndns.org
    Server-port is the PCAP_FILTER, the UDP port to send the knock on.
    Access is the firewall port to open. It must be on the server's OPEN_PORTS list.
    The 8-digit key must be the same, of course, as on the server.
    The followup ssh command to connect on the briefly-open port is just an example.
  3. Create a keyfile for automatic use (optional): Use the format servername: key
    echo "myserver.dyndns.org: <Your 8-digit-key> > .knock-keyfile
  4. Usage with keyfile key (optional - handy for scripting):
    $fwknop --Server-port 12345 --Access 'tcp/22' -R --Destination myserver.dyndns.org --get-key .knock-keyfile
    $ssh -p 22 myserver.dyndns.org

No comments: