github.com/metacubex/mihomo@v1.18.5/listener/tuic/server.go (about)

     1  package tuic
     2  
     3  import (
     4  	"context"
     5  	"crypto/tls"
     6  	"net"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/metacubex/mihomo/adapter/inbound"
    11  	CN "github.com/metacubex/mihomo/common/net"
    12  	"github.com/metacubex/mihomo/common/sockopt"
    13  	C "github.com/metacubex/mihomo/constant"
    14  	LC "github.com/metacubex/mihomo/listener/config"
    15  	"github.com/metacubex/mihomo/listener/sing"
    16  	"github.com/metacubex/mihomo/log"
    17  	"github.com/metacubex/mihomo/transport/socks5"
    18  	"github.com/metacubex/mihomo/transport/tuic"
    19  
    20  	"github.com/gofrs/uuid/v5"
    21  	"github.com/metacubex/quic-go"
    22  	"golang.org/x/exp/slices"
    23  )
    24  
    25  const ServerMaxIncomingStreams = (1 << 32) - 1
    26  
    27  type Listener struct {
    28  	closed       bool
    29  	config       LC.TuicServer
    30  	udpListeners []net.PacketConn
    31  	servers      []*tuic.Server
    32  }
    33  
    34  func New(config LC.TuicServer, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener, error) {
    35  	if len(additions) == 0 {
    36  		additions = []inbound.Addition{
    37  			inbound.WithInName("DEFAULT-TUIC"),
    38  			inbound.WithSpecialRules(""),
    39  		}
    40  	}
    41  	h, err := sing.NewListenerHandler(sing.ListenerConfig{
    42  		Tunnel:    tunnel,
    43  		Type:      C.TUIC,
    44  		Additions: additions,
    45  		MuxOption: config.MuxOption,
    46  	})
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	cert, err := CN.ParseCert(config.Certificate, config.PrivateKey, C.Path)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  	tlsConfig := &tls.Config{
    56  		MinVersion:   tls.VersionTLS13,
    57  		Certificates: []tls.Certificate{cert},
    58  	}
    59  	if len(config.ALPN) > 0 {
    60  		tlsConfig.NextProtos = config.ALPN
    61  	} else {
    62  		tlsConfig.NextProtos = []string{"h3"}
    63  	}
    64  	quicConfig := &quic.Config{
    65  		MaxIdleTimeout:        time.Duration(config.MaxIdleTime) * time.Millisecond,
    66  		MaxIncomingStreams:    ServerMaxIncomingStreams,
    67  		MaxIncomingUniStreams: ServerMaxIncomingStreams,
    68  		EnableDatagrams:       true,
    69  		Allow0RTT:             true,
    70  	}
    71  	quicConfig.InitialStreamReceiveWindow = tuic.DefaultStreamReceiveWindow / 10
    72  	quicConfig.MaxStreamReceiveWindow = tuic.DefaultStreamReceiveWindow
    73  	quicConfig.InitialConnectionReceiveWindow = tuic.DefaultConnectionReceiveWindow / 10
    74  	quicConfig.MaxConnectionReceiveWindow = tuic.DefaultConnectionReceiveWindow
    75  
    76  	packetOverHead := tuic.PacketOverHeadV4
    77  	if len(config.Token) == 0 {
    78  		packetOverHead = tuic.PacketOverHeadV5
    79  	}
    80  
    81  	if config.CWND == 0 {
    82  		config.CWND = 32
    83  	}
    84  
    85  	if config.MaxUdpRelayPacketSize == 0 {
    86  		config.MaxUdpRelayPacketSize = 1500
    87  	}
    88  	maxDatagramFrameSize := config.MaxUdpRelayPacketSize + packetOverHead
    89  	if maxDatagramFrameSize > 1400 {
    90  		maxDatagramFrameSize = 1400
    91  	}
    92  	config.MaxUdpRelayPacketSize = maxDatagramFrameSize - packetOverHead
    93  	quicConfig.MaxDatagramFrameSize = int64(maxDatagramFrameSize)
    94  
    95  	handleTcpFn := func(conn net.Conn, addr socks5.Addr, _additions ...inbound.Addition) error {
    96  		newAdditions := additions
    97  		if len(_additions) > 0 {
    98  			newAdditions = slices.Clone(additions)
    99  			newAdditions = append(newAdditions, _additions...)
   100  		}
   101  		conn, metadata := inbound.NewSocket(addr, conn, C.TUIC, newAdditions...)
   102  		if h.IsSpecialFqdn(metadata.Host) {
   103  			go func() { // ParseSpecialFqdn will block, so open a new goroutine
   104  				_ = h.ParseSpecialFqdn(
   105  					sing.WithAdditions(context.Background(), newAdditions...),
   106  					conn,
   107  					sing.ConvertMetadata(metadata),
   108  				)
   109  			}()
   110  			return nil
   111  		}
   112  		go tunnel.HandleTCPConn(conn, metadata)
   113  		return nil
   114  	}
   115  	handleUdpFn := func(addr socks5.Addr, packet C.UDPPacket, _additions ...inbound.Addition) error {
   116  		newAdditions := additions
   117  		if len(_additions) > 0 {
   118  			newAdditions = slices.Clone(additions)
   119  			newAdditions = append(newAdditions, _additions...)
   120  		}
   121  		tunnel.HandleUDPPacket(inbound.NewPacket(addr, packet, C.TUIC, newAdditions...))
   122  		return nil
   123  	}
   124  
   125  	option := &tuic.ServerOption{
   126  		HandleTcpFn:           handleTcpFn,
   127  		HandleUdpFn:           handleUdpFn,
   128  		TlsConfig:             tlsConfig,
   129  		QuicConfig:            quicConfig,
   130  		CongestionController:  config.CongestionController,
   131  		AuthenticationTimeout: time.Duration(config.AuthenticationTimeout) * time.Millisecond,
   132  		MaxUdpRelayPacketSize: config.MaxUdpRelayPacketSize,
   133  		CWND:                  config.CWND,
   134  	}
   135  	if len(config.Token) > 0 {
   136  		tokens := make([][32]byte, len(config.Token))
   137  		for i, token := range config.Token {
   138  			tokens[i] = tuic.GenTKN(token)
   139  		}
   140  		option.Tokens = tokens
   141  	}
   142  	if len(config.Users) > 0 {
   143  		users := make(map[[16]byte]string)
   144  		for _uuid, password := range config.Users {
   145  			users[uuid.FromStringOrNil(_uuid)] = password
   146  		}
   147  		option.Users = users
   148  	}
   149  
   150  	sl := &Listener{false, config, nil, nil}
   151  
   152  	for _, addr := range strings.Split(config.Listen, ",") {
   153  		addr := addr
   154  
   155  		ul, err := net.ListenPacket("udp", addr)
   156  		if err != nil {
   157  			return nil, err
   158  		}
   159  
   160  		err = sockopt.UDPReuseaddr(ul.(*net.UDPConn))
   161  		if err != nil {
   162  			log.Warnln("Failed to Reuse UDP Address: %s", err)
   163  		}
   164  
   165  		sl.udpListeners = append(sl.udpListeners, ul)
   166  
   167  		var server *tuic.Server
   168  		server, err = tuic.NewServer(option, ul)
   169  		if err != nil {
   170  			return nil, err
   171  		}
   172  
   173  		sl.servers = append(sl.servers, server)
   174  
   175  		go func() {
   176  			err := server.Serve()
   177  			if err != nil {
   178  				if sl.closed {
   179  					return
   180  				}
   181  			}
   182  		}()
   183  	}
   184  
   185  	return sl, nil
   186  }
   187  
   188  func (l *Listener) Close() error {
   189  	l.closed = true
   190  	var retErr error
   191  	for _, lis := range l.servers {
   192  		err := lis.Close()
   193  		if err != nil {
   194  			retErr = err
   195  		}
   196  	}
   197  	for _, lis := range l.udpListeners {
   198  		err := lis.Close()
   199  		if err != nil {
   200  			retErr = err
   201  		}
   202  	}
   203  	return retErr
   204  }
   205  
   206  func (l *Listener) Config() LC.TuicServer {
   207  	return l.config
   208  }
   209  
   210  func (l *Listener) AddrList() (addrList []net.Addr) {
   211  	for _, lis := range l.udpListeners {
   212  		addrList = append(addrList, lis.LocalAddr())
   213  	}
   214  	return
   215  }