Documentation
¶
Index ¶
- Constants
- Variables
- func ParseAddress(address string) (a byte, addr []byte, port []byte, err error)
- func ParseBytesAddress(b []byte) (a byte, addr []byte, port []byte, err error)
- func ToAddress(a byte, addr []byte, port []byte) string
- type Client
- func (c *Client) Close() error
- func (c *Client) Dial(network, addr string) (net.Conn, error)
- func (c *Client) DialWithLocalAddr(network, src, dst string, remoteAddr net.Addr) (net.Conn, error)
- func (c *Client) LocalAddr() net.Addr
- func (c *Client) Negotiate(laddr net.Addr) error
- func (c *Client) Read(b []byte) (int, error)
- func (c *Client) RemoteAddr() net.Addr
- func (c *Client) Request(r *Request) (*Reply, error)
- func (c *Client) SetDeadline(t time.Time) error
- func (c *Client) SetReadDeadline(t time.Time) error
- func (c *Client) SetWriteDeadline(t time.Time) error
- func (c *Client) Write(b []byte) (int, error)
- type Datagram
- type DefaultHandle
- type Handler
- type NegotiationReply
- type NegotiationRequest
- type Reply
- type Request
- type Server
- type UDPExchange
- type UserPassNegotiationReply
- type UserPassNegotiationRequest
Examples ¶
Constants ¶
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 ¶
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") )
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") )
var Debug bool
var DialTCP func(network string, laddr, raddr string) (net.Conn, error) = func(network string, laddr, raddr string) (net.Conn, error) { var la, ra *net.TCPAddr if laddr != "" { var err error la, err = net.ResolveTCPAddr(network, laddr) if err != nil { return nil, err } } a, err := Resolve(network, raddr) if err != nil { return nil, err } ra = a.(*net.TCPAddr) return net.DialTCP(network, la, ra) }
var DialUDP func(network string, laddr, raddr string) (net.Conn, error) = func(network string, laddr, raddr string) (net.Conn, error) { var la, ra *net.UDPAddr if laddr != "" { var err error la, err = net.ResolveUDPAddr(network, laddr) if err != nil { return nil, err } } a, err := Resolve(network, raddr) if err != nil { return nil, err } ra = a.(*net.UDPAddr) return net.DialUDP(network, la, ra) }
var ( // ErrBadReply is the error when read reply ErrBadReply = errors.New("Bad Reply") )
var Resolve func(network string, addr string) (net.Addr, error) = func(network string, addr string) (net.Addr, error) { if network == "tcp" { return net.ResolveTCPAddr("tcp", addr) } return net.ResolveUDPAddr("udp", addr) }
Functions ¶
func ParseAddress ¶
ParseAddress format address x.x.x.x:xx to raw address. addr contains domain length
func ParseBytesAddress ¶
bytes to address addr contains domain length
Types ¶
type Client ¶
type Client struct {
Server string
UserName string
Password string
// On cmd UDP, let server control the tcp and udp connection relationship
TCPConn net.Conn
UDPConn net.Conn
RemoteAddress net.Addr
TCPTimeout int
UDPTimeout int
Dst string
}
Client is socks5 client wrapper
Example (Tcp) ¶
package main
import (
"io/ioutil"
"log"
"net"
"net/http"
"github.com/txthinking/socks5"
)
func ExampleServer() {
s, err := socks5.NewClassicServer("127.0.0.1:1080", "127.0.0.1", "", "", 0, 60)
if err != nil {
log.Println(err)
return
}
s.ListenAndServe(nil)
}
func main() {
go ExampleServer()
c, err := socks5.NewClient("127.0.0.1:1080", "", "", 0, 60)
if err != nil {
log.Println(err)
return
}
client := &http.Client{
Transport: &http.Transport{
Dial: func(network, addr string) (net.Conn, error) {
return c.Dial(network, addr)
},
},
}
res, err := client.Get("https://ifconfig.co")
if err != nil {
log.Println(err)
return
}
defer res.Body.Close()
b, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Println(err)
return
}
log.Println("tcp", string(b))
}
Example (Udp) ¶
package main
import (
"encoding/hex"
"log"
"github.com/miekg/dns"
"github.com/txthinking/socks5"
)
func ExampleServer() {
s, err := socks5.NewClassicServer("127.0.0.1:1080", "127.0.0.1", "", "", 0, 60)
if err != nil {
log.Println(err)
return
}
s.ListenAndServe(nil)
}
func main() {
go ExampleServer()
c, err := socks5.NewClient("127.0.0.1:1080", "", "", 0, 60)
if err != nil {
log.Println(err)
return
}
conn, err := c.Dial("udp", "8.8.8.8:53")
if err != nil {
log.Println(err)
return
}
b, err := hex.DecodeString("0001010000010000000000000a74787468696e6b696e6703636f6d0000010001")
if err != nil {
log.Println(err)
return
}
if _, err := conn.Write(b); err != nil {
log.Println(err)
return
}
b = make([]byte, 2048)
n, err := conn.Read(b)
if err != nil {
log.Println(err)
return
}
m := &dns.Msg{}
if err := m.Unpack(b[0:n]); err != nil {
log.Println(err)
return
}
log.Println(m.String())
}
func (*Client) DialWithLocalAddr ¶
If you want to send address that expects to use to send UDP, just assign it to src, otherwise it will send zero address. Recommend specifying the src address in a non-NAT environment, and leave it blank in other cases.
func (*Client) RemoteAddr ¶
type Datagram ¶
type Datagram struct {
Rsv []byte // 0x00 0x00
Frag byte
Atyp byte
DstAddr []byte
DstPort []byte // 2 bytes
Data []byte
}
Datagram is the UDP packet
func NewDatagram ¶
NewDatagram return datagram packet can be writed into client, dstaddr should not have domain length
func NewDatagramFromBytes ¶
type DefaultHandle ¶
type DefaultHandle struct {
}
DefaultHandle implements Handler interface
type Handler ¶
type Handler interface {
// Request has not been replied yet
TCPHandle(*Server, *net.TCPConn, *Request) error
UDPHandle(*Server, *net.UDPAddr, *Datagram) error
}
Handler handle tcp, udp request
type NegotiationReply ¶
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
type NegotiationRequest ¶
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
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 ¶
NewReply return reply packet can be writed into client, bndaddr should not have domain length
func NewReplyFrom ¶
NewReplyFrom read reply packet from server
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 ¶
NewRequest return request packet can be writed into server, dstaddr should not have domain length
func NewRequestFrom ¶
NewRequestFrom read requst packet from client
func (*Request) Connect ¶
Connect remote conn which u want to connect with your dialer Error or OK both replied.
type Server ¶
type Server struct {
UserName string
Password string
Method byte
SupportedCommands []byte
Addr string
ServerAddr net.Addr
UDPConn *net.UDPConn
UDPExchanges *cache.Cache
TCPTimeout int
UDPTimeout int
Handle Handler
AssociatedUDP *cache.Cache
UDPSrc *cache.Cache
RunnerGroup *runnergroup.RunnerGroup
// RFC: [UDP ASSOCIATE] The server MAY use this information to limit access to the association. Default false, no limit.
LimitUDP bool
}
Server is socks5 server wrapper
Example ¶
package main
import (
"log"
"github.com/txthinking/socks5"
)
func main() {
s, err := socks5.NewClassicServer("127.0.0.1:1080", "127.0.0.1", "", "", 0, 60)
if err != nil {
log.Println(err)
return
}
// You can pass in custom Handler
s.ListenAndServe(nil)
// #Output:
}
func NewClassicServer ¶
func NewClassicServer(addr, ip, username, password string, tcpTimeout, udpTimeout int) (*Server, error)
NewClassicServer return a server which allow none method
func (*Server) GetRequest ¶
func (s *Server) GetRequest(rw io.ReadWriter) (*Request, error)
GetRequest get request packet from client, and check command according to SupportedCommands Error replied.
type UDPExchange ¶
UDPExchange used to store client address and remote connection
type UserPassNegotiationReply ¶
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
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