What MurOS does today
MurOS is a fork of OPNsense ported to Debian 13. The configuration model, the web UI and the rule editor are kept from OPNsense; the parts that talk to the system are rewritten for Linux: nftables instead of pf, iproute2 instead of ifconfig, systemd instead of rc, and dpkg / apt instead of the FreeBSD package tools. The list below reflects what is actually wired on Debian. Each area carries a percentage showing how far it has been ported from FreeBSD to Debian, and individual items still being wired are marked in progress.
Network 90%
- Interface assignment. Each NIC is bound to a logical key (wan, lan, opt1, ...). Rules and NAT reference the key, not the device name. At first boot the keys are mapped to the real Linux devices automatically, so the box comes up without hand-editing.
- Static addressing via iproute2. IPv4 and IPv6 address, MTU and link state per NIC, applied from config.xml.
- DHCP client on WAN. The lease is applied by a Linux lease hook (address, netmask, broadcast, classless and static routes) through iproute2, and is kept across renew, rebind and reboot. Assigned interfaces can alternatively be driven by systemd-networkd.
- VLANs, bridges and link aggregation. 802.1Q VLANs, bridges (members, port isolation, STP timers) and LAGG mapped to Linux bonding (LACP, balance, failover), all applied through iproute2.
- Tunnels. GRE and GIF tunnels (sit, ipip, ip6tnl, chosen from the underlay and overlay address family) created with iproute2.
- Static routes. Entries in the main routing table, shown live from ip route.
- Persistence. Assignment and addressing are reapplied at boot by systemd units (muros-interface-assign, muros-interfaces) before the firewall loads, so the state survives a reboot.
- Multi-WAN gateways. Gateways are configured in the UI and each one is monitored for latency, packet loss and availability by the dpinger daemon, with alarms when a link degrades. Automatic policy-based failover in progress.
Firewall 87%
- Filter rules. Generated as an nftables ruleset: input / forward / output chains, action pass / block / reject, per-rule logging and comment.
- Stateful by default. Default deny with connection-state matching, out of the box.
- IPv4 and IPv6. Per-rule address family, with the common protocols (tcp, udp, icmp, esp, gre, ...) and TCP flag matching.
- Aliases as sets. Host, network and port aliases are compiled into nftables named sets and referenced from rules; entries can be added to a running set and the contents are read back from nft.
- Live counters. Per-rule and per-table packets and bytes read back from netfilter.
- Policy routing (multi-WAN). A pass rule can be pinned to a gateway: matching connections are marked and steered out that uplink (route-to). Replies to a connection that arrived on a WAN are sent back through the same uplink (reply-to), so a multi-homed box does not leak answers into the wrong ISP. The marks are saved on the connection, so every following packet keeps the same path.
- Validated apply. The generated ruleset is checked with nft -c before it is loaded, and a mandatory anti-lockout rule (SSH / HTTP / HTTPS) keeps the management session reachable.
NAT 88%
- Outbound NAT. Automatic masquerade per WAN, or manual rules matched on source and destination. No-NAT rules exclude traffic from translation (for example to a remote VPN subnet), and a fixed source port keeps protocols that need it from being rewritten.
- Port forwarding (DNAT). Publish an internal service on a public port, scoped to the destination address it is published on (the WAN address or a chosen IP) and an optional source, with the matching forward rule opened automatically. No-rdr exclusions exempt selected traffic, so a management subnet can reach a service directly while everyone else is forwarded.
- 1:1 NAT. Static external-to-internal address mappings.
- Negation. Match everything except a given address or set.
LAN services 80%
- DHCP server (Kea). Per-interface pools for IPv4 and IPv6, offered gateway and DNS, lease time and static reservations. It runs on the Debian Kea daemons, generated from the UI and controlled through systemd; active leases are read live over the Kea control channel.
- DHCP relay. Forwards client requests to upstream servers on the Debian isc-dhcp-relay binary, for both IPv4 and IPv6, with the relay agent information option and automatic upstream interface selection.
- DHCP failover. Two firewalls share a single address pool in hot-standby through the Kea high availability hook, so leases survive a node going down. The generated configuration loads the lease and HA hook libraries shipped with Debian Kea.
- Recursive DNS. Unbound resolver with DNSSEC, forwarders and local records. UI present, backend being ported.
VPN 82%
- WireGuard. The native Linux wg device and its routing are set up through iproute2; configuration pages and key management come from OPNsense. Peers with a hostname endpoint are re-resolved on a systemd timer, so a tunnel recovers when the remote address changes, and each peer reports an online or offline status with the age of its last handshake, while every tunnel summarises how many peers it has and how many are currently online.
- OpenVPN. tun / tap devices and runtime interface setup ported to iproute2.
- IPsec (strongSwan 6). Site-to-site (policy-based) and routed (VTI) tunnels run on the in-kernel XFRM stack: charon runs under systemd, and routed tunnels bind their security associations to ipsec xfrm interfaces through a matching interface id. Configuration pages and the built-in PKI (CA, leaf certificates, CRL) come from OPNsense.
- The raw SAD and SPD diagnostic panels read the kernel XFRM stack through ip xfrm, with per-entry deletion, so they work on Linux without the FreeBSD setkey tool.
- The strongSwan up/down handler is fully Linux-native: routed tunnels rely on the xfrm interface created at apply time, and manual security policies set on a phase 2 are installed through ip xfrm policy, reapplied idempotently when a tunnel comes up.
High availability 85%
- VRRP active / passive and connection-state sync (virtual IPs sharing an interface and group id collapse into one instance, no TCP reset on takeover).
- This replaces the OPNsense CARP / pfsync stack with keepalived (VRRP) and conntrackd on Linux. Virtual IPs are rendered as keepalived instances and the state channel as conntrackd; advskew maps to the VRRP priority, and status, maintenance mode and enable / disable are wired into the UI through a role notify hook. A failed service demotes its node so a healthy peer takes the virtual IPs. Virtual IPs that a node should own fail over together through a keepalived sync group, so a single link or service failure cannot split the cluster across both nodes. Every generated keepalived configuration is validated before it is applied, so a bad change cannot take the cluster down. Live failover, including service-failure takeover and recovery, is validated on a two-node cluster; long-run state-sync soak testing in progress.
- VRRP can run over unicast with a pinned source address for segments that filter multicast, common on cloud and virtualised bridges, and a master periodically re-announces each virtual IP so downstream switches keep a fresh address entry and the post-failover blackout stays short.
Observability 75%
- Dashboard. CPU, memory, disk, swap and per-interface throughput, read from /proc and refreshed live.
- Service state. Start, stop and restart of MurOS services through systemd, from the UI.
- Firewall live log. Pass and block decisions are logged by nftables and streamed live to the UI through the system journal (journald); each line carries the action and the rule that matched, and the matching rule label is resolved from the configuration.
- Health graphs. CPU, memory and temperature history kept in round-robin databases, read from /proc and the thermal sensors.
- SNMP and notifications in progress, being ported to the Debian equivalents (snmpd, SMTP).
Diagnostic 90%
- Live tools. ping, traceroute, ARP / NDP and routing tables, read from iproute2 (ip neigh, ip route).
- Interface details and counters. Addresses, link state and per-interface statistics from ip addr and ip -s link.
- Ruleset inspection. The loaded nftables ruleset, viewable from the UI.
- Connection states. Inspect and flush live connections through conntrack.
- Packet capture. Start a capture per interface with a filter, then download or view the result; backed by tcpdump.
- Open sockets. Listening and connected sockets with the owning process, read from ss.
System 90%
- General. Hostname, time zone, locale, kernel and Debian version.
- Kernel modules and devices. Required modules (nf_tables, bridge, 8021q, ...) loaded with modprobe; device events handled by systemd-udevd.
- Backups. The whole configuration lives in a single config.xml. Download it, restore it, or keep dated copies.
- System DNS. /etc/resolv.conf, separate from the recursive resolver.
- Network time. Time sync runs on chrony. Upstream servers and pools, serving time to the LAN, interface binding and orphan mode are configured from the UI and written to the chrony daemon; the status page shows each source with its offset, jitter and delay read live from chrony.
- Maintenance. Reboot and shutdown, immediate or scheduled.
- Packages and updates. MurOS installs and updates as a Debian package from the MurOS apt repository; installed packages and available updates are read through dpkg and apt. The full upgrade flow is in progress.
HTTP access 90%
- Accounts. The web UI and SSH share the same accounts through PAM. Local accounts are real Debian accounts, created and synced with the shadow utilities (useradd, usermod, groupadd). root is the default administrator; grant or revoke web UI access per account.
- TOTP MFA. Standard RFC 6238, any authenticator app.
- Reachability at the firewall. The web UI listens on every interface; you decide who can reach it with a filter rule, the same way you expose any other service.
- HTTP / HTTPS ports. Configurable, with HTTP -> HTTPS redirect.
- TLS certificate. Upload an existing PEM cert + key, or generate a self-signed RSA 4096 in one click.
Console & SSH 90%
- Shared accounts. Console and SSH authenticate through Linux-PAM against the same MurOS accounts as the web UI.
- root by default. The root password is the one used for the web UI.
- Serial console. Enable a serial console at the chosen baud rate; it is wired through systemd (serial-getty), and the local video console stays available alongside it.
- sshd options from the UI (listen address, keys) are in progress.
Hardening 85%
- Network hardening defaults. A curated set of kernel parameters is applied at boot: ICMP redirect and source-route rejection, reverse-path martian logging, TCP SYN cookies, smurf protection and no IPv6 privacy addresses. IPv4 and IPv6 forwarding ship as a sysctl.d drop-in.
- System tunables editor. Add or override any kernel parameter from the UI; the values are applied live through sysctl and persisted in the configuration.
- HTTPS-only UI. The web interface is served over TLS, with a CSRF token and an HTTP referer check.
- Anti-lockout. A mandatory rule keeps SSH and the web UI reachable even under a default-deny ruleset.
- fail2ban and API rate limiting are in progress.