Skip to content

Use fwmark instead of UID-based rules for local traffic on Linux#1

Merged
madeye merged 3 commits intomainfrom
claude/tags-bypass-uid-rules-YvbZb
Mar 28, 2026
Merged

Use fwmark instead of UID-based rules for local traffic on Linux#1
madeye merged 3 commits intomainfrom
claude/tags-bypass-uid-rules-YvbZb

Conversation

@madeye
Copy link
Copy Markdown
Owner

@madeye madeye commented Mar 28, 2026

Replace the UID-based loop prevention (meta skuid / dedicated system user)
with nftables fwmark-based filtering (meta mark / SO_MARK) for the local
proxy mode on Linux. This eliminates the need to create a dedicated system
user or run the service as a specific user.

Changes:

  • tunnel.rs: Set SO_MARK on outbound sockets before connecting (Linux only)
  • nftables_setup.sh: Use meta mark instead of meta skuid in OUTPUT chain,
    plus upstream proxy destination exclusion for connections the proxy cannot
    mark (e.g. DoH via reqwest)
  • config.rs: Add --fwmark flag (default: 1) for configurable mark value
  • service/linux.rs: Remove User= from systemd unit, pass fwmark and upstream
    proxy address to nftables setup script
  • macOS (pf) unchanged — keeps UID-based approach since pf has no fwmark

https://claude.ai/code/session_01HxseK2yRYaCWLAmiiRzZtX

claude added 3 commits March 28, 2026 00:15
Replace the UID-based loop prevention (meta skuid / dedicated system user)
with nftables fwmark-based filtering (meta mark / SO_MARK) for the local
proxy mode on Linux. This eliminates the need to create a dedicated system
user or run the service as a specific user.

Changes:
- tunnel.rs: Set SO_MARK on outbound sockets before connecting (Linux only)
- nftables_setup.sh: Use `meta mark` instead of `meta skuid` in OUTPUT chain,
  plus upstream proxy destination exclusion for connections the proxy cannot
  mark (e.g. DoH via reqwest)
- config.rs: Add --fwmark flag (default: 1) for configurable mark value
- service/linux.rs: Remove User= from systemd unit, pass fwmark and upstream
  proxy address to nftables setup script
- macOS (pf) unchanged — keeps UID-based approach since pf has no fwmark

https://claude.ai/code/session_01HxseK2yRYaCWLAmiiRzZtX
Replace the UID-based loop prevention (pf `user !=` / dedicated system user)
with IP_BOUND_IF and destination-based pf exclusion for local traffic mode
on macOS. This eliminates the need for a dedicated system user on macOS,
matching the fwmark approach already used on Linux.

Two complementary mechanisms prevent loops:
1. IP_BOUND_IF: When upstream proxy is on localhost, outbound sockets are
   bound to lo0 via setsockopt(IP_BOUND_IF). Traffic stays on lo0 and never
   hits the `pass out on <iface> route-to` pf rule.
2. Destination exclusion: A `pass out quick` pf rule skips traffic destined
   to the upstream proxy address, covering remote upstreams and connections
   the proxy cannot mark (e.g. DoH via reqwest).

Changes:
- tunnel.rs: Add bind_to_loopback() using IP_BOUND_IF (macOS, setsockopt
  level IPPROTO_IP, opt 25) when upstream is loopback and local_traffic on
- pf_setup.sh: Replace `user != proxy_user` with `pass out quick` for
  upstream proxy destination; 3rd param changes from proxy_user to
  upstream_proxy (ip:port)
- service/macos.rs: Remove UserName from launchd plist
- config.rs: Deprecate --proxy-user (now unused on both platforms)
- proxy.rs: Pass platform-specific args (fwmark on Linux, local_traffic
  bool on macOS) to connect_via_proxy

https://claude.ai/code/session_01HxseK2yRYaCWLAmiiRzZtX
@madeye madeye merged commit 245e5c3 into main Mar 28, 2026
4 checks passed
@madeye madeye deleted the claude/tags-bypass-uid-rules-YvbZb branch March 28, 2026 00:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants