github.com/AntonOrnatskyi/goproxy@v0.0.0-20190205095733-4526a9fa18b4/utils/ss/util.go (about) 1 package ss 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "io" 7 "net" 8 "strconv" 9 10 "github.com/AntonOrnatskyi/goproxy/utils" 11 ) 12 13 const leakyBufSize = 4108 // data.len(2) + hmacsha1(10) + data(4096) 14 const maxNBuf = 2048 15 16 var leakyBuf = utils.NewLeakyBuf(maxNBuf, leakyBufSize) 17 18 const ( 19 idType = 0 // address type index 20 idIP0 = 1 // ip addres start index 21 idDmLen = 1 // domain address length index 22 idDm0 = 2 // domain address start index 23 24 typeIPv4 = 1 // type is ipv4 address 25 typeDm = 3 // type is domain address 26 typeIPv6 = 4 // type is ipv6 address 27 28 lenIPv4 = net.IPv4len + 2 // ipv4 + 2port 29 lenIPv6 = net.IPv6len + 2 // ipv6 + 2port 30 lenDmBase = 2 // 1addrLen + 2port, plus addrLen 31 lenHmacSha1 = 10 32 ) 33 34 func GetRequest(conn *Conn) (host string, err error) { 35 36 // buf size should at least have the same size with the largest possible 37 // request size (when addrType is 3, domain name has at most 256 bytes) 38 // 1(addrType) + 1(lenByte) + 255(max length address) + 2(port) + 10(hmac-sha1) 39 buf := make([]byte, 269) 40 // read till we get possible domain length field 41 if _, err = io.ReadFull(conn, buf[:idType+1]); err != nil { 42 return 43 } 44 45 var reqStart, reqEnd int 46 addrType := buf[idType] 47 switch addrType & AddrMask { 48 case typeIPv4: 49 reqStart, reqEnd = idIP0, idIP0+lenIPv4 50 case typeIPv6: 51 reqStart, reqEnd = idIP0, idIP0+lenIPv6 52 case typeDm: 53 if _, err = io.ReadFull(conn, buf[idType+1:idDmLen+1]); err != nil { 54 return 55 } 56 reqStart, reqEnd = idDm0, idDm0+int(buf[idDmLen])+lenDmBase 57 default: 58 err = fmt.Errorf("addr type %d not supported", addrType&AddrMask) 59 return 60 } 61 62 if _, err = io.ReadFull(conn, buf[reqStart:reqEnd]); err != nil { 63 return 64 } 65 66 // Return string for typeIP is not most efficient, but browsers (Chrome, 67 // Safari, Firefox) all seems using typeDm exclusively. So this is not a 68 // big problem. 69 switch addrType & AddrMask { 70 case typeIPv4: 71 host = net.IP(buf[idIP0 : idIP0+net.IPv4len]).String() 72 case typeIPv6: 73 host = net.IP(buf[idIP0 : idIP0+net.IPv6len]).String() 74 case typeDm: 75 host = string(buf[idDm0 : idDm0+int(buf[idDmLen])]) 76 } 77 // parse port 78 port := binary.BigEndian.Uint16(buf[reqEnd-2 : reqEnd]) 79 host = net.JoinHostPort(host, strconv.Itoa(int(port))) 80 81 return 82 }