mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2024-11-09 02:41:22 +08:00
Compare commits
17 Commits
fc9d5cfee9
...
3e966e82c7
Author | SHA1 | Date | |
---|---|---|---|
|
3e966e82c7 | ||
|
b9171ade7f | ||
|
95af5f7325 | ||
|
ca3f1ebae6 | ||
|
4437c8861c | ||
|
57725078e0 | ||
|
08dcef80bf | ||
|
9fd63fe938 | ||
|
8e6eb70e71 | ||
|
9937ae1002 | ||
|
8f5a86410c | ||
|
9286e21026 | ||
|
c63a851bba | ||
|
4a16d22398 | ||
|
990de84391 | ||
|
ecd8facd81 | ||
|
a330fa1506 |
@ -10,6 +10,7 @@ import (
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/metacubex/mihomo/common/atomic"
|
||||
@ -18,6 +19,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/ca"
|
||||
"github.com/metacubex/mihomo/component/dialer"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
"github.com/puzpuzpuz/xsync/v3"
|
||||
)
|
||||
|
||||
@ -260,10 +262,18 @@ func (p *Proxy) URLTest(ctx context.Context, url string, expectedStatus utils.In
|
||||
|
||||
if unifiedDelay {
|
||||
second := time.Now()
|
||||
resp, err = client.Do(req)
|
||||
if err == nil {
|
||||
var ignoredErr error
|
||||
var secondResp *http.Response
|
||||
secondResp, ignoredErr = client.Do(req)
|
||||
if ignoredErr == nil {
|
||||
resp = secondResp
|
||||
_ = resp.Body.Close()
|
||||
start = second
|
||||
} else {
|
||||
if strings.HasPrefix(url, "http://") {
|
||||
log.Errorln("%s failed to get the second response from %s: %v", p.Name(), url, ignoredErr)
|
||||
log.Warnln("It is recommended to use HTTPS for provider.health-check.url and group.url to ensure better reliability. Due to some proxy providers hijacking test addresses and not being compatible with repeated HEAD requests, using HTTP may result in failed tests.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
opts = append(opts, dialer.WithResolver(resolver.DefaultResolver))
|
||||
opts = append(opts, dialer.WithResolver(resolver.DirectHostResolver))
|
||||
c, err := dialer.DialContext(ctx, "tcp", metadata.RemoteAddress(), d.Base.DialOptions(opts...)...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -49,7 +49,7 @@ func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata,
|
||||
}
|
||||
// net.UDPConn.WriteTo only working with *net.UDPAddr, so we need a net.UDPAddr
|
||||
if !metadata.Resolved() {
|
||||
ip, err := resolver.ResolveIPWithResolver(ctx, metadata.Host, resolver.DefaultResolver)
|
||||
ip, err := resolver.ResolveIPWithResolver(ctx, metadata.Host, resolver.DirectHostResolver)
|
||||
if err != nil {
|
||||
return nil, errors.New("can't resolve ip")
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ func (h *Hysteria) ListenPacketContext(ctx context.Context, metadata *C.Metadata
|
||||
func (h *Hysteria) genHdc(ctx context.Context, opts ...dialer.Option) utils.PacketDialer {
|
||||
return &hyDialerWithContext{
|
||||
ctx: context.Background(),
|
||||
hyDialer: func(network string) (net.PacketConn, error) {
|
||||
hyDialer: func(network string, rAddr net.Addr) (net.PacketConn, error) {
|
||||
var err error
|
||||
var cDialer C.Dialer = dialer.NewDialer(h.Base.DialOptions(opts...)...)
|
||||
if len(h.option.DialerProxy) > 0 {
|
||||
@ -78,7 +78,7 @@ func (h *Hysteria) genHdc(ctx context.Context, opts ...dialer.Option) utils.Pack
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
rAddrPort, _ := netip.ParseAddrPort(h.Addr())
|
||||
rAddrPort, _ := netip.ParseAddrPort(rAddr.String())
|
||||
return cDialer.ListenPacket(ctx, network, "", rAddrPort)
|
||||
},
|
||||
remoteAddr: func(addr string) (net.Addr, error) {
|
||||
@ -131,11 +131,7 @@ func (c *HysteriaOption) Speed() (uint64, uint64, error) {
|
||||
}
|
||||
|
||||
func NewHysteria(option HysteriaOption) (*Hysteria, error) {
|
||||
clientTransport := &transport.ClientTransport{
|
||||
Dialer: &net.Dialer{
|
||||
Timeout: 8 * time.Second,
|
||||
},
|
||||
}
|
||||
clientTransport := &transport.ClientTransport{}
|
||||
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
|
||||
ports := option.Ports
|
||||
|
||||
@ -284,7 +280,7 @@ func (c *hyPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||
}
|
||||
|
||||
type hyDialerWithContext struct {
|
||||
hyDialer func(network string) (net.PacketConn, error)
|
||||
hyDialer func(network string, rAddr net.Addr) (net.PacketConn, error)
|
||||
ctx context.Context
|
||||
remoteAddr func(host string) (net.Addr, error)
|
||||
}
|
||||
@ -294,7 +290,7 @@ func (h *hyDialerWithContext) ListenPacket(rAddr net.Addr) (net.PacketConn, erro
|
||||
if addrPort, err := netip.ParseAddrPort(rAddr.String()); err == nil {
|
||||
network = dialer.ParseNetwork(network, addrPort.Addr())
|
||||
}
|
||||
return h.hyDialer(network)
|
||||
return h.hyDialer(network, rAddr)
|
||||
}
|
||||
|
||||
func (h *hyDialerWithContext) Context() context.Context {
|
||||
|
@ -55,7 +55,7 @@ func resolveUDPAddr(ctx context.Context, network, address string) (*net.UDPAddr,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ip, err := resolver.ResolveProxyServerHost(ctx, host)
|
||||
ip, err := resolver.ResolveIPWithResolver(ctx, host, resolver.ProxyServerHostResolver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -71,12 +71,12 @@ func resolveUDPAddrWithPrefer(ctx context.Context, network, address string, pref
|
||||
var fallback netip.Addr
|
||||
switch prefer {
|
||||
case C.IPv4Only:
|
||||
ip, err = resolver.ResolveIPv4ProxyServerHost(ctx, host)
|
||||
ip, err = resolver.ResolveIPv4WithResolver(ctx, host, resolver.ProxyServerHostResolver)
|
||||
case C.IPv6Only:
|
||||
ip, err = resolver.ResolveIPv6ProxyServerHost(ctx, host)
|
||||
ip, err = resolver.ResolveIPv6WithResolver(ctx, host, resolver.ProxyServerHostResolver)
|
||||
case C.IPv6Prefer:
|
||||
var ips []netip.Addr
|
||||
ips, err = resolver.LookupIPProxyServerHost(ctx, host)
|
||||
ips, err = resolver.LookupIPWithResolver(ctx, host, resolver.ProxyServerHostResolver)
|
||||
if err == nil {
|
||||
for _, addr := range ips {
|
||||
if addr.Is6() {
|
||||
@ -92,7 +92,7 @@ func resolveUDPAddrWithPrefer(ctx context.Context, network, address string, pref
|
||||
default:
|
||||
// C.IPv4Prefer, C.DualStack and other
|
||||
var ips []netip.Addr
|
||||
ips, err = resolver.LookupIPProxyServerHost(ctx, host)
|
||||
ips, err = resolver.LookupIPWithResolver(ctx, host, resolver.ProxyServerHostResolver)
|
||||
if err == nil {
|
||||
for _, addr := range ips {
|
||||
if addr.Is4() {
|
||||
|
@ -44,7 +44,7 @@ type WireGuard struct {
|
||||
device wireguardGoDevice
|
||||
tunDevice wireguard.Device
|
||||
dialer proxydialer.SingDialer
|
||||
resolver *dns.Resolver
|
||||
resolver resolver.Resolver
|
||||
refP *refProxyAdapter
|
||||
|
||||
initOk atomic.Bool
|
||||
@ -296,7 +296,7 @@ func NewWireGuard(option WireGuardOption) (*WireGuard, error) {
|
||||
for i := range nss {
|
||||
nss[i].ProxyAdapter = refP
|
||||
}
|
||||
outbound.resolver, _ = dns.NewResolver(dns.Config{
|
||||
outbound.resolver = dns.NewResolver(dns.Config{
|
||||
Main: nss,
|
||||
IPv6: has6,
|
||||
})
|
||||
|
@ -204,7 +204,7 @@ func strategyStickySessions(url string) strategyFn {
|
||||
for i := 1; i < maxRetry; i++ {
|
||||
proxy := proxies[nowIdx]
|
||||
if proxy.AliveForTestUrl(url) {
|
||||
if nowIdx != idx {
|
||||
if !has || nowIdx != idx {
|
||||
lruCache.Set(key, nowIdx)
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,9 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
@ -14,7 +12,7 @@ import (
|
||||
"github.com/metacubex/mihomo/adapter"
|
||||
"github.com/metacubex/mihomo/common/convert"
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
mihomoHttp "github.com/metacubex/mihomo/component/http"
|
||||
"github.com/metacubex/mihomo/component/profile/cachefile"
|
||||
"github.com/metacubex/mihomo/component/resource"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
types "github.com/metacubex/mihomo/constant/provider"
|
||||
@ -80,7 +78,9 @@ func (pp *proxySetProvider) Initial() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pp.getSubscriptionInfo()
|
||||
if subscriptionInfo := cachefile.Cache().GetSubscriptionInfo(pp.Name()); subscriptionInfo != "" {
|
||||
pp.SetSubscriptionInfo(subscriptionInfo)
|
||||
}
|
||||
pp.closeAllConnections()
|
||||
return nil
|
||||
}
|
||||
@ -117,35 +117,14 @@ func (pp *proxySetProvider) setProxies(proxies []C.Proxy) {
|
||||
}
|
||||
}
|
||||
|
||||
func (pp *proxySetProvider) getSubscriptionInfo() {
|
||||
if pp.VehicleType() != types.HTTP {
|
||||
return
|
||||
func (pp *proxySetProvider) SetSubscriptionInfo(userInfo string) {
|
||||
pp.subscriptionInfo = NewSubscriptionInfo(userInfo)
|
||||
}
|
||||
go func() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*90)
|
||||
defer cancel()
|
||||
resp, err := mihomoHttp.HttpRequestWithProxy(ctx, pp.Vehicle().Url(),
|
||||
http.MethodGet, nil, nil, pp.Vehicle().Proxy())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
userInfoStr := strings.TrimSpace(resp.Header.Get("subscription-userinfo"))
|
||||
if userInfoStr == "" {
|
||||
resp2, err := mihomoHttp.HttpRequestWithProxy(ctx, pp.Vehicle().Url(),
|
||||
http.MethodGet, http.Header{"User-Agent": {"Quantumultx"}}, nil, pp.Vehicle().Proxy())
|
||||
if err != nil {
|
||||
return
|
||||
func (pp *proxySetProvider) SetProvider(provider types.ProxyProvider) {
|
||||
if httpVehicle, ok := pp.Vehicle().(*resource.HTTPVehicle); ok {
|
||||
httpVehicle.SetProvider(provider)
|
||||
}
|
||||
defer resp2.Body.Close()
|
||||
userInfoStr = strings.TrimSpace(resp2.Header.Get("subscription-userinfo"))
|
||||
if userInfoStr == "" {
|
||||
return
|
||||
}
|
||||
}
|
||||
pp.subscriptionInfo = NewSubscriptionInfo(userInfoStr)
|
||||
}()
|
||||
}
|
||||
|
||||
func (pp *proxySetProvider) closeAllConnections() {
|
||||
@ -196,6 +175,9 @@ func NewProxySetProvider(name string, interval time.Duration, filter string, exc
|
||||
fetcher := resource.NewFetcher[[]C.Proxy](name, interval, vehicle, proxiesParseAndFilter(filter, excludeFilter, excludeTypeArray, filterRegs, excludeFilterReg, dialerProxy, override), proxiesOnUpdate(pd))
|
||||
pd.Fetcher = fetcher
|
||||
wrapper := &ProxySetProvider{pd}
|
||||
if httpVehicle, ok := vehicle.(*resource.HTTPVehicle); ok {
|
||||
httpVehicle.SetProvider(wrapper)
|
||||
}
|
||||
runtime.SetFinalizer(wrapper, (*ProxySetProvider).Close)
|
||||
return wrapper, nil
|
||||
}
|
||||
@ -205,6 +187,10 @@ func (pp *ProxySetProvider) Close() error {
|
||||
return pp.proxySetProvider.Close()
|
||||
}
|
||||
|
||||
func (pp *ProxySetProvider) SetProvider(provider types.ProxyProvider) {
|
||||
pp.proxySetProvider.SetProvider(provider)
|
||||
}
|
||||
|
||||
// CompatibleProvider for auto gc
|
||||
type CompatibleProvider struct {
|
||||
*compatibleProvider
|
||||
@ -213,6 +199,7 @@ type CompatibleProvider struct {
|
||||
type compatibleProvider struct {
|
||||
name string
|
||||
healthCheck *HealthCheck
|
||||
subscriptionInfo *SubscriptionInfo
|
||||
proxies []C.Proxy
|
||||
version uint32
|
||||
}
|
||||
@ -284,6 +271,10 @@ func (cp *compatibleProvider) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cp *compatibleProvider) SetSubscriptionInfo(userInfo string) {
|
||||
cp.subscriptionInfo = NewSubscriptionInfo(userInfo)
|
||||
}
|
||||
|
||||
func NewCompatibleProvider(name string, proxies []C.Proxy, hc *HealthCheck) (*CompatibleProvider, error) {
|
||||
if len(proxies) == 0 {
|
||||
return nil, errors.New("provider need one proxy at least")
|
||||
@ -313,7 +304,6 @@ func proxiesOnUpdate(pd *proxySetProvider) func([]C.Proxy) {
|
||||
return func(elm []C.Proxy) {
|
||||
pd.setProxies(elm)
|
||||
pd.version += 1
|
||||
pd.getSubscriptionInfo()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,7 @@ type SubscriptionInfo struct {
|
||||
}
|
||||
|
||||
func NewSubscriptionInfo(userinfo string) (si *SubscriptionInfo) {
|
||||
userinfo = strings.ToLower(userinfo)
|
||||
userinfo = strings.ReplaceAll(userinfo, " ", "")
|
||||
userinfo = strings.ReplaceAll(strings.ToLower(userinfo), " ", "")
|
||||
si = new(SubscriptionInfo)
|
||||
|
||||
for _, field := range strings.Split(userinfo, ";") {
|
||||
|
@ -340,27 +340,19 @@ func parseAddr(ctx context.Context, network, address string, preferResolver reso
|
||||
return nil, "-1", err
|
||||
}
|
||||
|
||||
if preferResolver == nil {
|
||||
preferResolver = resolver.ProxyServerHostResolver
|
||||
}
|
||||
|
||||
var ips []netip.Addr
|
||||
switch network {
|
||||
case "tcp4", "udp4":
|
||||
if preferResolver == nil {
|
||||
ips, err = resolver.LookupIPv4ProxyServerHost(ctx, host)
|
||||
} else {
|
||||
ips, err = resolver.LookupIPv4WithResolver(ctx, host, preferResolver)
|
||||
}
|
||||
case "tcp6", "udp6":
|
||||
if preferResolver == nil {
|
||||
ips, err = resolver.LookupIPv6ProxyServerHost(ctx, host)
|
||||
} else {
|
||||
ips, err = resolver.LookupIPv6WithResolver(ctx, host, preferResolver)
|
||||
}
|
||||
default:
|
||||
if preferResolver == nil {
|
||||
ips, err = resolver.LookupIPProxyServerHost(ctx, host)
|
||||
} else {
|
||||
ips, err = resolver.LookupIPWithResolver(ctx, host, preferResolver)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, "-1", fmt.Errorf("dns resolve failed: %w", err)
|
||||
}
|
||||
|
@ -1,29 +0,0 @@
|
||||
package dialer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/netip"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// We must use this DialContext to query DNS
|
||||
// when using net default resolver.
|
||||
net.DefaultResolver.PreferGo = true
|
||||
net.DefaultResolver.Dial = resolverDialContext
|
||||
}
|
||||
|
||||
func resolverDialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
d := &net.Dialer{}
|
||||
|
||||
interfaceName := DefaultInterface.Load()
|
||||
|
||||
if interfaceName != "" {
|
||||
dstIP, err := netip.ParseAddr(address)
|
||||
if err == nil {
|
||||
_ = bindIfaceToDialer(interfaceName, d, network, dstIP)
|
||||
}
|
||||
}
|
||||
|
||||
return d.DialContext(ctx, network, address)
|
||||
}
|
@ -12,6 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/metacubex/mihomo/component/ca"
|
||||
"github.com/metacubex/mihomo/component/dialer"
|
||||
"github.com/metacubex/mihomo/listener/inner"
|
||||
)
|
||||
|
||||
@ -71,8 +72,7 @@ func HttpRequestWithProxy(ctx context.Context, url, method string, header map[st
|
||||
if conn, err := inner.HandleTcp(address, specialProxy); err == nil {
|
||||
return conn, nil
|
||||
} else {
|
||||
d := net.Dialer{}
|
||||
return d.DialContext(ctx, network, address)
|
||||
return dialer.DialContext(ctx, network, address)
|
||||
}
|
||||
},
|
||||
TLSClientConfig: ca.GetGlobalTLSConfig(&tls.Config{}),
|
||||
|
@ -20,6 +20,7 @@ var (
|
||||
bucketSelected = []byte("selected")
|
||||
bucketFakeip = []byte("fakeip")
|
||||
bucketETag = []byte("etag")
|
||||
bucketSubscriptionInfo = []byte("subscriptioninfo")
|
||||
)
|
||||
|
||||
// CacheFile store and update the cache file
|
||||
|
41
component/profile/cachefile/subscriptioninfo.go
Normal file
41
component/profile/cachefile/subscriptioninfo.go
Normal file
@ -0,0 +1,41 @@
|
||||
package cachefile
|
||||
|
||||
import (
|
||||
"github.com/metacubex/mihomo/log"
|
||||
|
||||
"github.com/metacubex/bbolt"
|
||||
)
|
||||
|
||||
func (c *CacheFile) SetSubscriptionInfo(name string, userInfo string) {
|
||||
if c.DB == nil {
|
||||
return
|
||||
}
|
||||
|
||||
err := c.DB.Batch(func(t *bbolt.Tx) error {
|
||||
bucket, err := t.CreateBucketIfNotExists(bucketSubscriptionInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return bucket.Put([]byte(name), []byte(userInfo))
|
||||
})
|
||||
if err != nil {
|
||||
log.Warnln("[CacheFile] write cache to %s failed: %s", c.DB.Path(), err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
func (c *CacheFile) GetSubscriptionInfo(name string) (userInfo string) {
|
||||
if c.DB == nil {
|
||||
return
|
||||
}
|
||||
c.DB.View(func(t *bbolt.Tx) error {
|
||||
if bucket := t.Bucket(bucketSubscriptionInfo); bucket != nil {
|
||||
if v := bucket.Get([]byte(name)); v != nil {
|
||||
userInfo = string(v)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||
|
||||
package resolver
|
||||
|
||||
import _ "unsafe"
|
||||
|
||||
//go:linkname defaultNS net.defaultNS
|
||||
var defaultNS []string
|
||||
|
||||
func init() {
|
||||
defaultNS = []string{"114.114.114.114:53", "8.8.8.8:53"}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
//go:build !go1.22
|
||||
|
||||
// a simple standard lib fix from: https://github.com/golang/go/commit/33d4a5105cf2b2d549922e909e9239a48b8cefcc
|
||||
|
||||
package resolver
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/windows"
|
||||
_ "unsafe"
|
||||
)
|
||||
|
||||
//go:linkname testHookHostsPath net.testHookHostsPath
|
||||
var testHookHostsPath string
|
||||
|
||||
func init() {
|
||||
if dir, err := windows.GetSystemDirectory(); err == nil {
|
||||
testHookHostsPath = dir + "/Drivers/etc/hosts"
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"strings"
|
||||
"time"
|
||||
@ -20,9 +19,15 @@ var (
|
||||
// DefaultResolver aim to resolve ip
|
||||
DefaultResolver Resolver
|
||||
|
||||
// ProxyServerHostResolver resolve ip to proxies server host
|
||||
// ProxyServerHostResolver resolve ip for proxies server host, only nil when DefaultResolver is nil
|
||||
ProxyServerHostResolver Resolver
|
||||
|
||||
// DirectHostResolver resolve ip for direct outbound host, only nil when DefaultResolver is nil
|
||||
DirectHostResolver Resolver
|
||||
|
||||
// SystemResolver always using system dns, and was init in dns module
|
||||
SystemResolver Resolver
|
||||
|
||||
// DisableIPv6 means don't resolve ipv6 host
|
||||
// default value is true
|
||||
DisableIPv6 = true
|
||||
@ -72,14 +77,7 @@ func LookupIPv4WithResolver(ctx context.Context, host string, r Resolver) ([]net
|
||||
return r.LookupIPv4(ctx, host)
|
||||
}
|
||||
|
||||
ipAddrs, err := net.DefaultResolver.LookupNetIP(ctx, "ip4", host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(ipAddrs) == 0 {
|
||||
return nil, ErrIPNotFound
|
||||
}
|
||||
|
||||
return ipAddrs, nil
|
||||
return SystemResolver.LookupIPv4(ctx, host)
|
||||
}
|
||||
|
||||
// LookupIPv4 with a host, return ipv4 list
|
||||
@ -128,14 +126,7 @@ func LookupIPv6WithResolver(ctx context.Context, host string, r Resolver) ([]net
|
||||
return r.LookupIPv6(ctx, host)
|
||||
}
|
||||
|
||||
ipAddrs, err := net.DefaultResolver.LookupNetIP(ctx, "ip6", host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(ipAddrs) == 0 {
|
||||
return nil, ErrIPNotFound
|
||||
}
|
||||
|
||||
return ipAddrs, nil
|
||||
return SystemResolver.LookupIPv6(ctx, host)
|
||||
}
|
||||
|
||||
// LookupIPv6 with a host, return ipv6 list
|
||||
@ -177,14 +168,7 @@ func LookupIPWithResolver(ctx context.Context, host string, r Resolver) ([]netip
|
||||
return []netip.Addr{ip}, nil
|
||||
}
|
||||
|
||||
ips, err := net.DefaultResolver.LookupNetIP(ctx, "ip", host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(ips) == 0 {
|
||||
return nil, ErrIPNotFound
|
||||
}
|
||||
|
||||
return ips, nil
|
||||
return SystemResolver.LookupIP(ctx, host)
|
||||
}
|
||||
|
||||
// LookupIP with a host, return ip
|
||||
@ -212,58 +196,10 @@ func ResolveIP(ctx context.Context, host string) (netip.Addr, error) {
|
||||
return ResolveIPWithResolver(ctx, host, DefaultResolver)
|
||||
}
|
||||
|
||||
// ResolveIPv4ProxyServerHost proxies server host only
|
||||
func ResolveIPv4ProxyServerHost(ctx context.Context, host string) (netip.Addr, error) {
|
||||
if ProxyServerHostResolver != nil {
|
||||
return ResolveIPv4WithResolver(ctx, host, ProxyServerHostResolver)
|
||||
}
|
||||
return ResolveIPv4(ctx, host)
|
||||
}
|
||||
|
||||
// ResolveIPv6ProxyServerHost proxies server host only
|
||||
func ResolveIPv6ProxyServerHost(ctx context.Context, host string) (netip.Addr, error) {
|
||||
if ProxyServerHostResolver != nil {
|
||||
return ResolveIPv6WithResolver(ctx, host, ProxyServerHostResolver)
|
||||
}
|
||||
return ResolveIPv6(ctx, host)
|
||||
}
|
||||
|
||||
// ResolveProxyServerHost proxies server host only
|
||||
func ResolveProxyServerHost(ctx context.Context, host string) (netip.Addr, error) {
|
||||
if ProxyServerHostResolver != nil {
|
||||
return ResolveIPWithResolver(ctx, host, ProxyServerHostResolver)
|
||||
}
|
||||
return ResolveIP(ctx, host)
|
||||
}
|
||||
|
||||
func LookupIPv6ProxyServerHost(ctx context.Context, host string) ([]netip.Addr, error) {
|
||||
if ProxyServerHostResolver != nil {
|
||||
return LookupIPv6WithResolver(ctx, host, ProxyServerHostResolver)
|
||||
}
|
||||
return LookupIPv6(ctx, host)
|
||||
}
|
||||
|
||||
func LookupIPv4ProxyServerHost(ctx context.Context, host string) ([]netip.Addr, error) {
|
||||
if ProxyServerHostResolver != nil {
|
||||
return LookupIPv4WithResolver(ctx, host, ProxyServerHostResolver)
|
||||
}
|
||||
return LookupIPv4(ctx, host)
|
||||
}
|
||||
|
||||
func LookupIPProxyServerHost(ctx context.Context, host string) ([]netip.Addr, error) {
|
||||
if ProxyServerHostResolver != nil {
|
||||
return LookupIPWithResolver(ctx, host, ProxyServerHostResolver)
|
||||
}
|
||||
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) {
|
||||
|
@ -89,6 +89,7 @@ type HTTPVehicle struct {
|
||||
proxy string
|
||||
header http.Header
|
||||
timeout time.Duration
|
||||
provider types.ProxyProvider
|
||||
}
|
||||
|
||||
func (h *HTTPVehicle) Url() string {
|
||||
@ -111,6 +112,10 @@ func (h *HTTPVehicle) Write(buf []byte) error {
|
||||
return safeWrite(h.path, buf)
|
||||
}
|
||||
|
||||
func (h *HTTPVehicle) SetProvider(provider types.ProxyProvider) {
|
||||
h.provider = provider
|
||||
}
|
||||
|
||||
func (h *HTTPVehicle) Read(ctx context.Context, oldHash utils.HashType) (buf []byte, hash utils.HashType, err error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, h.timeout)
|
||||
defer cancel()
|
||||
@ -133,6 +138,12 @@ func (h *HTTPVehicle) Read(ctx context.Context, oldHash utils.HashType) (buf []b
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if subscriptionInfo := resp.Header.Get("subscription-userinfo"); h.provider != nil && subscriptionInfo != "" {
|
||||
cachefile.Cache().SetSubscriptionInfo(h.provider.Name(), subscriptionInfo)
|
||||
h.provider.SetSubscriptionInfo(subscriptionInfo)
|
||||
}
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
||||
if setIfNoneMatch && resp.StatusCode == http.StatusNotModified {
|
||||
return nil, oldHash, nil
|
||||
|
@ -229,20 +229,22 @@ func UpdateGeoDatabases() error {
|
||||
}
|
||||
|
||||
func getUpdateTime() (err error, time time.Time) {
|
||||
var fileInfo os.FileInfo
|
||||
if geodata.GeodataMode() {
|
||||
fileInfo, err = os.Stat(C.Path.GeoIP())
|
||||
if err != nil {
|
||||
return err, time
|
||||
filesToCheck := []string{
|
||||
C.Path.GeoIP(),
|
||||
C.Path.MMDB(),
|
||||
C.Path.ASN(),
|
||||
C.Path.GeoSite(),
|
||||
}
|
||||
} else {
|
||||
fileInfo, err = os.Stat(C.Path.MMDB())
|
||||
if err != nil {
|
||||
return err, time
|
||||
|
||||
for _, file := range filesToCheck {
|
||||
var fileInfo os.FileInfo
|
||||
fileInfo, err = os.Stat(file)
|
||||
if err == nil {
|
||||
return nil, fileInfo.ModTime()
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fileInfo.ModTime()
|
||||
return
|
||||
}
|
||||
|
||||
func RegisterGeoUpdater() {
|
||||
|
@ -14,24 +14,69 @@ import (
|
||||
"github.com/metacubex/mihomo/log"
|
||||
)
|
||||
|
||||
var (
|
||||
ExternalUIURL string
|
||||
ExternalUIPath string
|
||||
AutoDownloadUI bool
|
||||
)
|
||||
type UIUpdater struct {
|
||||
externalUIURL string
|
||||
externalUIPath string
|
||||
autoDownloadUI bool
|
||||
|
||||
var xdMutex sync.Mutex
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func DownloadUI() error {
|
||||
xdMutex.Lock()
|
||||
defer xdMutex.Unlock()
|
||||
var DefaultUiUpdater = &UIUpdater{}
|
||||
|
||||
err := prepareUIPath()
|
||||
func NewUiUpdater(externalUI, externalUIURL, externalUIName string) *UIUpdater {
|
||||
updater := &UIUpdater{}
|
||||
// checkout externalUI exist
|
||||
if externalUI != "" {
|
||||
updater.autoDownloadUI = true
|
||||
updater.externalUIPath = C.Path.Resolve(externalUI)
|
||||
} else {
|
||||
// default externalUI path
|
||||
updater.externalUIPath = path.Join(C.Path.HomeDir(), "ui")
|
||||
}
|
||||
|
||||
// checkout UIpath/name exist
|
||||
if externalUIName != "" {
|
||||
updater.autoDownloadUI = true
|
||||
updater.externalUIPath = path.Join(updater.externalUIPath, externalUIName)
|
||||
}
|
||||
|
||||
if externalUIURL != "" {
|
||||
updater.externalUIURL = externalUIURL
|
||||
}
|
||||
return updater
|
||||
}
|
||||
|
||||
func (u *UIUpdater) AutoDownloadUI() {
|
||||
u.mutex.Lock()
|
||||
defer u.mutex.Unlock()
|
||||
if u.autoDownloadUI {
|
||||
dirEntries, _ := os.ReadDir(u.externalUIPath)
|
||||
if len(dirEntries) > 0 {
|
||||
log.Infoln("UI already exists, skip downloading")
|
||||
} else {
|
||||
log.Infoln("External UI downloading ...")
|
||||
err := u.downloadUI()
|
||||
if err != nil {
|
||||
log.Errorln("Error downloading UI: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UIUpdater) DownloadUI() error {
|
||||
u.mutex.Lock()
|
||||
defer u.mutex.Unlock()
|
||||
return u.downloadUI()
|
||||
}
|
||||
|
||||
func (u *UIUpdater) downloadUI() error {
|
||||
err := u.prepareUIPath()
|
||||
if err != nil {
|
||||
return fmt.Errorf("prepare UI path failed: %w", err)
|
||||
}
|
||||
|
||||
data, err := downloadForBytes(ExternalUIURL)
|
||||
data, err := downloadForBytes(u.externalUIURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't download file: %w", err)
|
||||
}
|
||||
@ -42,7 +87,7 @@ func DownloadUI() error {
|
||||
}
|
||||
defer os.Remove(saved)
|
||||
|
||||
err = cleanup(ExternalUIPath)
|
||||
err = cleanup(u.externalUIPath)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return fmt.Errorf("cleanup exist file error: %w", err)
|
||||
@ -54,18 +99,18 @@ func DownloadUI() error {
|
||||
return fmt.Errorf("can't extract zip file: %w", err)
|
||||
}
|
||||
|
||||
err = os.Rename(unzipFolder, ExternalUIPath)
|
||||
err = os.Rename(unzipFolder, u.externalUIPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("rename UI folder failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func prepareUIPath() error {
|
||||
if _, err := os.Stat(ExternalUIPath); os.IsNotExist(err) {
|
||||
log.Infoln("dir %s does not exist, creating", ExternalUIPath)
|
||||
if err := os.MkdirAll(ExternalUIPath, os.ModePerm); err != nil {
|
||||
log.Warnln("create dir %s error: %s", ExternalUIPath, err)
|
||||
func (u *UIUpdater) prepareUIPath() error {
|
||||
if _, err := os.Stat(u.externalUIPath); os.IsNotExist(err) {
|
||||
log.Infoln("dir %s does not exist, creating", u.externalUIPath)
|
||||
if err := os.MkdirAll(u.externalUIPath, os.ModePerm); err != nil {
|
||||
log.Warnln("create dir %s error: %s", u.externalUIPath, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -7,9 +7,9 @@ import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/metacubex/mihomo/adapter"
|
||||
"github.com/metacubex/mihomo/adapter/outbound"
|
||||
@ -20,15 +20,10 @@ import (
|
||||
"github.com/metacubex/mihomo/component/cidr"
|
||||
"github.com/metacubex/mihomo/component/fakeip"
|
||||
"github.com/metacubex/mihomo/component/geodata"
|
||||
mihomoHttp "github.com/metacubex/mihomo/component/http"
|
||||
"github.com/metacubex/mihomo/component/keepalive"
|
||||
P "github.com/metacubex/mihomo/component/process"
|
||||
"github.com/metacubex/mihomo/component/resolver"
|
||||
"github.com/metacubex/mihomo/component/resource"
|
||||
"github.com/metacubex/mihomo/component/sniffer"
|
||||
tlsC "github.com/metacubex/mihomo/component/tls"
|
||||
"github.com/metacubex/mihomo/component/trie"
|
||||
"github.com/metacubex/mihomo/component/updater"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
providerTypes "github.com/metacubex/mihomo/constant/provider"
|
||||
snifferTypes "github.com/metacubex/mihomo/constant/sniffer"
|
||||
@ -67,6 +62,9 @@ type General struct {
|
||||
GlobalClientFingerprint string `json:"global-client-fingerprint"`
|
||||
GlobalUA string `json:"global-ua"`
|
||||
ETagSupport bool `json:"etag-support"`
|
||||
KeepAliveIdle int `json:"keep-alive-idle"`
|
||||
KeepAliveInterval int `json:"keep-alive-interval"`
|
||||
DisableKeepAlive bool `json:"disable-keep-alive"`
|
||||
}
|
||||
|
||||
// Inbound config
|
||||
@ -105,6 +103,8 @@ type Controller struct {
|
||||
ExternalControllerUnix string
|
||||
ExternalControllerPipe string
|
||||
ExternalUI string
|
||||
ExternalUIURL string
|
||||
ExternalUIName string
|
||||
ExternalDohServer string
|
||||
Secret string
|
||||
Cors Cors
|
||||
@ -160,6 +160,8 @@ type DNS struct {
|
||||
Hosts *trie.DomainTrie[resolver.HostValue]
|
||||
NameServerPolicy []dns.Policy
|
||||
ProxyServerNameserver []dns.NameServer
|
||||
DirectNameServer []dns.NameServer
|
||||
DirectFollowPolicy bool
|
||||
}
|
||||
|
||||
// Profile config
|
||||
@ -222,6 +224,8 @@ type RawDNS struct {
|
||||
CacheAlgorithm string `yaml:"cache-algorithm" json:"cache-algorithm"`
|
||||
NameServerPolicy *orderedmap.OrderedMap[string, any] `yaml:"nameserver-policy" json:"nameserver-policy"`
|
||||
ProxyServerNameserver []string `yaml:"proxy-server-nameserver" json:"proxy-server-nameserver"`
|
||||
DirectNameServer []string `yaml:"direct-nameserver" json:"direct-nameserver"`
|
||||
DirectNameServerFollowPolicy bool `yaml:"direct-nameserver-follow-policy" json:"direct-nameserver-follow-policy"`
|
||||
}
|
||||
|
||||
type RawFallbackFilter struct {
|
||||
@ -582,10 +586,11 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
|
||||
}
|
||||
config.General = general
|
||||
|
||||
if len(config.General.GlobalClientFingerprint) != 0 {
|
||||
log.Debugln("GlobalClientFingerprint: %s", config.General.GlobalClientFingerprint)
|
||||
tlsC.SetGlobalUtlsClient(config.General.GlobalClientFingerprint)
|
||||
}
|
||||
// We need to temporarily apply some configuration in general and roll back after parsing the complete configuration.
|
||||
// The loading and downloading of geodata in the parseRules and parseRuleProviders rely on these.
|
||||
// This implementation is very disgusting, but there is currently no better solution
|
||||
rollback := temporaryUpdateGeneral(config.General)
|
||||
defer rollback()
|
||||
|
||||
controller, err := parseController(rawCfg)
|
||||
if err != nil {
|
||||
@ -701,46 +706,10 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
//go:linkname temporaryUpdateGeneral
|
||||
func temporaryUpdateGeneral(general *General) func()
|
||||
|
||||
func parseGeneral(cfg *RawConfig) (*General, error) {
|
||||
updater.SetGeoAutoUpdate(cfg.GeoAutoUpdate)
|
||||
updater.SetGeoUpdateInterval(cfg.GeoUpdateInterval)
|
||||
geodata.SetGeodataMode(cfg.GeodataMode)
|
||||
geodata.SetLoader(cfg.GeodataLoader)
|
||||
geodata.SetSiteMatcher(cfg.GeositeMatcher)
|
||||
geodata.SetGeoIpUrl(cfg.GeoXUrl.GeoIp)
|
||||
geodata.SetGeoSiteUrl(cfg.GeoXUrl.GeoSite)
|
||||
geodata.SetMmdbUrl(cfg.GeoXUrl.Mmdb)
|
||||
geodata.SetASNUrl(cfg.GeoXUrl.ASN)
|
||||
mihomoHttp.SetUA(cfg.GlobalUA)
|
||||
resource.SetETag(cfg.ETagSupport)
|
||||
|
||||
if cfg.KeepAliveIdle != 0 {
|
||||
keepalive.SetKeepAliveIdle(time.Duration(cfg.KeepAliveIdle) * time.Second)
|
||||
}
|
||||
if cfg.KeepAliveInterval != 0 {
|
||||
keepalive.SetKeepAliveInterval(time.Duration(cfg.KeepAliveInterval) * time.Second)
|
||||
}
|
||||
keepalive.SetDisableKeepAlive(cfg.DisableKeepAlive)
|
||||
|
||||
// checkout externalUI exist
|
||||
if cfg.ExternalUI != "" {
|
||||
updater.AutoDownloadUI = true
|
||||
updater.ExternalUIPath = C.Path.Resolve(cfg.ExternalUI)
|
||||
} else {
|
||||
// default externalUI path
|
||||
updater.ExternalUIPath = path.Join(C.Path.HomeDir(), "ui")
|
||||
}
|
||||
|
||||
// checkout UIpath/name exist
|
||||
if cfg.ExternalUIName != "" {
|
||||
updater.AutoDownloadUI = true
|
||||
updater.ExternalUIPath = path.Join(updater.ExternalUIPath, cfg.ExternalUIName)
|
||||
}
|
||||
|
||||
if cfg.ExternalUIURL != "" {
|
||||
updater.ExternalUIURL = cfg.ExternalUIURL
|
||||
}
|
||||
|
||||
return &General{
|
||||
Inbound: Inbound{
|
||||
Port: cfg.Port,
|
||||
@ -774,11 +743,15 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
|
||||
GeoUpdateInterval: cfg.GeoUpdateInterval,
|
||||
GeodataMode: cfg.GeodataMode,
|
||||
GeodataLoader: cfg.GeodataLoader,
|
||||
GeositeMatcher: cfg.GeositeMatcher,
|
||||
TCPConcurrent: cfg.TCPConcurrent,
|
||||
FindProcessMode: cfg.FindProcessMode,
|
||||
GlobalClientFingerprint: cfg.GlobalClientFingerprint,
|
||||
GlobalUA: cfg.GlobalUA,
|
||||
ETagSupport: cfg.ETagSupport,
|
||||
KeepAliveIdle: cfg.KeepAliveIdle,
|
||||
KeepAliveInterval: cfg.KeepAliveInterval,
|
||||
DisableKeepAlive: cfg.DisableKeepAlive,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -786,6 +759,8 @@ func parseController(cfg *RawConfig) (*Controller, error) {
|
||||
return &Controller{
|
||||
ExternalController: cfg.ExternalController,
|
||||
ExternalUI: cfg.ExternalUI,
|
||||
ExternalUIURL: cfg.ExternalUIURL,
|
||||
ExternalUIName: cfg.ExternalUIName,
|
||||
Secret: cfg.Secret,
|
||||
ExternalControllerPipe: cfg.ExternalControllerPipe,
|
||||
ExternalControllerUnix: cfg.ExternalControllerUnix,
|
||||
@ -1423,6 +1398,11 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if dnsCfg.DirectNameServer, err = parseNameServer(cfg.DirectNameServer, false, cfg.PreferH3); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dnsCfg.DirectFollowPolicy = cfg.DirectNameServerFollowPolicy
|
||||
|
||||
if len(cfg.DefaultNameserver) == 0 {
|
||||
return nil, errors.New("default nameserver should have at least one nameserver")
|
||||
}
|
||||
|
@ -213,6 +213,8 @@ func (at AdapterType) String() string {
|
||||
return "WireGuard"
|
||||
case Tuic:
|
||||
return "Tuic"
|
||||
case Ssh:
|
||||
return "Ssh"
|
||||
|
||||
case Relay:
|
||||
return "Relay"
|
||||
@ -224,8 +226,6 @@ func (at AdapterType) String() string {
|
||||
return "URLTest"
|
||||
case LoadBalance:
|
||||
return "LoadBalance"
|
||||
case Ssh:
|
||||
return "Ssh"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
|
@ -81,6 +81,7 @@ type ProxyProvider interface {
|
||||
Version() uint32
|
||||
RegisterHealthCheckTask(url string, expectedStatus utils.IntRanges[uint16], filter string, interval uint)
|
||||
HealthCheckURL() string
|
||||
SetSubscriptionInfo(userInfo string)
|
||||
}
|
||||
|
||||
// RuleProvider interface
|
||||
|
@ -12,6 +12,9 @@ func FlushCacheWithDefaultResolver() {
|
||||
if r := resolver.DefaultResolver; r != nil {
|
||||
r.ClearCache()
|
||||
}
|
||||
if r := resolver.SystemResolver; r != nil {
|
||||
r.ClearCache()
|
||||
}
|
||||
resolver.ResetConnection()
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,6 @@ import (
|
||||
"github.com/metacubex/mihomo/component/resolver"
|
||||
"github.com/metacubex/mihomo/component/trie"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
|
||||
D "github.com/miekg/dns"
|
||||
@ -428,6 +427,8 @@ type Config struct {
|
||||
Main, Fallback []NameServer
|
||||
Default []NameServer
|
||||
ProxyServer []NameServer
|
||||
DirectServer []NameServer
|
||||
DirectFollowPolicy bool
|
||||
IPv6 bool
|
||||
IPv6Timeout uint
|
||||
EnhancedMode C.DNSMode
|
||||
@ -436,7 +437,6 @@ type Config struct {
|
||||
Pool *fakeip.Pool
|
||||
Hosts *trie.DomainTrie[resolver.HostValue]
|
||||
Policy []Policy
|
||||
Tunnel provider.Tunnel
|
||||
CacheAlgorithm string
|
||||
}
|
||||
|
||||
@ -448,7 +448,25 @@ func (config Config) newCache() dnsCache {
|
||||
}
|
||||
}
|
||||
|
||||
func NewResolver(config Config) (r *Resolver, pr *Resolver) {
|
||||
type Resolvers struct {
|
||||
*Resolver
|
||||
ProxyResolver *Resolver
|
||||
DirectResolver *Resolver
|
||||
}
|
||||
|
||||
func (rs Resolvers) ClearCache() {
|
||||
rs.Resolver.ClearCache()
|
||||
rs.ProxyResolver.ClearCache()
|
||||
rs.DirectResolver.ClearCache()
|
||||
}
|
||||
|
||||
func (rs Resolvers) ResetConnection() {
|
||||
rs.Resolver.ResetConnection()
|
||||
rs.ProxyResolver.ResetConnection()
|
||||
rs.DirectResolver.ResetConnection()
|
||||
}
|
||||
|
||||
func NewResolver(config Config) (rs Resolvers) {
|
||||
defaultResolver := &Resolver{
|
||||
main: transform(config.Default, nil),
|
||||
cache: config.newCache(),
|
||||
@ -482,7 +500,7 @@ func NewResolver(config Config) (r *Resolver, pr *Resolver) {
|
||||
return
|
||||
}
|
||||
|
||||
r = &Resolver{
|
||||
r := &Resolver{
|
||||
ipv6: config.IPv6,
|
||||
main: cacheTransform(config.Main),
|
||||
cache: config.newCache(),
|
||||
@ -490,9 +508,10 @@ func NewResolver(config Config) (r *Resolver, pr *Resolver) {
|
||||
ipv6Timeout: time.Duration(config.IPv6Timeout) * time.Millisecond,
|
||||
}
|
||||
r.defaultResolver = defaultResolver
|
||||
rs.Resolver = r
|
||||
|
||||
if len(config.ProxyServer) != 0 {
|
||||
pr = &Resolver{
|
||||
rs.ProxyResolver = &Resolver{
|
||||
ipv6: config.IPv6,
|
||||
main: cacheTransform(config.ProxyServer),
|
||||
cache: config.newCache(),
|
||||
@ -501,8 +520,20 @@ func NewResolver(config Config) (r *Resolver, pr *Resolver) {
|
||||
}
|
||||
}
|
||||
|
||||
if len(config.DirectServer) != 0 {
|
||||
rs.DirectResolver = &Resolver{
|
||||
ipv6: config.IPv6,
|
||||
main: cacheTransform(config.DirectServer),
|
||||
cache: config.newCache(),
|
||||
hosts: config.Hosts,
|
||||
ipv6Timeout: time.Duration(config.IPv6Timeout) * time.Millisecond,
|
||||
}
|
||||
}
|
||||
|
||||
if len(config.Fallback) != 0 {
|
||||
r.fallback = cacheTransform(config.Fallback)
|
||||
r.fallbackIPFilters = config.FallbackIPFilter
|
||||
r.fallbackDomainFilters = config.FallbackDomainFilter
|
||||
}
|
||||
|
||||
if len(config.Policy) != 0 {
|
||||
@ -531,9 +562,11 @@ func NewResolver(config Config) (r *Resolver, pr *Resolver) {
|
||||
}
|
||||
}
|
||||
insertPolicy(nil)
|
||||
|
||||
if rs.DirectResolver != nil && config.DirectFollowPolicy {
|
||||
rs.DirectResolver.policy = r.policy
|
||||
}
|
||||
}
|
||||
r.fallbackIPFilters = config.FallbackIPFilter
|
||||
r.fallbackDomainFilters = config.FallbackDomainFilter
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/metacubex/mihomo/component/resolver"
|
||||
|
||||
D "github.com/miekg/dns"
|
||||
)
|
||||
|
||||
@ -24,10 +26,15 @@ type systemClient struct {
|
||||
mu sync.Mutex
|
||||
dnsClients map[string]*systemDnsClient
|
||||
lastFlush time.Time
|
||||
defaultNS []dnsClient
|
||||
}
|
||||
|
||||
func (c *systemClient) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) {
|
||||
dnsClients, err := c.getDnsClients()
|
||||
if len(dnsClients) == 0 && len(c.defaultNS) > 0 {
|
||||
dnsClients = c.defaultNS
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -38,11 +45,16 @@ func (c *systemClient) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Ms
|
||||
// Address implements dnsClient
|
||||
func (c *systemClient) Address() string {
|
||||
dnsClients, _ := c.getDnsClients()
|
||||
isDefault := ""
|
||||
if len(dnsClients) == 0 && len(c.defaultNS) > 0 {
|
||||
dnsClients = c.defaultNS
|
||||
isDefault = "[defaultNS]"
|
||||
}
|
||||
addrs := make([]string, 0, len(dnsClients))
|
||||
for _, c := range dnsClients {
|
||||
addrs = append(addrs, c.Address())
|
||||
}
|
||||
return fmt.Sprintf("system(%s)", strings.Join(addrs, ","))
|
||||
return fmt.Sprintf("system%s(%s)", isDefault, strings.Join(addrs, ","))
|
||||
}
|
||||
|
||||
var _ dnsClient = (*systemClient)(nil)
|
||||
@ -52,3 +64,11 @@ func newSystemClient() *systemClient {
|
||||
dnsClients: map[string]*systemDnsClient{},
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
r := NewResolver(Config{})
|
||||
c := newSystemClient()
|
||||
c.defaultNS = transform([]NameServer{{Addr: "114.114.114.114:53"}, {Addr: "8.8.8.8:53"}}, nil)
|
||||
r.main = []dnsClient{c}
|
||||
resolver.SystemResolver = r
|
||||
}
|
||||
|
@ -294,11 +294,16 @@ dns:
|
||||
# - tcp://1.1.1.1
|
||||
# - 'tcp://1.1.1.1#ProxyGroupName' # 指定 DNS 过代理查询,ProxyGroupName 为策略组名或节点名,过代理配置优先于配置出口网卡,当找不到策略组或节点名则设置为出口网卡
|
||||
|
||||
# 专用于节点域名解析的 DNS 服务器,非必要配置项
|
||||
# 专用于节点域名解析的 DNS 服务器,非必要配置项,如果不填则遵循nameserver-policy、nameserver和fallback的配置
|
||||
# proxy-server-nameserver:
|
||||
# - https://dns.google/dns-query
|
||||
# - tls://one.one.one.one
|
||||
|
||||
# 专用于direct出口域名解析的 DNS 服务器,非必要配置项,如果不填则遵循nameserver-policy、nameserver和fallback的配置
|
||||
# direct-nameserver:
|
||||
# - system://
|
||||
# direct-nameserver-follow-policy: false # 是否遵循nameserver-policy,默认为不遵守,仅当direct-nameserver不为空时生效
|
||||
|
||||
# 配置 fallback 使用条件
|
||||
# fallback-filter:
|
||||
# geoip: true # 配置是否使用 geoip
|
||||
|
24
go.mod
24
go.mod
@ -5,13 +5,13 @@ go 1.20
|
||||
require (
|
||||
github.com/3andne/restls-client-go v0.1.6
|
||||
github.com/bahlo/generic-list-go v0.2.0
|
||||
github.com/coreos/go-iptables v0.7.0
|
||||
github.com/coreos/go-iptables v0.8.0
|
||||
github.com/dlclark/regexp2 v1.11.4
|
||||
github.com/go-chi/chi/v5 v5.1.0
|
||||
github.com/go-chi/render v1.0.3
|
||||
github.com/gobwas/ws v1.4.0
|
||||
github.com/gofrs/uuid/v5 v5.3.0
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240812123929-b105c29bd1b5
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475
|
||||
github.com/klauspost/compress v1.17.9
|
||||
github.com/klauspost/cpuid/v2 v2.2.8
|
||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
|
||||
@ -20,15 +20,15 @@ require (
|
||||
github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399
|
||||
github.com/metacubex/chacha v0.1.0
|
||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
|
||||
github.com/metacubex/quic-go v0.47.1-0.20240909010619-6b38f24bfcc4
|
||||
github.com/metacubex/quic-go v0.48.1-0.20241021013658-51ca987e0174
|
||||
github.com/metacubex/randv2 v0.2.0
|
||||
github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4
|
||||
github.com/metacubex/sing-shadowsocks v0.2.8
|
||||
github.com/metacubex/sing-shadowsocks2 v0.2.2
|
||||
github.com/metacubex/sing-tun v0.2.7-0.20240729131039-ed03f557dee1
|
||||
github.com/metacubex/sing-tun v0.2.7-0.20241021011113-857bcd6ee47c
|
||||
github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9
|
||||
github.com/metacubex/sing-wireguard v0.0.0-20240924052438-b0976fc59ea3
|
||||
github.com/metacubex/tfo-go v0.0.0-20240830120620-c5e019b67785
|
||||
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa
|
||||
github.com/metacubex/utls v1.6.6
|
||||
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181
|
||||
github.com/miekg/dns v1.1.62
|
||||
@ -39,7 +39,7 @@ require (
|
||||
github.com/sagernet/cors v1.2.1
|
||||
github.com/sagernet/fswatch v0.1.1
|
||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a
|
||||
github.com/sagernet/sing v0.5.0-alpha.13
|
||||
github.com/sagernet/sing v0.5.0-rc.4
|
||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6
|
||||
github.com/sagernet/sing-shadowtls v0.1.4
|
||||
github.com/samber/lo v1.47.0
|
||||
@ -51,10 +51,10 @@ require (
|
||||
gitlab.com/go-extension/aes-ccm v0.0.0-20230221065045-e58665ef23c7
|
||||
go.uber.org/automaxprocs v1.6.0
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||
golang.org/x/crypto v0.27.0
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa
|
||||
golang.org/x/net v0.29.0
|
||||
golang.org/x/sys v0.25.0
|
||||
golang.org/x/crypto v0.28.0
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // lastest version compatible with golang1.20
|
||||
golang.org/x/net v0.30.0
|
||||
golang.org/x/sys v0.26.0
|
||||
google.golang.org/protobuf v1.34.2
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
lukechampine.com/blake3 v1.3.0
|
||||
@ -111,9 +111,9 @@ require (
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
golang.org/x/text v0.19.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20240724044459-6f3cf5896297
|
||||
replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20241021005542-18b67490300a
|
||||
|
46
go.sum
46
go.sum
@ -19,8 +19,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||
github.com/coreos/go-iptables v0.7.0 h1:XWM3V+MPRr5/q51NuWSgU0fqMad64Zyxs8ZUoMsamr8=
|
||||
github.com/coreos/go-iptables v0.7.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
||||
github.com/coreos/go-iptables v0.8.0 h1:MPc2P89IhuVpLI7ETL/2tx3XZ61VeICZjYqDEgNsPRc=
|
||||
github.com/coreos/go-iptables v0.8.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
@ -71,8 +71,8 @@ github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I=
|
||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240812123929-b105c29bd1b5 h1:GkMacU5ftc+IEg1449N3UEy2XLDz58W4fkrRu2fibb8=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240812123929-b105c29bd1b5/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475 h1:hxST5pwMBEOWmxpkX20w9oZG+hXdhKmAIPQ3NGGAxas=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
@ -104,26 +104,26 @@ github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvO
|
||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88=
|
||||
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec h1:HxreOiFTUrJXJautEo8rnE1uKTVGY8wtZepY1Tii/Nc=
|
||||
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec/go.mod h1:8BVmQ+3cxjqzWElafm24rb2Ae4jRI6vAXNXWqWjfrXw=
|
||||
github.com/metacubex/quic-go v0.47.1-0.20240909010619-6b38f24bfcc4 h1:CgdUBRxmNlxEGkp35HwvgQ10jwOOUJKWdOxpi8yWi8o=
|
||||
github.com/metacubex/quic-go v0.47.1-0.20240909010619-6b38f24bfcc4/go.mod h1:Y7yRGqFE6UQL/3aKPYmiYdjfVkeujJaStP4+jiZMcN8=
|
||||
github.com/metacubex/quic-go v0.48.1-0.20241021013658-51ca987e0174 h1:GvigRPEU+cbnzdLWne47cxLrc28Abohl3ECtVdnrbq0=
|
||||
github.com/metacubex/quic-go v0.48.1-0.20241021013658-51ca987e0174/go.mod h1:AiZ+UPgrkO1DTnmiAX4b+kRoV1Vfc65UkYD7RbFlIZA=
|
||||
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
|
||||
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
|
||||
github.com/metacubex/sing v0.0.0-20240724044459-6f3cf5896297 h1:YG/JkwGPbca5rUtEMHIu8ZuqzR7BSVm1iqY8hNoMeMA=
|
||||
github.com/metacubex/sing v0.0.0-20240724044459-6f3cf5896297/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/metacubex/sing v0.0.0-20241021005542-18b67490300a h1:JuR0/7RDxQtlZp/GOzrdqNq04HplTxavPRHrek8ouJk=
|
||||
github.com/metacubex/sing v0.0.0-20241021005542-18b67490300a/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4 h1:HobpULaPK6OoxrHMmgcwLkwwIduXVmwdcznwUfH1GQM=
|
||||
github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4/go.mod h1:g7Mxj7b7zm7YVqD975mk/hSmrb0A0G4bVvIMr2MMzn8=
|
||||
github.com/metacubex/sing-shadowsocks v0.2.8 h1:wIhlaigswzjPw4hej75sEvWte3QR0+AJRafgwBHO5B4=
|
||||
github.com/metacubex/sing-shadowsocks v0.2.8/go.mod h1:X3x88XtJpBxG0W0/ECOJL6Ib0SJ3xdniAkU/6/RMWU0=
|
||||
github.com/metacubex/sing-shadowsocks2 v0.2.2 h1:eaf42uVx4Lr21S6MDYs0ZdTvGA0GEhDpb9no4+gdXPo=
|
||||
github.com/metacubex/sing-shadowsocks2 v0.2.2/go.mod h1:BhOug03a/RbI7y6hp6q+6ITM1dXjnLTmeWBHSTwvv2Q=
|
||||
github.com/metacubex/sing-tun v0.2.7-0.20240729131039-ed03f557dee1 h1:ypfofGDZbP8p3Y4P/m74JYu7sQViesi3c8nbmT6cS0Y=
|
||||
github.com/metacubex/sing-tun v0.2.7-0.20240729131039-ed03f557dee1/go.mod h1:olbEx9yVcaw5tHTNlRamRoxmMKcvDvcVS1YLnQGzvWE=
|
||||
github.com/metacubex/sing-tun v0.2.7-0.20241021011113-857bcd6ee47c h1:qfUZ8xBrViOCZamvcC8CyV7Ii8sAUrn7RqZxFGn56tQ=
|
||||
github.com/metacubex/sing-tun v0.2.7-0.20241021011113-857bcd6ee47c/go.mod h1:lCrP0AW7ieKnXG1JEeZLW+9h99QzjuOX0MfCQfz6TgE=
|
||||
github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9 h1:OAXiCosqY8xKDp3pqTW3qbrCprZ1l6WkrXSFSCwyY4I=
|
||||
github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9/go.mod h1:olVkD4FChQ5gKMHG4ZzuD7+fMkJY1G8vwOKpRehjrmY=
|
||||
github.com/metacubex/sing-wireguard v0.0.0-20240924052438-b0976fc59ea3 h1:xg71VmzLS6ByAzi/57phwDvjE+dLLs+ozH00k4DnOns=
|
||||
github.com/metacubex/sing-wireguard v0.0.0-20240924052438-b0976fc59ea3/go.mod h1:6nitcmzPDL3MXnLdhu6Hm126Zk4S1fBbX3P7jxUxSFw=
|
||||
github.com/metacubex/tfo-go v0.0.0-20240830120620-c5e019b67785 h1:NNmI+ZV0DzNuqaAInRQuZFLHlWVuyHeow8jYpdKjHjo=
|
||||
github.com/metacubex/tfo-go v0.0.0-20240830120620-c5e019b67785/go.mod h1:c7bVFM9f5+VzeZ/6Kg77T/jrg1Xp8QpqlSHvG/aXVts=
|
||||
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa h1:9mcjV+RGZVC3reJBNDjjNPyS8PmFG97zq56X7WNaFO4=
|
||||
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa/go.mod h1:4tLB5c8U0CxpkFM+AJJB77jEaVDbLH5XQvy42vAGsWw=
|
||||
github.com/metacubex/utls v1.6.6 h1:3D12YKHTf2Z41UPhQU2dWerNWJ5TVQD9gKoQ+H+iLC8=
|
||||
github.com/metacubex/utls v1.6.6/go.mod h1:+WLFUnXjcpdxXCnyX25nggw8C6YonZ8zOK2Zm/oRvdo=
|
||||
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 h1:hJLQviGySBuaynlCwf/oYgIxbVbGRUIKZCxdya9YrbQ=
|
||||
@ -230,18 +230,18 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
@ -261,12 +261,12 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/metacubex/mihomo/adapter"
|
||||
"github.com/metacubex/mihomo/adapter/inbound"
|
||||
@ -16,9 +17,10 @@ import (
|
||||
"github.com/metacubex/mihomo/component/auth"
|
||||
"github.com/metacubex/mihomo/component/ca"
|
||||
"github.com/metacubex/mihomo/component/dialer"
|
||||
G "github.com/metacubex/mihomo/component/geodata"
|
||||
"github.com/metacubex/mihomo/component/geodata"
|
||||
mihomoHttp "github.com/metacubex/mihomo/component/http"
|
||||
"github.com/metacubex/mihomo/component/iface"
|
||||
"github.com/metacubex/mihomo/component/keepalive"
|
||||
"github.com/metacubex/mihomo/component/profile"
|
||||
"github.com/metacubex/mihomo/component/profile/cachefile"
|
||||
"github.com/metacubex/mihomo/component/resolver"
|
||||
@ -100,7 +102,7 @@ func ApplyConfig(cfg *config.Config, force bool) {
|
||||
updateRules(cfg.Rules, cfg.SubRules, cfg.RuleProviders)
|
||||
updateSniffer(cfg.Sniffer)
|
||||
updateHosts(cfg.Hosts)
|
||||
updateGeneral(cfg.General)
|
||||
updateGeneral(cfg.General, true)
|
||||
updateNTP(cfg.NTP)
|
||||
updateDNS(cfg.DNS, cfg.General.IPv6)
|
||||
updateListeners(cfg.General, cfg.Listeners, force)
|
||||
@ -117,7 +119,7 @@ func ApplyConfig(cfg *config.Config, force bool) {
|
||||
runtime.GC()
|
||||
tunnel.OnRunning()
|
||||
hcCompatibleProvider(cfg.Providers)
|
||||
initExternalUI()
|
||||
updateUpdater(cfg)
|
||||
|
||||
resolver.ResetConnection()
|
||||
}
|
||||
@ -160,22 +162,25 @@ func GetGeneral() *config.General {
|
||||
Interface: dialer.DefaultInterface.Load(),
|
||||
RoutingMark: int(dialer.DefaultRoutingMark.Load()),
|
||||
GeoXUrl: config.GeoXUrl{
|
||||
GeoIp: G.GeoIpUrl(),
|
||||
Mmdb: G.MmdbUrl(),
|
||||
ASN: G.ASNUrl(),
|
||||
GeoSite: G.GeoSiteUrl(),
|
||||
GeoIp: geodata.GeoIpUrl(),
|
||||
Mmdb: geodata.MmdbUrl(),
|
||||
ASN: geodata.ASNUrl(),
|
||||
GeoSite: geodata.GeoSiteUrl(),
|
||||
},
|
||||
GeoAutoUpdate: updater.GeoAutoUpdate(),
|
||||
GeoUpdateInterval: updater.GeoUpdateInterval(),
|
||||
GeodataMode: G.GeodataMode(),
|
||||
GeodataLoader: G.LoaderName(),
|
||||
GeositeMatcher: G.SiteMatcherName(),
|
||||
GeodataMode: geodata.GeodataMode(),
|
||||
GeodataLoader: geodata.LoaderName(),
|
||||
GeositeMatcher: geodata.SiteMatcherName(),
|
||||
TCPConcurrent: dialer.GetTcpConcurrent(),
|
||||
FindProcessMode: tunnel.FindProcessMode(),
|
||||
Sniffing: tunnel.IsSniffing(),
|
||||
GlobalClientFingerprint: tlsC.GetGlobalFingerprint(),
|
||||
GlobalUA: mihomoHttp.UA(),
|
||||
ETagSupport: resource.ETag(),
|
||||
KeepAliveInterval: int(keepalive.KeepAliveInterval() / time.Second),
|
||||
KeepAliveIdle: int(keepalive.KeepAliveIdle() / time.Second),
|
||||
DisableKeepAlive: keepalive.DisableKeepAlive(),
|
||||
}
|
||||
|
||||
return general
|
||||
@ -235,6 +240,8 @@ func updateDNS(c *config.DNS, generalIPv6 bool) {
|
||||
resolver.DefaultResolver = nil
|
||||
resolver.DefaultHostMapper = nil
|
||||
resolver.DefaultLocalServer = nil
|
||||
resolver.ProxyServerHostResolver = nil
|
||||
resolver.DirectHostResolver = nil
|
||||
dns.ReCreateServer("", nil, nil)
|
||||
return
|
||||
}
|
||||
@ -251,11 +258,12 @@ func updateDNS(c *config.DNS, generalIPv6 bool) {
|
||||
Default: c.DefaultNameserver,
|
||||
Policy: c.NameServerPolicy,
|
||||
ProxyServer: c.ProxyServerNameserver,
|
||||
Tunnel: tunnel.Tunnel,
|
||||
DirectServer: c.DirectNameServer,
|
||||
DirectFollowPolicy: c.DirectFollowPolicy,
|
||||
CacheAlgorithm: c.CacheAlgorithm,
|
||||
}
|
||||
|
||||
r, pr := dns.NewResolver(cfg)
|
||||
r := dns.NewResolver(cfg)
|
||||
m := dns.NewEnhancer(cfg)
|
||||
|
||||
// reuse cache of old host mapper
|
||||
@ -265,14 +273,22 @@ func updateDNS(c *config.DNS, generalIPv6 bool) {
|
||||
|
||||
resolver.DefaultResolver = r
|
||||
resolver.DefaultHostMapper = m
|
||||
resolver.DefaultLocalServer = dns.NewLocalServer(r, m)
|
||||
resolver.DefaultLocalServer = dns.NewLocalServer(r.Resolver, m)
|
||||
resolver.UseSystemHosts = c.UseSystemHosts
|
||||
|
||||
if pr.Invalid() {
|
||||
resolver.ProxyServerHostResolver = pr
|
||||
if r.ProxyResolver.Invalid() {
|
||||
resolver.ProxyServerHostResolver = r.ProxyResolver
|
||||
} else {
|
||||
resolver.ProxyServerHostResolver = r.Resolver
|
||||
}
|
||||
|
||||
dns.ReCreateServer(c.Listen, r, m)
|
||||
if r.DirectResolver.Invalid() {
|
||||
resolver.DirectHostResolver = r.DirectResolver
|
||||
} else {
|
||||
resolver.DirectHostResolver = r.Resolver
|
||||
}
|
||||
|
||||
dns.ReCreateServer(c.Listen, r.Resolver, m)
|
||||
}
|
||||
|
||||
func updateHosts(tree *trie.DomainTrie[resolver.HostValue]) {
|
||||
@ -383,42 +399,63 @@ func updateTunnels(tunnels []LC.Tunnel) {
|
||||
listener.PatchTunnel(tunnels, tunnel.Tunnel)
|
||||
}
|
||||
|
||||
func initExternalUI() {
|
||||
if updater.AutoDownloadUI {
|
||||
dirEntries, _ := os.ReadDir(updater.ExternalUIPath)
|
||||
if len(dirEntries) > 0 {
|
||||
log.Infoln("UI already exists, skip downloading")
|
||||
} else {
|
||||
log.Infoln("External UI downloading ...")
|
||||
updater.DownloadUI()
|
||||
func updateUpdater(cfg *config.Config) {
|
||||
general := cfg.General
|
||||
updater.SetGeoAutoUpdate(general.GeoAutoUpdate)
|
||||
updater.SetGeoUpdateInterval(general.GeoUpdateInterval)
|
||||
|
||||
controller := cfg.Controller
|
||||
updater.DefaultUiUpdater = updater.NewUiUpdater(controller.ExternalUI, controller.ExternalUIURL, controller.ExternalUIName)
|
||||
updater.DefaultUiUpdater.AutoDownloadUI()
|
||||
}
|
||||
|
||||
//go:linkname temporaryUpdateGeneral github.com/metacubex/mihomo/config.temporaryUpdateGeneral
|
||||
func temporaryUpdateGeneral(general *config.General) func() {
|
||||
oldGeneral := GetGeneral()
|
||||
updateGeneral(general, false)
|
||||
return func() {
|
||||
updateGeneral(oldGeneral, false)
|
||||
}
|
||||
}
|
||||
|
||||
func updateGeneral(general *config.General) {
|
||||
func updateGeneral(general *config.General, logging bool) {
|
||||
tunnel.SetMode(general.Mode)
|
||||
tunnel.SetFindProcessMode(general.FindProcessMode)
|
||||
resolver.DisableIPv6 = !general.IPv6
|
||||
|
||||
if general.TCPConcurrent {
|
||||
dialer.SetTcpConcurrent(general.TCPConcurrent)
|
||||
if logging && general.TCPConcurrent {
|
||||
log.Infoln("Use tcp concurrent")
|
||||
}
|
||||
|
||||
inbound.SetTfo(general.InboundTfo)
|
||||
inbound.SetMPTCP(general.InboundMPTCP)
|
||||
|
||||
keepalive.SetKeepAliveIdle(time.Duration(general.KeepAliveIdle) * time.Second)
|
||||
keepalive.SetKeepAliveInterval(time.Duration(general.KeepAliveInterval) * time.Second)
|
||||
keepalive.SetDisableKeepAlive(general.DisableKeepAlive)
|
||||
|
||||
adapter.UnifiedDelay.Store(general.UnifiedDelay)
|
||||
|
||||
dialer.DefaultInterface.Store(general.Interface)
|
||||
dialer.DefaultRoutingMark.Store(int32(general.RoutingMark))
|
||||
if general.RoutingMark > 0 {
|
||||
if logging && general.RoutingMark > 0 {
|
||||
log.Infoln("Use routing mark: %#x", general.RoutingMark)
|
||||
}
|
||||
|
||||
iface.FlushCache()
|
||||
G.SetLoader(general.GeodataLoader)
|
||||
G.SetSiteMatcher(general.GeositeMatcher)
|
||||
|
||||
geodata.SetGeodataMode(general.GeodataMode)
|
||||
geodata.SetLoader(general.GeodataLoader)
|
||||
geodata.SetSiteMatcher(general.GeositeMatcher)
|
||||
geodata.SetGeoIpUrl(general.GeoXUrl.GeoIp)
|
||||
geodata.SetGeoSiteUrl(general.GeoXUrl.GeoSite)
|
||||
geodata.SetMmdbUrl(general.GeoXUrl.Mmdb)
|
||||
geodata.SetASNUrl(general.GeoXUrl.ASN)
|
||||
mihomoHttp.SetUA(general.GlobalUA)
|
||||
resource.SetETag(general.ETagSupport)
|
||||
|
||||
tlsC.SetGlobalUtlsClient(general.GlobalClientFingerprint)
|
||||
}
|
||||
|
||||
func updateUsers(users []auth.AuthUser) {
|
||||
|
@ -24,9 +24,11 @@ import (
|
||||
func configRouter() http.Handler {
|
||||
r := chi.NewRouter()
|
||||
r.Get("/", getConfigs)
|
||||
if !embedMode { // disallow update/patch configs in embed mode
|
||||
r.Put("/", updateConfigs)
|
||||
r.Post("/geo", updateGeoDatabases)
|
||||
r.Patch("/", patchConfigs)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ import (
|
||||
"github.com/metacubex/mihomo/tunnel"
|
||||
)
|
||||
|
||||
func GroupRouter() http.Handler {
|
||||
func groupRouter() http.Handler {
|
||||
r := chi.NewRouter()
|
||||
r.Get("/", getGroups)
|
||||
|
||||
|
7
hub/route/patch_android.go
Normal file
7
hub/route/patch_android.go
Normal file
@ -0,0 +1,7 @@
|
||||
//go:build android && cmfa
|
||||
|
||||
package route
|
||||
|
||||
func init() {
|
||||
SetEmbedMode(true) // set embed mode default
|
||||
}
|
@ -36,8 +36,14 @@ var (
|
||||
tlsServer *http.Server
|
||||
unixServer *http.Server
|
||||
pipeServer *http.Server
|
||||
|
||||
embedMode = false
|
||||
)
|
||||
|
||||
func SetEmbedMode(embed bool) {
|
||||
embedMode = embed
|
||||
}
|
||||
|
||||
type Traffic struct {
|
||||
Up int64 `json:"up"`
|
||||
Down int64 `json:"down"`
|
||||
@ -114,15 +120,17 @@ func router(isDebug bool, secret string, dohServer string, cors Cors) *chi.Mux {
|
||||
r.Get("/version", version)
|
||||
r.Mount("/configs", configRouter())
|
||||
r.Mount("/proxies", proxyRouter())
|
||||
r.Mount("/group", GroupRouter())
|
||||
r.Mount("/group", groupRouter())
|
||||
r.Mount("/rules", ruleRouter())
|
||||
r.Mount("/connections", connectionRouter())
|
||||
r.Mount("/providers/proxies", proxyProviderRouter())
|
||||
r.Mount("/providers/rules", ruleProviderRouter())
|
||||
r.Mount("/cache", cacheRouter())
|
||||
r.Mount("/dns", dnsRouter())
|
||||
if !embedMode { // disallow restart and upgrade in embed mode
|
||||
r.Mount("/restart", restartRouter())
|
||||
r.Mount("/upgrade", upgradeRouter())
|
||||
}
|
||||
addExternalRouters(r)
|
||||
|
||||
})
|
||||
|
@ -47,7 +47,7 @@ func upgradeCore(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func updateUI(w http.ResponseWriter, r *http.Request) {
|
||||
err := updater.DownloadUI()
|
||||
err := updater.DefaultUiUpdater.DownloadUI()
|
||||
if err != nil {
|
||||
log.Warnln("%s", err)
|
||||
render.Status(r, http.StatusInternalServerError)
|
||||
|
@ -279,7 +279,7 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis
|
||||
return
|
||||
}
|
||||
|
||||
defaultInterfaceMonitor, err = tun.NewDefaultInterfaceMonitor(networkUpdateMonitor, log.SingLogger, tun.DefaultInterfaceMonitorOptions{OverrideAndroidVPN: true})
|
||||
defaultInterfaceMonitor, err = tun.NewDefaultInterfaceMonitor(networkUpdateMonitor, log.SingLogger, tun.DefaultInterfaceMonitorOptions{InterfaceFinder: interfaceFinder, OverrideAndroidVPN: true})
|
||||
if err != nil {
|
||||
err = E.Cause(err, "create DefaultInterfaceMonitor")
|
||||
return
|
||||
|
8
main.go
8
main.go
@ -1,9 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
@ -55,6 +57,12 @@ func init() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Defensive programming: panic when code mistakenly calls net.DefaultResolver
|
||||
net.DefaultResolver.PreferGo = true
|
||||
net.DefaultResolver.Dial = func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
panic("should never be called")
|
||||
}
|
||||
|
||||
_, _ = maxprocs.Set(maxprocs.Logger(func(string, ...any) {}))
|
||||
|
||||
if len(os.Args) > 1 && os.Args[1] == "convert-ruleset" {
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/metacubex/quic-go"
|
||||
@ -16,9 +15,7 @@ import (
|
||||
"github.com/metacubex/mihomo/transport/hysteria/utils"
|
||||
)
|
||||
|
||||
type ClientTransport struct {
|
||||
Dialer *net.Dialer
|
||||
}
|
||||
type ClientTransport struct{}
|
||||
|
||||
func (ct *ClientTransport) quicPacketConn(proto string, rAddr net.Addr, serverPorts string, obfs obfsPkg.Obfuscator, hopInterval time.Duration, dialer utils.PacketDialer) (net.PacketConn, error) {
|
||||
server := rAddr.String()
|
||||
@ -86,23 +83,3 @@ func (ct *ClientTransport) QUICDial(proto string, server string, serverPorts str
|
||||
}
|
||||
return qs, nil
|
||||
}
|
||||
|
||||
func (ct *ClientTransport) DialTCP(raddr *net.TCPAddr) (*net.TCPConn, error) {
|
||||
conn, err := ct.Dialer.Dial("tcp", raddr.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return conn.(*net.TCPConn), nil
|
||||
}
|
||||
|
||||
func (ct *ClientTransport) ListenUDP() (*net.UDPConn, error) {
|
||||
return net.ListenUDP("udp", nil)
|
||||
}
|
||||
|
||||
func isMultiPortAddr(addr string) bool {
|
||||
_, portStr, err := net.SplitHostPort(addr)
|
||||
if err == nil && (strings.Contains(portStr, ",") || strings.Contains(portStr, "-")) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -114,10 +114,8 @@ func (m *Manager) handle() {
|
||||
ticker := time.NewTicker(time.Second)
|
||||
|
||||
for range ticker.C {
|
||||
m.uploadBlip.Store(m.uploadTemp.Load())
|
||||
m.uploadTemp.Store(0)
|
||||
m.downloadBlip.Store(m.downloadTemp.Load())
|
||||
m.downloadTemp.Store(0)
|
||||
m.uploadBlip.Store(m.uploadTemp.Swap(0))
|
||||
m.downloadBlip.Store(m.downloadTemp.Swap(0))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -625,7 +625,7 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) {
|
||||
// normal check for process
|
||||
uid, path, err := P.FindProcessName(metadata.NetWork.String(), metadata.SrcIP, int(metadata.SrcPort))
|
||||
if err != nil {
|
||||
log.Debugln("[Process] find process %s error: %v", metadata.String(), err)
|
||||
log.Debugln("[Process] find process error for %s: %v", metadata.String(), err)
|
||||
} else {
|
||||
metadata.Process = filepath.Base(path)
|
||||
metadata.ProcessPath = path
|
||||
@ -639,7 +639,7 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) {
|
||||
// check package names
|
||||
pkg, err := P.FindPackageName(metadata)
|
||||
if err != nil {
|
||||
log.Debugln("[Process] find process %s error: %v", metadata.String(), err)
|
||||
log.Debugln("[Process] find process error for %s: %v", metadata.String(), err)
|
||||
} else {
|
||||
metadata.Process = pkg
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user