socks5

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2024 License: Apache-2.0 Imports: 9 Imported by: 0

README

Go-Socks5

Provides the socks5 package that implements a SOCKS5 server. SOCKS (Secure Sockets) is used to route traffic between a client and server through an intermediate proxy layer. This can be used to bypass firewalls or NATs.

Feature

The package has the following features:

  • "No Auth" mode
  • User/Password authentication
  • Support for the CONNECT command
  • Rules to do granular filtering of commands
  • Custom DNS resolution
  • Unit tests

TODO

The package still needs the following:

  • Support for the BIND command
  • Support for the ASSOCIATE command

Example

Below is a simple example of usage

// Create a SOCKS5 server
conf := &socks5.Config{}
server, err := socks5.New(conf)
if err != nil {
  panic(err)
}

// Create SOCKS5 proxy on localhost port 8000
if err := server.ListenAndServe("tcp", "127.0.0.1:8000"); err != nil {
  panic(err)
}

Godoc

Step 1: Install godoc

First, ensure that you have godoc installed. You can install it using the following command:

go install golang.org/x/tools/cmd/godoc@latest
Step 2: Run godoc Server

Next, run the godoc server to serve the documentation for your Go project:

godoc -http=:6060 -goroot=.

This command starts a web server on port 6060, serving the documentation for your Go project.

Reference

This repository was originally cloned from go-socks5 due to its long period of inactivity. It is a small yet elegant repo, and we aim to use it as a pilot project to transform it into a comprehensive library with thorough documentation and automation. We will also strive to optimize and enhance it using AI.

Documentation

Index

Constants

View Source
const (
	// NoAuth represents the "No Authentication" method.
	NoAuth = uint8(0)

	// UserPassAuth represents the "User/Password Authentication" method.
	UserPassAuth = uint8(2)
)
View Source
const (
	ConnectCommand   = uint8(1)
	BindCommand      = uint8(2)
	AssociateCommand = uint8(3)
)

Variables

View Source
var (
	// UserAuthFailed is an error returned when user authentication fails.
	UserAuthFailed = fmt.Errorf("User authentication failed")

	// NoSupportedAuth is an error returned when no supported authentication mechanisms are available.
	NoSupportedAuth = fmt.Errorf("No supported authentication mechanism")
)

Functions

This section is empty.

Types

type AddrSpec

type AddrSpec struct {
	FQDN string
	IP   net.IP
	Port int
}

AddrSpec is used to return the target AddrSpec which may be specified as IPv4, IPv6, or a FQDN

func (AddrSpec) Address

func (a AddrSpec) Address() string

Address returns a string suitable to dial; prefer returning IP-based address, fallback to FQDN

func (*AddrSpec) String

func (a *AddrSpec) String() string

type AddressRewriter

type AddressRewriter interface {
	Rewrite(ctx context.Context, request *Request) (context.Context, *AddrSpec)
}

AddressRewriter is used to rewrite a destination transparently

type AuthContext

type AuthContext struct {
	// Method is the authentication method used.
	Method uint8

	// Payload contains additional information provided during the authentication process.
	// The keys depend on the used authentication method.
	// For UserPassAuth, it contains the username.
	Payload map[string]string
}

AuthContext encapsulates authentication state provided during negotiation.

type Authenticator

type Authenticator interface {
	// Authenticate performs the authentication process using the provided reader and writer.
	// It returns an AuthContext if the authentication is successful, and an error if it fails.
	Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error)

	// GetCode returns the authentication method code.
	GetCode() uint8
}

Authenticator is an interface for handling authentication. It provides methods to authenticate a connection and to get the authentication method code.

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

	// Logger can be used to provide a custom log target.
	// Defaults to stdout.
	Logger *log.Logger

	// Dial is an optional function for dialing out.
	Dial func(ctx context.Context, network, addr string) (net.Conn, error)

	// Mem is the memory allocator.
	Mem MemMgr
}

Config is used to setup and configure a Server.

type CredentialStore

type CredentialStore interface {
	// Valid checks if the given user and password combination is valid.
	// It returns true if the combination is valid, and false otherwise.
	Valid(user, password string) bool
}

CredentialStore is an interface used to support user/password authentication. It provides a method to validate a user and password combination.

type DNSResolver

type DNSResolver struct{}

DNSResolver is a struct that implements the NameResolver interface using the system's DNS resolver. It resolves hostnames to IP addresses using the standard library's net package.

func (DNSResolver) Resolve

func (d DNSResolver) Resolve(ctx context.Context, name string) (context.Context, net.IP, error)

Resolve resolves the given domain name to an IP address using the system's DNS resolver. It returns the resolved IP address and any error encountered during the resolution process.

type Mem

type Mem struct{}

Mem is a simple implementation of the MemAllocation interface. It uses the built-in `make` function to allocate memory and does nothing for deallocation.

func (*Mem) Alloc

func (m *Mem) Alloc(ctx context.Context, size int) []byte

Alloc allocates a slice of bytes of the specified size using the built-in `make` function. It does not perform any special handling for the context.

func (*Mem) Free

func (m *Mem) Free(ctx context.Context, bs []byte)

Free is a no-op function for deallocating memory. It does not perform any actual deallocation and ignores the provided context.

type MemAllocation

type MemAllocation interface {
	// Alloc allocates a slice of bytes of the specified size.
	// ctx can be used to control the allocation process, such as for timeouts or cancellations.
	Alloc(ctx context.Context, size int) []byte

	// Free deallocates the provided slice of bytes.
	// ctx can be used to control the deallocation process, such as for timeouts or cancellations.
	Free(ctx context.Context, bs []byte)
}

MemAllocation is an interface for managing memory allocation and deallocation. It provides methods to allocate and free memory.

type MemMgr

type MemMgr interface {
	// Create creates a new MemAllocation instance.
	// ctx can be used to control the creation process, such as for timeouts or cancellations.
	Create(ctx context.Context) MemAllocation
}

MemMgr is an interface for managing memory allocators. It provides a method to create a new MemAllocation instance.

type NameResolver

type NameResolver interface {
	// Resolve resolves the given domain name to an IP address.
	// ctx can be used to control the resolution process, such as for timeouts or cancellations.
	Resolve(ctx context.Context, name string) (context.Context, net.IP, error)
}

NameResolver is an interface used to implement custom name resolution. It provides a method to resolve a domain name to an IP address.

type NoAuthAuthenticator

type NoAuthAuthenticator struct{}

NoAuthAuthenticator is an implementation of the Authenticator interface for the "No Authentication" method.

func (NoAuthAuthenticator) Authenticate

func (a NoAuthAuthenticator) Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error)

Authenticate implements the Authenticator interface for the "No Authentication" method. It always returns a successful AuthContext with the NoAuth method and an empty payload.

func (NoAuthAuthenticator) GetCode

func (a NoAuthAuthenticator) GetCode() uint8

GetCode returns the authentication method code for the "No Authentication" method.

type PermitCommand

type PermitCommand struct {
	// EnableConnect specifies whether the CONNECT command is allowed.
	EnableConnect bool

	// EnableBind specifies whether the BIND command is allowed.
	EnableBind bool

	// EnableAssociate specifies whether the ASSOCIATE command is allowed.
	EnableAssociate bool
}

PermitCommand is an implementation of the RuleSet interface which enables filtering of supported commands.

func (*PermitCommand) Allow

func (p *PermitCommand) Allow(ctx context.Context, req *Request) (context.Context, bool)

Allow determines whether the given request should be allowed based on the configured command rules. It returns a new context and a boolean indicating whether the request is allowed.

type Request

type Request struct {
	// Protocol version
	Version uint8
	// Requested command
	Command uint8
	// AuthContext provided during negotiation
	AuthContext *AuthContext
	// AddrSpec of the the network that sent the request
	RemoteAddr *AddrSpec
	// AddrSpec of the desired destination
	DestAddr *AddrSpec
	// contains filtered or unexported fields
}

A Request represents request received by a server

func NewRequest

func NewRequest(bufConn io.Reader) (*Request, error)

NewRequest creates a new Request from the tcp connection

type RuleSet

type RuleSet interface {
	// Allow determines whether the given request should be allowed.
	// It returns a new context and a boolean indicating whether the request is allowed.
	Allow(ctx context.Context, req *Request) (context.Context, bool)
}

RuleSet is an interface used to provide custom rules to allow or prohibit actions. It provides a method to determine whether a given request should be allowed.

func PermitAll

func PermitAll() RuleSet

PermitAll returns a RuleSet which allows all types of connections.

func PermitNone

func PermitNone() RuleSet

PermitNone returns a RuleSet which disallows all types of connections.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is responsible for accepting connections and handling the details of the SOCKS5 protocol.

func New

func New(conf *Config) (*Server, error)

New creates a new Server instance and potentially returns an error if the configuration is invalid.

It ensures that the following defaults are set if not explicitly provided in the configuration:

  • At least one authentication method is enabled. If no methods are specified, it defaults to using a UserPassAuthenticator if credentials are provided, or a NoAuthAuthenticator if no credentials are provided.
  • A DNS resolver is set. If not provided, it defaults to a DNSResolver.
  • A rule set is set. If not provided, it defaults to PermitAll.
  • A log target is set. If not provided, it defaults to logging to standard output with standard log flags.

Parameters:

conf - The configuration for the server.

Returns:

A new Server instance and any error that might have occurred.

func (*Server) ListenAndServe

func (s *Server) ListenAndServe(network, addr string) error

ListenAndServe creates a listener on the specified network address and starts serving connections. It is a convenience function that calls net.Listen and then Serve.

network and addr are the network type and address to listen on, respectively. For example, "tcp" and "0.0.0.0:8080".

ListenAndServe returns an error if it fails to create the listener or if there is an error serving connections.

func (*Server) Serve

func (s *Server) Serve(l net.Listener) error

Serve accepts incoming connections from the provided listener and handles them. It runs in a loop, accepting connections and spawning a goroutine to handle each one using ServeConn.

Serve returns an error if there is an error accepting a connection.

func (*Server) ServeConn

func (s *Server) ServeConn(conn net.Conn) error

ServeConn handles a single connection. It reads from the connection, processes the SOCKS5 protocol, and handles the request.

ServeConn performs the following steps: - Check the IP allowlist - Reads the version byte from the connection. - Checks if the version is compatible with SOCKS5. - Authenticates the connection based on the server's configuration. - Reads the client's request. - Processes the client's request and sends the appropriate response.

ServeConn returns an error if any step fails.

func (*Server) SetIPAllowlist

func (s *Server) SetIPAllowlist(allowedIPs []net.IP)

SetIPAllowlist sets the function to check if a given IP is allowed. It takes a list of allowed IPs and updates the server's IP allowlist function accordingly.

type StaticCredentials

type StaticCredentials map[string]string

StaticCredentials is an implementation of the CredentialStore interface that uses a map to store user credentials. It enables direct use of a map as a credential store.

func (StaticCredentials) Valid

func (s StaticCredentials) Valid(user, password string) bool

Valid checks if the given user and password combination is valid. It returns true if the user exists in the map and the password matches, and false otherwise.

type UserPassAuthenticator

type UserPassAuthenticator struct {
	// Credentials is the credential store used to validate user credentials.
	Credentials CredentialStore
}

UserPassAuthenticator is an implementation of the Authenticator interface for the "User/Password Authentication" method.

func (UserPassAuthenticator) Authenticate

func (a UserPassAuthenticator) Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error)

Authenticate performs the user/password authentication process. It verifies the user credentials and returns an AuthContext if successful.

func (UserPassAuthenticator) GetCode

func (a UserPassAuthenticator) GetCode() uint8

GetCode returns the authentication method code for the "User/Password Authentication" method.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL