diff --git a/handler/tungo/handler.go b/handler/tungo/handler.go index d9976d7a..4e7f92d2 100644 --- a/handler/tungo/handler.go +++ b/handler/tungo/handler.go @@ -20,6 +20,7 @@ import ( "github.com/go-gost/x/registry" "github.com/xjasonlyu/tun2socks/v2/core" "github.com/xjasonlyu/tun2socks/v2/core/adapter" + "github.com/xjasonlyu/tun2socks/v2/core/option" "gvisor.dev/gvisor/pkg/tcpip/stack" ) @@ -129,9 +130,22 @@ func (h *tungoHandler) Handle(ctx context.Context, conn net.Conn, opts ...handle th.ProcessAsync() defer th.Close() + var cOpts []option.Option + if h.md.tcpModerateReceiveBuffer { + cOpts = append(cOpts, option.WithTCPModerateReceiveBuffer(h.md.tcpModerateReceiveBuffer)) + } + if h.md.tcpSendBufferSize > 0 { + cOpts = append(cOpts, option.WithTCPSendBufferSize(h.md.tcpSendBufferSize)) + } + if h.md.tcpReceiveBufferSize > 0 { + cOpts = append(cOpts, option.WithTCPReceiveBufferSize(h.md.tcpReceiveBufferSize)) + } + stack, err := core.CreateStack(&core.Config{ LinkEndpoint: newEndpoint(conn, config.MTU, log), TransportHandler: th, + MulticastGroups: h.md.multicastGroups, + Options: cOpts, }) if err != nil { return err diff --git a/handler/tungo/metadata.go b/handler/tungo/metadata.go index 03929ae1..aa0b058c 100644 --- a/handler/tungo/metadata.go +++ b/handler/tungo/metadata.go @@ -1,6 +1,9 @@ package tungo import ( + "fmt" + "net/netip" + "strings" "time" mdata "github.com/go-gost/core/metadata" @@ -11,7 +14,7 @@ type metadata struct { udpTimeout time.Duration sniffing bool - sniffingUDP bool + sniffingUDP bool sniffingTimeout time.Duration sniffingResponseTimeout time.Duration sniffingFallback bool @@ -21,10 +24,16 @@ type metadata struct { limiterRefreshInterval time.Duration limiterCleanupInterval time.Duration + + multicastGroups []netip.Addr + + tcpSendBufferSize int + tcpReceiveBufferSize int + tcpModerateReceiveBuffer bool } func (h *tungoHandler) parseMetadata(md mdata.Metadata) (err error) { - h.md.udpTimeout = mdutil.GetDuration(md, "udpTimeout") + h.md.udpTimeout = mdutil.GetDuration(md, "udpTimeout", "tungo.udpTimeout") h.md.sniffing = mdutil.GetBool(md, "sniffing") h.md.sniffingUDP = mdutil.GetBool(md, "sniffing.udp") @@ -44,5 +53,23 @@ func (h *tungoHandler) parseMetadata(md mdata.Metadata) (err error) { h.md.limiterRefreshInterval = mdutil.GetDuration(md, "limiter.refreshInterval") h.md.limiterCleanupInterval = mdutil.GetDuration(md, "limiter.cleanupInterval") + for _, v := range strings.Split(mdutil.GetString(md, "multicastGroups", "tungo.multicastGroups"), ",") { + if v = strings.TrimSpace(v); v == "" { + continue + } + addr, err := netip.ParseAddr(v) + if err != nil { + return err + } + if !addr.IsMulticast() { + return fmt.Errorf("invalid multicast IP: %s", addr) + } + h.md.multicastGroups = append(h.md.multicastGroups, addr) + } + + h.md.tcpSendBufferSize = mdutil.GetInt(md, "tcpSendBufferSize", "tungo.tcpSendBufferSize") + h.md.tcpReceiveBufferSize = mdutil.GetInt(md, "tcpReceiveBufferSize", "tungo.tcpReceiveBufferSize") + h.md.tcpModerateReceiveBuffer = mdutil.GetBool(md, "tcpModerateReceiveBuffer", "tungo.tcpModerateReceiveBuffer") + return } diff --git a/internal/net/pipe.go b/internal/net/pipe.go index cdadf2af..890cc6fe 100644 --- a/internal/net/pipe.go +++ b/internal/net/pipe.go @@ -12,7 +12,7 @@ import ( const ( // tcpWaitTimeout implements a TCP half-close timeout. - tcpWaitTimeout = 30 * time.Second + tcpWaitTimeout = 10 * time.Second ) func Pipe(ctx context.Context, rw1, rw2 io.ReadWriter) error { diff --git a/listener/tun/metadata.go b/listener/tun/metadata.go index 938bdff9..069ec8a0 100644 --- a/listener/tun/metadata.go +++ b/listener/tun/metadata.go @@ -19,6 +19,7 @@ const ( type metadata struct { config *tun_util.Config + guid string } func (l *tunListener) parseMetadata(md mdata.Metadata) (err error) { @@ -102,5 +103,7 @@ func (l *tunListener) parseMetadata(md mdata.Metadata) (err error) { l.md.config = config + l.md.guid = mdutil.GetString(md, "guid", "tun.guid") + return } diff --git a/listener/tun/tun_windows.go b/listener/tun/tun_windows.go index 19cc1b20..a0440708 100644 --- a/listener/tun/tun_windows.go +++ b/listener/tun/tun_windows.go @@ -6,6 +6,9 @@ import ( "net" "os/exec" "strings" + + "golang.org/x/sys/windows" + "golang.zx2c4.com/wireguard/tun" ) const ( @@ -14,15 +17,40 @@ const ( writeOffset = 0 ) +func init() { + tun.WintunTunnelType = "GOST" +} + func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) { if l.md.config.Name == "" { l.md.config.Name = defaultTunName } + + if l.md.guid != "" { + var guid windows.GUID + guid, err = windows.GUIDFromString(l.md.guid) + if err != nil { + return + } + tun.WintunStaticRequestedGUID = &guid + } + ifce, name, err = l.createTunDevice() if err != nil { return } + if l.md.config.MTU > 0 { + cmd := fmt.Sprintf("netsh interface ip set subinterface %s mtu=%d", name, l.md.config.MTU) + l.log.Debug(cmd) + + args := strings.Split(cmd, " ") + if er := exec.Command(args[0], args[1:]...).Run(); er != nil { + err = fmt.Errorf("%s: %v", cmd, er) + return + } + } + if len(l.md.config.Net) > 0 { ipNet := l.md.config.Net[0] cmd := fmt.Sprintf("netsh interface ip set address name=%s "+ diff --git a/listener/tungo/metadata.go b/listener/tungo/metadata.go index 8d01672f..c58b1085 100644 --- a/listener/tungo/metadata.go +++ b/listener/tungo/metadata.go @@ -12,12 +12,12 @@ import ( ) const ( - defaultMTU = 1420 - defaultName = "tungo" + defaultMTU = 1420 ) type metadata struct { config *tun_util.Config + guid string } func (l *tunListener) parseMetadata(md mdata.Metadata) (err error) { @@ -29,9 +29,6 @@ func (l *tunListener) parseMetadata(md mdata.Metadata) (err error) { if config.MTU <= 0 { config.MTU = defaultMTU } - if config.Name == "" { - config.Name = defaultName - } if gw := mdutil.GetString(md, "gw", "tun.gw"); gw != "" { config.Gateway = net.ParseIP(gw) } @@ -93,5 +90,7 @@ func (l *tunListener) parseMetadata(md mdata.Metadata) (err error) { l.md.config = config + l.md.guid = mdutil.GetString(md, "guid", "tun.guid") + return } diff --git a/listener/tungo/tun_linux.go b/listener/tungo/tun_linux.go index f8136ef6..cac510aa 100644 --- a/listener/tungo/tun_linux.go +++ b/listener/tungo/tun_linux.go @@ -11,11 +11,15 @@ import ( ) const ( - readOffset = 0 - writeOffset = 16 + defaultTunName = "tungo" + readOffset = 0 + writeOffset = 16 ) func (l *tunListener) createTun() (dev io.ReadWriteCloser, name string, ip net.IP, err error) { + if l.md.config.Name == "" { + l.md.config.Name = defaultTunName + } dev, name, err = l.createTunDevice() if err != nil { return diff --git a/listener/tungo/tun_other.go b/listener/tungo/tun_other.go index 5b65a527..a2a5c85d 100644 --- a/listener/tungo/tun_other.go +++ b/listener/tungo/tun_other.go @@ -11,7 +11,7 @@ import ( ) const ( - defaultTunName = "tun0" + defaultTunName = "tungo" readOffset = 4 writeOffset = 4 ) diff --git a/listener/tungo/tun_windows.go b/listener/tungo/tun_windows.go index 9bbff3a0..74494191 100644 --- a/listener/tungo/tun_windows.go +++ b/listener/tungo/tun_windows.go @@ -6,23 +6,51 @@ import ( "net" "os/exec" "strings" + + "golang.org/x/sys/windows" + "golang.zx2c4.com/wireguard/tun" ) const ( - defaultTunName = "wintun" + defaultTunName = "tungo" readOffset = 0 writeOffset = 0 ) +func init() { + tun.WintunTunnelType = "GOST" +} + func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) { if l.md.config.Name == "" { l.md.config.Name = defaultTunName } + + if l.md.guid != "" { + var guid windows.GUID + guid, err = windows.GUIDFromString(l.md.guid) + if err != nil { + return + } + tun.WintunStaticRequestedGUID = &guid + } + ifce, name, err = l.createTunDevice() if err != nil { return } + if l.md.config.MTU > 0 { + cmd := fmt.Sprintf("netsh interface ip set subinterface %s mtu=%d", name, l.md.config.MTU) + l.log.Debug(cmd) + + args := strings.Split(cmd, " ") + if er := exec.Command(args[0], args[1:]...).Run(); er != nil { + err = fmt.Errorf("%s: %v", cmd, er) + return + } + } + if len(l.md.config.Net) > 0 { ipNet := l.md.config.Net[0] cmd := fmt.Sprintf("netsh interface ip set address name=%s "+