PFsense DMZ setup for a home web server

It’s been a long time coming in getting the other sites consolidated into one server. I’ve been holding off until one of the server contracts was coming up for renewal which is now right around the corner.

Intro

The overall idea in getting a home web server setup is pretty straight forward:

  • Setup a Linux server and install LAMP stack
  • Create a DMZ network through pfSense
  • Move the server over to the DMZ network
  • Make a copy of the current WordPress server and move it over to the new one
  • Setup the DNS changes on the registar

There were a few sites that provided some pretty good insights in how to get the basic interface and DMZ firewall rules in place:

CEOS3C Ethical Hacking, Linux & Open Source. (2018, March 19). How to create a DMZ with pfSense 2.4.2. CEOS3C. https://www.ceos3c.com/pfsense/how-to-create-a-dmz-with-pfsense-2-4-2/

Rubicon Communications LLC. (2020). Basic Firewall Configuration Example. PfSense Documentation. https://pfsense-docs.readthedocs.io/en/latest/config/example-basic-configuration.html

Owokade, A. (2016, March 22). pfSense Series: Firewall Rules. Intense School. http://resources.intenseschool.com/pfsense-series-firewall-rules/

This is assuming you already have a basic pfSense setup on it’s own device or VM instance with the right amount of interfaces, in this case 3 interface: WAN, LAN, and one for the DMZ. Here’s a basic guide you can use as a reference in getting pfSense installed and running: https://docs.netgate.com/pfsense/en/latest/install/installing-pfsense.html

Main configuration setup

Thankfully there wasn’t too much to do while getting the interfaces up and ready for the DMZ network. Physically I ran a new line from a free port on the server on up to the router:

Router with the new cabling for the DMZ network

When initially connecting end points together you will still need to set the interfaces as up before traffic can start to be passed. Before that you will need to go ahead and configure a new virtual switch on the esxi side which will be dedicated to just that one interface and network. This degree of control will be beneficial in keeping traffic from the various networks to within their designated zones. From vSphere go to the Networking sidebar > “Add new standard virtual switch” from the configuration menu go through to naming, MTU size (I went with jumboframe / 9,000 bytes), what physical interface to connect to it for uplink, and the rest of the options should be fine as default. After it has been completed you should have a new switch available under the Networking section that should look something like this:

New DMZ virtual switch

The network topology shows my server Mercury connected, I’ll cover steps needed to get this done later. For now it’s time to set the interface up on pfSense, this is also to go ahead and think about the little things like IP address range and pool. Since I knew I wouldn’t have much out on this isolated network I went with a /30 CIDR submask giving me only 4 address to assign out and went with a generic Class C IP address.

Login onto the dashboard, as mentioned by Dan in CEOS3C:

  • Login to your pfSense dashboard and navigate to Interfaces -> Assignments … Click on +Add to add our DMZ interface.

Since I opted to go with manually assigning IP addresses for anything on the network I went ahead and skipped over setting up DCHP service for the DMZ network. I did make sure to set the MTU size for the interface to 9k under the interface’s General Configuration.

Fine tuning firewall rules

Dan continues in step 3 of his guide: Under Firewall -> Rules -> DMZ click on Add (Arrow Up) to create a new rule.

This is where I started to go through and setup my own rules since in Dan is only covering DNS and ICMP rules. Before going through that I did find the info from Adeolu in his Intense School article to be pretty useful here such as making use of aliases when getting rules put together. I also agree with his take on his DMZ security policy to be pretty close to what I am looking for in my own setup:

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 A and B in the DMZ to the LAN network.
Allow DNS, HTTP, and HTTPS from the DMZ to the Internet.
Deny everything else!

Let’s get those aliases put together, check out this example used by Dan:

Dan’s example alias setup, you can find this under Firewall > Aliases > Then setup for both the IP & Ports sections

Here’s a good boilerplate for firewall rules in a environment with three networks and one of them the DMZ:

pfSense firewall rules starts with the default “deny all unless otherwise defined”. The rules are ran top to bottom and stops once a relevant rule is hit. For example DNS queries coming from the DMZ network is only going to be allowed outbound since the first rule defines traffic on port 53 is only allowed anywhere but on the LAN or DMZ networks. Here’s a closer look at that rule:

The key point is that “Invert match” checked box with will mean anywhere but the specified input. In this case its anywhere but the defined “LAN_IOT_Net” which covers both my IP address spaces in LAN and IOT networks. This also means denying DNS queries to the main DNS server, just got to remember to set your server’s DNS to external servers such as those from Cloudflare (1.1.1.1) or Google (8.8.8.8) for example.

  • Next rule allows for ICMP traffic only going to the Mercury server which is useful for me when troubleshooting.
  • Next up is allowing SSH traffic only from the LAN network which is pretty important since most of my administrative interactions for the server takes place over port 22.
  • The next two rules is “just in case” rule in denying any undefined traffic from the DMZ from reaching either of the other two networks. pfSense reported there was some activity that was blocked as you can see in the rules screenshot where 6 KiB of data was logged as being blocked, likely when I was going through testing from the web server using nmap to hit specific ports on hosts in the other networks.
  • Next rule is allowing inbound traffic on either port 80 or 443 to be allowed for the web server.
  • Final rule is allowing any traffic on the the DMZ to anywhere but the LAN or IOT networks to be allowed. This was necessary since before the rule was established the server was not able to pull any updates.

With all that out of the way the DMZ network has been setup and ready for use. I’ll go through the general workflow I used in setting up the web server and securing it as well as migrating WordPress over to it in a later post.