John Galea's Blog

My blog on Gadgets and the like

PFSense open source Firewall

Ok, I will warn you straight off, this is going to be a tekkie post, sure to bore many. But if your one of the few that eats bits for breakfast … enjoy! I have to admit, even as an IT guy with pretty good network knowledge this project challenged me.

Routers sit there out of the internet, exposed. The result of this is that they get hacked. Manufacturers stop updating firmware and plugging vulnerabilities because in the end, there is no motivation for them to spend the effort/$$s. Instead they want you to buy a new router every so many years. And the cycle goes on. And the firewall on routers is not always impervious … If you don’t believe this, after you’ve setup Pfsense see how many hacks get through your existing router!

This product attempts to fix this issue by putting another layer between your precious laptops, phones, gadgets etc and your likely leaking router. Or so the story goes. Frankly when a colleague of mine, Jeff, starting talking about this topic I had to admit the fascination of it alluding me, all the while he was enthusiastic and embracing of Pfsense. Now given I think Jeff is a bright fellow, so I decided to dive in and see what I could see … And frankly, it’s the winter, I’m not snowboarding, my gf is out of town, and I’m bored, so I decided to burn some cycles. And burn some cycles this will … Setting up Pfsense is no small feat. So let’s jump in. We will take this in small steps, enabling functionality as we go. I’ve written, updated and rewritten this article a number of times as I’ve learned more and more. In all I’ve been at this almost a month, but don’t fret, you can start small and add features until you get the functionality set you want.


So what is Pfsense you ask? It is a Linux (FreeBSD to be exact) Open source, extensible, highly configurable firewall. By default, it does not have some advanced features (like intrusion detection, anti virus etc), but these can be added through a fairly extensive list of package add ons. Pfsense can run on super small appliances, or it can be loaded on just about any old PC you have laying around. I chose to load it as a HyperV VM at first so that it costs me nothing, and I can assign it as much or as little resources as I want to … In the end the hardware resources for this firewall are quite low. I gave it 2G memory and 4 VCPU 20G and that was more than enough. In reality you really only need a couple G drive space for it to run off. As a VM I can also move around the networking that Pfsense has quickly and easily allowing me to implement it as it goes! I downloaded an ISO (which stupidly was Gzipped) and installed it from there. Installation was quick and painless. Once up you simply tell Pfsense which network has your internet (the WAN) and which has internal network (the LAN). You will need (and want) two network cards for Pfsense. IPs for these networks can be super simply setup. It’s worth noting, that Pfsense becomes your gateway out to the internet, so if it’s down … so’s most of your internal network. I did notice that they have obsoleted the 32 bit version of Pfsense at 2.35. Going forward you will need a 64 bit x86 processor. Pfsense could have, but does not allow you to have the two subnets on the same NIC which would have been helpful, but compromising from a security point of view. Pfsense can also implement all DSL PPOE authentication, allowing you to put your modem in what’s called bridge mode. Although I’ve not done this, to allow me to fall back quickly by turning the Bell modem, a SmartRG SR505, back on anytime and abandon Pfsense.

Getting started

Step one of getting it up and able to act as a firewall is pretty easy. My Router will remain on the perimeter with IP in the 192.168.1.x range. I chose to setup the LAN as 192.168.2.x. I can slowly migrate clients from the 192.168.1.x exposed side to the 192.168.2.x behind the firewall side. Pfsense is setup initially to be pretty lenient and allow pretty much everything outbound. This makes setup and admin much easier. You can choose whether this is how you want to leave it, or start adding rules blocking outbound stuff. I’ve seen other firewalls that take the opposite approach and deny all, but this becomes a headache pretty quickly. If your going to have anything that is serving in the home (web server for example) you will need to assign a static IP to the WAN (192.168.1.x) side of Pfsense. If Pfsense is going to be DHCP duty then the lan side (192.168.2.x) will also end up with a static IP. By allowing Pfsense to do DHCP (instead of your router) DNS inside your home can be comprehensive. Something that never quite worked right on my previous setup.

Configuring inbound NATs (and static IPs)

Next step is setting up your inbound rules. For me I have inbound RDP, as well as a web server. So first off you have to create static IPs (DHCP reservations) for any hosts that are going to serve. This is easily done from Status > DHCP Leases and click the + sign to add a static mapping. Or you can add them yourself Services > DHCP server down the bottom. The static IPs are based on MAC addresses of the network cards. First off you have to go to your router and repoint any incoming rules and move them to point to the IP address on the WAN side of Pfsense. Within Pfsense you then add Firewall > NAT for each server you want to host. I had some difficulty in that I had a VPN running on the one host which blocked the incoming NAT. This cost a NUMBER of hours to sort out, but in debugging I poked around a lot. I found Canyouseeme very valuable in testing externally inbound ports.

Outbound VPN

Ok now your ready for the next feature … outbound VPN. If you do any form of P2P you want a VPN if for no other reason than to avoid nagging from your provider. I found a great guide for setting up PureVPN for Pfsense. The VPN setup is done using OpenVPN. The setup was not at all straight forward and honestly took a while to get working. The one thing missing in this doc was the compression setting which was LZO Compression Legacy.

Now with this setup ALL traffic will go through the VPN. This isn’t what I want. What I really want is for any traffic for the one host that I run P2P on to go through VPN. So to take care of that I added an additional interface for the VPN. Interfaces > Assignments, add. This adds something it calls OPT1. Then in System > routing you now see a gateway for the VPN. Lastly you can now create a firewall rule that triggers on requests from that host and passes it to the VPN gateway instead of the default gateway.

You can use tools like IP chicken, or Whats my ip address to help debug when your connected to VPN and not.

Status > system logs can show you any errors VPN might be having. The status of the VPN connection can be seen at Status > OpenVPN.

The default for OpenVPN client is to have all communications go out the VPN once setup (as I mentioned above). In the configuring of the client you can remove this and then route the traffic you want to the VPN through rules.

I had one MAJOR issue with the VPN on Pfsense. I want what is called an internet kill switch. Ie if the VPN is down, then I want no traffic outbound outside of the VPN. At this point I’ve been unsuccessful in getting this working. What ought to be simple rules, just don’t seem to be working.

It’s worth mentioning that if you create a VPN on the PC then that PC is directly exposed to all other members of the same VPN. So it’s important to insure your running a firewall at the very least. By moving the VPN onto PFsense it removes this exposure. It is important that you turn Snort on (more on this later) on the VPN interface.

Dynamic DNS

Next up I added Pfsense updating dyndns which was super trivial. This allows Pfsense to update dyndns instead of my client. This became super important if ALL internal traffic is going through the VPN, because it will end up updating dyndns with your VPN IP since this would be all your internal network was aware of.

Ad/Malware/Ransomware blocking

With a fully functioning firewall we can now look into exploiting some additional functionality. I had read a bit about PiHole which is an ad/malware blocking DNS server that can be setup in a separate VM. Well it turns out you can do the same thing in Pfsense using PfblockerNG. There are two sides to PfBlockerNG. The first which for now I don’t care about looks for incoming hackers. The second replaces the DNS forwarder that normally is in use for internal DNS requests and replaces it by a DNS resolver. The DNS resolver has the ability to add lists to it that it will in turn reroute to an internal IP address, in effect blocking that IP (called DNSBL). There are lists of “bad” sites that can be obtained from PiHole. These are then manually added as feeds into DNSBL and the Pfblocked goes out and updates them daily. This gives you PiHole like functionality for free! To test if this is working go into one of the lists that you added as feeds and find a URL. Then simply ping that URL. If you get (the default for DNSBL) as the IP address back for that URL DNSBL is working perfectly! I had a major issue that I had DNSSEC turned on which requires a secure DNS server. As it turns out the DNS servers I use are not compatible with DNSSEC so outbound was being blocked. Turning DNSSEC fixed the issue. I originally turned on another function of Pfblocker called DNSBL easylist, but I found that blocked too many things to be useful so turned it back off. Even Google calendar stopped working. I also had issues in that most clients will cache dns requests. So to flush this on windows you have to enter:
ipconfig /flushdns (as an admin)
I ran into one oddity which is that if you stop Pfblocker, I had to manually tell Pfblocker to back out and resync the DNSBL feeds to get it working again if you then enable it.

Tuning DNSBL

Once your have turned on Ad/malware blocking you may see that there are sites being blocked that you don’t want blocked. These can be easily tuned to allow those domains. By going into Pfblocker, then alerts you can see what is being blocked as well as which list it was on. These domains can then easily be clicked on to add to a whitelist. This white list allows these domains through. Or you can manually add them to the Pfblocker, DNSBL, custom domain whitelists. And you can add domains, and include subdomains to allow. Once they are on the whitelist you will need to force a reload for them to start working, by Pfblocker, Update, force. Then you can test to see if that site is now not being blocked. Using this method you can fine tune what you want and not want to allow.

Blocking hackers/web robots

Now that the more important DNSBL is setup and running we can look at blocking known incoming attacking web sites. There are lists for this just like there are for DNSBL. These are configured in PFBlocker, IPV4 tab.

This in turn creates an incoming firewall rule to block these IPs.

To test this I added my own external IP address to the block list and then attempted a connect. Sure enough it was blocked and shows in the alerts as being blocked.

This web site had a couple of lists of bad guys to add to PfBlocker! Now this is entirely based on the sources IPs. As you can imagine bad guys can change their IPs so this is somewhat like chasing your tail. This is not to be confused with something like Snort that is more algorithmic detection based. This would also not detect anything like a port scan of your host. You can also use this feature to block web robots/spiders/crawlers from indexing your web site and adding it to search engines. You can also control well behaved spiders using Robots.txt on your web site.

In the end I don’t see much point to this part of Pfblocker.


It is quite common for hackers to try and see if they can get into networks and poke around using everything from known exploits to hacking tools etc. There are apps called Intrusion detection sensors (IDS) and prevention that attempt to use known patterns to identify and block these prods. Snort is one of these. Setting up Snort is a multi step process.

Step 1 install Snort

First install it from the packages list. It will consume additional memory, processor and disk space, but it ended up being less than I thought …

Step 2 tell Snort what interface to listen on

Once installed you need to tell Snort what interfaces you want it to listen on. At the very least I recommend your VPN and WAN (internet connection). Remember that outbound VPN is it’s own connection, and people doing bad things maybe also using VPN so it’s not a bad place to keep an eye on as well. And, the VPN drills a hole directly through your router/firewall so this is a place Snort is actually extremely helpful. And lastly snort can watch for bad things coming out of your internal network … like viruses and the like. In fact the packet inspection, and pattern recognition in Snort can very much be compared to anti virus, and the positive thing is these are blocked at the perimeter of your network. When defining your network (especially your external network) be sure and check block offenders. What’s the point in seeing an intrusion and doing nothing? Don’t forget to press save.

Step 3 tell Snort what to look for

Once the network is defined you need to go into WAN categories and tell it what you want it to look for. I just turned them all on, which annoyingly there is no enable all button.

Step 4 is Global setting

This defines what Snort does for all networks. I also created an account on which allows me to download patterns from Snort itself. Be sure and set an update interval for the patterns to insure you have the most current. I chose daily. I also again just basically turned on all of the available sources for known threats. I can always revisit this if it becomes to slow/burdensome.

Step 5 go get updates

By going into Updates next you can download all of the patterns so Snort knows what to be looking for. This would happen according to the update frequency you set above but this just lets you kick it.

Step 6 start it

At this point Snort is ready to go, but you have to manually start it. Go back to interfaces and start Snort. I hadn’t noticed this at first, and was wondering why it seemed to be doing nothing πŸ™‚ DOH. Snort can take a few minutes to get started so be patient.

Once started it will look like this and is good to go:

Test it

Ok so it’s installed, and configured but is it doing anything? I read lots of articles about how to test Snort. There were many way too complicated answers to this stupidly simple question. Well it’s actually pretty easy to test. Just use a port scanner, pscan, nmap whatever. Now just point that scan at the interface you enabled Snort to watch and let it rip. In short order Snort will jump into action. You can see this in Snort, alerts.

From this interface you can click the red x under source interface to remove this block (assuming you enabled block), or you could also click the red x under SID to remove that rule if you decided it was blocking something you didn’t want blocked. You can see what the IP that the offender was using along with the rule that triggered this alert. Under the blocked tab you can see all IPs that Snort has triggered on and subsequently blocked. Again here you can click the red x to remove the block. Now it’s worth noting that if you were doing this by RDP you have now just lost contact with the host you were testing from πŸ™‚ Don’t forget to unblock your test machine. And with that you’ve tested Snort …

Tuning Snort

Because Snort actively blocks sites it’s important to keep an eye at least at first at what it is alerting on. I found it was alerting on, and then blocking my VPN provider which in turn broke my VPN. It had false positive triggered. So I had to go into the alerts, disable the rule that was causing a false positive and then unblock my VPN provider. I also had issues that Snort was triggering on P2P, which in a corporate environment is bad, but at home is good, so I simply told it to ignore those.

It’s worth noting the obvious, that any thing that Snort detects as an attack, is something that went through your router (in my current setup where Pfsense is behind my router, ie double Natd).

Inbound VPN using OpenVPN

Next up I thought I would look at OpenVPN to be able to setup a VPN externally into my network. I started with this official guide to get going. It recommended using the wizards within OpenVPN and I didn’t at first and had no end of issues. Then I discovered (and it’s in the guide but I missed it) that you need to add a package to Pfsense to allow you to export your OpenVPN connection. This allows you to create simple install files to test out OpenVPN. I found tweaking and making changes to your OpenVPN server was easiest dealt with by downloading the install files and running them. If all that had changed was the config, then that’s all it installed. It ought to be possible to just export the configuration but I had no luck with that on Windows. Then I had issues with DNS resolver not working. These were fixed by creating an access list for the subnet of the VPN clients, in my case I had chosen 192.168.3.x. With this fixed and working I was able to get at my internal network remotely. This also means ad blocking would now also work with my VPN clients. It also means I can refer to my internal machines by their names rather than their IPs from VPN clients. The last thing not working was internet traffic through the VPN tunnel. Ie all remote internet traffic would go through my internet connection. This I had issues with and could not find the solution. And then I found this article that pointed to the fact that I needed to create an outbound NAT rule to allow VPN traffic externally. And like that … le voila it was done!
It’s worth noting that I tried to setup IPSEC/L2TP but could not find a group of setting that windows would live with and gave up. I had no end of performance issues with OpenVPN, and in the end got the best results by dialing down from SSL/TLS to Remote access User auth. This still used TLS for authentication making it harder to hack into my VPN. I also dialed down the encryption. The greyed out one was too slow, in spite of trying a number of different hardware solutions.

It’s worth noting, that if you decide to pass all of your remote traffic through your home you will be limited by the slowest part of your service speed. So in my case I was roughly 24Mb/s down and 7 Mb/s up. But remember, for a remote client this gets reversed. So the fastest you could possibly dream of would be 7Mb/s. Not great. So, my decision was simply to leave remote clients using their own internet connection for external communications. Internal would still go through VPN, and ad blocking etc still work. Of course you do loose the protection of Snort. To tell the remote client to use their own external connection turn this off:

To be able to use internal DNS names as well as ad blocking for remote hosts, be sure and turn on block outside DNS.

Traffic shaping

Traffic shaping is something I’ve had in the past and like it. The theory is to prioritize those things that are important. Like web browsing. And de-prioritize unimportant things like torrents. I played with this a LOT and got no where. In fact, I had it cause MAJOR performance issues. For now, I’ve turned this off.


Since Pfsense now becomes essential in the home I decided to look into clustering Pfsense. To do this you start out with two fully functioning, fully setup Pfsenses. The easiest way to do this is to set one up, then do a base install on the second, install all packages, and then backup from the primary and restore to the backup. Test both to make sure they are working. Once confirmed your ready to start. The first step is to setup System > high availability sync. This keeps the settings etc in sync between the two boxes. To do this go to the primary, tell it what interface to sync on, I recommend the LAN. Some people talk about needing a dedicated interface, and ya that would be nice, but not necessary in a home environment. Add the IP address of the backup Lan IP. Add the sync config to ip to the backup lan IP. No idea why you have to do this twice. And give it the remote system username/password. Same you would use to logon to the web interface. On the backup box enter only the sync peer. And with that you can see sync working or not in Status system logs. Your now ready for the next phase adding VIPs. To make a seemless fail over your going to need a WAN (if you care about incoming) and a LAN VIP. These are called CARP VIPs. I had HyperV issues, but solved them (enabled MAC address spoofing) and I also had issues on my USB ethernet adapter not working with CARP.

Once I had CARP up I wanted to do some testing to insure it was actually working. I found I had to make a few adjustments to my settings. All incoming NATs had to be moved from the WAN address to the WAN VIP. DHCP had to be modified to add the default route and DNS server to be the LAN VIP rather than the server IP address. The DHCP changes have to be made manually on both servers this does NOT replicate.

It’s worth noting that the way this works is a master/slave relationship. The master, or primary if you prefer is the dominant server and will always take over when it’s available. The slave just sits there waiting to take over. Fail over and fail back happen pretty quickly. Any changes to the slave server in the area of things like firewalls will be completely over ridden when the master comes back online.

Hardware testing

If your like me you have a number of older physical boxes in your pile doing little to nothing. Seemed like a great place to play with Pfsense. Again this BURNED A LOT of time!

I dug out an old Asus ASROCK media player I have. It’s based on a dual core atom 330 processor. I got lucky and this one is 64 bit. I decided to put Pfsense on a 8G USB stick. The media player only has one NIC so I used a USB ethernet I had laying around. I also wanted to play with WIFI but I ran into an issue that my Realtek RTL8188 but couldn’t get it going on the 64 bit version of Pfsense. The driver ignored it. Migrating from my VM to the physical box was super simple. You simply backup your old configuration making sure you choose backup all. On the new box do a vanilla install. Be sure and add any packages you want on the new box that you had on the old one. Then use the restore function. If the NICs are different it will simply reask which NICs are which. I had to manually redownload the Pfblocker/Snort rules but that would have been done on the schedule anyway …

Now that you have a functioning Pfsense box you may want to benchmark it. So to do this I popped one of my machines in front of Pfsense, attached to the router and ran Speed test to get a baseline of my internet. I then ran the same test behind Pfsense. My performance was awful. 24.85/7.33 MB/s (down/up) and behind my physical Pfsense box I only got 9.57/4.81. So I looked at the dashboard and saw that processor, and memory seemed to be fine. This left hard drive as the likely culprit. I ran:
geom disk list
To get a list of disks and then ran:
diskinfo -c da0
to benchmark the drive. I discovered the USB key that I was using, and how it was connected was resulting in REALLY bad performance. Like 2.5MB/s vs what ought be 40MB/s or so. So I moved it back to a hard drive. With this resolved the performance improved a bit. At first I’d given up on Atom, but eventually discovered it was traffic shaping causing the poor performance and simply disabled it, I’m not convinced it was doing anything anyway.

By the way I used DSL reports to benchmark my internet speeds but you could also use Source Forge’s too.

Going back to my VM I ran the same test on the VM which was configured as 2 virtual CPUs running on a i7 860, and 3G memory. This time the performance over my 25Mb/s DSL connection was much better and showed little to no slow down.

Performance testing

So now I got curious as to how hard this could be pushed, so I went back to my VM. I setup a web server on one machine, and a web browser on another. I used a Ramdrive to host the content Imdisk so the question of the hard drive being the bottle neck was removed. Using H2testw I was able to measure the Ramdrive as being capable of 389/293 MByte/s (write/read). So on with the test. Locally the content was served up at 166MB/s. Remotely, not through Pfsense this got 150MB/s. It’s worth noting that the second machine is a VM on the same box so the connection is a virtual 10Mb/s adapter. So with 150MB/s as the now bar I was curious to see how multi threaded the firewall is, using a VM allowed me to change the number of CPUs. With 2/4/6/8 VCPUs I got 104/106/120/118 MB/s. So as you can see it scaled relatively well right up to 6 VCPUs. What this tells you, is the firewall is very well multi threaded, able to take advantage of multi core processors!

In running some of this I found a few tools worth pointing out. First of all there is a tool you can install that will tell you your incoming speed test. It removes the router and anything downstream. It’s a way of telling basically your line speed in. From a pfsense command line you need to install the tool:
pkg install py27-speedtest-cli
and then you can run the test anytime by running:

Second there’s a network bandwidth tool call iperf that you can use to test speeds between computers without having other bottlenecks like hard drives etc in the way. iperf is can be downloadfor windows amongst others. To add ipferf to pfsense install it from the web based package manager. To use iperf you start iperf on the receiving end by running:
iperf -s
then run it on the other end:
iperf -c host -p port

You will get back a bandwidth between the two.

On Redhat to install iPerf:
yum install
yum install iperf

Selecting hardware

I saw a guy on a forum ask a simple question … what’s the best hardware to run Pfsense on? The smart ass answer that came back is the one you already have πŸ™‚ That said, its quite true. The ones I played with were for exactly that reason, I already had the box available.

A VM is a great choice and allows you the max flexibility in network configuration as well as resource changing (memory/processor). But I have to say I have had issues with VMs. I could not for the life of me get Pfsense clustering to work, the VIPs refused to come online externally, until … I finally read an article on Best practices for FreeBSD on Hyperv which directly addressed CARP and solved the problem (it was MAC address spoofing had to be enabled). And CPU utilization just seems bizarre to me. I have more experience with Vmware and the way they allocated VCPUs makes a whole lot more sense to me. I would see Pfsense showing the CPUs pretty busy but the physical CPUs still being inactive. Temperature on the VMs never showed on the dashboard of Pfsense.

I tried for a LONG time to get Pfsense to run an older dual core Pentium 4, P4D. I could get the older 32 bit version of Pfsense running, but the 32 bit version is end of life. And since there is no support for taking configurations backed up on the 64 bit version and restoring them on the 32 bit (I tried and it restored but had bizarre issues). The 64 bit would oddly install but just not boot. So this was out. Although, the performance on the P4D on the 32 bit version was quite adequate.

I had an old Xeon Dell, a poweredge. This box seemed like it would have all the horsepower. Interestingly enough, the performance on this box was not night and day better and certainly didn’t justify the cost of running this HUGE box for nothing.

I also had a quad core atom box and this ran fine as long as I had traffic shaping turned off (as discussed above) and dialed down the VPN requirements.

Going forward Pfsense (2.5 and above) have stated that a CPU having the AES instruction set is a requirement, so if your buying hardware be sure and look for that.


March 29, 2018 - Posted by | Uncategorized

No comments yet.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: