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 }