Skip to content

Securing your PfSense Network (Part One?)

Subnets and VLANS

What was the saying? Don’t keep all your eggs in one basket?

A fundamental requirement for properly securing a network is to segment it based on it’s requirement. To do this we split our network into subnets and VLANs (Virtual LAN). Although all the devices may share one physical connection, we can compartmentalise them logically.

We do this to minimise the spread of impact if one device becomes compromised. The network is split and controls are placed between the compartments. Between each compartment firewall rules are used under a white-listing approach to only allow traffic that is required.

There are a couple ways you can go about this, and this is applicable to most people. Obviously to properly implement these controls you really need to ditch that “smart” ISP-supplied router of yours and get something that can actually do the job correctly (Netgate 1100) (Unifi Security Gateway).

The Almost-As-Good Way

Many modern routers feature a Guest Network setting. The idea is that you can broadcast a WiFi network with no pre-shared key, and that any devices that do connect to this network are only provided internet access.

This is a good start, and something that you could connect your personal microphones assistant and various other devices that just simply need internet access. You’d use the other ‘normal’ network for your laptop and other devices that you can trust to an extent.

I’d start by navigating to the administration portal of your router, generally located at or whatever your gateway IP address is (checkout ipconfig in cmd.exe).

The Good Way

As I have described earlier, and will elaborate on further, the good way of implementing security measures is by segmenting your network and grouping common devices into logical (or most ideally physical) networks.

There are various guides on how to create VLANs on different kinds of routers. I use PfSense and will be using that to describe my procedure but the whole damn thing is pretty standardised anyway. The following can be simply used as a guideline and suggestion.

Insecure, Secure, and Secret

This is simply suggestion/opinion and you should take this as a baseline and work with what you require, but I believe almost all networks fundamentally require three networks that are either logically or physically separated. These networks are;

  • The Insecure/IoT Network: For all devices that connect to the network for the first time that require at least internet access. These are devices we cannot trust initially and therefore should not have access to any other clients connected on the same network. Connecting to this network should be default and in most cases suitable to all devices.
  • The Secure Network: For all devices that we can trust to be secure, or that may need to be able to communicate with other devices on the network. This could be like Computers, Mobiles, Home-Servers.
  • The Secret Network: For all devices that contain sensitive data that do not require internet access to operate. IP (CCTV) cameras and their NVR’s generally would fit into here, as well as any storage servers that contain copies of your passports, or even locally operated password managers.

Simple Firewall Rules

To reduce adminis-trivia we must work to implement simple and elegant rules. Here is the best that I can think of lol.

Deny Egress

You’d assume that if there were not rules on a firewall all traffic would be blocked. Unfortunately this is not the case – at least for LAN side interfaces.

In PfSense, if no rules are added to a firewall – all incoming connections are blocked, but this only applies to the WAN interface. This is an unfortunate de facto default in many other firewall implementations, and one that PfSense is aware of. PfSense has decided to continue with this as to not trip up administrators.

Because of this, a fundamental rule that I add on my firewall for all my LAN interfaces is a “Deny Egress” rule. Simply, it’s a rule that sits at the very bottom of the stack where by if traffic does not meet the conditions for any other firewall-allow rule, it will be rejected. This way, only traffic that is specifically permitted to transit through the firewall is permitted.

To define this rule; BLOCK any traffic, on either IPv4 or IPv6, using ANY PROTOCOL, from ANY SOURCE or DESTINATION, on ANY PORT.

What you’ll do from here is define all your ALLOW rules, but make sure this deny egress rule sits at the bottom. You can imagine this Firewall like a filter with traffic flowing from the top to the bottom. If there are any ALLOW rules that meet the packets requirements, it is passed on through the firewall.

BTW; that “Anti-Lockout Rule” is applied by default to first LAN interface in PfSense. It’s a rule that you can’t easily remove to avoid locking yourself out from the administration portal. Just pretend it’s not there.

Allowing LAN Infrastructure

Now that we’ve completely blocked off 100% of traffic, let’s start allowing some important services through. Obviously, devices on your LAN must be able to communicate with your PfSense router, and any other services running to operate the network (DHCP, DNS).

Let’s create an alias for all our infrastructure. Jump into Firewall > Aliases and then click “Add”. I’m going to name this alias Infrastructure. You can have different kinds of aliases, for this one I’m going to select Hosts and identify our IP addresses we want to allow one by one. First and foremost, the router ( in my case). For this network, my PfSense router operates DHCP and DNS, so I don’t need to add any more IP’s here.

Save that. Let’s jump back over to our firewall. I’m going to add a new rule that will PASS any IPv4 traffic under ANY PROTOCOL, that comes from OUR NETWORK to the INFRASTRUCTURE ALIASES. Here’s what my stack looks like now, remember to keep the Deny Egress rule at the bottom!

Allowing Internet

In some cases, we may want internet access to our networks. We’ll need to create a rule to permit this.

There’s a cool way of doing it through the use of aliases. Rather than identifying all the IP addresses in the public space, we instead identify ones that are within the private space (RFC 1918).

What I’ve done here is identified the 3 classes of networks within private IP space as defined by RFC 1918. Now we’re going to create our firewall rule.

What I’ve done here is create a rule that allows any traffic that DOES NOT match any IP address defined within RFC 1918. This way, if a device tries to contact Cloudflare on it will be permitted to do so. If a device tries to contact my IP CCTV camera on it will be blocked.

At this stage, we now have a relatively functional and secure subnet. Clients are able to do their own thing and contact the web, but cannot contact each other! This is perfect for something like a guest network.

Allowing Local Client-to-Client

There may be times when clients may need to be able to communicate with each other on their network. For this, I have created a rule to allow Client-to-Client (C2C) communication.

Here, I’ve allowed any IP address that sits within the Secure network client-to-client (C2C) communication.

Suricata and Snort

A super neat way we can help to secure both incoming and outgoing connections is by utilising an Intrusion Detection System (IDS) and Intrusion Prevention System (IPS). Both Suricata and Snort can provide us this service.

An IDS/IPS is capable of analysing packets transiting through interfaces that the service is bound to and is able to identify and prevent malicious packets based on trends and patterns within the packets against a regularly updated and extensive database of known threats. I don’t plan on getting into the specifics on how this is achieved, primarily because I don’t fully understand it yet. What I do understand however is how blazingly fast and efficient it is at doing this. People are binding these services against multi-gigabit links.

Now obviously running something like this will require a bit of performance, but not quite as much as you’d expect. A well tuned IDS/IPS will only require a few CPU cycles, but this all depends on how much traffic is transiting through your interfaces, of course.

I personally use Snort, but I have seen Suricata and am very impressed. I haven’t really got the motive to switch, don’t really need to! Snort works for me.

Using Snort

PfSense has native support for Snort and there are no hoops that you need to jump to get it installed. Snort can be found in System > Package Manager, as an installable package. Once installed, you can configure it in Services > Snort.

I don’t think this is quite the place to go into a full blown discussion on how to operate Snort, but it is something I’d like to write about in future. You don’t need to pay any money for this service, there is a free tier, though if you would like to get the latest rulesets you’ll need to subscribe.

Enabling Rulesets

Jump into the Global Settings tab and enable the Snort GPLv2 Community Rules. You can also enable the Emerging Threats (ET) Rules as well. If you would like to detect what kinds of applications are being used to generate traffic on your network, you can also enable the Sourcefire OpenAppID Detectors. The FEODO Tracker Botnet C2 IP Rules is also a good one for detecting traffic from botnets.

I recommend you sign up to Snort and receive an “Oinkmaster Code”. This will allow you to enable Snort Subscriber Rules, Snort GPLv2 Community Rules, and the Emerging Threats (ET) Rules.

You can enable as many or as little rules as you like, but it’s absolutely critical you balance a level between security and functionality. Enabling absolutely everything will make your IPS incredibly noisy (loads of log messages) and basically pointless to a point where you can’t actually tell what kind of bad traffic is in transit. You must tune Snort!

Once we’ve enabled various rulesets, we need to pull the latests rules from Snorts repository. To do this go to the Updates tab and click Update Rules.

Binding an Interface

Head over to the Snort Interfaces tab and add a new interface. Here we will bind the Snort detector to either a LAN or WAN interface. Yes, there is a performance/functionality difference between binding to LAN and WAN.

The internet is a very noisy place, and if you bind to WAN you will pick up a lot of stuff and much of it being little to no risk (web crawlers and stuff). You must carefully tune this one to ensure friendly traffic is transiting through your gateway. You cloud bind to LAN and you will pick up bad traffic from perhaps an infected computer, you will be able to capture it before it even has an opportunity to spread! However, without binding on LAN you leave yourself susceptible to malicious incoming traffic going undetected.

My approach is to bind one detector to WAN and another to LAN and tune them independently! Use WAN as a IPS (prevention/blocking) and LAN as IDS (detection/monitoring). That way, your (generally) friendly LAN traffic is not so heavily restricted, just monitored for malicious intent, and your WAN IPS prevents malicious traffic from entering your network.

Let’s just work on WAN to start with.

Add a new Snort interface, enable it, bind it to WAN. Name it whatever you want (WAN is good enough). Enable Block Offenders. Save changes.

You’ll suddenly see a new row of settings in Snort. Once you’ve added the new Snort interface it will automatically direct you to it’s settings. You can return to here by clicking on Snort Interfaces > WAN > (Pencil Icon on the right).

Enabling Rules

Under the interface you want to modify, WAN in this case, go to the WAN Categories tab. Leave all the defaults, but enable Use IPS Policy and set it to Connectivity. Enable the Snort GPLv2 Community Rules (Talos Certified) ruleset as well. Click Save!

You can view the rules that are currently active by going over to the WAN Rules tab and setting the Category Selection to Active Rules. There’s quite a few rules but they’re all there to capture one specific thing. It’s not likely that you’ll receive traffic that triggers all the rules, but they’re there just in-case!


Snort Rulesets utilise various variables to refine traffic, most of which you can just leave as default. If you would like to, you can add IP Addresses and ports to various services hosted within your network. For example DNS_SERVERS can take a comma separated list of IPv4/IPv6 addresses and subnets.


Snort has these fancy pre-processors that inspect various bits of traffic. Something like HTTP Inspect is a neat one, it will analyse any HTTP/S traffic for anomalies to ensure someone isn’t trying to screw with your web server by sending malformed packets.

Portscan pre-processor is also another handy one. It can pick up if someone is running a port scan against your network and prevent it. This is pretty useful because a lot of attacks first start with a level of research conducted from a port/ip scan! Here you can prevent an attacker before they’ve even started to attack you! I tend to enable this one.


When your IPS/IDS is in action, Snort will log any alerts. You can view them under the Alerts tab.


I might leave this one for a future post.

PfBlockerNG is a another package that can be installed on PfSense. It it able to block packets in transit from certain IP addresses and domains a whole range of criteria such as Alexa reputation and IP address blocks assigned to various contries.

In simple terms, it allows you to block traffic from counties and websites where your network really doesn’t have much association with.

It’s extensively used by a massive community, and receives frequent updates.

A great place to start with PfBlockerNG is by installing it and reading the documentation.

Leave a Reply

Your email address will not be published. Required fields are marked *