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  }