github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgNet/kmgProxy/Socks4aDial.go (about) 1 package kmgProxy 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "io" 7 "net" 8 "time" 9 10 "github.com/bronze1man/kmg/kmgNet" 11 ) 12 13 func Socks4aDialTimeout(proxyAddr string, targetAddr string, timeout time.Duration) (conn net.Conn, err error) { 14 conn, err = net.DialTimeout("tcp", proxyAddr, timeout) 15 if err != nil { 16 return 17 } 18 err = socks4aConnect(conn, targetAddr) 19 if err != nil { 20 conn.Close() 21 return 22 } 23 return 24 } 25 func Socks4aDial(proxyAddr string, targetAddr string) (conn net.Conn, err error) { 26 return Socks4aDialTimeout(proxyAddr, targetAddr, 0) 27 } 28 29 func NewSocks4aDialer(proxyAddr string) kmgNet.Dialer { 30 return func(network, address string) (net.Conn, error) { 31 return Socks4aDialTimeout(proxyAddr, address, 0) 32 } 33 } 34 35 //按照socks4a接口,连接到那个地址去,后面可以当成这个连接已经连接到了对方主机,本实现没有用户密码功能 36 func socks4aConnect(conn net.Conn, addr string) (err error) { 37 uaddr, err := ParseUnsolvedAddr(addr) 38 if err != nil { 39 return 40 } 41 toWriteHeader := []byte{4, 1, 0, 0, 0, 0, 0, 1, 0} 42 binary.BigEndian.PutUint16(toWriteHeader[2:4], uint16(uaddr.Port)) 43 if uaddr.Ip != nil { 44 ip := uaddr.Ip.To4() 45 if ip == nil { 46 return fmt.Errorf("you can not connect to a ipv6 addr with socks4a") 47 } 48 copy(toWriteHeader[4:8], []byte(ip[:4])) 49 } else { 50 toWriteHeader = append(toWriteHeader, []byte(uaddr.Domain)...) 51 toWriteHeader = append(toWriteHeader, 0) 52 } 53 _, err = conn.Write(toWriteHeader) 54 if err != nil { 55 return 56 } 57 _, err = io.ReadFull(conn, toWriteHeader[:8]) 58 if err != nil { 59 return 60 } 61 switch toWriteHeader[1] { 62 case 0x5a: 63 //ok 64 case 0x5b: 65 return fmt.Errorf("socks4a: request rejected or failed") 66 case 0x5c: 67 return fmt.Errorf("socks4a: request failed because client is not running identd (or not reachable from the server)") 68 case 0x5d: 69 return fmt.Errorf("socks4a: request failed because client is not running identd (or not reachable from the server)") 70 default: 71 return fmt.Errorf("socks4a: protoal error 1 %d", toWriteHeader[1]) 72 } 73 return 74 }