https://www.vultr.com

The Everywhere Cloud

Deploy an instance.
Accelerate your application.


Configuring the FreeBSD Firewall with IPFW


IPFW is one of several firewalls included in FreeBSD by default. It has a command-line tool to handle the policies for incoming and outgoing connections.

In the configurations discussed here, network connections "from any to any" are deliberately avoided to prevent potential bounce attacks from happening, if the server is not intended to act as a router. Instead, a request/respond or incoming/outgoing rule pair is adopted to direct the flow of network traffic.

The main objective is to set up IPFW to block unauthorized remote access to unsecured ports on the server. But if attackers manage to break in through a vulnerability on some programs running on authorized incoming ports, the outgoing restrictions will prevent massive data exfiltration, stopping intruders dead in their tracks. A similar approach can be done on Debian-based Linux distributions using UFW.

==========

1. STRICT CONFIGURATION

1.1. Create a custom shell script for IPFW commands.

root@host: # ee /etc/myipfw.sh

1.2. Place the following code in the custom shell script.

===== BEGIN CODE =====
#!/bin/sh

ipfw -q -f flush
# This clears the existing firewall settings.

ipfw -q add 1 allow all from { me or me6 } to { me or me6 }; #Loopback
# This permits all loopback network traffic.

ipfw -q add allow tcp from any to { me or me6 } 22; # SSH server request
ipfw -q add allow tcp from { me or me6 } 22 to any; # SSH server response
# These open the SSH server port, ensuring that
# administrators will not be locked out of the server
# when the firewall is enabled.

ipfw -q add allow icmp from any to me icmptypes 0,8; # Incoming ping IPv4
ipfw -q add allow icmp from me to any icmptypes 0,8; # Outgoing ping IPv4
# These permit IPv4 pings for diagnostic purposes.

ipfw -q add allow ipv6-icmp from any to me6 icmp6types 128,129; # Incoming ping IPv6
ipfw -q add allow ipv6-icmp from me6 to any icmp6types 128,129; # Outgoing ping IPv6
# These permit IPv6 pings for diagnostic purposes.

ipfw -q add 65534 deny all from any to any
# This discards all other network traffic, preventing
# intruders from communicating with the outside
# world using server tools. Authorized ports can be
# opened and closed as needed later on.

ipfw list
# This enumerates the firewall settings after activation.
===== END CODE =====

1.3. Ensure that the shell script gets executed and the firewall is enabled during boot.

root@host: # sysrc firewall_script="/etc/myipfw.sh"
root@host: # sysrc firewall_enable="YES"

1.4. Activate the firewall.

root@host: # service ipfw start

1.5. [ONLY IF NECESSARY] Deactivate the firewall and keep it disabled during boot.

root@host: # service ipfw stop
root@host: # sysrc firewall_enable="NO"

/* If, for some reason, the settings do not reflect the expected policies, disabling the firewall prevents administrators from getting locked out while repeating the configuration process. */

2. POLICY MANAGEMENT

Once the initial configuration is done, incoming and outgoing connections can be added and removed as needed by modifying the custom shell script and restarting the firewall.

2.1. Open the custom shell script.

root@host: # ee /etc/myipfw.sh

2.2. Insert the following commands anywhere between the "ipfw -q add 1 ..." and "ipfw -q add 65534 ..." lines. Comment out (or delete) the line when no longer needed.

2.2.1. Open the port for incoming HTTPS to allow remote users to connect to the secure web service.

ipfw -q add allow tcp from any to { me or me6 } 443; # HTTPS server request
ipfw -q add allow tcp from { me or me6 } 443 to any; # HTTPS server response

2.2.2. Open the port for outgoing DNS to allow the server to access domain names, if some tasks require such services.

ipfw -q add allow udp from { me or me6 } to any 53; # Outgoing DNS request
ipfw -q add allow udp from any 53 to { me or me6 }; # Outgoing DNS response

2.2.3. Open the port for outgoing SSH to a remote host.

ipfw -q add allow tcp from me to 192.168.3.210 22; # SSH request to remote host
ipfw -q add allow tcp from 192.168.3.210 22 to me; # SSH response from remote host

2.2.4. Open all ports for incoming and outgoing connections from a trusted remote host.

ipfw -q add allow all from 192.168.3.210 to me; # Incoming from trusted host
ipfw -q add allow all from me to 192.168.3.210; # Outgoing to trusted host

2.2.5. Open all ports for incoming and outgoing connections from a trusted single Class B network with subnet mask 255.255.0.0 (256 Class C networks * 256 Class D hosts = 65,536 IP addresses).

ipfw -q add allow all from 192.168.0.0/16 to me; # Incoming from trusted Class B network
ipfw -q add allow all from me to 192.168.0.0/16; # Outgoing to trusted Class B network

2.2.6. Open the port for outgoing Multicast DNS (mDNS) to link-local addresses.

ipfw -q add allow udp from any to 224.0.0.251 5353; # Outgoing mDNS IPv4 request
ipfw -q add allow udp from any to ff02::fb 5353; # Outgoing mDNS IPv6 request

2.2.7. Open the port for incoming SSH from a trusted single Class A network with subnet mask 255.0.0.0 (256 Class B networks * 256 Class C networks * 256 Class D hosts = 16,777,216 IP addresses).

ipfw -q add allow tcp from 10.0.0.0/8 to me 22; # SSH server request from trusted Class A network
ipfw -q add allow tcp from me 22 to 10.0.0.0/8; # SSH server response to trusted Class A network

2.3. Restart the firewall.

root@host: # service ipfw restart

==========

REFERENCES

1. The FreeBSD Documentation Project. FreeBSD Handbook. Section 30.4, "IPFW". 

2. The FreeBSD Project. FreeBSD Manual Pages. "ipfw". 

==========

Comments

Popular posts from this blog

Enabling HTTPS in Home Assistant

Running Home Assistant on FreeBSD Servers