github.com/AntonOrnatskyi/goproxy@v0.0.0-20190205095733-4526a9fa18b4/utils/socks/server.go (about) 1 package socks 2 3 import ( 4 "fmt" 5 "net" 6 "strings" 7 "time" 8 9 "github.com/AntonOrnatskyi/goproxy/utils" 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 44 type ServerConn struct { 45 target string 46 user string 47 password string 48 conn *net.Conn 49 timeout time.Duration 50 auth *utils.BasicAuth 51 header []byte 52 ver uint8 53 //method 54 methodsCount uint8 55 methods []uint8 56 method uint8 57 //request 58 cmd uint8 59 reserve uint8 60 addressType uint8 61 dstAddr string 62 dstPort string 63 dstHost string 64 UDPConnListener *net.UDPConn 65 enableUDP bool 66 udpIP string 67 } 68 69 func NewServerConn(conn *net.Conn, timeout time.Duration, auth *utils.BasicAuth, enableUDP bool, udpHost string, header []byte) *ServerConn { 70 71 s := &ServerConn{ 72 conn: conn, 73 timeout: timeout, 74 auth: auth, 75 header: header, 76 ver: VERSION_V5, 77 enableUDP: enableUDP, 78 udpIP: udpHost, 79 } 80 return s 81 82 } 83 func (s *ServerConn) Close() { 84 utils.CloseConn(s.conn) 85 } 86 func (s *ServerConn) AuthData() Auth { 87 return Auth{s.user, s.password} 88 } 89 func (s *ServerConn) IsUDP() bool { 90 return s.cmd == CMD_ASSOCIATE 91 } 92 func (s *ServerConn) IsTCP() bool { 93 return s.cmd == CMD_CONNECT 94 } 95 func (s *ServerConn) Method() uint8 { 96 return s.method 97 } 98 func (s *ServerConn) Target() string { 99 return s.target 100 } 101 func (s *ServerConn) Host() string { 102 return s.dstHost 103 } 104 func (s *ServerConn) Port() string { 105 return s.dstPort 106 } 107 func (s *ServerConn) Handshake() (err error) { 108 remoteAddr := (*s.conn).RemoteAddr() 109 localAddr := (*s.conn).LocalAddr() 110 //协商开始 111 //method select request 112 var methodReq MethodsRequest 113 (*s.conn).SetReadDeadline(time.Now().Add(s.timeout)) 114 115 methodReq, e := NewMethodsRequest((*s.conn), s.header) 116 (*s.conn).SetReadDeadline(time.Time{}) 117 if e != nil { 118 (*s.conn).SetReadDeadline(time.Now().Add(s.timeout)) 119 methodReq.Reply(Method_NONE_ACCEPTABLE) 120 (*s.conn).SetReadDeadline(time.Time{}) 121 err = fmt.Errorf("new methods request fail,ERR: %s", e) 122 return 123 } 124 //log.Printf("%v,s.auth == %v && methodReq.Select(Method_NO_AUTH) %v", methodReq.methods, s.auth, methodReq.Select(Method_NO_AUTH)) 125 if s.auth == nil && methodReq.Select(Method_NO_AUTH) && !methodReq.Select(Method_USER_PASS) { 126 // if !methodReq.Select(Method_NO_AUTH) { 127 // (*s.conn).SetReadDeadline(time.Now().Add(s.timeout)) 128 // methodReq.Reply(Method_NONE_ACCEPTABLE) 129 // (*s.conn).SetReadDeadline(time.Time{}) 130 // err = fmt.Errorf("none method found : Method_NO_AUTH") 131 // return 132 // } 133 s.method = Method_NO_AUTH 134 //method select reply 135 (*s.conn).SetReadDeadline(time.Now().Add(s.timeout)) 136 err = methodReq.Reply(Method_NO_AUTH) 137 (*s.conn).SetReadDeadline(time.Time{}) 138 if err != nil { 139 err = fmt.Errorf("reply answer data fail,ERR: %s", err) 140 return 141 } 142 // err = fmt.Errorf("% x", methodReq.Bytes()) 143 } else { 144 //auth 145 if !methodReq.Select(Method_USER_PASS) { 146 (*s.conn).SetReadDeadline(time.Now().Add(s.timeout)) 147 methodReq.Reply(Method_NONE_ACCEPTABLE) 148 (*s.conn).SetReadDeadline(time.Time{}) 149 err = fmt.Errorf("none method found : Method_USER_PASS") 150 return 151 } 152 s.method = Method_USER_PASS 153 //method reply need auth 154 (*s.conn).SetReadDeadline(time.Now().Add(s.timeout)) 155 err = methodReq.Reply(Method_USER_PASS) 156 (*s.conn).SetReadDeadline(time.Time{}) 157 if err != nil { 158 err = fmt.Errorf("reply answer data fail,ERR: %s", err) 159 return 160 } 161 //read auth 162 buf := make([]byte, 500) 163 var n int 164 (*s.conn).SetReadDeadline(time.Now().Add(s.timeout)) 165 n, err = (*s.conn).Read(buf) 166 (*s.conn).SetReadDeadline(time.Time{}) 167 if err != nil { 168 err = fmt.Errorf("read auth info fail,ERR: %s", err) 169 return 170 } 171 r := buf[:n] 172 s.user = string(r[2 : r[1]+2]) 173 s.password = string(r[2+r[1]+1:]) 174 //err = fmt.Errorf("user:%s,pass:%s", user, pass) 175 //auth 176 _userAddr := strings.Split(remoteAddr.String(), ":") 177 _localAddr := strings.Split(localAddr.String(), ":") 178 if s.auth == nil || s.auth.CheckUserPass(s.user, s.password, _userAddr[0], _localAddr[0], "") { 179 (*s.conn).SetDeadline(time.Now().Add(s.timeout)) 180 _, err = (*s.conn).Write([]byte{0x01, 0x00}) 181 (*s.conn).SetDeadline(time.Time{}) 182 if err != nil { 183 err = fmt.Errorf("answer auth success to %s fail,ERR: %s", remoteAddr, err) 184 return 185 } 186 } else { 187 (*s.conn).SetDeadline(time.Now().Add(s.timeout)) 188 _, err = (*s.conn).Write([]byte{0x01, 0x01}) 189 (*s.conn).SetDeadline(time.Time{}) 190 if err != nil { 191 err = fmt.Errorf("answer auth fail to %s fail,ERR: %s", remoteAddr, err) 192 return 193 } 194 err = fmt.Errorf("auth fail from %s", remoteAddr) 195 return 196 } 197 } 198 //request detail 199 (*s.conn).SetReadDeadline(time.Now().Add(s.timeout)) 200 request, e := NewRequest(*s.conn) 201 (*s.conn).SetReadDeadline(time.Time{}) 202 if e != nil { 203 err = fmt.Errorf("read request data fail,ERR: %s", e) 204 return 205 } 206 //协商结束 207 208 switch request.CMD() { 209 case CMD_BIND: 210 err = request.TCPReply(REP_UNKNOWN) 211 if err != nil { 212 err = fmt.Errorf("TCPReply REP_UNKNOWN to %s fail,ERR: %s", remoteAddr, err) 213 return 214 } 215 err = fmt.Errorf("cmd bind not supported, form: %s", remoteAddr) 216 return 217 case CMD_CONNECT: 218 err = request.TCPReply(REP_SUCCESS) 219 if err != nil { 220 err = fmt.Errorf("TCPReply REP_SUCCESS to %s fail,ERR: %s", remoteAddr, err) 221 return 222 } 223 case CMD_ASSOCIATE: 224 if !s.enableUDP { 225 request.UDPReply(REP_UNKNOWN, "0.0.0.0:0") 226 if err != nil { 227 err = fmt.Errorf("UDPReply REP_UNKNOWN to %s fail,ERR: %s", remoteAddr, err) 228 return 229 } 230 err = fmt.Errorf("cmd associate not supported, form: %s", remoteAddr) 231 return 232 } 233 a, _ := net.ResolveUDPAddr("udp", ":0") 234 s.UDPConnListener, err = net.ListenUDP("udp", a) 235 if err != nil { 236 request.UDPReply(REP_UNKNOWN, "0.0.0.0:0") 237 err = fmt.Errorf("udp bind fail,ERR: %s , for %s", err, remoteAddr) 238 return 239 } 240 _, port, _ := net.SplitHostPort(s.UDPConnListener.LocalAddr().String()) 241 err = request.UDPReply(REP_SUCCESS, net.JoinHostPort(s.udpIP, port)) 242 if err != nil { 243 err = fmt.Errorf("UDPReply REP_SUCCESS to %s fail,ERR: %s", remoteAddr, err) 244 return 245 } 246 247 } 248 249 //fill socks info 250 s.target = request.Addr() 251 s.methodsCount = methodReq.MethodsCount() 252 s.methods = methodReq.Methods() 253 s.cmd = request.CMD() 254 s.reserve = request.reserve 255 s.addressType = request.addressType 256 s.dstAddr = request.dstAddr 257 s.dstHost = request.dstHost 258 s.dstPort = request.dstPort 259 return 260 }