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 Summary
FieldsModifier and TypeFieldDescriptionprivate final ConcurrentHashMap<String, String> Sticky proxy cache: host -> selected proxy, for consistent routing.private static final ObjectGuards starting the shared UDP tunnel.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.private final booleanWhether a username and password were configured.private static final byte[]Zero address sent when the client's real address is hidden.private booleanTrue once the SOCKS handshake has finished.private static SOCKSUDPTunnelThe shared UDP tunnel, started on first use.Fields inherited from class SOCKSServer
_context, _log, addressType, clientSock, connHostName, connPort, propsModifier and TypeFieldDescriptionprotected final I2PAppContextThe application context, used for the log manager and property lookups.protected final LogThe logger for this class.protected intSOCKS address type (e.g.protected final SocketThe connected socket back to the local SOCKS client.protected StringHostname requested by the SOCKS client.protected intPort requested by the SOCKS client.protected final PropertiesThe tunnel configuration, holding the IP to domain mappings.Constructor Summary
ConstructorsConstructorDescriptionSOCKS5Server(I2PAppContext ctx, Socket clientSock, Properties props) Create a SOCKS5 server that communicates with the client using the specified socket.Method Summary
Modifier and TypeMethodDescriptionprivate intcheckCommand(int command, DataOutputStream out) Validate the SOCKS5 command byte, replying and throwing for unsupported or unknown commands.protected voidConfirm to the client that the connection has succeeded.private I2PSocketConnect to the requested destination via I2P, an outproxy plugin, or a configured outproxy.Get a socket for sending/receiving 8-bit clean data to/from the client.Get an I2PSocket for sending/receiving 8-bit clean data to/from the destination of the SOCKS connection.private voidhandleUDP(DataInputStream in, DataOutputStream out) We got a UDP associate command.private voidinit(DataInputStream in, DataOutputStream out, InetAddress client) SOCKS5 connection initialization.private intmanageRequest(DataInputStream in, DataOutputStream out) SOCKS5 request management.private voidparseAddressType(DataInputStream in, int command, DataOutputStream out) Parse and validate the address type and host bytes of a SOCKS5 request, filling in connHostName and addressType.private StringselectProxy(List<String> proxies, String host) Select a proxy, preferring a cached one for the same host.private voidsendAuthReply(int replyCode, DataOutputStream out) Send the specified reply during SOCKS5 authorization.private voidsendFailureReply(int reply, DataOutputStream out) Send a failure reply and swallow any IOException.private voidsendInitReply(int replyCode, DataOutputStream out) Send the specified reply during SOCKS5 initialization.private voidsendRequestReply(int replyCode, int addressType, InetAddress inetAddr, String domainName, int bindPort, DataOutputStream out) Send the specified reply to a request of the client.protected voidPerform server initialization (expecially regarding protected variables).private voidverifyPassword(DataInputStream in, DataOutputStream out, InetAddress client) Wait for the username/password message and verify or throw SOCKSException on failure.Methods inherited from class SOCKSServer
getMappedDomainNameForIP, getOutproxyPlugin, httpsConnect, outproxyConnectModifier and TypeMethodDescriptionprotected StringIP to domain name mapping support.protected OutproxyLooks up the registered outproxy plugin to route through, if any.voidhttpsConnect(I2PSocket destSock, OutputStream pout, String connHostName, int connPort, String configUser, String configPW) Act as a https client to connect to a CONNECT outproxy.protected I2PSocketoutproxyConnect(I2PSOCKSTunnel tun, String proxy) Act as a SOCKS 5 client to connect to an outproxy Caller must send success or error to local socks client.
Field Details
setupCompleted
private boolean setupCompletedTrue once the SOCKS handshake has finished.authRequired
private final boolean authRequiredWhether a username and password were configured._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
Sticky proxy cache: host -> selected proxy, for consistent routing.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
Guards starting the shared UDP tunnel.dummyIP
private static final byte[] dummyIPZero address sent when the client's real address is hidden.
Constructor Details
SOCKS5Server
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 usingSOCKSServerFactory.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 inclientSock- the accepted socket, positioned just past the version and command bytes already consumedprops- non-null
Method Details
getClientSocket
Description copied from class:SOCKSServerGet a socket for sending/receiving 8-bit clean data to/from the client.- Specified by:
getClientSocketin classSOCKSServer- Returns:
- a Socket connected with the client
- Throws:
SOCKSException- if the initial handshake fails before the socket can be returned
setupServer
Description copied from class:SOCKSServerPerform server initialization (expecially regarding protected variables).- Specified by:
setupServerin classSOCKSServer- Throws:
SOCKSException- if the client's request cannot be read off the socket
init
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 listout- the client output stream for the method selection replyclient- 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 subnegotiationout- the client output stream for the authentication replyclient- 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
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 byteout- 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
Validate the SOCKS5 command byte, replying and throwing for unsupported or unknown commands.- Parameters:
command- the command byteout- the output stream for the failure reply- Returns:
- the command byte
- Throws:
IOException- on stream errorsSOCKSException- 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 streamcommand- the command byteout- the output stream for failure replies- Throws:
IOException- on stream errors
confirmConnection
Description copied from class:SOCKSServerConfirm to the client that the connection has succeeded.- Specified by:
confirmConnectionin classSOCKSServer- Throws:
SOCKSException- if the success reply cannot be written back to the client
sendInitReply
Send the specified reply during SOCKS5 initialization.- Parameters:
replyCode- the selected Method constant to send backout- the client output stream- Throws:
IOException- if the write to the client fails
sendAuthReply
Send the specified reply during SOCKS5 authorization.- Parameters:
replyCode- the result to send back, AUTH_SUCCESS or AUTH_FAILUREout- 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 sendaddressType- an AddressType constant selecting how the bound address is encoded: IPV4, IPV6, or DOMAINNAMEinetAddr- the IPv4 or IPv6 address to report, null if nonedomainName- the domain name to report for DOMAINNAME type, null if nonebindPort- the port to report in the reply, 0-65535out- the client output stream- Throws:
IOException- if the write to the client fails
sendFailureReply
Send a failure reply and swallow any IOException. Only for use in the connectTo() failure paths.- Parameters:
reply- the reply codeout- the output stream
getDestinationI2PSocket
Get an I2PSocket for sending/receiving 8-bit clean data to/from the destination of the SOCKS connection.- Specified by:
getDestinationI2PSocketin classSOCKSServer- 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
private I2PSocket connectToDestination(I2PSOCKSTunnel t, DataOutputStream out) throws SOCKSException, DataFormatException, IOException, I2PException Connect to the requested destination via I2P, an outproxy plugin, or a configured outproxy.- Parameters:
t- the owning tunnelout- the output stream for failure replies- Returns:
- the connected socket
- Throws:
SOCKSException- on any connection failureDataFormatException- if the destination is malformedIOException- on stream errorsI2PException- on I2P errors
selectProxy
Select a proxy, preferring a cached one for the same host.- Parameters:
proxies- the configured proxy destinations, non-emptyhost- 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
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 commandsout- 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