fix(migration): do not emit a NAT translation port for a port list
`set nat destination rule N translation port '16881,6881'` is rejected -- "16881,6881 is not a valid service name" -- because mapping a list of ports onto a list is ambiguous. `destination port` accepts the same list happily, which is why this only shows up on the translation side. All four UniFi port forwards map a port to itself, so translation port was redundant anyway: omitting it makes VyOS preserve the original port, which is exactly the intent. It is now emitted only when the forwarded port genuinely differs, and generation fails loudly rather than producing a config that will not commit if a differing port LIST ever appears. Found by loading vyos001's real running config onto the labsim router and applying the full delta to the candidate config without committing. Worth noting the delta had already passed a read-through: this one only surfaced by running it against a real VyOS of the same version. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DMVzWZgiKW2wquf5z8S1yH
This commit is contained in:
@@ -125,8 +125,20 @@ def build_delta(inv: dict, priority: int, wan_user: str) -> list[str]:
|
|||||||
f"set nat destination rule {rule} protocol {proto}",
|
f"set nat destination rule {rule} protocol {proto}",
|
||||||
f"set nat destination rule {rule} destination port '{p['dst_port']}'",
|
f"set nat destination rule {rule} destination port '{p['dst_port']}'",
|
||||||
f"set nat destination rule {rule} translation address {p['fwd']}",
|
f"set nat destination rule {rule} translation address {p['fwd']}",
|
||||||
f"set nat destination rule {rule} translation port '{p['fwd_port']}'",
|
|
||||||
]
|
]
|
||||||
|
# `destination port` accepts a comma list but `translation port` does
|
||||||
|
# NOT -- "16881,6881 is not a valid service name" -- because mapping a
|
||||||
|
# list onto a list is ambiguous. Every forward here maps a port to
|
||||||
|
# itself, and omitting translation port makes VyOS preserve the
|
||||||
|
# original, which is exactly right. Only emit it when it genuinely
|
||||||
|
# differs, and refuse rather than guess when a differing list appears.
|
||||||
|
if p["fwd_port"] != p["dst_port"]:
|
||||||
|
if "," in str(p["fwd_port"]) or "," in str(p["dst_port"]):
|
||||||
|
raise SystemExit(
|
||||||
|
f"port forward '{p['name']}' remaps a LIST of ports "
|
||||||
|
f"({p['dst_port']} -> {p['fwd_port']}). VyOS cannot express "
|
||||||
|
f"that in one rule; split it into one rule per port by hand.")
|
||||||
|
out.append(f"set nat destination rule {rule} translation port '{p['fwd_port']}'")
|
||||||
|
|
||||||
out += [
|
out += [
|
||||||
"",
|
"",
|
||||||
|
|||||||
Reference in New Issue
Block a user