pfSense Firewall 2.8: Install & Config – Settings Walkthrough

pfSense Firewall Config: My Settings with Screenshots: pfSense Dashboard

Let’s pick up right where Part 1 left off: pfSense Firewall Appliance Unboxing. This isn’t a quick-start guide. It’s my logbook from weeks of fine-tuning pfSense. Weeks, not years, so follow along and let’s learn and improve our pfSense configs together. In this article, I share my pfSense setup: interfaces, firewall rules, pfBlockerNG, Suricata, the works. A pfSense guide based on my journey to find the best config that works for me.

It’s my first time using pfSense, but I’ve managed various firewalls on Linux servers over the years. By sharing my config, I hope to welcome corrections, suggestions, and to help readers who are just getting started with pfSense.

The main goal here that we configure a secure pfSense firewall setup that survives ISP hiccups while providing added visibility into what’s going in and out of our home lab, home office, or small business networks. You know, peace of mind, all while being interesting!

pfSense Hardware & Prep

pfSense hardware and prep.
Photo of my current home lab. A work in progress.

If you haven’t settled on a firewall appliance yet, check out my unboxing write-up first (Part 1): Intel N100 CPU, 82599ES 10G SFP+ NIC, and i226-V 2.5G ports give you plenty of headroom while keeping power under 15W at idle. Note that some links below point to Amazon, where I earn a small amount on qualifying purchases, while other links direct you to manufacturer or product pages and other related resources that I’ve found useful during my pfSense firewall setup.

Choosing pfSense hardware

There are a host of hardware options available. I’ve filtered some of the best pfSense hardware options, that you can currently find on Amazon, as well as eBay.

RAM is cheap, around $15 to $20; start with at least 4 GB if you intend to run Suricata and pfBlockerNG concurrently. Then drop in a 128 GB NVMe for $20 for fast storage.

In my case, I’m using a 256 GB TEAMGROUP MP33 that I purchased back in 2022. Full parts list and thermals are in the unboxing post: My $300 pfSense Firewall Appliance – Part 1: Unboxing.

10G Uplink Options: Cat6, Fiber or DAC?

pfSense hardware: Cat6, Fiber or DAC

For connecting the 10G SFP+ port from my pfSense box to my TP-Link SG2210XMP-M2 switch, I went with a pair of 10GTEK 10GBase-SR SFP+ LC Transceivers and a 7 inch OM4 Fiber LC to LC cable. My main ISP uses not one, but two devices for internet connection: their Fiber ONT device and a modem-router device. I managed to delete the router, and I’m now waiting on an ONT stick in order to direct-connect the fiber to my pfSense box.

Here’s a comparison of your options for connecting via SFP+:

  • Plain CAT 6a, plug and play 10GBase-T modules convenient, but dissipate up to 5 watts, so they run pretty hot. Keep the hop under 15 meters, or you’ll pay in heat as you get closer to 30 meters.
  • Passive DAC (Direct Attach Copper) twin-ax is the cheapest way to connect a 10 Gb link inside the rack (up to ~7 m). It’s essentially two SFP+ ends bonded by copper; no optics, <0.5 W, not much heat generated.
  • Fiber (LC multimode, 10 G SR optics) breezes past 30 m connections, laughs at EMI (Electromagnetic Interference) and lowest power at ~ 1 W. Two SR modules plus a short OM4 patch cable usually cost less than a pair of RJ-45 10GBase-T transceivers.
Type 10GBASE-T SFP+ (RJ-45) Passive DAC SFP+ Fiber SFP+ (SR)
Max Distance ≤ 30 m (Short RJ-45 runs) ≤ 7 m (Intra-rack) 300 m (Long or EMI-prone runs)
Power Draw 2 to 5 W < 0.5 W ~ 1 W
Heat Moderate (needs airflow) Minimal Low
Cost (pair) Moderate Lowest Moderate
EMI Immune? No No Yes
Recommended Model H!Fiber 10Gb Transceiver 10Gtek SFP+ DAC Twinax 10GTEK 10GBase-SR

 

Removing my ISP’s ONT (Optical Network Terminal)

ISP router put in its resting place.
Rest in peace, ISP router. An electricity leach @ ~20 watts.

As mentioned above, I was able to get rid of the ISP’s modem/router box and plug the RJ-45 cable from the ONT directly into my second SFP+ port on the pfSense firewall. I did this by spoofing the mac address of the ISP device and then cloning the PPPoE connection. The PPPoE config was not visible in the UI of the device, so I had to download the config using the UI’s backup feature and found everything needed in the exported text config file.

ISP ONT delete, coming soon.
Hopefully, the GPON stick works so I can unplug this ONT and save ~10 watts.

The ONT is already set to pass-through mode, so it’s solely there to terminate the fiber. PfSense is already handling connecting to my ISP. Mainly, now, it’s just a waste of electricity and an additional failure point. But first, I’ll need a GPON stick. I just ordered one on eBay for $20 (while writing this they cancelled my order and said due to shipping and taxes I have to pay $35).

Please check your specific ISP requirements, but here’s an comparison of GPON SFP modules specific to my setup for ONT delete (sometimes called an “ONT-stick”, “mini-ONT” or “PON-stick”):

Model Chipset Connector Notes
Sercomm FGS202 Lantiq PEB98036 SC/APC inside SFP shell Same vendor as my FG1000R; already built to talk GPON OLTs with Sercomm profile.
FS GPON-ONU-34-20BI Broadcom B+ class LC/UPC Lets you spoof/clone LOID/SN via CLI; widely documented.
Nokia G-010S-A / G-010S-P Broadcom SC/APC Works on many Huawei/Calix OLTs after the ISP whitelists the module’s serial number.
Ubiquiti UF-Instant Realtek LC/UPC User-friendly web UI, but some OLTs reject non-Broadcom sticks.

 

pfSense 2.8 Installation

pfSense Setup Wizard

I’m not going into great detail. Because the pfSense 2.8.0 (2.8.*) installation process is pretty simple. However, I will include a few tips and comments.

BIOS and booting checklist

These were my settings for my n100 (fan disabled) pfSense install. The N100 is overkill for most setups. But it’s cheap, runs cool and very well proven with lots of online documentation, and discussions specific to pfSense:

  • Secure Boot: disable it because it blocks the booting pfSense.
  • Restore power on AC Power Loss: Set to ‘Power On’ so that pfSense will automatically boot when power is restored after a power loss.
  • Fan profile: choose “Balanced” or “Off” for CPUs like the N100 which run really coolAlso see: N100 Fans Don’t Turn Off. If all else fails, you can unplug the fan.
  • Boot delay: Still in system BIOS, don’t remove the default 3-second pause! Keeping this allows the hardware a little extra breathing room to fully initialize before pfSense begins probing interfaces. If you remove the BIOS boot 3-second delay, NICs sometimes aren’t 100% ready, kernel sees up/down flapping events, pfSense triggers package/service restarts, and it results in slower problematic startups. I experienced this first hand, so sharing.
  • Reduce or remove pfSense boot delay: On the other hand, this IS safe! Use either the SystemAdvancedSystem Tunables or manually create /conf/loader.conf.local with: autoboot_delay="-1" to remove completely or autoboot_delay="1"  to reduce delay to 1 second.
  • With these settings, rebooting takes ~ 60 seconds, even with IDS/IPS packages installed.

Grab a clean image

  1. Head to Downloads ▸ pfSense CE and pull the latest amd64 ISO.
  2. Verify it before you touch a USB key:
    sha256sum pfSense-CE-*.iso
    

    Compare against the SHA-256 string on the download page; mismatches mean re-download.

Write the installer to a USB

I used balenaEtcher.

You can also use Linux CLI:

sudo dd if=pfSense-CE-*.iso of=/dev/sdX bs=1M status=progress && sync

Replace /dev/sdX with your flash-drive path.

On macOS use balenaEtcher or sudo diskutil unmountDisk /dev/diskN then dd.

Windows users: balenaEtcher or Rufus.

Boot and run the pfSense installer

  1. Insert the USB, hit your board’s boot menu, choose the USB device. (Walkthrough)
  2. At the pfSense splash, accept defaults → Install → keymap (your language)→ filesystem *ZFS**.
  3. Reboot when prompted; remove the stick.

Complete the first-boot wizard

pfSense Setup > General Information
I like to use Cloudflare or Quad9.

pfSense Setup > Time Server Information
I use time.cloudflare.com and time.google.com.

pfSense Setup > Configure WAN Interface
Use defaults for DHCP. Keep everything else default for now.

pfSense Setup > Configure LAN Interface
Set LAN IP address to your preference. Click next, then set password.

pfSense Setup > Reload configuration
Finally, click reload and then continue from there.

Now open https://192.168.1.1 (or the IP you assigned), accept the self-signed cert warning, then sign in. That’s it, pfSense 2.8.0 is not installed, let’s go!

Also read: 10 pfSense Setup Changes to Make Post Install.

pfSense System settings walkthrough

pfSense > System settings

Let’s begin from left-to-right in the navigation bar at the top of the pfSense UI. Starting with the ‘system‘ menu. The first drop-down on the pfSense navigation bar. This is where you tell the firewall who it is, how it keeps time, which DNS servers it trusts, and how you, and only you, get through the admin door.

A couple of minutes in General Setup and Advanced locks the GUI behind HTTPS on a quiet port, routes all look-ups through a filtered resolver, and enables the CPU’s AES instructions so every future VPN or TLS handshake runs at full speed. Many of these essential settings we already covered in the previous section.

Moving on, the same menu also houses the day-to-day plumbing: extra packages, user accounts, and the gateway group that lets the box fail over ISPs without dropping a beat. Configure these early and every setting that follows—DHCP scopes, IDS/IPS, even the dashboard graphs, inherits a clean, trusted baseline. Below is an overview of my settings.

pfSense > System > General Settings

General Setup

  • Hostname / domain: hostname.hydn.dev ties local services and to my personal namespace.
  • Timezone: America/St_Kitts keeps log time-stamps square with your location.
  • DNS servers: Quad9 primary/secondary 9.9.9.9 / 149.112.112.112. Quad9 DNS blocks malware, phishing, spyware, and botnets. You can also use Cloudflare’s DNS.
  • NTP pool: time.cloudflare.com followed by time.google.com.

Advanced (System → Advanced)

  • WebGUI hardening: GUI is HTTPS-only on non-standard port, autocomplete disabled and an alternate host list (myaccountname.cloudflareaccess.com) for Cloudflare Zero-Trust can front-end it while keeping WAN ports closed.
  • GUI certificate: Presented cert is GUI default a self-signed RSA created at install.
  • SSH access: Disabled but when enabled is also on non-standard Port, key-only auth. SSHGuard blocks a source after x bad logins for x hours (tweak to your preference).
  • Hardware tweaks: AES-NI crypto enabled, thermal set to Intel, and NAT reflection is pure-NAT.

SMTP notifications

System > Advanced > Notifications: The system is set up to send mail (notifications) using my Postmarkapp account on TLS with my unique token.

User Manager

  • admin (uid 0) is the built-in root with shell access, login disabled.
  • myusrname is the day-to-day admin account, member of admins but without a shell for extra safety.

Package Manager

My installed packages:

  • pfBlockerNG-devel: IP blocking and DNS geo and content filtering with DNSBL.
  • Suricata: IDS in IPS-inline mode on WANs, alert logs pruned after 14 days.
  • Cron: A package to apply and maintain custom and recommended system patches.
  • System_Patches: A package to apply and maintain custom and recommended system patches.
  • Watchdog: Monitors for stopped services and restarts them.

pfSense > System > Package Manager > Installed Packages

Routing

pfSense > Routing > Gateways

  • Gateways: Three dynamic gateways: WAN1_ISP_CW (fiber), WAN2_ISP_Cable (coax), and NORDVPN_VPNV4 (client).
  • Gateway group “Multi_ISP”: sets WAN1 Tier-1, WAN2 Tier-2 with trigger down/packet-loss/latency, giving automatic fail-over while avoiding flaps during brief jitter.
  • Default Gateway IPv4: points to the group; IPv6 disabled everywhere.

Network Interfaces config — Assignments, VLANs, and WAN links

pfSense > Interface Assignments

Before any firewall rules or packages can do their job, the box needs a solid interface blueprint. Mine carves the network into clear-cut zones, each with its own Layer-3 IP space: an admin LAN on 192.168.11.0/24, a Windows LAN on 192.168.4.0/24, a Homelab LAN on 192.168.2.0/24, and an IoT/guest VLAN on 192.168.3.0/24. That separation lets stateful rules decide, down to the byte, who can talk to whom.

Physical layout follows function

pfSense Firewall Appliance
Read more about this box: My $300 pfSense Firewall Appliance – Part 1: Unboxing

The 10G port ix1 carries both management (tag 1) and guest (tag 3) traffic to the 10G SFP+ port on my multigig switch, where eight 2.5 Gb ports fan out to my IoT hardware (with some unused for future expansion).

For internet, ix0 tags VLAN 20 for the fiber ISP’s PPPoE hand-off, while igc3 (ETH3) keeps a DHCP cable link as fail-over; pfSense lumps them into a Multi_ISP gateway group so latency or packet-loss flips routes automatically. A NordVPN tunnel shows up as ovpnc1, giving policy-based routing the same knobs as any WAN. This is handy for pushing only the IoT VLAN through a privacy exit without floating-rules.

From here, firewall policies, DHCP scopes, and IDS sensors slot into place:

Interface Assignments Physical port Type IPv4 / Mask Role
WAN1_FIBER (ix0 fiber) pppoe0 → ix0.20 PPPoE on VLAN 20 Dynamic Primary ISP (fiber)
WAN2_Coax igc3 DHCP Dynamic Backup ISP (cable)
VPN_NORD ovpnc1 OpenVPN client NordVPN for VLAN3
L0_ADM igc0 Static IPv4 192.168.11.1/24 Admin-only LAN
L1_WIN igc1 Static IPv4 192.168.4.1/24 Windows devices
L2_LAB igc2 Static IPv4 192.168.2.1/24 Home-lab devices
VLAN1 (ix1 fiber sw uplink) ix1.1 (tag 1) Static IPv4 192.168.1.1/24 Wired & Wi-Fi LAN
VLAN3 (ix1 fiber sw uplink) ix1.3 (tag 3) Static IPv4 192.168.3.1/24 Guest Wi-Fi / IoT devices

 

Why this layout works for me

  • Clear separation – each security zone (admin, lab, IoT/guest) has its own Layer-3 interface, so stateful rules can isolate or allow traffic precisely where I need.
  • 10 Gb trunkix1 carries both management VLAN 1 and guest VLAN 3 to my 10 GB switch, which has eight 2.5 GB LAN ports.
  • Dual-WAN resilience – fiber ISP (Tier 1) and cable ISP (Tier 2) are fed into a gateway group Multi_ISP that fails over on loss/latency; pfSense sets that group as the IPv4 default route.
  • Clean PPPoE – the FTTH provider requires VLAN 20 in order to replace their modem device; tagging happens on ix0.20, then PPPoE creates pppoe0.
  • VPN as an interface – having NordVPN on ovpnc1 lets me make policy-routing and NAT rules just like any other WAN, instead of having to use floating rules.

pfSense > Interfaces

pfSense > Routing > Gateways

pfSense > Routing > Gateway Groups

Firewall — Aliases, NAT, Rules

The Firewall menu is where the design you mapped out in Interfaces turns into concrete, enforceable policies. I started by building a list of aliases—IP, network and port groups. With names such as Ring_Cams or Web_TCP, a single edit later can ripple through dozens of rules without hunting for scattered addresses.

Because a Cloudflare Tunnel fronts the primary WAN for the hydn.dev website, Checkmk, the Unifi controller, the network switch, remote printing and other services, inbound NAT is almost nonexistent; the box handles only a pair of port-forwards on the backup WAN2, restricted to specific allowed ports and IPs.

pfSense > Firewall settings

Let’s go over some of the config.

Aliases – the Lego-bricks for firewall rules

pfSense > Firewall > Aliases

PfSense lets you build reusable address/port groups (“aliases”) so rules stay readable and easier to manage. My config holds several aliases spanning IPs, Ports, URLs, and networks:

Type Examples Purpose
Port/IPs Windows, Web browsing, Security/IoT bundles such as Ring, Unifi doorbell, cams, APs, controller. Bundle many TCP/UDP service ports.
Network / Host RFC1918 networks, DoT IPs/ports, Checkmk Reference entire subnets or key hosts without hard-coding individual IPs.
URL Table Pingdom Probes IPs, Cloudflare IPv4 ranges, pfBlockerNG auto-generated lists Pull external TXT/IP lists on a schedule (e.g. Pingdom probe list, threat feeds).

Adding and organizing Aliases pays dividends later when you need to make changes.

NAT (Network Address Translation)

As mentioned I’m making use of Cloudflare Tunnels via Zero trust. So my front facing ISP WAN1 has all incoming ports closed and firewall rules set to drop all unsolicited incoming traffic. Check/test your with routersecurity.org.

Port-forward snapshot

On WAN2, Two port forwarding rules expose Checkmk server which runs on a VM on Win 11 ThinkCentre-M75 box (192.168.4.109) to the alias cmk_hosts (access restricted to this IP list):

pfSense > NAT > Port Forward

Firewall Rules

IPv6 traffic is globally blocked on all interfaces silently to reduce logs/noise. pfBlockerNG rules sit at the top and my custom rules follow. As an example, here are a few screenshots of my rules. Suggestions welcomed:

pfSense > Rules > VLAN3 (guest) pfSense > Rules > WAN1 _Fiber pfSense > Rules > WAN2 _COAX

Firewall — pfBlockerNG IP, DNSBL Blocking

pfSense > pfBlockerNG > widget

pfBlockerNG is used to pull CINS Army, DShield, and Emerging-Threats intopfB_PRI1_v4.

Note: The default pfBlockerNG selected lists include a couple of deprecated and broken links, so feel free to use and improve on my list below:

Feed/URL Description Approx. unique IPs
CINS Army “CI Bad Guys” High-confidence attacker list built from a global network of honeypots; refreshed ~12-hourly. ≈ 15000
DShield Top Attackers
(7-day aggregate)
Rolling set of the most aggressive /24 subnets seen scanning the Internet in the last three days; FireHOL keeps seven days of history. ≈ 10000 (37 /24 nets)
Emerging Threats “Block IPs” Composite feed (Spamhaus DROP + DShield + Abuse.ch); updated twice daily for broad, catch-all blocking. ≈ 15 million

There is about 65% overlap between DShield and ET. Still, I kept both feeds because pfBlockerNG deduplicates IPs before they ever reach the firewall table, so the overlap costs no extra states, no extra memory, and no extra processing time. Whereas, what I’d lose by dropping one list is the 35% that doesn’t overlap. I’ll continue to compare the two and may replace if I find better. Recommendations are welcome.

pfBlockerNG Feeds

pfSense > pfBlockerNG > IP > IPv4

pfBlockerNG is set to automatically inject drop rules on WAN2, Windows LAN and the Guest/IoT VLAN interfaces, so that any packets matching the above feeds are dropped even before the default pfSense firewall rules run. I tried my best to focus on feeds that are well-respected, actively updated, and have low false-positives. For

pfSense > pfBlockerNG > IP > IPv4 > AbuseIPDB

I’m using AbuseIPDB feed in pfB_AbuseIPdb_v4 on a 12-hour refresh. Also consider adding FireHOL_L2. However, it can be very noisy to logs on LAN interfaces.

pfBlockerNG DNSBL

For DNSBL, I’m currently not using GeoIP. I did briefly, but I think it’s overkill and prone to false positives depending on the countries blocked. If you do use it, I wouldn’t recommend mass blocking of countries. It’s easy to get carried away! I’ve seen admins just 1 or 2 major countries they are 100% sure will have no need to reach their network. Even then, maybe just block inbound, or outbound, not both. It really varies depending on each network. For me, I decided to disable GeoIP DNSBL.

That said, I’m using Steven Black’s list — consolidating and extending hosts files from several well-curated sources. Which has been very effective while also super-simple to allow any sites I need to visit:

pfSense > pfBlockerNG > DNSBL blocking ads

On networks with higher risk, such as those used by kids or transient users, you might also consider adding PhishingArmy which is a compilation of PhishTank, OpenPhish, Cert.pl, PhishFindR, Urlscan.io and Phishunt.io reports:

pfSense > pfBlockerNG > DNSBL > Phishing Army

Services — DNS Resolver, DHCP and NTP

pfSense > Services > DHCP Server > VLAN3

The Services menu is where the box acts like the nervous system of the network: handing out IP leases, resolving names, and keeping everything in sync. It’s here that we lean on three core daemons:

  • DNS Resolver (Unbound): for encrypted, policy-aware name look-ups.

  • DHCP Server (kea-dhcp4): to parcel out addresses and gateways.

  • NTP (ntpd): so logs and certificates all agree on the same time­line.

The goal is to keep each one as simple as possible while still gaining the speed of local caching, the convenience of per-VLAN pools, and the reliability of good time.

DNS Resolver (Unbound)

Unbound is running and bound to all interfaces for both listening and outgoing queries. You only need two DNS server entries (a pair), add a third DNS provider if worried about DNS outages, which are extremely rare for both Cloudflare and Quad9. Cloudflare offers lower latency than Quad9, while Quad9 offers better malware blocking and privacy.

pfSense > General Settings > DNS Server Settings

Also, I enabled forward TLS upstream, to my preferred DoT endpoints so that all queries are TLS encrypted beyond pfSense in Services > DNS Resolver > General Settings:

pfSense > Services > DNS Resolver > General Settings

Added dedicated “DoT” (DNS over TLS) allow rule (drop all other DNS traffic):

pfSense > Firewall > Rules > DoT (DNS over TLS)

The result of these changes seen in the below screenshot when visiting the Cloudflare DNS debug/test page — https://one.one.one.one/help/:

Cloudflare connection information test page.

Note, you must also set your DNS IPs AND hostnames in System > General Setup:

pfSense > DNS Server Settings
Find the hostname you need you use for Cloudflare or Quad9.

DHCP Server (kea-dhcp4)

Kea DHCP4 manages DHCP for the following pfSense interfaces:

Interface DHCP Pool Notes
Admin (LAN 0) 192.168.11.100 – 192.168.11.150 Management devices
Windows (LAN 1) 192.168.4.100 – 192.168.4.150 Desktops / VMs
Home Lab (LAN 2) 192.168.2.150 – 192.168.2.200 Home-lab VLAN-aware (ex. Unifi Controller)
VLAN 1 (Trusted LAN + Wi-Fi) 192.168.1.100 – 192.168.1.200 10 Gb back-bone (ix1)
VLAN 3 (Guest Wi-FI SSID/IoT devices) 192.168.3.20 – 192.168.3.200 Guest Wi-Fi & cameras (ix1)

 

My NTP settings

pfSense > Services > NTP > Settings

To ensure consistent timekeeping across, I’ve enabled pfSense’s built-in NTP server. It syncs against two trusted public time sources: time.cloudflare.com and time.google.com. Both known for their reliability and low jitter. Cloudflare is set as preferred.

Services — Suricata

pfSense > Suricata settings menu

With the core firewall rules and PFBlockerNG in place, it’s time to add Suricata as a second firewall security layer IDS/IPS. Another option is to SKIP adding PGBlockerNG if you prefer the IDS analytics of Suricata. Suricata also has IP reputation blocking as well as additional feeds that you can enable.

For Suricate, I skipped WAN1_FIBER where firewall rules blocks all incoming traffic because all ports are set to closed, and instead focused inline IPS on WAN2_Coax where a few ports are open.

I have Suricata also enabled on VLAN3 (Guest/IoT) and L1_WIN (for Windows devices) so I can monitor (IDS) traffic. Traffic now flows through three security layers—pfBlockerNG first, Suricata next, and finally, my pfSense firewall rules:

Packet In
     ↓
pfBlockerNG
• IP & GeoIP feeds/tables
• DNSBL filters (DNS query level, not packet level)
     ↓
Suricata Inline
• Signature matching (ETOpen, Snort GPLv2 rules)
• Automatic SID management (drops, disabled rules)
     ↓
pfSense Firewall Rules
• Drop all IPv6 traffic
• Interface Pass / Drop / Reject rules
     ↓
IPv4 deny• Drop all remaining IPv4 packets.

 

Suricata — Global Settings & Rule Downloads

pfSense > Suricata > Global Settings

In the Suricata Global Settings page, you’ll see a handful of rule categories ready to download. I’ve opted to enable the ETOpen Emerging Threats rules. This gives a solid, community-maintained baseline without the complexity or cost of ETPro or paid Snort feeds.

Just below it, I’ve also enabled the Snort GPLv2 Community ruleset (the Talos-certified subset), which rounds out coverage for the most common threat signatures. To keep the interface clean, the Hide deprecated rules categories option is checked, so you’re not distracted by legacy rule groups you’ll never use.

Finally, the update interval is set to “1 DAY” with a randomized start minute. This ensures you get fresh rules every 24 hours without hammering the download servers.

 Suricata Enabled Interfaces

pfSense > Suricata Interfaces

In the Suricata Interfaces Settings Overview, you can see three Suricata instances that use IDS on: WAN2_Coax (igc3), VLAN3 (ix1.3) and L1_WIN (igc1). All configured for HS (High-speed) pattern matching (more efficient CPU performance). WAN2 is also running IPS (intrusion prevention system) Inline IPS mode, so threats are automatically blocked, while VLAN3 and L1_WIN remain in alert-only mode with blocking disabled until I’ve had more time to understand their traffic profiles better in the coming weeks. I’ve been learning so much, patience is key!

Update: After doing some more research, the best practice is to prioritize IDS/IPS on your LAN interfaces and not the WAN interface(s). The reason is that monitoring LAN gives us better visibility into what’s actually happening inside our network, including traffic going out to the internet.

Monitoring the WAN interface generally leads to plenty of false positives because you’re seeing everything hitting your firewall, even the stuff that would be blocked by the default pfSense firewall. You should consider monitoring WAN only if, as in my case (WAN2), you have some open ports exposed to the internet that you cannot — like with most things — 100% guarantee the security of the systems behind them. In this case, it helps detect potential breaches.

In general, focusing Suricata IDS/IPS on LAN interfaces gives us better insights into internal devices and outbound traffic, which is more critical for identifying real threats.

Suricate Per-Interface Settings (WAN2_COAX)

pfSense > Suricata > Interface settings

In the WAN2_COAX Suricata interface settings, I’ve enabled Suricata inspection but otherwise left most extras turned off to keep resource use and log noise to a minimum. HTTP logging remains on using the regular file format, in append mode with extended HTTP info. This is so that I can see requests without generating massive dumps.

Down in Alert & Block Settings, the “Block Offenders” box is checked. Any host that trips a signature will be dropped immediately.

pfSense > Suricata > Interface settings > Performance

When running Suricata in inline IPS mode, it’s recommended to set the Run Mode to Workers as it allows Suricata to run with multiple dedicated worker threads that process packets in parallel and efficiently. This mode uses zero-copy packet handling, which reduces CPU overhead and latency by not copying packets between kernel and user space.

It also allows for proper CPU affinity, where each worker thread can be pinned to a separate CPU core, for maximum performance and throughput for inline packet inspection and dropping. This is critical for inline IPS as it must process and potentially drop packets in real time without introducing bottlenecks or packet loss. So, setting the Run Mode to Workers ensures Suricata can perform well and be reliable when blocking traffic inline. Source: docs.suricata.io, /r/pfSense/ and forums I’ve been reading.

Suricata Rule Categories

pfSense > Suricata > Interface settings > Categories

In the Categories tab, Resolve Flowbits is enabled (I believe this is default). Enabled are Talos-certified Snort GPLv2 Community Rules up top (checked for insight into common exploits). Below that, you see three columns of rule sets: the Default Rules, ET Open Emerging-Threats rules and Snort rules. The latter, I didn’t enable.

Suricata SID Management

pfSense > Suricata > SID Management

In the SID Management section, allows the system to enable, disable, or drop signatures based on predefined lists, avoiding the need to manually adjust rules after every update.

My configuration includes a list called WAN-Disabled that filters out noisy or redundant signatures on the WAN2 interface. Another list is Drops, this contains high-confidence signatures that should immediately trigger packet drops. WAN-Enabled is blank, have not had the need to use that yet. For internal networks like VLAN3 and L1_WIN, I’m using a separate LAN-Disabled list to hide the flood of low-risk alerts from logs during this learning phase as I observe traffic behavior.

Drop and reject actions are not configured on these LAN interfaces, since they are still in alert-only mode while I monitor traffic. I will continue to update this blog post as I keep making changes, learn more and have more to share.

Why Suricata (or Snort) Matters!

Running Suricata inline on my fail-over WAN2 catches common bad traffic in the act by actively inspecting and blocking malicious packets before they hit my internal network. This inline IPS deployment allows Suricata to inspect network traffic in real time, using its multithreaded architecture to handle high volumes without becoming a bottleneck.

On my VLAN3 (IoT devices and guest Wi-Fi) I run Suricata in alert-only IDS mode, which gives me visibility into network activity and potential threats without disrupting devices that may be sensitive to blocking actions. This staged approach allows me to tune and manage Suricata’s Signature IDs (SIDs) to filter out false positives and make sure legitimate traffic isn’t blocked. Of course, VLAN3 as mentioned earlier, is isolated—blocked from accessing any of the other LANs (private networks).

Once I’m confident the ruleset is properly filtered, I can enable full blocking in inline IPS mode and Suricata will automatically drop or reject malicious traffic without blocking valid traffic.

Suricata AND Snort, both being open source, having extensive protocol parsing and an active community, are flexible and powerful tools for network security, providing visibility and control over evolving threats.

Important notes about pfSense +Suricata + pfBlockerNG

Suricata on WAN interfaces duplicates pfSense’s “deny-all-unsolicited” policy, so enabling Suricata on WAN interfaces mostly burns CPU by parsing packets that will be dropped anyway. See added details on how and when to run Suricata IDS/IPS on WAN, in the discussion section at the end of this article.

pfBlockerNG on WAN interfaces drops traffic before state creation based on feeds, reputation, and GeoIP, something the default rule-set does not do. That saves resources, shrinks logs, and reduces the chance a future port-forward or mis-rule accidentally exposes you to a known bad host.

VPN settings — OpenVPN

pfSense > VPN > OpenVPN > Clients

OpenVPN client (NordVPN)

pfSense > OpenVPN > Clients > Edit (NordVPN)

My only VPN entry is a site-to-Internet client that dials NordVPN. It connects to the Multi_ISP gateway, meaning when even WAN1 is down or experiencing packet loss, it will automatically reconnect to NordVPN using WAN2.

  • Interface & transport It rides the Multi_ISP gateway group over UDP in a TUN device, so pfSense can fail over from fiber to cable without dropping the tunnel.
  • TLS profile The client runs in p2p-tls mode with its CA/cert pair and full TLS-key-based server verification (remote-cert-tls server).
  • Keep-alivekeepalive 10 60 means pfSense sends a ping every ten seconds and restarts the session if nothing returns within a minute.
  • Route handlingroute-no-exec yes blocks OpenVPN from touching the system routing table; instead, it steers traffic with policy-routing firewall rules, keeping default WAN traffic on your faster ISP.

Status menu

pfSense > Status > Monitoring

Having finished every menu that actually stores settings, the Status menu is where you simply view and monitor the firewall. Aside from a handful of log-rotation options and graph layouts, these pages contain mostly read-only information that lets you confirm if the tweaks you just made are working or identify any trouble.

Status menu cheat sheet

pfSense Status menu What you’ll look for Typical use-case
Dashboard Widgets: gateways, services, traffic, alerts Quick “all-green?” glance
Gateways dpinger latency / loss icons Confirm or debug WAN fail-over
Interfaces Link speed, errors, IP/MAC Spot a NIC that dropped to 100 Mb/s
Monitoring RRD graphs: bandwidth, RTT, states Compare week-long trends to an outage
Traffic Graph 1-second live bps per interface Monitor interface traffic in real-time
Services Daemon up/down toggles Restart Unbound without SSH
System Logs Tail by tab: firewall, DHCP, etc. Watch drops while testing a rule
DNS Resolver Cache hits, forwarder status Verify DoT is healthy
NTP Peer offset & jitter Ensure time sync for VPN/IPsec
OpenVPN Client/server byte counters Confirm NordVPN tunnel is up
IPsec Phase-1/2 health Check site-to-site tunnels (if used)
Queues Traffic-shaper stats See which class is hitting its cap
Captive Portal Active sessions Audit guest logins (if portal used)
CARP (failover) VIP state: master/backup Verify HA pair roles
DHCP Leases IP ↔ MAC ↔ hostname list Find what IP a device pulled
DHCPv6 Leases IPv6 lease table Same idea for v6 (if enabled)
UPnP & NAT-PMP Current port mappings Review or clear auto-opened ports

 

Status > Traffic Graph

pfSense > Status > Traffic Graph

A one-minute, per-interface chart. Play around with it. Great to monitor real-time traffic on your interfaces.

Status > System Logs > Firewall > Summary View

pfSense > Status > Syatem Logs > Firewall > Summary View

pfSense crunches the last 10,000 log entries into pie charts. The first shows the split between blocks, passes and rejects; the second breaks those actions down by interface. If I suddenly find 90% of blocks coming from WAN2 COAX, it’s a quick hint that the cable link is under scanning fire or a rule is mis-matching. Below this screenshot, it also breaks down events by protocols, IPs, and ports.

Status > Monitoring

pfSense > Status > Monitoring (ISP failover)

RRD-backed line, bar, or area graphs for bandwidth, gateway quality, CPU load, and more. Tabs across the top (“WAN1-RxTx”, “VLAN-Guest”, “NordVPN-Uptime”) let you save custom views for instant access when you return. Pick Quality on the left axis to graph packet-loss and latency, or choose Traffic to watch seven-day throughput trends. Great for correlating a user’s “it was slow Tuesday night” report with an actual spike.

pfSense Diagnostics menu

pfSense > Diagnostics > Packet Capture

The Diagnostics menu is your on-demand toolbox for low-level troubleshooting: everything from ARP tables to live pf state viewers, inline shell and file editors, packet captures, and quick network probes. Most entries simply scan the running system, while some more advanced options you can interact with the system as root, so use them carefully!

A couple of settings do persist, like forcing Syslog into reverse order, or grabbing backups preferences under Backup & Restore, but otherwise these pages let you verify runtime health, debug issues without SSH, and perform emergency tasks without rebooting.

Diagnostics menu cheat sheet

Below is a reference to the Diagnostics menu options, what each one does, and a few notes to keep in mind while using them:

pfSense Diagnostics menu What it’s for / does Notes / gotchas
ARP Table Show MAC ↔ IP neighbors on IPv4 networks Clears on reboot; useful for spotting rogue hosts
Authentication Test LDAP, RADIUS or local-user login Great sanity-check
Backup & Restore Download / upload config.xml and RRD data Safest place to grab a manual backup
Command Prompt Run shell or PHP commands in browser Executes using root user
DNS Lookup GUI wrapper for dig Perfect for verifying DoT / forwarder changes
Edit File Inline editor for any file on disk Put custom scripts in /conf to survive upgrades
Factory Defaults Erase config and reboot to stock state Nuke button—always back up first
Halt System Graceful shutdown Unmounts ZFS cleanly
Limiter Info Display ALTQ/HFSC limiters Empty when no traffic-shaper is configured
NDP Table IPv6 neighbor cache (ARP for IPv6) Empty if IPv6 is disabled or blocked
Packet Capture Browser front-end for tcpdump Stores capture in RAM until you download
pfInfo Quick summary of loaded pf rules & counters Great “is this rule matching?” sanity check
pfTop Real-time state viewer (top-like) Filter by interface, rule number, address, etc.
Ping ICMP reachability test Choose source-interface to test Multi-WAN paths
Reboot Warm restart of firewall Graceful—waits for services
Routes Show routing table Validate policy-routing or static routes
S.M.A.R.T. Status Drive health (smartctl) Visible only if smartmontools is installed
Sockets List open TCP/UDP sockets (sockstat) Filter by PID when hunting suspicious listeners
States Live list of all pf states Search by IP to debug NAT / asymmetric flows
States Summary Counts of states per rule / interface Quick view of which rule is hottest
System Activity CPU / RAM viewer (top -SHaz) Toggle threads to spot runaway PHP workers
Tables View / flush individual pf tables Essential for pfBlockerNG testing
Test Port TCP connect test to remote host:port Great for quick “is this service reachable?” checks
Traceroute Hop-by-hop path discovery Source-interface option mirrors Ping/Test Port

 

Bringing it all together with the Dashboard!

pfSense > Dashboard

Now that everything has been configured, the last step is to arrange the Dashboard so a single glance answers the daily “is it healthy?” question. The screenshot above shows my layout, stacked left-to-right, top-to-bottom:

  • Gateways sits at the very top-left, so WAN latency or a fail-over event jumps out immediately.
  • Just below, Services Status turns red the moment Unbound, Suricata, pfBlockerNG, or OpenVPN stumbles.
  • System Information I unchecked some options and kept version, uptime, DNS servers, temperature, system load average, CPU, and memory usage.
  • Below that is Disks. It’s a lot more space than needed, but it was an NVMe I had sitting around since 2022. You can easily run pfSense for years on just 8 GB — 16 GB USB stick! These 128 GB NVMe’s, however, are cheap and fast!
  • The center column starts with the rolling Firewall Logs, followed by Suricata Alerts and the pfBlockerNG widget—three panes that surface security events without diving into log files.
  • Under those are Interfaces status, Interface Statistics and OpenVPN Client Interface Statistics (have to scroll).
  • Lastly, the right column is all traffic: four live Traffic Graph widgets (Guest VLAN, VPN tunnel, Fiber WAN, Cable WAN) refresh every second, so bandwidth spikes are obvious.

That order matches how I triage problems: WAN up? → services up? → any blocks or alerts? → bandwidth normal? With the dashboard tuned this way, you land on pfSense, skim, and move on—no extra clicks needed.

Conclusion

With that, your pfSense box is no longer a blank slate but a finely tuned gateway: hardened at the edges, segmented into clear security zones, armed with curated threat feeds, and topped off with real-time visibility and off-site backups.

What we’ve built here is a platform we can use to learn our network traffic and, over time, improve performance, reliability, and security. A network you can continue to refine as your needs change or new packages emerge.

Most recent home lab photo - June 2025
My 12u homelab rack as of June 2025

In this article, I tried to share tweaks, tips, and pitfalls from my own first few weeks with pfSense.

Next, I will be trying OPNsense, which is a fork of pfSense. I started with pfSense because something about the UI felt more familiar as I did my original research  However, as a Linux sysadmin I generally prefer to be using Linux based systems.

So for now, here’s to stable ISPs, encrypted tunnels, and many trouble-free hours behind a pfSense firewall that we will continue to understand increasingly with time.

Changelog

List of recent updates and changes to this article (added to the comments section below, unless noted otherwise).

— June 13th 2025: added “Diagnostics > Packet Capture”.
— June 16th 2025: added “Keeping Suricata lean on a lightly used secondary WAN”.
— June 18th 2025: added a new pfSense package called Status Traffic Totals.

Tags: , , , , ,

Comments from Our Members

  1. This article is a work in progress and will continue to receive ongoing updates and improvements. It’s essentially a collection of notes being assembled. I hope it’s useful to those interested in getting the most out of pfSense.

    pfSense has been pure joy learning and configuring for the for past 2 months. It’s protecting all my Linux stuff, and FreeBSD is a close neighbor to Linux.

    I plan on comparing OPNsense next. Stay tuned!


    Update: June 13th 2025

    Diagnostics > Packet Capture

    I kept running into a problem where the NordVPN app on my phone refused to connect whenever I was on VLAN 1, the main Wi-Fi SSID/network. Auto-connect spun forever, and a manual tap on Connect did the same.

    Rather than guess which rule was guilty or missing, I turned to Diagnostics > Packet Capture in pfSense.

    1 — Set up a focused capture

    Set the following:

    • Interface: VLAN 1’s parent (ix1.1 in my case)
    • Host IP: 192.168.1.105 (my iPhone’s IP address)
    • Click Start and immediately attempted to connect to NordVPN on my phone.

    2 — Stop after 5-10 seconds
    That short window is enough to grab the initial handshake. Hit Stop and view or download the capture.

    3 — Spot the blocked flow
    Opening the file in Wireshark or in this case just scrolling through the plain-text dump showed repeats like:

    192.168.1.105 → xx.xx.xx.xx  UDP 51820
    192.168.1.105 → xxx.xxx.xxx.xxx UDP 51820
    

    UDP 51820 is NordLynx/WireGuard’s default port. Every packet was leaving, none were returning. A clear sign the firewall was dropping them.

    4 — Create an allow rule
    On VLAN 1 I added one outbound pass rule:

    image

    Action:  Pass
    Protocol:  UDP
    Source:   VLAN1
    Destination port:  51820
    

    The moment the rule went live, NordVPN connected instantly.

    Packet Capture is often treated as a heavy-weight troubleshooting tool, but it’s perfect for quick wins like this: isolate one device, capture a short burst, and let the traffic itself tell you which port or host is being blocked.

    Update: June 15th 2025

    Keeping Suricata lean on a lightly-used secondary WAN

    When you bind Suricata to a WAN that only has one or two forwarded ports, loading the full rule corpus is overkill. All unsolicited traffic is already dropped by pfSense’s default WAN policy (and pfBlockerNG also does a sweep at the IP layer), so Suricata’s job is simply to watch the flows you intentionally allow.

    That means you enable only the categories that can realistically match those ports, and nothing else.

    Here’s what that looks like on my backup interface (WAN2):

    The ticked boxes in the screenshot boil down to two small groups:

    • Core decoder / app-layer helpersapp-layer-events, decoder-events, http-events, http2-events, and stream-events. These Suricata needs to parse HTTP/S traffic cleanly.
    • Targeted ET-Open intel
      emerging-botcc.portgrouped, emerging-botcc, emerging-current_events,
      emerging-exploit, emerging-exploit_kit, emerging-info, emerging-ja3,
      emerging-malware, emerging-misc, emerging-threatview_CS_c2,
      emerging-web_server, and emerging-web_specific_apps.

    Everything else—mail, VoIP, SCADA, games, shell-code heuristics, and the heavier protocol families, stays unchecked.

    The result is a ruleset that compiles in seconds, uses a fraction of the RAM, and only fires when something interesting reaches the ports I’ve purposefully exposed (but restricted by alias list of IPs).

    That’s this keeps the fail-over WAN monitoring useful without drowning in alerts or wasting CPU by overlapping with pfSense default blocks.

    Update: June 18th 2025

    I added a new pfSense package called Status Traffic Totals:



Top ↑