github.com/yaling888/clash@v1.53.0/listener/socks/tcp.go (about)

     1  package socks
     2  
     3  import (
     4  	"io"
     5  	"net"
     6  
     7  	"github.com/yaling888/clash/adapter/inbound"
     8  	N "github.com/yaling888/clash/common/net"
     9  	"github.com/yaling888/clash/component/auth"
    10  	C "github.com/yaling888/clash/constant"
    11  	authStore "github.com/yaling888/clash/listener/auth"
    12  	"github.com/yaling888/clash/transport/socks4"
    13  	"github.com/yaling888/clash/transport/socks5"
    14  )
    15  
    16  type Listener struct {
    17  	listener net.Listener
    18  	addr     string
    19  	auth     auth.Authenticator
    20  	closed   bool
    21  }
    22  
    23  // RawAddress implements C.Listener
    24  func (l *Listener) RawAddress() string {
    25  	return l.addr
    26  }
    27  
    28  // Address implements C.Listener
    29  func (l *Listener) Address() string {
    30  	return l.listener.Addr().String()
    31  }
    32  
    33  // Close implements C.Listener
    34  func (l *Listener) Close() error {
    35  	l.closed = true
    36  	return l.listener.Close()
    37  }
    38  
    39  // SetAuthenticator implements C.AuthenticatorListener
    40  func (l *Listener) SetAuthenticator(users []auth.AuthUser) {
    41  	l.auth = auth.NewAuthenticator(users)
    42  }
    43  
    44  func New(addr string, in chan<- C.ConnContext) (C.Listener, error) {
    45  	l, err := net.Listen("tcp", addr)
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  
    50  	sl := &Listener{
    51  		listener: l,
    52  		addr:     addr,
    53  	}
    54  	go func() {
    55  		for {
    56  			c, err := l.Accept()
    57  			if err != nil {
    58  				if sl.closed {
    59  					break
    60  				}
    61  				continue
    62  			}
    63  			go handleSocks(c, in, sl.auth)
    64  		}
    65  	}()
    66  
    67  	return sl, nil
    68  }
    69  
    70  func New4(addr string, in chan<- C.ConnContext) (C.Listener, error) {
    71  	l, err := net.Listen("tcp", addr)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	sl := &Listener{
    77  		listener: l,
    78  		addr:     addr,
    79  	}
    80  	go func() {
    81  		for {
    82  			c, err := l.Accept()
    83  			if err != nil {
    84  				if sl.closed {
    85  					break
    86  				}
    87  				continue
    88  			}
    89  			_ = c.(*net.TCPConn).SetKeepAlive(true)
    90  			go HandleSocks4(c, in, sl.auth)
    91  		}
    92  	}()
    93  
    94  	return sl, nil
    95  }
    96  
    97  func New5(addr string, in chan<- C.ConnContext) (C.Listener, error) {
    98  	l, err := net.Listen("tcp", addr)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  
   103  	sl := &Listener{
   104  		listener: l,
   105  		addr:     addr,
   106  	}
   107  	go func() {
   108  		for {
   109  			c, err := l.Accept()
   110  			if err != nil {
   111  				if sl.closed {
   112  					break
   113  				}
   114  				continue
   115  			}
   116  			_ = c.(*net.TCPConn).SetKeepAlive(true)
   117  			go HandleSocks5(c, in, sl.auth)
   118  		}
   119  	}()
   120  
   121  	return sl, nil
   122  }
   123  
   124  func handleSocks(conn net.Conn, in chan<- C.ConnContext, auth auth.Authenticator) {
   125  	_ = conn.(*net.TCPConn).SetKeepAlive(true)
   126  	bufConn := N.NewBufferedConn(conn)
   127  	head, err := bufConn.Peek(1)
   128  	if err != nil {
   129  		_ = conn.Close()
   130  		return
   131  	}
   132  
   133  	switch head[0] {
   134  	case socks4.Version:
   135  		HandleSocks4(bufConn, in, auth)
   136  	case socks5.Version:
   137  		HandleSocks5(bufConn, in, auth)
   138  	default:
   139  		_ = conn.Close()
   140  	}
   141  }
   142  
   143  func HandleSocks4(conn net.Conn, in chan<- C.ConnContext, auth auth.Authenticator) {
   144  	authenticator := auth
   145  	if authenticator == nil {
   146  		authenticator = authStore.Authenticator()
   147  	}
   148  	addr, _, err := socks4.ServerHandshake(conn, authenticator)
   149  	if err != nil {
   150  		_ = conn.Close()
   151  		return
   152  	}
   153  	in <- inbound.NewSocket(socks5.ParseAddr(addr), conn, C.SOCKS4)
   154  }
   155  
   156  func HandleSocks5(conn net.Conn, in chan<- C.ConnContext, auth auth.Authenticator) {
   157  	authenticator := auth
   158  	if authenticator == nil {
   159  		authenticator = authStore.Authenticator()
   160  	}
   161  	target, command, err := socks5.ServerHandshake(conn, authenticator)
   162  	if err != nil {
   163  		_ = conn.Close()
   164  		return
   165  	}
   166  	if command == socks5.CmdUDPAssociate {
   167  		_, _ = io.Copy(io.Discard, conn)
   168  		_ = conn.Close()
   169  		return
   170  	}
   171  	in <- inbound.NewSocket(target, conn, C.SOCKS5)
   172  }