diff --git a/Dockerfile b/Dockerfile index 3dda97b..596b75c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,6 +22,7 @@ ENV PROXY=direct:// ENV MTU=9000 ENV RESTAPI= ENV UDP_TIMEOUT= +ENV UDP_RLYBUF= ENV TCP_SNDBUF= ENV TCP_RCVBUF= ENV TCP_AUTO_TUNING= diff --git a/common/pool/pool.go b/common/pool/pool.go index 8bea3cb..fa87e14 100644 --- a/common/pool/pool.go +++ b/common/pool/pool.go @@ -7,9 +7,10 @@ const ( // MaxSegmentSize is the largest possible UDP datagram size. MaxSegmentSize = (1 << 16) - 1 - // io.Copy default buffer size is 32 KiB, but the maximum packet - // size of vmess/shadowsocks is about 16 KiB, so define a buffer - // of 20 KiB to reduce the memory of each TCP relay. + // RelayBufferSize is a buffer of 20 KiB to reduce the memory + // of each TCP relay as io.Copy default buffer size is 32 KiB, + // but the maximum packet size of vmess/shadowsocks is about + // 16 KiB, so define . RelayBufferSize = 20 << 10 ) diff --git a/engine/engine.go b/engine/engine.go index e7cb863..2284d67 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -129,6 +129,14 @@ func general(k *Key) error { } tunnel.SetUDPTimeout(k.UDPTimeout) } + + if k.UDPRelayBufferSize != "" { + size, err := units.RAMInBytes(k.UDPRelayBufferSize) + if err != nil { + return err + } + tunnel.SetUDPRelayBufferSize(int(size)) + } return nil } diff --git a/engine/key.go b/engine/key.go index 32e39dc..fcbfcd7 100644 --- a/engine/key.go +++ b/engine/key.go @@ -13,7 +13,8 @@ type Key struct { TCPModerateReceiveBuffer bool `yaml:"tcp-moderate-receive-buffer"` TCPSendBufferSize string `yaml:"tcp-send-buffer-size"` TCPReceiveBufferSize string `yaml:"tcp-receive-buffer-size"` + UDPRelayBufferSize string `yaml:"udp-relay-buffer-size"` + UDPTimeout time.Duration `yaml:"udp-timeout"` TUNPreUp string `yaml:"tun-pre-up"` TUNPostUp string `yaml:"tun-post-up"` - UDPTimeout time.Duration `yaml:"udp-timeout"` } diff --git a/main.go b/main.go index 7cc4b1f..e7aa992 100644 --- a/main.go +++ b/main.go @@ -35,6 +35,7 @@ func init() { flag.StringVar(&key.RestAPI, "restapi", "", "HTTP statistic server listen address") flag.StringVar(&key.TCPSendBufferSize, "tcp-sndbuf", "", "Set TCP send buffer size for netstack") flag.StringVar(&key.TCPReceiveBufferSize, "tcp-rcvbuf", "", "Set TCP receive buffer size for netstack") + flag.StringVar(&key.UDPRelayBufferSize, "udp-rlybuf", "", "Set UDP relay buffer size for tunnel") flag.BoolVar(&key.TCPModerateReceiveBuffer, "tcp-auto-tuning", false, "Enable TCP receive buffer auto-tuning") flag.StringVar(&key.TUNPreUp, "tun-pre-up", "", "Execute a command before TUN device setup") flag.StringVar(&key.TUNPostUp, "tun-post-up", "", "Execute a command after TUN device setup") diff --git a/tunnel/udp.go b/tunnel/udp.go index 1672de8..758aa77 100644 --- a/tunnel/udp.go +++ b/tunnel/udp.go @@ -15,13 +15,22 @@ import ( "github.com/xjasonlyu/tun2socks/v2/tunnel/statistic" ) -// _udpSessionTimeout is the default timeout for each UDP session. -var _udpSessionTimeout = 60 * time.Second +var ( + // _udpSessionTimeout is the default timeout for each UDP session. + _udpSessionTimeout = 60 * time.Second + + // _udpRelayBufferSize is the default size for UDP packets relay. + _udpRelayBufferSize = 16 << 10 +) func SetUDPTimeout(t time.Duration) { _udpSessionTimeout = t } +func SetUDPRelayBufferSize(size int) { + _udpRelayBufferSize = size +} + // TODO: Port Restricted NAT support. func handleUDPConn(uc adapter.UDPConn) { defer uc.Close() @@ -84,7 +93,7 @@ func relayPacket(left net.PacketConn, right net.PacketConn, to net.Addr) error { } func copyPacketBuffer(dst net.PacketConn, src net.PacketConn, to net.Addr, timeout time.Duration) error { - buf := pool.Get(pool.MaxSegmentSize) + buf := pool.Get(_udpRelayBufferSize) defer pool.Put(buf) for {