# gre-panel:managed=1 # # The panel's port forwarding ruleset, rendered from the database. Every change # rewrites this file in full and applies it with a single nft transaction, so the # kernel never holds a partial ruleset. # # Everything the panel installs lives in the one table below. Replacing that table # replaces the panel's rules and touches nothing else on this host: rules belonging # to Docker, firewalld or anything else live in their own tables and are never read, # flushed or reordered from here. # # Every rule carries the comment grep:, which is what lets a rule read # back from the kernel be matched to the database row that generated it. # Declaring the table before flushing it makes this file work on a host that has # never seen it; flushing a table that does not exist is an error. table inet gre_panel flush table inet gre_panel table inet gre_panel { # Named counter objects, one pair per rule. Byte accounting reads these, # never the nat chains: a nat hook only ever sees the first packet of a # connection, so counting there would report connections as if they were # bytes and under-report traffic by orders of magnitude. counter route_1_rx { } counter route_1_tx { } chain prerouting { type nat hook prerouting priority dstnat; policy accept; # Destination NAT: traffic arriving for a rule is redirected to its destination. # route 1 "Web relay": tcp 203.0.113.10:2044 -> 198.51.100.20:2044, 198.51.100.21:2044, 198.51.100.22:2044 [nat masquerade] ip daddr 203.0.113.10 tcp dport 2044 dnat ip to numgen inc mod 10 map { 0-6 : 198.51.100.20 . 2044, 7-8 : 198.51.100.21 . 2044, 9 : 198.51.100.22 . 2044 } comment "grep:1" } chain postrouting { type nat hook postrouting priority srcnat; policy accept; # Source NAT. Absent for a rule whose NAT mode is None, which preserves the # client address and needs the return path to come back through this server. # route 1 "Web relay": tcp 203.0.113.10:2044 -> 198.51.100.20:2044, 198.51.100.21:2044, 198.51.100.22:2044 [nat masquerade] ip daddr 198.51.100.20 tcp dport 2044 masquerade comment "grep:1" ip daddr 198.51.100.21 tcp dport 2044 masquerade comment "grep:1" ip daddr 198.51.100.22 tcp dport 2044 masquerade comment "grep:1" } chain forward { type filter hook forward priority filter; policy accept; # Forward permission. The established/related rule covers the return direction, # so no reverse rule matching on source port is emitted: conntrack expresses the # intent exactly, and matching on the far end's source port would accept traffic # that belongs to no flow this server ever started. ct state established,related accept comment "gre-panel:structural" # route 1 "Web relay": tcp 203.0.113.10:2044 -> 198.51.100.20:2044, 198.51.100.21:2044, 198.51.100.22:2044 [nat masquerade] ip daddr 198.51.100.20 tcp dport 2044 accept comment "grep:1" ip daddr 198.51.100.21 tcp dport 2044 accept comment "grep:1" ip daddr 198.51.100.22 tcp dport 2044 accept comment "grep:1" } chain accounting { type filter hook forward priority filter - 10; policy accept; # Accounting. These rules carry no verdict, so they count and fall through # without influencing policy, and they sit at their own priority so they see # traffic whatever the forward chain decides. # route 1 "Web relay": tcp 203.0.113.10:2044 -> 198.51.100.20:2044, 198.51.100.21:2044, 198.51.100.22:2044 [nat masquerade] ip daddr 198.51.100.20 tcp dport 2044 counter name "route_1_tx" comment "grep:1" ip saddr 198.51.100.20 tcp sport 2044 counter name "route_1_rx" comment "grep:1" ip daddr 198.51.100.21 tcp dport 2044 counter name "route_1_tx" comment "grep:1" ip saddr 198.51.100.21 tcp sport 2044 counter name "route_1_rx" comment "grep:1" ip daddr 198.51.100.22 tcp dport 2044 counter name "route_1_tx" comment "grep:1" ip saddr 198.51.100.22 tcp sport 2044 counter name "route_1_rx" comment "grep:1" } }