Setting up Zero Trust on pfSense

The Zero Trust Model is the most secure way to control egress. For clarity, here are the elements of our zero trust model:

  • Operating in whitelist mode (block all, allow some)
  • Feature enabled (with appropriate plan): Don’t Talk To Strangers
  • Default LAN Allow All rule removed , or at least disabled

This approach ensures that no device can make an outbound connection of any kind, no matter the protocol, destination, or port. If you try to make a connection to say to one of Google’s IPs on TCP port 443, here’s what you’ll get:

curl … this connection fails with:
curl: (7) Failed to connect to port 443: Connection refused
However, compare with this one:
curl … this connection succeeds!
Another example:
PING ( 56 data bytes92 bytes from ( Destination Host Unreachable
And yet this one…
$ ping ( 56 data bytes64 bytes from icmp_seq=0 ttl=59 time=16.982 ms

The difference is that when a successful (non-blocked) DNS query is answered, a temporary outbound firewall hole is opened for the period of the TTL.

Assuming you are starting from a default installation of mostly-default pfSense settings, here are your steps:

  1. Contact support to change your plan to allow for DTTS (Don’t Talk To Strangers) feature set
  2. Log into your dashboard -> Advanced -> Enable DTTS as shown here:
  3. Create (and enable) a LAN Firewall Rule to allow LAN DNS queries
  4. Create (and enable) a LAN Firewall Rule to allow LAN port 80 access for the block page to function
  5. Turn off your pfSense default LAN Allow All rule (shown here as disabled as they are unbolded) or, alternatively check “Automatically manage DTTS rules in firewall” in Services -> adam:ONE
  6. Create any required Firewall Rules

Most environments that choose the Zero Trust Model end up with at least a few “misbehaving” apps that require special permission to make Internet-bound connections without preceding DNS queries. In cases like this, Enablers are needed as outlined here: Enablers on pfSense

All attempted (but dropped) dns-less traffic can also be observed following the troubleshooting article here: Troubleshooting services behind DTTS® on pfSense

To view real-time dynamic rules created, run this at the command-line:
pfctl -s rules -a "adamnet/*"
To view all rules for the IP4 address of
pfctl -s rules -a "adamnet/4/10/0/1/48"

A few comments i like to add from my experience:

  1. If you use DTTS on pfsense, don’t use the enablers on the dashboard, as they will lock up the pfsense, rather use the rules in the firewall.
  2. Disable IPv6 or IPv4 prior to enabling DTTS, as DTTS doesn’t support Dual Stack. (this can cause disruptions with the internet, if both are enabled with DTTS)

Where exactly do you disable ipv6?

All you need to do is ensure that no IPv6 address (either via tracked interface or static) is on the LAN interface and IPv6 will be effectively disabled.

For anyone concerned that we are recommending to disable IPv6, the issue is primarily with dual-stack. If a client is able to run IPv6-only on their internal network by using NAT64 then instead we would recommend disabling IPv4 on the LAN interface.

Interesting post. In order for this to be a ZTM model, it needs AAA (even in egress). Is this being done somewhere else in your setup?

I would break it down like this:

adam:ONE runs on the gateway, agent-free on endpoint, so authentication is limited to MAC address identity, not the user per se, but AAA still applies in the following ways:

Authentication - and all policies are applied based on MAC address.

Authorization - this comes by way of the adam:ONE policy which is customizable to individual or group requirements.

Accounting - considering adam:ONE does not do any packet inspection, it is source/destination pairs that includes the DNS query and responses that are logged at log-level 4 and can be integrated into any SIEM.

As with a lot of modern marketing/packaging words and labels, zero trust is not 100% defined but certainly is aligned with these concepts as well as least privilege. This approach shows its strength in IoT devices, appliances, networking equipment that mostly have no “user”, and as we now know with Ripple20, often not designed for any upgrades/patches either, so containing their communication at egress is key.