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