github.com/geph-official/geph2@v0.22.6-0.20210211030601-f527cb59b0df/libs/tinysocks/socks5.go (about)

     1  package tinysocks
     2  
     3  import (
     4  	"errors"
     5  	"io"
     6  	"net"
     7  	"strconv"
     8  )
     9  
    10  // SOCKS request commands as defined in RFC 1928 section 4.
    11  const (
    12  	CmdConnect      = 1
    13  	CmdBind         = 2
    14  	CmdUDPAssociate = 3
    15  )
    16  
    17  // SOCKS address types as defined in RFC 1928 section 5.
    18  const (
    19  	AtypIPv4       = 1
    20  	AtypDomainName = 3
    21  	AtypIPv6       = 4
    22  )
    23  
    24  // Error represents a SOCKS error
    25  type Error byte
    26  
    27  func (err Error) Error() string {
    28  	return "SOCKS error: " + strconv.Itoa(int(err))
    29  }
    30  
    31  // SOCKS errors as defined in RFC 1928 section 6.
    32  const (
    33  	ErrGeneralFailure       = Error(1)
    34  	ErrConnectionNotAllowed = Error(2)
    35  	ErrNetworkUnreachable   = Error(3)
    36  	ErrHostUnreachable      = Error(4)
    37  	ErrConnectionRefused    = Error(5)
    38  	ErrTTLExpired           = Error(6)
    39  	ErrCommandNotSupported  = Error(7)
    40  	ErrAddressNotSupported  = Error(8)
    41  	InfoUDPAssociate        = Error(9)
    42  )
    43  
    44  // MaxAddrLen is the maximum size of SOCKS address in bytes.
    45  const MaxAddrLen = 1 + 1 + 255 + 2
    46  
    47  // Addr represents a SOCKS address as defined in RFC 1928 section 5.
    48  type Addr []byte
    49  
    50  // String serializes SOCKS address a to string form.
    51  func (a Addr) String() string {
    52  	var host, port string
    53  
    54  	switch a[0] { // address type
    55  	case AtypDomainName:
    56  		host = string(a[2 : 2+int(a[1])])
    57  		port = strconv.Itoa((int(a[2+int(a[1])]) << 8) | int(a[2+int(a[1])+1]))
    58  	case AtypIPv4:
    59  		host = net.IP(a[1 : 1+net.IPv4len]).String()
    60  		port = strconv.Itoa((int(a[1+net.IPv4len]) << 8) | int(a[1+net.IPv4len+1]))
    61  	case AtypIPv6:
    62  		host = net.IP(a[1 : 1+net.IPv6len]).String()
    63  		port = strconv.Itoa((int(a[1+net.IPv6len]) << 8) | int(a[1+net.IPv6len+1]))
    64  	}
    65  
    66  	return net.JoinHostPort(host, port)
    67  }
    68  
    69  func readAddr(r io.Reader, b []byte) (Addr, error) {
    70  	if len(b) < MaxAddrLen {
    71  		return nil, io.ErrShortBuffer
    72  	}
    73  	_, err := io.ReadFull(r, b[:1]) // read 1st byte for address type
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  
    78  	switch b[0] {
    79  	case AtypDomainName:
    80  		_, err = io.ReadFull(r, b[1:2]) // read 2nd byte for domain length
    81  		if err != nil {
    82  			return nil, err
    83  		}
    84  		_, err = io.ReadFull(r, b[2:2+int(b[1])+2])
    85  		return b[:1+1+int(b[1])+2], err
    86  	case AtypIPv4:
    87  		_, err = io.ReadFull(r, b[1:1+net.IPv4len+2])
    88  		return b[:1+net.IPv4len+2], err
    89  	case AtypIPv6:
    90  		_, err = io.ReadFull(r, b[1:1+net.IPv6len+2])
    91  		return b[:1+net.IPv6len+2], err
    92  	}
    93  
    94  	return nil, ErrAddressNotSupported
    95  }
    96  
    97  // ReadAddr reads just enough bytes from r to get a valid Addr.
    98  func ReadAddr(r io.Reader) (Addr, error) {
    99  	return readAddr(r, make([]byte, MaxAddrLen))
   100  }
   101  
   102  // SplitAddr slices a SOCKS address from beginning of b. Returns nil if failed.
   103  func SplitAddr(b []byte) Addr {
   104  	addrLen := 1
   105  	if len(b) < addrLen {
   106  		return nil
   107  	}
   108  
   109  	switch b[0] {
   110  	case AtypDomainName:
   111  		if len(b) < 2 {
   112  			return nil
   113  		}
   114  		addrLen = 1 + 1 + int(b[1]) + 2
   115  	case AtypIPv4:
   116  		addrLen = 1 + net.IPv4len + 2
   117  	case AtypIPv6:
   118  		addrLen = 1 + net.IPv6len + 2
   119  	default:
   120  		return nil
   121  
   122  	}
   123  
   124  	if len(b) < addrLen {
   125  		return nil
   126  	}
   127  
   128  	return b[:addrLen]
   129  }
   130  
   131  // ParseAddr parses the address in string s. Returns nil if failed.
   132  func ParseAddr(s string) Addr {
   133  	var addr Addr
   134  	host, port, err := net.SplitHostPort(s)
   135  	if err != nil {
   136  		return nil
   137  	}
   138  	if ip := net.ParseIP(host); ip != nil {
   139  		if ip4 := ip.To4(); ip4 != nil {
   140  			addr = make([]byte, 1+net.IPv4len+2)
   141  			addr[0] = AtypIPv4
   142  			copy(addr[1:], ip4)
   143  		} else {
   144  			addr = make([]byte, 1+net.IPv6len+2)
   145  			addr[0] = AtypIPv6
   146  			copy(addr[1:], ip)
   147  		}
   148  	} else {
   149  		if len(host) > 255 {
   150  			return nil
   151  		}
   152  		addr = make([]byte, 1+1+len(host)+2)
   153  		addr[0] = AtypDomainName
   154  		addr[1] = byte(len(host))
   155  		copy(addr[2:], host)
   156  	}
   157  
   158  	portnum, err := strconv.ParseUint(port, 10, 16)
   159  	if err != nil {
   160  		return nil
   161  	}
   162  
   163  	addr[len(addr)-2], addr[len(addr)-1] = byte(portnum>>8), byte(portnum)
   164  
   165  	return addr
   166  }
   167  
   168  // Handshake fast-tracks SOCKS initialization to get target address to connect.
   169  func ReadRequest(rw io.ReadWriter) (byte, Addr, error) {
   170  	// Read RFC 1928 for request and reply structure and sizes.
   171  	buf := make([]byte, MaxAddrLen)
   172  	// read VER, NMETHODS, METHODS
   173  	if _, err := io.ReadFull(rw, buf[:2]); err != nil {
   174  		return 0, nil, err
   175  	}
   176  	nmethods := buf[1]
   177  	if _, err := io.ReadFull(rw, buf[:nmethods]); err != nil {
   178  		return 0, nil, err
   179  	}
   180  	// write VER METHOD
   181  	if _, err := rw.Write([]byte{5, 0}); err != nil {
   182  		return 0, nil, err
   183  	}
   184  	// read VER CMD RSV ATYP DST.ADDR DST.PORT
   185  	if _, err := io.ReadFull(rw, buf[:3]); err != nil {
   186  		return 0, nil, err
   187  	}
   188  	cmd := buf[1]
   189  	addr, err := readAddr(rw, buf)
   190  	if err != nil {
   191  		return 0, nil, err
   192  	}
   193  	return cmd, addr, err // skip VER, RSV fields
   194  }
   195  
   196  // Reply to client abount condition of proxy target
   197  func CompleteRequestTCP(errcode byte, conn io.ReadWriteCloser) error {
   198  	_, err := conn.Write([]byte{5, errcode, 0, 1, 0, 0, 0, 0, 0, 0})
   199  	if err != nil {
   200  		return errors.New("Couldn't complete handshake")
   201  	}
   202  	return nil
   203  }
   204  
   205  // Client outbounds SOCKS5 requests.
   206  func Client(rw io.ReadWriter, ad Addr, conntype int) (error, Addr) {
   207  	// Read RFC 1928 for request and reply structure and sizes.
   208  	buf := make([]byte, MaxAddrLen)
   209  	// write VER, NMETHODS, METHODS
   210  	if _, err := rw.Write([]byte{5, 1, 0}); err != nil {
   211  		return err, nil
   212  	}
   213  	// read VER METHOD
   214  	if _, err := io.ReadFull(rw, buf[:2]); err != nil {
   215  		return err, nil
   216  	}
   217  	if buf[0] != 5 || buf[1] != 0 {
   218  		return errors.New("SOCKS server mismatch"), nil
   219  	}
   220  	if conntype == CmdConnect {
   221  		// write VER, CMD, RSV, ATYP, DST.ADDR, DST.PORT
   222  		copy(buf[:], []byte{5, 1, 0})
   223  		copy(buf[3:], ad)
   224  		lentosend := 3 + len(ad)
   225  		if _, err := rw.Write(buf[:lentosend]); err != nil {
   226  			return err, nil
   227  		}
   228  		_, err := io.ReadFull(rw, buf[:3])
   229  		if err != nil {
   230  			return errors.New("Couldn't read server response"), nil
   231  		}
   232  		if buf[1] != 0 {
   233  			err = errors.New("Failed to pass to local proxy")
   234  		}
   235  		readAddr(rw, buf)
   236  		return err, nil
   237  	} else if conntype == CmdUDPAssociate {
   238  		// write VER, CMD, RSV, ATYP, DST.ADDR, DST.PORT
   239  		copy(buf[:], []byte{5, 3, 0})
   240  		copy(buf[3:], ad)
   241  		lentosend := 3 + len(ad)
   242  		if _, err := rw.Write(buf[:lentosend]); err != nil {
   243  			return err, nil
   244  		}
   245  		_, err := io.ReadFull(rw, buf[:3])
   246  		if err != nil {
   247  			return errors.New("Couldn't read server response"), nil
   248  		}
   249  		if buf[1] != 0 {
   250  			err = errors.New("Failed to pass to local proxy")
   251  		}
   252  		addr, err := readAddr(rw, buf)
   253  		return err, addr
   254  	} else {
   255  		return errors.New("SOCKS command unsupported"), nil
   256  	}
   257  }