socks5

package module
v0.0.0-...-a091342 Latest Latest
Warning

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

Go to latest
Published: Mar 10, 2017 License: MIT Imports: 8 Imported by: 181

README

socks5

Go Report Card GoDoc

SOCKS Protocol Version 5 Library

Install

$ go get github.com/txthinking/socks5

Example

func ExampleServer() {
	socks5.Debug = true // enable socks5 debug log

	l, err := net.Listen("tcp", ":1980")
	if err != nil {
		log.Println(err)
		return
	}
	defer l.Close()

	for {
		c, err := l.Accept()
		if err != nil {
			log.Println(err)
			return
		}
		go func(c net.Conn) {
			defer c.Close()
			s5s := socks5.NewClassicServer(c)
			if err := s5s.Negotiate(); err != nil {
				log.Println(err)
				return
			}
			r, err := s5s.GetRequest()
			if err != nil {
				log.Println(err)
				return
			}
			rc, err := r.Connect(c)
			if err != nil {
				log.Println(err)
				return
			}
			defer rc.Close()
			go func() {
				_, _ = io.Copy(c, rc)
			}()
			_, _ = io.Copy(rc, c)
		}(c)
	}
}

Now you have a socks5 proxy listen on :1980

You can test with curl: curl --socks5-hostname YOUR_SERVER_IP:1980 http://httpbin.org/ip

Documentation

Index

Examples

Constants

View Source
const (
	// Ver is socks protocol version
	Ver byte = 0x05

	// MethodNone is none method
	MethodNone byte = 0x00
	// MethodGSSAPI is gssapi method
	MethodGSSAPI byte = 0x01 // MUST support // todo
	// MethodUsernamePassword is username/assword auth method
	MethodUsernamePassword byte = 0x02 // SHOULD support
	// MethodUnsupportAll means unsupport all given methods
	MethodUnsupportAll byte = 0xFF

	// UserPassVer is username/password auth protocol version
	UserPassVer byte = 0x01
	// UserPassStatusSuccess is success status of username/password auth
	UserPassStatusSuccess byte = 0x00
	// UserPassStatusFailure is failure status of username/password auth
	UserPassStatusFailure byte = 0x01 // just other than 0x00

	// CmdConnect is connect command
	CmdConnect byte = 0x01
	// CmdBind is bind command
	CmdBind byte = 0x02
	// CmdUDP is UDP command
	CmdUDP byte = 0x03

	// ATYPIPv4 is ipv4 address type
	ATYPIPv4 byte = 0x01 // 4 octets
	// ATYPDomain is domain address type
	ATYPDomain byte = 0x03 // The first octet of the address field contains the number of octets of name that follow, there is no terminating NUL octet.
	// ATYPIPv6 is ipv6 address type
	ATYPIPv6 byte = 0x04 // 16 octets

	// RepSuccess means that success for repling
	RepSuccess byte = 0x00
	// RepServerFailure means the server failure
	RepServerFailure byte = 0x01
	// RepNotAllowed means the request not allowed
	RepNotAllowed byte = 0x02
	// RepNetworkUnreachable means the network unreachable
	RepNetworkUnreachable byte = 0x03
	// RepHostUnreachable means the host unreachable
	RepHostUnreachable byte = 0x04
	// RepConnectionRefused means the connection refused
	RepConnectionRefused byte = 0x05
	// RepTTLExpired means the TTL expired
	RepTTLExpired byte = 0x06
	// RepCommandNotSupported means the request command not supported
	RepCommandNotSupported byte = 0x07
	// RepAddressNotSupported means the request address not supported
	RepAddressNotSupported byte = 0x08
)

Variables

View Source
var (
	// ErrUnsupportCmd is the error when got unsupport command
	ErrUnsupportCmd = errors.New("Unsupport Command")
	// ErrUserPassAuth is the error when got invalid username or password
	ErrUserPassAuth = errors.New("Invalid Username or Password for Auth")
)
View Source
var (
	// ErrVersion is version error
	ErrVersion = errors.New("Invalid Version")
	// ErrUserPassVersion is username/password auth version error
	ErrUserPassVersion = errors.New("Invalid Version of Username Password Auth")
	// ErrBadRequest is bad request error
	ErrBadRequest = errors.New("Bad Request")
)
View Source
var Debug bool

Debug enable debug log

View Source
var (
	// ErrBadReply is the error when read reply
	ErrBadReply = errors.New("Bad Reply")
)

Functions

func ParseAddress

func ParseAddress(na net.Addr) (a byte, addr []byte, port []byte)

ParseAddress format net.Addr to raw address

func ToAddress

func ToAddress(a byte, addr []byte, port []byte) string

ToAddress format raw address to x.x.x.x:xx

Types

type NegotiationReply

type NegotiationReply struct {
	Ver    byte
	Method byte
}

NegotiationReply is the negotiation reply packet

func NewNegotiationReply

func NewNegotiationReply(method byte) *NegotiationReply

NewNegotiationReply return negotiation reply packet can be writed into client

func NewNegotiationReplyFrom

func NewNegotiationReplyFrom(r io.Reader) (*NegotiationReply, error)

NewNegotiationReplyFrom read negotiation reply packet from server

func (*NegotiationReply) WriteTo

func (r *NegotiationReply) WriteTo(w io.Writer) error

WriteTo write negotiation reply packet into client

type NegotiationRequest

type NegotiationRequest struct {
	Ver      byte
	NMethods byte
	Methods  []byte // 1-255 bytes
}

NegotiationRequest is the negotiation reqeust packet

func NewNegotiationRequest

func NewNegotiationRequest(methods []byte) *NegotiationRequest

NewNegotiationRequest return negotiation request packet can be writed into server

func NewNegotiationRequestFrom

func NewNegotiationRequestFrom(r io.Reader) (*NegotiationRequest, error)

NewNegotiationRequestFrom read negotiation requst packet from client

func (*NegotiationRequest) WriteTo

func (r *NegotiationRequest) WriteTo(w io.Writer) error

WriteTo write negotiation request packet into server

type Reply

type Reply struct {
	Ver  byte
	Rep  byte
	Rsv  byte // 0x00
	Atyp byte
	// CONNECT socks server's address which used to connect to dst addr
	// BIND ...
	// UDP socks server's address which used to connect to dst addr
	BndAddr []byte
	// CONNECT socks server's port which used to connect to dst addr
	// BIND ...
	// UDP socks server's port which used to connect to dst addr
	BndPort []byte // 2 bytes
}

Reply is the reply packet

func NewReply

func NewReply(rep byte, atyp byte, bndaddr []byte, bndport []byte) *Reply

NewReply return reply packet can be writed into client

func NewReplyFrom

func NewReplyFrom(r io.Reader) (*Reply, error)

NewReplyFrom read reply packet from server

func (*Reply) WriteTo

func (r *Reply) WriteTo(w io.Writer) error

WriteTo write reply packet into client

type Request

type Request struct {
	Ver     byte
	Cmd     byte
	Rsv     byte // 0x00
	Atyp    byte
	DstAddr []byte
	DstPort []byte // 2 bytes
}

Request is the request packet

func NewRequest

func NewRequest(cmd byte, atyp byte, dstaddr []byte, dstport []byte) *Request

NewRequest return request packet can be writed into server

func NewRequestFrom

func NewRequestFrom(r io.Reader) (*Request, error)

NewRequestFrom read requst packet from client

func (*Request) Address

func (r *Request) Address() string

Address return request address like x.x.x.x:xx

func (*Request) Connect

func (r *Request) Connect(c net.Conn) (*net.TCPConn, error)

Connect remote conn which u want to connect. You may should write your method instead of use this method.

func (*Request) WriteTo

func (r *Request) WriteTo(w io.Writer) error

WriteTo write request packet into server

type Server

type Server struct {
	C                 net.Conn
	CheckUserPass     func(user, pass []byte) bool
	SelectMethod      func(methods []byte) (method byte, got bool)
	SupportedCommands []byte // Now only support connect command
}

Server is socks5 server wrapper

Example
package main

import (
	"io"
	"log"
	"net"

	"github.com/txthinking/socks5"
)

func main() {
	socks5.Debug = true // enable socks5 debug log

	l, err := net.Listen("tcp", ":1980")
	if err != nil {
		log.Println(err)
		return
	}
	defer l.Close()

	for {
		c, err := l.Accept()
		if err != nil {
			log.Println(err)
			return
		}
		go func(c net.Conn) {
			defer c.Close()
			s5s := socks5.NewClassicServer(c)
			if err := s5s.Negotiate(); err != nil {
				log.Println(err)
				return
			}
			r, err := s5s.GetRequest()
			if err != nil {
				log.Println(err)
				return
			}
			rc, err := r.Connect(c)
			if err != nil {
				log.Println(err)
				return
			}
			defer rc.Close()
			go func() {
				_, _ = io.Copy(c, rc)
			}()
			_, _ = io.Copy(rc, c)
		}(c)
	}
}

func NewClassicServer

func NewClassicServer(c net.Conn) *Server

NewClassicServer return a server which allow none method and connect command

func (*Server) GetRequest

func (s *Server) GetRequest() (*Request, error)

GetRequest get request packet from client, and check command according to SupportedCommands

func (*Server) Negotiate

func (s *Server) Negotiate() error

Negotiate handle negotiate packet. This method do not handle gssapi(0x01) method now.

type UDPHeader

type UDPHeader struct {
	Rsv     []byte // 0x00 0x00
	Flag    byte
	Atyp    byte
	DstAddr []byte
	DstPort []byte // 2 bytes
}

UDPHeader is the UDP header packet

type UserPassNegotiationReply

type UserPassNegotiationReply struct {
	Ver    byte
	Status byte
}

UserPassNegotiationReply is the negotiation username/password reply packet

func NewUserPassNegotiationReply

func NewUserPassNegotiationReply(status byte) *UserPassNegotiationReply

NewUserPassNegotiationReply return negotiation username password reply packet can be writed into client

func NewUserPassNegotiationReplyFrom

func NewUserPassNegotiationReplyFrom(r io.Reader) (*UserPassNegotiationReply, error)

NewUserPassNegotiationReplyFrom read user password negotiation reply packet from server

func (*UserPassNegotiationReply) WriteTo

func (r *UserPassNegotiationReply) WriteTo(w io.Writer) error

WriteTo write negotiation username password reply packet into client

type UserPassNegotiationRequest

type UserPassNegotiationRequest struct {
	Ver    byte
	Ulen   byte
	Uname  []byte // 1-255 bytes
	Plen   byte
	Passwd []byte // 1-255 bytes
}

UserPassNegotiationRequest is the negotiation username/password reqeust packet

func NewUserPassNegotiationRequest

func NewUserPassNegotiationRequest(username []byte, password []byte) *UserPassNegotiationRequest

NewUserPassNegotiationRequest return user password negotiation request packet can be writed into server

func NewUserPassNegotiationRequestFrom

func NewUserPassNegotiationRequestFrom(r io.Reader) (*UserPassNegotiationRequest, error)

NewUserPassNegotiationRequestFrom read user password negotiation request packet from client

func (*UserPassNegotiationRequest) WriteTo

func (r *UserPassNegotiationRequest) WriteTo(w io.Writer) error

WriteTo write user password negotiation request packet into server

Jump to

Keyboard shortcuts

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