netcfg: add -connmark flag for DNAT reply routing

When VPN traffic is DNAT'd to local namespaces/VMs, reply packets have
a different source IP (namespace veth) so the policy route's
"from <VPN_IP>" rule doesn't match. CONNMARK marks all connections
arriving on the VPN interface and restores the mark on reply packets,
routing them back through the tunnel via fwmark rule.

New flag: -connmark (requires -policy-route-table)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Git Sagar 2026-06-07 01:00:43 +05:30
parent 857733863c
commit 51824b830e
5 changed files with 51 additions and 7 deletions

View file

@ -57,7 +57,7 @@ pkg/tap/
## CLI flags
Required: `-host`, `-user`
Optional: `-pass`, `-port` (443), `-hub` (DEFAULT), `-tap` (auto), `-mac`, `-plain-password`, `-insecure`, `-no-dhcp`, `-accept-default-gateway`, `-accept-static-routes`, `-accept-dns`, `-policy-route-table` (0=disabled), `-reconnect-delay` (5s)
Optional: `-pass`, `-port` (443), `-hub` (DEFAULT), `-tap` (auto), `-mac`, `-plain-password`, `-insecure`, `-no-dhcp`, `-accept-default-gateway`, `-accept-static-routes`, `-accept-dns`, `-policy-route-table` (0=disabled), `-connmark`, `-reconnect-delay` (5s)
## SoftEther protocol pitfalls
@ -96,6 +96,9 @@ Before connecting, resolves server hostname and adds `/32` route via current def
### Policy routing
`-policy-route-table N` adds `ip rule from <VPN_IP> table N` + `ip route replace default via <VPN_GW> dev <TAP> table N`. Needed when VPN server port-forwards to client — ensures reply packets go back through VPN tunnel, not default route.
### CONNMARK for DNAT reply routing
`-connmark` (requires `-policy-route-table`) adds iptables CONNMARK rules so DNAT'd connections (port forwards to namespaces/VMs) have replies routed back through the tunnel. Without this, replies from DNAT targets use the default route because their source IP doesn't match the `from <VPN_IP>` policy rule. CONNMARK marks incoming VPN connections and restores the mark on reply packets.
## Performance
- **RAM**: 4.6 MB RSS idle, flat under 97 Mbit/s load (vs SoftEther C client: ~23 MB across 4 processes)
@ -125,7 +128,7 @@ Equivalent softether-go command:
softether-go -host 65-20-68-5.ip.fresh.ipb.cloud -port 992 \
-user T0Eq5yf97gXy8Q -plain-password -insecure \
-tap india-pub-ip -mac 5E:3B:6F:63:A8:3E \
-policy-route-table 200
-policy-route-table 200 -connmark
```
To add as flake input: `softether-go.url = "git+https://git.sagar.ch/sagar/softether-go.git";`
@ -133,5 +136,5 @@ To add as flake input: `softether-go.url = "git+https://git.sagar.ch/sagar/softe
## Dependencies
- Go 1.24+, single dep: `golang.org/x/sys` (vendored)
- Runtime: `ip` (iproute2)
- Runtime: `ip` (iproute2), `iptables` (only for `-connmark`)
- `vendorHash = null` in flake.nix (deps are vendored)