Skip to content

Message Protocol ​

LinkSocks uses a custom binary message protocol over WebSocket. This page details the message transmission mechanisms and protocol specifications.

Protocol Version ​

Current protocol version: 0x01

Message Types ​

Authentication Messages ​

AuthMessage: Initial authentication from client to server

Version(1) + Type(1) + TokenLen(1) + Token(N) + Reverse(1) + Instance(16)

AuthResponseMessage: Server response to authentication

Version(1) + Type(1) + Success(1) + [ErrorLen(1) + Error(N) if !Success]

Connection Management ​

ConnectMessage: Request to establish a new connection

Version(1) + Type(1) + Protocol(1) + ChannelID(16) + [AddrLen(1) + Addr(N) + Port(2) if TCP]

ConnectResponseMessage: Response to connection request

Version(1) + Type(1) + Success(1) + ChannelID(16) + [ErrorLen(1) + Error(N) if !Success]

DisconnectMessage: Request to close a connection

Version(1) + Type(1) + ChannelID(16) + [ErrorLen(1) + Error(N) if error]

Data Transfer ​

DataMessage: Data transmission between client and server

Version(1) + Type(1) + Protocol(1) + ChannelID(16) + Compression(1) + DataLen(4) + Data(N) +
    [AddrLen(1) + Addr(N) + Port(2) if UDP]

Channel Management ​

Channel Identification ​

Each proxy connection is assigned a unique ChannelID (UUID) that serves multiple purposes:

  • Links related messages across the WebSocket connection
  • Enables multiplexing multiple proxy connections over a single WebSocket
  • Facilitates message routing in relay proxy mode

Message Queuing ​

LinkSocks uses channel-specific message queues to handle asynchronous message delivery. Each channel gets its own message queue with a buffer size of 1000 messages. When the queue is full, new messages are dropped to prevent memory exhaustion.

Channel Cleanup ​

When connections close, the system automatically:

  • Removes the channel from active channel maps
  • Closes and removes the associated message queue
  • Cleans up any pending goroutines

TCP Connection Flow ​

Forward Proxy Mode ​

  1. Connection Request: Client sends ConnectMessage with target address and port
  2. Server Processing: Server attempts to establish connection to target
  3. Response: Server sends ConnectResponseMessage indicating success or failure
  4. Data Exchange: Bidirectional DataMessage exchange until connection closes
  5. Cleanup: DisconnectMessage sent when either side closes

Reverse Proxy Mode ​

In reverse proxy mode, the server initiates connections to the client:

  1. Server Request: Server sends ConnectMessage with target address and port
  2. Client Processing: Client attempts to establish connection to target
  3. Response: Client sends ConnectResponseMessage indicating success or failure
  4. Data Exchange: Bidirectional DataMessage exchange until connection closes
  5. Cleanup: DisconnectMessage sent when either side closes

UDP Handling ​

UDP over SOCKS5 requires special handling due to its connectionless nature. The process involves SOCKS5 UDP association and WebSocket message exchange.

SOCKS5 UDP Association Process ​

When a SOCKS5 client requests UDP ASSOCIATE (cmd=0x03):

  1. Local UDP Listener Creation

    • LinkSocks creates a local UDP listener on an available port
    • This listener will receive UDP packets from the SOCKS5 client
    • The listener address is returned to the SOCKS5 client
  2. WebSocket Connection Setup

    • LinkSocks sends a ConnectMessage to the server with Protocol="udp"
    • The ChannelID identifies this UDP association
    • No target address is included in the initial ConnectMessage for UDP
  3. SOCKS5 Response

    • LinkSocks responds to the SOCKS5 client with the local UDP listener address
    • The client will send UDP packets to this address for forwarding

UDP Data Processing Flow ​

Client → Server Direction ​

  1. Packet Reception

    • Local UDP listener receives packet from SOCKS5 client
    • Packet includes SOCKS5 UDP header with target address information
  2. SOCKS5 UDP Header Parsing

    • Extract target address and port from SOCKS5 UDP header format:
      RSV(2) + FRAG(1) + ATYP(1) + DST.ADDR(var) + DST.PORT(2) + DATA(var)
  3. WebSocket Transmission

    • Create DataMessage with extracted target address
    • Send via WebSocket to server with Protocol="udp"

Server → Client Direction ​

  1. Server Reception

    • Server receives UDP packet from remote target
    • Server knows the source address of the incoming packet
  2. SOCKS5 UDP Header Construction

    • Server constructs SOCKS5 UDP header with source address information
    • Format matches SOCKS5 specification
  3. WebSocket Transmission

    • Create DataMessage with SOCKS5 UDP header + data
    • Send to client via WebSocket
  4. Client Forwarding

    • Client receives DataMessage and forwards to local UDP listener
    • SOCKS5 client receives packet with proper source address information

UDP Connection Lifecycle ​

  • Association: Lasts until SOCKS5 TCP control connection closes
  • Timeout: UDP associations may timeout if inactive
  • Cleanup: When association ends, local UDP listener is closed and resources freed

Performance ​

Data Compression ​

DataMessage supports conditional compression when data size exceeds the compression threshold (default: 512KB, configurable via WithCompressionThreshold). Compression flag in DataMessage is set to 0x01 for gzip compression.

Batch Processing ​

LinkSocks implements dynamic batching for network data reads:

SendManager Batching

  • Network data is batched in a buffer before creating DataMessage
  • Default batch wait time: 20ms minimum, 500ms maximum
  • Adaptive batching adjusts delay based on connection speed
  • Timer-based flushing when delay expires or buffer is full

Batching Control

  • Dynamic batching can be disabled via WithDynamicBatching(false) for immediate sending
  • High-speed connections increase batch delay
  • Low-speed connections reduce batch delay
  • Buffer size and timing limits are configurable via WithBatchingTimeLimits

Error Handling ​

Client-Server Connection Failures ​

When token validation fails

  • Server sends AuthResponseMessage{Success: false, Error: "invalid token"}
  • WebSocket connection is immediately closed
  • Client receives nonRetriableError and stops reconnection attempts

When WebSocket connection is lost

  • Client checks if reconnect is enabled and error is not nonRetriableError
  • Waits ReconnectDelay (default: 5s; configurable via ClientOption.WithReconnectDelay) before attempting reconnection
  • Existing channels remain in memory, DataMessages continue queuing
  • Data transmission resumes after successful reconnection

When no clients are available for load balancing

  • Server waits 10 seconds to find available reverse proxy clients
  • Uses round-robin selection with ping liveness checks
  • If ping fails, selects next available client
  • After 10 seconds with no clients, sends error code 0x03 to SOCKS5 client

Network Connection Failures ​

When target server connection fails

  • Normal mode: immediately sends ConnectResponseMessage{Success: false, Error: details}
  • SOCKS5 client receives error response (code 0x04) and connection is closed
  • FastOpen mode: assumes success initially, detects failure on first data transmission
  • FastOpen timeout: disconnects channel if no success confirmation after ConnectTimeout+5 seconds

When remote peer closes connection

  • Sends DisconnectMessage{ChannelID: channelID, Error: details}
  • Cleans up resources: removes message queue, deletes from channel maps, cancels context
  • Closes SOCKS5 client connection to signal termination

When connection closes abnormally

  • Channel cleaner checks activity every 60 seconds
  • Channels inactive for 12 hours are automatically cleaned up
  • RST packets or network timeouts trigger immediate resource cleanup
  • Individual channel failures do not affect other channels on the same WebSocket

Released under the MIT License.