Documentation
¶
Overview ¶
Package socks5 provides a complete implementation of a SOCKS5 server as defined in RFC 1928.
This package includes support for:
- TCP CONNECT command for proxying TCP connections
- UDP ASSOCIATE command for proxying UDP datagrams
- Multiple authentication methods (no auth, username/password)
- Configurable address resolution and connection handling
- Rule-based access control
- Address rewriting capabilities
- Graceful server shutdown
- Connection timeouts and context-based cancellation
The server is designed to be flexible and extensible, allowing custom implementations of authentication, name resolution, access rules, and address rewriting.
Basic usage:
config := &socks5.Config{}
server, err := socks5.New(config)
if err != nil {
log.Fatal(err)
}
if err := server.ListenAndServe(context.Background(), ":1080"); err != nil {
log.Fatal(err)
}
For more advanced configurations, see the Config struct and its various interface types.
Index ¶
- Constants
- Variables
- type AddrSpec
- type AddressRewriter
- type AuthContext
- type Authenticator
- type Config
- type CredentialStore
- type DNSResolver
- type ErrorLogger
- type NameResolver
- type NoAuthAuthenticator
- type PermitCommand
- type Request
- type RuleSet
- type Server
- type StaticCredentials
- type UDPSession
- type UDPSessionManager
- func (m *UDPSessionManager) GetSession(clientAddr string) (*UDPSession, bool)
- func (m *UDPSessionManager) GetSessionByIP(clientIP string) *UDPSession
- func (m *UDPSessionManager) RegisterSession(clientAddr string, ctx context.Context, req *Request)
- func (m *UDPSessionManager) Stop()
- func (m *UDPSessionManager) UnregisterSession(clientAddr string)
- func (m *UDPSessionManager) UpdateActivity(clientAddr string)
- func (m *UDPSessionManager) UpdateActivityByIP(clientIP string)
- type UserPassAuthenticator
Constants ¶
const ( // AuthMethodNoAuth indicates no authentication is required (X'00') AuthMethodNoAuth = uint8(0) // AuthMethodUserPass indicates username/password authentication (X'02') AuthMethodUserPass = uint8(2) // AuthMethodNoAcceptable indicates no acceptable authentication methods (X'FF') AuthMethodNoAcceptable = uint8(255) )
Authentication method constants as defined in RFC 1928
const ( // AuthUserPassVersion is the version field for username/password sub-negotiation (X'01') AuthUserPassVersion = uint8(1) // AuthUserPassStatusSuccess indicates successful username/password authentication (X'00') AuthUserPassStatusSuccess = uint8(0) // AuthUserPassStatusFailure indicates failed username/password authentication (X'01') AuthUserPassStatusFailure = uint8(1) )
const ( // CommandConnect requests a TCP connection to the target (X'01') CommandConnect = uint8(1) // CommandBind requests the server to bind to a port for incoming connections (X'02') CommandBind = uint8(2) // CommandAssociate requests UDP association for relaying UDP datagrams (X'03') CommandAssociate = uint8(3) )
SOCKS5 command constants as defined in RFC 1928
const ( // AddressIPv4 indicates an IPv4 address follows (X'01') AddressIPv4 = uint8(1) // AddressDomainName indicates a domain name follows (X'03') AddressDomainName = uint8(3) // AddressIPv6 indicates an IPv6 address follows (X'04') AddressIPv6 = uint8(4) )
Address type constants as defined in RFC 1928
const ( // ReplySucceeded indicates the request was successful (X'00') ReplySucceeded uint8 = iota // ReplyServerFailure indicates a general server failure (X'01') ReplyServerFailure // ReplyRuleFailure indicates the connection was blocked by rules (X'02') ReplyRuleFailure // ReplyNetworkUnreachable indicates the network is unreachable (X'03') ReplyNetworkUnreachable // ReplyHostUnreachable indicates the host is unreachable (X'04') ReplyHostUnreachable // ReplyConnectionRefused indicates the connection was refused (X'05') ReplyConnectionRefused // ReplyTTLExpired indicates the TTL expired (X'06') ReplyTTLExpired // ReplyCommandNotSupported indicates the command is not supported (X'07') ReplyCommandNotSupported // ReplyAddrTypeNotSupported indicates the address type is not supported (X'08') ReplyAddrTypeNotSupported )
Reply constants for server responses as defined in RFC 1928
const ( // ClientAddrKey is the context key for storing the client's remote address ClientAddrKey contextKey = "client_addr" // ServerAddrKey is the context key for storing the server's local address ServerAddrKey contextKey = "server_addr" // ConnTimeKey is the context key for storing the connection start time ConnTimeKey contextKey = "conn_time" )
Variables ¶
var ( // ErrUserAuthFailed is returned when username/password authentication fails ErrUserAuthFailed = fmt.Errorf("user authentication failed") // ErrNoSupportedAuth is returned when no mutually supported authentication method exists ErrNoSupportedAuth = fmt.Errorf("no supported authentication mechanism") )
var ErrUDPFragmentNoSupported = errors.New("UDP fragmentation not supported")
ErrUDPFragmentNoSupported is returned when a UDP packet indicates fragmentation
Functions ¶
This section is empty.
Types ¶
type AddrSpec ¶
type AddrSpec struct {
// FQDN is the fully qualified domain name (empty if IP is used)
FQDN string
// IP is the IP address (nil if FQDN is used)
IP net.IP
// Port is the port number
Port int
}
AddrSpec represents a SOCKS5 address specification. It can contain either an IP address (IPv4/IPv6) or a fully qualified domain name (FQDN).
type AddressRewriter ¶
type AddressRewriter interface {
// Rewrite takes a request and returns a potentially modified destination address.
// The context may be modified to include additional routing information.
Rewrite(ctx context.Context, request *Request) (context.Context, *AddrSpec)
}
AddressRewriter is used to rewrite a destination address transparently. This can be used for implementing features like traffic routing, load balancing, or address translation. The returned context can contain additional metadata.
type AuthContext ¶
type AuthContext struct {
// Method is the authentication method code that was used
Method uint8
// Payload contains method-specific authentication data.
// For UserPassAuth, contains "Username" key with the authenticated username.
Payload map[string]string
}
AuthContext encapsulates authentication state provided during negotiation. It contains the authentication method used and any associated payload data.
type Authenticator ¶
type Authenticator interface {
// Authenticate performs the authentication handshake with the client
Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error)
// GetCode returns the authentication method code for this authenticator
GetCode() uint8
}
Authenticator defines the interface for SOCKS5 authentication methods. Implementations handle the authentication negotiation for specific methods.
type Config ¶
type Config struct {
// AuthMethods can be provided to implement custom authentication
// By default, "auth-less" mode is enabled.
// For password-based auth use UserPassAuthenticator.
AuthMethods []Authenticator
// If provided, username/password authentication is enabled,
// by appending a UserPassAuthenticator to AuthMethods. If not provided,
// and AUthMethods is nil, then "auth-less" mode is enabled.
Credentials CredentialStore
// Resolver can be provided to do custom name resolution.
// Defaults to DNSResolver if not provided.
Resolver NameResolver
// Rules is provided to enable custom logic around permitting
// various commands. If not provided, PermitAll is used.
Rules RuleSet
// Rewriter can be used to transparently rewrite addresses.
// This is invoked before the RuleSet is invoked.
// Defaults to NoRewrite.
Rewriter AddressRewriter
// BindIP is used for bind or udp associate
BindIP net.IP
// BindPort is the port used for bind or UDP associate operations.
// If set to 0, UDP support is disabled.
BindPort int
// Logger can be used to provide a custom log target.
// Defaults to stdout.
Logger ErrorLogger
// ConnTimeout is the maximum time a connection can be active.
// If zero (default), connections have no timeout.
ConnTimeout time.Duration
// Dial is an optional function for making outbound TCP connections.
// If nil, net.Dial is used.
Dial func(ctx context.Context, network, addr string) (net.Conn, error)
// DialUDP is an optional function for making outbound UDP connections.
// If nil, net.DialUDP is used with a zero source address.
DialUDP func(ctx context.Context, network string, udpClientSrcAddr, targetUDPAddr *net.UDPAddr) (net.Conn, error)
// UDPPacketSize sets the maximum size for UDP packets.
// If zero, defaults to 2048 bytes.
UDPPacketSize int
// UDPSessionTimeout sets how long UDP sessions remain active without traffic.
// If zero, defaults to 5 minutes.
UDPSessionTimeout time.Duration
}
Config is used to setup and configure a SOCKS5 Server. It provides options for authentication, networking, logging, and connection handling.
type CredentialStore ¶
type CredentialStore interface {
// Valid checks if the provided username and password are valid
Valid(user, password string) bool
}
CredentialStore defines the interface for validating user credentials. Implementations should return true if the username/password combination is valid.
type DNSResolver ¶
type DNSResolver struct{}
DNSResolver uses the system's default DNS resolver to resolve hostnames. This is the default resolver used when no custom resolver is provided.
type ErrorLogger ¶
type ErrorLogger interface {
// Printf formats and prints a log message similar to fmt.Printf
Printf(format string, v ...interface{})
}
ErrorLogger is an error handler interface compatible with the standard library logger. It is used by the SOCKS5 server to log errors and diagnostic information.
type NameResolver ¶
type NameResolver interface {
// Resolve resolves a hostname to an IP address, returning the updated context and IP
Resolve(ctx context.Context, name string) (context.Context, net.IP, error)
}
NameResolver defines the interface for resolving hostnames to IP addresses. Custom implementations can provide alternative resolution strategies.
type NoAuthAuthenticator ¶
type NoAuthAuthenticator struct{}
NoAuthAuthenticator is used to handle the "No Authentication" mode
func (NoAuthAuthenticator) Authenticate ¶
func (a NoAuthAuthenticator) Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error)
Authenticate performs the no-auth handshake by simply confirming the method.
func (NoAuthAuthenticator) GetCode ¶
func (a NoAuthAuthenticator) GetCode() uint8
GetCode returns the authentication method code for no authentication.
type PermitCommand ¶
type PermitCommand struct {
// EnableConnect allows or denies CONNECT commands for TCP proxying
EnableConnect bool
// EnableBind allows or denies BIND commands for incoming connections
EnableBind bool
// EnableAssociate allows or denies ASSOCIATE commands for UDP proxying
EnableAssociate bool
}
PermitCommand implements RuleSet to allow or deny specific SOCKS5 commands. It provides granular control over which operations are permitted.
type Request ¶
type Request struct {
// Version is the SOCKS protocol version (should be 5)
Version uint8
// Command is the requested SOCKS command (CONNECT, BIND, ASSOCIATE)
Command uint8
// AuthContext contains authentication information from negotiation
AuthContext *AuthContext
// RemoteAddr is the address of the client that sent the request
RemoteAddr *AddrSpec
// DestAddr is the desired destination address from the client
DestAddr *AddrSpec
// contains filtered or unexported fields
}
Request represents a SOCKS5 request received from a client. It contains the parsed command, destination address, and authentication context.
type RuleSet ¶
type RuleSet interface {
// Allow determines if a request should be permitted, returning updated context and decision
Allow(ctx context.Context, req *Request) (context.Context, bool)
}
RuleSet defines the interface for implementing access control rules. Custom implementations can provide fine-grained control over which requests are allowed.
func PermitAll ¶
func PermitAll() RuleSet
PermitAll returns a RuleSet that allows all SOCKS5 commands (CONNECT, BIND, ASSOCIATE).
func PermitNone ¶
func PermitNone() RuleSet
PermitNone returns a RuleSet that disallows all SOCKS5 commands.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is responsible for accepting connections and handling the details of the SOCKS5 protocol. It supports TCP CONNECT, UDP ASSOCIATE commands, and provides graceful shutdown capabilities.
func New ¶
New creates a new SOCKS5 server with the given configuration. It validates the configuration and sets up default values for any missing required fields. Returns an error if the configuration is invalid.
func (*Server) ListenAndServe ¶
ListenAndServe creates a network listener on the given address and serves SOCKS5 connections. It blocks until the context is cancelled or an error occurs. The network parameter should be "tcp", "tcp4", or "tcp6".
func (*Server) Serve ¶
Serve accepts incoming connections from a listener and handles SOCKS5 protocol negotiations. It starts a UDP server if BindPort is configured, and spawns a goroutine for each TCP connection. This method blocks until the context is cancelled or an error occurs.
type StaticCredentials ¶
StaticCredentials enables using a map directly as a credential store. The map keys are usernames and values are passwords.
func (StaticCredentials) Valid ¶
func (s StaticCredentials) Valid(user, password string) bool
Valid checks if the provided username exists and the password matches.
type UDPSession ¶
type UDPSession struct {
// Context from the ASSOCIATE command, with any rule modifications applied
Context context.Context
// ClientAddr is the client's control connection address for session identification
ClientAddr string
// CreatedAt records when this session was established
CreatedAt time.Time
// LastActivity tracks the last time UDP traffic was seen for this session
LastActivity time.Time
// Request is the original ASSOCIATE request that created this session
Request *Request
}
UDPSession represents an active UDP association session created by an ASSOCIATE command. It tracks the client's context, timing information, and the original request.
type UDPSessionManager ¶
type UDPSessionManager struct {
// contains filtered or unexported fields
}
UDPSessionManager manages active UDP sessions for SOCKS5 UDP association. It provides thread-safe access to sessions and automatic cleanup of idle sessions.
func NewUDPSessionManager ¶
func NewUDPSessionManager(sessionTimeout time.Duration) *UDPSessionManager
NewUDPSessionManager creates and initializes a new UDP session manager. It starts a background goroutine for cleaning up expired sessions.
func (*UDPSessionManager) GetSession ¶
func (m *UDPSessionManager) GetSession(clientAddr string) (*UDPSession, bool)
GetSession retrieves a UDP session by exact client address match.
func (*UDPSessionManager) GetSessionByIP ¶ added in v0.1.1
func (m *UDPSessionManager) GetSessionByIP(clientIP string) *UDPSession
GetSessionByIP retrieves a UDP session by client IP only, ignoring port. This is useful when client port numbers change but IP remains the same.
func (*UDPSessionManager) RegisterSession ¶
func (m *UDPSessionManager) RegisterSession(clientAddr string, ctx context.Context, req *Request)
RegisterSession creates and registers a new UDP session for the given client. The session will be indexed by both full address and IP-only for flexible lookup.
func (*UDPSessionManager) Stop ¶
func (m *UDPSessionManager) Stop()
Stop gracefully shuts down the session manager and its cleanup goroutine.
func (*UDPSessionManager) UnregisterSession ¶
func (m *UDPSessionManager) UnregisterSession(clientAddr string)
UnregisterSession removes a UDP session from both address indexes.
func (*UDPSessionManager) UpdateActivity ¶ added in v0.1.1
func (m *UDPSessionManager) UpdateActivity(clientAddr string)
UpdateActivity updates the last activity timestamp for a session by exact address.
func (*UDPSessionManager) UpdateActivityByIP ¶ added in v0.1.1
func (m *UDPSessionManager) UpdateActivityByIP(clientIP string)
UpdateActivityByIP updates the last activity timestamp for a session by IP only.
type UserPassAuthenticator ¶
type UserPassAuthenticator struct {
Credentials CredentialStore
}
UserPassAuthenticator is used to handle username/password based authentication
func (UserPassAuthenticator) Authenticate ¶
func (a UserPassAuthenticator) Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error)
Authenticate performs username/password authentication as per RFC 1929. It reads the username and password from the client and validates them using the credential store.
func (UserPassAuthenticator) GetCode ¶
func (a UserPassAuthenticator) GetCode() uint8
GetCode returns the authentication method code for username/password authentication.