26.4 Series
The OPNsense business edition transitions to this 26.4 release including full MVC/API experience as automation rules have been promoted to the new rules GUI, Suricata with a new inline inspection mode using “divert”, assorted IPv6 reliability and feature improvements, router advertisements MVC/API, full code shell command escaping revamp, default IPv6 mode now using Dnsmsaq for client connectivity, Unbound blocklist source selection, an automatic host discovery service, captive portal IPv6 support plus much more.
Please make sure to read the migration notes before upgrading.
Download link is as follows. An installation guide [1] and the checksums for the images can be found below as well.
https://downloads.opnsense.com/
26.4.1 (June 16, 2026)
This business release is based on the OPNsense 26.1.9 community version with additional reliability improvements.
Here are the full patch notes for the initial release:
system: refactor dashboard to use User model instead of direct config access
system: throw UserException when dashboard size limit was reached on save
system: add notes dashboard widget (contributed by Konstantinos Spartalis)
system: fix traffic dashboard widget initialization race condition (contributed by Greelan)
system: avoid side effect rendering sysctl item in config.xml during console assignment
system: improve cron command and parameter escaping
system: support RADIUS NAS-IP-Address attribute for authentication
system: add compatibility layer to future route disable/enable migration
system: only split first colon when reading sysctls
system: revisit snapshot name validation (partially contributed by Konstantinos Spartalis)
system: fix missing newline when generating cron jobs due to a regression
system: fix missing base64_decode() in JsonField which prevented user settings from saving
system: link CA references after all changes
system: parse certificate “key_type” and “digest”
system: allow flushing legacy OpenVPN legacy config
system: audit “staticroute” config access
system: use safe config iteration in core_user_changed_groups()
system: tighten landing page redirect (contributed by Konstantinos Spartalis)
system: fix passing null into getRealInterface()
system: fix regression in selective group delete introduced previously
system: allow unregistered plugin cron actions to be deleted
system: disable MAILTO for cron jobs
system: dashboard: explicitly compact on layout shift if there is no predefined layout
system: dashboard: update result on default restore
reporting: render NaN values as empty values and omit leading empty records from data set for health graphs
reporting: add max on Y axis for traffic graphs
interfaces: refactor bridge reconfigure script
interfaces: add missing config locks in device controllers
interfaces: use safe iteration in backend code
interfaces: adjust and annotate interface_dhcpv6_id()
interfaces: account for multiple UUIDs in VIP deletion
interfaces: more safe iteration through config_read_array()
interfaces: fix wrong DUID-UUID format but keep accepting the wrong one
interfaces: fix regression in selective device delete introduced previously
interfaces: IAID selection and prefix range reservation for WAN DHCPv6
interfaces: parse ifconfig output despite exit error in legacy_interfaces_details()
interfaces: hostwatch: pin warning banner to enabled flag
firewall: live view: decode HTML where necessary to aid filtering
firewall: use save method from ApiMutableModelControllerBase for log command, move rule command and savepoint action
firewall: safe config access in list_legacy_rules.php
firewall: remove duplicated CSV button hook
firewall: fix NPTv6 validation for empty external subnet
firewall: make getRealInterface() a static utility function
firewall: refactor searchRuleAction() to use the same filtering and sorting logic on MVC and legacy data
firewall: fix inverted source/destination cosmetic issue in SNAT and One-to-One NAT grids
firewall: fix search for floating rules in new rules GUI
firewall: add an alias formatter to show content fields as “dynamic” when populated by other components
firewall: fix Tabulator regression with alias batch delete
firewall: use safe config iteration in interface registration
firewall: fix unintended change in filtering logic for new rules GUI
firewall: fix action, ipprotocol and protocol translations for legacy rules in new rules GUI
firewall: use safe iteration over rules in filter_core_rules_user()
firewall: add missing exclamation mark for “not” in scrub rules
firewall: fix interface sorting by value for live log and groups
firewall: add banner if no rules defined in new rules GUI to match legacy GUI
firewall: use strnatcasecmp() for interface list in new rules GUI
firewall: fix typo that prevented queues to be selectable in pf-based traffic shaping
firewall: escape shaper targets in rule edit [1] (contributed by lujiefsi)
captive portal: remove redirection on HTTPS and ditch non-functional pass statement
dnsmasq: change DHCP tag to DescriptionField
dnsmasq: change widget link from settings to leases page
firmware: opnsense-bootstrap: add “-B” bare bootstrap mode
firmware: add repo configuration output to connectivity audit
firmware: stop buffering in sed to fix chunked update log output
firmware: retain ordering in update servers for connectivity check
firmware: allow “local” business mirror subscription
firmware: put clickable trailer for community plugins
firmware: fix return value masking during updates
firmware: opnsense-update: do not clean obsolete files on manual -r invokes
intrusion detection: fix drop and alert buttons on rules tab
ipsec: move swanctl.conf download button to the tab
ipsec: restyle the connections page for clarity
ipsec: disable scroll in authentication and children grids (contributed by Konstantinos Spartalis)
ipsec: validate the use of refid in CA certificates [2] (reported by lujiefsi)
kea: fix “Delegated length must be longer than or equal to prefix length” validation
kea: add ddns-override-no-update, ddns-override-client-update and ddns-update-on-renew per subnet
kea: DDNS DNS server port can now be specified
kea: add explicit reverse DDNS zones support (contributed by XtraLarge)
kea: add DDNS manual config override
kea: remove depend constraint of ddns_reverse_zone
kea: plug socket into dynamic PD route installation script
kea: add prefix to reservations to allow for static PD allocations based on DUID/MAC
kea: infer IPv6 lease type in delete script via lease lookup so IA_NA/IA_PD can be deleted
kea: DDNS add ddns-conflict-resolution-mode per subnet (contributed by chaispaquichui)
kea: allow customizing “mac_sources” and change default to “ipv6-link-local”
kea: add user-context object to config to emit description
kea: fix option_data_autocollect mismatch in DHCPv6 page
kea: enable internalModelSafeDelete due to increased model relation field usage
kea: build reservation status from control socket output
kea: add subnet vltime (partially contributed by Brandan Giles)
kea: add client-id to DHCPv4 reservations
kea: use JSON_UNESCAPED_UNICODE when writing the JSON configuration
kea: dynamic prefix delegation support [3]
kea: always start the prefix watcher when DHCPv6 is enabled
kea: cleanups for IntegerField using isSet() and no negative numbers allowed
kea: add decline_probation_period and set lower default to mitigate faulty client implementations to consume the whole pool
kea: add subnet allocator field (contributed by Marcos Della)
kea: add DHCPv4 compatibility options (contributed by Marcos Della)
kea: hook up reservation.next_server (contributed by Ian Munsie)
kea: fix missing visual cues for manual mode in DDNS and DHCPv4/6
network time: small cleanups in ntpd_configure_gps()
openvpn: add tls-crypt-v2 support
openvpn: allow restart action via cron
openvpn: fix client export not showing common names
openvpn: require an integer of at least 1 for “vpnid” field
radvd: allow user controlled hop limit (contributed by BPplays)
radvd: allow to start a manual configuration without primary IPv6
unbound: improve hostname/domain override validation
unbound: minor style/refactor for safe config access
unbound: hide unused tree row in form output for overrides
unbound: restyle statistics page
unbound: blocklists categorization and apply button message update (contributed by Konstantinos Spartalis)
wireguard: use getValues() consistently in control script
acl: some missing references and using camelCase pointers instead of snake_case
backend: configctl: properly quote parameters to avoid skipping empty ones (contributed by Majx)
backend: configctl: support -f cache flush parameter to fix cache invalidation preamble “!” pass
lang: numerous updates and fixes in existing languages
mvc: introduce JSON field type and refactor dashboard to use it
mvc: fixed a number of class import statements
mvc: remove unused UIModelGrid imports in IDS, Monit and Syslog controllers
mvc: remove Util imports where not needed
mvc: BaseField: add count() helper
mvc: fix validation to use getValue instead of plain string cast
mvc: UIModelGrid: remove flatten() method as getFlatNodes() is almost the same
mvc: add support for pluggable dynamic menu items and move some existing parts out of the MenuSystem class
mvc: stricter email address validation
mvc: OptionsField: use key as value if no value is set
mvc: unify migration message returns
mvc: add new validators to TextField: AllowSpaces, AllowNewlines, AllowSpecial and introduce new StrictTextField
mvc: strict alphanumeric-only regex for certificate refid [4] (contributed by eev4n)
mvc: simplify assorted option values to reduce duplication
mvc: static header support for forms
rc: move system_powerd_configure() to bootup plugin hook
shell: config access refactor in password and setaddr scripts
shell: safe iteration for VLAN/LAGG in port assignment
shell: use safe config iteration in live mode banner
shell: fix syntax error in port assignment
ui: generalize placeholders between controllers and JS
ui: simplify and clean up debounce() usage
ui: trap generic error popup for specific API URLs such as /api/core/firmware/upgradestatus when it adds no value and known to be unstable
ui: add static dialog header support and fix bool/string compare
ui: add type_formatter keyword to form rendering
ui: add save/cancel button support to form rendering
ui: remove “event” use from bootgrid showSaveAlert()
ui: add support for binary file uploads
ui: bootgrid: onRendered executed in wrong spot
ui: clean up useRequestHandlerOnGet usage
ui: use space in apply box for the apply reminder
ui: improve form validation error append
ui: tab exclusion for SimpleActionButton
ui: split form button row render as some forms only use save
ui: override selectpicker defaults for translations
ui: hide apply button for specific tabs on multiple pages (contributed by Konstantinos Spartalis)
ui: bootgrid: align datakey with the rest of the options, but allow top-level placement
ui: bootgrid: mark state variables as such
ui: bootgrid: safeguard replace() function
ui: bootgrid: remove unused getTotalRowCount() method
ui: bootgrid: prevent NaN pagination values for non-ajax grids when row count is set to all
ui: bootgrid: clean up converter compatibility code
ui: bootgrid: replace “append” with “replace” for ajax: false grids
ui: bootgrid: adjust column persistence behavior to prevent horizontal dead space
ui: bootgrid: allow column selection exclusions
ui: allow passing of data attributes for select items in setFormData()
ui: remove banner on inline reload if applicable
ui: button padding when injecting next to apply button
ui: fix spurious padding in apply button section (contributed by Konstantinos Spartalis)
plugins: os-cloudflared 1.0 (contributed by Richard Aspden)
plugins: os-ddclient 1.31 [5]
plugins: os-frr 1.53 [6]
plugins: os-netbird 1.3 [7]
plugins: os-q-feeds-connector 1.6 [8]
plugins: os-rfc2136 1.10 [9]
plugins: os-stunnel fix for missing include in script
plugins: os-telegraf 1.12.15 [10]
plugins: os-tinc fixes evaluation of hosts enabled flag (contributed by Konstantinos Spartalis)
plugins: os-turnserver 1.3 [11]
plugins: os-zabbix-agent 1.9 [12]
plugins: os-zabbix-proxy 1.7 [13]
plugins: use safe config iteration in interface registration code
src: missing permission check in thr_kill2 [14]
src: arbitrary file overwrite via the KTLS receive path [15]
src: multiple vulnerabilities in the sound mmap path [16]
src: sigqueue missing capability mode restriction [17]
src: use-after-free bug in the IPV6_MSFILTER socket option handler [18]
src: flaw in Linuxulator execution of setugid binaries [19]
src: ASLR bypass for setuid executables via procctl [20]
src: integer overflow in vt CONS_HISTORY ioctl [21]
src: openssl: fix multiple vulnerabilities [22]
src: ldns: fix query response validation [23]
src: netlink: fix lock leak in nl_find_nhop
src: pf: avoid taking the pf rules write lock in a couple of ioctls
src: ipfw: add ability to run ipfw binary with 15.0+ kernel module
src: ipfw: treat ipv6 address with zero mask as “any”
ports: curl 8.20.0 [24]
ports: dnsmasq 2.93 [25]
ports: filterlog 0.8 changes rule label fetch to libpfctl
ports: kea 3.0.3 [26]
ports: krb5 1.22.2 [27]
ports: libxml 2.15.3 [28]
ports: nss 3.124 [29]
ports: openssh 10.3p1 [30]
ports: openssl 3.0.21 [31]
ports: openvpn 2.7.4 [32]
ports: phalcon 5.14.2 [33]
ports: php 8.3.31 [34]
ports: phpseclib 3.0.55 [35]
ports: py-duckdb 1.5.3 [36]
ports: py-numpy 2.4.6
ports: py-requests 2.33.1
ports: python 3.13.14 [37]
ports: sqlite3 3.53.1 [38]
ports: strongswan 6.0.7 [39]
Here are the full patch notes for patch release 1:
system: configuration line injection via multiple GUI text fields [40] (reported by lujiefsi)
system: add missing legacy_html_escape_form_data() for $a_cert on administration settings [41] (reported by Jonas Ampferl of Hacking Cult)
system: lockout: address newline injection and correct IP parsing [42] (reported by lujiefsi)
system: hasPrivilege() not merging user privs correctly [43] (reported by iys8)
system: fix ACL pattern for carp_status action (contributed by Etienne Girault)
interfaces: prohibit the use of advanced DHCP option settings by non-administrators
firewall: safeguard ISO country codes in alias download [44] (reported by Jonas Ampferl of Hacking Cult)
firewall: escape user-controlled values in tooltip attributes [45] (reported by Jonas Ampferl of Hacking Cult)
firewall: unify group names of OpenVPN, WireGuard and IPsec encapsulation
firewall: skip alias on new rules GUI apply
captive portal: pass in ip_address as a set for accounting
firmware: fix small glitch that re-prompts for showing community plugins
network time: fix stored XSS in GPS init string display [46] (reported by Jonas Ampferl of Hacking Cult)
openvpn: prevent path traversal in “common_name” attribute [47] (reported by lujiefsi)
openvpn: escape client common_name in connection-status views [48] (reported by Jan Kahmen of turningpoint and lujiefsi)
mvc: checkAndThrowValueInUse validate input token which may only contain alphanum and dashes [49] (reported by Jonas Ampferl of Hacking Cult)
mvc: also do not translate empty labels in grids
ui: add generic escaping function htmlSafe() for JavaScript
src: vm: use-after-free in device pager page list [50]
src: execve: local privilege escalation via execve(2) TOCTOU race [51]
src: openzfs: multiple vulnerabilities in OpenZFS [52]
src: libalias: bffer overflow in libalias RTSP handler [53]
src: unlinkat: unlinkat(2) ignores AT_RESOLVE_BENEATH flag [54]
src: tcp: use-after-free in TCP RACK stack option handler [55]
src: posixshm: multiple vulnerabilities in POSIX largepage objects [56]
src: audit: incorrect audit records for ptrace(2) syscall requests [57]
src: ktls: remote DOS via uninitialized memory access in KTLS receive [58]
src: linux: kernel stack disclosure in Linux compatibility layer [59]
src: iconf: multiple vulnerabilities in iconv(3) [60]
ports: expat 2.8.2 [61]
ports: ldns 1.9.2 [62]
A hotfix release issued as 26.4.1p1_2:
firmware: support for patch release matching
openvpn: add a specific regex constraint for static keys to fix previous safeguarding
26.4 (April 15, 2026)
The OPNsense business edition transitions to this 26.4 release including full MVC/API experience as automation rules have been promoted to the new rules GUI, Suricata with a new inline inspection mode using “divert”, assorted IPv6 reliability and feature improvements, router advertisements MVC/API, full code shell command escaping revamp, default IPv6 mode now using Dnsmsaq for client connectivity, Unbound blocklist source selection, an automatic host discovery service, captive portal IPv6 support plus much more.
Please make sure to read the migration notes before upgrading.
Download link is as follows. An installation guide [1] and the checksums for the images can be found below as well.
https://downloads.opnsense.com/
This business release is based on the OPNsense 26.1.6 community version with additional reliability improvements.
Here are the full patch notes:
system: factory reset and console tools now default to using Dnsmasq for DHCP
system: wizard now offers an abort button and deployment type selections
system: wizard can disable WAN or LAN interface now
system: provide resolv.conf overrides via /etc/resolv.conf.local
system: add XMLRPC option for hostwatch
system: remove “upstream” from gateway grid as priority already reflects the proper data
system: adjust gateway group priority (tier) wording
system: add note field to store comments for each snapshot
system: add configurable “memberOf” attribute to LDAP connector
system: do not scrub unrelated IPv6 DHCP ranges from Dnsmasq LAN config during wizard
system: adapt DHCP address shell setup for new config access functions
system: adapt web GUI certificate renew for new config access function
system: adapt initial port configuration DHCP setting for new config access functions
system: avoid using “(system)” user revision annotation to match legacy and MVC code
system: fix log files ‘go to page’ edge case and row count persistence/max
system: ignore future backups when they exist to ensure new backups are saved
system: ensure proper types are emitted in searchGatewayAction() when configd action fails
system: use safe iteration for cert/ca in system_trust_configure()
system: fixed broken link in modal header when using HA and saving administration settings
system: create a backup on factory reset
system: unify pwd_changed_at usage
system: store dashboard layout types based on column breakpoints
system: do not show snapshot notes in the grid
system: use safe config iteration in admin settings page
system: cleanup and simplify certificate deployment and remove legacy config import
system: validate monitor uniqueness based on the host route presence
system: simplify user/group sync scripts using config_read_array()
system: dashboard gauge improvements (contributed by Konstantinos Spartalis)
system: compress height of the log viewer grid
reporting: restore canvas state in health graph to fix Firefox display bug
reporting: use safe config iteration in RRD code
interfaces: a new IPv6 mode called “Identity association” was added
interfaces: add and enable new host discovery feature for neighbours via hostwatch
interfaces: settings page was migrated to MVC/API
interfaces: handle hostwatch user/group via package
interfaces: force-reload IPv6 connectivity when PDINFO changes during renew
interfaces: dhcp6c rapid-commit, request-dns and config write refactoring
interfaces: generalise the rtsold_script code
interfaces: use descriptive interface names in automatic discovery table
interfaces: harden settings page with file_safe() and allowed_classes=false
interfaces: host discovery: make sure the full dump includes NDP output on fallback
interfaces: fix migration for IPv6 no-release option
interfaces: fix wlanmode argument usage
interfaces: generalise the dhcp6c_script using the new IFNAME variable
interfaces: fix enter key in assignment description and general cleanup
interfaces: protect device reads against forcing empty arrays into $config
interfaces: remove unused ip_in_interface_alias_subnet()
interfaces: use safe config iteration in PPP edit page
interfaces: clean up overview UI code and fix CARP badge alignment
interfaces: simplify CARP scripts using config_read_array()
interfaces: automatic dhclient recovery
interfaces: settings page use cases for config_read_array()
interfaces: configurable cleanups for automatic neighbor discovery via hostwatch
interfaces: refactor PPP CARP hook
firewall: escape selector in rule_protocol
firewall: “Port forward” was migrated to “Destination NAT” MVC/API
firewall: unified look and feel of MVC/API pages formerly known as “automation”
firewall: improved support of gateway groups in policy-based routing
firewall: plugin support for “ether” rules has been removed
firewall: add import/export to shaper queues and pipes
firewall: “divert-to” support in new rules GUI
firewall: added a rule migration page (use with care)
firewall: make previously associated DNAT rules editable
firewall: FilterBaseController requires BaseUserException
firewall: fix typo with sprintf() with DNAT rule
firewall: fix target mapping inconsistency leading to references not being processed in destination NAT
firewall: use local-port as target when specified in destination NAT
firewall: fix missing reply-to when not specifically set in new rules
firewall: live view: fix parsing of combined filters stored as converted strings
firewall: fix group rename in source_net, destination_net and SNAT/DNAT target fields
firewall: add tcpflags_any in new rules GUI for parity with legacy rules
firewall: exclude loopback from interface selectpicker in new rules GUI
firewall: well known ports added to filter rule selection
firewall: undefined is also “*” in new rules grid
firewall: add download button for validation errors in rule import
firewall: allow TTL usage on host entries
firewall: add missing implementation for “disablereplyto” in new rules
firewall: fix encoding issue in dashboard widget
firewall: check for schedules in use in new rules
firewall: add import/export function and missing lock on set action
firewall: better focus selected alias updates to in crease performance when either –aliases or –types is used
firewall: implement missing ICMP types in new rules GUI (contributed by Bjoern Jakobsen)
firewall: adjust for parseReplace() for icmp-type “skip”
firewall: fix NAT rule enabled checks display (contributed by Aaron Rogers)
firewall: prevent separator char from being used in category names
firewall: fix running into error using well known protocols with “-” in them
firewall: add validation to prevent using both gateway and reply-to in the same rule in new GUI
firewall: add a command button to open the live log with pre-filled rule ID in new GUI
firewall: move download and upload commands out of partial into global commands in new GUI
firewall: reduce complexity in URL hash handling and when using firewall_rule_lookup.php in new GUI
firewall: fix default ipprotocol mismatch so that when not specified both are indicated
firewall: update destination NAT ACL to match our menu entry
firewall: fix issues with searching in the states page
firewall: allow well known ports in local-port destination NAT
firewall: adjust row selection behaviour for internal rules in MVC pages
firewall: offer aliases the same was as the field type expects them
firewall: fix access to deleted filter node in advanced settings
firewall: merge MVC NAT page templates into a single one
firewall: when repopulating the interface selectpicker, always restore current selection in new rules GUI
firewall: remove hardcoded colors where possible in new rules GUI
firewall: fix category colors in new rules GUI
firewall: merge read of groups and interfaces in new rules GUI
firewall: make MVC protocol selection match the old rules pages
firewall: add model validations for common errors in destination NAT
firewall: live view: allow regex use in “contains” cases
firewall: live view: fix SyntaxWarning in log reader backend
firewall: use safe iteration in old rule page for schedule lookup
firewall: use safe config iteration in outbound NAT page
firewall: fix regression in alias summary not shown in new rules GUI
firewall: invalidate database when last updated time is in the future
firewall: add missing “static port” option in source NAT
firewall: add semantic groups coloring option in dashboard widget (contributed by Gunnar Lieb)
firewall: add missing alias rename rule targets
firewall: add alias GeoIP database update button and move bogons one to the same tab
firewall: fix port handling in registered NAT rule
firewall: fix MVC code vs. legacy rules display issues
firewall: outbound NAT page use case for config_read_array()
firewall: fix wrong “pass” on DNAT rule when using register rule
firewall: adjust sort order in networks and aliases in new rules GUI
firewall: change sorting to interface/group name and stop caring about counted rules in new rules GUI
firewall: change category sorting using names instead of counted rules in new rules GUI
firewall: remove tokenizer from categories and use selectpicker instead in new rules GUI
captive portal: cleanup and simplify certificate deployment and remove legacy config import
captive portal: enforce POST-only on logoffAction() (contributed by Oliver Jueguen)
captive portal: add IPv6 support (partially contributed by Alex Goodkind)
captive portal: fix allowed addresses missing from session IPs in roaming case
dhcrelay: relax the check for present addresses and CARP-related cleanups
dnsmasq: add automatic RDNSS option when none is configured
dnsmasq: fix log conditions
dnsmasq: add IP address validations for some of the DHCPv4 and DHCPv6 options (contributed by Greelan)
dnsmasq: add “no-ping” option (contributed by Konstantinos Spartalis)
dnsmasq: remove a too-strict validation for suffix IPv6 addresses without constructor use
dnsmasq: ensure the lease view handles client-id correctly
dnsmasq: prevent “*” from being collected as “client_id”
firmware: opnsense-code: run configure script on upgrade if needed
firmware: revoke 25.7 fingerprint
firmware: fix automatic advanced toggle in settings
firmware: shorten the reboot message to fit the spinner on the same line
firmware: tweaks for update/upgrade cleanup behaviours between core and opnsense-update
firmware: add support for aux repository handling in opnsense-update
firmware: add aux repository support
firmware: repeat the update after pkg reinstall
installer: ufs: ignore errors when flushing the full disk
intrusion detection: add a “divert” intrusion prevention mode
intrusion detection: upgrade ET Open ruleset to version 8.0 (contributed by 0nnyx)
ipsec: expose ChaCha20-Poly1305 AEAD proposals in IKEv2 (contributed by Kota Shiratsuka)
ipsec: use safe config iteration for VIP lookup
ipsec: add 4 insecure proposals for compatibility (contributed by Bjoern Jakobsen)
kea: add libdhcp_host_cmds.so to expose internal API commands for reservations
kea: exit prefix watcher script if no lease file exists
kea: allow “hw-address” for reservations
kea: add pool in subnet validation
kea: minor code cleanups in model code
kea: fix subnets GUI missing root node
kea: add required scope to prefix watcher link local address route
kea: guard prefix watcher when no link-local address exists for a route that should be installed
kea: add DDNS and DHCP option support
kea: add DDNS subnet-specific qualifying suffix and prevent updates if no server is set
kea: add sockets max-retries and retry-wait-time options
kea: add delete lease command and use socket for up-to-date lease collection
kea: move pool-in-subnet validation logic mostly to KeaPoolsField
kea: remove KeaCtrlAgent dependency on HA configuration
kea: use SetConstraint for match_data to allow 0 as valid value
monit: use safe config iteration in gateway alert script
network time: add pool property for time servers (contributed by Konstantinos Spartalis)
network time: remove stale symlink when PPS is disabled
openvpn: removed the stale TheGreenBow client export
openvpn: add options for legacy ciphers (contributed by Bjoern Jakobsen)
openvpn: debounce learn-address calls to limit the number of alias updates to a minimum
openvpn: add validation for selecting username as CN without setting any authentication
radvd: migrated to MVC/API
radvd: remove faulty empty address exception
radvd: remove configuration file if disabled
radvd: implement RemoveAdvOnExit override
radvd: add Base6Interface constructor
radvd: support nat64prefix
radvd: change tabs to spaces in radvd.conf for better maintenance
radvd: use safe config array iteration over virtual IPs
radvd: when adding a manual instance for an automatic “track6” interface do not ignore its settings
unbound: safeguard the blocklist tester against empty configuration testing
unbound: persist overrides PTR configuration and allow the user to deselect it
unbound: split logic in update_blocklist() and simplify getPoliciesAction()
unbound: move policy fetch to the controller and clean up accordingly
unbound: only emit warning when “addptr” was requested
unbound: use expand formatter for blocklist URLs and DNSBL types
unbound: include blocklist length in state change logic
unbound: add harden below NXDOMAIN option (contributed by Konstantinos Spartalis)
unbound: consolidate override aliases into tree view
unbound: deprecate Blocklist.site blocklists (contributed by Drumba08)
unbound: clean up blocklists update marker and size file handling
unbound: add per-policy quick actions in reporting overview
unbound: improve CNAME handling of whitelisted domains
unbound: safe command execution changes
unbound: merge extended blocklists into community version
unbound: prevent caching of blocklist entries on overlapping subnet policies
unbound: notify user if a blocklist reset is required
unbound: reconfigure if marker file present
backend: safe execution changes in the whole code base
backend: removed short-lived mwexecf_bg() function
backend: allow non-intrusive config_read_array() and fix a gateway group delete issue with it
backend: removed mwexec() and mwexec_bg() functions following their deprecation
backend: add config_push_array() and config_merge_array() helpers
backend: remove constant configd cleanups as they may influence requests from other threads executing different commands
backend: remove unused examples throwing errors now
backend: fix configd using a new temporary file for cached items
backend: more fixes for re-bound SyntaxWarning throws in Python 3.13
backend: use config_read_array() non-insert mode mode iteration of virtual IPs
lang: various translation updates
lang: various language updates
mvc: add ChangeCase support to ProtocolField for DNAT special case
mvc: improve importCsv() to support either comma or semicolon
mvc: removed long obsolete sessionClose() from ControllerRoot
mvc: BaseModel: isEmptyAndRequired() has been removed
mvc: removed unusued RegexField
mvc: add $separator as parameter for CSV export and switch the default to a semicolon
mvc: InterfaceField: minor adjustments and add resetStaticOptionList()
mvc: catch empty data in CSV import
mvc: restructure menu items and system using findNodeByPath()/getItem() additions
mvc: BaseListField: generic implementation of static options
mvc: PortField: make “well-known” port numbers known by allowing them to be mapped to their respective numbers
mvc: collect UUID field so it can be searched, but only if the searchPhrase contains a valid UUID
mvc: move CertificateField, InterfaceField and ProtocolField to newer static option API
mvc: BaseListField: merge remaining use of shared implementation of static options
mvc: File: add file_update_contents() helper
mvc: Shell: rewrite exec_safe() to avoid vsprintf() complications
mvc: BaseListField: replace empty() check with isSet() for proper selection of value “0”
mvc: HostnameField: show string that failed validation by default
mvc: BaseField: add setValues() for generic use
mvc: add SetConstraint for problematic “0” value constraining
mvc: ApiMutableModelControllerBase: remove unused error returning in setActionHook()
rc: replace camcontrol with diskinfo for TRIM check (contributed by Maurice Walker)
rc: speed up maintenance file deletes
shell: opnsense-log now supports “backend” and “php” aliases
shell: improve config restore UX using diff and additional meta data display
tests: Shell: add testing framework
tests: merge stable filter tests to double check upcoming changes
ui: allow HTML tags in menu items and title
ui: improve user readability in SimpleFileUploadDlg()
ui: batch bootgrid enable/disable-selected toggle by default
ui: swap order of custom bootgrid commands placement making sure they participate in command binding
ui: remove two unused static PHP array definitions
ui: Bootgrid: split row selection behavior into rowSelection boolean
ui: Bootgrid: force a lightweight redraw when columns are programmatically changed
ui: Bootgrid: fix curRowCount type conversion issue when stored in localStorage
ui: bootgrid: require selection to be enabled for delete-selected
ui: bootgrid: introduce ‘expand’ formatter to cap lists of data
ui: set visibility hidden for base_bootgrid_table
ui: upgrade Tabulator to version 6.4.0
ui: automatic grid height calculation
ui: bootgrid: maintain scrolling position for both datatree and command actions
plugins: os-acme-client 4.15 [2]
plugins: os-caddy 2.1.0 [3]
plugins: os-ddclient 1.29 [4]
plugins: os-freeradius 1.10 [5]
plugins: os-frr 1.51 [6]
plugins: os-haproxy 5.1 [7]
plugins: os-isc-dhcp 1.0 [8]
plugins: os-netbird 1.2
plugins: os-nextcloud-backup 1.2 [9]
plugins: os-nginx 1.36 [10]
plugins: os-postfix 1.24.1 [11]
plugins: os-q-feeds-connector 1.5 [12]
plugins: os-tailscale 1.4 [13]
plugins: os-tayga 1.5 [14]
plugins: os-theme-cicada 1.41 (contributed by Team Rebellion)
plugins: os-theme-flexcolor 1.1 (contributed by Schnuffel2008)
plugins: os-theme-tukan 1.31 (contributed by Team Rebellion)
plugins: os-theme-vicuna 1.51 (contributed by Team Rebellion)
plugins: os-turnserver 1.2 [15]
plugins: os-upnp 1.9 [16]
plugins: os-wazuh-agent 1.3 [17]
src: assorted patches from stable/14 for LinuxKPI, QAT, and network stack
src: if_ovpn: use epoch to free peers
src: carp6: revise the generation of ND6 NA
src: igmp: do not upgrade IGMP version beyond net.inet.igmp.default_version
src: igmp: apply net.inet.igmp.default_version to existing interfaces
src: ice: handle allmulti flag in ice_if_promisc_set function
src: icmp6: clear csum_flags on mbuf reuse
src: divert: Use a better source identifier for netisr_queue_src() calls
src: if_ovpn: add interface counters
src: e1000: fix setting the promiscuous mode
src: pfctl: allow new page character (^L) in pf.conf
src: sctp: support bridge interfaces
src: ifconfig: assorted stable fixes
src: ip_mroute: assorted stable fixes
src: vtnet: assorted stable fixes
src: pf: silently ignores certain rules [18]
src: vnet: ensure the space allocated by vnet_data_alloc() is sufficent aligned
src: ifnet: Fix decreasing the vnet interface count
src: e1000: Increase FC pause/refresh time on PCH2 and newer
src: net80211: fix VHT160/80P80/80 chanwidth selection in the “40-” case
ports: curl 8.19.0 [19]
ports: dhcp6c v20260122
ports: expat 2.7.4 [20]
ports: hostwatch 1.0.13
ports: ldns 1.9.0 [21]
ports: libucl 0.9.4
ports: libxml 2.15.2 [22]
ports: nss 3.121 [23]
ports: openldap 2.6.13 [24]
ports: openssl 3.0.20 [25]
ports: openvpn 2.6.19 [26]
ports: perl 5.42.2 [27]
ports: phpseclib 3.0.50 [28]
ports: py-duckdb 1.5.0 [29]
ports: python 3.13.13 [30]
ports: strongswan 6.0.4 [31]
ports: suricata 8.0.4 [32]
ports: syslog-ng 4.11.0 [33]
A hotfix release was issued as 26.4_6:
system: protect popen() with exec_safe() [34]
system: lockout bypass fix [35] (contributed by Konstantinos Spartalis)
system: allow gateway load balance weights from 1 to 10 for more flexibility (contributed by Matthew Hall)
system: add “nosync” option to gateway configuration
firewall: fix typo in alias update error log and make parser a bit more resilient
firmware: opnsense-update: handle FreeBSD.conf disable internally
plugins: os-acme-client 4.16 [36]
src: vm_fault: reset m_needs_zeroing properly [37]
src: timerfd: Fix interval callout scheduling [38]
src: tty: avoid leaving dangling pointers in tty_drop_ctty() [39]
src: pkru: fix handling of 1GB largepage mappings [40]
src: contrib/tzdata: import tzdata 2025c, 2026a and 2026b [41]
src: amd64: fix INVLPGB range invalidation [42]
src: pf: improve SCTP validation [43]
src: execve: fix an operator precedence bug [44]
src: dhclient: check for unexpected characters in some DHCP server options [45]
src: dhclient: fix reallocation of dhclient script environments [46]
src: libnv: switch fd_wait() from select(2) to poll(2) [47]
src: libnv: fix heap overflow in nvlist_recv() [48]
src: libpcap: update to 1.10.6
src: ipfw_nptv6: fix handling the ifaddr removal event
src: if_tuntap: make SIOCIFDESTROY interruptible
src: pfctl: parser must not ignore error from pfctl_optimize_ruleset()
src: pf: fix duplicate rule detection for automatic tables
src: openssl: update from 3.0.16 to 3.0.20
src: routing: fix use-after-free in finalize_nhop
src: ixgbe: fix MRQC register value
src: in_mcast: Fix a lock leak in inp_set_source_filters()
src: linuxkpi: fix an off-by-one error in the kfifo implementation
src: sctp: fix so_proto when peeling off a socket
ports: expat 2.8.0 [49]
ports: openvpn 2.6.20 [50]
ports: strongswan 6.0.6 [51]
A hotfix release was issued as 26.4_14:
system: properly escape username in sync_user.php command invoke [52] (contributed by Konstantinos Spartalis)
system: fix XMLRPC sync with VIP and “nosync” option
interfaces: safeguard DHCPv4 settings against arbitrary command injection [53] (reported by Kchigo)
captive portal: re-introduce hash lookup for accounting purposes
captive portal: reload IPFW on captive portal reconfigure too
dnsmasq: ignore DHCP names for “wpad” to fix CERT Vulnerability VU#598349
network time: fix ACL definitions (contributed by Konstantinos Spartalis)
openvpn: reload configuration for group sync after successful authentication
ports: dnsmasq 2.92rel2 [54]
ports: expat 2.8.1 [55]
A hotfix release was issued as 26.4_20:
system remove unused data-tooltip that is not properly escaped from certificates widget [56]
interfaces: dhclient.conf does not cope with multi-line request/require
firewall: fix for missing HTML escape in description render in legacy rules GUI [57]
monit: sanitize monit output before offering it
network time: cleanse port option before use [58] (reported by Konstantinos Spartalis)
mvc: do not translate empty strings
src: dhclient: improve server and filename validation [59]
src: setcred: fix buffer overflow [60]
src: kern: make sure to drain selinfo sleepers [61]
src: fusefs: handle buggy server LISTXATTR response [62]
src: ptrace: fix validation of PT_SC_REMOTE arguments [63]
src: libcasper: switch from select(2) to poll(2) [64]
src: cap_net: do not allow new limits to drop keys from the old ones [65]
src: ipfw: fix parsing error in nat config port_range
src: ipfw: fix checksum after NAT
src: igmp: Avoid leaving dangling pointers in the state-change queue
src: vxlan: Update *m0 after a pullup
src: routing: use a better error number in sysctl_fibs()
src: routing: initialize V_rt_numfibs earlier during boot
src: pfsync: reject invalid SCTP states
src: pf: do not reject rules with colliding hashes
src: rtnetlink: check for allocation failure in nlattr_get_multipath()
src: rtnetlink: align RTA_MULTIPATH length validation in nlattr_get
ports: suricata 8.0.5 [66]
ports: unbound 1.25.1 [67]
Migration notes, known issues and limitations:
ISC-DHCP moves to a plugin. It will be automatically installed during upgrades. It is not installed on new installations because it is not being used, but you can still install and keep using it.
To accommodate the change away from ISC-DCHP defaults the “Track interface” IPv6 mode now has a sibling called “Identity Association” which does the same except it is not automatically starting ISC-DHCPv6 and Radvd router advertisements to allow better interoperability with Kea and Dnsmasq setups.
Dnsmasq is now the default for DHCPv4 and DHCPv6 as well as RA out of the box. One thing that the upstream software cannot cover is prefix delegation so that is no longer offered by default. Use another DHCPv6 server in this case.
Due to command line execution safety concerns the historic functions mwexec_bg() and mwexec() were removed. Make sure your custom code is not using them and use mwexecf(), mwexecfb() and mwexecfm() instead.
The function sessionClose() has also been removed from the MVC code and is no longer needed. Make sure to remove it from your custom code.
The custom.yaml support has been removed from intrusion detection. Please migrate to the newer /usr/local/etc/suricata/conf.d override directory.
The new host discovery service “hostwatch” is enabled by default. You can always turn it off under Interfaces: Neighbors: Automatic Discovery if you so choose.
The firewall migration page is not something you need to jump into right away. Please make yourself familiar with the new rules GUI first and check the documentation for incompatibilities. Single interface from the floating interface will not be considered “floating” in priorities.
Firewall: NAT: Port Forwarding is now called “Destination NAT”. Firewall rule associations are no longer supported, but the old associated firewall rules remain in place with their last known configuration and can now be edited to suit future needs.
Firewall: NAT: Source NAT is from the set of pages formerly known as automation, but Outbound NAT is still the main page for these types of rules.
Unbound blocklists are now the same between business and community version. This requires a manual reapply of the blocklists in order to use the new shared format.
The public key for the 26.4 series is:
# -----BEGIN PUBLIC KEY-----
# MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArTnFQp0jjj5bkLNx9G1j
# q26WmN/EtAaJUt+2MY8W8h7L3kokRMlTgEvCYJOkUjbJYbjuG0Cut3JExNYa1vdD
# 1SLIlJShyI8OsjbAS/flZdJB9c0Vxz2CwpoX9Efmp5TaB3GWqhHS0OVLx4MSI3HJ
# qP/aQLjZMuCQHX8beUQB77YWcT6sPC5UMYeNEW1uHR7Oki/TpOXWnzNStEQXRL6/
# MiuYJovedlNXeNUeebJyG0TyLJ/3uGMYhHKYK+OJkB03P3iLGGVE/WWNugsqX6bY
# tTU9PquHo5zDApndp8iG49Fs/DC0r7V1P85ETPtW2SuZQ7YeDuz3VKvuMxAqyQoC
# 1FLOsIuEfudDmRuMuTsRgB6jaGACEWUTuRyiFG4+kVDi1/qOWpYatP8C8B7Lx9UU
# CTZhCl+Se4woWGtp5KOtYe+pvJ4oz40SL4drUQFEP3ZOsK/HzyLjPFRgxfANNUPG
# ONayKHJXVVFPg2ATk9jeNPsLmXlcDmi/rihyN4RM2w0/bi8BWSc+dMGZ5ZhNJdsF
# wHBIscgpiAhs+HS8Usxy3idv/JkY0h9tZ2QnljhUUwhYV+DT9yZf5ABU0B68VjJ4
# /GloUc3bS7HBeSTAauYMOQvgkY1vcySGWTXvsGOw/Crpk4DYx5KpGNYHmENRey2c
# AQdi+Fvi3fFkV1BoxGo78NcCAwEAAQ==
# -----END PUBLIC KEY-----
# SHA256 (OPNsense-business-26.4-dvd-amd64.iso.bz2) = 201fa8fb384fda534853f2a0fbc82aecbb8753e37a77426f55a1478029b02a2e
# SHA256 (OPNsense-business-26.4-nano-amd64.img.bz2) = e133243e85aa630d00d29ea78b8f6fe3b87de06bd7e62f88c3c8fed1b51edb9e
# SHA256 (OPNsense-business-26.4-serial-amd64.img.bz2) = 44dfd3a696bd04961145e40478128b75d911f0e8d6a9ea2a6d20a3b6205c7bc5
# SHA256 (OPNsense-business-26.4-vga-amd64.img.bz2) = 52c4d12b87c5464f9bfff9124a6c3a1c1dd52bb9a6a16d8e5b5cdeee4f108c78