1:1 NAT#
A 1:1 mapping ties one public address to one inside host in both directions, every port,
without a rule per service. Wheelhouse reads those mappings: the middle table on the NAT
page lists every rule under nat static rule <n>, and clicking one opens a panel showing
it. Wheelhouse does not write them on this platform build. Committing nat static
through the router's HTTP API stops the API process — the CLI accepts the same lines — so
the editor is disabled with that reason on the page, and the panel hands you the console
commands instead.
The platform gap#
What that means in the UI:
- + Add 1:1 is disabled for everyone, with the explanation as its tooltip.
- The 1:1 NAT (static) panel carries the same explanation as a line of warning text above the table.
- Clicking a row opens a read-only panel: the rule's fields, and the commands to remove it from the console.
Deleting is blocked for the same reason as adding. A delete of a nat static rule is also a
nat static commit, and it takes the API down exactly as an add does — so the panel offers
no delete button, only the commands.
The table#
| Column | From |
|---|---|
| Rule | The rule number. |
| Description | description. |
| Inbound | inbound-interface. Note the shape: nat static names its interface as a plain leaf, where nat destination uses inbound-interface name. The page reads both forms. |
| Public address | destination address — the address arriving on the uplink. |
| Inside address | translation address — the host behind the router. |
There are no counters in this table: the statistics endpoint reads
show nat destination statistics and show nat source statistics only
(agent/opmode.go handleNatStats).
The read-only panel#
Clicking a row opens a side panel with the warning, a summary of the rule — inbound interface, public address, inside address, description — and a From the console block containing exactly what to type:
configure
delete nat static rule 100
commit
saveThe footer button reads Editing is off for 1:1 rules and is disabled.
Writing one by hand#
From the console, a mapping of a second provider address to an inside host:
configure
set nat static rule 100 inbound-interface eth1
set nat static rule 100 destination address 203.0.113.10
set nat static rule 100 translation address 10.0.10.30
set nat static rule 100 description "mail server"
commit
saveTwo conditions that are not the router's to arrange:
- The public address must already be routed to this router — a second address from the provider, or a delegated prefix. A 1:1 rule does not make the internet send you an address you were not given.
- The firewall still decides what gets in. A mapping translates; it does not permit. The forward chain needs accept rules for the inside host, exactly as a port forward does. Those you can write from the UI.
The rules appear in the table on the next read, and the page will show them for as long as they exist.
When it is fixed#
The block is a single constant in the page source. When a platform build commits
nat static through the API without taking the API process down, the editor behind it is
already written: interface, public address, inside address, description and a Log
translations checkbox, staging the same commands as above. Until then this page documents a
table, not an editor.
See also#
- NAT — the page, and the two tables that are editable.
- Port forwards — the per-service alternative, which the UI does write.
- Firewall — rules — the accept rules an inside host still needs.
- What is finished, and what is not — this is on that list.
Checked against#
ui/src/pages/Nat.tsx,
agent/opmode.go,
agent/main.go,
PLAN.md.