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

     1  package tun
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"runtime"
     7  
     8  	"github.com/Asutorufa/yuhaiin/pkg/log"
     9  	"github.com/Asutorufa/yuhaiin/pkg/net/netapi"
    10  	"github.com/Asutorufa/yuhaiin/pkg/net/netlink"
    11  	"github.com/Asutorufa/yuhaiin/pkg/protos/config/listener"
    12  	"golang.org/x/time/rate"
    13  	"gvisor.dev/gvisor/pkg/tcpip"
    14  	"gvisor.dev/gvisor/pkg/tcpip/header"
    15  	"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
    16  	"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
    17  	"gvisor.dev/gvisor/pkg/tcpip/stack"
    18  	"gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
    19  	"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
    20  	"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
    21  )
    22  
    23  type tunServer struct {
    24  	nicID tcpip.NICID
    25  	stack *stack.Stack
    26  	ep    stack.LinkEndpoint
    27  
    28  	*netapi.ChannelServer
    29  }
    30  
    31  func (t *tunServer) Close() error {
    32  
    33  	log.Debug("start close tun server")
    34  
    35  	log.Debug("start close endpoint")
    36  	var err error
    37  	if ep, ok := t.ep.(io.Closer); ok {
    38  		err = ep.Close()
    39  	}
    40  
    41  	log.Debug("start close stack")
    42  	if t.stack != nil {
    43  		log.Debug("start remove routes")
    44  		t.stack.RemoveRoutes(func(r tcpip.Route) bool {
    45  			return true
    46  		})
    47  		log.Debug("start destroy stack")
    48  		t.stack.Destroy()
    49  	}
    50  	log.Debug("start close tun channel server")
    51  	t.ChannelServer.Close()
    52  	return err
    53  }
    54  
    55  type Opt struct {
    56  	*listener.Inbound_Tun
    57  	*netlink.Options
    58  }
    59  
    60  func New(o *Opt) (netapi.Accepter, error) {
    61  	opt := o.Tun
    62  	if opt.Mtu <= 0 {
    63  		opt.Mtu = 1500
    64  	}
    65  
    66  	ep, err := Open(o.Interface, opt.GetDriver(), int(opt.Mtu))
    67  	if err != nil {
    68  		return nil, fmt.Errorf("open tun failed: %w", err)
    69  	}
    70  
    71  	o.Endpoint = ep
    72  
    73  	log.Info("preload tun device", "name", o.Interface, "mtu", opt.Mtu, "portal", opt.Portal)
    74  
    75  	if err = netlink.Route(o.Options); err != nil {
    76  		log.Warn("preload failed", "err", err)
    77  	}
    78  
    79  	log.Debug("new tun stack", "name", opt.Name, "mtu", opt.Mtu, "portal", opt.Portal)
    80  
    81  	stackOption := stack.Options{
    82  		NetworkProtocols: []stack.NetworkProtocolFactory{
    83  			ipv4.NewProtocol,
    84  			ipv6.NewProtocol,
    85  		},
    86  		TransportProtocols: []stack.TransportProtocolFactory{
    87  			tcp.NewProtocol, udp.NewProtocol,
    88  			icmp.NewProtocol4, icmp.NewProtocol6,
    89  		},
    90  	}
    91  
    92  	s := stack.New(stackOption)
    93  
    94  	// Generate unique NIC id.
    95  	nicID := tcpip.NICID(s.UniqueID())
    96  	if er := s.CreateNIC(nicID, ep); er != nil {
    97  		ep.Attach(nil)
    98  		return nil, fmt.Errorf("create nic failed: %v", er)
    99  	}
   100  
   101  	t := &tunServer{
   102  		nicID:         nicID,
   103  		stack:         s,
   104  		ep:            ep,
   105  		ChannelServer: netapi.NewChannelServer(),
   106  	}
   107  
   108  	s.SetSpoofing(nicID, true)
   109  	// By default the netstack NIC will only accept packets for the IPs
   110  	// registered to it. Since in some cases we dynamically register IPs
   111  	// based on the packets that arrive, the NIC needs to accept all
   112  	// incoming packets.
   113  	s.SetPromiscuousMode(nicID, true)
   114  	s.SetRouteTable([]tcpip.Route{
   115  		{Destination: header.IPv4EmptySubnet, NIC: nicID},
   116  		{Destination: header.IPv6EmptySubnet, NIC: nicID},
   117  	})
   118  	ttlopt := tcpip.DefaultTTLOption(defaultTimeToLive)
   119  	s.SetNetworkProtocolOption(ipv4.ProtocolNumber, &ttlopt)
   120  	s.SetNetworkProtocolOption(ipv6.ProtocolNumber, &ttlopt)
   121  
   122  	s.SetForwardingDefaultAndAllNICs(ipv4.ProtocolNumber, ipForwardingEnabled)
   123  	s.SetForwardingDefaultAndAllNICs(ipv6.ProtocolNumber, ipForwardingEnabled)
   124  
   125  	s.SetICMPBurst(icmpBurst)
   126  	s.SetICMPLimit(icmpLimit)
   127  
   128  	rcvOpt := tcpip.TCPReceiveBufferSizeRangeOption{
   129  		Min:     tcp.MinBufferSize,
   130  		Default: tcp.DefaultReceiveBufferSize,
   131  		Max:     tcp.MaxBufferSize,
   132  	}
   133  	s.SetTransportProtocolOption(tcp.ProtocolNumber, &rcvOpt)
   134  
   135  	sndOpt := tcpip.TCPSendBufferSizeRangeOption{
   136  		Min:     tcp.MinBufferSize,
   137  		Default: tcp.DefaultSendBufferSize,
   138  		Max:     tcp.MaxBufferSize,
   139  	}
   140  	s.SetTransportProtocolOption(tcp.ProtocolNumber, &sndOpt)
   141  
   142  	// https://github.com/google/gvisor/issues/6113
   143  	// I meet this issue, but it's already fix?
   144  	opt2 := tcpip.CongestionControlOption(tcpCongestionControlAlgorithm)
   145  	s.SetTransportProtocolOption(tcp.ProtocolNumber, &opt2)
   146  
   147  	opt3 := tcpip.TCPDelayEnabled(tcpDelayEnabled)
   148  	s.SetTransportProtocolOption(tcp.ProtocolNumber, &opt3)
   149  
   150  	sOpt := tcpip.TCPSACKEnabled(tcpSACKEnabled)
   151  	s.SetTransportProtocolOption(tcp.ProtocolNumber, &sOpt)
   152  
   153  	mOpt := tcpip.TCPModerateReceiveBufferOption(tcpModerateReceiveBufferEnabled)
   154  	s.SetTransportProtocolOption(tcp.ProtocolNumber, &mOpt)
   155  
   156  	tr := tcpRecovery
   157  	s.SetTransportProtocolOption(tcp.ProtocolNumber, &tr)
   158  
   159  	s.SetTransportProtocolHandler(tcp.ProtocolNumber, t.tcpForwarder().HandlePacket)
   160  
   161  	// s.SetTransportProtocolHandler(udp.ProtocolNumber, t.udpForwarder().HandlePacket)
   162  	s.SetTransportProtocolHandler(udp.ProtocolNumber, t.HandleUDPPacket)
   163  
   164  	return t, nil
   165  }
   166  
   167  var (
   168  	// defaultTimeToLive specifies the default TTL used by stack.
   169  	defaultTimeToLive uint8 = 64
   170  
   171  	// ipForwardingEnabled is the value used by stack to enable packet
   172  	// forwarding between NICs.
   173  	ipForwardingEnabled = true
   174  
   175  	// icmpBurst is the default number of ICMP messages that can be sent in
   176  	// a single burst.
   177  	icmpBurst = 50
   178  
   179  	// icmpLimit is the default maximum number of ICMP messages permitted
   180  	// by this rate limiter.
   181  	icmpLimit rate.Limit = 1000
   182  
   183  	// tcpCongestionControl is the congestion control algorithm used by
   184  	// stack. ccReno is the default option in gVisor stack.
   185  	tcpCongestionControlAlgorithm = "cubic" // "reno" or "cubic"
   186  
   187  	// tcpDelayEnabled is the value used by stack to enable or disable
   188  	// tcp delay option. Disable Nagle's algorithm here by default.
   189  	tcpDelayEnabled = false
   190  
   191  	// tcpModerateReceiveBufferEnabled is the value used by stack to
   192  	// enable or disable tcp receive buffer auto-tuning option.
   193  	tcpModerateReceiveBufferEnabled = false
   194  
   195  	// tcpSACKEnabled is the value used by stack to enable or disable
   196  	// tcp selective ACK.
   197  	tcpSACKEnabled = true
   198  
   199  	// tcpRecovery is the loss detection algorithm used by TCP.
   200  	tcpRecovery = tcpip.TCPRACKLossDetection
   201  )
   202  
   203  func init() {
   204  	if runtime.GOOS == "windows" {
   205  		// See https://github.com/tailscale/tailscale/issues/9707
   206  		// Windows w/RACK performs poorly. ACKs do not appear to be handled in a
   207  		// timely manner, leading to spurious retransmissions and a reduced
   208  		// congestion window.
   209  		//
   210  		// https://github.com/google/gvisor/issues/9778
   211  		tcpRecovery = tcpip.TCPRecovery(0)
   212  	}
   213  }