=== STEP_033H DSCP CANARY PLAN === timestamp=20260708-112434 mode=read-only / package only idea: VM100 tags one client before NAT with DSCP cs1; VM101 converts DSCP cs1 from 10.200.0.1/iif eth1 to fwmark 0x203 -> vpn3 remote_changes=none === VM100 read-only client/NAT inventory === Wed Jul 8 11:24:35 UTC 2026 === ip -br addr === lo UNKNOWN 127.0.0.1/8 ::1/128 eth0 UP 10.201.0.1/24 fe80::be24:11ff:fe94:bbfb/64 eth1 UP eth2 UP 10.200.0.1/24 fe80::be24:11ff:fee4:6cfb/64 br-lan UP 10.71.100.1/24 fe80::be24:11ff:feee:7d14/64 wg_paid UNKNOWN 10.253.1.1/16 wg_remote UNKNOWN 10.250.100.1/24 === routes === default via 10.201.0.2 dev eth0 proto static metric 10 default via 10.200.0.2 dev eth2 proto static metric 20 10.71.100.0/24 dev br-lan proto kernel scope link src 10.71.100.1 10.200.0.0/24 dev eth2 proto static scope link metric 20 10.201.0.0/24 dev eth0 proto static scope link metric 10 10.250.100.0/24 dev wg_remote proto kernel scope link src 10.250.100.1 10.250.100.2 dev wg_remote proto static scope link 10.250.100.3 dev wg_remote proto static scope link 10.250.100.4 dev wg_remote proto static scope link 10.250.100.121 dev wg_remote proto static scope link 10.253.0.0/16 dev wg_paid proto kernel scope link src 10.253.1.1 === DHCP leases === === UCI dhcp hosts/leases hints === dhcp.@dnsmasq[0].rebind_localhost='1' dhcp.@dnsmasq[0].expandhosts='1' dhcp.@dnsmasq[0].leasefile='/tmp/dhcp.leases' dhcp.lan.leasetime='12h' dhcp.odhcpd.leasefile='/tmp/hosts/odhcpd' dhcp.odhcpd.leasetrigger='/usr/sbin/odhcpd-update' dhcp.@host[0]=host dhcp.@host[0].name='wg-guest' dhcp.@host[0].ip='10.71.1.189' dhcp.@host[0].mac='BC:24:11:81:3F:F6' dhcp.@host[1]=host dhcp.@host[1].name='vm105-control-panel' dhcp.@host[1].mac='bc:24:11:97:99:24' dhcp.@host[1].ip='10.71.100.105' dhcp.@host[1].leasetime='infinite' === firewall zones masq/forwarding === firewall.@zone[0]=zone firewall.@zone[0].name='lan' firewall.@zone[0].input='ACCEPT' firewall.@zone[0].output='ACCEPT' firewall.@zone[0].forward='ACCEPT' firewall.@zone[0].network='lan' firewall.@zone[1]=zone firewall.@zone[1].name='transit_direct' firewall.@zone[1].input='ACCEPT' firewall.@zone[1].output='ACCEPT' firewall.@zone[1].forward='REJECT' firewall.@zone[1].network='transit_direct' firewall.@zone[1].masq='1' firewall.@zone[1].mtu_fix='1' firewall.@forwarding[0]=forwarding firewall.@forwarding[0].src='lan' firewall.@forwarding[0].dest='transit_direct' firewall.@zone[2]=zone firewall.@zone[2].name='transit_vpn' firewall.@zone[2].input='ACCEPT' firewall.@zone[2].output='ACCEPT' firewall.@zone[2].forward='REJECT' firewall.@zone[2].masq='1' firewall.@zone[2].mtu_fix='1' firewall.@zone[2].network='transit_vpn' firewall.@forwarding[1]=forwarding firewall.@forwarding[1].src='lan' firewall.@forwarding[1].dest='transit_vpn' firewall.@zone[3]=zone firewall.@zone[3].name='remote_in' firewall.@zone[3].input='ACCEPT' firewall.@zone[3].output='ACCEPT' firewall.@zone[3].forward='ACCEPT' firewall.@zone[3].network='wg_remote' firewall.@forwarding[2]=forwarding firewall.@forwarding[2].src='remote_in' firewall.@forwarding[2].dest='lan' firewall.@forwarding[3]=forwarding firewall.@forwarding[3].src='remote_in' firewall.@forwarding[3].dest='transit_direct' firewall.@forwarding[4]=forwarding firewall.@forwarding[4].src='remote_in' firewall.@forwarding[4].dest='transit_vpn' firewall.@rule[0].src='transit_direct' firewall.@rule[0].name='Allow-WG-Remote-In' firewall.@rule[1].name='ALLOW_OWNER_DNS_VM100' firewall.@rule[1].src='remote_in' firewall.@rule[2].name='ALLOW_OWNER_WGEASY_UI' firewall.@rule[2].src='remote_in' firewall.@rule[2].dest='lan' firewall.@rule[3].name='BLOCK_OWNER_VM100_ROUTER' firewall.@rule[3].src='remote_in' firewall.@rule[4].name='BLOCK_OWNER_VM101' firewall.@rule[4].src='remote_in' firewall.@rule[4].dest='lan' firewall.@rule[5].name='BLOCK_OWNER_PROXMOX' firewall.@rule[5].src='remote_in' firewall.@rule[5].dest='lan' firewall.@rule[6].name='BLOCK_OWNER_VM103_EXCEPT_UI' firewall.@rule[6].src='remote_in' firewall.@rule[6].dest='lan' firewall.wg_paid=zone firewall.wg_paid.name='wg_paid' firewall.wg_paid.network='wg_paid' firewall.wg_paid_to_transit_direct=forwarding firewall.wg_paid_to_transit_direct.src='wg_paid' firewall.wg_paid_to_transit_direct.dest='transit_direct' firewall.wg_paid_to_transit_vpn=forwarding firewall.wg_paid_to_transit_vpn.src='wg_paid' firewall.wg_paid_to_transit_vpn.dest='transit_vpn' firewall.allow_wg_paid_51830.name='Allow-WG-Paid-51830' === nft NAT snippets === set pbr_transit_direct_4_dst_ip_user { 122.10.164.0-122.10.195.255, 122.10.200.0-122.10.219.255, 194.110.71.0/24, 194.110.80.0/22, set pbr_transit_direct_4_src_ip_user { set pbr_transit_direct_4_src_mac_user { type ether_addr set pbr_transit_vpn_4_dst_ip_user { set pbr_transit_vpn_4_src_ip_user { elements = { 10.71.100.0/24, 10.250.100.0/24, set pbr_transit_vpn_4_src_mac_user { type ether_addr chain wg_remote_snat_to_pc { type nat hook postrouting priority srcnat - 1; policy accept; ip saddr 10.250.0.0/24 ip daddr 192.168.30.64 oifname "br-lan" counter packets 0 bytes 0 snat ip to 192.168.30.1 comment "wg_remote_to_pc64_snat" iifname "br-lan" jump input_lan comment "!fw4: Handle lan IPv4/IPv6 input traffic" iifname "eth0" jump input_transit_direct comment "!fw4: Handle transit_direct IPv4/IPv6 input traffic" iifname "eth2" jump input_transit_vpn comment "!fw4: Handle transit_vpn IPv4/IPv6 input traffic" iifname "br-lan" jump forward_lan comment "!fw4: Handle lan IPv4/IPv6 forward traffic" iifname "eth0" jump forward_transit_direct comment "!fw4: Handle transit_direct IPv4/IPv6 forward traffic" iifname "eth2" jump forward_transit_vpn comment "!fw4: Handle transit_vpn IPv4/IPv6 forward traffic" oifname "br-lan" jump output_lan comment "!fw4: Handle lan IPv4/IPv6 output traffic" oifname "eth0" jump output_transit_direct comment "!fw4: Handle transit_direct IPv4/IPv6 output traffic" oifname "eth2" jump output_transit_vpn comment "!fw4: Handle transit_vpn IPv4/IPv6 output traffic" chain prerouting { type filter hook prerouting priority filter; policy accept; iifname "br-lan" jump helper_lan comment "!fw4: Handle lan IPv4/IPv6 helper assignment" chain input_lan { jump accept_from_lan chain output_lan { jump accept_to_lan chain forward_lan { jump accept_to_transit_direct comment "!fw4: Accept lan to transit_direct forwarding" jump accept_to_transit_vpn comment "!fw4: Accept lan to transit_vpn forwarding" jump accept_to_lan chain helper_lan { chain accept_from_lan { iifname "br-lan" counter packets 234 bytes 16415 accept comment "!fw4: accept lan IPv4/IPv6 traffic" chain accept_to_lan { oifname "br-lan" counter packets 483 bytes 29032 accept comment "!fw4: accept lan IPv4/IPv6 traffic" chain reject_to_lan { oifname "br-lan" counter packets 0 bytes 0 jump handle_reject comment "!fw4: reject lan IPv4/IPv6 traffic" chain input_transit_direct { ip daddr 10.201.0.1 udp dport 51820 counter packets 0 bytes 0 accept comment "!fw4: Allow-WG-Remote-In" jump accept_from_transit_direct chain output_transit_direct { jump accept_to_transit_direct chain forward_transit_direct { jump reject_to_transit_direct chain accept_from_transit_direct { iifname "eth0" counter packets 23 bytes 1288 accept comment "!fw4: accept transit_direct IPv4/IPv6 traffic" chain accept_to_transit_direct { meta nfproto ipv4 oifname "eth0" ct state invalid counter packets 0 bytes 0 drop comment "!fw4: Prevent NAT leakage" oifname "eth0" counter packets 1250 bytes 90600 accept comment "!fw4: accept transit_direct IPv4/IPv6 traffic" chain reject_to_transit_direct { oifname "eth0" counter packets 0 bytes 0 jump handle_reject comment "!fw4: reject transit_direct IPv4/IPv6 traffic" chain input_transit_vpn { jump accept_from_transit_vpn chain output_transit_vpn { jump accept_to_transit_vpn chain forward_transit_vpn { jump reject_to_transit_vpn chain accept_from_transit_vpn { iifname "eth2" counter packets 23 bytes 1288 accept comment "!fw4: accept transit_vpn IPv4/IPv6 traffic" chain accept_to_transit_vpn { meta nfproto ipv4 oifname "eth2" ct state invalid counter packets 0 bytes 0 drop comment "!fw4: Prevent NAT leakage" oifname "eth2" counter packets 6 bytes 544 accept comment "!fw4: accept transit_vpn IPv4/IPv6 traffic" chain reject_to_transit_vpn { oifname "eth2" counter packets 0 bytes 0 jump handle_reject comment "!fw4: reject transit_vpn IPv4/IPv6 traffic" ip saddr 10.250.1.3 ip daddr 10.71.1.189 tcp dport 51822 counter packets 0 bytes 0 jump accept_to_lan comment "!fw4: ALLOW_OWNER_WGEASY_UI" ip saddr 10.250.1.3 ip daddr 10.71.1.2 counter packets 0 bytes 0 jump reject_to_lan comment "!fw4: BLOCK_OWNER_VM101" ip saddr 10.250.1.3 ip daddr 10.71.1.222 counter packets 0 bytes 0 jump reject_to_lan comment "!fw4: BLOCK_OWNER_PROXMOX" ip saddr 10.250.1.3 ip daddr 10.71.1.189 counter packets 0 bytes 0 jump reject_to_lan comment "!fw4: BLOCK_OWNER_VM103_EXCEPT_UI" jump accept_to_lan comment "!fw4: Accept remote_in to lan forwarding" jump accept_to_transit_direct comment "!fw4: Accept remote_in to transit_direct forwarding" jump accept_to_transit_vpn comment "!fw4: Accept remote_in to transit_vpn forwarding" jump accept_to_transit_direct comment "!fw4: Accept wg_paid to transit_direct forwarding" jump accept_to_transit_vpn comment "!fw4: Accept wg_paid to transit_vpn forwarding" type nat hook prerouting priority dstnat; policy accept; type nat hook postrouting priority srcnat; policy accept; oifname "eth0" jump srcnat_transit_direct comment "!fw4: Handle transit_direct IPv4/IPv6 srcnat traffic" oifname "eth2" jump srcnat_transit_vpn comment "!fw4: Handle transit_vpn IPv4/IPv6 srcnat traffic" chain srcnat_transit_direct { meta nfproto ipv4 masquerade comment "!fw4: Masquerade IPv4 transit_direct traffic" chain srcnat_transit_vpn { meta nfproto ipv4 masquerade comment "!fw4: Masquerade IPv4 transit_vpn traffic" chain raw_prerouting { type filter hook prerouting priority raw; policy accept; chain mangle_prerouting { type filter hook prerouting priority mangle; policy accept; jump pbr_prerouting chain mangle_postrouting { type filter hook postrouting priority mangle; policy accept; oifname "eth0" tcp flags & (fin | syn | rst) == syn tcp option maxseg size set rt mtu comment "!fw4: Zone transit_direct IPv4/IPv6 egress MTU fixing" oifname "eth2" tcp flags & (fin | syn | rst) == syn tcp option maxseg size set rt mtu comment "!fw4: Zone transit_vpn IPv4/IPv6 egress MTU fixing" iifname "eth0" tcp flags & (fin | syn | rst) == syn tcp option maxseg size set rt mtu comment "!fw4: Zone transit_direct IPv4/IPv6 ingress MTU fixing" iifname "eth2" tcp flags & (fin | syn | rst) == syn tcp option maxseg size set rt mtu comment "!fw4: Zone transit_vpn IPv4/IPv6 ingress MTU fixing" chain pbr_prerouting { ip saddr 10.250.100.0/24 ip daddr 10.71.100.0/24 return comment "IGNORE_ADMIN_WG_TO_LAN" ip daddr @pbr_transit_direct_4_dst_ip_user goto pbr_mark_0x010000 ip saddr @pbr_transit_direct_4_src_ip_user goto pbr_mark_0x010000 ether saddr @pbr_transit_direct_4_src_mac_user goto pbr_mark_0x010000 ip daddr @pbr_transit_vpn_4_dst_ip_user goto pbr_mark_0x020000 ip saddr @pbr_transit_vpn_4_src_ip_user goto pbr_mark_0x020000 ether saddr @pbr_transit_vpn_4_src_mac_user goto pbr_mark_0x020000 === nft tables === /usr/sbin/nft table inet fw4 === UCI pending VM100 === === VM101 read-only mark/routing state === Wed Jul 8 11:24:35 UTC 2026 === canary should be absent === router_egress_canary_absent === ip rule === 0: from all lookup local 10013: from all fwmark 0x203 lookup 203 10014: from all fwmark 0x204 lookup 204 10015: from all fwmark 0x205 lookup 205 10019: from all iif eth1 lookup 200 10020: from 10.200.0.0/24 lookup 200 32766: from all lookup main 32767: from all lookup default === table 200 === default dev vpn1 scope link 10.200.0.0/24 dev eth1 scope link src 10.200.0.2 10.201.0.0/24 dev eth3 scope link src 10.201.0.2 === table 203 === default dev vpn3 scope link === route marked DSCP-target equivalent === 1.1.1.1 from 10.200.0.1 dev vpn3 table 203 mark 0x203 cache iif eth1 === tunnel pings === PING 1.1.1.1 (1.1.1.1): 56 data bytes 64 bytes from 1.1.1.1: seq=0 ttl=57 time=53.138 ms 64 bytes from 1.1.1.1: seq=1 ttl=57 time=53.451 ms --- 1.1.1.1 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 53.138/53.294/53.451 ms PING_VM101_vpn1_RC=0 PING 1.1.1.1 (1.1.1.1): 56 data bytes 64 bytes from 1.1.1.1: seq=0 ttl=55 time=52.005 ms 64 bytes from 1.1.1.1: seq=1 ttl=55 time=52.221 ms --- 1.1.1.1 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 52.005/52.113/52.221 ms PING_VM101_vpn3_RC=0 === nft tables === /usr/sbin/nft table inet fw4 === UCI pending VM101 === === STEP_033H RESULT === dhcp_lease_lines=0 nat_related_lines=2 canary_absent_lines=1 fwmark_rule203_lines=1 table200_default_vpn1_lines=1 table203_default_vpn3_lines=1 ping_vm101_vpn1_rc=0 ping_vm101_vpn3_rc=0 uci_pending_lines=0 package=/opt/router-ops/apply-packages/20260708-112434_step033h_dscp_canary_plan decision=PASS_DSCP_CANARY_PLAN_READY