feat: configurable TCPKeepAlive interval
This commit is contained in:
parent
d79c13064e
commit
73fa79bf3f
23 changed files with 62 additions and 48 deletions
|
@ -3,6 +3,8 @@ package outbound
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
"github.com/Dreamacro/clash/component/dialer"
|
||||
"github.com/Dreamacro/clash/component/resolver"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
|
@ -24,7 +26,7 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
return NewConn(c, d), nil
|
||||
}
|
||||
|
||||
|
|
|
@ -7,11 +7,13 @@ import (
|
|||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
"github.com/Dreamacro/clash/component/dialer"
|
||||
"github.com/Dreamacro/clash/component/proxydialer"
|
||||
tlsC "github.com/Dreamacro/clash/component/tls"
|
||||
|
@ -74,7 +76,7 @@ func (h *Http) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metad
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", h.addr, err)
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
|
||||
defer func(c net.Conn) {
|
||||
safeConnClose(c, err)
|
||||
|
|
|
@ -146,7 +146,7 @@ func (ss *ShadowSocks) DialContextWithDialer(ctx context.Context, dialer C.Diale
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
|
||||
defer func(c net.Conn) {
|
||||
safeConnClose(c, err)
|
||||
|
|
|
@ -80,7 +80,7 @@ func (ssr *ShadowSocksR) DialContextWithDialer(ctx context.Context, dialer C.Dia
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", ssr.addr, err)
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
|
||||
defer func(c net.Conn) {
|
||||
safeConnClose(c, err)
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"net"
|
||||
"strconv"
|
||||
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
"github.com/Dreamacro/clash/common/structure"
|
||||
"github.com/Dreamacro/clash/component/dialer"
|
||||
"github.com/Dreamacro/clash/component/proxydialer"
|
||||
|
@ -93,7 +94,7 @@ func (s *Snell) DialContextWithDialer(ctx context.Context, dialer C.Dialer, meta
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", s.addr, err)
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
|
||||
defer func(c net.Conn) {
|
||||
safeConnClose(c, err)
|
||||
|
@ -121,7 +122,7 @@ func (s *Snell) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, met
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
c = streamConn(c, streamOption{s.psk, s.version, s.addr, s.obfsOption})
|
||||
|
||||
err = snell.WriteUDPHeader(c, s.version)
|
||||
|
@ -207,7 +208,7 @@ func NewSnell(option SnellOption) (*Snell, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
return streamConn(c, streamOption{psk, option.Version, addr, obfsOption}), nil
|
||||
})
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"net"
|
||||
"strconv"
|
||||
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
"github.com/Dreamacro/clash/component/dialer"
|
||||
"github.com/Dreamacro/clash/component/proxydialer"
|
||||
tlsC "github.com/Dreamacro/clash/component/tls"
|
||||
|
@ -80,7 +81,7 @@ func (ss *Socks5) DialContextWithDialer(ctx context.Context, dialer C.Dialer, me
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
|
||||
defer func(c net.Conn) {
|
||||
safeConnClose(c, err)
|
||||
|
@ -126,7 +127,7 @@ func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata,
|
|||
safeConnClose(c, err)
|
||||
}(c)
|
||||
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
var user *socks5.User
|
||||
if ss.user != "" {
|
||||
user = &socks5.User{
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
"github.com/Dreamacro/clash/component/dialer"
|
||||
"github.com/Dreamacro/clash/component/proxydialer"
|
||||
tlsC "github.com/Dreamacro/clash/component/tls"
|
||||
|
@ -131,7 +132,7 @@ func (t *Trojan) DialContextWithDialer(ctx context.Context, dialer C.Dialer, met
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
|
||||
defer func(c net.Conn) {
|
||||
safeConnClose(c, err)
|
||||
|
@ -184,7 +185,7 @@ func (t *Trojan) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, me
|
|||
defer func(c net.Conn) {
|
||||
safeConnClose(c, err)
|
||||
}(c)
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
c, err = t.plainStream(ctx, c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
||||
|
@ -268,7 +269,7 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %s", t.addr, err.Error())
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"net"
|
||||
"net/netip"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Dreamacro/clash/component/resolver"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
|
@ -19,13 +18,6 @@ var (
|
|||
once sync.Once
|
||||
)
|
||||
|
||||
func tcpKeepAlive(c net.Conn) {
|
||||
if tcp, ok := c.(*net.TCPConn); ok {
|
||||
_ = tcp.SetKeepAlive(true)
|
||||
_ = tcp.SetKeepAlivePeriod(30 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func getClientSessionCache() tls.ClientSessionCache {
|
||||
once.Do(func() {
|
||||
globalClientSessionCache = tls.NewLRUClientSessionCache(128)
|
||||
|
|
|
@ -263,7 +263,7 @@ func (v *Vless) DialContextWithDialer(ctx context.Context, dialer C.Dialer, meta
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
defer func(c net.Conn) {
|
||||
safeConnClose(c, err)
|
||||
}(c)
|
||||
|
@ -328,7 +328,7 @@ func (v *Vless) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, met
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
defer func(c net.Conn) {
|
||||
safeConnClose(c, err)
|
||||
}(c)
|
||||
|
@ -578,7 +578,7 @@ func NewVless(option VlessOption) (*Vless, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -308,7 +308,7 @@ func (v *Vmess) DialContextWithDialer(ctx context.Context, dialer C.Dialer, meta
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
defer func(c net.Conn) {
|
||||
safeConnClose(c, err)
|
||||
}(c)
|
||||
|
@ -369,7 +369,7 @@ func (v *Vmess) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, met
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
defer func(c net.Conn) {
|
||||
safeConnClose(c, err)
|
||||
}(c)
|
||||
|
@ -469,7 +469,7 @@ func NewVmess(option VmessOption) (*Vmess, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
N.TCPKeepAlive(c)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,5 @@
|
|||
package outboundgroup
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
func tcpKeepAlive(c net.Conn) {
|
||||
if tcp, ok := c.(*net.TCPConn); ok {
|
||||
_ = tcp.SetKeepAlive(true)
|
||||
_ = tcp.SetKeepAlivePeriod(30 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
type SelectAble interface {
|
||||
Set(string) error
|
||||
ForceSet(name string)
|
||||
|
|
|
@ -4,8 +4,11 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var KeepAliveInterval time.Duration
|
||||
|
||||
func SplitNetworkType(s string) (string, string, error) {
|
||||
var (
|
||||
shecme string
|
||||
|
@ -44,3 +47,10 @@ func SplitHostPort(s string) (host, port string, hasPort bool, err error) {
|
|||
host, port, err = net.SplitHostPort(temp)
|
||||
return
|
||||
}
|
||||
|
||||
func TCPKeepAlive(c net.Conn) {
|
||||
if tcp, ok := c.(*net.TCPConn); ok {
|
||||
_ = tcp.SetKeepAlive(true)
|
||||
_ = tcp.SetKeepAlivePeriod(KeepAliveInterval * time.Second)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/Dreamacro/clash/adapter/outbound"
|
||||
"github.com/Dreamacro/clash/adapter/outboundgroup"
|
||||
"github.com/Dreamacro/clash/adapter/provider"
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
"github.com/Dreamacro/clash/common/utils"
|
||||
"github.com/Dreamacro/clash/component/auth"
|
||||
"github.com/Dreamacro/clash/component/dialer"
|
||||
|
@ -59,6 +60,7 @@ type General struct {
|
|||
Sniffing bool `json:"sniffing"`
|
||||
EBpf EBpf `json:"-"`
|
||||
GlobalClientFingerprint string `json:"global-client-fingerprint"`
|
||||
KeepAliveInterval int `json:"keep-alive-interval"`
|
||||
}
|
||||
|
||||
// Inbound config
|
||||
|
@ -280,6 +282,7 @@ type RawConfig struct {
|
|||
TCPConcurrent bool `yaml:"tcp-concurrent" json:"tcp-concurrent"`
|
||||
FindProcessMode P.FindProcessMode `yaml:"find-process-mode" json:"find-process-mode"`
|
||||
GlobalClientFingerprint string `yaml:"global-client-fingerprint"`
|
||||
KeepAliveInterval int `yaml:"keep-alive-interval"`
|
||||
|
||||
Sniffer RawSniffer `yaml:"sniffer"`
|
||||
ProxyProvider map[string]map[string]any `yaml:"proxy-providers"`
|
||||
|
@ -559,6 +562,11 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
|
|||
C.GeoSiteUrl = cfg.GeoXUrl.GeoSite
|
||||
C.MmdbUrl = cfg.GeoXUrl.Mmdb
|
||||
C.GeodataMode = cfg.GeodataMode
|
||||
if cfg.KeepAliveInterval == 0 {
|
||||
cfg.KeepAliveInterval = 30
|
||||
}
|
||||
N.KeepAliveInterval = time.Duration(cfg.KeepAliveInterval) * time.Second
|
||||
log.Infoln("Keep Alive Interval set %+v", N.KeepAliveInterval)
|
||||
// checkout externalUI exist
|
||||
if externalUI != "" {
|
||||
externalUI = C.Path.Resolve(externalUI)
|
||||
|
@ -600,6 +608,7 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
|
|||
FindProcessMode: cfg.FindProcessMode,
|
||||
EBpf: cfg.EBpf,
|
||||
GlobalClientFingerprint: cfg.GlobalClientFingerprint,
|
||||
KeepAliveInterval: cfg.KeepAliveInterval,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,8 @@ external-ui: /path/to/ui/folder # 配置 WEB UI 目录,使用 http://{{externa
|
|||
# Utls is currently support TLS transport in TCP/grpc/WS/HTTP for VLESS/Vmess and trojan.
|
||||
global-client-fingerprint: chrome
|
||||
|
||||
keep-alive-interval: 30
|
||||
|
||||
# routing-mark:6666 # 配置 fwmark 仅用于 Linux
|
||||
experimental:
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net/netip"
|
||||
|
||||
"github.com/Dreamacro/clash/adapter/inbound"
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
"github.com/Dreamacro/clash/transport/socks5"
|
||||
|
@ -55,7 +56,7 @@ func (l *Listener) handleRedir(conn net.Conn, in chan<- C.ConnContext) {
|
|||
return
|
||||
}
|
||||
|
||||
_ = conn.(*net.TCPConn).SetKeepAlive(true)
|
||||
N.TCPKeepAlive(conn)
|
||||
|
||||
in <- inbound.NewSocket(target, conn, C.REDIR, l.additions...)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package mixed
|
||||
|
||||
import (
|
||||
"github.com/Dreamacro/clash/adapter/inbound"
|
||||
"net"
|
||||
|
||||
"github.com/Dreamacro/clash/adapter/inbound"
|
||||
"github.com/Dreamacro/clash/common/cache"
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
|
@ -70,7 +70,7 @@ func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*
|
|||
}
|
||||
|
||||
func handleConn(conn net.Conn, in chan<- C.ConnContext, cache *cache.LruCache[string, bool], additions ...inbound.Addition) {
|
||||
conn.(*net.TCPConn).SetKeepAlive(true)
|
||||
N.TCPKeepAlive(conn)
|
||||
|
||||
bufConn := N.NewBufferedConn(conn)
|
||||
head, err := bufConn.Peek(1)
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"net"
|
||||
|
||||
"github.com/Dreamacro/clash/adapter/inbound"
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
)
|
||||
|
||||
|
@ -66,6 +67,6 @@ func handleRedir(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Ad
|
|||
conn.Close()
|
||||
return
|
||||
}
|
||||
conn.(*net.TCPConn).SetKeepAlive(true)
|
||||
N.TCPKeepAlive(conn)
|
||||
in <- inbound.NewSocket(target, conn, C.REDIR, additions...)
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ func New(config LC.ShadowsocksServer, tcpIn chan<- C.ConnContext, udpIn chan<- C
|
|||
}
|
||||
continue
|
||||
}
|
||||
_ = c.(*net.TCPConn).SetKeepAlive(true)
|
||||
N.TCPKeepAlive(c)
|
||||
go sl.HandleConn(c, tcpIn)
|
||||
}
|
||||
}()
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/Dreamacro/clash/adapter/inbound"
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
"github.com/Dreamacro/clash/common/sockopt"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
LC "github.com/Dreamacro/clash/listener/config"
|
||||
|
@ -145,7 +146,7 @@ func New(config LC.ShadowsocksServer, tcpIn chan<- C.ConnContext, udpIn chan<- C
|
|||
}
|
||||
continue
|
||||
}
|
||||
_ = c.(*net.TCPConn).SetKeepAlive(true)
|
||||
N.TCPKeepAlive(c)
|
||||
|
||||
go sl.HandleConn(c, tcpIn)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/Dreamacro/clash/adapter/inbound"
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
LC "github.com/Dreamacro/clash/listener/config"
|
||||
"github.com/Dreamacro/clash/listener/sing"
|
||||
|
@ -84,7 +85,7 @@ func New(config LC.VmessServer, tcpIn chan<- C.ConnContext, udpIn chan<- C.Packe
|
|||
}
|
||||
continue
|
||||
}
|
||||
_ = c.(*net.TCPConn).SetKeepAlive(true)
|
||||
N.TCPKeepAlive(c)
|
||||
|
||||
go sl.HandleConn(c, tcpIn)
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*
|
|||
}
|
||||
|
||||
func handleSocks(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) {
|
||||
conn.(*net.TCPConn).SetKeepAlive(true)
|
||||
N.TCPKeepAlive(conn)
|
||||
bufConn := N.NewBufferedConn(conn)
|
||||
head, err := bufConn.Peek(1)
|
||||
if err != nil {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"net"
|
||||
|
||||
"github.com/Dreamacro/clash/adapter/inbound"
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/transport/socks5"
|
||||
)
|
||||
|
@ -32,7 +33,7 @@ func (l *Listener) Close() error {
|
|||
|
||||
func (l *Listener) handleTProxy(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) {
|
||||
target := socks5.ParseAddrToSocksAddr(conn.LocalAddr())
|
||||
conn.(*net.TCPConn).SetKeepAlive(true)
|
||||
N.TCPKeepAlive(conn)
|
||||
in <- inbound.NewSocket(target, conn, C.TPROXY, additions...)
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net"
|
||||
|
||||
"github.com/Dreamacro/clash/adapter/inbound"
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/transport/socks5"
|
||||
)
|
||||
|
@ -34,7 +35,7 @@ func (l *Listener) Close() error {
|
|||
}
|
||||
|
||||
func (l *Listener) handleTCP(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) {
|
||||
conn.(*net.TCPConn).SetKeepAlive(true)
|
||||
N.TCPKeepAlive(conn)
|
||||
ctx := inbound.NewSocket(l.target, conn, C.TUNNEL, additions...)
|
||||
ctx.Metadata().SpecialProxy = l.proxy
|
||||
in <- ctx
|
||||
|
|
Loading…
Reference in a new issue