`nat cgnat` checks its input too little. Values the CLI accepts make the commit fail with a Python traceback instead of an error message. Worse, some valid-looking configurations commit fine but give the same external address and port block to two subscribers. All cases below were reproduced on rolling (vyos-1x 999.0-15088-gce2baa317).
All examples start from this working configuration:
```
set nat cgnat pool external EXT range 192.0.2.1/32
set nat cgnat pool internal INT range 100.64.0.0/29
set nat cgnat rule 10 source pool INT
set nat cgnat rule 10 translation pool EXT
```
**Port range given as a single port or service name.** `external-port-range` uses the generic port-range validator, which also accepts `2000` or `http`. The handler expects `start-end` and crashes with `ValueError: not enough values to unpack` or `invalid literal for int()`. A reversed range such as `3000-1000` is accepted too and only fails later with a misleading "not enough ports" message.
```
set nat cgnat pool external EXT external-port-range 2000
commit
```
**Range with host bits set.** Both pool `range` nodes include the `ipv4-host` validator, so `100.64.0.1/29` is accepted. Turning it into a network then fails
with `ValueError: 100.64.0.1/29 has host bits set`.
```
set nat cgnat pool internal INT range 100.64.0.1/29
commit
```
**Empty translation node.** A rule with `translation` but no `pool` below it passes verify and crashes with `KeyError: 'pool'`. An empty `source` node is already caught.
```
delete nat cgnat rule 10 translation pool
set nat cgnat rule 10 translation
commit
```
**Same external address used twice.** Ports are allocated range by range, starting over at the first port of each range. If an external address is in two ranges, or in the pools of two different rules, it is handed out twice, so two subscribers share the same external address and port block. The commit succeeds, so nothing tells the operator.
```
set nat cgnat pool external EXT2 range 192.0.2.1/32
set nat cgnat pool internal INT2 range 100.64.1.0/31
set nat cgnat rule 20 source pool INT2
set nat cgnat rule 20 translation pool EXT2
commit
```
```
sudo nft list map ip cgnat tcp_nat_map
100.64.0.0 : 192.0.2.1 . 1024-3023, ...
100.64.1.0 : 192.0.2.1 . 1024-3023, ...
```
The same happens inside one pool, e.g. `range 192.0.2.1/32` plus `range 192.0.2.0/31`. The address is also counted twice in the capacity check, so the pool looks bigger than it is.
**Overlapping internal ranges.**
An internal address in two ranges (one pool, or pools of two rules) produces overlapping nftables map elements. The commit then fails only at the `nft --check` step with "Configuration file errors encountered!", which says nothing about the cause.
```
set nat cgnat pool internal INT range 100.64.0.0-100.64.0.7
```
**External range overlapping an internal range.**
Nothing stops an external pool from using subscriber addresses, so one subscriber can be translated to another subscriber's address. This commits without complaint:
```
set nat cgnat pool external EXT range 100.64.0.4/30
commit
```
**Op-mode crash with one port per subscriber.**
With `per-user-limit port 1`, nftables stores each allocation as a single port instead of a range, and `show nat cgnat allocation` fails with `TypeError: 'int' object is not subscriptable`.
```
set nat cgnat pool external EXT per-user-limit port 1
commit
run show nat cgnat allocation
```
Seen but not addressed here: commit time grows with the number of subscribers (a /16 internal pool takes about 6 s, almost all of it nftables loading four maps of 65536 elements each). Also, changing only a rule's translation pool does not clear existing conntrack entries.