mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2024-11-14 05:11:17 +08:00
chore: reset resolver's connection after default interface changed
This commit is contained in:
parent
1633885794
commit
acfc9f8baa
@ -296,7 +296,7 @@ func NewWireGuard(option WireGuardOption) (*WireGuard, error) {
|
|||||||
for i := range nss {
|
for i := range nss {
|
||||||
nss[i].ProxyAdapter = refP
|
nss[i].ProxyAdapter = refP
|
||||||
}
|
}
|
||||||
outbound.resolver = dns.NewResolver(dns.Config{
|
outbound.resolver, _ = dns.NewResolver(dns.Config{
|
||||||
Main: nss,
|
Main: nss,
|
||||||
IPv6: has6,
|
IPv6: has6,
|
||||||
})
|
})
|
||||||
|
@ -47,6 +47,7 @@ type Resolver interface {
|
|||||||
ExchangeContext(ctx context.Context, m *dns.Msg) (msg *dns.Msg, err error)
|
ExchangeContext(ctx context.Context, m *dns.Msg) (msg *dns.Msg, err error)
|
||||||
Invalid() bool
|
Invalid() bool
|
||||||
ClearCache()
|
ClearCache()
|
||||||
|
ResetConnection()
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookupIPv4WithResolver same as LookupIPv4, but with a resolver
|
// LookupIPv4WithResolver same as LookupIPv4, but with a resolver
|
||||||
@ -256,6 +257,15 @@ func LookupIPProxyServerHost(ctx context.Context, host string) ([]netip.Addr, er
|
|||||||
return LookupIP(ctx, host)
|
return LookupIP(ctx, host)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ResetConnection() {
|
||||||
|
if DefaultResolver != nil {
|
||||||
|
go DefaultResolver.ResetConnection()
|
||||||
|
}
|
||||||
|
if ProxyServerHostResolver != nil {
|
||||||
|
go ProxyServerHostResolver.ResetConnection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func SortationAddr(ips []netip.Addr) (ipv4s, ipv6s []netip.Addr) {
|
func SortationAddr(ips []netip.Addr) (ipv4s, ipv6s []netip.Addr) {
|
||||||
for _, v := range ips {
|
for _, v := range ips {
|
||||||
if v.Unmap().Is4() {
|
if v.Unmap().Is4() {
|
||||||
|
@ -103,3 +103,5 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error)
|
|||||||
return ret.msg, ret.err
|
return ret.msg, ret.err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *client) ResetConnection() {}
|
||||||
|
@ -53,6 +53,12 @@ func (d *dhcpClient) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *dhcpClient) ResetConnection() {
|
||||||
|
for _, client := range d.clients {
|
||||||
|
client.ResetConnection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (d *dhcpClient) resolve(ctx context.Context) ([]dnsClient, error) {
|
func (d *dhcpClient) resolve(ctx context.Context) ([]dnsClient, error) {
|
||||||
d.lock.Lock()
|
d.lock.Lock()
|
||||||
|
|
||||||
|
27
dns/doh.go
27
dns/doh.go
@ -203,11 +203,23 @@ func (doh *dnsOverHTTPS) Close() (err error) {
|
|||||||
return doh.closeClient(doh.client)
|
return doh.closeClient(doh.client)
|
||||||
}
|
}
|
||||||
|
|
||||||
// closeClient cleans up resources used by client if necessary. Note, that at
|
func (doh *dnsOverHTTPS) ResetConnection() {
|
||||||
// this point it should only be done for HTTP/3 as it may leak due to keep-alive
|
doh.clientMu.Lock()
|
||||||
// connections.
|
defer doh.clientMu.Unlock()
|
||||||
|
|
||||||
|
if doh.client == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = doh.closeClient(doh.client)
|
||||||
|
doh.client = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// closeClient cleans up resources used by client if necessary.
|
||||||
func (doh *dnsOverHTTPS) closeClient(client *http.Client) (err error) {
|
func (doh *dnsOverHTTPS) closeClient(client *http.Client) (err error) {
|
||||||
if isHTTP3(client) {
|
client.CloseIdleConnections()
|
||||||
|
|
||||||
|
if isHTTP3(client) { // HTTP/3 may leak due to keep-alive connections.
|
||||||
return client.Transport.(io.Closer).Close()
|
return client.Transport.(io.Closer).Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,6 +520,13 @@ func (h *http3Transport) Close() (err error) {
|
|||||||
return h.baseTransport.Close()
|
return h.baseTransport.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *http3Transport) CloseIdleConnections() {
|
||||||
|
h.mu.RLock()
|
||||||
|
defer h.mu.RUnlock()
|
||||||
|
|
||||||
|
h.baseTransport.CloseIdleConnections()
|
||||||
|
}
|
||||||
|
|
||||||
// createTransportH3 tries to create an HTTP/3 transport for this upstream.
|
// createTransportH3 tries to create an HTTP/3 transport for this upstream.
|
||||||
// We should be able to fall back to H1/H2 in case if HTTP/3 is unavailable or
|
// We should be able to fall back to H1/H2 in case if HTTP/3 is unavailable or
|
||||||
// if it is too slow. In order to do that, this method will run two probes
|
// if it is too slow. In order to do that, this method will run two probes
|
||||||
|
@ -144,6 +144,10 @@ func (doq *dnsOverQUIC) Close() (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (doq *dnsOverQUIC) ResetConnection() {
|
||||||
|
doq.closeConnWithError(nil)
|
||||||
|
}
|
||||||
|
|
||||||
// exchangeQUIC attempts to open a QUIC connection, send the DNS message
|
// exchangeQUIC attempts to open a QUIC connection, send the DNS message
|
||||||
// through it and return the response it got from the server.
|
// through it and return the response it got from the server.
|
||||||
func (doq *dnsOverQUIC) exchangeQUIC(ctx context.Context, msg *D.Msg) (resp *D.Msg, err error) {
|
func (doq *dnsOverQUIC) exchangeQUIC(ctx context.Context, msg *D.Msg) (resp *D.Msg, err error) {
|
||||||
|
@ -12,6 +12,7 @@ func FlushCacheWithDefaultResolver() {
|
|||||||
if r := resolver.DefaultResolver; r != nil {
|
if r := resolver.DefaultResolver; r != nil {
|
||||||
r.ClearCache()
|
r.ClearCache()
|
||||||
}
|
}
|
||||||
|
resolver.ResetConnection()
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateSystemDNS(addr []string) {
|
func UpdateSystemDNS(addr []string) {
|
||||||
@ -30,3 +31,9 @@ func UpdateSystemDNS(addr []string) {
|
|||||||
func (c *systemClient) getDnsClients() ([]dnsClient, error) {
|
func (c *systemClient) getDnsClients() ([]dnsClient, error) {
|
||||||
return systemResolver, nil
|
return systemResolver, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *systemClient) ResetConnection() {
|
||||||
|
for _, r := range systemResolver {
|
||||||
|
r.ResetConnection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -48,3 +48,5 @@ func (r rcodeClient) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, err
|
|||||||
func (r rcodeClient) Address() string {
|
func (r rcodeClient) Address() string {
|
||||||
return r.addr
|
return r.addr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r rcodeClient) ResetConnection() {}
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
type dnsClient interface {
|
type dnsClient interface {
|
||||||
ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error)
|
ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error)
|
||||||
Address() string
|
Address() string
|
||||||
|
ResetConnection()
|
||||||
}
|
}
|
||||||
|
|
||||||
type dnsCache interface {
|
type dnsCache interface {
|
||||||
@ -48,7 +49,7 @@ type Resolver struct {
|
|||||||
group singleflight.Group[*D.Msg]
|
group singleflight.Group[*D.Msg]
|
||||||
cache dnsCache
|
cache dnsCache
|
||||||
policy []dnsPolicy
|
policy []dnsPolicy
|
||||||
proxyServer []dnsClient
|
defaultResolver *Resolver
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resolver) LookupIPPrimaryIPv4(ctx context.Context, host string) (ips []netip.Addr, err error) {
|
func (r *Resolver) LookupIPPrimaryIPv4(ctx context.Context, host string) (ips []netip.Addr, err error) {
|
||||||
@ -376,6 +377,20 @@ func (r *Resolver) ClearCache() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Resolver) ResetConnection() {
|
||||||
|
if r != nil {
|
||||||
|
for _, c := range r.main {
|
||||||
|
c.ResetConnection()
|
||||||
|
}
|
||||||
|
for _, c := range r.fallback {
|
||||||
|
c.ResetConnection()
|
||||||
|
}
|
||||||
|
if dr := r.defaultResolver; dr != nil {
|
||||||
|
dr.ResetConnection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type NameServer struct {
|
type NameServer struct {
|
||||||
Net string
|
Net string
|
||||||
Addr string
|
Addr string
|
||||||
@ -425,16 +440,18 @@ type Config struct {
|
|||||||
CacheAlgorithm string
|
CacheAlgorithm string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewResolver(config Config) *Resolver {
|
func (config Config) newCache() dnsCache {
|
||||||
var cache dnsCache
|
if config.CacheAlgorithm == "" || config.CacheAlgorithm == "lru" {
|
||||||
if config.CacheAlgorithm == "lru" {
|
return lru.New(lru.WithSize[string, *D.Msg](4096), lru.WithStale[string, *D.Msg](true))
|
||||||
cache = lru.New(lru.WithSize[string, *D.Msg](4096), lru.WithStale[string, *D.Msg](true))
|
|
||||||
} else {
|
} else {
|
||||||
cache = arc.New(arc.WithSize[string, *D.Msg](4096))
|
return arc.New(arc.WithSize[string, *D.Msg](4096))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewResolver(config Config) (r *Resolver, pr *Resolver) {
|
||||||
defaultResolver := &Resolver{
|
defaultResolver := &Resolver{
|
||||||
main: transform(config.Default, nil),
|
main: transform(config.Default, nil),
|
||||||
cache: cache,
|
cache: config.newCache(),
|
||||||
ipv6Timeout: time.Duration(config.IPv6Timeout) * time.Millisecond,
|
ipv6Timeout: time.Duration(config.IPv6Timeout) * time.Millisecond,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -465,27 +482,29 @@ func NewResolver(config Config) *Resolver {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.CacheAlgorithm == "" || config.CacheAlgorithm == "lru" {
|
r = &Resolver{
|
||||||
cache = lru.New(lru.WithSize[string, *D.Msg](4096), lru.WithStale[string, *D.Msg](true))
|
|
||||||
} else {
|
|
||||||
cache = arc.New(arc.WithSize[string, *D.Msg](4096))
|
|
||||||
}
|
|
||||||
r := &Resolver{
|
|
||||||
ipv6: config.IPv6,
|
ipv6: config.IPv6,
|
||||||
main: cacheTransform(config.Main),
|
main: cacheTransform(config.Main),
|
||||||
cache: cache,
|
cache: config.newCache(),
|
||||||
hosts: config.Hosts,
|
hosts: config.Hosts,
|
||||||
ipv6Timeout: time.Duration(config.IPv6Timeout) * time.Millisecond,
|
ipv6Timeout: time.Duration(config.IPv6Timeout) * time.Millisecond,
|
||||||
}
|
}
|
||||||
|
r.defaultResolver = defaultResolver
|
||||||
|
|
||||||
|
if len(config.ProxyServer) != 0 {
|
||||||
|
pr = &Resolver{
|
||||||
|
ipv6: config.IPv6,
|
||||||
|
main: cacheTransform(config.ProxyServer),
|
||||||
|
cache: config.newCache(),
|
||||||
|
hosts: config.Hosts,
|
||||||
|
ipv6Timeout: time.Duration(config.IPv6Timeout) * time.Millisecond,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(config.Fallback) != 0 {
|
if len(config.Fallback) != 0 {
|
||||||
r.fallback = cacheTransform(config.Fallback)
|
r.fallback = cacheTransform(config.Fallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(config.ProxyServer) != 0 {
|
|
||||||
r.proxyServer = cacheTransform(config.ProxyServer)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(config.Policy) != 0 {
|
if len(config.Policy) != 0 {
|
||||||
r.policy = make([]dnsPolicy, 0)
|
r.policy = make([]dnsPolicy, 0)
|
||||||
|
|
||||||
@ -516,18 +535,7 @@ func NewResolver(config Config) *Resolver {
|
|||||||
r.fallbackIPFilters = config.FallbackIPFilter
|
r.fallbackIPFilters = config.FallbackIPFilter
|
||||||
r.fallbackDomainFilters = config.FallbackDomainFilter
|
r.fallbackDomainFilters = config.FallbackDomainFilter
|
||||||
|
|
||||||
return r
|
return
|
||||||
}
|
|
||||||
|
|
||||||
func NewProxyServerHostResolver(old *Resolver) *Resolver {
|
|
||||||
r := &Resolver{
|
|
||||||
ipv6: old.ipv6,
|
|
||||||
main: old.proxyServer,
|
|
||||||
cache: old.cache,
|
|
||||||
hosts: old.hosts,
|
|
||||||
ipv6Timeout: old.ipv6Timeout,
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var ParseNameServer func(servers []string) ([]NameServer, error) // define in config/config.go
|
var ParseNameServer func(servers []string) ([]NameServer, error) // define in config/config.go
|
||||||
|
@ -69,3 +69,5 @@ func (c *systemClient) getDnsClients() ([]dnsClient, error) {
|
|||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *systemClient) ResetConnection() {}
|
||||||
|
@ -118,6 +118,8 @@ func ApplyConfig(cfg *config.Config, force bool) {
|
|||||||
tunnel.OnRunning()
|
tunnel.OnRunning()
|
||||||
hcCompatibleProvider(cfg.Providers)
|
hcCompatibleProvider(cfg.Providers)
|
||||||
initExternalUI()
|
initExternalUI()
|
||||||
|
|
||||||
|
resolver.ResetConnection()
|
||||||
}
|
}
|
||||||
|
|
||||||
func initInnerTcp() {
|
func initInnerTcp() {
|
||||||
@ -253,8 +255,7 @@ func updateDNS(c *config.DNS, generalIPv6 bool) {
|
|||||||
CacheAlgorithm: c.CacheAlgorithm,
|
CacheAlgorithm: c.CacheAlgorithm,
|
||||||
}
|
}
|
||||||
|
|
||||||
r := dns.NewResolver(cfg)
|
r, pr := dns.NewResolver(cfg)
|
||||||
pr := dns.NewProxyServerHostResolver(r)
|
|
||||||
m := dns.NewEnhancer(cfg)
|
m := dns.NewEnhancer(cfg)
|
||||||
|
|
||||||
// reuse cache of old host mapper
|
// reuse cache of old host mapper
|
||||||
|
@ -440,6 +440,10 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis
|
|||||||
|
|
||||||
//l.openAndroidHotspot(tunOptions)
|
//l.openAndroidHotspot(tunOptions)
|
||||||
|
|
||||||
|
if !l.options.AutoDetectInterface {
|
||||||
|
resolver.ResetConnection()
|
||||||
|
}
|
||||||
|
|
||||||
if options.FileDescriptor != 0 {
|
if options.FileDescriptor != 0 {
|
||||||
tunName = fmt.Sprintf("%s(fd=%d)", tunName, options.FileDescriptor)
|
tunName = fmt.Sprintf("%s(fd=%d)", tunName, options.FileDescriptor)
|
||||||
}
|
}
|
||||||
@ -507,6 +511,7 @@ func (l *Listener) FlushDefaultInterface() {
|
|||||||
if old := dialer.DefaultInterface.Swap(autoDetectInterfaceName); old != autoDetectInterfaceName {
|
if old := dialer.DefaultInterface.Swap(autoDetectInterfaceName); old != autoDetectInterfaceName {
|
||||||
log.Warnln("[TUN] default interface changed by monitor, %s => %s", old, autoDetectInterfaceName)
|
log.Warnln("[TUN] default interface changed by monitor, %s => %s", old, autoDetectInterfaceName)
|
||||||
iface.FlushCache()
|
iface.FlushCache()
|
||||||
|
resolver.ResetConnection() // reset resolver's connection after default interface changed
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user