github.com/xxf098/lite-proxy@v0.15.1-0.20230422081941-12c69f323218/transport/socks5/socks5.go (about)

     1  package socks5
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"errors"
     7  	"io"
     8  	"net"
     9  	"strconv"
    10  )
    11  
    12  // Error represents a SOCKS error
    13  type Error byte
    14  
    15  func (err Error) Error() string {
    16  	return "SOCKS error: " + strconv.Itoa(int(err))
    17  }
    18  
    19  const (
    20  	AtypIPv4       = 1
    21  	AtypDomainName = 3
    22  	AtypIPv6       = 4
    23  )
    24  
    25  // SOCKS errors as defined in RFC 1928 section 6.
    26  const (
    27  	ErrGeneralFailure       = Error(1)
    28  	ErrConnectionNotAllowed = Error(2)
    29  	ErrNetworkUnreachable   = Error(3)
    30  	ErrHostUnreachable      = Error(4)
    31  	ErrConnectionRefused    = Error(5)
    32  	ErrTTLExpired           = Error(6)
    33  	ErrCommandNotSupported  = Error(7)
    34  	ErrAddressNotSupported  = Error(8)
    35  )
    36  
    37  // MaxAddrLen is the maximum size of SOCKS address in bytes.
    38  const MaxAddrLen = 1 + 1 + 255 + 2
    39  
    40  type Addr []byte
    41  
    42  func (a Addr) String() string {
    43  	var host, port string
    44  
    45  	switch a[0] {
    46  	case AtypDomainName:
    47  		hostLen := uint16(a[1])
    48  		host = string(a[2 : 2+hostLen])
    49  		port = strconv.Itoa((int(a[2+hostLen]) << 8) | int(a[2+hostLen+1]))
    50  	case AtypIPv4:
    51  		host = net.IP(a[1 : 1+net.IPv4len]).String()
    52  		port = strconv.Itoa((int(a[1+net.IPv4len]) << 8) | int(a[1+net.IPv4len+1]))
    53  	case AtypIPv6:
    54  		host = net.IP(a[1 : 1+net.IPv6len]).String()
    55  		port = strconv.Itoa((int(a[1+net.IPv6len]) << 8) | int(a[1+net.IPv6len+1]))
    56  	}
    57  
    58  	return net.JoinHostPort(host, port)
    59  }
    60  
    61  func (a Addr) UDPAddr() *net.UDPAddr {
    62  	if len(a) == 0 {
    63  		return nil
    64  	}
    65  	switch a[0] {
    66  	case AtypIPv4:
    67  		var ip [net.IPv4len]byte
    68  		copy(ip[0:], a[1:1+net.IPv4len])
    69  		return &net.UDPAddr{IP: net.IP(ip[:]), Port: int(binary.BigEndian.Uint16(a[1+net.IPv4len : 1+net.IPv4len+2]))}
    70  	case AtypIPv6:
    71  		var ip [net.IPv6len]byte
    72  		copy(ip[0:], a[1:1+net.IPv6len])
    73  		return &net.UDPAddr{IP: net.IP(ip[:]), Port: int(binary.BigEndian.Uint16(a[1+net.IPv6len : 1+net.IPv6len+2]))}
    74  	}
    75  	// Other Atyp
    76  	return nil
    77  }
    78  
    79  func SplitAddr(b []byte) Addr {
    80  	addrLen := 1
    81  	if len(b) < addrLen {
    82  		return nil
    83  	}
    84  
    85  	switch b[0] {
    86  	case AtypDomainName:
    87  		if len(b) < 2 {
    88  			return nil
    89  		}
    90  		addrLen = 1 + 1 + int(b[1]) + 2
    91  	case AtypIPv4:
    92  		addrLen = 1 + net.IPv4len + 2
    93  	case AtypIPv6:
    94  		addrLen = 1 + net.IPv6len + 2
    95  	default:
    96  		return nil
    97  
    98  	}
    99  
   100  	if len(b) < addrLen {
   101  		return nil
   102  	}
   103  
   104  	return b[:addrLen]
   105  }
   106  
   107  func ReadAddr(r io.Reader, b []byte) (Addr, error) {
   108  	if len(b) < MaxAddrLen {
   109  		return nil, io.ErrShortBuffer
   110  	}
   111  	_, err := io.ReadFull(r, b[:1]) // read 1st byte for address type
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  
   116  	switch b[0] {
   117  	case AtypDomainName:
   118  		_, err = io.ReadFull(r, b[1:2]) // read 2nd byte for domain length
   119  		if err != nil {
   120  			return nil, err
   121  		}
   122  		domainLength := uint16(b[1])
   123  		_, err = io.ReadFull(r, b[2:2+domainLength+2])
   124  		return b[:1+1+domainLength+2], err
   125  	case AtypIPv4:
   126  		_, err = io.ReadFull(r, b[1:1+net.IPv4len+2])
   127  		return b[:1+net.IPv4len+2], err
   128  	case AtypIPv6:
   129  		_, err = io.ReadFull(r, b[1:1+net.IPv6len+2])
   130  		return b[:1+net.IPv6len+2], err
   131  	}
   132  
   133  	return nil, ErrAddressNotSupported
   134  }
   135  
   136  func ParseAddrToSocksAddr(addr net.Addr) Addr {
   137  	var hostip net.IP
   138  	var port int
   139  	if udpaddr, ok := addr.(*net.UDPAddr); ok {
   140  		hostip = udpaddr.IP
   141  		port = udpaddr.Port
   142  	} else if tcpaddr, ok := addr.(*net.TCPAddr); ok {
   143  		hostip = tcpaddr.IP
   144  		port = tcpaddr.Port
   145  	}
   146  
   147  	// fallback parse
   148  	if hostip == nil {
   149  		return ParseAddr(addr.String())
   150  	}
   151  
   152  	var parsed Addr
   153  	if ip4 := hostip.To4(); ip4.DefaultMask() != nil {
   154  		parsed = make([]byte, 1+net.IPv4len+2)
   155  		parsed[0] = AtypIPv4
   156  		copy(parsed[1:], ip4)
   157  		binary.BigEndian.PutUint16(parsed[1+net.IPv4len:], uint16(port))
   158  
   159  	} else {
   160  		parsed = make([]byte, 1+net.IPv6len+2)
   161  		parsed[0] = AtypIPv6
   162  		copy(parsed[1:], hostip)
   163  		binary.BigEndian.PutUint16(parsed[1+net.IPv6len:], uint16(port))
   164  	}
   165  	return parsed
   166  }
   167  
   168  // ParseAddr parses the address in string s. Returns nil if failed.
   169  func ParseAddr(s string) Addr {
   170  	var addr Addr
   171  	host, port, err := net.SplitHostPort(s)
   172  	if err != nil {
   173  		return nil
   174  	}
   175  	if ip := net.ParseIP(host); ip != nil {
   176  		if ip4 := ip.To4(); ip4 != nil {
   177  			addr = make([]byte, 1+net.IPv4len+2)
   178  			addr[0] = AtypIPv4
   179  			copy(addr[1:], ip4)
   180  		} else {
   181  			addr = make([]byte, 1+net.IPv6len+2)
   182  			addr[0] = AtypIPv6
   183  			copy(addr[1:], ip)
   184  		}
   185  	} else {
   186  		if len(host) > 255 {
   187  			return nil
   188  		}
   189  		addr = make([]byte, 1+1+len(host)+2)
   190  		addr[0] = AtypDomainName
   191  		addr[1] = byte(len(host))
   192  		copy(addr[2:], host)
   193  	}
   194  
   195  	portnum, err := strconv.ParseUint(port, 10, 16)
   196  	if err != nil {
   197  		return nil
   198  	}
   199  
   200  	addr[len(addr)-2], addr[len(addr)-1] = byte(portnum>>8), byte(portnum)
   201  
   202  	return addr
   203  }
   204  
   205  func EncodeUDPPacket(addr Addr, payload []byte) (packet []byte, err error) {
   206  	if addr == nil {
   207  		err = errors.New("address is invalid")
   208  		return
   209  	}
   210  	packet = bytes.Join([][]byte{{0, 0, 0}, addr, payload}, []byte{})
   211  	return
   212  }