github.com/AntonOrnatskyi/goproxy@v0.0.0-20190205095733-4526a9fa18b4/core/lib/socks5/socks5.go (about)

     1  package socks5
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"errors"
     7  	"fmt"
     8  	"net"
     9  	"strconv"
    10  )
    11  
    12  const (
    13  	Method_NO_AUTH         = uint8(0x00)
    14  	Method_GSSAPI          = uint8(0x01)
    15  	Method_USER_PASS       = uint8(0x02)
    16  	Method_IANA            = uint8(0x7F)
    17  	Method_RESVERVE        = uint8(0x80)
    18  	Method_NONE_ACCEPTABLE = uint8(0xFF)
    19  	VERSION_V5             = uint8(0x05)
    20  	CMD_CONNECT            = uint8(0x01)
    21  	CMD_BIND               = uint8(0x02)
    22  	CMD_ASSOCIATE          = uint8(0x03)
    23  	ATYP_IPV4              = uint8(0x01)
    24  	ATYP_DOMAIN            = uint8(0x03)
    25  	ATYP_IPV6              = uint8(0x04)
    26  	REP_SUCCESS            = uint8(0x00)
    27  	REP_REQ_FAIL           = uint8(0x01)
    28  	REP_RULE_FORBIDDEN     = uint8(0x02)
    29  	REP_NETWOR_UNREACHABLE = uint8(0x03)
    30  	REP_HOST_UNREACHABLE   = uint8(0x04)
    31  	REP_CONNECTION_REFUSED = uint8(0x05)
    32  	REP_TTL_TIMEOUT        = uint8(0x06)
    33  	REP_CMD_UNSUPPORTED    = uint8(0x07)
    34  	REP_ATYP_UNSUPPORTED   = uint8(0x08)
    35  	REP_UNKNOWN            = uint8(0x09)
    36  	RSV                    = uint8(0x00)
    37  )
    38  
    39  var (
    40  	ZERO_IP   = []byte{0x00, 0x00, 0x00, 0x00}
    41  	ZERO_PORT = []byte{0x00, 0x00}
    42  )
    43  var Socks5Errors = []string{
    44  	"",
    45  	"general failure",
    46  	"connection forbidden",
    47  	"network unreachable",
    48  	"host unreachable",
    49  	"connection refused",
    50  	"TTL expired",
    51  	"command not supported",
    52  	"address type not supported",
    53  }
    54  
    55  // Auth contains authentication parameters that specific Dialers may require.
    56  type UsernamePassword struct {
    57  	Username, Password string
    58  }
    59  
    60  type PacketUDP struct {
    61  	rsv     uint16
    62  	frag    uint8
    63  	atype   uint8
    64  	dstHost string
    65  	dstPort string
    66  	data    []byte
    67  }
    68  
    69  func NewPacketUDP() (p PacketUDP) {
    70  	return PacketUDP{}
    71  }
    72  func (p *PacketUDP) Build(destAddr string, data []byte) (err error) {
    73  	host, port, err := net.SplitHostPort(destAddr)
    74  	if err != nil {
    75  		return
    76  	}
    77  	p.rsv = 0
    78  	p.frag = 0
    79  	p.dstHost = host
    80  	p.dstPort = port
    81  	p.atype = ATYP_IPV4
    82  	if ip := net.ParseIP(host); ip != nil {
    83  		if ip4 := ip.To4(); ip4 != nil {
    84  			p.atype = ATYP_IPV4
    85  			ip = ip4
    86  		} else {
    87  			p.atype = ATYP_IPV6
    88  		}
    89  	} else {
    90  		if len(host) > 255 {
    91  			err = errors.New("proxy: destination host name too long: " + host)
    92  			return
    93  		}
    94  		p.atype = ATYP_DOMAIN
    95  	}
    96  	p.data = data
    97  
    98  	return
    99  }
   100  func (p *PacketUDP) Parse(b []byte) (err error) {
   101  	p.frag = uint8(b[2])
   102  	if p.frag != 0 {
   103  		err = fmt.Errorf("FRAG only support for 0 , %v ,%v", p.frag, b[:4])
   104  		return
   105  	}
   106  	portIndex := 0
   107  	p.atype = b[3]
   108  	switch p.atype {
   109  	case ATYP_IPV4: //IP V4
   110  		p.dstHost = net.IPv4(b[4], b[5], b[6], b[7]).String()
   111  		portIndex = 8
   112  	case ATYP_DOMAIN: //域名
   113  		domainLen := uint8(b[4])
   114  		p.dstHost = string(b[5 : 5+domainLen]) //b[4]表示域名的长度
   115  		portIndex = int(5 + domainLen)
   116  	case ATYP_IPV6: //IP V6
   117  		p.dstHost = net.IP{b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19]}.String()
   118  		portIndex = 20
   119  	}
   120  	p.dstPort = strconv.Itoa(int(b[portIndex])<<8 | int(b[portIndex+1]))
   121  	p.data = b[portIndex+2:]
   122  	return
   123  }
   124  func (p *PacketUDP) Header() []byte {
   125  	header := new(bytes.Buffer)
   126  	header.Write([]byte{0x00, 0x00, p.frag, p.atype})
   127  	if p.atype == ATYP_IPV4 {
   128  		ip := net.ParseIP(p.dstHost)
   129  		header.Write(ip.To4())
   130  	} else if p.atype == ATYP_IPV6 {
   131  		ip := net.ParseIP(p.dstHost)
   132  		header.Write(ip.To16())
   133  	} else if p.atype == ATYP_DOMAIN {
   134  		hBytes := []byte(p.dstHost)
   135  		header.WriteByte(byte(len(hBytes)))
   136  		header.Write(hBytes)
   137  	}
   138  	port, _ := strconv.ParseUint(p.dstPort, 10, 64)
   139  	portBytes := new(bytes.Buffer)
   140  	binary.Write(portBytes, binary.BigEndian, port)
   141  	header.Write(portBytes.Bytes()[portBytes.Len()-2:])
   142  	return header.Bytes()
   143  }
   144  func (p *PacketUDP) Bytes() []byte {
   145  	packBytes := new(bytes.Buffer)
   146  	packBytes.Write(p.Header())
   147  	packBytes.Write(p.data)
   148  	return packBytes.Bytes()
   149  }
   150  func (p *PacketUDP) Host() string {
   151  	return p.dstHost
   152  }
   153  
   154  func (p *PacketUDP) Port() string {
   155  	return p.dstPort
   156  }
   157  func (p *PacketUDP) Data() []byte {
   158  	return p.data
   159  }