Skip to content

Relay Response in tcpHandler Breaks Reverse Tunnel #859

@navidR

Description

@navidR

What happens:

When a relay Bind creates a local port (e.g., 127.0.0.1:1080) on the bind-server side,
incoming TCP connections to that port are handled by tcpHandler in
handler/relay/entrypoint.go. This handler opens a new mux stream back to the bind-client,
then writes a relay Response header (version, StatusOK, AddrFeature with source address)
before piping data. This relay Response is protocol framing that only makes sense within
the relay handshake — not on a data stream.

When the mux stream reaches the bind-client side, the handler there reads this relay
Response as if it were a relay Request. The status byte 0x00 matches CmdConnect, so the
handler interprets it as a Connect request to the source address (e.g., 127.0.0.1:45242)
rather than the actual destination the client requested. The real destination
(facebook.com:443) is in a subsequent relay Request on the same stream — sent by the
relay connector that connected to the bound port — but the handler only reads one relay
entry per stream and never sees it.

The fix:

Remove lines 102–112 of handler/relay/entrypoint.go — the entire relay Response write
block. The Bind already succeeded (the rtcp listener confirmed it), and the source
address provides no value downstream. Without this header, the first bytes on the mux
stream are the relay Request from the connector (containing the actual target
destination), which the remote relay handler can parse correctly, dial, and pipe. The
xnet.Pipe call on line 117 handles data forwarding without any protocol framing needed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions