Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions prokop/files/usr/lib/nft/apply.uc
Original file line number Diff line number Diff line change
Expand Up @@ -1561,6 +1561,14 @@ function nft_create_runtime_base(table, localv4_set, common_set, port_set, ip_po
!nft_add_rule(table, "mangle", [ "iifname", "@" + as_string(interface_set), "ip", "daddr", fakeip_range, "meta", "l4proto", "udp", "meta", "mark", "set", fakeip_mark, "counter" ]) ||
!nft_add_rule(table, "mangle", [ "iifname", "@" + as_string(interface_set), "ip6", "daddr", fakeip6_range, "meta", "l4proto", "tcp", "meta", "mark", "set", fakeip_mark, "counter" ]) ||
!nft_add_rule(table, "mangle", [ "iifname", "@" + as_string(interface_set), "ip6", "daddr", fakeip6_range, "meta", "l4proto", "udp", "meta", "mark", "set", fakeip_mark, "counter" ]) ||
// mangle (-149) marks the first packet of a flow before dns_redirect
// (-101) rewrites it, so a client query to a captured resolver such
// as 8.8.8.8 arrives here redirected to the router's own :53 or
// :1603 and still marked. TPROXY of that packet makes sing-box answer
// from a transparent socket bound to that local address, which then
// takes the LAN's queries meant for dnsmasq and never reads them.
// A redirected packet is already delivered locally: never TPROXY it.
!nft_add_rule(table, "proxy", [ "ct", "status", "dnat", "return" ]) ||
!nft_add_rule(table, "proxy", [ "meta", "mark", "&", fakeip_mark, "==", fakeip_mark, "meta", "l4proto", "tcp", "tproxy", "ip", "to", ":" + as_string(tproxy_port), "counter" ]) ||
!nft_add_rule(table, "proxy", [ "meta", "mark", "&", fakeip_mark, "==", fakeip_mark, "meta", "l4proto", "udp", "tproxy", "ip", "to", ":" + as_string(tproxy_port), "counter" ]) ||
!nft_add_rule(table, "proxy", [ "meta", "mark", "&", fakeip_mark, "==", fakeip_mark, "meta", "l4proto", "tcp", "tproxy", "ip6", "to", core_ip.format_ipv6_tproxy_target(tproxy6_address, tproxy_port), "counter" ]) ||
Expand Down
5 changes: 5 additions & 0 deletions tests/nft_apply.sh
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,11 @@ for shared_set in prokop_subnets prokop_subnets6 prokop_ports prokop_ip_ports pr
done
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tProkopTable\tproxy\tmeta\tmark\t&\t0x00100000\t==\t0x00100000\tmeta\tl4proto\ttcp\ttproxy\tip\tto\t:1602\tcounter' "runtime proxy tcp rule"
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tProkopTable\tproxy\tmeta\tmark\t&\t0x00100000\t==\t0x00100000\tmeta\tl4proto\ttcp\ttproxy\tip6\tto\t[::1]:1602\tcounter' "runtime proxy6 tcp rule"
# mangle marks a client query to a captured resolver (8.8.8.8) before
# dns_redirect sends it to the router's :53; TPROXY of that redirected packet
# left sing-box sockets on 192.168.1.1:53 that swallowed the LAN's DNS.
[ "$(grep -F $'\tProkopTable\tproxy\t' "$NFT_LOG" | grep -F $'\trule\t' | head -n 1 | cut -f7- | tr '\t' ' ')" = 'ct status dnat return' ] ||
fail "proxy must skip redirected (DNAT) packets before any TPROXY rule"
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tProkopTable\tmangle_output\tmeta\tmark\t&\t0xff2000ff\t==\t0x00200000\tcounter\treturn' "runtime outbound return on Prokop's mark bits"
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tProkopTable\tmangle_output\tip6\tdaddr\t@localv6\tip6\tdaddr\t!=\tfc00::/18\treturn' "runtime output local6 return preserves FakeIP6 capture"
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tProkopTable\tmangle_output\tjump\tpriority_output_rules' "runtime priority output jump"
Expand Down