Table of Contents
PFSense - Install pfSense - DNS Configuration
DNS Resolver
Unbound will be configured as the DNS Resolver.
NOTE: Unbound uses the authoritative root name servers, which is considered better than being resolved by a non authoritative service such as Google, Cloudflare or OpenDNS.
Navigate to Services → DNS Resolver → General Settings.
- Enable: Checked. This makes Unbound the DNS Resolver.
- Listen Port: 53.
- Enable SSL/TLS Service: Not Checked.
- SSL/TLS Certificate: webConfigurator default(12345678). Default. Unused.
- SSL/TLS Listen Port: 853. Default. Unused.
- Network Interfaces: LAN, IOT, GUEST and localhost. The CLEAR Interface is not included here. It will use external DNS directly, and also act as a failover DNS just in case the other Interfaces fail for some reason.
- Outgoing Network Interfaces: WAN.
Default is actually ALL.
- By default the DNS Resolver utilizes all interfaces for outbound queries so it will source the query from whichever interface and IP address is closest to the target server from a routing perspective.
- Selecting specific interfaces will limit the choices to only specific interfaces that may be used as a source of queries.
- Controls which interfaces the firewall will utilize when sending its own queries to other DNS servers.
- Can be set for instance to a VPN interface to to prevent DNS leaks.
- Or by deselecting the WAN interface to force pfSense to use a local DNS server, like pihole.
- Or only select localhost if pfSense is running a BIND DNS server.
- System Domain Local Zone Type: Transparent. Static is an alternative option to be look at here.
NOTE: The local-zone type can be:
- deny serves local data (if any), else, drops queries.
- refuse serves local data (if any), else, replies with error.
- static serves local data, else, nxdomain or nodata answer.
- transparent gives local data, but resolves normally for other names.
- redirect serves the zone data for any subdomain in the zone.
- nodefault can be used to normally resolve AS112 zones.
- typetransparent resolves normally for other types and other names.
- inform acts like transparent, but logs client IP address.
- inform_deny drops queries and logs client IP address.
- inform_redirect redirects queries and logs client IP address
- always_transparent resolve in that way but ignore local data for that name.
- always_refuse resolve in that way but ignore local data for that name.
- always_nxdomain resolve in that way but ignore local data for that name.
- noview breaks out of that view towards global local-zones.
- DNSSEC: Checked. This ensures that DNS queries are validated to be legit and can be trusted and the results have not been tampered with.
- Python module: Not Checked.
- DNS Query Forwarding:
- Enable Forwarding Mode: Not Checked. If Checked, then Unbound will forward all DNS traffic to the upstream DNS-Servers configured in System → General Setup and will not handle these queries itself. This is not wanted.
- Use SSL/TLS for outgoing DNS Queries to Forwarding Servers: Not Checked.
- DHCP Registration: Not Checked. If checked, makes sure that you can lookup your local hosts.
NOTE: With this checked results in Unbound restarting every time a DHCP lease is issued, or refreshed.
This results in DNS caching being cleared. Not what we want.
- Static DHCP: Not Checked. If checked, makes sure that you can lookup your local hosts; which have static bindings. See note above in DHCP Registration why this is kept unchecked.
- OpenVPN Clients: Not Checked.
- Custom options:
server: private-domain: "plex.direct" access-control-view: 192.168.1.0/24 LAN access-control-view: 192.168.50.0/24 CLEAR access-control-view: 192.168.70.0/24 IOT access-control-view: 192.168.99.0/24 GUEST view: name: "LAN" view-first: yes include: /var/unbound/pfb_dnsbl.*conf view: name: "CLEAR" view-first: no include: /var/unbound/host_entries.conf #Host overrides AND DHCP reservations include: /var/unbound/dhcpleases_entries.conf #DHCP leases view: name: "IOT" view-first: yes include: /var/unbound/pfb_dnsbl.*conf view: name: "GUEST" view-first: yes include: /var/unbound/pfb_dnsbl.*conf
- Click Save.
NOTE: Custom options are configured to use different views:
- The LAN view, is the default one handling the LAN, and does include the pfBlockerNG DNSBL checks.
- The CLEAR view, does NOT include pfBlockerNG DNSBL checks, i.e. it bypasses these additional checks.
- The view-first: no means it also does not use the Global zone for data queries.
WARNING: With the view-first: no, it might result in some devices, such as mobile phones, taking a long time (~30s) to connect to the network at first.
You should consider whether to allow this to be changed to view-first: yes.
- The IOT view does include the pfBlockerNG DNSBL checks.
- The GUEST view includes pfBlockerNG DNSBL checks.
The options used include:
- private-domain: “plex.direct” - As I run a Plex server, this allows access to this internal Plex Server using the external Plex network address.
- Without this, pfSense will report a rebounding error.
- view-first: yes - It will try to answer using the global local-zone and local-data elements if there is no view specific match.
- The default is no.
- include: /var/unbound/pfb_dnsbl.*conf - includes pfBlockerNG checks against spam etc.
Using local-data
An option that could be configured is to use local-data for DNS queries. For example:
view: name: "IOT" view-first: no local-data: "localdomain. 10800 IN SOA pfsense.localdomain. root.localdomain. 1 3600 1200 604800 10800" include: /var/unbound/pfb_dnsbl.*conf
The local-data parameters declares the DNS Resolver as authoritative for .localdomain.
- This means that names not resolved as part of .localdomain are not forwarded to the root notes for resolution preventing unneeded leakage of information.
- A firewall rule will be configured later to support this enforcement.
The parameters used are:
- ttl = 10800 (3 hours)
- primary name server = pfsense.localdomain
- responsible mail address = root.localdomain
- serial = 1
- refresh = 3600 (1 hour)
- retry = 1200 (20 mins)
- expire = 604800 (7 days)
- default TTL = 10800 (3 hours)
NOTE: Alternatively, if separate different views are not needed, simply declare the DNS Resolver as authoritative for the .localdomain domain.
local-data: "localdomain. 10800 IN SOA pfsense.localdomain. root.localdomain. 1 3600 1200 604800 10800"
Keep this line if it exists too, which includes pfBlockerNG checks against spam etc.
server:include: /var/unbound/pfb_dnsbl.*conf
Advanced Privacy Options
Navigate to Services → DNS Resolver → Advanced Settings.
In Advanced Privacy Options:
- Hide Identity: Checked.
- Hide Version: Checked.
- Query Name Minimization: Checked.
- Strict Query Name Minimization: Not Checked.
WARNING: Changes to advanced settings can sometimes break DNS lookups.
If any issues are found, then adjust as needed, otherwise leave ALL other options on default settings.
In Advanced Resolver Options:
- Prefetch Support: Checked.
- Prefetch DNS Key Support: Checked.
- Harden DNSSEC Data: Checked.
- Serve Expired: Checked. See note below.
- Message Cache Size: 512MB. Increased from default of 4MB as system has lots of memory available.
- Outgoing TCP Buffers: 10.
- Incoming TCP Buffers: 10.
- EDNS Buffer Size: 4096.
- Number of queries per thread: 512.
- Jostle timeout: 200.
- Maximum TTL for RRsets and messages: 86400.
- Minimum TTL for RRsets and messages: 0.
- TTL for host cache entries: 15 minutes.
- Number of hosts to cache: 10000.
- Unwanted reply threshold: Disabled.
- Log Level: Level 1: Basic Operational Information. Adjust for debugging or production etc.
- Disable Auto-added Access control: Not Checked.
- Disable Auto-added Host Entries: Not Checked.
- Experimental Bit 0x20 Support: Not Checked.
Click Save and Apply changes.
NOTE: The issue with prefetch and reason why Serve Expired is Checked.
Many mainstream services use DNS to route their traffic, and because of things like maintenance, DDOS attacks and so forth, they use extremely low TTL values, so they can reroute very quickly if required.
- TTL values of 30 seconds or less is now fairly common.
- Having to do a new DNS lookup so often has a performance hit.
Prefetch Support allows Unbound to prefetch records that are about to expire that the user has recently requested.
- An issue with the prefetch feature is it only works if you do a DNS lookup when less than 10% of the TTL is left, so basically with a 30 secs TTL, if another lookup is not done within the last 3 seconds of the TTL, then prefetch is not providing any benefit.
- Its operating scope is too narrow.
So Unbound implemented Serve Expired.
- What it does is when a record is expired, it will stay in the cache with the TTL value as 0.
- If another lookup comes in from the LAN (or whatever networks Unbound is serving), then it will be served as a cached record for performance.
- However at the same time a new lookup is initiated from Unbound to the authoritative server, so when there is a newer lookup later, it will serve a newer record.
- The important thing to note is that the same expired record is not served forever; it is only served once, then a new one is fetched.
Newer versions of Unbound allow this to be tweaked further.
- There is now an option as well that if e.g. you are uncomfortable perhaps using a cached record that might have been sitting there for a day you can set an effective expiry on the cached record itself using the more granular controls now available.
- This functionality is already in the latest stable Unbound build within pfSense.
- However the pfSense GUI does not currently have options to set this; but the developer is looking at getting this added. See https://forum.netgate.com/topic/142561/serve-expired-clearification/4
- Message Cache Size: As a rough guide, set this to Memory in GB * 8. So on a device with 32G memory, this would be set to at least 32*8=256M, but can be set higher on higher memory devices.
- Note that the cache memory values are all per thread. This means that much more memory is used, as every core uses its own cache. Because every core has its own cache, if one gets cache poisoned, the others are not affected.
- Even though this is increased, not all the space will necessarily be used for caching:
- The malloc code in FreeBSD is very good and the actual cache size that is used might be lower most of the time than set here.
- Memory fragmentation (the space between allocated memory blocks) will increase slowly, so not all of the cache will actually be used for “proper” caching.
- Unbound has an internal alloc-check mode that tests memory as well (The Unbound extra memory checks are slow) which will set actual caching usage.
See https://nlnetlabs.nl/documentation/unbound/howto-optimise/
Verify DNS Functionality
Navigate to Diagnostics → DNS Lookup.
- Enter an address to test lookups with, e.g.: pfsense.org
- Click DNS Lookup.
NOTE: You should see an IP address returned as well as the time taken to receive the response from the servers configured in System → General Setup.
Successive attempts to resolve the same address should be cached and be returned faster than the original query.
Return to Install pfSense or continue to Create Firewall Aliases.