mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-09-15 21:00:27 +00:00
Improve network reset
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
|||||||
|
|
||||||
type Searcher interface {
|
type Searcher interface {
|
||||||
FindProcessInfo(ctx context.Context, network string, source netip.AddrPort, destination netip.AddrPort) (*adapter.ConnectionOwner, error)
|
FindProcessInfo(ctx context.Context, network string, source netip.AddrPort, destination netip.AddrPort) (*adapter.ConnectionOwner, error)
|
||||||
|
ResetCache()
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ func NewSearcher(config Config) (Searcher, error) {
|
|||||||
return &androidSearcher{config.PackageManager}, nil
|
return &androidSearcher{config.PackageManager}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *androidSearcher) ResetCache() {
|
||||||
|
}
|
||||||
|
|
||||||
func (s *androidSearcher) Close() error {
|
func (s *androidSearcher) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ func NewSearcher(_ Config) (Searcher, error) {
|
|||||||
return &darwinSearcher{}, nil
|
return &darwinSearcher{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *darwinSearcher) ResetCache() {
|
||||||
|
sharedDarwinConnectionFinder.resetCache()
|
||||||
|
}
|
||||||
|
|
||||||
func (d *darwinSearcher) Close() error {
|
func (d *darwinSearcher) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,6 +119,12 @@ func (f *darwinConnectionFinder) find(network string, source netip.AddrPort, des
|
|||||||
return nil, ErrNotFound
|
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) {
|
func (f *darwinConnectionFinder) loadSnapshot(network string, forceRefresh bool) (darwinSnapshot, bool, error) {
|
||||||
f.access.Lock()
|
f.access.Lock()
|
||||||
defer f.access.Unlock()
|
defer f.access.Unlock()
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ func NewSearcher(config Config) (Searcher, error) {
|
|||||||
return searcher, nil
|
return searcher, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *linuxSearcher) ResetCache() {
|
||||||
|
s.processPathCache.cache.Purge()
|
||||||
|
}
|
||||||
|
|
||||||
func (s *linuxSearcher) Close() error {
|
func (s *linuxSearcher) Close() error {
|
||||||
var errs []error
|
var errs []error
|
||||||
for _, conn := range s.diagConns {
|
for _, conn := range s.diagConns {
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ func initWin32API() error {
|
|||||||
return winiphlpapi.LoadExtendedTable()
|
return winiphlpapi.LoadExtendedTable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *windowsSearcher) ResetCache() {
|
||||||
|
}
|
||||||
|
|
||||||
func (s *windowsSearcher) Close() error {
|
func (s *windowsSearcher) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-6
@@ -10,6 +10,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
@@ -45,6 +46,8 @@ type HTTPSTransport struct {
|
|||||||
dialer N.Dialer
|
dialer N.Dialer
|
||||||
destination *url.URL
|
destination *url.URL
|
||||||
headers http.Header
|
headers http.Header
|
||||||
|
serverAddr M.Socksaddr
|
||||||
|
fallback *atomic.Bool
|
||||||
transportAccess sync.Mutex
|
transportAccess sync.Mutex
|
||||||
transport *HTTPSTransportWrapper
|
transport *HTTPSTransportWrapper
|
||||||
transportResetAt time.Time
|
transportResetAt time.Time
|
||||||
@@ -123,13 +126,20 @@ func NewHTTPSRaw(
|
|||||||
if tlsConfig != nil {
|
if tlsConfig != nil {
|
||||||
dialer = tls.NewDialer(dialer, tlsConfig)
|
dialer = tls.NewDialer(dialer, tlsConfig)
|
||||||
}
|
}
|
||||||
|
fallback := new(atomic.Bool)
|
||||||
|
if destination.Scheme == "http" {
|
||||||
|
// plain HTTP DoH used by Tailscale
|
||||||
|
fallback.Store(true)
|
||||||
|
}
|
||||||
return &HTTPSTransport{
|
return &HTTPSTransport{
|
||||||
TransportAdapter: adapter,
|
TransportAdapter: adapter,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
dialer: dialer,
|
dialer: dialer,
|
||||||
destination: destination,
|
destination: destination,
|
||||||
headers: headers,
|
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() {
|
func (t *HTTPSTransport) Reset() {
|
||||||
t.transportAccess.Lock()
|
t.transportAccess.Lock()
|
||||||
defer t.transportAccess.Unlock()
|
defer t.transportAccess.Unlock()
|
||||||
t.transport.CloseIdleConnections()
|
t.resetTransportLocked()
|
||||||
t.transport = t.transport.Clone()
|
}
|
||||||
|
|
||||||
|
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) {
|
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) {
|
if t.transportResetAt.After(startAt) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
t.transport.CloseIdleConnections()
|
t.resetTransportLocked()
|
||||||
t.transport = t.transport.Clone()
|
|
||||||
t.transportResetAt = time.Now()
|
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
@@ -22,42 +22,50 @@ type HTTPSTransportWrapper struct {
|
|||||||
http2Transport *http2.Transport
|
http2Transport *http2.Transport
|
||||||
httpTransport *http.Transport
|
httpTransport *http.Transport
|
||||||
fallback *atomic.Bool
|
fallback *atomic.Bool
|
||||||
|
connAccess sync.Mutex
|
||||||
|
connections map[*httpsTrackedConn]struct{}
|
||||||
|
closed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHTTPSTransportWrapper(dialer N.Dialer, serverAddr M.Socksaddr, destination *url.URL) *HTTPSTransportWrapper {
|
func NewHTTPSTransportWrapper(dialer N.Dialer, serverAddr M.Socksaddr, fallback *atomic.Bool) *HTTPSTransportWrapper {
|
||||||
var fallback atomic.Bool
|
wrapper := &HTTPSTransportWrapper{
|
||||||
if destination.Scheme == "http" {
|
fallback: fallback,
|
||||||
// plain HTTP DoH used by Tailscale
|
connections: make(map[*httpsTrackedConn]struct{}),
|
||||||
fallback.Store(true)
|
|
||||||
}
|
}
|
||||||
return &HTTPSTransportWrapper{
|
wrapper.http2Transport = &http2.Transport{
|
||||||
http2Transport: &http2.Transport{
|
DialTLSContext: func(ctx context.Context, _, _ string, _ *tls.STDConfig) (net.Conn, error) {
|
||||||
DialTLSContext: func(ctx context.Context, _, _ string, _ *tls.STDConfig) (net.Conn, error) {
|
resultConn, err := dialer.DialContext(ctx, N.NetworkTCP, serverAddr)
|
||||||
resultConn, err := dialer.DialContext(ctx, N.NetworkTCP, serverAddr)
|
if err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
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()
|
return wrapper.trackConn(resultConn)
|
||||||
if state.NegotiatedProtocol != http2.NextProtoTLS {
|
|
||||||
tlsConn.Close()
|
|
||||||
fallback.Store(true)
|
|
||||||
return nil, errFallback
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return resultConn, nil
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
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) {
|
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
|
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.http2Transport.CloseIdleConnections()
|
||||||
h.httpTransport.CloseIdleConnections()
|
h.httpTransport.CloseIdleConnections()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HTTPSTransportWrapper) Clone() *HTTPSTransportWrapper {
|
type httpsTrackedConn struct {
|
||||||
return &HTTPSTransportWrapper{
|
net.Conn
|
||||||
httpTransport: h.httpTransport,
|
wrapper *HTTPSTransportWrapper
|
||||||
http2Transport: &http2.Transport{
|
}
|
||||||
DialTLSContext: h.http2Transport.DialTLSContext,
|
|
||||||
},
|
func (c *httpsTrackedConn) Close() error {
|
||||||
fallback: h.fallback,
|
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()
|
t.system.reset()
|
||||||
|
if t.resolved != nil {
|
||||||
|
t.resolved.Reset()
|
||||||
|
}
|
||||||
if t.dhcpTransport != nil {
|
if t.dhcpTransport != nil {
|
||||||
t.dhcpTransport.Reset()
|
t.dhcpTransport.Reset()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
type ResolvedResolver interface {
|
type ResolvedResolver interface {
|
||||||
Start() error
|
Start() error
|
||||||
Close() error
|
Close() error
|
||||||
|
Reset()
|
||||||
Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error)
|
Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error)
|
||||||
ExchangeAsync(ctx context.Context, message *mDNS.Msg, callback func(response *mDNS.Msg, err 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
|
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) {
|
func (t *DBusResolvedResolver) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
|
||||||
serverSet := t.savedServerSet.Load()
|
serverSet := t.savedServerSet.Load()
|
||||||
if serverSet == nil {
|
if serverSet == nil {
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ require (
|
|||||||
github.com/sagernet/sing v0.9.0-beta.3
|
github.com/sagernet/sing v0.9.0-beta.3
|
||||||
github.com/sagernet/sing-cloudflared v0.1.3-0.20260706062323-d9787e794aa3
|
github.com/sagernet/sing-cloudflared v0.1.3-0.20260706062323-d9787e794aa3
|
||||||
github.com/sagernet/sing-mux v0.3.5
|
github.com/sagernet/sing-mux v0.3.5
|
||||||
github.com/sagernet/sing-openconnect v0.0.0-20260718163953-a1c7815e4f04
|
github.com/sagernet/sing-openconnect v0.0.0-20260719094202-dc28b269c7ce
|
||||||
github.com/sagernet/sing-openvpn v0.0.0-20260718163953-26ecbeb6352c
|
github.com/sagernet/sing-openvpn v0.0.0-20260719094204-c57d60b5c5a4
|
||||||
github.com/sagernet/sing-quic v0.6.4-0.20260803041931-6c84c468bea2
|
github.com/sagernet/sing-quic v0.6.4-0.20260803041931-6c84c468bea2
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.8
|
github.com/sagernet/sing-shadowsocks v0.2.8
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.1
|
github.com/sagernet/sing-shadowsocks2 v0.2.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-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 h1:RHnhVEc+SFqkrK4xMygYjDwwLhzp2Bj3lztSukONfhI=
|
||||||
github.com/sagernet/sing-mux v0.3.5/go.mod h1:QvlKMyNBNrQoyX4x+gq028uPbLM2XeRpWtDsWBJbFSk=
|
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-20260719094202-dc28b269c7ce h1:uPyEKbqEyGaJoKxQtiS+T9ZTrioL0Vl5Ko3i6iTpV2Y=
|
||||||
github.com/sagernet/sing-openconnect v0.0.0-20260718163953-a1c7815e4f04/go.mod h1:EIzh5HtImfQJxPKXFwS9lyMnmMy4aCQCx7ntQ4u41Gs=
|
github.com/sagernet/sing-openconnect v0.0.0-20260719094202-dc28b269c7ce/go.mod h1:EIzh5HtImfQJxPKXFwS9lyMnmMy4aCQCx7ntQ4u41Gs=
|
||||||
github.com/sagernet/sing-openvpn v0.0.0-20260718163953-26ecbeb6352c h1:EhwLZF3IUyDj4uZ7vkUZAI7GymXCeOCwiseuOTsFjp8=
|
github.com/sagernet/sing-openvpn v0.0.0-20260719094204-c57d60b5c5a4 h1:3H1pOsE5IRzr2U+oUTabPrvryj7xg1CEmOnMMwsQSQA=
|
||||||
github.com/sagernet/sing-openvpn v0.0.0-20260718163953-26ecbeb6352c/go.mod h1:CmTGnS5ijVSqFQV1dTq4WvFLUoz7bk9xasBPsX8NcYo=
|
github.com/sagernet/sing-openvpn v0.0.0-20260719094204-c57d60b5c5a4/go.mod h1:CmTGnS5ijVSqFQV1dTq4WvFLUoz7bk9xasBPsX8NcYo=
|
||||||
github.com/sagernet/sing-quic v0.6.4-0.20260803041931-6c84c468bea2 h1:XhJro6+Ou+WOPjfs22m14lY7Sh6sWPm/f0QiyFUgM60=
|
github.com/sagernet/sing-quic v0.6.4-0.20260803041931-6c84c468bea2 h1:XhJro6+Ou+WOPjfs22m14lY7Sh6sWPm/f0QiyFUgM60=
|
||||||
github.com/sagernet/sing-quic v0.6.4-0.20260803041931-6c84c468bea2/go.mod h1:9k+dzGsWMttUGldBzq3dU792YHXzW6NgfbOGltnXq+0=
|
github.com/sagernet/sing-quic v0.6.4-0.20260803041931-6c84c468bea2/go.mod h1:9k+dzGsWMttUGldBzq3dU792YHXzW6NgfbOGltnXq+0=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.8 h1:PURj5PRoAkqeHh2ZW205RWzN9E9RtKCVCzByXruQWfE=
|
github.com/sagernet/sing-shadowsocks v0.2.8 h1:PURj5PRoAkqeHh2ZW205RWzN9E9RtKCVCzByXruQWfE=
|
||||||
|
|||||||
@@ -77,6 +77,10 @@ func (i *Inbound) Start(stage adapter.StartStage) error {
|
|||||||
return i.listener.Start()
|
return i.listener.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *Inbound) InterfaceUpdated() {
|
||||||
|
i.udpNat.Purge()
|
||||||
|
}
|
||||||
|
|
||||||
func (i *Inbound) Close() error {
|
func (i *Inbound) Close() error {
|
||||||
return i.listener.Close()
|
return i.listener.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,11 @@ func RegisterOutbound(registry *outbound.Registry) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ N.ParallelDialer = (*Outbound)(nil)
|
_ N.ParallelDialer = (*Outbound)(nil)
|
||||||
_ dialer.ParallelNetworkDialer = (*Outbound)(nil)
|
_ dialer.ParallelNetworkDialer = (*Outbound)(nil)
|
||||||
_ dialer.DirectDialer = (*Outbound)(nil)
|
_ dialer.DirectDialer = (*Outbound)(nil)
|
||||||
_ adapter.FlowOutbound = (*Outbound)(nil)
|
_ adapter.FlowOutbound = (*Outbound)(nil)
|
||||||
|
_ adapter.InterfaceUpdateListener = (*Outbound)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
type Outbound struct {
|
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 {
|
func (h *Outbound) Start(stage adapter.StartStage) error {
|
||||||
switch stage {
|
switch stage {
|
||||||
case adapter.StartStatePostStart, adapter.StartStateStarted:
|
case adapter.StartStatePostStart, adapter.StartStateStarted:
|
||||||
h.fetchMyAddresses()
|
if len(h.myAddresses.Load()) == 0 {
|
||||||
|
h.fetchMyAddresses()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) fetchMyAddresses() {
|
func (h *Outbound) fetchMyAddresses() {
|
||||||
if len(h.myAddresses.Load()) > 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
myInterfaceNames := h.network.InterfaceMonitor().MyInterfaces()
|
myInterfaceNames := h.network.InterfaceMonitor().MyInterfaces()
|
||||||
if len(myInterfaceNames) == 0 {
|
if len(myInterfaceNames) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var myAddresses []netip.Prefix
|
var (
|
||||||
|
myAddresses []netip.Prefix
|
||||||
|
found bool
|
||||||
|
)
|
||||||
for _, myInterfaceName := range myInterfaceNames {
|
for _, myInterfaceName := range myInterfaceNames {
|
||||||
myInterface, err := h.network.InterfaceFinder().ByName(myInterfaceName)
|
myInterface, err := h.network.InterfaceFinder().ByName(myInterfaceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
found = true
|
||||||
myAddresses = append(myAddresses, myInterface.Addresses...)
|
myAddresses = append(myAddresses, myInterface.Addresses...)
|
||||||
}
|
}
|
||||||
|
if !found {
|
||||||
|
return
|
||||||
|
}
|
||||||
h.myAddresses.Store(myAddresses)
|
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 {
|
func (h *Outbound) isMyLoopbackAddress(addresses ...netip.Addr) bool {
|
||||||
for _, prefix := range h.myAddresses.Load() {
|
for _, prefix := range h.myAddresses.Load() {
|
||||||
for _, address := range addresses {
|
for _, address := range addresses {
|
||||||
|
|||||||
@@ -28,7 +28,10 @@ func RegisterURLTest(registry *outbound.Registry) {
|
|||||||
outbound.Register[option.URLTestOutboundOptions](registry, C.TypeURLTest, NewURLTest)
|
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 {
|
type URLTest struct {
|
||||||
outbound.Adapter
|
outbound.Adapter
|
||||||
@@ -118,6 +121,17 @@ func (s *URLTest) PerformUpdateCheck() {
|
|||||||
s.group.performUpdateCheck()
|
s.group.performUpdateCheck()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
func (s *URLTest) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
s.group.Touch()
|
s.group.Touch()
|
||||||
var outbound adapter.Outbound
|
var outbound adapter.Outbound
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
_ adapter.OutboundWithPreferredRoutes = (*Endpoint)(nil)
|
_ adapter.OutboundWithPreferredRoutes = (*Endpoint)(nil)
|
||||||
_ adapter.FlowOutbound = (*Endpoint)(nil)
|
_ adapter.FlowOutbound = (*Endpoint)(nil)
|
||||||
|
_ adapter.InterfaceUpdateListener = (*Endpoint)(nil)
|
||||||
_ dialer.PacketDialerWithDestination = (*Endpoint)(nil)
|
_ dialer.PacketDialerWithDestination = (*Endpoint)(nil)
|
||||||
_ tun.Port = (*Endpoint)(nil)
|
_ tun.Port = (*Endpoint)(nil)
|
||||||
)
|
)
|
||||||
@@ -396,6 +397,10 @@ func (e *Endpoint) Close() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Endpoint) InterfaceUpdated() {
|
||||||
|
e.client.RestartSession()
|
||||||
|
}
|
||||||
|
|
||||||
func (e *Endpoint) PreMatchFlow(network string, destination netip.Addr) adapter.PreMatchAction {
|
func (e *Endpoint) PreMatchFlow(network string, destination netip.Addr) adapter.PreMatchAction {
|
||||||
return adapter.PreMatchFlow
|
return adapter.PreMatchFlow
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
_ adapter.OutboundWithPreferredRoutes = (*ClientEndpoint)(nil)
|
_ adapter.OutboundWithPreferredRoutes = (*ClientEndpoint)(nil)
|
||||||
_ adapter.FlowOutbound = (*ClientEndpoint)(nil)
|
_ adapter.FlowOutbound = (*ClientEndpoint)(nil)
|
||||||
|
_ adapter.InterfaceUpdateListener = (*ClientEndpoint)(nil)
|
||||||
_ dialer.PacketDialerWithDestination = (*ClientEndpoint)(nil)
|
_ dialer.PacketDialerWithDestination = (*ClientEndpoint)(nil)
|
||||||
_ tun.Port = (*ClientEndpoint)(nil)
|
_ tun.Port = (*ClientEndpoint)(nil)
|
||||||
)
|
)
|
||||||
@@ -453,6 +454,10 @@ func (c *ClientEndpoint) Close() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ClientEndpoint) InterfaceUpdated() {
|
||||||
|
c.client.RestartSession()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ClientEndpoint) PreMatchFlow(network string, destination netip.Addr) adapter.PreMatchAction {
|
func (c *ClientEndpoint) PreMatchFlow(network string, destination netip.Addr) adapter.PreMatchAction {
|
||||||
return adapter.PreMatchFlow
|
return adapter.PreMatchFlow
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,6 +85,10 @@ func (t *TProxy) Start(stage adapter.StartStage) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *TProxy) InterfaceUpdated() {
|
||||||
|
t.udpNat.Purge()
|
||||||
|
}
|
||||||
|
|
||||||
func (t *TProxy) Close() error {
|
func (t *TProxy) Close() error {
|
||||||
_ = t.udpNat.Close()
|
_ = t.udpNat.Close()
|
||||||
return t.listener.Close()
|
return t.listener.Close()
|
||||||
|
|||||||
@@ -32,9 +32,12 @@ type Outbound struct {
|
|||||||
serverAddr M.Socksaddr
|
serverAddr M.Socksaddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ adapter.InterfaceUpdateListener = (*Outbound)(nil)
|
||||||
|
|
||||||
type snellClient interface {
|
type snellClient interface {
|
||||||
snellprotocol.Method
|
snellprotocol.Method
|
||||||
DialContext(ctx context.Context, destination M.Socksaddr) (net.Conn, error)
|
DialContext(ctx context.Context, destination M.Socksaddr) (net.Conn, error)
|
||||||
|
Reset()
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,6 +139,10 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
|
|||||||
return packetConn, nil
|
return packetConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Outbound) InterfaceUpdated() {
|
||||||
|
h.client.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Outbound) Close() error {
|
func (h *Outbound) Close() error {
|
||||||
return h.client.Close()
|
return h.client.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
_ adapter.OutboundWithPreferredRoutes = (*Endpoint)(nil)
|
_ adapter.OutboundWithPreferredRoutes = (*Endpoint)(nil)
|
||||||
|
_ adapter.InterfaceUpdateListener = (*Endpoint)(nil)
|
||||||
_ dialer.PacketDialerWithDestination = (*Endpoint)(nil)
|
_ dialer.PacketDialerWithDestination = (*Endpoint)(nil)
|
||||||
_ tun.Port = (*Endpoint)(nil)
|
_ tun.Port = (*Endpoint)(nil)
|
||||||
)
|
)
|
||||||
@@ -687,6 +688,16 @@ func (t *Endpoint) Close() error {
|
|||||||
return err
|
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) {
|
func (t *Endpoint) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
switch network {
|
switch network {
|
||||||
case N.NetworkTCP:
|
case N.NetworkTCP:
|
||||||
|
|||||||
@@ -505,6 +505,13 @@ func (t *Inbound) updateRouteAddressSet(it adapter.RuleSet) {
|
|||||||
t.routeExcludeAddressSet = nil
|
t.routeExcludeAddressSet = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Inbound) InterfaceUpdated() {
|
||||||
|
tunStack := t.tunStack
|
||||||
|
if tunStack != nil {
|
||||||
|
tunStack.ResetNetwork()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Inbound) Close() error {
|
func (t *Inbound) Close() error {
|
||||||
return common.Close(
|
return common.Close(
|
||||||
t.tunStack,
|
t.tunStack,
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
_ adapter.OutboundWithPreferredRoutes = (*Endpoint)(nil)
|
_ adapter.OutboundWithPreferredRoutes = (*Endpoint)(nil)
|
||||||
|
_ adapter.InterfaceUpdateListener = (*Endpoint)(nil)
|
||||||
_ dialer.PacketDialerWithDestination = (*Endpoint)(nil)
|
_ dialer.PacketDialerWithDestination = (*Endpoint)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -159,6 +160,16 @@ func (w *Endpoint) Close() error {
|
|||||||
return w.endpoint.Close()
|
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 {
|
func (w *Endpoint) PreMatchFlow(network string, destination netip.Addr) adapter.PreMatchAction {
|
||||||
return adapter.PreMatchFlow
|
return adapter.PreMatchFlow
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ func (s *platformSearcher) FindProcessInfo(ctx context.Context, network string,
|
|||||||
return s.platform.FindConnectionOwner(request)
|
return s.platform.FindConnectionOwner(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *platformSearcher) ResetCache() {
|
||||||
|
}
|
||||||
|
|
||||||
func (s *platformSearcher) Close() error {
|
func (s *platformSearcher) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,4 +288,10 @@ func (r *Router) NeighborResolver() adapter.NeighborResolver {
|
|||||||
func (r *Router) ResetNetwork() {
|
func (r *Router) ResetNetwork() {
|
||||||
r.httpClientManager.ResetNetwork()
|
r.httpClientManager.ResetNetwork()
|
||||||
r.dns.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())
|
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) {
|
func (e *Endpoint) onPauseUpdated(event int) {
|
||||||
switch event {
|
switch event {
|
||||||
case pause.EventDevicePaused, pause.EventNetworkPause:
|
case pause.EventDevicePaused, pause.EventNetworkPause:
|
||||||
|
|||||||
Reference in New Issue
Block a user