mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2024-11-16 03:32:33 +08:00
chore: better apply tcp keepalive to listeners
Some checks are pending
Trigger CMFA Update / trigger-CMFA-update (push) Waiting to run
Some checks are pending
Trigger CMFA Update / trigger-CMFA-update (push) Waiting to run
This commit is contained in:
parent
6c0383026e
commit
af73211231
|
@ -3,6 +3,9 @@ package inbound
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/metacubex/mihomo/component/keepalive"
|
||||||
|
|
||||||
"github.com/metacubex/tfo-go"
|
"github.com/metacubex/tfo-go"
|
||||||
)
|
)
|
||||||
|
@ -11,28 +14,47 @@ var (
|
||||||
lc = tfo.ListenConfig{
|
lc = tfo.ListenConfig{
|
||||||
DisableTFO: true,
|
DisableTFO: true,
|
||||||
}
|
}
|
||||||
|
mutex sync.RWMutex
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetTfo(open bool) {
|
func SetTfo(open bool) {
|
||||||
|
mutex.Lock()
|
||||||
|
defer mutex.Unlock()
|
||||||
lc.DisableTFO = !open
|
lc.DisableTFO = !open
|
||||||
}
|
}
|
||||||
|
|
||||||
func Tfo() bool {
|
func Tfo() bool {
|
||||||
|
mutex.RLock()
|
||||||
|
defer mutex.RUnlock()
|
||||||
return !lc.DisableTFO
|
return !lc.DisableTFO
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetMPTCP(open bool) {
|
func SetMPTCP(open bool) {
|
||||||
|
mutex.Lock()
|
||||||
|
defer mutex.Unlock()
|
||||||
setMultiPathTCP(&lc.ListenConfig, open)
|
setMultiPathTCP(&lc.ListenConfig, open)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MPTCP() bool {
|
func MPTCP() bool {
|
||||||
|
mutex.RLock()
|
||||||
|
defer mutex.RUnlock()
|
||||||
return getMultiPathTCP(&lc.ListenConfig)
|
return getMultiPathTCP(&lc.ListenConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListenContext(ctx context.Context, network, address string) (net.Listener, error) {
|
func ListenContext(ctx context.Context, network, address string) (net.Listener, error) {
|
||||||
|
mutex.RLock()
|
||||||
|
defer mutex.RUnlock()
|
||||||
return lc.Listen(ctx, network, address)
|
return lc.Listen(ctx, network, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Listen(network, address string) (net.Listener, error) {
|
func Listen(network, address string) (net.Listener, error) {
|
||||||
return ListenContext(context.Background(), network, address)
|
return ListenContext(context.Background(), network, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
keepalive.SetDisableKeepAliveCallback.Register(func(b bool) {
|
||||||
|
mutex.Lock()
|
||||||
|
defer mutex.Unlock()
|
||||||
|
keepalive.SetNetListenConfig(&lc.ListenConfig)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
N "github.com/metacubex/mihomo/common/net"
|
|
||||||
"github.com/metacubex/mihomo/component/dialer"
|
"github.com/metacubex/mihomo/component/dialer"
|
||||||
"github.com/metacubex/mihomo/component/loopback"
|
"github.com/metacubex/mihomo/component/loopback"
|
||||||
"github.com/metacubex/mihomo/component/resolver"
|
"github.com/metacubex/mihomo/component/resolver"
|
||||||
|
@ -38,7 +37,6 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
return d.loopBack.NewConn(NewConn(c, d)), nil
|
return d.loopBack.NewConn(NewConn(c, d)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,11 @@ import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
N "github.com/metacubex/mihomo/common/net"
|
|
||||||
"github.com/metacubex/mihomo/component/ca"
|
"github.com/metacubex/mihomo/component/ca"
|
||||||
"github.com/metacubex/mihomo/component/dialer"
|
"github.com/metacubex/mihomo/component/dialer"
|
||||||
"github.com/metacubex/mihomo/component/proxydialer"
|
"github.com/metacubex/mihomo/component/proxydialer"
|
||||||
|
@ -76,7 +74,6 @@ func (h *Http) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metad
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", h.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", h.addr, err)
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
|
|
||||||
defer func(c net.Conn) {
|
defer func(c net.Conn) {
|
||||||
safeConnClose(c, err)
|
safeConnClose(c, err)
|
||||||
|
|
|
@ -149,7 +149,6 @@ func (ss *ShadowSocks) DialContextWithDialer(ctx context.Context, dialer C.Diale
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
|
|
||||||
defer func(c net.Conn) {
|
defer func(c net.Conn) {
|
||||||
safeConnClose(c, err)
|
safeConnClose(c, err)
|
||||||
|
|
|
@ -80,7 +80,6 @@ func (ssr *ShadowSocksR) DialContextWithDialer(ctx context.Context, dialer C.Dia
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", ssr.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", ssr.addr, err)
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
|
|
||||||
defer func(c net.Conn) {
|
defer func(c net.Conn) {
|
||||||
safeConnClose(c, err)
|
safeConnClose(c, err)
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
N "github.com/metacubex/mihomo/common/net"
|
|
||||||
"github.com/metacubex/mihomo/common/structure"
|
"github.com/metacubex/mihomo/common/structure"
|
||||||
"github.com/metacubex/mihomo/component/dialer"
|
"github.com/metacubex/mihomo/component/dialer"
|
||||||
"github.com/metacubex/mihomo/component/proxydialer"
|
"github.com/metacubex/mihomo/component/proxydialer"
|
||||||
|
@ -94,7 +93,6 @@ func (s *Snell) DialContextWithDialer(ctx context.Context, dialer C.Dialer, meta
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", s.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", s.addr, err)
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
|
|
||||||
defer func(c net.Conn) {
|
defer func(c net.Conn) {
|
||||||
safeConnClose(c, err)
|
safeConnClose(c, err)
|
||||||
|
@ -122,7 +120,6 @@ func (s *Snell) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, met
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
c = streamConn(c, streamOption{s.psk, s.version, s.addr, s.obfsOption})
|
c = streamConn(c, streamOption{s.psk, s.version, s.addr, s.obfsOption})
|
||||||
|
|
||||||
err = snell.WriteUDPHeader(c, s.version)
|
err = snell.WriteUDPHeader(c, s.version)
|
||||||
|
@ -208,7 +205,6 @@ func NewSnell(option SnellOption) (*Snell, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
return streamConn(c, streamOption{psk, option.Version, addr, obfsOption}), nil
|
return streamConn(c, streamOption{psk, option.Version, addr, obfsOption}), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
N "github.com/metacubex/mihomo/common/net"
|
|
||||||
"github.com/metacubex/mihomo/component/ca"
|
"github.com/metacubex/mihomo/component/ca"
|
||||||
"github.com/metacubex/mihomo/component/dialer"
|
"github.com/metacubex/mihomo/component/dialer"
|
||||||
"github.com/metacubex/mihomo/component/proxydialer"
|
"github.com/metacubex/mihomo/component/proxydialer"
|
||||||
|
@ -82,7 +81,6 @@ func (ss *Socks5) DialContextWithDialer(ctx context.Context, dialer C.Dialer, me
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
|
|
||||||
defer func(c net.Conn) {
|
defer func(c net.Conn) {
|
||||||
safeConnClose(c, err)
|
safeConnClose(c, err)
|
||||||
|
@ -128,7 +126,6 @@ func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata,
|
||||||
safeConnClose(c, err)
|
safeConnClose(c, err)
|
||||||
}(c)
|
}(c)
|
||||||
|
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
var user *socks5.User
|
var user *socks5.User
|
||||||
if ss.user != "" {
|
if ss.user != "" {
|
||||||
user = &socks5.User{
|
user = &socks5.User{
|
||||||
|
|
|
@ -77,7 +77,6 @@ func (s *sshClient) connect(ctx context.Context, cDialer C.Dialer, addr string)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
|
|
||||||
defer func(c net.Conn) {
|
defer func(c net.Conn) {
|
||||||
safeConnClose(c, err)
|
safeConnClose(c, err)
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
N "github.com/metacubex/mihomo/common/net"
|
|
||||||
"github.com/metacubex/mihomo/component/ca"
|
"github.com/metacubex/mihomo/component/ca"
|
||||||
"github.com/metacubex/mihomo/component/dialer"
|
"github.com/metacubex/mihomo/component/dialer"
|
||||||
"github.com/metacubex/mihomo/component/proxydialer"
|
"github.com/metacubex/mihomo/component/proxydialer"
|
||||||
|
@ -154,7 +153,6 @@ func (t *Trojan) DialContextWithDialer(ctx context.Context, dialer C.Dialer, met
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
|
|
||||||
defer func(c net.Conn) {
|
defer func(c net.Conn) {
|
||||||
safeConnClose(c, err)
|
safeConnClose(c, err)
|
||||||
|
@ -212,7 +210,6 @@ func (t *Trojan) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, me
|
||||||
defer func(c net.Conn) {
|
defer func(c net.Conn) {
|
||||||
safeConnClose(c, err)
|
safeConnClose(c, err)
|
||||||
}(c)
|
}(c)
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
c, err = t.plainStream(ctx, c)
|
c, err = t.plainStream(ctx, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
||||||
|
@ -314,7 +311,6 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %s", t.addr, err.Error())
|
return nil, fmt.Errorf("%s connect error: %s", t.addr, err.Error())
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -262,7 +262,6 @@ func (v *Vless) DialContextWithDialer(ctx context.Context, dialer C.Dialer, meta
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
defer func(c net.Conn) {
|
defer func(c net.Conn) {
|
||||||
safeConnClose(c, err)
|
safeConnClose(c, err)
|
||||||
}(c)
|
}(c)
|
||||||
|
@ -327,7 +326,6 @@ func (v *Vless) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, met
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
defer func(c net.Conn) {
|
defer func(c net.Conn) {
|
||||||
safeConnClose(c, err)
|
safeConnClose(c, err)
|
||||||
}(c)
|
}(c)
|
||||||
|
@ -574,7 +572,6 @@ func NewVless(option VlessOption) (*Vless, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -312,7 +312,6 @@ func (v *Vmess) DialContextWithDialer(ctx context.Context, dialer C.Dialer, meta
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
defer func(c net.Conn) {
|
defer func(c net.Conn) {
|
||||||
safeConnClose(c, err)
|
safeConnClose(c, err)
|
||||||
}(c)
|
}(c)
|
||||||
|
@ -373,7 +372,6 @@ func (v *Vmess) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, met
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
defer func(c net.Conn) {
|
defer func(c net.Conn) {
|
||||||
safeConnClose(c, err)
|
safeConnClose(c, err)
|
||||||
}(c)
|
}(c)
|
||||||
|
@ -473,7 +471,6 @@ func NewVmess(option VmessOption) (*Vmess, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
package net
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"runtime"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
KeepAliveIdle = 0 * time.Second
|
|
||||||
KeepAliveInterval = 0 * time.Second
|
|
||||||
DisableKeepAlive = false
|
|
||||||
)
|
|
||||||
|
|
||||||
func TCPKeepAlive(c net.Conn) {
|
|
||||||
if tcp, ok := c.(*net.TCPConn); ok {
|
|
||||||
if runtime.GOOS == "android" || DisableKeepAlive {
|
|
||||||
_ = tcp.SetKeepAlive(false)
|
|
||||||
} else {
|
|
||||||
tcpKeepAlive(tcp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
//go:build !go1.23
|
|
||||||
|
|
||||||
package net
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
func tcpKeepAlive(tcp *net.TCPConn) {
|
|
||||||
_ = tcp.SetKeepAlive(true)
|
|
||||||
_ = tcp.SetKeepAlivePeriod(KeepAliveInterval)
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
//go:build go1.23
|
|
||||||
|
|
||||||
package net
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
func tcpKeepAlive(tcp *net.TCPConn) {
|
|
||||||
config := net.KeepAliveConfig{
|
|
||||||
Enable: true,
|
|
||||||
Idle: KeepAliveIdle,
|
|
||||||
Interval: KeepAliveInterval,
|
|
||||||
}
|
|
||||||
if !SupportTCPKeepAliveCount() {
|
|
||||||
// it's recommended to set both Idle and Interval to non-negative values in conjunction with a -1
|
|
||||||
// for Count on those old Windows if you intend to customize the TCP keep-alive settings.
|
|
||||||
config.Count = -1
|
|
||||||
}
|
|
||||||
_ = tcp.SetKeepAliveConfig(config)
|
|
||||||
}
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/metacubex/mihomo/component/keepalive"
|
||||||
"github.com/metacubex/mihomo/component/resolver"
|
"github.com/metacubex/mihomo/component/resolver"
|
||||||
"github.com/metacubex/mihomo/log"
|
"github.com/metacubex/mihomo/log"
|
||||||
)
|
)
|
||||||
|
@ -144,6 +145,7 @@ func dialContext(ctx context.Context, network string, destination netip.Addr, po
|
||||||
}
|
}
|
||||||
|
|
||||||
dialer := netDialer.(*net.Dialer)
|
dialer := netDialer.(*net.Dialer)
|
||||||
|
keepalive.SetNetDialer(dialer)
|
||||||
if opt.mpTcp {
|
if opt.mpTcp {
|
||||||
setMultiPathTCP(dialer)
|
setMultiPathTCP(dialer)
|
||||||
}
|
}
|
||||||
|
|
65
component/keepalive/tcp_keepalive.go
Normal file
65
component/keepalive/tcp_keepalive.go
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
package keepalive
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/metacubex/mihomo/common/atomic"
|
||||||
|
"github.com/metacubex/mihomo/common/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
keepAliveIdle = atomic.NewTypedValue[time.Duration](0 * time.Second)
|
||||||
|
keepAliveInterval = atomic.NewTypedValue[time.Duration](0 * time.Second)
|
||||||
|
disableKeepAlive = atomic.NewBool(false)
|
||||||
|
|
||||||
|
SetDisableKeepAliveCallback = utils.NewCallback[bool]()
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetKeepAliveIdle(t time.Duration) {
|
||||||
|
keepAliveIdle.Store(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetKeepAliveInterval(t time.Duration) {
|
||||||
|
keepAliveInterval.Store(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func KeepAliveIdle() time.Duration {
|
||||||
|
return keepAliveIdle.Load()
|
||||||
|
}
|
||||||
|
|
||||||
|
func KeepAliveInterval() time.Duration {
|
||||||
|
return keepAliveInterval.Load()
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetDisableKeepAlive(disable bool) {
|
||||||
|
if runtime.GOOS == "android" {
|
||||||
|
setDisableKeepAlive(false)
|
||||||
|
} else {
|
||||||
|
setDisableKeepAlive(disable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setDisableKeepAlive(disable bool) {
|
||||||
|
disableKeepAlive.Store(disable)
|
||||||
|
SetDisableKeepAliveCallback.Emit(disable)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DisableKeepAlive() bool {
|
||||||
|
return disableKeepAlive.Load()
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetNetDialer(dialer *net.Dialer) {
|
||||||
|
setNetDialer(dialer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetNetListenConfig(lc *net.ListenConfig) {
|
||||||
|
setNetListenConfig(lc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TCPKeepAlive(c net.Conn) {
|
||||||
|
if tcp, ok := c.(*net.TCPConn); ok && tcp != nil {
|
||||||
|
tcpKeepAlive(tcp)
|
||||||
|
}
|
||||||
|
}
|
30
component/keepalive/tcp_keepalive_go122.go
Normal file
30
component/keepalive/tcp_keepalive_go122.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
//go:build !go1.23
|
||||||
|
|
||||||
|
package keepalive
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
func tcpKeepAlive(tcp *net.TCPConn) {
|
||||||
|
if DisableKeepAlive() {
|
||||||
|
_ = tcp.SetKeepAlive(false)
|
||||||
|
} else {
|
||||||
|
_ = tcp.SetKeepAlive(true)
|
||||||
|
_ = tcp.SetKeepAlivePeriod(KeepAliveInterval.Load())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setNetDialer(dialer *net.Dialer) {
|
||||||
|
if DisableKeepAlive() {
|
||||||
|
dialer.KeepAlive = -1 // If negative, keep-alive probes are disabled.
|
||||||
|
} else {
|
||||||
|
dialer.KeepAlive = KeepAliveInterval()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setNetListenConfig(lc *net.ListenConfig) {
|
||||||
|
if DisableKeepAlive() {
|
||||||
|
lc.KeepAlive = -1 // If negative, keep-alive probes are disabled.
|
||||||
|
} else {
|
||||||
|
lc.KeepAlive = KeepAliveInterval()
|
||||||
|
}
|
||||||
|
}
|
45
component/keepalive/tcp_keepalive_go123.go
Normal file
45
component/keepalive/tcp_keepalive_go123.go
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
//go:build go1.23
|
||||||
|
|
||||||
|
package keepalive
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
func keepAliveConfig() net.KeepAliveConfig {
|
||||||
|
config := net.KeepAliveConfig{
|
||||||
|
Enable: true,
|
||||||
|
Idle: KeepAliveIdle(),
|
||||||
|
Interval: KeepAliveInterval(),
|
||||||
|
}
|
||||||
|
if !SupportTCPKeepAliveCount() {
|
||||||
|
// it's recommended to set both Idle and Interval to non-negative values in conjunction with a -1
|
||||||
|
// for Count on those old Windows if you intend to customize the TCP keep-alive settings.
|
||||||
|
config.Count = -1
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func tcpKeepAlive(tcp *net.TCPConn) {
|
||||||
|
if DisableKeepAlive() {
|
||||||
|
_ = tcp.SetKeepAlive(false)
|
||||||
|
} else {
|
||||||
|
_ = tcp.SetKeepAliveConfig(keepAliveConfig())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setNetDialer(dialer *net.Dialer) {
|
||||||
|
if DisableKeepAlive() {
|
||||||
|
dialer.KeepAlive = -1 // If negative, keep-alive probes are disabled.
|
||||||
|
dialer.KeepAliveConfig.Enable = false
|
||||||
|
} else {
|
||||||
|
dialer.KeepAliveConfig = keepAliveConfig()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setNetListenConfig(lc *net.ListenConfig) {
|
||||||
|
if DisableKeepAlive() {
|
||||||
|
lc.KeepAlive = -1 // If negative, keep-alive probes are disabled.
|
||||||
|
lc.KeepAliveConfig.Enable = false
|
||||||
|
} else {
|
||||||
|
lc.KeepAliveConfig = keepAliveConfig()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
//go:build go1.23 && unix
|
//go:build go1.23 && unix
|
||||||
|
|
||||||
package net
|
package keepalive
|
||||||
|
|
||||||
func SupportTCPKeepAliveIdle() bool {
|
func SupportTCPKeepAliveIdle() bool {
|
||||||
return true
|
return true
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// copy and modify from golang1.23's internal/syscall/windows/version_windows.go
|
// copy and modify from golang1.23's internal/syscall/windows/version_windows.go
|
||||||
|
|
||||||
package net
|
package keepalive
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
|
@ -15,13 +15,13 @@ import (
|
||||||
"github.com/metacubex/mihomo/adapter/outbound"
|
"github.com/metacubex/mihomo/adapter/outbound"
|
||||||
"github.com/metacubex/mihomo/adapter/outboundgroup"
|
"github.com/metacubex/mihomo/adapter/outboundgroup"
|
||||||
"github.com/metacubex/mihomo/adapter/provider"
|
"github.com/metacubex/mihomo/adapter/provider"
|
||||||
N "github.com/metacubex/mihomo/common/net"
|
|
||||||
"github.com/metacubex/mihomo/common/utils"
|
"github.com/metacubex/mihomo/common/utils"
|
||||||
"github.com/metacubex/mihomo/component/auth"
|
"github.com/metacubex/mihomo/component/auth"
|
||||||
"github.com/metacubex/mihomo/component/cidr"
|
"github.com/metacubex/mihomo/component/cidr"
|
||||||
"github.com/metacubex/mihomo/component/fakeip"
|
"github.com/metacubex/mihomo/component/fakeip"
|
||||||
"github.com/metacubex/mihomo/component/geodata"
|
"github.com/metacubex/mihomo/component/geodata"
|
||||||
mihomoHttp "github.com/metacubex/mihomo/component/http"
|
mihomoHttp "github.com/metacubex/mihomo/component/http"
|
||||||
|
"github.com/metacubex/mihomo/component/keepalive"
|
||||||
P "github.com/metacubex/mihomo/component/process"
|
P "github.com/metacubex/mihomo/component/process"
|
||||||
"github.com/metacubex/mihomo/component/resolver"
|
"github.com/metacubex/mihomo/component/resolver"
|
||||||
"github.com/metacubex/mihomo/component/resource"
|
"github.com/metacubex/mihomo/component/resource"
|
||||||
|
@ -697,12 +697,12 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
|
||||||
resource.SetETag(cfg.ETagSupport)
|
resource.SetETag(cfg.ETagSupport)
|
||||||
|
|
||||||
if cfg.KeepAliveIdle != 0 {
|
if cfg.KeepAliveIdle != 0 {
|
||||||
N.KeepAliveIdle = time.Duration(cfg.KeepAliveIdle) * time.Second
|
keepalive.SetKeepAliveIdle(time.Duration(cfg.KeepAliveIdle) * time.Second)
|
||||||
}
|
}
|
||||||
if cfg.KeepAliveInterval != 0 {
|
if cfg.KeepAliveInterval != 0 {
|
||||||
N.KeepAliveInterval = time.Duration(cfg.KeepAliveInterval) * time.Second
|
keepalive.SetKeepAliveInterval(time.Duration(cfg.KeepAliveInterval) * time.Second)
|
||||||
}
|
}
|
||||||
N.DisableKeepAlive = cfg.DisableKeepAlive
|
keepalive.SetDisableKeepAlive(cfg.DisableKeepAlive)
|
||||||
|
|
||||||
// checkout externalUI exist
|
// checkout externalUI exist
|
||||||
if cfg.ExternalUI != "" {
|
if cfg.ExternalUI != "" {
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/metacubex/mihomo/adapter/inbound"
|
"github.com/metacubex/mihomo/adapter/inbound"
|
||||||
N "github.com/metacubex/mihomo/common/net"
|
|
||||||
"github.com/metacubex/mihomo/component/auth"
|
"github.com/metacubex/mihomo/component/auth"
|
||||||
C "github.com/metacubex/mihomo/constant"
|
C "github.com/metacubex/mihomo/constant"
|
||||||
authStore "github.com/metacubex/mihomo/listener/auth"
|
authStore "github.com/metacubex/mihomo/listener/auth"
|
||||||
|
@ -55,8 +54,8 @@ func NewWithAuthenticator(addr string, tunnel C.Tunnel, getAuth func() auth.Auth
|
||||||
inbound.WithSpecialRules(""),
|
inbound.WithSpecialRules(""),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
l, err := inbound.Listen("tcp", addr)
|
|
||||||
|
|
||||||
|
l, err := inbound.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -74,7 +73,6 @@ func NewWithAuthenticator(addr string, tunnel C.Tunnel, getAuth func() auth.Auth
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(conn)
|
|
||||||
|
|
||||||
getAuth := getAuth
|
getAuth := getAuth
|
||||||
if isDefault { // only apply on default listener
|
if isDefault { // only apply on default listener
|
||||||
|
|
|
@ -49,6 +49,7 @@ func NewWithAuthenticator(addr string, tunnel C.Tunnel, getAuth func() auth.Auth
|
||||||
inbound.WithSpecialRules(""),
|
inbound.WithSpecialRules(""),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
l, err := inbound.Listen("tcp", addr)
|
l, err := inbound.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -85,8 +86,6 @@ func NewWithAuthenticator(addr string, tunnel C.Tunnel, getAuth func() auth.Auth
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleConn(conn net.Conn, tunnel C.Tunnel, getAuth func() auth.Authenticator, additions ...inbound.Addition) {
|
func handleConn(conn net.Conn, tunnel C.Tunnel, getAuth func() auth.Authenticator, additions ...inbound.Addition) {
|
||||||
N.TCPKeepAlive(conn)
|
|
||||||
|
|
||||||
bufConn := N.NewBufferedConn(conn)
|
bufConn := N.NewBufferedConn(conn)
|
||||||
head, err := bufConn.Peek(1)
|
head, err := bufConn.Peek(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/metacubex/mihomo/adapter/inbound"
|
"github.com/metacubex/mihomo/adapter/inbound"
|
||||||
N "github.com/metacubex/mihomo/common/net"
|
"github.com/metacubex/mihomo/component/keepalive"
|
||||||
C "github.com/metacubex/mihomo/constant"
|
C "github.com/metacubex/mihomo/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,10 +37,12 @@ func New(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener
|
||||||
inbound.WithSpecialRules(""),
|
inbound.WithSpecialRules(""),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
l, err := net.Listen("tcp", addr)
|
l, err := net.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
rl := &Listener{
|
rl := &Listener{
|
||||||
listener: l,
|
listener: l,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
|
@ -68,6 +70,6 @@ func handleRedir(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition)
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(conn)
|
keepalive.TCPKeepAlive(conn)
|
||||||
tunnel.HandleTCPConn(inbound.NewSocket(target, conn, C.REDIR, additions...))
|
tunnel.HandleTCPConn(inbound.NewSocket(target, conn, C.REDIR, additions...))
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,6 @@ func New(config LC.ShadowsocksServer, tunnel C.Tunnel, additions ...inbound.Addi
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
go sl.HandleConn(c, tunnel, additions...)
|
go sl.HandleConn(c, tunnel, additions...)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/metacubex/mihomo/adapter/inbound"
|
"github.com/metacubex/mihomo/adapter/inbound"
|
||||||
N "github.com/metacubex/mihomo/common/net"
|
|
||||||
"github.com/metacubex/mihomo/common/sockopt"
|
"github.com/metacubex/mihomo/common/sockopt"
|
||||||
C "github.com/metacubex/mihomo/constant"
|
C "github.com/metacubex/mihomo/constant"
|
||||||
LC "github.com/metacubex/mihomo/listener/config"
|
LC "github.com/metacubex/mihomo/listener/config"
|
||||||
|
@ -153,7 +152,6 @@ func New(config LC.ShadowsocksServer, tunnel C.Tunnel, additions ...inbound.Addi
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
|
|
||||||
go sl.HandleConn(c, tunnel)
|
go sl.HandleConn(c, tunnel)
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,6 @@ func New(config LC.VmessServer, tunnel C.Tunnel, additions ...inbound.Addition)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
N.TCPKeepAlive(c)
|
|
||||||
|
|
||||||
go sl.HandleConn(c, tunnel)
|
go sl.HandleConn(c, tunnel)
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ func NewWithAuthenticator(addr string, tunnel C.Tunnel, getAuth func() auth.Auth
|
||||||
inbound.WithSpecialRules(""),
|
inbound.WithSpecialRules(""),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
l, err := inbound.Listen("tcp", addr)
|
l, err := inbound.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -84,7 +85,6 @@ func NewWithAuthenticator(addr string, tunnel C.Tunnel, getAuth func() auth.Auth
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleSocks(conn net.Conn, tunnel C.Tunnel, getAuth func() auth.Authenticator, additions ...inbound.Addition) {
|
func handleSocks(conn net.Conn, tunnel C.Tunnel, getAuth func() auth.Authenticator, additions ...inbound.Addition) {
|
||||||
N.TCPKeepAlive(conn)
|
|
||||||
bufConn := N.NewBufferedConn(conn)
|
bufConn := N.NewBufferedConn(conn)
|
||||||
head, err := bufConn.Peek(1)
|
head, err := bufConn.Peek(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/metacubex/mihomo/adapter/inbound"
|
"github.com/metacubex/mihomo/adapter/inbound"
|
||||||
N "github.com/metacubex/mihomo/common/net"
|
"github.com/metacubex/mihomo/component/keepalive"
|
||||||
C "github.com/metacubex/mihomo/constant"
|
C "github.com/metacubex/mihomo/constant"
|
||||||
"github.com/metacubex/mihomo/transport/socks5"
|
"github.com/metacubex/mihomo/transport/socks5"
|
||||||
)
|
)
|
||||||
|
@ -33,7 +33,7 @@ func (l *Listener) Close() error {
|
||||||
|
|
||||||
func (l *Listener) handleTProxy(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) {
|
func (l *Listener) handleTProxy(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) {
|
||||||
target := socks5.ParseAddrToSocksAddr(conn.LocalAddr())
|
target := socks5.ParseAddrToSocksAddr(conn.LocalAddr())
|
||||||
N.TCPKeepAlive(conn)
|
keepalive.TCPKeepAlive(conn)
|
||||||
// TProxy's conn.LocalAddr() is target address, so we set from l.listener
|
// TProxy's conn.LocalAddr() is target address, so we set from l.listener
|
||||||
additions = append([]inbound.Addition{inbound.WithInAddr(l.listener.Addr())}, additions...)
|
additions = append([]inbound.Addition{inbound.WithInAddr(l.listener.Addr())}, additions...)
|
||||||
tunnel.HandleTCPConn(inbound.NewSocket(target, conn, C.TPROXY, additions...))
|
tunnel.HandleTCPConn(inbound.NewSocket(target, conn, C.TPROXY, additions...))
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/metacubex/mihomo/adapter/inbound"
|
"github.com/metacubex/mihomo/adapter/inbound"
|
||||||
N "github.com/metacubex/mihomo/common/net"
|
|
||||||
C "github.com/metacubex/mihomo/constant"
|
C "github.com/metacubex/mihomo/constant"
|
||||||
"github.com/metacubex/mihomo/transport/socks5"
|
"github.com/metacubex/mihomo/transport/socks5"
|
||||||
)
|
)
|
||||||
|
@ -35,7 +34,6 @@ func (l *Listener) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Listener) handleTCP(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) {
|
func (l *Listener) handleTCP(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) {
|
||||||
N.TCPKeepAlive(conn)
|
|
||||||
tunnel.HandleTCPConn(inbound.NewSocket(l.target, conn, C.TUNNEL, additions...))
|
tunnel.HandleTCPConn(inbound.NewSocket(l.target, conn, C.TUNNEL, additions...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user