github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/proxy/socks5/tools/tools.go (about) 1 package tools 2 3 import ( 4 "context" 5 "encoding/binary" 6 "fmt" 7 "io" 8 9 "github.com/Asutorufa/yuhaiin/pkg/net/netapi" 10 "github.com/Asutorufa/yuhaiin/pkg/protos/statistic" 11 "github.com/Asutorufa/yuhaiin/pkg/utils/pool" 12 "github.com/Asutorufa/yuhaiin/pkg/utils/yerror" 13 ) 14 15 const ( 16 NoAuthenticationRequired = 0x00 17 Gssapi = 0x01 18 UserAndPassword = 0x02 19 NoAcceptableMethods = 0xff 20 21 Succeeded = 0x00 22 SocksServerFailure = 0x01 23 ConnectionNotAllowedByRuleset = 0x02 24 NetworkUnreachable = 0x03 25 HostUnreachable = 0x04 26 ConnectionRefused = 0x05 27 TTLExpired = 0x06 28 CommandNotSupport = 0x07 29 AddressTypeNotSupport = 0x08 30 ) 31 32 type CMD byte 33 34 const ( 35 Connect CMD = 0x01 36 Bind CMD = 0x02 37 Udp CMD = 0x03 38 39 IPv4 byte = 0x01 40 Domain byte = 0x03 41 IPv6 byte = 0x04 42 ) 43 44 func EncodeAddr(addr netapi.Address, buf io.Writer) { 45 switch addr.Type() { 46 case netapi.IP: 47 if ip := yerror.Must(addr.IP(context.TODO())).To4(); ip != nil { 48 _, _ = buf.Write([]byte{0x01}) 49 _, _ = buf.Write(ip) 50 } else { 51 _, _ = buf.Write([]byte{0x04}) 52 _, _ = buf.Write(yerror.Must(addr.IP(context.TODO())).To16()) 53 } 54 55 case netapi.FQDN: 56 fallthrough 57 default: 58 _, _ = buf.Write([]byte{0x03, byte(len(addr.Hostname()))}) 59 _, _ = buf.Write([]byte(addr.Hostname())) 60 } 61 _ = binary.Write(buf, binary.BigEndian, addr.Port().Port()) 62 } 63 64 type Addr struct { 65 *pool.Bytes 66 } 67 68 func (a *Addr) Address(network statistic.Type) netapi.Address { 69 if a.Len() == 0 { 70 return netapi.EmptyAddr 71 } 72 73 port := binary.BigEndian.Uint16(a.After(a.Len() - 2)) 74 75 switch a.Bytes.Bytes()[0] { 76 case IPv4, IPv6: 77 return netapi.ParseIPAddrPort(network, a.Bytes.Bytes()[1:a.Len()-2], int(port)) 78 case Domain: 79 hostname := string(a.Bytes.Bytes()[2 : a.Len()-2]) 80 return netapi.ParseDomainPort(network, hostname, netapi.ParsePort(port)) 81 } 82 83 return netapi.EmptyAddr 84 } 85 86 func ResolveAddr(r io.Reader) (*Addr, error) { 87 var buf [2]byte 88 if _, err := io.ReadFull(r, buf[:]); err != nil { 89 return nil, fmt.Errorf("unable to read addr type: %w", err) 90 } 91 92 addr := pool.GetBytesBuffer(1 + 255 + 2 + 1) 93 94 switch buf[0] { 95 case IPv4: 96 addr.Refactor(0, 1+4+2) 97 case IPv6: 98 addr.Refactor(0, 1+16+2) 99 case Domain: 100 addr.Refactor(0, int(1+1+buf[1]+2)) 101 default: 102 return nil, fmt.Errorf("unknown addr type: %d", buf[0]) 103 } 104 105 copy(addr.Bytes()[:2], buf[:]) 106 107 if _, err := io.ReadFull(r, addr.Bytes()[2:]); err != nil { 108 return nil, err 109 } 110 111 return &Addr{addr}, nil 112 } 113 114 func ParseAddr(addr netapi.Address) *Addr { 115 buf := pool.GetBytesWriter(1 + 255 + 2 + 1) 116 EncodeAddr(addr, buf) 117 return &Addr{buf.Unwrap()} 118 }