Use fwmark instead of UID-based rules for local traffic on Linux#1
Merged
Use fwmark instead of UID-based rules for local traffic on Linux#1
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
meta markinstead ofmeta skuidin OUTPUT chain,plus upstream proxy destination exclusion for connections the proxy cannot
mark (e.g. DoH via reqwest)
proxy address to nftables setup script
https://claude.ai/code/session_01HxseK2yRYaCWLAmiiRzZtX