2.9.0 New Features and Changes

This is a regularly scheduled software release including new features and bug fixes.

Tip

Review the Upgrade Guide before performing any upgrade of pfSense software.

General

  • Base OS updated to FreeBSD 16-CURRENT

  • OpenSSL upgraded to 3.5.7

  • OpenSSH upgraded to 10.3p1

  • PHP updated to 8.5.7

SSH Algorithms

This release includes several changes to algorithms for the SSH daemon for key exchange, encryption, and message authentication. These changes increase security by including post-quantum key exchange algorithms and by removing older and weaker algorithms.

The current set of SSH server algorithms are supported by most SSH, SCP, and SFTP clients released in the last several years, but some older or specialized clients may fail to connect. Ensure all client software is fully up-to-date before upgrading to this version of pfSense software.

If a client does not connect to the SSH daemon on this version, please post on the Netgate Forum and include the full client name and version.

TLS Certificate Strength

The version of OpenSSL in this release further tightens certificate requirements and removes support for certain weak properties. For example, if a TLS server certificate for a service such as the GUI has a weak key (<2048 bits), the service may fail with an error such as “key too small”.

Such weak certificates have been deprecated for some time and the GUI has warned against using weak settings, however, if the certificates were generated on other systems and imported, or generated years ago with long lifetimes, users may not realize such certificates are now considered insecure.

This version of pfSense software checks the GUI certificate during the upgrade process and will re-generate a new GUI certificate if the current certificate is invalid, expired, or weak.

Even with that automatic check, the best practice is to inspect all server certificates before upgrading. Navigate to the System > Certificates, Certificates tab. On that page, check each TLS server certificate by clicking the fa-arrow-rotate-right Renew/Reissue icon. On the renewal screen, inspect the Certificate Properties vs Strict Security table. If any items in the Would Change column are Yes, then either renew the certificate with Strict Security checked, or create/import a replacement certificate which meets these standards.

If the fa-arrow-rotate-right Renew/Reissue icon is not available for a certificate, such as for those imported from an external CA, use the fa-info-circle icon to view the certificate properties and check the values manually.

TLS Server Certificate Lifetime

CA/Browser forum baseline requirements are calling for shorter TLS server certificate validity periods to be phased in over the next few years and the current period is a maximum of 200 days for server certificates issued between March 15, 2026, and March 15, 2027.

To follow those recommendations, this release lowers the recommended secure server certificate lifetime from 398 days to 200 days.

Note

This value is only a recommendation, not a strict limitation. Users may opt to use longer lifetimes by manually entering the lifetime value of their choice.

TLS Certificate Auto-Renew

This version of pfSense software can automatically renew TLS server certificates which are self-signed or signed by an internal CA stored in the pfSense software configuration. Automatic renewal is a per-certificate option, and pfSense software automatically enables this option for the GUI certificate when possible. When automatically renewing a certificate, pfSense software uses the latest strict security options to ensure the certificate meets current standards.

While many operating systems and browsers will ignore strict validity requirements for self-signed certificates or certificates signed by a custom CA, some do not. Allowing GUI certificates to expire will result in the GUI being unreachable in those cases.

Users can edit the GUI certificate entry and disable the automatic renewal option if it does not suit their environment.

While the option is not automatically enabled for other TLS server certificates, it is generally safe to enable it manually. For example, TLS server certificates for OpenVPN servers can safely auto-renew.

Endpoint-independent Port Restricted Cone Outbound NAT

This version includes partial experimental support for “Port Restricted Cone” endpoint-independent outbound NAT. This functionality must be manually enabled on a per-rule basis.

“Port Restricted Cone” NAT mappings attempt to preserve port and external address mappings for clients when speaking to multiple remote hosts, but in a dynamic way that does not rely on static port NAT. This helps avoid issues with multiple local clients using the same source port to the same remote host. These rules enable a client communicating with multiple remote hosts using the same source port to receive the same external IP address and port on outbound connections to any destination. This behavior facilitates use cases such as online gaming, peer-to-peer connections, and VoIP.

Inbound communication from a remote host and port is only possible after a local client initiates first contact to that remote host and port. While this is more secure, it is not yet capable of “full cone” NAT which some use cases may require such as certain types of online gaming.

Security / Errata

FreeBSD

  • Security and errata fixes were merged from FreeBSD, including fixes for vulnerabilities discovered in OpenSSL and the DHCP client.

  • Base system packages were updated to address various upstream security issues.

pfSense Software

This release contains several security fixes, some of which were previously released via the Recommended System Patches feature of the System Patches Package.

pfSense CE

Changes in this version of pfSense CE software.

Aliases / Tables

  • Changed: Increase amount of system alias content printed in alias list #16118

  • Fixed: Editing an alias used in static routes does not correctly update the routing table #16407

  • Added: Allow using interface subnet macros with interfaces which only contain VIPs #16613

  • Fixed: URL tables cannot import content from tgz file URLs #16964

Authentication

  • Added: PHP RADIUS client Message-Authenticator attribute capability #15952

  • Fixed: LDAP shell authentication does not honor configured group DN restriction #16799

Backup / Restore

  • Fixed: RRD data fails to restore via the ECL #16141

  • Fixed: ECL can modify a discovered config file #16153

Build / Release

  • Added: Include System Patches package by default #16695

Captive Portal

  • Fixed: Captive Portal Ethernet rules can block ARP #16264

  • Fixed: Reserved DUMMYNET pipes for Captive Portal can overlap #16540

  • Fixed: Captive Portal “Allowed IPs” entries do not work if the language is not set to English #16549

  • Fixed: Potential XSS in Captive Portal widget #16773

  • Fixed: Captive Portal authentication failures from usernames containing special characters or long strings can cause ambiguous or confusing log messages #16922

Certificates

  • Changed: Update certificate expiration warning behavior #16605

  • Changed: Update recommended maximum server certificate lifetimes to 200 days #16606

  • Added: Auto-renewal for certificates #16607

  • Changed: Improve handling of certificates without subjects #16657

  • Fixed: Creating a CA certificate with Trust Store checked is not trusted #16688

Configuration Backend

  • Changed: Improve file handling of the configuration cache #16469

  • Fixed: Alerts do not trigger for empty configuration change descriptions #16557

  • Fixed: UTF-8 characters in configuration data can result in an invalid configuration #16661

  • Changed: Migrate config.xml encoding from ENT_HTML401 to ENT_XML1 #16745

Configuration Upgrade

  • Fixed: Some package installation configuration data may be missing after OS upgrade #16634

  • Changed: Remove quick from previous match rules on upgrade #16636

DHCP (IPv4)

  • Added: Option to control Kea log level #16230

  • Changed: Upgrade to Kea 3.0.2 #16388

  • Changed: Kea configuration parameter client-class is deprecated #16468

  • Fixed: kea2unbound crashes when reading an invalid configuration file #16602

  • Changed: Kea attempts DNS Registration when Unbound is disabled #16865

DHCP (IPv6)

  • Fixed: Hostnames in Kea static leases may not be registered with DNS #16552

  • Fixed: Kea DHCPv6 Leases page does not include delegated prefixes from active dynamic leases #16697

  • Fixed: Potential XSS in Delegated Length value for Prefix Delegation on services_dhcpv6.php when using Kea #16744

DHCP Relay

  • Fixed: DHCP relay does not respect configured CARP VIP status #15017

DNS Forwarder

  • Fixed: PHP error in DNS Forwarder host overrides when the language is set to French #14741

DNS Resolver

  • Changed: Update Unbound to 1.24.2 to address CVE-2025-11411 #16503

  • Added: Omit reserved NAT64 addresses from DNS64 answers #16534

  • Added: Omit NAT64 address for queries from the firewall itself #16615

  • Fixed: Unbound configuration validation does not test the complete configuration #16637

  • Fixed: Unbound configuration may be generated with duplicate interface bindings #16906

Dashboard

  • Changed: Speed up MBUF Usage command in System Information Dashboard widget #15780

  • Fixed: Thermal Sensors widget does not respect per-sensor threshold vales #16266

  • Fixed: Potential XSS in RSS Widget feed content post titles #16770

Diagnostics

  • Fixed: Captive Portal backwardsyncpassword value not sanitized in status output #16339

  • Fixed: Potential Stored XSS in diag_arp.php when using ISC DHCP #16763

  • Changed: Add device_key to filtered tags list for status output #16959

Dynamic DNS

  • Added: Preserve other record types when updating IPv4 or IPv6 using deSEC DDNS #12495

  • Fixed: All-Inkl Dynamic DNS responses are not parsed correctly #16218

  • Fixed: Dynamic DNS does not use preferred VIP in Gateway Group #16326

  • Fixed: Custom Dynamic DNS services ignore the monitor interface #16368

  • Added: Allow wildcard records for Dynamic DNS provider deSEC.io #16666

  • Fixed: Dynamic DNS client ignores Verify SSL/TLS Certificate Trust option when the entry does not contain a username #16690

  • Fixed: Cannot update GoDaddy Dynamic DNS AAAA record #16731

  • Added: Log errors when determining the RFC2136 update source address #16819

  • Changed: Encode Dynamic DNS credentials when passed as URL parameters #16905

Gateway Monitoring

  • Fixed: Gateway monitoring daemon can unexpectedly use a CARP VIP as the source IP address #16322

  • Added: Gateway recovery functionality for the default failover gateway group when all gateways are offline #16635

  • Changed: Improve gateway status consistency #16707

Gateways

  • Fixed: Gateway list order is incorrect until reloading page after moving entries and saving #16495

  • Changed: Remove custom gateway ordering #16559

  • Fixed: Inaccurate “No default gateway found” log message when the default gateway is set to automatic #16681

  • Changed: Improve default gateway detection when gateways share the same address #16816

  • Fixed: Static route not removed when enabling dpinger_dont_add_static_route while a gateway monitor IP address is set #16861

Hardware / Drivers

  • Added: Option to deactivate ALTQ for VirtIO vtnet interfaces #16166

  • Fixed: QLink/Marvell 41000 NIC bug #16248

  • Fixed: e1000 network interfaces unexpectedly link at half-duplex #16449

IPsec

  • Fixed: IPsec Keep Alive does not update the gateway status #15087

  • Changed: Update strongSwan to 6.0.3 #16509

  • Fixed: Cannot disable IPsec Advanced Settings tab option for Strict Interface Binding #16709

  • Fixed: IPsec daemon can crash if a peer initiates two rekeys for the same child SA #16836

IPv6 Router Advertisements (radvd/rtsold)

  • Fixed: Cannot set RADVD router lifetime to 0 #16472

  • Fixed: Potential remote command execution via DNSSL router advertisement messages #16593

  • Fixed: IPv6 Track Interfaces ignores the Disabled Router Advertisements mode #16925

Interfaces

  • Added: Option to change QinQ ethertype to Service VLAN Tag #13340

  • Fixed: Retain previous QinQ VLAN tag type value for existing entries on upgrade #13622

  • Fixed: PPPoE MSSFix uses incorrect values for 6RD #16243

  • Changed: Do not add fe80::1:1 link-local address to interfaces configured for IPv6 tracking #16567

  • Fixed: Interfaces menu does not use natural sorting when configured to sort alphabetically #16654

  • Added: Set IP Alias VIP as the Router Advertisement source #16914

Logging

  • Added: Option to disable logging of packets blocked due to unmatched IP options #16068

  • Fixed: syslogd daemon can terminate when a remote log server refuses connections #16362

  • Fixed: Firewall log always shows rules with Reject action under “Associated Rules” #16644

OpenVPN

  • Fixed: Automatic IPv6 gateways for OpenVPN servers are created with the wrong gateway address #16351

  • Fixed: OpenVPN servers will not start with DH parameter lengths less than 2048 #16421

  • Fixed: OpenVPN does not include client-to-client in generated configuration for Peer-to-Peer SSL/TLS servers #16428

  • Changed: Automatically configure the OpenVPN tunnel MTU when set in the assigned interface configuration #16658

  • Added: 6rd interface prefix tracking for OpenVPN IPv6 tunnel network #16706

  • Fixed: Automatically generated vpn_networks table is missing OpenVPN networks #16795

  • Fixed: All OpenVPN instances are restarted when applying changes to any assigned interface #16815

Operating System

  • Fixed: Swap fails to activate when multiple swap partitions exist #16232

  • Added: Update the SSH server configuration to current standards and include post-quantum cryptography algorithms #16423

  • Fixed: Loader menu does not display the logo properly #16726

  • Fixed: Kernel panic due to race condition on a bpf device #16790

PHP Interpreter

  • Changed: Upgrade PHP to 8.4 #16471

  • Fixed: NULL bytes in an IP address can trigger PHP errors from ip2long() #16771

PPP Interfaces

  • Changed: Sanitize PPPoE configuration parameters #16128

  • Fixed: PPPoE interfaces using if_pppoe increase error counters due to normal ALTQ traffic shaping operations #16216

  • Fixed: Virtual IP addresses on PPPoE interfaces using if_pppoe can prevent PPP session termination #16487

  • Fixed: PPPoE on VirtIO vtnet interface fails to pass routed traffic #16638

Package System

  • Fixed: Error notification and log message "Updating repositories metadata" returned error code 1 at boot due to certctl race condition #16341

  • Changed: Prevent the GUI from removing vital packages #16538

  • Added: Allow packages to preserve RAM disk data between boots #16624

RRD Graphs

  • Fixed: Multiple updaterrd.sh processes #16927

Routing

  • Fixed: Input validation error when saving an existing static route which contains an alias destination #16625

Rules / NAT

  • Fixed: Cannot add Port Forward with an unassociated filter rule #15346

  • Added: Allow floating rules using the “match” action to match based on IP Options #16215

  • Added: Block non-global NAT64 addresses by default #16241

  • Changed: Refactor PF ruleset generation #16307

  • Added: Avoid traffic stalls from unnecessary filter reloads #16308

  • Fixed: NAT64 rules using reply-to do not forward packets #16429

  • Fixed: Filter rule evaluation continues after matching a match quick rule #16475

  • Added: Support state killing on gateway recovery for policy-routed traffic from the firewall itself #16502

  • Added: Endpoint-independent Port Restricted Cone Outbound NAT rules #16517

  • Fixed: NAT64 rules do not pass traffic when a gateway is specified for the rule #16546

  • Changed: Update output and parsing behavior for PHP shell pfanchordrill #16551

  • Fixed: Incorrect configuration change message when deleting an outbound NAT rule #16566

  • Changed: Add label to automatic PF antispoof, CARP, Captive Portal, and ICMPv6 rules #16653

  • Fixed: Firewall rule source option This Firewall (self) is not available when duplicating floating rules #16729

  • Fixed: Same port forward on multiple WANs can generate a PF error due to Pure NAT mode NAT reflection #16783

  • Changed: Retain a copy of the failed ruleset when a filter reload fails #16796

  • Fixed: Filter rules created as part of NAT rules can have an invalid protocol value #16954

SNMP

  • Fixed: Memory leak in libpfctl causes bsnmpd memory usage to grow over time #16456

Services

  • Fixed: isvalidpid() function does not properly check or escape PID file parameter #16743

System Logs

  • Fixed: Log entries without a hostname can cause the system log to display in an unexpected manner #15411

  • Fixed: Some remote syslog messages are duplicated when “System Events” option is enabled #16376

  • Changed: Set appropriate log levels for PHP and /usr/bin/logger logs #16515

  • Fixed: Firewall logs do not match PF rules with rule number 0 #16575

  • Fixed: Firewall logs do not correctly parse short packet errors #16579

  • Added: Option to set a default log level for all logs #16616

  • Changed: Exclude nginx logs from system.log #16826

Traffic Graphs

  • Fixed: Traffic Graphs display option “Description” does not utilize DHCP static mapping descriptions #16979

Traffic Shaper (Limiters)

  • Fixed: Using a Limiter on a rule with a gateway group limits all traffic through that gateway instead of the host IP address #15770

Translations

  • Fixed: Korean locale configuration name is incorrect #16505

Upgrade

  • Added: Fix configuration artifacts on upgrade #16253

  • Changed: Save the update branch preference on system update #16626

User Manager / Privileges

  • Fixed: sshguard does not trigger for GUI logins from usernames containing unexpected characters #16312

  • Fixed: GUI login events from usernames containing special characters or long strings can cause ambiguous or confusing log messages #16314

  • Fixed: Inconsistent and incorrect privilege names on some PPP service-related log tabs #16630

  • Fixed: Creating a new user ignores certificate checkbox value if the certificate fields are populated #16721

Virtual IP Addresses

  • Fixed: Input validation text for deleting an IP Alias VIP within a CARP VIP subnet may reference incorrect VIP #16272

  • Fixed: GUI does not prevent adding a VIP with a blank address #16610

Wake on LAN

  • Fixed: Links to send WOL packets are not handled consistently, may fail to send #16803

  • Changed: “Wake All” functionality on services_wol.php should only use POST #16961

Web Interface

  • Changed: Apple TouchID/FaceID probes for site icon files that do not exist #6727

  • Added: Sort list of System Tunables #15221

  • Fixed: CE shows QAT as a crypto option #16451

  • Changed: Require absolute path when saving a file on diag_edit.php #16580

  • Changed: Remove dead link about .local TLD use from system.php #16620

  • Fixed: GUI performance degradation due to check for weak passwords on each page load #16720

Wireless

  • Fixed: Interfaces Status shows an invalid SSID value for Wi-Fi interfaces #16769