├── LICENSE ├── README.md ├── basic.go ├── client.go ├── examples └── socks-server.go └── server.go /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, yinghuocho 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | gosocks 2 | ======= 3 | 4 | A Golang implementation of socks5 proxy 5 | -------------------------------------------------------------------------------- /basic.go: -------------------------------------------------------------------------------- 1 | package gosocks 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "fmt" 7 | "io" 8 | "net" 9 | "strconv" 10 | "strings" 11 | "time" 12 | ) 13 | 14 | const ( 15 | SocksVersion = 0x05 16 | 17 | SocksReserved = 0x00 18 | 19 | SocksNoAuthentication = 0x00 20 | SocksNoAcceptableMethods = 0xFF 21 | 22 | SocksIPv4Host = 0x01 23 | SocksIPv6Host = 0x04 24 | SocksDomainHost = 0x03 25 | 26 | SocksCmdConnect = 0x01 27 | SocksCmdBind = 0x02 28 | SocksCmdUDPAssociate = 0x03 29 | 30 | SocksSucceeded = 0x00 31 | SocksGeneralFailure = 0x01 32 | 33 | SocksNoFragment = 0x00 34 | 35 | smallBufSize = 0x200 36 | largeBufSize = 0x10000 37 | ) 38 | 39 | type SocksRequest struct { 40 | Cmd byte 41 | HostType byte 42 | DstHost string 43 | DstPort uint16 44 | } 45 | 46 | type SocksReply struct { 47 | Rep byte 48 | HostType byte 49 | BndHost string 50 | BndPort uint16 51 | } 52 | 53 | // This is for SocksReply and SocksRequest to share pack/unpack methods. 54 | type socksCommon struct { 55 | Flag byte 56 | HostType byte 57 | Host string 58 | Port uint16 59 | } 60 | 61 | type UDPRequest struct { 62 | Frag byte 63 | HostType byte 64 | DstHost string 65 | DstPort uint16 66 | Data []byte 67 | } 68 | 69 | type SocksConn struct { 70 | net.Conn 71 | Timeout time.Duration 72 | } 73 | 74 | func Ntohs(data [2]byte) uint16 { 75 | return uint16(data[0])<<8 | uint16(data[1])<<0 76 | } 77 | 78 | func Htons(data uint16) (ret [2]byte) { 79 | ret[0] = byte((data >> 8) & 0xff) 80 | ret[1] = byte((data >> 0) & 0xff) 81 | return 82 | } 83 | 84 | func SockAddrString(host string, port uint16) string { 85 | return net.JoinHostPort(host, strconv.Itoa(int(port))) 86 | } 87 | 88 | func SocksAddrToNetAddr(nw, host string, port uint16) net.Addr { 89 | s := net.JoinHostPort(host, strconv.Itoa(int(port))) 90 | var addr net.Addr 91 | switch nw { 92 | case "tcp": 93 | addr, _ = net.ResolveTCPAddr(nw, s) 94 | case "udp": 95 | addr, _ = net.ResolveUDPAddr(nw, s) 96 | } 97 | 98 | return addr 99 | } 100 | 101 | func ParseHost(host string) (byte, string) { 102 | i := strings.LastIndex(host, "%") 103 | s := host 104 | if i > 0 { 105 | s = host[:i] 106 | } 107 | 108 | ip := net.ParseIP(s) 109 | var t byte 110 | if ip != nil { 111 | if ip.To16() != nil { 112 | t = SocksIPv6Host 113 | } else { 114 | t = SocksIPv4Host 115 | } 116 | } else { 117 | t = SocksDomainHost 118 | } 119 | return t, s 120 | } 121 | 122 | func NetAddrToSocksAddr(addr interface{}) (hostType byte, host string, port uint16) { 123 | var ip net.IP 124 | switch addr.(type) { 125 | case *net.UDPAddr: 126 | a := addr.(*net.UDPAddr) 127 | ip = a.IP 128 | port = uint16(a.Port) 129 | case *net.TCPAddr: 130 | a := addr.(*net.TCPAddr) 131 | ip = a.IP 132 | port = uint16(a.Port) 133 | } 134 | 135 | hostType = SocksIPv4Host 136 | if len(ip) == 16 { 137 | hostType = SocksIPv6Host 138 | } 139 | host = ip.String() 140 | return 141 | } 142 | 143 | func readSocksIPv4Host(r io.Reader) (host string, err error) { 144 | var buf [4]byte 145 | _, err = io.ReadFull(r, buf[:]) 146 | if err != nil { 147 | return 148 | } 149 | 150 | var ip net.IP = buf[:] 151 | host = ip.String() 152 | return 153 | } 154 | 155 | func readSocksIPv6Host(r io.Reader) (host string, err error) { 156 | var buf [16]byte 157 | _, err = io.ReadFull(r, buf[:]) 158 | if err != nil { 159 | return 160 | } 161 | 162 | var ip net.IP = buf[:] 163 | host = ip.String() 164 | return 165 | } 166 | 167 | func readSocksDomainHost(r io.Reader) (host string, err error) { 168 | var buf [smallBufSize]byte 169 | _, err = r.Read(buf[0:1]) 170 | if err != nil { 171 | return 172 | } 173 | length := buf[0] 174 | _, err = io.ReadFull(r, buf[1:1+length]) 175 | if err != nil { 176 | return 177 | } 178 | host = string(buf[1 : 1+length]) 179 | return 180 | } 181 | 182 | func readSocksHost(r io.Reader, hostType byte) (string, error) { 183 | switch hostType { 184 | case SocksIPv4Host: 185 | return readSocksIPv4Host(r) 186 | case SocksIPv6Host: 187 | return readSocksIPv6Host(r) 188 | case SocksDomainHost: 189 | return readSocksDomainHost(r) 190 | default: 191 | return string(""), fmt.Errorf("Unknown address type 0x%02x", hostType) 192 | } 193 | } 194 | 195 | func readSocksPort(r io.Reader) (port uint16, err error) { 196 | var buf [2]byte 197 | _, err = io.ReadFull(r, buf[:]) 198 | if err != nil { 199 | return 200 | } 201 | 202 | port = Ntohs(buf) 203 | return 204 | } 205 | 206 | func packSocksHost(hostType byte, host string) (data []byte, err error) { 207 | switch hostType { 208 | case SocksIPv4Host: 209 | ip := net.ParseIP(host) 210 | if ip == nil { 211 | err = fmt.Errorf("Invalid host %s", host) 212 | return 213 | } 214 | data = ip.To4() 215 | return 216 | case SocksIPv6Host: 217 | ip := net.ParseIP(host) 218 | if ip == nil { 219 | err = fmt.Errorf("Invalid host %s", host) 220 | return 221 | } 222 | data = ip.To16() 223 | return 224 | case SocksDomainHost: 225 | data = append(data, byte(len(host))) 226 | data = append(data, []byte(host)...) 227 | return 228 | default: 229 | err = fmt.Errorf("Unknown address type 0x%02x", hostType) 230 | return 231 | } 232 | } 233 | 234 | func readSocksComm(r io.Reader) (data socksCommon, err error) { 235 | var h [4]byte 236 | r = bufio.NewReader(r) 237 | _, err = io.ReadFull(r, h[:]) 238 | if err != nil { 239 | return 240 | } 241 | 242 | if h[0] != SocksVersion { 243 | err = fmt.Errorf("Unsupported version 0x%02x", h[0]) 244 | return 245 | } 246 | 247 | host, err := readSocksHost(r, h[3]) 248 | if err != nil { 249 | return 250 | } 251 | 252 | port, err := readSocksPort(r) 253 | if err != nil { 254 | return 255 | } 256 | 257 | data.Flag = h[1] 258 | data.HostType = h[3] 259 | data.Host = host 260 | data.Port = port 261 | return 262 | } 263 | 264 | func writeSocksComm(w io.Writer, data *socksCommon) (n int, err error) { 265 | // buf := make([]byte, 4, smallBufSize) 266 | var buf [smallBufSize]byte 267 | 268 | buf[0] = SocksVersion 269 | buf[1] = data.Flag 270 | buf[2] = SocksReserved 271 | buf[3] = data.HostType 272 | 273 | h, err := packSocksHost(data.HostType, data.Host) 274 | if err != nil { 275 | return 276 | } 277 | copy(buf[4:], h) 278 | // buf = append(buf, h...) 279 | p := Htons(data.Port) 280 | // buf = append(buf, p[:]...) 281 | copy(buf[(4+len(h)):], p[:]) 282 | 283 | n, err = w.Write(buf[0 : 4+len(h)+2]) 284 | return 285 | } 286 | 287 | func ReadSocksRequest(r io.Reader) (req *SocksRequest, err error) { 288 | data, err := readSocksComm(r) 289 | if err != nil { 290 | return 291 | } 292 | req = &SocksRequest{data.Flag, data.HostType, data.Host, data.Port} 293 | return 294 | } 295 | 296 | func WriteSocksRequest(w io.Writer, req *SocksRequest) (n int, err error) { 297 | data := &socksCommon{req.Cmd, req.HostType, req.DstHost, req.DstPort} 298 | return writeSocksComm(w, data) 299 | } 300 | 301 | func ReadSocksReply(r io.Reader) (reply *SocksReply, err error) { 302 | data, err := readSocksComm(r) 303 | if err != nil { 304 | return 305 | } 306 | reply = &SocksReply{data.Flag, data.HostType, data.Host, data.Port} 307 | return 308 | } 309 | 310 | func ReplyGeneralFailure(w io.Writer, req *SocksRequest) (n int, err error) { 311 | host := "0.0.0.0" 312 | if req.HostType == SocksIPv6Host { 313 | host = "::" 314 | } 315 | return WriteSocksReply(w, &SocksReply{SocksGeneralFailure, SocksIPv4Host, host, 0}) 316 | } 317 | 318 | func WriteSocksReply(w io.Writer, reply *SocksReply) (n int, err error) { 319 | data := &socksCommon{reply.Rep, reply.HostType, reply.BndHost, reply.BndPort} 320 | return writeSocksComm(w, data) 321 | } 322 | 323 | func ParseUDPRequest(data []byte) (udpReq *UDPRequest, err error) { 324 | udpReq = &UDPRequest{} 325 | total := len(data) 326 | if total <= 8 { 327 | err = fmt.Errorf("Invalid UDP Request: only %d bytes data", total) 328 | return 329 | } 330 | udpReq.Frag = data[2] 331 | udpReq.HostType = data[3] 332 | pos := 4 333 | r := bytes.NewReader(data[pos:]) 334 | host, e := readSocksHost(r, udpReq.HostType) 335 | if err != nil { 336 | err = fmt.Errorf("Invalid UDP Request: fail to read dst host: %s", e) 337 | return 338 | } 339 | udpReq.DstHost = host 340 | port, e := readSocksPort(r) 341 | if err != nil { 342 | err = fmt.Errorf("Invalid UDP Request: fail to read dst port: %s", e) 343 | return 344 | } 345 | udpReq.DstPort = port 346 | udpReq.Data = data[total-r.Len():] 347 | return 348 | } 349 | 350 | func PackUDPRequest(udpReq *UDPRequest) []byte { 351 | buf := make([]byte, 4, largeBufSize) 352 | buf[0] = SocksReserved 353 | buf[1] = SocksReserved 354 | buf[2] = udpReq.Frag 355 | buf[3] = udpReq.HostType 356 | h, _ := packSocksHost(udpReq.HostType, udpReq.DstHost) 357 | buf = append(buf, h...) 358 | p := Htons(udpReq.DstPort) 359 | buf = append(buf, p[:]...) 360 | buf = append(buf, udpReq.Data...) 361 | return buf 362 | } 363 | 364 | func LegalClientAddr(clientAssociate *net.UDPAddr, addr *net.UDPAddr) bool { 365 | ip := clientAssociate.IP.String() 366 | if ip == "0.0.0.0" || ip == "::" { 367 | return true 368 | } 369 | if addr.String() == clientAssociate.String() { 370 | return true 371 | } 372 | return false 373 | } 374 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package gosocks 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io" 7 | "net" 8 | "time" 9 | ) 10 | 11 | type ClientAuthenticator interface { 12 | ClientAuthenticate(conn *SocksConn) error 13 | } 14 | 15 | type SocksDialer struct { 16 | Timeout time.Duration 17 | Auth ClientAuthenticator 18 | } 19 | 20 | type AnonymousClientAuthenticator struct{} 21 | 22 | func (a *AnonymousClientAuthenticator) ClientAuthenticate(conn *SocksConn) (err error) { 23 | conn.SetWriteDeadline(time.Now().Add(conn.Timeout)) 24 | var req [3]byte 25 | req[0] = SocksVersion 26 | req[1] = 1 27 | req[2] = SocksNoAuthentication 28 | _, err = conn.Write(req[:]) 29 | if err != nil { 30 | return 31 | } 32 | 33 | conn.SetReadDeadline(time.Now().Add(conn.Timeout)) 34 | var resp [2]byte 35 | r := bufio.NewReader(conn) 36 | _, err = io.ReadFull(r, resp[:2]) 37 | if err != nil { 38 | return 39 | } 40 | if resp[0] != SocksVersion || resp[1] != SocksNoAuthentication { 41 | err = fmt.Errorf("Fail to pass anonymous authentication: (0x%02x, 0x%02x)", resp[0], resp[1]) 42 | return 43 | } 44 | return 45 | } 46 | 47 | func (d *SocksDialer) Dial(address string) (conn *SocksConn, err error) { 48 | c, err := net.DialTimeout("tcp", address, d.Timeout) 49 | if err != nil { 50 | return 51 | } 52 | conn = &SocksConn{c.(*net.TCPConn), d.Timeout} 53 | err = d.Auth.ClientAuthenticate(conn) 54 | if err != nil { 55 | conn.Close() 56 | return 57 | } 58 | return 59 | } 60 | 61 | func ClientAuthAnonymous(conn *SocksConn) (err error) { 62 | conn.SetWriteDeadline(time.Now().Add(conn.Timeout)) 63 | var req [3]byte 64 | req[0] = SocksVersion 65 | req[1] = 1 66 | req[2] = SocksNoAuthentication 67 | _, err = conn.Write(req[:]) 68 | if err != nil { 69 | return 70 | } 71 | 72 | conn.SetReadDeadline(time.Now().Add(conn.Timeout)) 73 | var resp [2]byte 74 | r := bufio.NewReader(conn) 75 | _, err = io.ReadFull(r, resp[:2]) 76 | if err != nil { 77 | return 78 | } 79 | if resp[0] != SocksVersion || resp[1] != SocksNoAuthentication { 80 | err = fmt.Errorf("Fail to pass anonymous authentication: (0x%02x, 0x%02x)", resp[0], resp[1]) 81 | return 82 | } 83 | return 84 | } 85 | 86 | func ClientRequest(conn *SocksConn, req *SocksRequest) (reply *SocksReply, err error) { 87 | conn.SetWriteDeadline(time.Now().Add(conn.Timeout)) 88 | _, err = WriteSocksRequest(conn, req) 89 | if err != nil { 90 | return 91 | } 92 | conn.SetReadDeadline(time.Now().Add(conn.Timeout)) 93 | reply, err = ReadSocksReply(conn) 94 | return 95 | } 96 | -------------------------------------------------------------------------------- /examples/socks-server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/yinghuocho/gosocks" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | srv := gosocks.NewBasicServer(":10800", time.Minute) 10 | srv.ListenAndServe() 11 | } 12 | -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | package gosocks 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io" 7 | "log" 8 | "net" 9 | "sync" 10 | "time" 11 | ) 12 | 13 | const ( 14 | DefaultPort = 1080 15 | ) 16 | 17 | type Handler interface { 18 | ServeSocks(conn *SocksConn) 19 | Quit() 20 | } 21 | 22 | type ServerAuthenticator interface { 23 | ServerAuthenticate(conn *SocksConn) error 24 | } 25 | 26 | type Server struct { 27 | addr string 28 | timeout time.Duration 29 | handler Handler 30 | auth ServerAuthenticator 31 | msgCh chan interface{} 32 | quit chan bool 33 | } 34 | 35 | type UDPPacket struct { 36 | Addr *net.UDPAddr 37 | Data []byte 38 | } 39 | 40 | func (svr *Server) ListenAndServe() error { 41 | addr := svr.addr 42 | if addr == "" { 43 | addr = fmt.Sprintf(":%d", DefaultPort) 44 | } 45 | ln, err := net.Listen("tcp", addr) 46 | if err != nil { 47 | return err 48 | } 49 | defer ln.Close() 50 | return svr.Serve(ln) 51 | } 52 | 53 | func (svr *Server) GetTimeout() time.Duration { 54 | return svr.timeout 55 | } 56 | 57 | // ChangeAuth safely changes authenticator when server is running 58 | func (svr *Server) ChangeAuth(auth ServerAuthenticator) { 59 | select { 60 | case svr.msgCh <- auth: 61 | case <-svr.quit: 62 | } 63 | } 64 | 65 | func (svr *Server) ChangeHandler(handler Handler) { 66 | select { 67 | case svr.msgCh <- handler: 68 | case <-svr.quit: 69 | } 70 | } 71 | 72 | type ret struct { 73 | conn net.Conn 74 | err error 75 | } 76 | 77 | func (svr *Server) Serve(ln net.Listener) error { 78 | // close quit channel after loop ends, so that attempts to change 79 | // authenticator or handler do not block. 80 | defer func() { 81 | close(svr.quit) 82 | svr.handler.Quit() 83 | }() 84 | 85 | ch := make(chan ret) 86 | go func() { 87 | // how long to sleep on accept failure 88 | var tempDelay time.Duration 89 | for { 90 | conn, e := ln.Accept() 91 | if e != nil { 92 | if ne, ok := e.(net.Error); ok && ne.Temporary() { 93 | if tempDelay == 0 { 94 | tempDelay = 5 * time.Millisecond 95 | } else { 96 | tempDelay *= 2 97 | } 98 | if max := 1 * time.Second; tempDelay > max { 99 | tempDelay = max 100 | } 101 | time.Sleep(tempDelay) 102 | continue 103 | } else { 104 | ch <- ret{nil, e} 105 | return 106 | } 107 | } 108 | tempDelay = 0 109 | ch <- ret{conn, e} 110 | } 111 | }() 112 | 113 | for { 114 | select { 115 | case r := <-ch: 116 | if r.err != nil { 117 | return r.err 118 | } 119 | 120 | go func(c net.Conn, to time.Duration, auth ServerAuthenticator, handler Handler) { 121 | socks := &SocksConn{Conn: c, Timeout: to} 122 | // if svr.Auth is nil, Handler should process authenticate. 123 | if auth != nil { 124 | if auth.ServerAuthenticate(socks) != nil { 125 | socks.Close() 126 | return 127 | } 128 | } 129 | handler.ServeSocks(socks) 130 | }(r.conn, svr.timeout, svr.auth, svr.handler) 131 | case msg := <-svr.msgCh: 132 | switch msg.(type) { 133 | case ServerAuthenticator: 134 | svr.auth = msg.(ServerAuthenticator) 135 | case Handler: 136 | svr.handler = msg.(Handler) 137 | } 138 | } 139 | } 140 | } 141 | 142 | type AnonymousServerAuthenticator struct{} 143 | 144 | func (a *AnonymousServerAuthenticator) ServerAuthenticate(conn *SocksConn) (err error) { 145 | conn.SetReadDeadline(time.Now().Add(conn.Timeout)) 146 | var h [smallBufSize]byte 147 | r := bufio.NewReader(conn) 148 | _, err = io.ReadFull(r, h[:2]) 149 | if err != nil { 150 | return 151 | } 152 | 153 | if h[0] != SocksVersion { 154 | err = fmt.Errorf("Unsupported version 0x%02x", h[0]) 155 | return 156 | } 157 | 158 | n := int(h[1]) 159 | _, err = io.ReadFull(r, h[2:(2+n)]) 160 | if err != nil { 161 | return 162 | } 163 | 164 | conn.SetWriteDeadline(time.Now().Add(conn.Timeout)) 165 | var buf [2]byte 166 | buf[0] = SocksVersion 167 | for i := 0; i < n; i++ { 168 | if h[i+3] == SocksNoAuthentication { 169 | buf[1] = SocksNoAuthentication 170 | _, err = conn.Write(buf[:]) 171 | return 172 | } 173 | } 174 | buf[1] = SocksNoAcceptableMethods 175 | _, err = conn.Write(buf[:]) 176 | if err == nil { 177 | err = fmt.Errorf("NoAuthentication(0x%02x) not found in claimed methods", SocksNoAuthentication) 178 | } 179 | return 180 | } 181 | 182 | type BasicSocksHandler struct{} 183 | 184 | func (h *BasicSocksHandler) HandleCmdConnect(req *SocksRequest, conn *SocksConn) { 185 | addr := SockAddrString(req.DstHost, req.DstPort) 186 | log.Printf("connect: %s", addr) 187 | remote, err := net.DialTimeout("tcp", addr, conn.Timeout) 188 | if err != nil { 189 | log.Printf("error in connecting remote target %s: %s", addr, err) 190 | ReplyGeneralFailure(conn, req) 191 | conn.Close() 192 | return 193 | } 194 | 195 | localAddr := remote.LocalAddr() 196 | hostType, host, port := NetAddrToSocksAddr(localAddr) 197 | conn.SetWriteDeadline(time.Now().Add(conn.Timeout)) 198 | _, err = WriteSocksReply(conn, &SocksReply{SocksSucceeded, hostType, host, port}) 199 | if err != nil { 200 | log.Printf("error in sending reply: %s", err) 201 | conn.Close() 202 | remote.Close() 203 | return 204 | } 205 | 206 | CopyLoopTimeout(conn, remote, conn.Timeout) 207 | log.Printf("TCP connection done") 208 | } 209 | 210 | func (h *BasicSocksHandler) UDPAssociateFirstPacket(req *SocksRequest, conn *SocksConn) (*net.UDPConn, *net.UDPAddr, *UDPRequest, *net.UDPAddr, error) { 211 | log.Printf("udp associate: %s:%d", req.DstHost, req.DstPort) 212 | socksAddr := conn.LocalAddr().(*net.TCPAddr) 213 | // create one UDP to recv/send packets from client 214 | clientBind, err := net.ListenUDP("udp", &net.UDPAddr{ 215 | IP: socksAddr.IP, 216 | Port: 0, 217 | Zone: socksAddr.Zone, 218 | }) 219 | if err != nil { 220 | log.Printf("error in binding local UDP: %s", err) 221 | ReplyGeneralFailure(conn, req) 222 | return nil, nil, nil, nil, err 223 | } 224 | 225 | bindAddr := clientBind.LocalAddr() 226 | hostType, host, port := NetAddrToSocksAddr(bindAddr) 227 | log.Printf("UDP bind local address: %s", bindAddr.String()) 228 | conn.SetWriteDeadline(time.Now().Add(conn.Timeout)) 229 | _, err = WriteSocksReply(conn, &SocksReply{SocksSucceeded, hostType, host, port}) 230 | if err != nil { 231 | log.Printf("error in sending reply: %s", err) 232 | clientBind.Close() 233 | return nil, nil, nil, nil, err 234 | } 235 | clientAssociate := SocksAddrToNetAddr("udp", req.DstHost, req.DstPort).(*net.UDPAddr) 236 | 237 | clientBind.SetReadDeadline(time.Now().Add(conn.Timeout)) 238 | var udpReq *UDPRequest 239 | var buf [largeBufSize]byte 240 | var clientAddr *net.UDPAddr 241 | loop: 242 | for { 243 | n, addr, err := clientBind.ReadFromUDP(buf[:]) 244 | if err != nil { 245 | log.Printf("error in reading UDP packet from client: %s", err) 246 | clientBind.Close() 247 | return nil, nil, nil, nil, err 248 | } 249 | // validation 250 | // 1) RFC1928 Section-7 251 | if !LegalClientAddr(clientAssociate, addr) { 252 | log.Printf("illegal addr: %s vs %s", clientAssociate.IP.String(), addr.String()) 253 | continue 254 | } 255 | // 2) format 256 | udpReq, err = ParseUDPRequest(buf[:n]) 257 | if err != nil { 258 | log.Printf("error to parse UDP packet: %s", err) 259 | clientBind.Close() 260 | return nil, nil, nil, nil, err 261 | } 262 | // 3) no fragment 263 | if udpReq.Frag != SocksNoFragment { 264 | continue 265 | } 266 | clientAddr = addr 267 | break loop 268 | } 269 | return clientBind, clientAssociate, udpReq, clientAddr, nil 270 | } 271 | 272 | func (h *BasicSocksHandler) UDPAssociateForwarding(conn *SocksConn, clientBind *net.UDPConn, clientAssociate *net.UDPAddr, firstPkt *UDPRequest, clientAddr *net.UDPAddr) { 273 | forwardingAddr := SocksAddrToNetAddr("udp", firstPkt.DstHost, firstPkt.DstPort).(*net.UDPAddr) 274 | c, err := net.DialUDP("udp", nil, forwardingAddr) 275 | if err != nil { 276 | log.Printf("error to connect UDP target (%s):%s", forwardingAddr.String(), err) 277 | clientBind.Close() 278 | conn.Close() 279 | return 280 | } 281 | uaddr := c.LocalAddr().(*net.UDPAddr) 282 | uaddr.Port = 0 283 | c.Close() 284 | forwardingBind, _ := net.ListenUDP("udp", uaddr) 285 | _, err = forwardingBind.WriteToUDP(firstPkt.Data, forwardingAddr) 286 | if err != nil { 287 | log.Printf("error to send UDP packet to remote: %s", err) 288 | forwardingBind.Close() 289 | clientBind.Close() 290 | return 291 | } 292 | 293 | // monitoring socks connection, quit for any reading event 294 | quit := make(chan bool) 295 | go ConnMonitor(conn, quit) 296 | 297 | // read client UPD packets 298 | chClientUDP := make(chan *UDPPacket) 299 | go UDPReader(clientBind, chClientUDP, quit) 300 | 301 | // read remote UPD packets 302 | chRemoteUDP := make(chan *UDPPacket) 303 | go UDPReader(forwardingBind, chRemoteUDP, quit) 304 | 305 | loop: 306 | for { 307 | t := time.NewTimer(conn.Timeout) 308 | select { 309 | // packets from client 310 | case pkt, ok := <-chClientUDP: 311 | t.Stop() 312 | if !ok { 313 | break loop 314 | } 315 | // validation 316 | // 1) RFC1928 Section-7 317 | if !LegalClientAddr(clientAssociate, pkt.Addr) { 318 | continue 319 | } 320 | // 2) format 321 | udpReq, err := ParseUDPRequest(pkt.Data) 322 | if err != nil { 323 | log.Printf("error to parse UDP packet: %s", err) 324 | break loop 325 | } 326 | // 3) no fragment 327 | if udpReq.Frag != SocksNoFragment { 328 | continue 329 | } 330 | 331 | // update clientAddr (not required) 332 | clientAddr = pkt.Addr 333 | forwardingAddr := SocksAddrToNetAddr("udp", udpReq.DstHost, udpReq.DstPort).(*net.UDPAddr) 334 | _, err = forwardingBind.WriteToUDP(udpReq.Data, forwardingAddr) 335 | if err != nil { 336 | log.Printf("error to send UDP packet to remote: %s", err) 337 | break loop 338 | } 339 | 340 | // packets from remote 341 | case pkt, ok := <-chRemoteUDP: 342 | t.Stop() 343 | if !ok { 344 | break loop 345 | } 346 | 347 | hostType, host, port := NetAddrToSocksAddr(pkt.Addr) 348 | data := PackUDPRequest(&UDPRequest{SocksNoFragment, hostType, host, port, pkt.Data}) 349 | _, err := clientBind.WriteToUDP(data, clientAddr) 350 | if err != nil { 351 | log.Printf("error to send UDP packet to client: %s", err) 352 | break loop 353 | } 354 | 355 | case <-quit: 356 | t.Stop() 357 | log.Printf("UDP unexpected event from socks connection") 358 | break loop 359 | 360 | case <-t.C: 361 | log.Printf("UDP timeout") 362 | break loop 363 | } 364 | t.Stop() 365 | } 366 | 367 | conn.Close() 368 | clientBind.Close() 369 | forwardingBind.Close() 370 | 371 | // readeres may block on writing, try read to wake them so they 372 | // are aware that the underlying connection has closed. 373 | <-chClientUDP 374 | <-chRemoteUDP 375 | } 376 | 377 | func (h *BasicSocksHandler) HandleCmdUDPAssociate(req *SocksRequest, conn *SocksConn) { 378 | clientBind, clientAssociate, udpReq, clientAddr, err := h.UDPAssociateFirstPacket(req, conn) 379 | if err != nil { 380 | conn.Close() 381 | return 382 | } 383 | h.UDPAssociateForwarding(conn, clientBind, clientAssociate, udpReq, clientAddr) 384 | log.Printf("UDP connection done") 385 | } 386 | 387 | func UDPReader(u *net.UDPConn, ch chan<- *UDPPacket, quit chan bool) { 388 | u.SetDeadline(time.Time{}) 389 | var buf [largeBufSize]byte 390 | loop: 391 | for { 392 | n, addr, err := u.ReadFromUDP(buf[:]) 393 | if err != nil { 394 | break loop 395 | } 396 | b := make([]byte, n) 397 | copy(b, buf[:n]) 398 | select { 399 | case ch <- &UDPPacket{addr, b}: 400 | case <-quit: 401 | break loop 402 | } 403 | } 404 | close(ch) 405 | } 406 | 407 | func ConnMonitor(c net.Conn, quit chan bool) { 408 | var buf [1]byte 409 | c.SetDeadline(time.Time{}) 410 | r := bufio.NewReader(c) 411 | r.Read(buf[:]) 412 | close(quit) 413 | } 414 | 415 | type timeoutConn struct { 416 | c net.Conn 417 | t time.Duration 418 | } 419 | 420 | func (tc timeoutConn) Read(buf []byte) (int, error) { 421 | tc.c.SetDeadline(time.Now().Add(tc.t)) 422 | return tc.c.Read(buf) 423 | } 424 | 425 | func (tc timeoutConn) Write(buf []byte) (int, error) { 426 | tc.c.SetDeadline(time.Now().Add(tc.t)) 427 | return tc.c.Write(buf) 428 | } 429 | 430 | func (tc timeoutConn) Close() { 431 | tc.c.Close() 432 | } 433 | 434 | func CopyLoopTimeout(c1 net.Conn, c2 net.Conn, timeout time.Duration) { 435 | tc1 := timeoutConn{c: c1, t: timeout} 436 | tc2 := timeoutConn{c: c2, t: timeout} 437 | var wg sync.WaitGroup 438 | copyer := func(dst timeoutConn, src timeoutConn) { 439 | defer wg.Done() 440 | _, e := io.Copy(dst, src) 441 | dst.Close() 442 | if e != nil { 443 | src.Close() 444 | } 445 | } 446 | wg.Add(2) 447 | go copyer(tc1, tc2) 448 | go copyer(tc2, tc1) 449 | wg.Wait() 450 | } 451 | 452 | func (h *BasicSocksHandler) Quit() {} 453 | 454 | func (h *BasicSocksHandler) ServeSocks(conn *SocksConn) { 455 | conn.SetReadDeadline(time.Now().Add(conn.Timeout)) 456 | req, err := ReadSocksRequest(conn) 457 | if err != nil { 458 | log.Printf("error in ReadSocksRequest: %s", err) 459 | return 460 | } 461 | 462 | switch req.Cmd { 463 | case SocksCmdConnect: 464 | h.HandleCmdConnect(req, conn) 465 | return 466 | case SocksCmdUDPAssociate: 467 | h.HandleCmdUDPAssociate(req, conn) 468 | return 469 | case SocksCmdBind: 470 | conn.Close() 471 | return 472 | default: 473 | return 474 | } 475 | } 476 | 477 | func NewBasicServer(addr string, to time.Duration) *Server { 478 | return &Server{ 479 | addr: addr, 480 | timeout: to, 481 | handler: &BasicSocksHandler{}, 482 | auth: &AnonymousServerAuthenticator{}, 483 | msgCh: make(chan interface{}), 484 | quit: make(chan bool), 485 | } 486 | } 487 | 488 | func NewServer(addr string, to time.Duration, handler Handler, auth ServerAuthenticator) *Server { 489 | return &Server{ 490 | addr: addr, 491 | timeout: to, 492 | handler: handler, 493 | auth: auth, 494 | msgCh: make(chan interface{}), 495 | quit: make(chan bool), 496 | } 497 | } 498 | --------------------------------------------------------------------------------