Welcome back to this series, in which we discuss and configure the various features of pfSense. In the previous article, we set up VLANs on pfSense so that we could use pfSense for inter-VLAN routing. In that article, we also touched a bit on firewall rules. In this article, we will take a deeper look at configuring firewall rules on pfSense.

Firewall Rules

Among the most important features you will configure on a firewall are the firewall rules (obviously). When you install pfSense, all connections from the LAN are automatically permitted by default. However, all connections from the WAN are denied. We can view/configure firewall rules by navigating to Firewall > Rules:

Hint: In that article, we also saw that there are no firewall rules defined by default for new OPT interfaces. This means that any traffic seen on those interfaces will be denied, even traffic destined to pfSense itself!

Except for rules defined under the Floating tab, firewall rules process traffic in the inbound direction only, from top to bottom, and the process stops when a match is found. This is similar to how a Cisco router processes access lists, so one should be careful to put more specific rules at the top so that they are matched before generic rules.

Let’s configure a sample security policy as follows:

  • Any traffic from the LAN to any destination should be allowed.
  • Allow ICMP from the DMZ to any destination.
  • Allow SSH/HTTPS only from hosts 172.16.100.200 and 172.16.100.201 in the DMZ to the LAN network.
  • Allow DNS, HTTP, and HTTPS from the DMZ to the Internet.
  • Deny everything else!

Note: Because I’m trunking the VMware interface used for both LAN and DMZ, I may not be able to access the webGUI from the host PC anymore via the LAN IP address. Therefore, I will leave the rule for WAN access open. Keep in mind that, if you are using DHCP, the host PC’s IP address may change from the one you configured in the firewall rule and you won’t be able to access the webGUI anymore (depending on how strict your rule was).

Policy #1: Permit all traffic from LAN

As we have seen above, all traffic (IPv4 and IPv6) from the LAN is permitted by default. Therefore, we don’t need to do anything extra to configure this security policy.

Policy #2: Permit ICMP from DMZ

In the last article, we configured a firewall rule that allows ICMP from the DMZ to any destination, as shown below:

Let’s leave this rule configured but, by walking through the steps of configuring firewall rules for policy #3 and #4, you can understand how this rule was configured.

Policy #3: Permit SSH/HTTPS from 172.16.100.200 and 172.16.100.201 to LAN

I decided to include this policy here so that we could see another feature available in pfSense – Aliases. This feature is similar to object groups on the Cisco IOS, where we group similar objects together to make configuration simpler. With aliases, instead of specifying the individual objects, you just specify the alias name.

Therefore, let’s configure two aliases: one for SSH and HTTPS and the second one for the hosts 172.16.100.200 and 172.16.100.201. To do this, we will navigate to Firewall > Aliases:

As you can see, we can create aliases for IP, Ports, and URLs. We will start with the one for IP and then move to the one for ports.

When you are done with your configuration, apply your changes and we can move on to creating the firewall rule itself. We will navigate to Firewall > Rules and then select the DMZ tab. The settings for my own rule are shown below:

As you may have noticed when creating the port aliases, you don’t specify the protocol. It is when we are creating the firewall rule that we specify the protocol, as shown above. Also notice how we specified the source as the alias we created—once you start typing the name, aliases that match that name show up. We also used the alias we created for the ports under the Destination port range field. Finally, there are some default names such as LAN address (i.e., LAN interface IP address of pfSense) and LAN net (i.e., LAN network and other static routes configured on that interface) that we can use when configuring rules. These make your life easier because, if an address/network changes, you won’t have to alter the rule as the rule will be automatically updated to match the new address(es).

Policy #4: Allow DNS, HTTP, and HTTPS from DMZ to Internet

There are several ways you can configure this rule, depending on how restrictive you want your rule to be. DNS (not zone transfers) uses UDP port 53 by default, while HTTP and HTTPS use TCP port 80 and 443, respectively. If you create a port alias matching the three protocols, you will have to use “TCP/UDP” in the Protocol field of the firewall rule. This means that TCP/UDP ports 53, 80 and 443 will be allowed which is more than you want.

Let’s practice the principle of least privilege and be as restrictive as possible. We will create a port alias for HTTP and HTTPS and then create a standalone rule for DNS.

If you were able to identify a gap in this our configuration, I salute your observation skills. Because firewall rules apply to traffic coming into an interface and since we didn’t specify a destination network, it means this last rule we just created also allows hosts on the DMZ to open DNS, HTTP, and HTTPS connections to the LAN!

To remedy this situation, we need to add a rule that blocks traffic from the DMZ network to the LAN and place this rule between Policy #3 and Policy #4.

First, let’s create the rule: by default, new rules are added at the bottom.

To move the rule to the correct position, we will select the checkbox in front of the rule and click the “Move selected rules before this rule” button for the rule which we want the selected rules to precede (highlighted above):

With this, we have come to the end of our rules definition. The last policy says that everything else should be denied, but that is already implicit in the rules table (just like a Cisco ACL). Explicitly defining a “deny all” rule is useful when you want to log such traffic.

It is always advisable to test your firewall rules to make sure you have not accidentally permitted traffic that should be blocked or denied traffic that should be allowed. In our case, we may want to add some smarter devices (than VPCS) onto the LAN and DMZ that will allow us open SSH and HTTPS connections. Therefore, our GNS3 topology now looks like this:

Note: I have basic IP configuration on the routers. I have also enabled SSH on the LAN-RTR. Both routers are configured to use pfSense as their DNS server.

Let’s begin our test by checking that the LAN-RTR can ping an Internet URL (i.e., DNS and ICMP):

Next we will ping from a DMZ host to the LAN since ICMP from the DMZ is allowed to any destination (policy #2):

To test the third policy, I will open an SSH connection from the DMZ-RTR to the LAN-RTR:

For the fourth policy, I can ping from the DMZ-RTR to an Internet URL. Since this will involve DNS, we can confirm that our fourth policy works:

Just to confirm that our deny rule works (the one denying DMZ from accessing the LAN), I will change the IP address of the DMZ-RTR from 172.16.100.201 to 172.16.100.220 and try to open SSH to LAN-RTR again. As shown below, it won’t work:

Although the webGUI doesn’t (yet) provide a way to check the counters on firewall rules, we can use the following command through the Shell: pfctl -vvsr:

@89(1456227294) block drop in quick on le0_vlan20 inet from any to 172.16.215.0/24 label "USER_RULE: Block all traffic from DMZ to LAN"

  [ Evaluations: 11        Packets: 6         Bytes: 264         States: 0     ]

  [ Inserted: pid 25519 State Creations: 18446735277677785112]

Note: To access the Shell, enter option 8 at the console of pfSense or via the terminal when connected via SSH.

Summary

This brings us to the end of this article, in which we have configured firewall rules on pfSense. I hope you have found this article insightful and I look forward to writing the next one in the series.

References