diff --git a/core/option/option.go b/core/option/option.go index 13d04f0..823210b 100644 --- a/core/option/option.go +++ b/core/option/option.go @@ -159,6 +159,17 @@ func WithICMPLimit(limit rate.Limit) Option { } } +// WithTCPSendBufferSize sets default the send buffer size for TCP. +func WithTCPSendBufferSize(size int) Option { + return func(s *stack.Stack) error { + sndOpt := tcpip.TCPSendBufferSizeRangeOption{Min: tcpMinBufferSize, Default: size, Max: tcpMaxBufferSize} + if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &sndOpt); err != nil { + return fmt.Errorf("set TCP send buffer size range: %s", err) + } + return nil + } +} + // WithTCPSendBufferSizeRange sets the send buffer size range for TCP. func WithTCPSendBufferSizeRange(a, b, c int) Option { return func(s *stack.Stack) error { @@ -170,6 +181,17 @@ func WithTCPSendBufferSizeRange(a, b, c int) Option { } } +// WithTCPReceiveBufferSize sets the default receive buffer size for TCP. +func WithTCPReceiveBufferSize(size int) Option { + return func(s *stack.Stack) error { + rcvOpt := tcpip.TCPReceiveBufferSizeRangeOption{Min: tcpMinBufferSize, Default: size, Max: tcpMaxBufferSize} + if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &rcvOpt); err != nil { + return fmt.Errorf("set TCP receive buffer size range: %s", err) + } + return nil + } +} + // WithTCPReceiveBufferSizeRange sets the receive buffer size range for TCP. func WithTCPReceiveBufferSizeRange(a, b, c int) Option { return func(s *stack.Stack) error { diff --git a/engine/engine.go b/engine/engine.go index cc3a1ab..499a2bf 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -8,12 +8,14 @@ import ( "github.com/xjasonlyu/tun2socks/v2/component/dialer" "github.com/xjasonlyu/tun2socks/v2/core" "github.com/xjasonlyu/tun2socks/v2/core/device" + "github.com/xjasonlyu/tun2socks/v2/core/option" "github.com/xjasonlyu/tun2socks/v2/engine/mirror" "github.com/xjasonlyu/tun2socks/v2/log" "github.com/xjasonlyu/tun2socks/v2/proxy" "github.com/xjasonlyu/tun2socks/v2/restapi" "github.com/xjasonlyu/tun2socks/v2/tunnel" + units "github.com/docker/go-units" "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/stack" ) @@ -156,12 +158,34 @@ func netstack(k *Key) (err error) { return } + var opts []option.Option + if k.TCPModerateReceiveBuffer { + opts = append(opts, option.WithTCPModerateReceiveBuffer(true)) + } + + if k.TCPSendBufferSize != "" { + size, err := units.RAMInBytes(k.TCPSendBufferSize) + if err != nil { + return err + } + opts = append(opts, option.WithTCPSendBufferSize(int(size))) + } + + if k.TCPReceiveBufferSize != "" { + size, err := units.RAMInBytes(k.TCPReceiveBufferSize) + if err != nil { + return err + } + opts = append(opts, option.WithTCPReceiveBufferSize(int(size))) + } + if _defaultStack, err = core.CreateStack(&core.Config{ LinkEndpoint: _defaultDevice, TransportHandler: &mirror.Tunnel{}, PrintFunc: func(format string, v ...any) { log.Warnf("[STACK] %s", fmt.Sprintf(format, v...)) }, + Options: opts, }); err != nil { return } diff --git a/engine/key.go b/engine/key.go index 7e9f729..25d0a00 100644 --- a/engine/key.go +++ b/engine/key.go @@ -1,12 +1,15 @@ package engine type Key struct { - MTU int `yaml:"mtu"` - Mark int `yaml:"fwmark"` - UDPTimeout int `yaml:"udp-timeout"` - Proxy string `yaml:"proxy"` - RestAPI string `yaml:"restapi"` - Device string `yaml:"device"` - LogLevel string `yaml:"loglevel"` - Interface string `yaml:"interface"` + MTU int `yaml:"mtu"` + Mark int `yaml:"fwmark"` + UDPTimeout int `yaml:"udp-timeout"` + Proxy string `yaml:"proxy"` + RestAPI string `yaml:"restapi"` + Device string `yaml:"device"` + LogLevel string `yaml:"loglevel"` + Interface string `yaml:"interface"` + TCPModerateReceiveBuffer bool `yaml:"tcp-moderate-receive-buffer"` + TCPSendBufferSize string `yaml:"tcp-send-buffer-size"` + TCPReceiveBufferSize string `yaml:"tcp-receive-buffer-size"` } diff --git a/main.go b/main.go index 410067d..724aed0 100644 --- a/main.go +++ b/main.go @@ -24,7 +24,6 @@ var ( ) func init() { - flag.BoolVar(&versionFlag, "version", false, "Show version and then quit") flag.IntVar(&key.Mark, "fwmark", 0, "Set firewall MARK (Linux only)") flag.IntVar(&key.MTU, "mtu", 0, "Set device maximum transmission unit (MTU)") flag.IntVar(&key.UDPTimeout, "udp-timeout", 0, "Set timeout for each UDP session") @@ -34,6 +33,10 @@ func init() { flag.StringVar(&key.LogLevel, "loglevel", "info", "Log level [debug|info|warning|error|silent]") flag.StringVar(&key.Proxy, "proxy", "", "Use this proxy [protocol://]host[:port]") flag.StringVar(&key.RestAPI, "restapi", "", "HTTP statistic server listen address") + flag.StringVar(&key.TCPSendBufferSize, "tcp-sndbuf", "", "Set TCP send buffer size for stack") + flag.StringVar(&key.TCPReceiveBufferSize, "tcp-rcvbuf", "", "Set TCP receive buffer size for stack") + flag.BoolVar(&key.TCPModerateReceiveBuffer, "tcp-auto-tuning", false, "Enable TCP receive buffer auto-tuning") + flag.BoolVar(&versionFlag, "version", false, "Show version and then quit") flag.Parse() }