java.lang.Object
net.i2p.i2ptunnel.socks.SOCKSServer
net.i2p.i2ptunnel.socks.SOCKS5Server

class SOCKS5Serverextends SOCKSServer
SOCKS5 server implementation with comprehensive protocol support and authentication.

This class handles SOCKS version 5 protocol including authentication (username/password and no-auth), multiple address types (IPv4, IPv6, domain), and extended commands including Tor RESOLVE for hostname resolution. It supports UDP ASSOCIATE commands and provides outproxy connectivity through both SOCKS and HTTP CONNECT methods.

The server includes security features like localhost blocking, IP-to-domain mapping, and integrates with I2P naming service for destination resolution. It also supports torsocks compatibility through hostname caching mechanisms.

Supports torsocks as of 0.9.57.

  • Field Details

    • setupCompleted

      private boolean setupCompleted
      True once the SOCKS handshake has finished.
    • authRequired

      private final boolean authRequired
      Whether a username and password were configured.
    • _torCache

      private static final Map<String,String> _torCache
      Torsocks support Cache of fake IPv4 255.x.x.x (as returned from RESOLVE) to hostname torsocks 2.3.0 does NOT support IPv6, even though Tor does now The fake IP is a partial SipHash of the hostname, so collisions aren't predictable. The IPs will change at restart, but torsocks doesn't appear to do any caching.
    • _proxyCache

      private final ConcurrentHashMap<String,String> _proxyCache
      Sticky proxy cache: host -> selected proxy, for consistent routing.
    • tunnel

      private static SOCKSUDPTunnel tunnel
      The shared UDP tunnel, started on first use. This isn't really the right place for it, since we can't stop the tunnel once it starts.
    • _startLock

      private static final Object _startLock
      Guards starting the shared UDP tunnel.
    • dummyIP

      private static final byte[] dummyIP
      Zero address sent when the client's real address is hidden.
  • Constructor Details

    • SOCKS5Server

      public SOCKS5Server(I2PAppContext ctx, Socket clientSock, Properties props)
      Create a SOCKS5 server that communicates with the client using the specified socket. This method should not be invoked directly: new SOCKS5Server objects should be created by using SOCKSServerFactory.createSOCKSServer(net.i2p.I2PAppContext, java.net.Socket, java.util.Properties). It is assumed that the SOCKS VER field has been stripped from the input stream of the client socket.
      Parameters:
      ctx - the context to run the tunnel in
      clientSock - the accepted socket, positioned just past the version and command bytes already consumed
      props - non-null
  • Method Details

    • getClientSocket

      public Socket getClientSocket() throws SOCKSException
      Description copied from class: SOCKSServer
      Get a socket for sending/receiving 8-bit clean data to/from the client.
      Specified by:
      getClientSocket in class SOCKSServer
      Returns:
      a Socket connected with the client
      Throws:
      SOCKSException - if the initial handshake fails before the socket can be returned
    • setupServer

      protected void setupServer() throws SOCKSException
      Description copied from class: SOCKSServer
      Perform server initialization (expecially regarding protected variables).
      Specified by:
      setupServer in class SOCKSServer
      Throws:
      SOCKSException - if the client's request cannot be read off the socket
    • init

      private void init(DataInputStream in, DataOutputStream out, InetAddress client) throws IOException
      SOCKS5 connection initialization. This method assumes that SOCKS "VER" field has been stripped from the input stream.
      Parameters:
      in - the client input stream, positioned after the VER byte, carrying the method count and the offered method list
      out - the client output stream for the method selection reply
      client - the client's IP address, used in the authentication log messages
      Throws:
      IOException - if a stream read or write fails, or if the client offers no acceptable authentication method
    • verifyPassword

      private void verifyPassword(DataInputStream in, DataOutputStream out, InetAddress client) throws IOException
      Wait for the username/password message and verify or throw SOCKSException on failure.
      Parameters:
      in - the client input stream, positioned at the start of the username/password subnegotiation
      out - the client output stream for the authentication reply
      client - the client's IP address, used only in the log messages
      Throws:
      IOException - if a stream read or write fails, or if the subnegotiation version, the user or password fields, or the credentials are invalid
    • manageRequest

      private int manageRequest(DataInputStream in, DataOutputStream out) throws IOException
      SOCKS5 request management. This method assumes that all the stuff preceding or enveloping the actual request (e.g. protocol initialization, integrity/confidentiality encapsulations, etc) has been stripped out of the input/output streams.
      Parameters:
      in - the client input stream, positioned at the request's version byte
      out - the client output stream for the failure reply
      Returns:
      the validated command byte, Command.CONNECT or Command.UDP_ASSOCIATE
      Throws:
      IOException - if a stream read or write fails, or if the request has an invalid protocol version, command, or port number
    • checkCommand

      private int checkCommand(int command, DataOutputStream out) throws IOException
      Validate the SOCKS5 command byte, replying and throwing for unsupported or unknown commands.
      Parameters:
      command - the command byte
      out - the output stream for the failure reply
      Returns:
      the command byte
      Throws:
      IOException - on stream errors
      SOCKSException - if the command is not supported
    • parseAddressType

      private void parseAddressType(DataInputStream in, int command, DataOutputStream out) throws IOException
      Parse and validate the address type and host bytes of a SOCKS5 request, filling in connHostName and addressType. TOR_RESOLVE requests cache the hostname under a fake 255.x.x.x address.
      Parameters:
      in - the request stream
      command - the command byte
      out - the output stream for failure replies
      Throws:
      IOException - on stream errors
    • confirmConnection

      protected void confirmConnection() throws SOCKSException
      Description copied from class: SOCKSServer
      Confirm to the client that the connection has succeeded.
      Specified by:
      confirmConnection in class SOCKSServer
      Throws:
      SOCKSException - if the success reply cannot be written back to the client
    • sendInitReply

      private void sendInitReply(int replyCode, DataOutputStream out) throws IOException
      Send the specified reply during SOCKS5 initialization.
      Parameters:
      replyCode - the selected Method constant to send back
      out - the client output stream
      Throws:
      IOException - if the write to the client fails
    • sendAuthReply

      private void sendAuthReply(int replyCode, DataOutputStream out) throws IOException
      Send the specified reply during SOCKS5 authorization.
      Parameters:
      replyCode - the result to send back, AUTH_SUCCESS or AUTH_FAILURE
      out - the client output stream
      Throws:
      IOException - if the write to the client fails
    • sendRequestReply

      private void sendRequestReply(int replyCode, int addressType, InetAddress inetAddr, String domainName, int bindPort, DataOutputStream out) throws IOException
      Send the specified reply to a request of the client. Either one of inetAddr or domainName can be null, depending on addressType.
      Parameters:
      replyCode - the Reply constant to send
      addressType - an AddressType constant selecting how the bound address is encoded: IPV4, IPV6, or DOMAINNAME
      inetAddr - the IPv4 or IPv6 address to report, null if none
      domainName - the domain name to report for DOMAINNAME type, null if none
      bindPort - the port to report in the reply, 0-65535
      out - the client output stream
      Throws:
      IOException - if the write to the client fails
    • sendFailureReply

      private void sendFailureReply(int reply, DataOutputStream out)
      Send a failure reply and swallow any IOException. Only for use in the connectTo() failure paths.
      Parameters:
      reply - the reply code
      out - the output stream
    • getDestinationI2PSocket

      public I2PSocket getDestinationI2PSocket(I2PSOCKSTunnel t) throws SOCKSException
      Get an I2PSocket for sending/receiving 8-bit clean data to/from the destination of the SOCKS connection.
      Specified by:
      getDestinationI2PSocket in class SOCKSServer
      Parameters:
      t - the streaming tunnel to build the destination socket over
      Returns:
      an I2PSocket connected with the destination
      Throws:
      SOCKSException - if the requested host name or port was never established
    • connectToDestination

      Connect to the requested destination via I2P, an outproxy plugin, or a configured outproxy.
      Parameters:
      t - the owning tunnel
      out - the output stream for failure replies
      Returns:
      the connected socket
      Throws:
      SOCKSException - on any connection failure
      DataFormatException - if the destination is malformed
      IOException - on stream errors
      I2PException - on I2P errors
    • selectProxy

      private String selectProxy(List<String> proxies, String host)
      Select a proxy, preferring a cached one for the same host.
      Parameters:
      proxies - the configured proxy destinations, non-empty
      host - the destination host whose earlier choice is reused if it is still in the list
      Returns:
      the proxy to use: the cached one for this host if still listed, otherwise a random pick that is then cached
    • handleUDP

      private void handleUDP(DataInputStream in, DataOutputStream out) throws SOCKSException
      We got a UDP associate command. Loop here looking for more, never return normally, or else I2PSocksTunnel will create a streaming lib connection.

      RFC 1928 defines one UDP relay per TCP control connection, but a client may open more; each additional ASSOCIATE request gets its own local port. The loop ends on any other command, or on a closed control connection.

      Parameters:
      in - the control connection input stream, read for further ASSOCIATE commands
      out - the control connection output stream, for the relay port replies
      Throws:
      SOCKSException - always, after the UDP relays are closed, so the caller never opens a streaming connection