We didn’t start the Fire[HOL]

FireHOL is one of those programs that have been out there but never got into using it. In contrast I was always relying on IPTABLES and many times locking myself out of my servers because I forgot to include SSH in the rules.

Since I started testing FireHOL out I reduced the need for IPTABLES or even improved on my IPTABLES understanding. Why? FireHOL is an IPTABLES configuration generator i.e an extremely simplified way to create IPTABLES chains.

*Some of the examples explained below were taken directly from the FireHOL documentation pages so the credit goes to the FireHOL team.

Installing FireHOL is as easy as apt install firewall on Ubuntu and everything related to FireHOL is in /etc/firehol/. The main configuration file is firehol.conf .

After installing FireHOL the firehol-defaults.conf must be created with the following command:

firehol firehol.conf

This file includes defaults which can be amended at a later stage.

It is very important to understand that FireHOL begins with DENY ALL and the rules apply for both IPv4 and IPv6. All packets coming in will be dropped i.e no traffic will be coming in or going out from the interfaces.

First things first, since I don’t use IPv6 in my network I disabled it in /etc/firehol-defaults.conf by changing

ENABLE_IPV6=1 to ENABLE_IPV6=0

Another very important element of FireHOL is that it only deals with requests and the replies are handled automatically. This means that when we set up a rule we will only set the rule of the incoming or outgoing request and not both pairs making it much easier to work with it.

Some glossary that will be useful later on.

  • Servers – Incoming requests – Internet to LAN
  • Clients – Outgoing requests – LAN to Internet

FireHOL configuration

All changes in the next sections are to be included in the /etc/firehol/ config file.

So first we need to declare the interfaces that the rules should apply to. If you are unsure about the interfaces names on your machine…

ip link show

1




So in my test server I have two interfaces. The lo interface is used for communication between programs running on the machine. FireHOL will automatically handle this therefore it should be ignored. So the only interface that I should care about is eth0.

In the configuration file we begin by declaring the interfaces to be used

interface eth0 internet 
#Internet is just the name to be used and it is the interface to be used for both internet and LAN requests. 
#If there is a separate interface for LAN it should be declared here.

Then we continue by declaring which services we will allow to come in and which services from inside the network will be allowed to reach the internet. As mentioned before, server refers to incoming connections and client refers to outgoing connections.

interface eth0 internet
    server dns accept
    server http accept

    
    client http accept
    client smtp accept 
	client dns accept 


# Another option is to declare allow all for clients outgoing access

    client all accept

The above configuration would be useful in scenarios that this server acts as an HTTP and SMTP redirector as it will accept HTTP requests coming in to the server but also allow the server to make outgoing HTTP connections.

At my intro I mentioned that FireHOL helped my improve my IPTABLES skills. At any given point in time we can view the actual IPTABLES rules that are used by FireHOL with:

firehol explain

And then type the commands.

2












The output might look daunting but in reality these are the rules created in the backend.

3












Now let’s say that I don’t want to use default services. As an example my HTTP servers usually run on port 80 on the redirector and port 8080 on the destination server. FireHOL allow us to declare variables as well.

server_custom_http_ports="tcp/80"

client_custom_http_ports="tcp/8080"

interface eth0 internet
    server server_custom_http_ports accept 
    client client_custom_http_ports accept 

The above configuration will allow incoming connections to port TCP 80 and outgoing connections to TCP 8080. As mentioned before we don’t have to deal with replies meaning that the rule for allowing traffic to port 80 doesn’t have to have an equivalent rule to allow traffic to port 80 to complete the communication. All of this will be handled by FireHOL itself. Taken verbatim from the FireHOL documentation page

“if a request is allowed, then the corresponding reply is also allowed. This also means that FireHOL produces the iptables statements to exactly match what is allowed in both directions and nothing more.”

FireHOL is also very flexible when defining ports and protocols. For example

The services can be defined in variables

udp_tcp_ports="TCP/8080,443 udp/4546"

same_protocol="tcp,udp/53"

interface eth0 lan
    server same_protocol accept 
    client udp_tcp_ports accept 

The above configuration will allow for TCP and UDP port 53 to be used for both incoming and outgoing connections and TCP ports 8080,443 and UDP 4546 to be used for incoming connections only.

FireHOL also supports more advanced rules which can help limit the packets which are matched by any statement by applying packet matching rules known as optional rule parameters.

  • inface – Input interface
  • outface – Output interface
  • src – Incoming IP
  • dst – Destination ip
  • proto – protocol
  • sport – Source port
  • dport – Destination port

Looking at some practical examples, let’s say for example we know the IP space of our target and we only want to allow connection to our server from that range. We first declare a variable containing the IP space that we want to allow. Then we declare the interface at which this rule should apply to.

target_range = "56.54.45.34/24"

interface eth0 internet src "${target_range}”  

The order of the rules is very important. For example if there is a rule defined to accept traffic from 10.1.1.1/24 and then another rule to accept
traffic from 10.1.1.4 only the first rule will be matched and processed therefore the second rule will be ignored.

FireHOL Helpers

The key feature of helpers is NAT. Two kinds of NAT are supported:

  • source NAT – Change the source IP of the packets going out to the internet
    • masquerade – dynamically check the IP the interface is using
    • snat – statically assign an IP we already know
  • destination NAT
    • dnat – send the traffic to another host
    • redirect – redirect the traffic to a process on the firewall

SNAT and DNAT definitions must always be defined at the top of the configuration file.

An example that this can be used is if the server running FireHOL is a redirector. In the following scenario the server will accept connections on port 80 on the eth0 interface and forward them to the 10.0.0.2.

dnat to 10.0.0.2 inface eth0 proto tcp dport 80

When NATing takes place we overwrite something on the packet like the source or destination IP, its source or destination port or all of them. When using NATting it is mandatory to match each rule with a router, server or client to explain what the traffic really is.

Final example config file that puts most into usage to put the examples into perspective.


public_ip="eth0"

#IP ranges that are allowed to access the server via SSH
ALLOWED_SSH_IPS="192.168.1.0/24 1.2.3.4"

# Masquerade outgoing traffic to use the public IP
ipv4 masquerade "${public_ip}"

#Send packets coming in on eth0 for destination port 8090 to 10.0.0.2
#Matched below at the router definition
dnat to 10.0.0.2 inface eth0 proto tcp dport 8090


interface eth0 internet
    server ssh accept src "$ALLOWED_SSH_IPS"
    server "http https" accept
    server ping accept
#Accept DNS lookups only from the target IP space
    server custom dns_tcp tcp/53 default accept src "[target IP space]"
    server custom dns_udp udp/53 default accept src "[target IP space]"

router apachetoc2 infame eth0 outface eth0 
	server http accept dst 10.0.0.2

# Outgoing:
    client all accept

Logging

Firehol will log anything that is not matched by the configuration file. However, this often fills /var/log/messages with logs of packets, so you can create a separate line for this using rsyslog, by creating a file named /etc/rsyslog.d/firehol.conf :

:msg, startswith, "firehol: " -/var/log/firewall.log
& ~ 

Edit /etc/firehol/firehol.conf and add

FIREHOL_LOG_PREFIX="firehol: "

This firewall.log file will quickly turn large with random blocked traffic; so you will want to create a /etc/logrotate.d/firewall file

/var/log/firewall.log
{
    sharedscripts
    compress
    postrotate
        /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
    endscript
}

Then restart rsyslog

service rsyslog restart

As with IPTABLES these configurations are prone to mistakes or blind spots. Make sure that all the scenarios are tested in a controlled environment before using in real engagements.

FireHOL is very dynamic and we only touched the surface here. The full documentation can be found at https://firehol.org/documentation/

And that is it!

For any questions or comments hit me up on Twitter.