# 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 { } # Dynamic sets backing the per-source connection and rate limits. set route_1_conn { type ipv4_addr size 65535 flags dynamic } set route_1_rate { type ipv4_addr size 65535 flags dynamic, timeout timeout 1m } chain prerouting { type nat hook prerouting priority dstnat; policy accept; # Destination NAT: traffic arriving for a rule is redirected to its destination. # route 1 "Everything at once": both 203.0.113.10:2044 -> 172.31.7.2:2044, 172.31.7.6:2044 [nat snat] ip daddr 203.0.113.10 tcp dport 2044 iifname "eth0" ip saddr { 10.0.0.0/8 } dnat ip to numgen inc mod 4 map { 0-2 : 172.31.7.2 . 2044, 3 : 172.31.7.6 . 2044 } comment "grep:1" ip daddr 203.0.113.10 udp dport 2044 iifname "eth0" ip saddr { 10.0.0.0/8 } dnat ip to numgen inc mod 4 map { 0-2 : 172.31.7.2 . 2044, 3 : 172.31.7.6 . 2044 } comment "grep:1" } chain output { type nat hook output priority -100; policy accept; # The prerouting hook never sees traffic this host generates itself, so a rule # that should also serve local processes is repeated here. # route 1 "Everything at once": both 203.0.113.10:2044 -> 172.31.7.2:2044, 172.31.7.6:2044 [nat snat] ip daddr 203.0.113.10 tcp dport 2044 iifname "eth0" ip saddr { 10.0.0.0/8 } dnat ip to numgen inc mod 4 map { 0-2 : 172.31.7.2 . 2044, 3 : 172.31.7.6 . 2044 } comment "grep:1" ip daddr 203.0.113.10 udp dport 2044 iifname "eth0" ip saddr { 10.0.0.0/8 } dnat ip to numgen inc mod 4 map { 0-2 : 172.31.7.2 . 2044, 3 : 172.31.7.6 . 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 "Everything at once": both 203.0.113.10:2044 -> 172.31.7.2:2044, 172.31.7.6:2044 [nat snat] ip daddr 172.31.7.2 tcp dport 2044 snat ip to 203.0.113.10 comment "grep:1" ip daddr 172.31.7.6 tcp dport 2044 snat ip to 203.0.113.10 comment "grep:1" ip daddr 172.31.7.2 udp dport 2044 snat ip to 203.0.113.10 comment "grep:1" ip daddr 172.31.7.6 udp dport 2044 snat ip to 203.0.113.10 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 "Everything at once": both 203.0.113.10:2044 -> 172.31.7.2:2044, 172.31.7.6:2044 [nat snat] ip daddr 172.31.7.2 tcp dport 2044 ct state new add @route_1_conn { ip saddr ct count over 25 } drop comment "grep:1" ip daddr 172.31.7.2 tcp dport 2044 ct state new add @route_1_rate { ip saddr limit rate over 120/minute } drop comment "grep:1" ip daddr 172.31.7.2 tcp dport 2044 ct state new limit rate 5/minute log prefix "gre-panel route 1: " comment "grep:1" ip daddr 172.31.7.2 tcp dport 2044 ip saddr { 10.0.0.0/8 } accept comment "grep:1" ip daddr 172.31.7.6 tcp dport 2044 ct state new add @route_1_conn { ip saddr ct count over 25 } drop comment "grep:1" ip daddr 172.31.7.6 tcp dport 2044 ct state new add @route_1_rate { ip saddr limit rate over 120/minute } drop comment "grep:1" ip daddr 172.31.7.6 tcp dport 2044 ct state new limit rate 5/minute log prefix "gre-panel route 1: " comment "grep:1" ip daddr 172.31.7.6 tcp dport 2044 ip saddr { 10.0.0.0/8 } accept comment "grep:1" ip daddr 172.31.7.2 udp dport 2044 ct state new add @route_1_conn { ip saddr ct count over 25 } drop comment "grep:1" ip daddr 172.31.7.2 udp dport 2044 ct state new add @route_1_rate { ip saddr limit rate over 120/minute } drop comment "grep:1" ip daddr 172.31.7.2 udp dport 2044 ct state new limit rate 5/minute log prefix "gre-panel route 1: " comment "grep:1" ip daddr 172.31.7.2 udp dport 2044 ip saddr { 10.0.0.0/8 } accept comment "grep:1" ip daddr 172.31.7.6 udp dport 2044 ct state new add @route_1_conn { ip saddr ct count over 25 } drop comment "grep:1" ip daddr 172.31.7.6 udp dport 2044 ct state new add @route_1_rate { ip saddr limit rate over 120/minute } drop comment "grep:1" ip daddr 172.31.7.6 udp dport 2044 ct state new limit rate 5/minute log prefix "gre-panel route 1: " comment "grep:1" ip daddr 172.31.7.6 udp dport 2044 ip saddr { 10.0.0.0/8 } 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 "Everything at once": both 203.0.113.10:2044 -> 172.31.7.2:2044, 172.31.7.6:2044 [nat snat] ip daddr 172.31.7.2 tcp dport 2044 counter name "route_1_tx" comment "grep:1" ip saddr 172.31.7.2 tcp sport 2044 counter name "route_1_rx" comment "grep:1" ip daddr 172.31.7.6 tcp dport 2044 counter name "route_1_tx" comment "grep:1" ip saddr 172.31.7.6 tcp sport 2044 counter name "route_1_rx" comment "grep:1" ip daddr 172.31.7.2 udp dport 2044 counter name "route_1_tx" comment "grep:1" ip saddr 172.31.7.2 udp sport 2044 counter name "route_1_rx" comment "grep:1" ip daddr 172.31.7.6 udp dport 2044 counter name "route_1_tx" comment "grep:1" ip saddr 172.31.7.6 udp sport 2044 counter name "route_1_rx" comment "grep:1" } chain local_out_accounting { type filter hook output priority filter - 10; policy accept; # Accounting for traffic this server originates itself, which the forward hook # never sees. It references the same counters as the chain above, so a rule's # total is its whole total rather than the forwarded half of it. # route 1 "Everything at once": both 203.0.113.10:2044 -> 172.31.7.2:2044, 172.31.7.6:2044 [nat snat] ip daddr 172.31.7.2 tcp dport 2044 counter name "route_1_tx" comment "grep:1" ip daddr 172.31.7.6 tcp dport 2044 counter name "route_1_tx" comment "grep:1" ip daddr 172.31.7.2 udp dport 2044 counter name "route_1_tx" comment "grep:1" ip daddr 172.31.7.6 udp dport 2044 counter name "route_1_tx" comment "grep:1" } chain local_in_accounting { type filter hook input priority filter - 10; policy accept; # The return direction of the same traffic. Replies to a locally-originated # connection are delivered to a socket on this host, so they arrive at input # rather than being forwarded. # route 1 "Everything at once": both 203.0.113.10:2044 -> 172.31.7.2:2044, 172.31.7.6:2044 [nat snat] ip saddr 172.31.7.2 tcp sport 2044 counter name "route_1_rx" comment "grep:1" ip saddr 172.31.7.6 tcp sport 2044 counter name "route_1_rx" comment "grep:1" ip saddr 172.31.7.2 udp sport 2044 counter name "route_1_rx" comment "grep:1" ip saddr 172.31.7.6 udp sport 2044 counter name "route_1_rx" comment "grep:1" } chain mss_clamp { type filter hook forward priority mangle; policy accept; # MSS clamping. A relay whose destination is reached across a tunnel hands the # client an MSS the path cannot carry; connections then establish and stall on # the first large transfer. The mask form matches a SYN without RST, so a # reset is not rewritten. # route 1 "Everything at once": both 203.0.113.10:2044 -> 172.31.7.2:2044, 172.31.7.6:2044 [nat snat] ip daddr 172.31.7.2 tcp dport 2044 tcp flags syn / syn,rst tcp option maxseg size set rt mtu comment "grep:1" ip daddr 172.31.7.6 tcp dport 2044 tcp flags syn / syn,rst tcp option maxseg size set rt mtu comment "grep:1" } chain marking { type filter hook prerouting priority mangle; policy accept; # Firewall marks, for integration with policy routing. # route 1 "Everything at once": both 203.0.113.10:2044 -> 172.31.7.2:2044, 172.31.7.6:2044 [nat snat] ip daddr 203.0.113.10 tcp dport 2044 iifname "eth0" ip saddr { 10.0.0.0/8 } meta mark set 0x1f comment "grep:1" ip daddr 203.0.113.10 udp dport 2044 iifname "eth0" ip saddr { 10.0.0.0/8 } meta mark set 0x1f comment "grep:1" } }