Documentation
¶
Index ¶
- Constants
- Variables
- func BaseOnBind(ctx context.Context, conn net.Conn, req *Request, ...) error
- func BaseOnConnect(ctx context.Context, conn net.Conn, req *Request, dialer socksnet.Dialer, ...) error
- func BaseOnRequest(ctx context.Context, handler ServerHandler, conn net.Conn, req *Request) error
- func ListenAndServe(ctx context.Context, network, address string, handler ServerHandler) error
- func Serve(ctx context.Context, listener net.Listener, handler ServerHandler) error
- func ServeConn(ctx context.Context, handler ServerHandler, conn net.Conn) error
- func WriteRejectReply(conn net.Conn, code byte)
- func WriteSuccessReply(conn net.Conn, addr net.Addr) error
- type BaseServerHandler
- func (d *BaseServerHandler) OnAccept(ctx context.Context, conn net.Conn) error
- func (d *BaseServerHandler) OnBind(ctx context.Context, conn net.Conn, req *Request) error
- func (d *BaseServerHandler) OnConnect(ctx context.Context, conn net.Conn, req *Request) error
- func (d *BaseServerHandler) OnError(ctx context.Context, conn net.Conn, err error)
- func (d *BaseServerHandler) OnPanic(ctx context.Context, conn net.Conn, r any)
- func (d *BaseServerHandler) OnRequest(ctx context.Context, conn net.Conn, req *Request) error
- func (d *BaseServerHandler) OnUserID(ctx context.Context, conn net.Conn, userID string, hasUserID bool) error
- type Dialer
- func (d *Dialer) Bind(network, address string) (net.Conn, *net.TCPAddr, <-chan error, error)
- func (d *Dialer) BindContext(ctx context.Context, network, address string) (net.Conn, *net.TCPAddr, <-chan error, error)
- func (d *Dialer) Dial(network, address string) (net.Conn, error)
- func (d *Dialer) DialConn(conn net.Conn, network, address string) (net.Conn, error)
- func (d *Dialer) DialConnContext(ctx context.Context, conn net.Conn, network, address string) (net.Conn, error)
- func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error)
- func (d *Dialer) ProxyAddress() string
- type Reply
- func (r *Reply) GetIP() net.IP
- func (r *Reply) Init(version, code byte, port uint16, ip net.IP)
- func (r *Reply) IsGranted() bool
- func (r *Reply) ReadFrom(src io.Reader) (int64, error)
- func (r *Reply) String() string
- func (r *Reply) Validate() error
- func (r *Reply) WriteTo(dst io.Writer) (int64, error)
- type Request
- func (r *Request) Addr() string
- func (r *Request) Host() string
- func (r *Request) IPv4() net.IP
- func (r *Request) Init(version byte, command byte, port uint16, ip net.IP, userID string, ...)
- func (r *Request) IsSOCKS4() bool
- func (r *Request) IsSOCKS4a() bool
- func (r *Request) ReadFrom(src io.Reader) (int64, error)
- func (r *Request) ReadFromWithLimits(src io.Reader, maxUserIDLen, maxDomainLen int64) (int64, error)
- func (r *Request) ReadHeaderFrom(src io.Reader) (int64, error)
- func (r *Request) ReadUserIDAndDomain(src io.Reader, maxUserIDLen, maxDomainLen int64) (int64, error)
- func (r *Request) String() string
- func (r *Request) Validate() error
- func (r *Request) ValidateDomain() error
- func (r *Request) ValidateHeader() error
- func (r *Request) WriteTo(dst io.Writer) (int64, error)
- type ServerHandler
Constants ¶
const ( CmdConnect = 1 CmdBind = 2 )
Command codes (CD) for client requests.
const ( DefaultMaxUserIDLen = 256 DefaultMaxDomainLen = 256 )
Default maximum lengths for SOCKS4a string fields.
const ( RepGranted = 90 RepRejected = 91 RepIdentFailed = 92 RepUserIDMismatch = 93 )
Reply codes (CD) for server responses.
const (
SocksVersion = 4
)
Protocol version.
Variables ¶
var ( ErrInvalidResponseVersion = errors.New("invalid SOCKS4 reply version (must be 0x00)") ErrInvalidResponseCode = errors.New("invalid SOCKS4 reply code") )
SOCKS4 reply error codes and helpers.
Functions ¶
func BaseOnBind ¶
func BaseOnBind(ctx context.Context, conn net.Conn, req *Request, acceptTimeout, connTimeout time.Duration, bufferSize int) error
BaseOnBind provides BIND implementation
func BaseOnConnect ¶
func BaseOnConnect(ctx context.Context, conn net.Conn, req *Request, dialer socksnet.Dialer, connTimeout time.Duration, bufferSize int) error
BaseOnConnect provides CONNECT implementation
func BaseOnRequest ¶
BaseOnRequest provides request handling logic for both CONNECT and BIND commands.
func ListenAndServe ¶
func ListenAndServe(ctx context.Context, network, address string, handler ServerHandler) error
ListenAndServe listens on the network address and serves SOCKS4 requests.
func ServeConn ¶
ServeConn handles a single client connection, including reading the request and processing it.
func WriteRejectReply ¶
WriteRejectReply sends a SOCKS4 reply with the given rejection code.
Types ¶
type BaseServerHandler ¶
type BaseServerHandler struct {
Dialer socksnet.Dialer
RequestTimeout time.Duration
BindAcceptTimeout time.Duration
BindConnTimeout time.Duration
ConnectConnTimeout time.Duration
ConnectBufferSize int
AllowConnect bool
AllowBind bool
// UserIDChecker is a function that validates the user ID from the SOCKS4 request.
// It should return an error if the user ID is not allowed, or nil to accept the request.
// If nil, all user IDs will be accepted by default.
UserIDChecker func(ctx context.Context, userID string) error
}
BaseServerHandler provides a basic implementation of ServerHandler with configurable options.
type Dialer ¶
type Dialer struct {
ProxyAddr string // e.g. "127.0.0.1:1080"
UserID string // optional SOCKS4 user ID
Dialer socksnet.Dialer // optional underlying dialer (nil=DefaultDialer)
}
Dialer implements a SOCKS4/4a proxy dialer.
func (*Dialer) BindContext ¶
func (d *Dialer) BindContext( ctx context.Context, network, address string, ) (net.Conn, *net.TCPAddr, <-chan error, error)
BindContext establishes a passive BIND connection via SOCKS4 proxy (CMD_BIND). It returns the active connection and the proxy’s bind address once ready. BindContext establishes a passive BIND connection via SOCKS4 proxy.
func (*Dialer) DialConnContext ¶
func (d *Dialer) DialConnContext(ctx context.Context, conn net.Conn, network, address string) (net.Conn, error)
DialConnContext upgrades an existing connection via SOCKS4/4a proxy (CONNECT command).
func (*Dialer) DialContext ¶
DialContext establishes a connection via SOCKS4/4a proxy (CONNECT command).
func (*Dialer) ProxyAddress ¶
ProxyAddress returns the configured SOCKS4 proxy address.
type Reply ¶
type Reply struct {
Version byte // VN; always 0x00 per SOCKS4 spec
Code byte // CD; reply code (0x5A = granted, 0x5B–0x5D = failure)
Port uint16 // DSTPORT; server-assigned or echoed port
IP [4]byte // DSTIP; server-assigned or echoed address
}
Reply represents a SOCKS4 or SOCKS4a CONNECT/BIND server reply.
type Request ¶
type Request struct {
Version byte // VN; SOCKS protocol version (should always be 4)
Command byte // CD; command code (1 = CONNECT, 2 = BIND)
Port uint16 // DSTPORT; destination port (big-endian)
IP [4]byte // DSTIP; destination IPv4 address, or 0.0.0.x for SOCKS4a
UserID string // USERID; null-terminated user identifier
Domain string // DOMAIN; null-terminated domain name (SOCKS4a only)
}
Request represents a SOCKS4 or SOCKS4a CONNECT/BIND request.
func (*Request) Init ¶
func (r *Request) Init( version byte, command byte, port uint16, ip net.IP, userID string, domain string, )
Init initializes a SOCKS4 or SOCKS4a CONNECT/BIND request.
func (*Request) ReadFrom ¶
ReadFrom reads a SOCKS4 or SOCKS4a CONNECT/BIND request from a Reader. Implements the io.ReaderFrom interface.
func (*Request) ReadFromWithLimits ¶
func (r *Request) ReadFromWithLimits(src io.Reader, maxUserIDLen, maxDomainLen int64) (int64, error)
ReadFromWithLimits reads a 8-byte SOCKS4 or SOCKS4a CONNECT/BIND request from a Reader. Note that the limits do not include the null-terminator.
func (*Request) ReadHeaderFrom ¶
ReadHeaderFrom reads a 8-byte SOCKS4 or SOCKS4a CONNECT/BIND request from a Reader.
func (*Request) ReadUserIDAndDomain ¶
func (r *Request) ReadUserIDAndDomain(src io.Reader, maxUserIDLen, maxDomainLen int64) (int64, error)
ReadUserIDAndDomain reads a 8-byte SOCKS4 or SOCKS4a CONNECT/BIND request from a Reader. Note that the limits do not include the null-terminator. Beware if there is data beyond request it can be dropped.
func (*Request) ValidateDomain ¶
Validate validates a SOCKS4 or SOCKS4a CONNECT/BIND request (SOCKS4a only).
func (*Request) ValidateHeader ¶
ValidateHeader validates a SOCKS4 or SOCKS4a CONNECT/BIND request header (first 8 bytes).
type ServerHandler ¶
type ServerHandler interface {
// OnAccept is called for each accepted connection.
OnAccept(ctx context.Context, conn net.Conn) error
// OnUserID is called to validate the user ID from the SOCKS4 request.
OnUserID(ctx context.Context, conn net.Conn, userID string, hasUserID bool) error
// OnRequest is called for each request.
OnRequest(ctx context.Context, conn net.Conn, req *Request) error
// OnConnect is called for each CONNECT request.
OnConnect(ctx context.Context, conn net.Conn, req *Request) error
// OnBind is called for each BIND request.
OnBind(ctx context.Context, conn net.Conn, req *Request) error
// OnError is called for each connection error.
OnError(ctx context.Context, conn net.Conn, err error)
// OnPanic is called when a panic occurs in any handler goroutine.
OnPanic(ctx context.Context, conn net.Conn, r any)
}
ServerHandler handles SOCKS4 server events.
var DefaultServerHandler ServerHandler = &BaseServerHandler{ RequestTimeout: 10 * time.Second, BindAcceptTimeout: 10 * time.Second, BindConnTimeout: 60 * time.Second, ConnectConnTimeout: 60 * time.Second, ConnectBufferSize: 1024 * 32, AllowConnect: true, AllowBind: false, }
DefaultServerHandler is a default implementation used when no custom ServerHandler is provided to Serve or ListenAndServe.