Improve network reset
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
type Searcher interface {
|
||||
FindProcessInfo(ctx context.Context, network string, source netip.AddrPort, destination netip.AddrPort) (*adapter.ConnectionOwner, error)
|
||||
ResetCache()
|
||||
Close() error
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@ func NewSearcher(config Config) (Searcher, error) {
|
||||
return &androidSearcher{config.PackageManager}, nil
|
||||
}
|
||||
|
||||
func (s *androidSearcher) ResetCache() {
|
||||
}
|
||||
|
||||
func (s *androidSearcher) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -20,6 +20,10 @@ func NewSearcher(_ Config) (Searcher, error) {
|
||||
return &darwinSearcher{}, nil
|
||||
}
|
||||
|
||||
func (d *darwinSearcher) ResetCache() {
|
||||
sharedDarwinConnectionFinder.resetCache()
|
||||
}
|
||||
|
||||
func (d *darwinSearcher) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -119,6 +119,12 @@ func (f *darwinConnectionFinder) find(network string, source netip.AddrPort, des
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
func (f *darwinConnectionFinder) resetCache() {
|
||||
f.access.Lock()
|
||||
defer f.access.Unlock()
|
||||
clear(f.snapshots)
|
||||
}
|
||||
|
||||
func (f *darwinConnectionFinder) loadSnapshot(network string, forceRefresh bool) (darwinSnapshot, bool, error) {
|
||||
f.access.Lock()
|
||||
defer f.access.Unlock()
|
||||
|
||||
@@ -35,6 +35,10 @@ func NewSearcher(config Config) (Searcher, error) {
|
||||
return searcher, nil
|
||||
}
|
||||
|
||||
func (s *linuxSearcher) ResetCache() {
|
||||
s.processPathCache.cache.Purge()
|
||||
}
|
||||
|
||||
func (s *linuxSearcher) Close() error {
|
||||
var errs []error
|
||||
for _, conn := range s.diagConns {
|
||||
|
||||
@@ -28,6 +28,9 @@ func initWin32API() error {
|
||||
return winiphlpapi.LoadExtendedTable()
|
||||
}
|
||||
|
||||
func (s *windowsSearcher) ResetCache() {
|
||||
}
|
||||
|
||||
func (s *windowsSearcher) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
+20
-6
@@ -10,6 +10,7 @@ import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
@@ -45,6 +46,8 @@ type HTTPSTransport struct {
|
||||
dialer N.Dialer
|
||||
destination *url.URL
|
||||
headers http.Header
|
||||
serverAddr M.Socksaddr
|
||||
fallback *atomic.Bool
|
||||
transportAccess sync.Mutex
|
||||
transport *HTTPSTransportWrapper
|
||||
transportResetAt time.Time
|
||||
@@ -123,13 +126,20 @@ func NewHTTPSRaw(
|
||||
if tlsConfig != nil {
|
||||
dialer = tls.NewDialer(dialer, tlsConfig)
|
||||
}
|
||||
fallback := new(atomic.Bool)
|
||||
if destination.Scheme == "http" {
|
||||
// plain HTTP DoH used by Tailscale
|
||||
fallback.Store(true)
|
||||
}
|
||||
return &HTTPSTransport{
|
||||
TransportAdapter: adapter,
|
||||
logger: logger,
|
||||
dialer: dialer,
|
||||
destination: destination,
|
||||
headers: headers,
|
||||
transport: NewHTTPSTransportWrapper(dialer, serverAddr, destination),
|
||||
serverAddr: serverAddr,
|
||||
fallback: fallback,
|
||||
transport: NewHTTPSTransportWrapper(dialer, serverAddr, fallback),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,8 +158,14 @@ func (t *HTTPSTransport) Close() error {
|
||||
func (t *HTTPSTransport) Reset() {
|
||||
t.transportAccess.Lock()
|
||||
defer t.transportAccess.Unlock()
|
||||
t.transport.CloseIdleConnections()
|
||||
t.transport = t.transport.Clone()
|
||||
t.resetTransportLocked()
|
||||
}
|
||||
|
||||
func (t *HTTPSTransport) resetTransportLocked() {
|
||||
oldTransport := t.transport
|
||||
t.transport = NewHTTPSTransportWrapper(t.dialer, t.serverAddr, t.fallback)
|
||||
t.transportResetAt = time.Now()
|
||||
oldTransport.Close()
|
||||
}
|
||||
|
||||
func (t *HTTPSTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
|
||||
@@ -162,9 +178,7 @@ func (t *HTTPSTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS
|
||||
if t.transportResetAt.After(startAt) {
|
||||
return nil, err
|
||||
}
|
||||
t.transport.CloseIdleConnections()
|
||||
t.transport = t.transport.Clone()
|
||||
t.transportResetAt = time.Now()
|
||||
t.resetTransportLocked()
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/sagernet/sing-box/common/tls"
|
||||
@@ -22,42 +22,50 @@ type HTTPSTransportWrapper struct {
|
||||
http2Transport *http2.Transport
|
||||
httpTransport *http.Transport
|
||||
fallback *atomic.Bool
|
||||
connAccess sync.Mutex
|
||||
connections map[*httpsTrackedConn]struct{}
|
||||
closed bool
|
||||
}
|
||||
|
||||
func NewHTTPSTransportWrapper(dialer N.Dialer, serverAddr M.Socksaddr, destination *url.URL) *HTTPSTransportWrapper {
|
||||
var fallback atomic.Bool
|
||||
if destination.Scheme == "http" {
|
||||
// plain HTTP DoH used by Tailscale
|
||||
fallback.Store(true)
|
||||
func NewHTTPSTransportWrapper(dialer N.Dialer, serverAddr M.Socksaddr, fallback *atomic.Bool) *HTTPSTransportWrapper {
|
||||
wrapper := &HTTPSTransportWrapper{
|
||||
fallback: fallback,
|
||||
connections: make(map[*httpsTrackedConn]struct{}),
|
||||
}
|
||||
return &HTTPSTransportWrapper{
|
||||
http2Transport: &http2.Transport{
|
||||
DialTLSContext: func(ctx context.Context, _, _ string, _ *tls.STDConfig) (net.Conn, error) {
|
||||
resultConn, err := dialer.DialContext(ctx, N.NetworkTCP, serverAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
wrapper.http2Transport = &http2.Transport{
|
||||
DialTLSContext: func(ctx context.Context, _, _ string, _ *tls.STDConfig) (net.Conn, error) {
|
||||
resultConn, err := dialer.DialContext(ctx, N.NetworkTCP, serverAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tlsConn, isTLSConn := resultConn.(tls.Conn); isTLSConn {
|
||||
state := tlsConn.ConnectionState()
|
||||
if state.NegotiatedProtocol != http2.NextProtoTLS {
|
||||
tlsConn.Close()
|
||||
fallback.Store(true)
|
||||
return nil, errFallback
|
||||
}
|
||||
if tlsConn, isTLSConn := resultConn.(tls.Conn); isTLSConn {
|
||||
state := tlsConn.ConnectionState()
|
||||
if state.NegotiatedProtocol != http2.NextProtoTLS {
|
||||
tlsConn.Close()
|
||||
fallback.Store(true)
|
||||
return nil, errFallback
|
||||
}
|
||||
}
|
||||
return resultConn, nil
|
||||
},
|
||||
}
|
||||
return wrapper.trackConn(resultConn)
|
||||
},
|
||||
httpTransport: &http.Transport{
|
||||
DialContext: func(ctx context.Context, _, addr string) (net.Conn, error) {
|
||||
return dialer.DialContext(ctx, N.NetworkTCP, serverAddr)
|
||||
},
|
||||
DialTLSContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||
return dialer.DialContext(ctx, N.NetworkTCP, serverAddr)
|
||||
},
|
||||
},
|
||||
fallback: &fallback,
|
||||
}
|
||||
wrapper.httpTransport = &http.Transport{
|
||||
DialContext: func(ctx context.Context, _, addr string) (net.Conn, error) {
|
||||
resultConn, err := dialer.DialContext(ctx, N.NetworkTCP, serverAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return wrapper.trackConn(resultConn)
|
||||
},
|
||||
DialTLSContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||
resultConn, err := dialer.DialContext(ctx, N.NetworkTCP, serverAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return wrapper.trackConn(resultConn)
|
||||
},
|
||||
}
|
||||
return wrapper
|
||||
}
|
||||
|
||||
func (h *HTTPSTransportWrapper) RoundTrip(request *http.Request) (*http.Response, error) {
|
||||
@@ -74,17 +82,47 @@ func (h *HTTPSTransportWrapper) RoundTrip(request *http.Request) (*http.Response
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (h *HTTPSTransportWrapper) CloseIdleConnections() {
|
||||
func (h *HTTPSTransportWrapper) trackConn(conn net.Conn) (net.Conn, error) {
|
||||
trackedConn := &httpsTrackedConn{Conn: conn, wrapper: h}
|
||||
h.connAccess.Lock()
|
||||
if h.closed {
|
||||
h.connAccess.Unlock()
|
||||
conn.Close()
|
||||
return nil, net.ErrClosed
|
||||
}
|
||||
h.connections[trackedConn] = struct{}{}
|
||||
h.connAccess.Unlock()
|
||||
return trackedConn, nil
|
||||
}
|
||||
|
||||
func (h *HTTPSTransportWrapper) Close() {
|
||||
h.connAccess.Lock()
|
||||
if h.closed {
|
||||
h.connAccess.Unlock()
|
||||
return
|
||||
}
|
||||
h.closed = true
|
||||
connections := make([]*httpsTrackedConn, 0, len(h.connections))
|
||||
for trackedConn := range h.connections {
|
||||
connections = append(connections, trackedConn)
|
||||
}
|
||||
h.connections = nil
|
||||
h.connAccess.Unlock()
|
||||
for _, trackedConn := range connections {
|
||||
trackedConn.Conn.Close()
|
||||
}
|
||||
h.http2Transport.CloseIdleConnections()
|
||||
h.httpTransport.CloseIdleConnections()
|
||||
}
|
||||
|
||||
func (h *HTTPSTransportWrapper) Clone() *HTTPSTransportWrapper {
|
||||
return &HTTPSTransportWrapper{
|
||||
httpTransport: h.httpTransport,
|
||||
http2Transport: &http2.Transport{
|
||||
DialTLSContext: h.http2Transport.DialTLSContext,
|
||||
},
|
||||
fallback: h.fallback,
|
||||
}
|
||||
type httpsTrackedConn struct {
|
||||
net.Conn
|
||||
wrapper *HTTPSTransportWrapper
|
||||
}
|
||||
|
||||
func (c *httpsTrackedConn) Close() error {
|
||||
c.wrapper.connAccess.Lock()
|
||||
delete(c.wrapper.connections, c)
|
||||
c.wrapper.connAccess.Unlock()
|
||||
return c.Conn.Close()
|
||||
}
|
||||
|
||||
@@ -148,6 +148,9 @@ func (t *Transport) Reset() {
|
||||
}
|
||||
}
|
||||
t.system.reset()
|
||||
if t.resolved != nil {
|
||||
t.resolved.Reset()
|
||||
}
|
||||
if t.dhcpTransport != nil {
|
||||
t.dhcpTransport.Reset()
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
type ResolvedResolver interface {
|
||||
Start() error
|
||||
Close() error
|
||||
Reset()
|
||||
Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error)
|
||||
ExchangeAsync(ctx context.Context, message *mDNS.Msg, callback func(response *mDNS.Msg, err error))
|
||||
}
|
||||
|
||||
@@ -134,6 +134,19 @@ func (t *DBusResolvedResolver) Close() error {
|
||||
return closeErr
|
||||
}
|
||||
|
||||
func (t *DBusResolvedResolver) Reset() {
|
||||
serverSet := t.savedServerSet.Load()
|
||||
if serverSet == nil {
|
||||
return
|
||||
}
|
||||
for _, server := range serverSet.servers {
|
||||
server.primaryTransport.Reset()
|
||||
if server.fallbackTransport != nil {
|
||||
server.fallbackTransport.Reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *DBusResolvedResolver) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
|
||||
serverSet := t.savedServerSet.Load()
|
||||
if serverSet == nil {
|
||||
|
||||
@@ -46,14 +46,14 @@ require (
|
||||
github.com/sagernet/sing v0.8.12-0.20260717153536-4f1ed45a99a5
|
||||
github.com/sagernet/sing-cloudflared v0.1.3-0.20260706062323-d9787e794aa3
|
||||
github.com/sagernet/sing-mux v0.3.5
|
||||
github.com/sagernet/sing-openconnect v0.0.0-20260718163953-a1c7815e4f04
|
||||
github.com/sagernet/sing-openvpn v0.0.0-20260718163953-26ecbeb6352c
|
||||
github.com/sagernet/sing-openconnect v0.0.0-20260719094202-dc28b269c7ce
|
||||
github.com/sagernet/sing-openvpn v0.0.0-20260719094204-c57d60b5c5a4
|
||||
github.com/sagernet/sing-quic v0.6.4-0.20260709034545-e23afe1172dc
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1
|
||||
github.com/sagernet/sing-shadowtls v0.2.1
|
||||
github.com/sagernet/sing-snell v0.0.0-20260710094516-a4e97ee24beb
|
||||
github.com/sagernet/sing-tun v0.8.12-0.20260719050255-7e7bd198288c
|
||||
github.com/sagernet/sing-snell v0.0.0-20260719094200-c43fbee0e839
|
||||
github.com/sagernet/sing-tun v0.8.12-0.20260719094150-557ca930fccd
|
||||
github.com/sagernet/sing-usbip v0.0.0-20260616101517-efb91521eddb
|
||||
github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1
|
||||
github.com/sagernet/smux v1.5.50-sing-box-mod.1
|
||||
|
||||
@@ -285,10 +285,10 @@ github.com/sagernet/sing-cloudflared v0.1.3-0.20260706062323-d9787e794aa3 h1:3y6
|
||||
github.com/sagernet/sing-cloudflared v0.1.3-0.20260706062323-d9787e794aa3/go.mod h1:XEqEDYRCAYLaoPjZ1ifVWJg5iWAJHL2gOAXe/PM28Cg=
|
||||
github.com/sagernet/sing-mux v0.3.5 h1:RHnhVEc+SFqkrK4xMygYjDwwLhzp2Bj3lztSukONfhI=
|
||||
github.com/sagernet/sing-mux v0.3.5/go.mod h1:QvlKMyNBNrQoyX4x+gq028uPbLM2XeRpWtDsWBJbFSk=
|
||||
github.com/sagernet/sing-openconnect v0.0.0-20260718163953-a1c7815e4f04 h1:HIb3Tu19qqH5fD5xnyyHb6zJaETIsnXamb/hWTtxil8=
|
||||
github.com/sagernet/sing-openconnect v0.0.0-20260718163953-a1c7815e4f04/go.mod h1:EIzh5HtImfQJxPKXFwS9lyMnmMy4aCQCx7ntQ4u41Gs=
|
||||
github.com/sagernet/sing-openvpn v0.0.0-20260718163953-26ecbeb6352c h1:EhwLZF3IUyDj4uZ7vkUZAI7GymXCeOCwiseuOTsFjp8=
|
||||
github.com/sagernet/sing-openvpn v0.0.0-20260718163953-26ecbeb6352c/go.mod h1:CmTGnS5ijVSqFQV1dTq4WvFLUoz7bk9xasBPsX8NcYo=
|
||||
github.com/sagernet/sing-openconnect v0.0.0-20260719094202-dc28b269c7ce h1:uPyEKbqEyGaJoKxQtiS+T9ZTrioL0Vl5Ko3i6iTpV2Y=
|
||||
github.com/sagernet/sing-openconnect v0.0.0-20260719094202-dc28b269c7ce/go.mod h1:EIzh5HtImfQJxPKXFwS9lyMnmMy4aCQCx7ntQ4u41Gs=
|
||||
github.com/sagernet/sing-openvpn v0.0.0-20260719094204-c57d60b5c5a4 h1:3H1pOsE5IRzr2U+oUTabPrvryj7xg1CEmOnMMwsQSQA=
|
||||
github.com/sagernet/sing-openvpn v0.0.0-20260719094204-c57d60b5c5a4/go.mod h1:CmTGnS5ijVSqFQV1dTq4WvFLUoz7bk9xasBPsX8NcYo=
|
||||
github.com/sagernet/sing-quic v0.6.4-0.20260709034545-e23afe1172dc h1:zdc0fj4JdAdgAmQIoh7ZF+B/wPTEF2X75lYDqTmvlaw=
|
||||
github.com/sagernet/sing-quic v0.6.4-0.20260709034545-e23afe1172dc/go.mod h1:9k+dzGsWMttUGldBzq3dU792YHXzW6NgfbOGltnXq+0=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8 h1:PURj5PRoAkqeHh2ZW205RWzN9E9RtKCVCzByXruQWfE=
|
||||
@@ -297,10 +297,10 @@ github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnq
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
||||
github.com/sagernet/sing-shadowtls v0.2.1 h1:ZiHZdnEnP+YS73NMsxiZmIFCwNd0M4k7PkGCKNXhbaM=
|
||||
github.com/sagernet/sing-shadowtls v0.2.1/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA=
|
||||
github.com/sagernet/sing-snell v0.0.0-20260710094516-a4e97ee24beb h1:VvU2/PZqP5tbKTDq0BxkhRO8ZnKI4UJzziakgBiP2Qg=
|
||||
github.com/sagernet/sing-snell v0.0.0-20260710094516-a4e97ee24beb/go.mod h1:PcwzX/Xvqky0EP3kGt8OCjYb3R1pydenPHNQZcPZmXY=
|
||||
github.com/sagernet/sing-tun v0.8.12-0.20260719050255-7e7bd198288c h1:jS5eWD9PyXhHY89DueRDgenfcrfpyPOuuZIoNfnBmOs=
|
||||
github.com/sagernet/sing-tun v0.8.12-0.20260719050255-7e7bd198288c/go.mod h1:F/gRq5VX1WN/OZtsvbN2JjXXuNl2ATJglHMSk1/iN9U=
|
||||
github.com/sagernet/sing-snell v0.0.0-20260719094200-c43fbee0e839 h1:YL0oCb55moImUGvjhhVEYODGMo5i9dAf+RpmMFPCq9w=
|
||||
github.com/sagernet/sing-snell v0.0.0-20260719094200-c43fbee0e839/go.mod h1:PcwzX/Xvqky0EP3kGt8OCjYb3R1pydenPHNQZcPZmXY=
|
||||
github.com/sagernet/sing-tun v0.8.12-0.20260719094150-557ca930fccd h1:tH79/IieRjLx5DiVu3NpXc1hir0xL6Avmmist0aFHks=
|
||||
github.com/sagernet/sing-tun v0.8.12-0.20260719094150-557ca930fccd/go.mod h1:F/gRq5VX1WN/OZtsvbN2JjXXuNl2ATJglHMSk1/iN9U=
|
||||
github.com/sagernet/sing-usbip v0.0.0-20260616101517-efb91521eddb h1:KEMbfexD4DvrQGYWwx6r+AwH9Veh8z6cnBZmtCS2G+0=
|
||||
github.com/sagernet/sing-usbip v0.0.0-20260616101517-efb91521eddb/go.mod h1:D4CnJX3MNAAANhbQUxfIRgBdnvlTEaV7h6ojedcs+pw=
|
||||
github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1 h1:aSwUNYUkVyVvdmBSufR8/nRFonwJeKSIROxHcm5br9o=
|
||||
|
||||
@@ -77,6 +77,10 @@ func (i *Inbound) Start(stage adapter.StartStage) error {
|
||||
return i.listener.Start()
|
||||
}
|
||||
|
||||
func (i *Inbound) InterfaceUpdated() {
|
||||
i.udpNat.Purge()
|
||||
}
|
||||
|
||||
func (i *Inbound) Close() error {
|
||||
return i.listener.Close()
|
||||
}
|
||||
|
||||
@@ -29,10 +29,11 @@ func RegisterOutbound(registry *outbound.Registry) {
|
||||
}
|
||||
|
||||
var (
|
||||
_ N.ParallelDialer = (*Outbound)(nil)
|
||||
_ dialer.ParallelNetworkDialer = (*Outbound)(nil)
|
||||
_ dialer.DirectDialer = (*Outbound)(nil)
|
||||
_ adapter.FlowOutbound = (*Outbound)(nil)
|
||||
_ N.ParallelDialer = (*Outbound)(nil)
|
||||
_ dialer.ParallelNetworkDialer = (*Outbound)(nil)
|
||||
_ dialer.DirectDialer = (*Outbound)(nil)
|
||||
_ adapter.FlowOutbound = (*Outbound)(nil)
|
||||
_ adapter.InterfaceUpdateListener = (*Outbound)(nil)
|
||||
)
|
||||
|
||||
type Outbound struct {
|
||||
@@ -88,30 +89,43 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||
func (h *Outbound) Start(stage adapter.StartStage) error {
|
||||
switch stage {
|
||||
case adapter.StartStatePostStart, adapter.StartStateStarted:
|
||||
h.fetchMyAddresses()
|
||||
if len(h.myAddresses.Load()) == 0 {
|
||||
h.fetchMyAddresses()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Outbound) fetchMyAddresses() {
|
||||
if len(h.myAddresses.Load()) > 0 {
|
||||
return
|
||||
}
|
||||
myInterfaceNames := h.network.InterfaceMonitor().MyInterfaces()
|
||||
if len(myInterfaceNames) == 0 {
|
||||
return
|
||||
}
|
||||
var myAddresses []netip.Prefix
|
||||
var (
|
||||
myAddresses []netip.Prefix
|
||||
found bool
|
||||
)
|
||||
for _, myInterfaceName := range myInterfaceNames {
|
||||
myInterface, err := h.network.InterfaceFinder().ByName(myInterfaceName)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
found = true
|
||||
myAddresses = append(myAddresses, myInterface.Addresses...)
|
||||
}
|
||||
if !found {
|
||||
return
|
||||
}
|
||||
h.myAddresses.Store(myAddresses)
|
||||
}
|
||||
|
||||
func (h *Outbound) InterfaceUpdated() {
|
||||
h.fetchMyAddresses()
|
||||
if h.icmpPort != nil {
|
||||
h.icmpPort.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Outbound) isMyLoopbackAddress(addresses ...netip.Addr) bool {
|
||||
for _, prefix := range h.myAddresses.Load() {
|
||||
for _, address := range addresses {
|
||||
|
||||
@@ -28,7 +28,10 @@ func RegisterURLTest(registry *outbound.Registry) {
|
||||
outbound.Register[option.URLTestOutboundOptions](registry, C.TypeURLTest, NewURLTest)
|
||||
}
|
||||
|
||||
var _ adapter.OutboundGroup = (*URLTest)(nil)
|
||||
var (
|
||||
_ adapter.OutboundGroup = (*URLTest)(nil)
|
||||
_ adapter.InterfaceUpdateListener = (*URLTest)(nil)
|
||||
)
|
||||
|
||||
type URLTest struct {
|
||||
outbound.Adapter
|
||||
@@ -114,6 +117,17 @@ func (s *URLTest) CheckOutbounds() {
|
||||
s.group.CheckOutbounds(true)
|
||||
}
|
||||
|
||||
func (s *URLTest) InterfaceUpdated() {
|
||||
group := s.group
|
||||
if group == nil {
|
||||
return
|
||||
}
|
||||
if group.pause.IsDevicePaused() || group.pause.IsNetworkPaused() {
|
||||
return
|
||||
}
|
||||
go group.CheckOutbounds(true)
|
||||
}
|
||||
|
||||
func (s *URLTest) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
s.group.Touch()
|
||||
var outbound adapter.Outbound
|
||||
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
var (
|
||||
_ adapter.OutboundWithPreferredRoutes = (*Endpoint)(nil)
|
||||
_ adapter.FlowOutbound = (*Endpoint)(nil)
|
||||
_ adapter.InterfaceUpdateListener = (*Endpoint)(nil)
|
||||
_ dialer.PacketDialerWithDestination = (*Endpoint)(nil)
|
||||
_ tun.Port = (*Endpoint)(nil)
|
||||
)
|
||||
@@ -396,6 +397,10 @@ func (e *Endpoint) Close() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *Endpoint) InterfaceUpdated() {
|
||||
e.client.RestartSession()
|
||||
}
|
||||
|
||||
func (e *Endpoint) PreMatchFlow(network string, destination netip.Addr) adapter.PreMatchAction {
|
||||
return adapter.PreMatchFlow
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
var (
|
||||
_ adapter.OutboundWithPreferredRoutes = (*ClientEndpoint)(nil)
|
||||
_ adapter.FlowOutbound = (*ClientEndpoint)(nil)
|
||||
_ adapter.InterfaceUpdateListener = (*ClientEndpoint)(nil)
|
||||
_ dialer.PacketDialerWithDestination = (*ClientEndpoint)(nil)
|
||||
_ tun.Port = (*ClientEndpoint)(nil)
|
||||
)
|
||||
@@ -453,6 +454,10 @@ func (c *ClientEndpoint) Close() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *ClientEndpoint) InterfaceUpdated() {
|
||||
c.client.RestartSession()
|
||||
}
|
||||
|
||||
func (c *ClientEndpoint) PreMatchFlow(network string, destination netip.Addr) adapter.PreMatchAction {
|
||||
return adapter.PreMatchFlow
|
||||
}
|
||||
|
||||
@@ -85,6 +85,10 @@ func (t *TProxy) Start(stage adapter.StartStage) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *TProxy) InterfaceUpdated() {
|
||||
t.udpNat.Purge()
|
||||
}
|
||||
|
||||
func (t *TProxy) Close() error {
|
||||
_ = t.udpNat.Close()
|
||||
return t.listener.Close()
|
||||
|
||||
@@ -32,9 +32,12 @@ type Outbound struct {
|
||||
serverAddr M.Socksaddr
|
||||
}
|
||||
|
||||
var _ adapter.InterfaceUpdateListener = (*Outbound)(nil)
|
||||
|
||||
type snellClient interface {
|
||||
snellprotocol.Method
|
||||
DialContext(ctx context.Context, destination M.Socksaddr) (net.Conn, error)
|
||||
Reset()
|
||||
Close() error
|
||||
}
|
||||
|
||||
@@ -136,6 +139,10 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
|
||||
return packetConn, nil
|
||||
}
|
||||
|
||||
func (h *Outbound) InterfaceUpdated() {
|
||||
h.client.Reset()
|
||||
}
|
||||
|
||||
func (h *Outbound) Close() error {
|
||||
return h.client.Close()
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ import (
|
||||
|
||||
var (
|
||||
_ adapter.OutboundWithPreferredRoutes = (*Endpoint)(nil)
|
||||
_ adapter.InterfaceUpdateListener = (*Endpoint)(nil)
|
||||
_ dialer.PacketDialerWithDestination = (*Endpoint)(nil)
|
||||
_ tun.Port = (*Endpoint)(nil)
|
||||
)
|
||||
@@ -696,6 +697,16 @@ func (t *Endpoint) Close() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *Endpoint) InterfaceUpdated() {
|
||||
if !t.started.Load() {
|
||||
return
|
||||
}
|
||||
netMon, loaded := t.server.Sys().NetMon.GetOK()
|
||||
if loaded && netMon != nil {
|
||||
netMon.InjectEvent()
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Endpoint) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
switch network {
|
||||
case N.NetworkTCP:
|
||||
|
||||
@@ -507,6 +507,13 @@ func (t *Inbound) updateRouteAddressSet(it adapter.RuleSet) {
|
||||
t.routeExcludeAddressSet = nil
|
||||
}
|
||||
|
||||
func (t *Inbound) InterfaceUpdated() {
|
||||
tunStack := t.tunStack
|
||||
if tunStack != nil {
|
||||
tunStack.ResetNetwork()
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Inbound) Close() error {
|
||||
return common.Close(
|
||||
t.tunStack,
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
|
||||
var (
|
||||
_ adapter.OutboundWithPreferredRoutes = (*Endpoint)(nil)
|
||||
_ adapter.InterfaceUpdateListener = (*Endpoint)(nil)
|
||||
_ dialer.PacketDialerWithDestination = (*Endpoint)(nil)
|
||||
)
|
||||
|
||||
@@ -159,6 +160,16 @@ func (w *Endpoint) Close() error {
|
||||
return w.endpoint.Close()
|
||||
}
|
||||
|
||||
func (w *Endpoint) InterfaceUpdated() {
|
||||
if !w.started.Load() {
|
||||
return
|
||||
}
|
||||
err := w.endpoint.BindUpdate()
|
||||
if err != nil {
|
||||
w.logger.Error(E.Cause(err, "update bind"))
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Endpoint) PreMatchFlow(network string, destination netip.Addr) adapter.PreMatchAction {
|
||||
return adapter.PreMatchFlow
|
||||
}
|
||||
|
||||
@@ -44,6 +44,9 @@ func (s *platformSearcher) FindProcessInfo(ctx context.Context, network string,
|
||||
return s.platform.FindConnectionOwner(request)
|
||||
}
|
||||
|
||||
func (s *platformSearcher) ResetCache() {
|
||||
}
|
||||
|
||||
func (s *platformSearcher) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -288,4 +288,10 @@ func (r *Router) NeighborResolver() adapter.NeighborResolver {
|
||||
func (r *Router) ResetNetwork() {
|
||||
r.httpClientManager.ResetNetwork()
|
||||
r.dns.ResetNetwork()
|
||||
if r.processCache != nil {
|
||||
r.processCache.Purge()
|
||||
}
|
||||
if r.processSearcher != nil {
|
||||
r.processSearcher.ResetCache()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,6 +254,13 @@ func (e *Endpoint) Lookup(address netip.Addr) *device.Peer {
|
||||
return e.allowedIPs.Lookup(address.AsSlice())
|
||||
}
|
||||
|
||||
func (e *Endpoint) BindUpdate() error {
|
||||
if e.device == nil {
|
||||
return nil
|
||||
}
|
||||
return e.device.BindUpdate()
|
||||
}
|
||||
|
||||
func (e *Endpoint) onPauseUpdated(event int) {
|
||||
switch event {
|
||||
case pause.EventDevicePaused, pause.EventNetworkPause:
|
||||
|
||||
Reference in New Issue
Block a user