Documentation
¶
Overview ¶
Package protocol implements low-level SOCKS protocol encoding and decoding.
This package provides the building blocks for SOCKS4, SOCKS4a, and SOCKS5 protocols, including address representation, command codes, reply status codes, authentication negotiation, and wire format encoding/decoding.
Protocol References ¶
- RFC 1928: SOCKS Protocol Version 5
- RFC 1929: Username/Password Authentication for SOCKS V5
- SOCKS4/SOCKS4a: https://www.openssh.com/txt/socks4.protocol
- Tor SOCKS Extensions: https://spec.torproject.org/socks-extensions.html
Index ¶
- Constants
- Variables
- func AppendSocks5UDPHeader(buf []byte, rsv uint16, addr Addr) []byte
- func BuildSocks4TCPReply(stat ReplyStatus, addr Addr, pool bufpool.Pool) (request []byte)
- func BuildSocks5TCPReply(stat ReplyStatus, addr Addr, pool bufpool.Pool) (reply []byte, err error)
- func BuildSocks5TCPRequest(cmd Cmd, addr Addr, pool bufpool.Pool) (request []byte, err error)
- func BuildSocsk4TCPRequest(cmd Cmd, addr Addr, user string, pool bufpool.Pool) (request []byte, err error)
- func GetAuthParam[T any](info AuthInfo, key string) (ok bool, val T)
- func JoinNetErrors(a, b error) (err error)
- func ProxySocks5UDPAssoc(assoc, proxy gonnect.PacketConn, ctrl net.Conn, binded bool, defaultAddr *Addr, ...) (err error)
- func ProxySocks5UDPTun(tun net.Conn, proxy gonnect.PacketConn, binded bool, defaultAddr *Addr, ...) (err error)
- func ReadSocks4TCPReply(reader io.Reader) (stat ReplyStatus, addr Addr, err error)
- func ReadSocks4TCPRequest(reader io.Reader, pool bufpool.Pool) (cmd Cmd, addr Addr, user string, err error)
- func ReadSocks5TCPReply(reader io.Reader, pool bufpool.Pool) (stat ReplyStatus, addr Addr, err error)
- func ReadSocks5TCPRequest(reader io.Reader, pool bufpool.Pool) (cmd Cmd, addr Addr, err error)
- func Reject(ver string, conn net.Conn, stat ReplyStatus, pool bufpool.Pool)
- func Reply(ver string, conn net.Conn, stat ReplyStatus, addr Addr, pool bufpool.Pool) (err error)
- func WriteSocks5TUNUDPPacket(pool bufpool.Pool, conn net.Conn, addr Addr, data []byte) (n int, err error)
- func WriteSocksAssoc5UDPPacket(pool bufpool.Pool, conn gonnect.PacketConn, peerAddr net.Addr, addr Addr, ...) (n int, err error)
- func WriteToAddrUDP(conn gonnect.PacketConn, addr Addr, b []byte) (err error)
- type Addr
- func AddrFromFQDN(fqdn string, port uint16, net string) Addr
- func AddrFromFQDNNoDot(fqdn string, port uint16, net string) Addr
- func AddrFromHostPort(hostport, network string) Addr
- func AddrFromIP(ip net.IP, port uint16, net string) Addr
- func AddrFromNetAddr(addr net.Addr) Addr
- func AddrFromNetIPAddrPort(addrPort netip.AddrPort, network ...string) Addr
- func AddrFromString(host string, port uint16, network string) Addr
- func AddrFromTCPAddr(t *net.TCPAddr) Addr
- func AddrFromUDPAddr(u *net.UDPAddr) Addr
- func ReadSocks5AssocUDPPacket(pool bufpool.Pool, conn net.PacketConn, p []byte, skipAddr bool, ...) (n int, addr Addr, incAddr net.Addr, err error)
- func ReadSocks5TunUDPPacket(pool bufpool.Pool, conn net.Conn, p []byte, skipAddr bool) (n int, addr Addr, err error)
- func (a Addr) Copy() Addr
- func (a Addr) IpNetwork() string
- func (a Addr) IsUnspecified() bool
- func (a Addr) Len() int
- func (a Addr) Network() string
- func (a Addr) PortStr() string
- func (a Addr) ResolveToIP4(ctx context.Context, ...) *Addr
- func (a Addr) String() string
- func (a Addr) ToFQDN() string
- func (a Addr) ToHostPort() string
- func (a Addr) ToIP() net.IP
- func (a Addr) ToTCP() *net.TCPAddr
- func (a Addr) ToUDP() *net.UDPAddr
- func (a Addr) ToUnspecified() Addr
- func (a Addr) WithDefaultAddr(def *Addr) Addr
- func (a Addr) WithDefaultHost(host string) Addr
- func (a Addr) WithNetTyp(nt string) Addr
- type AddrType
- type AuthHandler
- type AuthHandlers
- type AuthInfo
- type AuthMethod
- type AuthMethodCode
- type AuthMethods
- type Cmd
- type GSSAPIClient
- type GSSAPIServer
- type GSSAuthHandler
- type GSSAuthMethod
- type NoAuthHandler
- type PassAuthHandler
- type PassAuthMethod
- type ReplyStatus
- type Socks5UDPClient
- type Socks5UDPClientAssoc
- func (uc *Socks5UDPClientAssoc) Close() error
- func (uc *Socks5UDPClientAssoc) Read(b []byte) (n int, err error)
- func (uc *Socks5UDPClientAssoc) ReadFrom(p []byte) (n int, addr net.Addr, err error)
- func (uc *Socks5UDPClientAssoc) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error)
- func (uc *Socks5UDPClientAssoc) ReadFromUDPAddrPort(b []byte) (n int, addr netip.AddrPort, err error)
- func (uc *Socks5UDPClientAssoc) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error)
- func (uc *Socks5UDPClientAssoc) ReadMsgUDPAddrPort(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error)
- func (uc *Socks5UDPClientAssoc) RemoteAddr() net.Addr
- func (uc *Socks5UDPClientAssoc) Write(b []byte) (n int, err error)
- func (uc *Socks5UDPClientAssoc) WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error)
- func (uc *Socks5UDPClientAssoc) WriteMsgUDPAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn int, err error)
- func (uc *Socks5UDPClientAssoc) WriteTo(p []byte, addr net.Addr) (n int, err error)
- func (uc *Socks5UDPClientAssoc) WriteToIpPort(p []byte, ip net.IP, port uint16) (n int, err error)
- func (uc *Socks5UDPClientAssoc) WriteToUDP(b []byte, addr *net.UDPAddr) (int, error)
- func (uc *Socks5UDPClientAssoc) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error)
- type Socks5UDPClientTUN
- func (uc *Socks5UDPClientTUN) Close() error
- func (uc *Socks5UDPClientTUN) LocalAddr() net.Addr
- func (uc *Socks5UDPClientTUN) Read(b []byte) (n int, err error)
- func (uc *Socks5UDPClientTUN) ReadFrom(p []byte) (n int, addr net.Addr, err error)
- func (uc *Socks5UDPClientTUN) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error)
- func (uc *Socks5UDPClientTUN) ReadFromUDPAddrPort(b []byte) (n int, addr netip.AddrPort, err error)
- func (uc *Socks5UDPClientTUN) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error)
- func (uc *Socks5UDPClientTUN) ReadMsgUDPAddrPort(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error)
- func (uc *Socks5UDPClientTUN) RemoteAddr() net.Addr
- func (uc *Socks5UDPClientTUN) Write(b []byte) (n int, err error)
- func (uc *Socks5UDPClientTUN) WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error)
- func (uc *Socks5UDPClientTUN) WriteMsgUDPAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn int, err error)
- func (uc *Socks5UDPClientTUN) WriteTo(p []byte, addr net.Addr) (n int, err error)
- func (uc *Socks5UDPClientTUN) WriteToIpPort(p []byte, ip net.IP, port uint16) (n int, err error)
- func (uc *Socks5UDPClientTUN) WriteToUDP(b []byte, addr *net.UDPAddr) (int, error)
- func (uc *Socks5UDPClientTUN) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error)
- type UnknownAddrTypeError
- type UnknownAuthVerError
- type UnsupportedAuthMethodError
- type Wrong4ReplyVerError
- type WrongProtocolVerError
Constants ¶
const ( // MAX_HEADER_STR_LENGTH is the maximum length for string fields in the // SOCKS protocol (e.g., FQDN in address, username in auth). // This is a hard limit. MAX_HEADER_STR_LENGTH = 255 // MAX_SOCKS_TCP_HEADER_LEN is the maximum size of a SOCKS TCP request // or reply header. Calculated as: // - 3 bytes: version + command/reserved + address type // - 1 byte: FQDN length (if applicable) // - 255 bytes: maximum FQDN length // - 2 bytes: port // Total: 7 + 255 = 262 bytes MAX_SOCKS_TCP_HEADER_LEN = 7 + MAX_HEADER_STR_LENGTH // MAX_SOCKS_UDP_HEADER_LEN is the maximum size of a SOCKS5 UDP packet // header. Has the same structure as TCP header: // - 2 bytes: RSV (reserved/fragment) // - 1 byte: FRAG (fragment flag) // - 1 byte: address type // - 1 byte: FQDN length (if applicable) // - 255 bytes: maximum FQDN length // - 2 bytes: port // Total: 7 + 255 = 262 bytes MAX_SOCKS_UDP_HEADER_LEN = 7 + MAX_HEADER_STR_LENGTH // GOST_UDP_FRAG_FLAG is the fragment value used in Gost's UDP Tunnel // extension to indicate a complete (non-fragmented) packet. // Standard SOCKS5 uses 0x00 for no fragmentation. // Gost uses 0xFF (255) to identify its UDP tunnel format. GOST_UDP_FRAG_FLAG = 255 // MAX_AUTH_METHODS_COUNT is the maximum number of authentication methods // a client can advertise in the SOCKS5 authentication negotiation. // The SOCKS5 protocol uses a single byte for the count, limiting it to // 255 methods (0 is reserved, so 255 is the practical maximum). MAX_AUTH_METHODS_COUNT = 255 )
Protocol constants for buffer sizes and limits.
These constants define maximum sizes for various SOCKS protocol elements and are used for buffer allocation throughout the library.
Variables ¶
var ( // ErrNoAcceptableAuthMethods is returned when the server doesn't // support any of the client's advertised authentication methods. ErrNoAcceptableAuthMethods = errors.New("no acceptable socks auth methods") // ErrTooLongUser is returned when a username exceeds the maximum // allowed length (MAX_HEADER_STR_LENGTH = 255 bytes). ErrTooLongUser = errors.New("socks user name is too long") // ErrTooLongHost is returned when a hostname/FQDN exceeds the // maximum allowed length (MAX_HEADER_STR_LENGTH = 255 bytes). ErrTooLongHost = errors.New("socks host name is too long") // ErrUDPAssocTimeout is returned when a UDP association times out // due to inactivity. ErrUDPAssocTimeout = errors.New("socks udp assoc timeout") )
Protocol-level error values.
These errors are returned when protocol encoding/decoding fails or when protocol constraints are violated.
var ( DefaultMethodSelectionMsg = []byte{ 5, 1, byte(NoAuthCode), } )
Functions ¶
func AppendSocks5UDPHeader ¶
AppendSocks5UDPHeader appends a SOCKS5 UDP header to a buffer.
Builds the header for either standard UDP ASSOC or Gost UDP Tunnel:
- Standard: rsv=0, frag=0
- Gost TUN: rsv=payload length, frag=0xFF
Header Format ¶
+----+------+------+----------+----------+ |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | +----+------+------+----------+----------+ | 2 | 1 | 1 | Variable | 2 | +----+------+------+----------+----------+
Parameters ¶
- buf: Buffer to append to (may be nil for new allocation)
- rsv: Reserved field (0 for standard, payload length for Gost)
- addr: Destination address
Returns ¶
The buffer with the header appended.
func BuildSocks4TCPReply ¶
func BuildSocks4TCPReply( stat ReplyStatus, addr Addr, pool bufpool.Pool, ) (request []byte)
BuildSocks4TCPReply builds a SOCKS4 TCP reply.
Creates a reply packet with the given status and bound address. If the address is not IPv4, uses 0.0.0.0 as the IP.
Wire Format ¶
+----+----+----+----+----+----+----+----+ | VN | CD | DSTPORT | DSTIP | +----+----+----+----+----+----+----+----+ 1 1 2 4
Where:
- VN: Reply version (always 0)
- CD: Status code (Granted, Rejected, etc.)
- DSTPORT: Bound port (big-endian)
- DSTIP: Bound IP address
Parameters ¶
- stat: Reply status code (automatically converted to SOCKS4 format)
- addr: Bound address (typically the server's listening address)
- pool: Buffer pool for allocation
Returns ¶
The reply byte slice. The returned buffer must be returned to the pool after use.
Examples ¶
addr := protocol.AddrFromIP(net.ParseIP("192.168.1.1"), 8080, "")
reply := protocol.BuildSocks4TCPReply(protocol.Granted, addr, pool)
defer bufpool.PutBuffer(pool, reply)
func BuildSocks5TCPReply ¶
func BuildSocks5TCPReply( stat ReplyStatus, addr Addr, pool bufpool.Pool, ) (reply []byte, err error)
BuildSocks5TCPReply builds a SOCKS5 TCP reply.
Creates a reply packet with the given status and bound address. The reply format is identical to the request format, with the CMD field repurposed to carry the status code.
Wire Format (RFC 1928) RFC 1928)" aria-label="Go to Wire Format (RFC 1928)">¶
+----+-----+-------+------+----------+----------+ |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | +----+-----+-------+------+----------+----------+ | 1 | 1 | 1 | 1 | Variable | 2 | +----+-----+-------+------+----------+----------+
Where:
- VER: Protocol version (0x05)
- REP: Reply status code (SuccReply, FailReply, etc.)
- RSV: Reserved (0x00)
- ATYP: Address type
- BND.ADDR: Bound address
- BND.PORT: Bound port
Parameters ¶
- stat: Reply status code (automatically converted to SOCKS5 format)
- addr: Bound address (typically the server's listening address)
- pool: Buffer pool for allocation
Returns ¶
The reply byte slice. The returned buffer must be returned to the pool after use.
Examples ¶
addr := protocol.AddrFromIP(net.ParseIP("192.168.1.1"), 8080, "tcp")
reply, err := protocol.BuildSocks5TCPReply(protocol.SuccReply, addr, pool)
defer bufpool.PutBuffer(pool, reply)
func BuildSocks5TCPRequest ¶
BuildSocks5TCPRequest builds a SOCKS5 TCP request.
Creates a request packet for the given command and address.
Wire Format (RFC 1928) RFC 1928)" aria-label="Go to Wire Format (RFC 1928)">¶
+----+-----+-------+------+----------+----------+ |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | +----+-----+-------+------+----------+----------+ | 1 | 1 | 1 | 1 | Variable | 2 | +----+-----+-------+------+----------+----------+
Where:
- VER: Protocol version (0x05)
- CMD: Command code (Connect, Bind, UDPAssoc, etc.)
- RSV: Reserved (0x00)
- ATYP: Address type (IP4=0x01, IP6=0x04, FQDN=0x03)
- DST.ADDR: Destination address (4/16 bytes for IP, variable for FQDN)
- DST.PORT: Destination port (big-endian)
Parameters ¶
- cmd: Command code (CmdConnect, CmdBind, CmdUDPAssoc, or extension commands)
- addr: Target address
- pool: Buffer pool for allocation
Returns ¶
The request byte slice, or an error if the hostname is too long. The returned buffer must be returned to the pool after use.
Examples ¶
addr := protocol.AddrFromFQDN("example.com", 80, "tcp")
req, err := protocol.BuildSocks5TCPRequest(protocol.CmdConnect, addr, pool)
defer bufpool.PutBuffer(pool, req)
func BuildSocsk4TCPRequest ¶
func BuildSocsk4TCPRequest( cmd Cmd, addr Addr, user string, pool bufpool.Pool, ) (request []byte, err error)
BuildSocsk4TCPRequest builds a SOCKS4 or SOCKS4a TCP request.
For IPv4 addresses, builds a standard SOCKS4 request. For other address types (FQDN), builds a SOCKS4a request with the domain name appended after the username.
Wire Format (SOCKS4) ¶
+----+----+----+----+----+----+----+----+----+----+ ... +----+ | VN | CD | DSTPORT | DSTIP | USERID |NULL| +----+----+----+----+----+----+----+----+----+----+ ... +----+ 1 1 2 4 variable 1
Wire Format (SOCKS4a) ¶
+----+----+----+----+----+----+----+----+----+----+ ... +----+----+ ... +----+ | VN | CD | DSTPORT | DSTIP | USERID |NULL| HOST |NULL| +----+----+----+----+----+----+----+----+----+----+ ... +----+----+ ... +----+ 1 1 2 4 variable 1 variable 1
Parameters ¶
- cmd: Command code (typically CmdConnect)
- addr: Target address
- user: Username (may be empty)
- pool: Buffer pool for allocation
Returns ¶
The request byte slice, or an error if the hostname is too long. The returned buffer must be returned to the pool after use.
Examples ¶
addr := protocol.AddrFromIP(net.ParseIP("192.168.1.1"), 80, "")
req, err := protocol.BuildSocsk4TCPRequest(protocol.CmdConnect, addr, "", pool)
defer bufpool.PutBuffer(pool, req)
func GetAuthParam ¶
GetAuthParam retrieves a typed parameter from AuthInfo.Info.
This is a type-safe helper for extracting authentication parameters. Returns (false, zero) if the key doesn't exist or the type doesn't match.
Type Parameter ¶
T - The expected type of the parameter ¶
Examples ¶
info, _ := protocol.RunAuth(conn, pool, methods)
if user, ok := protocol.GetAuthParam[string](info, "user"); ok {
fmt.Printf("Username: %s\n", user)
}
if token, ok := protocol.GetAuthParam[[]byte](info, "token"); ok {
// Use GSS token
}
func JoinNetErrors ¶ added in v0.2.0
joinNetErrors joins two errors, treating closed network connection errors as nil.
func ProxySocks5UDPAssoc ¶
func ProxySocks5UDPAssoc( assoc, proxy gonnect.PacketConn, ctrl net.Conn, binded bool, defaultAddr *Addr, pool bufpool.Pool, bufSize int, timeOut time.Duration, ) (err error)
ProxySocks5UDPAssoc proxies UDP packets between a SOCKS5 client and a target UDP server using standard UDP ASSOCIATE.
This function runs two goroutines:
- Client -> Proxy: Reads SOCKS5 UDP packets, strips headers, forwards to target
- Proxy -> Client: Reads UDP responses, adds SOCKS5 headers, sends to client
The control connection (ctrl) is monitored for closure. When it closes, both UDP connections are closed and the function returns.
Parameters ¶
- assoc: Client's UDP association (from UDP ASSOCIATE command)
- proxy: Outgoing UDP connection to target server
- ctrl: Control TCP connection (monitored for closure)
- binded: If true, all packets use a fixed remote address
- defaultAddr: Default destination for unbound packets
- pool: Buffer pool for allocations
- bufSize: Buffer size for packet copying
- timeOut: Idle timeout for UDP association
Returns ¶
Error if any connection fails, including ErrUDPAssocTimeout on timeout.
Thread Safety ¶
This function spawns goroutines and blocks until all connections close.
func ProxySocks5UDPTun ¶
func ProxySocks5UDPTun( tun net.Conn, proxy gonnect.PacketConn, binded bool, defaultAddr *Addr, pool bufpool.Pool, bufSize int, ) (err error)
ProxySocks5UDPTun proxies UDP packets between a Gost UDP Tunnel client and a target UDP server.
Unlike ProxySocks5UDPAssoc, this function works with a TCP connection (tun) that carries encapsulated UDP packets. No separate control connection is needed since the TCP connection itself carries the data.
This function runs two goroutines:
- Client -> Proxy: Reads Gost UDP packets from TCP, forwards to target
- Proxy -> Client: Reads UDP responses, encapsulates in Gost format, sends via TCP
Parameters ¶
- tun: Client's TCP connection (Gost UDP Tunnel)
- proxy: Outgoing UDP connection to target server
- binded: If true, all packets use a fixed remote address
- defaultAddr: Default destination for unbound packets
- pool: Buffer pool for allocations
- bufSize: Buffer size for packet copying
Returns ¶
Error if any connection fails.
Thread Safety ¶
This function spawns goroutines and blocks until all connections close.
func ReadSocks4TCPReply ¶
func ReadSocks4TCPReply(reader io.Reader) ( stat ReplyStatus, addr Addr, err error, )
ReadSocks4TCPReply reads and parses a SOCKS4 TCP reply.
Reads an 8-byte reply packet and extracts the status code and bound address.
Wire Format ¶
+----+----+----+----+----+----+----+----+ | VN | CD | DSTPORT | DSTIP | +----+----+----+----+----+----+----+----+ # bytes: 1 1 2 4
Parameters ¶
- reader: Source to read from
Returns ¶
- stat: Reply status code (converted to SOCKS4 format)
- addr: Bound address (only valid if status is Granted)
- err: Error if parsing fails or version is invalid
Errors ¶
Returns Wrong4ReplyVerError if the version byte is not 0.
func ReadSocks4TCPRequest ¶
func ReadSocks4TCPRequest(reader io.Reader, pool bufpool.Pool) ( cmd Cmd, addr Addr, user string, err error, )
ReadSocks4TCPRequest reads and parses a SOCKS4/4a TCP request.
Reads the request from the reader and extracts the command, address, and username. Automatically detects SOCKS4a extension by checking for the special address pattern (0.0.0.1 with non-zero domain).
Parameters ¶
- reader: Source to read from
- pool: Buffer pool for temporary allocations
Returns ¶
- cmd: Command code
- addr: Target address
- user: Username (may be empty)
- err: Error if parsing fails
Note ¶
The function expects to be called AFTER reading the version byte. It reads from the command byte onward.
func ReadSocks5TCPReply ¶
func ReadSocks5TCPReply(reader io.Reader, pool bufpool.Pool) ( stat ReplyStatus, addr Addr, err error, )
ReadSocks5TCPReply reads and parses a SOCKS5 TCP reply.
Reads a reply packet and extracts the status code and bound address. Internally uses ReadSocks5TCPRequest since the wire format is identical, then converts the command code to a status code.
Parameters ¶
- reader: Source to read from
- pool: Buffer pool for temporary allocations
Returns ¶
- stat: Reply status code (converted to SOCKS5 format)
- addr: Bound address (only valid if status indicates success)
- err: Error if parsing fails
func ReadSocks5TCPRequest ¶
ReadSocks5TCPRequest reads and parses a SOCKS5 TCP request.
Reads a request packet and extracts the command and address. Supports all three address types: IPv4, IPv6, and FQDN.
Parameters ¶
- reader: Source to read from
- pool: Buffer pool for temporary allocations
Returns ¶
- cmd: Command code
- addr: Target address
- err: Error if parsing fails
Errors ¶
- WrongProtocolVerError: If version byte is not 0x05
- UnknownAddrTypeError: If address type is not recognized
func Reject ¶
Reject sends a rejection reply and closes the connection.
A convenience function that sends a failure reply with a zero bound address (0.0.0.0:0) and closes the connection.
Parameters ¶
- ver: Protocol version ("4", "4a", "5", or "5h")
- conn: Connection to reject
- stat: Rejection status code
- pool: Buffer pool for allocation
Behavior ¶
The connection is always closed, even if sending the reply fails.
Examples ¶
// Reject SOCKS5 request
protocol.Reject("5", conn, protocol.DisallowReply, pool)
// Reject SOCKS4 request
protocol.Reject("4", conn, protocol.Rejected, pool)
func Reply ¶
func Reply( ver string, conn net.Conn, stat ReplyStatus, addr Addr, pool bufpool.Pool, ) (err error)
Reply sends a SOCKS reply packet.
Builds and sends a protocol-specific reply (SOCKS4 or SOCKS5) with automatic status code conversion between protocol versions.
Protocol Versions ¶
- "4" / "4a": Uses SOCKS4 reply format, status converted via To4()
- "5" / "5h": Uses SOCKS5 reply format, status converted via To5()
Parameters ¶
- ver: Protocol version ("4", "4a", "5", or "5h")
- conn: Connection to send reply on
- stat: Reply status code (automatically converted to appropriate format)
- addr: Bound address to include in reply
- pool: Buffer pool for allocation
Returns ¶
Error if building or sending the reply fails.
Examples ¶
// SOCKS5 success reply
addr := protocol.AddrFromIP(net.ParseIP("192.168.1.1"), 8080, "tcp")
err := protocol.Reply("5", conn, protocol.SuccReply, addr, pool)
// SOCKS4 rejection reply
err := protocol.Reply("4", conn, protocol.Rejected, addr, pool)
func WriteSocks5TUNUDPPacket ¶
func WriteSocks5TUNUDPPacket( pool bufpool.Pool, conn net.Conn, addr Addr, data []byte, ) (n int, err error)
Builds ans writes gost's socks5 extension's UDP TUN packet to conn
func WriteSocksAssoc5UDPPacket ¶
func WriteSocksAssoc5UDPPacket( pool bufpool.Pool, conn gonnect.PacketConn, peerAddr net.Addr, addr Addr, data []byte, ) (n int, err error)
Builds and writes socks5 UDP Assoc packet to conn
func WriteToAddrUDP ¶
func WriteToAddrUDP(conn gonnect.PacketConn, addr Addr, b []byte) (err error)
Types ¶
type Addr ¶
type Addr struct {
// Type specifies the address format: IP4Addr, IP6Addr, or FQDNAddr.
// This determines how the Host field should be interpreted.
Type AddrType
// Host contains the address data:
// - For IP4Addr: 4-byte IPv4 address
// - For IP6Addr: 16-byte IPv6 address
// - For FQDNAddr: Domain name as a byte slice
Host []byte
// Port is the TCP or UDP port number (0-65535).
Port uint16
// NetTyp specifies the network type: "tcp" or "udp".
// Values like "tcp4", "tcp6", "udp4", "udp6" are normalized to "tcp" or "udp".
// Empty string is treated as "tcp" in most conversions.
NetTyp string
}
Addr represents a network address in the SOCKS protocol.
Addr is the central type for representing addresses throughout socksgo. It can represent IPv4, IPv6, or domain name addresses with an associated port and network type.
Wire Format ¶
SOCKS5 encodes addresses as:
- ATYP (1 byte): Address type (IP4Addr=0x01, IP6Addr=0x04, FQDNAddr=0x03)
- DST.ADDR (variable): IP address or domain name
- DST.PORT (2 bytes): Port number in big-endian order
Examples ¶
// Create from IP address
addr := protocol.AddrFromIP(net.ParseIP("192.168.1.1"), 8080, "tcp")
// Create from domain name
addr := protocol.AddrFromFQDN("example.com", 443, "tcp")
// Create from host:port string
addr := protocol.AddrFromHostPort("example.com:443", "tcp")
// Convert to net.TCPAddr
tcpAddr := addr.ToTCP()
func AddrFromFQDN ¶
AddrFromFQDN constructs an FQDN Addr from a domain name string.
If the fqdn argument already contains a port (e.g., "example.com:80"), the embedded port will override the provided port argument.
Examples ¶
addr := protocol.AddrFromFQDN("example.com", 443, "tcp")
addr := protocol.AddrFromFQDN("example.com:8080", 443, "tcp") // Uses port 8080
func AddrFromFQDNNoDot ¶
AddrFromFQDNNoDot constructs an FQDN Addr, trimming any trailing dot from the domain name.
This is useful for compatibility with some DNS implementations (such as Tor's ResolvePtr).
Examples ¶
// Standard FQDN
addr := protocol.AddrFromFQDNNoDot("example.com", 443, "tcp")
// FQDN with trailing dot (from DNS response)
addr := protocol.AddrFromFQDNNoDot("example.com.", 443, "tcp") // Trims to "example.com"
func AddrFromHostPort ¶
AddrFromHostPort creates an Addr from a host:port string and a network name.
Parses a host:port string (e.g., "example.com:8080" or "[::1]:443") and creates an Addr with the appropriate Type (IP4Addr, IP6Addr, or FQDNAddr).
If hostport is empty, a suitable wildcard host is chosen based on the network:
- "tcp6" or "udp6": IPv6 wildcard "[::]:0"
- Others: IPv4 wildcard "0.0.0.0:0"
Examples ¶
addr := protocol.AddrFromHostPort("example.com:443", "tcp")
addr := protocol.AddrFromHostPort("192.168.1.1:8080", "tcp")
addr := protocol.AddrFromHostPort("", "tcp6") // Returns [::]:0
func AddrFromIP ¶
AddrFromIP returns an Addr representing the provided net.IP and port.
Automatically detects IPv4 vs IPv6 and stores the canonical byte representation in Host:
- IPv4: 4-byte representation (via ip.To4())
- IPv6: 16-byte representation (via ip.To16())
Examples ¶
// IPv4
addr := protocol.AddrFromIP(net.ParseIP("192.168.1.1"), 8080, "tcp")
// IPv6
addr := protocol.AddrFromIP(net.ParseIP("2001:db8::1"), 443, "tcp")
func AddrFromNetAddr ¶
AddrFromNetAddr converts a net.Addr to protocol Addr.
This function provides a unified way to convert standard Go network addresses to protocol.Addr. It specially handles *net.TCPAddr and *net.UDPAddr for efficiency. For other net.Addr implementations, it falls back to parsing addr.String() and uses addr.Network() as the NetTyp.
Examples ¶
tcpAddr := &net.TCPAddr{IP: net.ParseIP("192.168.1.1"), Port: 8080}
addr := protocol.AddrFromNetAddr(tcpAddr)
udpAddr := &net.UDPAddr{IP: net.ParseIP("::1"), Port: 53}
addr := protocol.AddrFromNetAddr(udpAddr)
func AddrFromNetIPAddrPort ¶ added in v0.2.0
AddrFromNetIPAddrPort converts a netip.AddrPort to protocol Addr.
A zero value input yields the zero Addr. The NetTyp is set based on the network parameter.
Examples ¶
addrPort := netip.MustParseAddrPort("192.168.1.1:8080")
addr := protocol.AddrFromNetIPAddrPort(addrPort)
func AddrFromString ¶
AddrFromString constructs an Addr from a host string and numeric port.
Examines the host string: if it parses as a valid IP address (IPv4 or IPv6), an IP Addr is returned with the appropriate Type. Otherwise, an FQDN Addr is returned.
Examples ¶
// IP address
addr := protocol.AddrFromString("192.168.1.1", 8080, "tcp") // Type: IP4Addr
addr := protocol.AddrFromString("::1", 80, "tcp") // Type: IP6Addr
// Domain name
addr := protocol.AddrFromString("example.com", 443, "tcp") // Type: FQDNAddr
func AddrFromTCPAddr ¶
AddrFromTCPAddr converts a *net.TCPAddr to protocol Addr.
A nil input yields the zero Addr. Port values outside the valid range (0-65535) are clamped to zero. The NetTyp is set to "tcp".
Examples ¶
tcpAddr := &net.TCPAddr{IP: net.ParseIP("192.168.1.1"), Port: 8080}
addr := protocol.AddrFromTCPAddr(tcpAddr)
func AddrFromUDPAddr ¶
AddrFromUDPAddr converts a *net.UDPAddr to protocol Addr.
A nil input yields the zero Addr. Port values outside the valid range (0-65535) are clamped to zero. The NetTyp is set to "udp".
Examples ¶
udpAddr := &net.UDPAddr{IP: net.ParseIP("8.8.8.8"), Port: 53}
addr := protocol.AddrFromUDPAddr(udpAddr)
func ReadSocks5TunUDPPacket ¶
func (Addr) Copy ¶
Copy returns a deep copy of the Addr.
Creates a new Addr with all fields copied, including a new slice for Host.
Examples ¶
original := protocol.AddrFromHostPort("example.com:443", "tcp")
copy := original.Copy()
// Modifying original won't affect copy
func (Addr) IpNetwork ¶
IpNetwork returns the IP network family name based on NetTyp.
Returns:
- "ip" for generic networks ("", "tcp", "udp", "ip")
- "ip4" for IPv4 networks ("tcp4", "udp4", "ip4")
- "ip6" for IPv6 networks ("tcp6", "udp6", "ip6")
- The original NetTyp for unknown values
This is useful for determining the address family when creating network connections.
func (Addr) IsUnspecified ¶
IsUnspecified reports whether the address has an unspecified host.
Returns true for:
- Empty Host slice
- IPv4 wildcard address (0.0.0.0)
- IPv6 wildcard address (::)
Returns false for FQDN addresses unless Host is empty.
Examples ¶
addr := protocol.AddrFromHostPort("0.0.0.0:0", "tcp")
addr.IsUnspecified() // true
addr := protocol.AddrFromHostPort("192.168.1.1:8080", "tcp")
addr.IsUnspecified() // false
func (Addr) Len ¶
Len returns the length of the Host field in bytes.
Returns:
- 4 for IPv4 addresses (IP4Addr)
- 16 for IPv6 addresses (IP6Addr)
- len(Host) for FQDN addresses (FQDNAddr)
func (Addr) Network ¶
Network implements net.Addr.Network.
Returns a network string based on Type and NetTyp:
- IP4Addr: "tcp4" or "udp4"
- IP6Addr: "tcp6" or "udp6"
- FQDNAddr: "tcp" or "udp" (no version suffix)
If NetTyp is empty, "tcp" is used as the default.
This method satisfies the net.Addr interface.
func (Addr) PortStr ¶
PortStr returns the port as a decimal string.
Examples ¶
addr := protocol.AddrFromHostPort("example.com:8080", "tcp")
port := addr.PortStr() // Returns "8080"
func (Addr) ResolveToIP4 ¶
func (a Addr) ResolveToIP4( ctx context.Context, lookup func(context.Context, string, string) ([]net.IP, error), ) *Addr
ResolveToIP4 resolves an FQDN address to an IPv4 address.
If the address is already IPv4, it returns itself. If it's an FQDN, it uses the provided lookup function to resolve to an IPv4 address. Returns nil for IPv6 addresses or if resolution fails.
Parameters ¶
- ctx: Context for cancellation and timeouts
- lookup: DNS lookup function (e.g., net.Resolver.LookupIP)
Examples ¶
addr := protocol.AddrFromFQDN("example.com", 443, "tcp")
resolved := addr.ResolveToIP4(ctx, net.DefaultResolver.LookupIP)
if resolved != nil {
// resolved is now an IPv4 address
}
func (Addr) String ¶
String returns the string representation of the address.
Returns:
- Just the host (IP or FQDN) if Port is zero
- host:port format if Port is non-zero
This method satisfies the net.Addr interface and fmt.Stringer.
Examples ¶
addr := protocol.AddrFromHostPort("192.168.1.1:8080", "tcp")
s := addr.String() // Returns "192.168.1.1:8080"
addr := protocol.AddrFromHostPort("example.com:0", "tcp")
s := addr.String() // Returns "example.com"
func (Addr) ToFQDN ¶
ToFQDN returns the textual representation of the address host.
Returns:
- IP address string (e.g., "192.168.1.1" or "2001:db8::1") for IP addresses
- Domain name string for FQDN addresses
This is useful for formatting the host portion of a host:port string.
Examples ¶
addr := protocol.AddrFromHostPort("192.168.1.1:8080", "tcp")
host := addr.ToFQDN() // Returns "192.168.1.1"
addr := protocol.AddrFromFQDN("example.com", 443, "tcp")
host := addr.ToFQDN() // Returns "example.com"
func (Addr) ToHostPort ¶
ToHostPort returns a host:port string suitable for use with net package functions like net.Dial or net.Listen.
The host is formatted as an IP address or domain name as appropriate. IPv6 addresses are automatically enclosed in brackets.
Examples ¶
addr := protocol.AddrFromHostPort("192.168.1.1:8080", "tcp")
hostPort := addr.ToHostPort() // Returns "192.168.1.1:8080"
addr := protocol.AddrFromHostPort("::1:443", "tcp")
hostPort := addr.ToHostPort() // Returns "[::1]:443"
func (Addr) ToIP ¶
ToIP returns the net.IP representation of the address.
Returns:
- IPv4 address (4-byte) for IP4Addr
- IPv6 address (16-byte) for IP6Addr
- nil for FQDNAddr or unknown types
Examples ¶
addr := protocol.AddrFromHostPort("192.168.1.1:8080", "tcp")
ip := addr.ToIP() // Returns net.IP{192, 168, 1, 1}
addr := protocol.AddrFromFQDN("example.com", 443, "tcp")
ip := addr.ToIP() // Returns nil
func (Addr) ToTCP ¶
ToTCP returns a *net.TCPAddr for IP addresses.
Returns nil for FQDN addresses since TCP connections require IP addresses.
Examples ¶
addr := protocol.AddrFromHostPort("192.168.1.1:8080", "tcp")
tcpAddr := addr.ToTCP() // Returns &net.TCPAddr{IP: ..., Port: 8080}
func (Addr) ToUDP ¶
ToUDP returns a *net.UDPAddr for IP addresses.
Returns nil for FQDN addresses since UDP connections require IP addresses.
Examples ¶
addr := protocol.AddrFromHostPort("8.8.8.8:53", "udp")
udpAddr := addr.ToUDP() // Returns &net.UDPAddr{IP: ..., Port: 53}
func (Addr) ToUnspecified ¶
ToUnspecified returns a new Addr with the same Type and NetTyp but with an unspecified host and zero port.
Returns:
- For IP4Addr: Host set to 0.0.0.0
- For IP6Addr: Host set to ::
- For FQDNAddr: Host remains nil
This is useful for creating reply addresses or wildcard addresses.
func (Addr) WithDefaultAddr ¶
WithDefaultAddr returns def if it is not nil and the address is unspecified, otherwise returns itself.
This is useful for providing a default address when dealing with wildcard/unspecified addresses.
Examples ¶
defaultAddr := protocol.AddrFromHostPort("127.0.0.1:0", "tcp")
addr := protocol.AddrFromHostPort("0.0.0.0:0", "tcp")
addr = addr.WithDefaultAddr(&defaultAddr) // Returns 127.0.0.1:0
addr = protocol.AddrFromHostPort("192.168.1.1:8080", "tcp")
addr = addr.WithDefaultAddr(&defaultAddr) // Returns 192.168.1.1:8080 (unchanged)
func (Addr) WithDefaultHost ¶
WithDefaultHost returns a copy of Addr where an unspecified host is replaced with the provided host.
If the address is already specified (IsUnspecified returns false), it is returned unchanged. If the address is unspecified and host is empty, the IPv4 wildcard "0.0.0.0" is used.
Examples ¶
// Unspecified address with custom host
addr := protocol.AddrFromHostPort("0.0.0.0:0", "tcp")
addr = addr.WithDefaultHost("127.0.0.1") // Returns 127.0.0.1:0
// Unspecified address with empty host (uses 0.0.0.0)
addr := protocol.AddrFromHostPort("0.0.0.0:8080", "tcp")
addr = addr.WithDefaultHost("") // Returns 0.0.0.0:8080
// Already specified - unchanged
addr := protocol.AddrFromHostPort("192.168.1.1:8080", "tcp")
addr = addr.WithDefaultHost("127.0.0.1") // Returns 192.168.1.1:8080
func (Addr) WithNetTyp ¶
WithNetTyp returns a copy of the Addr with NetTyp normalized.
Normalizes network type strings:
- "tcp4", "tcp6" -> "tcp"
- "udp4", "udp6" -> "udp"
- Other strings are preserved as-is
Examples ¶
addr := protocol.AddrFromHostPort("192.168.1.1:8080", "tcp4")
addr = addr.WithNetTyp("tcp4") // NetTyp becomes "tcp"
addr := protocol.AddrFromHostPort("8.8.8.8:53", "udp")
addr = addr.WithNetTyp("udp4") // NetTyp becomes "udp"
type AddrType ¶
type AddrType uint8
AddrType represents the type of address in the SOCKS protocol.
AddrType is used to encode/decode addresses in SOCKS requests and replies. The type determines how the Host field in Addr should be interpreted:
- IP4Addr: Host contains 4-byte IPv4 address
- IP6Addr: Host contains 16-byte IPv6 address
- FQDNAddr: Host contains domain name string
const ( // IP4Addr indicates an IPv4 address (4 bytes). // Wire value: 0x01 IP4Addr AddrType = 0x01 // IP6Addr indicates an IPv6 address (16 bytes). // Wire value: 0x04 IP6Addr AddrType = 0x04 // FQDNAddr indicates a fully qualified domain name. // Wire value: 0x03 // The domain name is preceded by a single byte length field. FQDNAddr AddrType = 0x03 )
Address type constants for SOCKS protocol.
These values are used in the ATYP field of SOCKS5 requests/replies and in the address encoding of SOCKS4a requests.
type AuthHandler ¶
type AuthHandler interface {
Name() string
// AuthHandlers with Code() == 0x0 or Code() == 0xff are invalid
Code() AuthMethodCode
HandleAuth(conn net.Conn, pool bufpool.Pool) (net.Conn, AuthInfo, error)
}
AuthHandler is the server-side authentication interface.
AuthHandler implementations handle the server side of SOCKS5 authentication protocols. Each method (NoAuth, PassAuth, GSSAuth) has its own handler implementation.
Implementation Requirements ¶
- Code() must return a valid method code (not 0x00 or 0xFF)
- HandleAuth() performs the authentication handshake
- Name() returns a human-readable description
Usage ¶
handlers := (&protocol.AuthHandlers{}).Add(&protocol.PassAuthHandler{
Verify: func(user, pass string) bool {
return user == "admin" && pass == "secret"
},
})
conn, info, err := protocol.HandleAuth(conn, pool, handlers)
type AuthHandlers ¶
type AuthHandlers struct {
// contains filtered or unexported fields
}
AuthHandlers is a server-side collection of authentication handlers.
AuthHandlers manages a set of authentication handlers that the server supports. When a client proposes authentication methods, the server selects the first matching handler from this collection.
Default Behavior ¶
For nil or empty AuthHandlers:
- Get(NoAuthCode) returns a blank NoAuthHandler
- Get(PassAuthCode) returns a PassAuthHandler that accepts any credentials
Thread Safety ¶
AuthHandlers is not thread-safe. Build the handler list before calling HandleAuth.
Usage ¶
handlers := (&protocol.AuthHandlers{}).
Add(&protocol.NoAuthHandler{}).
Add(&protocol.PassAuthHandler{
Verify: func(user, pass string) bool {
return isValid(user, pass)
},
})
conn, info, err := protocol.HandleAuth(conn, pool, handlers)
func (*AuthHandlers) Add ¶
func (m *AuthHandlers) Add(handler AuthHandler) *AuthHandlers
func (*AuthHandlers) CheckSocks4User ¶
func (m *AuthHandlers) CheckSocks4User(user string) (accept bool)
func (*AuthHandlers) Get ¶
func (m *AuthHandlers) Get(code AuthMethodCode) AuthHandler
For nil or void AuthHandlers - Get(NoAuthCode) always return blank method that just do nothing - Get(PassAuthCode) always return PassAuthHandler that accept any user+pass
type AuthInfo ¶
type AuthInfo struct {
Code AuthMethodCode
Name string // May be ""; Use GetName()
Info map[string]any
}
AuthInfo provides information about a successful authentication.
AuthInfo is returned after successful authentication and contains details about the method used and any relevant credentials or session information.
Fields ¶
- Code: The authentication method code used
- Name: Human-readable method name (may be empty, use GetName())
- Info: Method-specific information (e.g., username for PassAuth)
Examples ¶
// After authentication
info, err := protocol.RunAuth(conn, pool, methods)
if err == nil {
fmt.Printf("Authenticated with: %s\n", info.GetName())
if user, ok := protocol.GetAuthParam[string](info, "user"); ok {
fmt.Printf("User: %s\n", user)
}
}
func HandleAuth ¶
func HandleAuth( conn net.Conn, pool bufpool.Pool, handlers *AuthHandlers, ) (c net.Conn, i AuthInfo, err error)
HandleAuth performs server-side SOCKS5 authentication negotiation.
Reads the client's method list, selects a supported method, and executes the authentication handshake.
Negotiation Flow ¶
1. Read client methods: [VER, NMETHODS, METHODS...] 2. Select first matching handler 3. Send response: [VER, METHOD] 4. If METHOD requires authentication, execute HandleAuth() on selected handler
Parameters ¶
- conn: Network connection from SOCKS5 client
- pool: Buffer pool for allocations
- handlers: Server's authentication handlers
Returns ¶
- c: Connection (possibly wrapped by auth handler)
- i: AuthInfo with authentication details
- err: Error if negotiation or authentication fails
Errors ¶
- ErrNoAcceptableAuthMethods: No matching handlers found
- Method-specific errors from HandleAuth implementations
func RunAuth ¶
func RunAuth( conn net.Conn, pool bufpool.Pool, methods *AuthMethods, ) (c net.Conn, i AuthInfo, err error)
RunAuth performs client-side SOCKS5 authentication negotiation.
Sends the client's method list to the server, reads the server's selection, and executes the selected authentication method.
Negotiation Flow ¶
1. Send method list: [VER, NMETHODS, METHODS...] 2. Read server response: [VER, METHOD] 3. If METHOD requires authentication, execute RunAuth() on selected method
Parameters ¶
- conn: Network connection to SOCKS5 server
- pool: Buffer pool for allocations
- methods: Client's authentication methods
Returns ¶
- c: Connection (possibly wrapped by auth method)
- i: AuthInfo with authentication details
- err: Error if negotiation or authentication fails
Errors ¶
- ErrNoAcceptableAuthMethods: Server rejected all methods
- UnsupportedAuthMethodError: Server selected unsupported method
- UnknownAuthVerError: Invalid response version
type AuthMethod ¶
type AuthMethod interface {
Name() string
// AuthMethods with Code() == 0x0 or Code() == 0xff are invalid
Code() AuthMethodCode
RunAuth(conn net.Conn, pool bufpool.Pool) (net.Conn, AuthInfo, error)
}
AuthMethod is the client-side authentication interface.
AuthMethod implementations handle the client side of SOCKS5 authentication protocols. Each method (NoAuth, PassAuth, GSSAuth) has its own implementation.
Implementation Requirements ¶
- Code() must return a valid method code (not 0x00 or 0xFF)
- RunAuth() performs the authentication handshake
- Name() returns a human-readable description
Usage ¶
methods := (&protocol.AuthMethods{}).Add(&protocol.PassAuthMethod{
User: "username",
Pass: "password",
})
conn, info, err := protocol.RunAuth(conn, pool, methods)
type AuthMethodCode ¶
type AuthMethodCode uint8
AuthMethodCode represents a SOCKS5 authentication method identifier.
AuthMethodCode is used in the authentication negotiation phase to advertise supported methods (client) or select a method (server).
Standard Values ¶
- 0x00: No authentication required
- 0x01: GSS-API
- 0x02: Username/Password
- 0x03-0x7F: IANA assigned
- 0x80-0xFE: Private methods
- 0xFF: No acceptable methods
Examples ¶
code := protocol.PassAuthCode
if code == protocol.PassAuthCode {
// Handle username/password auth
}
// String representation
code.String() // Returns "user-pass auth"
const ( // NoAuthCode indicates no authentication is required. // Wire value: 0x00 NoAuthCode AuthMethodCode = 0x0 // GSSAuthCode indicates GSS-API authentication. // Wire value: 0x01 GSSAuthCode AuthMethodCode = 0x1 // PassAuthCode indicates username/password authentication. // Wire value: 0x02 PassAuthCode AuthMethodCode = 0x02 // NoAccAuthCode indicates no acceptable authentication methods. // Used by server to reject all client-proposed methods. // Wire value: 0xFF NoAccAuthCode AuthMethodCode = 0xff )
Authentication method codes as defined in RFC 1928.
func (AuthMethodCode) String ¶
func (a AuthMethodCode) String() string
type AuthMethods ¶
type AuthMethods struct {
// contains filtered or unexported fields
}
AuthMethods is a client-side collection of authentication methods.
AuthMethods manages a set of authentication methods that the client is willing to use. Methods are advertised to the server during negotiation, and the selected method is used for authentication.
Thread Safety ¶
AuthMethods is not thread-safe. Build the method list before calling RunAuth.
Usage ¶
methods := (&protocol.AuthMethods{}).
Add(&protocol.PassAuthMethod{User: "user", Pass: "pass"}).
Add(&protocol.GSSAuthMethod{Client: gssClient})
conn, info, err := protocol.RunAuth(conn, pool, methods)
func (*AuthMethods) Add ¶
func (m *AuthMethods) Add(method AuthMethod) *AuthMethods
func (*AuthMethods) Clone ¶
func (m *AuthMethods) Clone() *AuthMethods
func (*AuthMethods) Get ¶
func (m *AuthMethods) Get(code AuthMethodCode) AuthMethod
func (*AuthMethods) GetMsg ¶
func (m *AuthMethods) GetMsg() []byte
func (*AuthMethods) Rebuild ¶
func (m *AuthMethods) Rebuild()
func (*AuthMethods) User ¶
func (m *AuthMethods) User() string
If there is PassAuthMethod provided, return its User field.
type Cmd ¶
type Cmd uint8
Cmd represents a SOCKS command code.
Cmd is used in SOCKS requests to specify the operation the client wants the server to perform. Standard commands are defined in RFC 1928, while extension commands are defined by Tor and Gost projects.
Examples ¶
// Check command type
if cmd == protocol.CmdConnect {
// Handle CONNECT command
}
// String representation
cmd.String() // Returns "cmd connect"
const ( // CmdConnect establishes a TCP connection to the target address. // Standard SOCKS command (RFC 1928). // Wire value: 0x01 CmdConnect Cmd = 0x01 // CmdBind listens for incoming connections on the server. // Standard SOCKS command (RFC 1928). // Used for protocols that require reverse connections (e.g., FTP passive mode). // Wire value: 0x02 CmdBind Cmd = 0x02 // CmdUDPAssoc associates a UDP port for UDP relay. // Standard SOCKS command (RFC 1928). // Returns a UDP socket address for sending/receiving UDP packets. // Wire value: 0x03 CmdUDPAssoc Cmd = 0x03 // CmdTorResolve performs a forward DNS lookup (Tor extension). // https://spec.torproject.org/socks-extensions.html // Wire value: 0xF0 CmdTorResolve Cmd = 0xF0 // CmdTorResolvePtr performs a reverse DNS lookup (Tor extension). // https://spec.torproject.org/socks-extensions.html // Wire value: 0xF1 CmdTorResolvePtr Cmd = 0xF1 // CmdGostMuxBind creates a multiplexed bind using smux (Gost extension). // Allows multiple incoming connections over a single TCP connection. // Wire value: 0xF2 CmdGostMuxBind Cmd = 0xF2 // CmdGostUDPTun tunnels UDP over TCP (Gost extension). // Encapsulates UDP packets in a TCP connection. // Wire value: 0xF3 CmdGostUDPTun Cmd = 0xF3 )
SOCKS command codes.
These constants define the command values used in SOCKS requests. Standard commands (Connect, Bind, UDPAssoc) are defined in RFC 1928. Extension commands (TorResolve, TorResolvePtr, GostMuxBind, GostUDPTun) are defined by their respective projects.
func (Cmd) String ¶
String returns a human-readable description of the command.
Returns descriptive strings for known commands:
- "cmd connect" for CmdConnect
- "cmd bind" for CmdBind
- "cmd UDP associate" for CmdUDPAssoc
- "cmd tor resolve" for CmdTorResolve
- "cmd tor resolve_ptr" for CmdTorResolvePtr
- "cmd gost mbind" for CmdGostMuxBind
- "cmd gost udp tun" for CmdGostUDPTun
For unknown command values, returns "cmd noX" where X is the numeric value.
type GSSAPIClient ¶
type GSSAPIClient interface {
// InitSecContext produces a context token to send to the server.
// `token` is the input from the peer (nil on first call).
// Returns outputToken (to send), needContinue=true if more tokens are needed, or err.
InitSecContext(
targetName string,
token []byte,
) (outputToken []byte, needContinue bool, err error)
// DeleteSecContext cleans up the context when done.
DeleteSecContext() error
}
GSSAPIClient is the interface for client-side GSS-API implementations.
This interface should be implemented by a GSS-API library wrapper (e.g., MIT Kerberos, Heimdal).
Methods ¶
- InitSecContext: Initialize security context and produce tokens
- DeleteSecContext: Clean up context resources
Implementation Notes ¶
The implementation should: 1. On first call with nil token, initiate GSS context 2. Process server tokens and produce response tokens 3. Return needContinue=false when GSS_S_COMPLETE is reached 4. Handle context cleanup in DeleteSecContext
type GSSAPIServer ¶
type GSSAPIServer interface {
// AcceptSecContext processes a token from the client, returning a token to send back.
// Returns outputToken, the authenticated principal (srcName), needContinue flag, or err.
AcceptSecContext(
token []byte,
) (outputToken []byte, srcName string, needContinue bool, err error)
// DeleteSecContext cleans up the context when done.
DeleteSecContext() error
}
GSSAPIServer is the interface for server-side GSS-API implementations.
This interface should be implemented by a GSS-API library wrapper (e.g., MIT Kerberos, Heimdal) for server-side authentication.
Methods ¶
- AcceptSecContext: Process client tokens and produce response tokens
- DeleteSecContext: Clean up context resources
Implementation Notes ¶
The implementation should: 1. Process client tokens through AcceptSecContext 2. Return the authenticated principal name (srcName) on success 3. Return needContinue=false when GSS_S_COMPLETE is reached 4. Handle context cleanup in DeleteSecContext
type GSSAuthHandler ¶
type GSSAuthHandler struct {
Server GSSAPIServer // Provided GSS implementation
}
GSSAuthHandler implements server-side GSS-API authentication.
GSSAuthHandler wraps a GSSAPIServer implementation to provide SOCKS5 GSS-API authentication. It handles token framing and exchange.
Fields ¶
- Server: GSS-API server implementation (required)
Status ¶
This is a STUB implementation. It provides the framework but requires an external GSS-API library to function.
Examples ¶
// Requires a GSS-API implementation
gssServer := &myGSS.Server{Keytab: "/etc/krb5.keytab"}
handler := &protocol.GSSAuthHandler{Server: gssServer}
handlers := (&protocol.AuthHandlers{}).Add(handler)
func (*GSSAuthHandler) Code ¶
func (h *GSSAuthHandler) Code() AuthMethodCode
func (*GSSAuthHandler) HandleAuth ¶
func (*GSSAuthHandler) Name ¶
func (h *GSSAuthHandler) Name() string
type GSSAuthMethod ¶
type GSSAuthMethod struct {
Client GSSAPIClient // Provided GSS implementation
TargetName string // e.g. "socks@server.example.com"
}
GSSAuthMethod implements client-side GSS-API authentication.
GSSAuthMethod wraps a GSSAPIClient implementation to provide SOCKS5 GSS-API authentication. It handles token framing and exchange.
Fields ¶
- Client: GSS-API client implementation (required)
- TargetName: Service principal name (e.g., "socks@proxy.example.com")
Status ¶
This is a STUB implementation. It provides the framework but requires an external GSS-API library to function.
Examples ¶
// Requires a GSS-API implementation
gssClient := &myGSS.Client{ServiceName: "socks@proxy.example.com"}
method := &protocol.GSSAuthMethod{
Client: gssClient,
TargetName: "socks@proxy.example.com",
}
methods := (&protocol.AuthMethods{}).Add(method)
func (*GSSAuthMethod) Code ¶
func (m *GSSAuthMethod) Code() AuthMethodCode
func (*GSSAuthMethod) Name ¶
func (m *GSSAuthMethod) Name() string
type NoAuthHandler ¶
type NoAuthHandler struct{}
NoAuthHandler implements server-side no-authentication.
This handler accepts any connection without requiring credentials. It's the simplest auth handler and is commonly used for open proxies.
Wire Format ¶
Server response (2 bytes):
- VER: 0x05
- METHOD: 0x00 (NoAuth)
Examples ¶
handlers := (&protocol.AuthHandlers{}).Add(&protocol.NoAuthHandler{})
func (*NoAuthHandler) Code ¶
func (m *NoAuthHandler) Code() AuthMethodCode
func (*NoAuthHandler) HandleAuth ¶
func (*NoAuthHandler) Name ¶
func (m *NoAuthHandler) Name() string
type PassAuthHandler ¶
type PassAuthHandler struct {
// Nil means any user+pass combination is allowed
VerifyFn func(user, pass string) bool
}
PassAuthHandler implements server-side username/password authentication.
PassAuthHandler validates client credentials using the provided VerifyFn function. If VerifyFn is nil, all credentials are accepted (useful for testing or open proxies).
Fields ¶
- VerifyFn: Validation function. Returns true for valid credentials. If nil, all credentials are accepted.
Wire Format ¶
See PassAuthMethod for the complete protocol description.
Examples ¶
// Strict validation
handler := &protocol.PassAuthHandler{
Verify: func(user, pass string) bool {
return user == "admin" && pass == "secret"
},
}
// Accept all credentials
handler := &protocol.PassAuthHandler{}
handlers := (&protocol.AuthHandlers{}).Add(handler)
conn, info, err := protocol.HandleAuth(conn, pool, handlers)
func (*PassAuthHandler) Code ¶
func (m *PassAuthHandler) Code() AuthMethodCode
func (*PassAuthHandler) HandleAuth ¶
func (*PassAuthHandler) Name ¶
func (m *PassAuthHandler) Name() string
type PassAuthMethod ¶
type PassAuthMethod struct {
User, Pass string
}
PassAuthMethod implements client-side username/password authentication.
PassAuthMethod sends credentials to the server using the RFC 1929 protocol. The username and password are sent in plain text.
Fields ¶
- User: Username (1-255 bytes)
- Pass: Password (1-255 bytes)
Wire Format ¶
Client request:
- VER (1 byte): 0x01
- ULEN (1 byte): Username length
- UNAME (variable): Username
- PLEN (1 byte): Password length
- PASSWD (variable): Password
Server response:
- VER (1 byte): 0x01
- STATUS (1 byte): 0x00=success, 0x01=failure
Examples ¶
method := &protocol.PassAuthMethod{
User: "admin",
Pass: "secret",
}
methods := (&protocol.AuthMethods{}).Add(method)
conn, info, err := protocol.RunAuth(conn, pool, methods)
func (*PassAuthMethod) Code ¶
func (m *PassAuthMethod) Code() AuthMethodCode
func (*PassAuthMethod) Name ¶
func (m *PassAuthMethod) Name() string
type ReplyStatus ¶
type ReplyStatus uint8
ReplyStatus represents a SOCKS reply status code.
ReplyStatus is used in SOCKS replies to indicate the result of a request. SOCKS4 and SOCKS5 use different status code ranges, and this type provides methods to convert between them (To4, To5).
Examples ¶
// Check if request succeeded
if status.Ok() {
// Request granted
}
// Convert to SOCKS4 status
status4 := status.To4()
// String representation
status.String() // Returns "succeeded", "host unreachable", etc.
const ( // SuccReply indicates the request succeeded. // Wire value: 0x0 SuccReply ReplyStatus = 0x0 // FailReply indicates a general SOCKS server failure. // Wire value: 0x1 FailReply ReplyStatus = 0x1 // DisallowReply indicates the connection was not allowed by ruleset. // Typically used when address filters reject the request. // Wire value: 0x2 DisallowReply ReplyStatus = 0x2 // NetUnreachReply indicates the network is unreachable. // Wire value: 0x3 NetUnreachReply ReplyStatus = 0x3 // HostUnreachReply indicates the host is unreachable. // Typically used when dialing the target fails. // Wire value: 0x4 HostUnreachReply ReplyStatus = 0x4 // ConnRefusedReply indicates the connection was refused by the target. // Wire value: 0x5 ConnRefusedReply ReplyStatus = 0x5 // TTLExpiredReply indicates the TTL expired (used in UDP assoc). // Wire value: 0x6 TTLExpiredReply ReplyStatus = 0x6 // CmdNotSuppReply indicates the command is not supported. // Wire value: 0x7 CmdNotSuppReply ReplyStatus = 0x7 // AddrNotSuppReply indicates the address type is not supported. // Wire value: 0x8 AddrNotSuppReply ReplyStatus = 0x80 )
SOCKS5 reply status codes.
These constants define the response status values in SOCKS5 replies as specified in RFC 1928.
const ( // Granted indicates the request was granted. // Wire value: 90 Granted ReplyStatus = 90 // Rejected indicates the request was rejected or failed. // Wire value: 91 Rejected ReplyStatus = 91 // IdentRequired indicates the client program and identd report // different user-ids. // Wire value: 92 IdentRequired ReplyStatus = 92 // IdentFailed indicates the socks server cannot connect to identd // on the client. // Wire value: 93 IdentFailed ReplyStatus = 93 )
SOCKS4 reply status codes.
SOCKS4 uses a different reply code scheme than SOCKS5. See https://www.openssh.com/txt/socks4.protocol
const ( // TorDescNotFound indicates the onion service descriptor cannot be found. // Wire value: 0xf0 TorDescNotFound ReplyStatus = 0xf0 // TorDescInvalid indicates the onion service descriptor is invalid. // Wire value: 0xf1 TorDescInvalid ReplyStatus = 0xf1 // TorIntroFail indicates the onion service introduction failed. // Wire value: 0xf2 TorIntroFail ReplyStatus = 0xf2 // TorRendFailed indicates the onion service rendezvous failed. // Wire value: 0xf3 TorRendFailed ReplyStatus = 0xf3 // TorMissAuth indicates the onion service is missing client authorization. // Wire value: 0xf4 TorMissAuth ReplyStatus = 0xf4 // TorWrongAuth indicates the onion service has wrong client authorization. // Wire value: 0xf5 TorWrongAuth ReplyStatus = 0xf5 // TorInvalidAddr indicates an invalid onion service address. // Wire value: 0xf6 TorInvalidAddr ReplyStatus = 0xf6 // TorIntroTimeOut indicates the onion service introduction timed out. // Wire value: 0xf7 TorIntroTimeOut ReplyStatus = 0xf7 )
Tor SOCKS extension reply codes.
These status codes are defined in the Tor SOCKS extensions specification: https://spec.torproject.org/socks-extensions.html
func (ReplyStatus) Ok ¶
func (r ReplyStatus) Ok() bool
Ok reports whether the status indicates success.
Returns true for:
- SuccReply (SOCKS5 success)
- Granted (SOCKS4 success)
All other status codes return false.
func (ReplyStatus) String ¶
func (r ReplyStatus) String() string
String returns a human-readable description of the status code.
Returns descriptive strings for all known SOCKS4, SOCKS5, and Tor extension status codes. For unknown values, returns "reply code noX" where X is the numeric value.
Examples ¶
protocol.SuccReply.String() // "succeeded" protocol.HostUnreachReply.String() // "host unreachable" protocol.Granted.String() // "request granted"
func (ReplyStatus) To4 ¶
func (r ReplyStatus) To4() ReplyStatus
To4 converts a ReplyStatus to its SOCKS4 equivalent.
SOCKS5-specific codes are mapped to SOCKS4 equivalents:
- SuccReply -> Granted
- All other SOCKS5 codes -> Rejected
SOCKS4 codes are returned unchanged.
Note: SOCKS4 has limited status code granularity compared to SOCKS5, so most error conditions map to the generic Rejected code.
func (ReplyStatus) To5 ¶
func (r ReplyStatus) To5() ReplyStatus
To5 converts a ReplyStatus to its SOCKS5 equivalent.
SOCKS4-specific codes are mapped to SOCKS5 equivalents:
- Granted -> SuccReply
- Rejected, IdentFailed, IdentRequired -> FailReply
SOCKS5 and Tor extension codes are returned unchanged.
type Socks5UDPClient ¶
type Socks5UDPClient interface {
gonnect.UDPConn
WriteToIpPort(p []byte, ip net.IP, port uint16) (n int, err error)
ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error)
WriteToUDP(b []byte, addr *net.UDPAddr) (int, error)
ReadFromUDPAddrPort(b []byte) (n int, addr netip.AddrPort, err error)
WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error)
ReadMsgUDP(b, oob []byte) (n, oobn, flags int,
addr *net.UDPAddr, err error)
ReadMsgUDPAddrPort(b, oob []byte) (n, oobn, flags int,
addr netip.AddrPort, err error)
WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error)
WriteMsgUDPAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn int,
err error)
}
Socks5UDPClient is the interface for SOCKS5 UDP clients.
This interface combines net.Conn and net.PacketConn to support both stream-oriented and packet-oriented operations. It's implemented by:
- Socks5UDPClientAssoc: Standard UDP ASSOC
- Socks5UDPClientTUN: Gost UDP Tunnel
Methods ¶
- Read/Write: Stream-oriented I/O (uses default remote address)
- ReadFrom/WriteTo: Packet-oriented I/O with explicit addresses
- ReadFromUDP/WriteToUDP: UDP-specific packet I/O
- ReadFromUDPAddrPort/WriteToUDPAddrPort: AddrPort-based I/O
- ReadMsgUDP/WriteMsgUDP: UDP messages with out-of-band data
- WriteToIpPort: Write to a specific IP and port
type Socks5UDPClientAssoc ¶
type Socks5UDPClientAssoc struct {
gonnect.PacketConn
DefaultHeader []byte // For binded UDP connections (ones with fixed raddr)
Pool bufpool.Pool
Raddr net.Addr
OnClose func()
}
Socks5UDPClientAssoc implements standard SOCKS5 UDP ASSOCIATE.
This type wraps a UDP PacketConn to provide SOCKS5 UDP relay functionality. It adds SOCKS5 UDP headers to outgoing packets and parses them from incoming packets.
Usage ¶
After a successful UDP ASSOCIATE command over TCP, use the returned server UDP address to create this client:
udpConn, _ := net.DialUDP("udp", nil, serverUDPAddr)
client := protocol.NewSocks5UDPClientAssoc(udpConn, &bindAddr, pool, onClose)
defer client.Close()
// Send UDP packet
client.WriteToUDP(data, &net.UDPAddr{IP: targetIP, Port: targetPort})
// Receive UDP packet
n, addr, err := client.ReadFromUDP(buf)
func NewSocks5UDPClientAssoc ¶
func NewSocks5UDPClientAssoc( conn gonnect.PacketConn, addr *Addr, pool bufpool.Pool, onc func(), ) *Socks5UDPClientAssoc
NewSocks5UDPClientAssoc creates a new standard UDP ASSOC client.
Parameters ¶
- conn: Underlying UDP PacketConn (already connected to server's UDP address)
- addr: Bound address from UDP ASSOCIATE reply (used as default remote)
- pool: Buffer pool for allocations
- onc: Optional callback called once on Close()
Returns ¶
A new Socks5UDPClientAssoc instance.
func (*Socks5UDPClientAssoc) Close ¶
func (uc *Socks5UDPClientAssoc) Close() error
func (*Socks5UDPClientAssoc) Read ¶
func (uc *Socks5UDPClientAssoc) Read(b []byte) (n int, err error)
func (*Socks5UDPClientAssoc) ReadFromUDP ¶
func (*Socks5UDPClientAssoc) ReadFromUDPAddrPort ¶ added in v0.2.0
func (*Socks5UDPClientAssoc) ReadMsgUDP ¶ added in v0.2.0
func (*Socks5UDPClientAssoc) ReadMsgUDPAddrPort ¶ added in v0.2.0
func (*Socks5UDPClientAssoc) RemoteAddr ¶
func (uc *Socks5UDPClientAssoc) RemoteAddr() net.Addr
func (*Socks5UDPClientAssoc) Write ¶
func (uc *Socks5UDPClientAssoc) Write(b []byte) (n int, err error)
func (*Socks5UDPClientAssoc) WriteMsgUDP ¶ added in v0.2.0
func (*Socks5UDPClientAssoc) WriteMsgUDPAddrPort ¶ added in v0.2.0
func (*Socks5UDPClientAssoc) WriteToIpPort ¶
func (*Socks5UDPClientAssoc) WriteToUDP ¶
func (*Socks5UDPClientAssoc) WriteToUDPAddrPort ¶ added in v0.2.0
type Socks5UDPClientTUN ¶
type Socks5UDPClientTUN struct {
net.Conn
DefaultHeader []byte // For binded UDP connections (ones with fixed raddr)
Pool bufpool.Pool
Laddr, Raddr net.Addr
OnClose func()
}
Socks5UDPClientTUN implements Gost's UDP Tunnel extension.
This type wraps a TCP Conn to provide UDP-over-TCP relay. Unlike standard UDP ASSOC which uses a separate UDP connection, Gost's tunnel encapsulates UDP packets within a TCP stream.
Wire Format ¶
Each UDP packet is prefixed with a header:
- RSV (2 bytes): Payload length (big-endian)
- FRAG (1 byte): Always 0xFF
- ATYP (1 byte): Address type
- DST.ADDR/DST.PORT: Destination address
- DATA: UDP payload
Usage ¶
After a successful GostUDPTun command over TCP:
client := protocol.NewSocks5UDPClientTUN(tcpConn, bindAddr, &targetAddr, pool)
defer client.Close()
// Send UDP packet (automatically encapsulated in TCP)
client.WriteToUDP(data, &net.UDPAddr{IP: targetIP, Port: targetPort})
// Receive UDP packet
n, addr, err := client.ReadFromUDP(buf)
func NewSocks5UDPClientTUN ¶
func NewSocks5UDPClientTUN( conn net.Conn, laddr Addr, raddr *Addr, pool bufpool.Pool, ) *Socks5UDPClientTUN
NewSocks5UDPClientTUN creates a new Gost UDP Tunnel client.
Parameters ¶
- conn: Underlying TCP connection (already upgraded to UDP tunnel)
- laddr: Local bound address
- raddr: Optional remote address (nil for unbound)
- pool: Buffer pool for allocations
Returns ¶
A new Socks5UDPClientTUN instance.
func (*Socks5UDPClientTUN) Close ¶
func (uc *Socks5UDPClientTUN) Close() error
func (*Socks5UDPClientTUN) LocalAddr ¶
func (uc *Socks5UDPClientTUN) LocalAddr() net.Addr
func (*Socks5UDPClientTUN) ReadFromUDP ¶
func (*Socks5UDPClientTUN) ReadFromUDPAddrPort ¶ added in v0.2.0
func (*Socks5UDPClientTUN) ReadMsgUDP ¶ added in v0.2.0
func (*Socks5UDPClientTUN) ReadMsgUDPAddrPort ¶ added in v0.2.0
func (*Socks5UDPClientTUN) RemoteAddr ¶
func (uc *Socks5UDPClientTUN) RemoteAddr() net.Addr
func (*Socks5UDPClientTUN) WriteMsgUDP ¶ added in v0.2.0
func (*Socks5UDPClientTUN) WriteMsgUDPAddrPort ¶ added in v0.2.0
func (*Socks5UDPClientTUN) WriteToIpPort ¶
func (*Socks5UDPClientTUN) WriteToUDP ¶
func (*Socks5UDPClientTUN) WriteToUDPAddrPort ¶ added in v0.2.0
type UnknownAddrTypeError ¶
type UnknownAddrTypeError struct {
Type AddrType
}
UnknownAddrTypeError is returned when an unknown address type is encountered in a SOCKS request or reply.
func (UnknownAddrTypeError) Error ¶
func (e UnknownAddrTypeError) Error() string
type UnknownAuthVerError ¶
type UnknownAuthVerError struct {
Version int
}
UnknownAuthVerError is returned when an unknown authentication version is received during SOCKS5 auth negotiation.
func (UnknownAuthVerError) Error ¶
func (e UnknownAuthVerError) Error() string
type UnsupportedAuthMethodError ¶
type UnsupportedAuthMethodError struct {
Method AuthMethodCode
}
UnsupportedAuthMethodError is returned when the server selects an authentication method that the client doesn't support.
func (UnsupportedAuthMethodError) Error ¶
func (e UnsupportedAuthMethodError) Error() string
type Wrong4ReplyVerError ¶
type Wrong4ReplyVerError struct {
Version int
}
Wrong4ReplyVerError is returned when a SOCKS4 reply has an unexpected version byte.
SOCKS4 replies should always have version byte 0.
func (Wrong4ReplyVerError) Error ¶
func (e Wrong4ReplyVerError) Error() string
type WrongProtocolVerError ¶
type WrongProtocolVerError struct {
Version int
}
WrongProtocolVerError is returned when a SOCKS request or reply has an unexpected protocol version.
func (WrongProtocolVerError) Error ¶
func (e WrongProtocolVerError) Error() string