github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/proxy/socks5/server.go (about)

     1  package socks5
     2  
     3  import (
     4  	"crypto/subtle"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  	"net"
     9  
    10  	"github.com/Asutorufa/yuhaiin/pkg/log"
    11  	"github.com/Asutorufa/yuhaiin/pkg/net/netapi"
    12  	"github.com/Asutorufa/yuhaiin/pkg/net/proxy/socks5/tools"
    13  	"github.com/Asutorufa/yuhaiin/pkg/net/proxy/yuubinsya"
    14  	"github.com/Asutorufa/yuhaiin/pkg/protos/config/listener"
    15  	"github.com/Asutorufa/yuhaiin/pkg/protos/statistic"
    16  	"github.com/Asutorufa/yuhaiin/pkg/utils/pool"
    17  	"github.com/Asutorufa/yuhaiin/pkg/utils/relay"
    18  )
    19  
    20  func (s *Server) startUDPServer() error {
    21  	packet, err := s.lis.Packet(s.Context())
    22  	if err != nil {
    23  		return err
    24  	}
    25  
    26  	go func() {
    27  		defer packet.Close()
    28  		yuubinsya.StartUDPServer(packet, s.SendPacket, nil, true)
    29  	}()
    30  
    31  	return nil
    32  }
    33  
    34  func (s *Server) startTCPServer() error {
    35  	lis, err := s.lis.Stream(s.Context())
    36  	if err != nil {
    37  		return err
    38  	}
    39  	go func() {
    40  		defer s.Close()
    41  		defer lis.Close()
    42  
    43  		for {
    44  			conn, err := lis.Accept()
    45  			if err != nil {
    46  				log.Error("socks5 accept failed", "err", err)
    47  
    48  				if ne, ok := err.(net.Error); ok && ne.Temporary() {
    49  					continue
    50  				}
    51  				return
    52  			}
    53  
    54  			go func() {
    55  				if err := s.Handle(conn); err != nil {
    56  					if errors.Is(err, netapi.ErrBlocked) {
    57  						log.Debug(err.Error())
    58  					} else {
    59  						log.Error("socks5 server handle failed", "err", err)
    60  					}
    61  				}
    62  			}()
    63  
    64  		}
    65  	}()
    66  
    67  	return nil
    68  }
    69  
    70  func (s *Server) Handle(client net.Conn) (err error) {
    71  	b := pool.GetBytes(pool.DefaultSize)
    72  	defer pool.PutBytes(b)
    73  
    74  	err = s.handshake1(client, b)
    75  	if err != nil {
    76  		return fmt.Errorf("first hand failed: %w", err)
    77  	}
    78  
    79  	if err = s.handshake2(client, b); err != nil {
    80  		return fmt.Errorf("second hand failed: %w", err)
    81  	}
    82  
    83  	return
    84  }
    85  
    86  func (s *Server) handshake1(client net.Conn, buf []byte) error {
    87  	//socks5 first handshake
    88  	if _, err := io.ReadFull(client, buf[:2]); err != nil {
    89  		return fmt.Errorf("read first handshake failed: %w", err)
    90  	}
    91  
    92  	if buf[0] != 0x05 { // ver
    93  		err := writeHandshake1(client, tools.NoAcceptableMethods)
    94  		return fmt.Errorf("no acceptable method: %d, resp err: %w", buf[0], err)
    95  	}
    96  
    97  	nMethods := int(buf[1])
    98  
    99  	if nMethods > len(buf) {
   100  		err := writeHandshake1(client, tools.NoAcceptableMethods)
   101  		return fmt.Errorf("nMethods length of methods out of buf, resp err: %w", err)
   102  	}
   103  
   104  	if _, err := io.ReadFull(client, buf[:nMethods]); err != nil {
   105  		return fmt.Errorf("read methods failed: %w", err)
   106  	}
   107  
   108  	noNeedVerify := s.username == "" && s.password == ""
   109  	userAndPasswordSupport := false
   110  
   111  	for _, v := range buf[:nMethods] { // range all supported methods
   112  		if v == tools.NoAuthenticationRequired && noNeedVerify {
   113  			return writeHandshake1(client, tools.NoAuthenticationRequired)
   114  		}
   115  
   116  		if v == tools.UserAndPassword {
   117  			userAndPasswordSupport = true
   118  		}
   119  	}
   120  
   121  	if userAndPasswordSupport {
   122  		return verifyUserPass(client, s.username, s.password)
   123  	}
   124  
   125  	err := writeHandshake1(client, tools.NoAcceptableMethods)
   126  
   127  	return fmt.Errorf("no acceptable authentication methods: [length: %d, method:%v], response err: %w", nMethods, buf[:nMethods], err)
   128  }
   129  
   130  func verifyUserPass(client net.Conn, user, key string) error {
   131  	if err := writeHandshake1(client, tools.UserAndPassword); err != nil {
   132  		return err
   133  	}
   134  
   135  	b := pool.GetBytes(pool.DefaultSize)
   136  	defer pool.PutBytes(b)
   137  
   138  	if _, err := io.ReadFull(client, b[:2]); err != nil {
   139  		return fmt.Errorf("read ver and user name length failed: %w", err)
   140  	}
   141  
   142  	// if b[0] != 0x01 {
   143  	// 	return fmt.Errorf("unknown ver: %d", b[0])
   144  	// }
   145  
   146  	usernameLength := int(b[1])
   147  
   148  	if _, err := io.ReadFull(client, b[2:2+usernameLength]); err != nil {
   149  		return fmt.Errorf("read username failed: %w", err)
   150  	}
   151  
   152  	username := b[2 : 2+usernameLength]
   153  
   154  	if _, err := io.ReadFull(client, b[2+usernameLength:2+usernameLength+1]); err != nil {
   155  		return fmt.Errorf("read password length failed: %w", err)
   156  	}
   157  
   158  	passwordLength := int(b[2+usernameLength])
   159  
   160  	if _, err := io.ReadFull(client, b[2+usernameLength+1:2+usernameLength+1+passwordLength]); err != nil {
   161  		return fmt.Errorf("read password failed: %w", err)
   162  	}
   163  
   164  	password := b[2+usernameLength+1 : 2+usernameLength+1+passwordLength]
   165  
   166  	if (len(user) > 0 && subtle.ConstantTimeCompare([]byte(user), username) != 1) ||
   167  		(len(key) > 0 && subtle.ConstantTimeCompare([]byte(key), password) != 1) {
   168  		_, err := client.Write([]byte{1, 1})
   169  		return fmt.Errorf("verify username and password failed, resp err: %w", err)
   170  	}
   171  
   172  	_, err := client.Write([]byte{1, 0})
   173  	return err
   174  }
   175  
   176  func (s *Server) handshake2(client net.Conn, buf []byte) error {
   177  	// socks5 second handshake
   178  	if _, err := io.ReadFull(client, buf[:3]); err != nil {
   179  		return fmt.Errorf("read second handshake failed: %w", err)
   180  	}
   181  
   182  	if buf[0] != 0x05 { // ver
   183  		err := writeHandshake2(client, tools.NoAcceptableMethods, netapi.EmptyAddr)
   184  		return fmt.Errorf("no acceptable method: %d, resp err: %w", buf[0], err)
   185  	}
   186  
   187  	var err error
   188  
   189  	switch tools.CMD(buf[1]) { // mode
   190  	case tools.Connect:
   191  		var adr *tools.Addr
   192  		adr, err = tools.ResolveAddr(client)
   193  		if err != nil {
   194  			return fmt.Errorf("resolve addr failed: %w", err)
   195  		}
   196  		defer adr.Free()
   197  
   198  		addr := adr.Address(statistic.Type_tcp)
   199  
   200  		caddr, err := netapi.ParseSysAddr(client.LocalAddr())
   201  		if err != nil {
   202  			return fmt.Errorf("parse local addr failed: %w", err)
   203  		}
   204  		err = writeHandshake2(client, tools.Succeeded, caddr) // response to connect successful
   205  		if err != nil {
   206  			return err
   207  		}
   208  
   209  		return s.SendStream(&netapi.StreamMeta{
   210  			Source:      client.RemoteAddr(),
   211  			Destination: addr,
   212  			Inbound:     client.LocalAddr(),
   213  			Src:         client,
   214  			Address:     addr,
   215  		})
   216  
   217  	case tools.Udp: // udp
   218  		if s.udp {
   219  			err = handleUDP(client)
   220  			break
   221  		}
   222  		fallthrough
   223  
   224  	case tools.Bind: // bind request
   225  		fallthrough
   226  
   227  	default:
   228  		err := writeHandshake2(client, tools.CommandNotSupport, netapi.EmptyAddr)
   229  		return fmt.Errorf("not Support Method %d, resp err: %w", buf[1], err)
   230  	}
   231  
   232  	if err != nil {
   233  		_ = writeHandshake2(client, tools.HostUnreachable, netapi.EmptyAddr)
   234  	}
   235  	return err
   236  }
   237  
   238  func handleUDP(client net.Conn) error {
   239  	laddr, err := netapi.ParseSysAddr(client.LocalAddr())
   240  	if err != nil {
   241  		return fmt.Errorf("parse sys addr failed: %w", err)
   242  	}
   243  	err = writeHandshake2(client, tools.Succeeded, netapi.ParseAddressPort(statistic.Type_tcp, "0.0.0.0", laddr.Port()))
   244  	if err != nil {
   245  		return err
   246  	}
   247  	_, _ = relay.Copy(io.Discard, client)
   248  	return nil
   249  }
   250  
   251  func writeHandshake1(conn net.Conn, errREP byte) error {
   252  	_, err := conn.Write([]byte{0x05, errREP})
   253  	return err
   254  }
   255  
   256  func writeHandshake2(conn net.Conn, errREP byte, addr netapi.Address) error {
   257  	adr := tools.ParseAddr(addr)
   258  	defer adr.Free()
   259  	_, err := conn.Write(append([]byte{0x05, errREP, 0x00}, adr.Bytes.Bytes()...))
   260  	return err
   261  }
   262  
   263  type Server struct {
   264  	udp      bool
   265  	lis      netapi.Listener
   266  	username string
   267  	password string
   268  
   269  	*netapi.ChannelServer
   270  }
   271  
   272  func (s *Server) Close() error {
   273  	s.ChannelServer.Close()
   274  	return s.lis.Close()
   275  }
   276  
   277  func init() {
   278  	listener.RegisterProtocol(NewServer)
   279  }
   280  
   281  func NewServer(o *listener.Inbound_Socks5) func(netapi.Listener) (netapi.Accepter, error) {
   282  	return func(ii netapi.Listener) (netapi.Accepter, error) {
   283  		s := &Server{
   284  			udp:           o.Socks5.Udp,
   285  			username:      o.Socks5.Username,
   286  			password:      o.Socks5.Password,
   287  			lis:           ii,
   288  			ChannelServer: netapi.NewChannelServer(),
   289  		}
   290  
   291  		if s.udp {
   292  			if err := s.startUDPServer(); err != nil {
   293  				return nil, err
   294  			}
   295  		}
   296  
   297  		if err := s.startTCPServer(); err != nil {
   298  			s.Close()
   299  			return nil, err
   300  		}
   301  
   302  		return s, nil
   303  	}
   304  }