Describe the bug
On Linux, while ProxyBridge is active (NFQUEUE on mangle/OUTPUT), HTTP requests to
local services on 127.0.0.1 that return a non-trivial amount of data hang (time out,
0 bytes received). Small/quick responses to the same ports return instantly, and external
traffic is unaffected.
This reproduces even with no rules and no proxy configured (pure pass-through), so the
cause is the NFQUEUE interception itself, not any PROXY action. Only ProxyBridge --cleanup
or stopping the process restores loopback — disabling rules in the config/GUI does not.
Environment
- OS: Debian 13 (trixie)
- ProxyBridge:
dev (V4.0)
- Platform: Linux
To reproduce
# 1. local service with a heavy response
dd if=/dev/urandom of=/srv/big.bin bs=1M count=16
( cd /srv && python3 -m http.server 8080 --bind 127.0.0.1 & )
# 2. start ProxyBridge with NO rules and NO proxy
sudo ProxyBridge --verbose 1
# 3. heavy loopback request -> HANGS
curl --max-time 12 http://127.0.0.1:8080/big.bin # timeout, 0 bytes
# 4. small request + external -> fine
curl http://127.0.0.1:8080/ # 200 instantly
curl https://ifconfig.me # 200
# 5. remove interception -> heavy request works again
sudo ProxyBridge --cleanup
curl http://127.0.0.1:8080/big.bin # 200 instantly
Root cause (confirmed)
ProxyBridge sends all OUTPUT packets — including loopback — to NFQUEUE and reinjects them.
The lo interface has an MTU of 65536, so loopback TCP uses very large segments (~64 KB),
and these do not survive the NFQUEUE -> userspace -> reinject path. Small responses fit in
the initial TCP window and complete before this matters.
Confirmed by A/B (interception active the whole time):
lo MTU |
curl big.bin (16 MB over loopback) |
| 65536 (default) |
timeout, 0 bytes |
| 1500 |
200, ~0.05 s |
| 65536 (restored) |
timeout, 0 bytes again |
Toggling only the MTU toggles the bug, which pins the cause to loopback segment size rather
than queue size, rule matching, or DNS. (copy_range is not involved: DIRECT issues an
ACCEPT verdict by packet id, and the PROXY path moves data through the relay sockets, not
the queue.)
Proposed fix
Exclude loopback from interception by inserting
iptables -t mangle -A OUTPUT -o lo -j ACCEPT
before the NFQUEUE rules (and removing it symmetrically on cleanup). Loopback never needs
proxying in the default configuration. This also matches the Windows behaviour, where
localhost traffic is DIRECT by default unless LocalhostViaProxy is enabled.
I have a fix + tests ready and can open a PR against dev.
Future enhancement (separate PR, optional)
The Linux build currently has no LocalhostViaProxy toggle, while Windows does. A follow-up
could add it for parity. Making LocalhostViaProxy = true actually proxy loopback is feasible
without globally changing the lo MTU, by having ProxyBridge clamp the TCP MSS only on the
intercepted loopback path (e.g. TCPMSS --set-mss on lo SYN packets), so segments stay small
enough to survive reinjection. Happy to do this as a second PR if it is of interest.
Note: this was investigated and fixed with Claude Code (Opus 4.8); I am not a C developer
myself. I have reproduced and verified the fix on Debian 13, but I am equally happy for you to
take it from here and implement it yourselves if you prefer.
Describe the bug
On Linux, while ProxyBridge is active (NFQUEUE on
mangle/OUTPUT), HTTP requests tolocal services on
127.0.0.1that return a non-trivial amount of data hang (time out,0 bytes received). Small/quick responses to the same ports return instantly, and external
traffic is unaffected.
This reproduces even with no rules and no proxy configured (pure pass-through), so the
cause is the NFQUEUE interception itself, not any PROXY action. Only
ProxyBridge --cleanupor stopping the process restores loopback — disabling rules in the config/GUI does not.
Environment
dev(V4.0)To reproduce
Root cause (confirmed)
ProxyBridge sends all
OUTPUTpackets — including loopback — to NFQUEUE and reinjects them.The
lointerface has an MTU of 65536, so loopback TCP uses very large segments (~64 KB),and these do not survive the NFQUEUE -> userspace -> reinject path. Small responses fit in
the initial TCP window and complete before this matters.
Confirmed by A/B (interception active the whole time):
loMTUcurl big.bin(16 MB over loopback)Toggling only the MTU toggles the bug, which pins the cause to loopback segment size rather
than queue size, rule matching, or DNS. (
copy_rangeis not involved: DIRECT issues anACCEPT verdict by packet id, and the PROXY path moves data through the relay sockets, not
the queue.)
Proposed fix
Exclude loopback from interception by inserting
before the NFQUEUE rules (and removing it symmetrically on cleanup). Loopback never needs
proxying in the default configuration. This also matches the Windows behaviour, where
localhost traffic is DIRECT by default unless
LocalhostViaProxyis enabled.I have a fix + tests ready and can open a PR against
dev.Future enhancement (separate PR, optional)
The Linux build currently has no
LocalhostViaProxytoggle, while Windows does. A follow-upcould add it for parity. Making
LocalhostViaProxy = trueactually proxy loopback is feasiblewithout globally changing the
loMTU, by having ProxyBridge clamp the TCP MSS only on theintercepted loopback path (e.g.
TCPMSS --set-mssonloSYN packets), so segments stay smallenough to survive reinjection. Happy to do this as a second PR if it is of interest.
Note: this was investigated and fixed with Claude Code (Opus 4.8); I am not a C developer
myself. I have reproduced and verified the fix on Debian 13, but I am equally happy for you to
take it from here and implement it yourselves if you prefer.