Wheelhouse docs

NAT#

Security → NAT shows the router's nat subtree as three tables — port forwards (destination NAT), 1:1 mappings (nat static) and source NAT — each row carrying the packet and byte counts the router reports for it. Clicking a row opens an editor for that rule; the two buttons in the header open the creation editors. Everything except the 1:1 editor stages set and delete commands for the Commit Bar; the 1:1 editor is switched off on this platform build, for a reason the page states on itself and this section explains in full.

Where the page gets its data#

WhatCallRefresh
All three tablesGET /api/nat/rules — the whole nat subtreeon load, and after every commit
CountersGET /api/nat/statsshow nat destination statistics and show nat source statisticsevery 5 seconds
The CLI viewGET /api/config/commands?path=["nat"]after every commit
The uplink modelGET /api/wan — used by the hairpin and 1:1 editors for the WAN address and the LAN sideon load; failures are tolerated
The forward chainGET /api/firewall/rules — so the accept rule the forward editor offers cannot collide with an existing ruleon load

The nat subtree is IPv4. Nothing on this page reads or writes an IPv6 NAT tree — agent/main.go handleNatRules.

The three tables#

Port forwards (DNAT)#

Rules under nat destination rule <n>. Columns: #, Description, In (the inbound interface, or any), Port (the matched destination port, or any), Proto, Translates to (the translation address, with :port appended when the rule translates the port too), Packets, Bytes.

The empty state gives you the four commands a minimal forward consists of, and says the sentence that matters most on this page: NAT alone does not permit the flow. See port forwards.

1:1 NAT (static)#

Rules under nat static rule <n>. Columns: Rule, Description, Inbound, Public address, Inside address.

No counters: show nat … statistics is read for the destination and source tables only. This table is read-only on this build; see 1:1 NAT for why, and for the console commands the panel hands you instead.

Source NAT#

Rules under nat source rule <n>. Columns: #, Description, Out (the outbound interface, or any), Source (the matched source address, or any), Translation (the translation address, or the word masquerade when the rule has none), Packets, Bytes. See source NAT.

How a row is read#

Each table row is built from one configuration object, with a few shapes normalised:

  • nat static names its inbound interface as a plain leafinbound-interface eth1 — where nat destination uses inbound-interface name eth1. The page reads both.
  • The matched side depends on the direction: destination and static rules match on destination address / destination port, source rules on source address / source port. The editor relabels its fields to match.
  • protocol defaults to all in the table when the rule does not set one.
  • A source rule with no translation address is displayed as masquerade.

Counters#

show nat destination statistics and show nat source statistics are parsed into rows keyed by rule number, and joined onto the table by direction and number (agent/opmode.go handleNatStats). Unlike the firewall page, a failed read here is not distinguished from zero: both show 0. If a rule you expect to be busy reads zero, check the counters on the router before concluding the rule is not matching.

The rule editor#

Clicking a destination or source row opens a panel with:

  • Live counters — packets and bytes for the rule.
  • Edit — inbound or outbound interface, protocol, matched address, matched port, translation address, translation port, Log matches, Disabled, description.
  • This stages — the commands your edits have produced.
  • Config object — the rule as the router returned it, as JSON.

The footer has Stage n changes and Delete rule. The commands are built the same way the firewall editor builds them: a changed field becomes a set, a cleared field becomes a delete, an unchanged field produces nothing.

Everything the add editor can set, this panel can change. That is a deliberate repair: it used to offer two fields — translation address and description — against an add editor with ten, so a forward this product created could not be re-pointed at a different port from the UI that made it (ui/src/pages/Nat.tsx).

The CLI view#

The CLI toggle replaces the three tables with the nat subtree rendered as set commands by the router itself, through GET /api/config/commands. It is the fastest way to copy a working configuration to another router, and the fastest way to see rules the tables have normalised.

What you need to change anything#

+ Add forward is gated on the operator role. + Add 1:1 is gated on the operator role and on the static-NAT block, so it is disabled for everyone on this build, with the reason as its tooltip. Staging is refused server-side without the operator role and a usable licence.

Every path this page stages begins nat or, for the accept rule the forward editor offers, firewall — both of which the Commit Bar treats as changes that can cut you off, so it recommends commit-confirm for the batch (ui/src/lib/format.ts isDangerousPath).

See also#

Checked against#

ui/src/pages/Nat.tsx, ui/src/lib/api.ts, ui/src/lib/format.ts, agent/main.go, agent/opmode.go, agent/license.go.

Updated 2026-09-02 manual nat dnat snat