Skip to content

Tproxy inbound support (linux only)#141

Open
janeblower wants to merge 19 commits into
cfal:masterfrom
janeblower:tproxy-pr
Open

Tproxy inbound support (linux only)#141
janeblower wants to merge 19 commits into
cfal:masterfrom
janeblower:tproxy-pr

Conversation

@janeblower
Copy link
Copy Markdown

TPROXY inbound support (Linux)

Adds a new tproxy server protocol that accepts traffic redirected by the kernel via iptables/nftables + IP_TRANSPARENT, recovers the original destination, and forwards it through the normal outbound chain.

What's included

  • Config: new ServerProxyConfig::Tproxy variant with tcp_enabled / udp_enabled flags and validation (Linux-only, requires non-empty bind addresses, rejects nested protocols).
  • TCP: IP_TRANSPARENT listener; original destination read from the accepted socket.
  • UDP: session-based relay with recvmsg + cmsg parsing (IP_ORIGDSTADDR / IPV6_ORIGDSTADDR), source-address spoofing on replies via a per-destination send-socket cache, race-safe session insertion, and per-packet error tolerance.
  • Dispatcher: start_tproxy_servers wired into startup.
  • Helpers: NetLocation::from_socket_addr; process_setup_result extracted from process_stream for reuse.
  • Docs: examples/tproxy.yaml with iptables/ip rule setup, plus a section in CONFIG.md.

Notes

  • Linux-only; listeners need CAP_NET_RAW (or CAP_NET_ADMIN, or root).
  • musl build fix included.
  • Cmsg control buffer is properly aligned; MSG_CTRUNC is detected and surfaced.

janeblower and others added 19 commits May 28, 2026 13:13
Move the match-on-TcpServerSetupResult block into a new pub async fn
process_setup_result so future tproxy inbound code can call it directly
without going through TcpServerHandler trait dispatch. process_stream
now delegates to process_setup_result after the setup timeout logic.
Behavior is identical.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds the Tproxy variant to ServerProxyConfig with tcp_enabled and
udp_enabled boolean fields (both defaulting to true), Display arm, serde
round-trip tests, and a placeholder arm in tcp_server_handler_factory.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reject tproxy configs early: non-Linux builds, QUIC transport,
unix-socket bind, and both tcp_enabled+udp_enabled disabled.
Add four unit tests covering all error paths and the happy path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ings

Add #[cfg(target_os = "linux")] to tproxy_rejects_quic_transport,
tproxy_rejects_unix_socket_bind, and tproxy_rejects_both_disabled so
they are not compiled on non-Linux hosts where the early-return message
differs. Add new tproxy_rejects_quic_settings test covering the
quic_settings.is_some() rejection path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Create src/tproxy/ module (Linux-only) with low-level socket factory
functions: new_tproxy_tcp_listener, new_tproxy_udp_socket, and
new_tproxy_udp_send_socket, each applying the appropriate IP_TRANSPARENT /
IPV6_TRANSPARENT / IP_RECVORIGDSTADDR setsockopt calls via libc.
Tests skip gracefully on EPERM (no CAP_NET_ADMIN) and run fully when
privileged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add start_tproxy_servers to src/tproxy/mod.rs with per-bind TCP and UDP
run-loop helpers; dispatch ServerProxyConfig::Tproxy from start_servers
in tcp_server.rs (Linux cfg-gated); replace the unreachable!() placeholder
in tcp_server_handler_factory.rs with a clear panic message; remove
#![allow(dead_code)] from all three tproxy submodules now that the items
are wired in.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

1 participant