# Egress of OpenVPN clients via a Hysteria2 tunnel (2026-09-30) Goal: all traffic of VPN clients leaves the internet through an exit node reached over an existing Hysteria2 client tunnel (`hytun`) on the VPN host. ``` OpenVPN client --udp/1194--> tun0 (172.20.1.1/24) -> ip rule 102: from 172.20.1.0/24 -> table 100 -> table 100: default dev hytun (metric 10), blackhole default (metric 1000) -> iptables nat POSTROUTING -s 172.20.1.0/24 -o hytun -j MASQUERADE -> hytun (TUN of the Hysteria2 client) --QUIC/UDP 443--> exit node --> Internet ``` ## Prerequisites - A running Hysteria2 client with a TUN device (`hytun`), a routing table (100) with `default dev hytun` and a `blackhole` fallback, and `rp_filter=2` (loose) on all/default/hytun (strict mode drops TUN replies). - Hysteria server-side `socks5`/`http` outbounds are TCP-only, so UDP needs TUN + policy routing, not a SOCKS chain. - The exit node needs no changes. ## Implementation (OpenRC service `ovpn-hytun`) `depend: need hysteria-route; before openvpn`. On start: ```sh sysctl -qw net.ipv4.ip_forward=1 ip rule add priority 102 from 172.20.1.0/24 lookup 100 iptables -t nat -A POSTROUTING -s 172.20.1.0/24 -o hytun -j MASQUERADE iptables -t mangle -A FORWARD -o hytun -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu # and -i hytun iptables -A FORWARD -s 172.20.1.0/24 ! -o hytun -j DROP # anti-leak ``` Rules are idempotent (`-C` before `-A`); `stop` removes them. Adjust `172.20.1.0/24` to the `server` network in `server.conf`. Persist `ip_forward` in `/etc/sysctl.d/`. Use POSIX `sh` in OpenRC scripts (no bash arrays). ## Properties - Only the VPN subnet enters the tunnel; SSH, OpenVPN's own port (1194) and management traffic use the main table. - If the Hysteria client dies, table 100 falls to `blackhole`: clients lose internet, they do not leak through `eth0`. - Clients get public DNS (e.g. 1.1.1.1) that is resolved through the same tunnel. ## Verification | Check | Result | |---|---| | Node: TCP and UDP (DNS) through `hytun` | works | | Reference (uid routed to `hytun`): external IP | exit node address | | Real VPN client: `https://ifconfig.me` | exit node address (end-to-end test passed) | | `ip rule`, `iptables -t nat -S POSTROUTING`, `rc-status` | rules present, services started | Testing tip: a network namespace test that reuses the VPN subnet conflicts with a live `tun0`; test with a real client or a different, temporary subnet added to the rules.