Compare commits

..

2 Commits

Author SHA1 Message Date
Aubrey Yang
00d58f9972
Merge 256e9d8c3d into 50d60cb004 2024-06-11 21:07:44 +08:00
xishang0128
50d60cb004 chore: Disable the loop back detector for CMFA 2024-06-11 20:52:41 +08:00
6 changed files with 67 additions and 129 deletions

View File

@ -4,8 +4,6 @@ import (
"context"
"errors"
"net/netip"
"os"
"strconv"
N "github.com/metacubex/mihomo/common/net"
"github.com/metacubex/mihomo/component/dialer"
@ -15,8 +13,6 @@ import (
"github.com/metacubex/mihomo/constant/features"
)
var DisableLoopBackDetector, _ = strconv.ParseBool(os.Getenv("DISABLE_LOOPBACK_DETECTOR"))
type Direct struct {
*Base
loopBack *loopback.Detector
@ -29,7 +25,7 @@ type DirectOption struct {
// DialContext implements C.ProxyAdapter
func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
if !features.CMFA && !DisableLoopBackDetector {
if !features.CMFA {
if err := d.loopBack.CheckConn(metadata); err != nil {
return nil, err
}
@ -45,7 +41,7 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...
// ListenPacketContext implements C.ProxyAdapter
func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
if !features.CMFA && !DisableLoopBackDetector {
if !features.CMFA {
if err := d.loopBack.CheckPacketConn(metadata); err != nil {
return nil, err
}

View File

@ -304,16 +304,13 @@ func (w *WireGuard) init(ctx context.Context) error {
ipcConf := "private_key=" + w.option.PrivateKey
if len(w.option.Peers) > 0 {
for i, peer := range w.option.Peers {
ipcConf += "\npublic_key=" + peer.PublicKey
destination, err := w.resolve(ctx, peer.Addr())
if err != nil {
// !!! do not set initErr here !!!
// let us can retry domain resolve in next time
return E.Cause(err, "resolve endpoint domain for peer ", i)
}
if len(w.option.Peers) == 1 { // must call SetConnectAddr if isConnect == true
w.bind.SetConnectAddr(destination)
}
ipcConf += "\npublic_key=" + peer.PublicKey
ipcConf += "\nendpoint=" + destination.String()
if peer.PreSharedKey != "" {
ipcConf += "\npreshared_key=" + peer.PreSharedKey
@ -335,7 +332,7 @@ func (w *WireGuard) init(ctx context.Context) error {
// let us can retry domain resolve in next time
return E.Cause(err, "resolve endpoint domain")
}
w.bind.SetConnectAddr(destination) // must call SetConnectAddr if isConnect == true
w.bind.SetConnectAddr(destination)
ipcConf += "\nendpoint=" + destination.String()
if w.option.PreSharedKey != "" {
ipcConf += "\npreshared_key=" + w.option.PreSharedKey

View File

@ -212,7 +212,6 @@ type RawDNS struct {
IPv6Timeout uint `yaml:"ipv6-timeout" json:"ipv6-timeout"`
UseHosts bool `yaml:"use-hosts" json:"use-hosts"`
UseSystemHosts bool `yaml:"use-system-hosts" json:"use-system-hosts"`
RespectRules bool `yaml:"respect-rules" json:"respect-rules"`
NameServer []string `yaml:"nameserver" json:"nameserver"`
Fallback []string `yaml:"fallback" json:"fallback"`
FallbackFilter RawFallbackFilter `yaml:"fallback-filter" json:"fallback-filter"`
@ -1040,7 +1039,7 @@ func hostWithDefaultPort(host string, defPort string) (string, error) {
return net.JoinHostPort(hostname, port), nil
}
func parseNameServer(servers []string, respectRules bool, preferH3 bool) ([]dns.NameServer, error) {
func parseNameServer(servers []string, preferH3 bool) ([]dns.NameServer, error) {
var nameservers []dns.NameServer
for idx, server := range servers {
@ -1115,10 +1114,6 @@ func parseNameServer(servers []string, respectRules bool, preferH3 bool) ([]dns.
return nil, fmt.Errorf("DNS NameServer[%d] format error: %s", idx, err.Error())
}
if respectRules && len(proxyName) == 0 {
proxyName = dns.RespectRules
}
nameservers = append(
nameservers,
dns.NameServer{
@ -1135,7 +1130,7 @@ func parseNameServer(servers []string, respectRules bool, preferH3 bool) ([]dns.
func init() {
dns.ParseNameServer = func(servers []string) ([]dns.NameServer, error) { // using by wireguard
return parseNameServer(servers, false, false)
return parseNameServer(servers, false)
}
}
@ -1161,7 +1156,7 @@ func parsePureDNSServer(server string) string {
}
}
}
func parseNameServerPolicy(nsPolicy *orderedmap.OrderedMap[string, any], ruleProviders map[string]providerTypes.RuleProvider, respectRules bool, preferH3 bool) (*orderedmap.OrderedMap[string, []dns.NameServer], error) {
func parseNameServerPolicy(nsPolicy *orderedmap.OrderedMap[string, any], ruleProviders map[string]providerTypes.RuleProvider, preferH3 bool) (*orderedmap.OrderedMap[string, []dns.NameServer], error) {
policy := orderedmap.New[string, []dns.NameServer]()
updatedPolicy := orderedmap.New[string, any]()
re := regexp.MustCompile(`[a-zA-Z0-9\-]+\.[a-zA-Z]{2,}(\.[a-zA-Z]{2,})?`)
@ -1207,7 +1202,7 @@ func parseNameServerPolicy(nsPolicy *orderedmap.OrderedMap[string, any], rulePro
if err != nil {
return nil, err
}
nameservers, err := parseNameServer(servers, respectRules, preferH3)
nameservers, err := parseNameServer(servers, preferH3)
if err != nil {
return nil, err
}
@ -1301,10 +1296,6 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
return nil, fmt.Errorf("if DNS configuration is turned on, NameServer cannot be empty")
}
if cfg.RespectRules && len(cfg.ProxyServerNameserver) == 0 {
return nil, fmt.Errorf("if “respect-rules” is turned on, “proxy-server-nameserver” cannot be empty")
}
dnsCfg := &DNS{
Enable: cfg.Enable,
Listen: cfg.Listen,
@ -1319,26 +1310,26 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
},
}
var err error
if dnsCfg.NameServer, err = parseNameServer(cfg.NameServer, cfg.RespectRules, cfg.PreferH3); err != nil {
if dnsCfg.NameServer, err = parseNameServer(cfg.NameServer, cfg.PreferH3); err != nil {
return nil, err
}
if dnsCfg.Fallback, err = parseNameServer(cfg.Fallback, cfg.RespectRules, cfg.PreferH3); err != nil {
if dnsCfg.Fallback, err = parseNameServer(cfg.Fallback, cfg.PreferH3); err != nil {
return nil, err
}
if dnsCfg.NameServerPolicy, err = parseNameServerPolicy(cfg.NameServerPolicy, ruleProviders, cfg.RespectRules, cfg.PreferH3); err != nil {
if dnsCfg.NameServerPolicy, err = parseNameServerPolicy(cfg.NameServerPolicy, ruleProviders, cfg.PreferH3); err != nil {
return nil, err
}
if dnsCfg.ProxyServerNameserver, err = parseNameServer(cfg.ProxyServerNameserver, false, cfg.PreferH3); err != nil {
if dnsCfg.ProxyServerNameserver, err = parseNameServer(cfg.ProxyServerNameserver, cfg.PreferH3); err != nil {
return nil, err
}
if len(cfg.DefaultNameserver) == 0 {
return nil, errors.New("default nameserver should have at least one nameserver")
}
if dnsCfg.DefaultNameserver, err = parseNameServer(cfg.DefaultNameserver, false, cfg.PreferH3); err != nil {
if dnsCfg.DefaultNameserver, err = parseNameServer(cfg.DefaultNameserver, cfg.PreferH3); err != nil {
return nil, err
}
// check default nameserver is pure ip addr

View File

@ -7,6 +7,7 @@ import (
"fmt"
"net"
"net/netip"
"strconv"
"strings"
"time"
@ -18,7 +19,6 @@ import (
C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log"
"github.com/metacubex/mihomo/tunnel"
"github.com/metacubex/mihomo/tunnel/statistic"
D "github.com/miekg/dns"
"github.com/samber/lo"
@ -175,8 +175,6 @@ func msgToDomain(msg *D.Msg) string {
return ""
}
const RespectRules = "RULES"
type dialHandler func(ctx context.Context, network, addr string) (net.Conn, error)
func getDialHandler(r *Resolver, proxyAdapter C.ProxyAdapter, proxyName string, opts ...dialer.Option) dialHandler {
@ -185,76 +183,54 @@ func getDialHandler(r *Resolver, proxyAdapter C.ProxyAdapter, proxyName string,
opts = append(opts, dialer.WithResolver(r))
return dialer.DialContext(ctx, network, addr, opts...)
} else {
metadata := &C.Metadata{
NetWork: C.TCP,
Type: C.INNER,
}
err := metadata.SetRemoteAddress(addr) // tcp can resolve host by remote
host, port, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
if !strings.Contains(network, "tcp") {
metadata.NetWork = C.UDP
if !metadata.Resolved() {
// udp must resolve host first
dstIP, err := resolver.ResolveIPWithResolver(ctx, metadata.Host, r)
if err != nil {
return nil, err
}
metadata.DstIP = dstIP
}
uintPort, err := strconv.ParseUint(port, 10, 16)
if err != nil {
return nil, err
}
var rule C.Rule
if proxyAdapter == nil {
if proxyName == RespectRules {
if !metadata.Resolved() {
// resolve here before ResolveMetadata to avoid its inner resolver.ResolveIP
dstIP, err := resolver.ResolveIPWithResolver(ctx, metadata.Host, r)
if err != nil {
return nil, err
}
metadata.DstIP = dstIP
}
proxyAdapter, rule, err = tunnel.ResolveMetadata(metadata)
if err != nil {
return nil, err
}
} else {
var ok bool
proxyAdapter, ok = tunnel.Proxies()[proxyName]
if !ok {
opts = append(opts, dialer.WithInterface(proxyName))
}
var ok bool
proxyAdapter, ok = tunnel.Proxies()[proxyName]
if !ok {
opts = append(opts, dialer.WithInterface(proxyName))
}
}
if strings.Contains(network, "tcp") {
if proxyAdapter == nil {
opts = append(opts, dialer.WithResolver(r))
return dialer.DialContext(ctx, network, addr, opts...)
// tcp can resolve host by remote
metadata := &C.Metadata{
NetWork: C.TCP,
Host: host,
DstPort: uint16(uintPort),
}
if proxyAdapter.IsL3Protocol(metadata) { // L3 proxy should resolve domain before to avoid loopback
if !metadata.Resolved() {
dstIP, err := resolver.ResolveIPWithResolver(ctx, metadata.Host, r)
if proxyAdapter != nil {
if proxyAdapter.IsL3Protocol(metadata) { // L3 proxy should resolve domain before to avoid loopback
dstIP, err := resolver.ResolveIPWithResolver(ctx, host, r)
if err != nil {
return nil, err
}
metadata.Host = ""
metadata.DstIP = dstIP
}
metadata.Host = "" // clear host to avoid double resolve in proxy
return proxyAdapter.DialContext(ctx, metadata, opts...)
}
conn, err := proxyAdapter.DialContext(ctx, metadata, opts...)
opts = append(opts, dialer.WithResolver(r))
return dialer.DialContext(ctx, network, addr, opts...)
} else {
// udp must resolve host first
dstIP, err := resolver.ResolveIPWithResolver(ctx, host, r)
if err != nil {
return nil, err
}
conn = statistic.NewTCPTracker(conn, statistic.DefaultManager, metadata, rule, 0, 0, false)
return conn, nil
} else {
metadata := &C.Metadata{
NetWork: C.UDP,
Host: "",
DstIP: dstIP,
DstPort: uint16(uintPort),
}
if proxyAdapter == nil {
return dialer.DialContext(ctx, network, addr, opts...)
}
@ -268,8 +244,6 @@ func getDialHandler(r *Resolver, proxyAdapter C.ProxyAdapter, proxyName string,
return nil, err
}
packetConn = statistic.NewUDPTracker(packetConn, statistic.DefaultManager, metadata, rule, 0, 0, false)
return N.NewBindPacketConn(packetConn, metadata.UDPAddr()), nil
}
}
@ -277,38 +251,33 @@ func getDialHandler(r *Resolver, proxyAdapter C.ProxyAdapter, proxyName string,
}
func listenPacket(ctx context.Context, proxyAdapter C.ProxyAdapter, proxyName string, network string, addr string, r *Resolver, opts ...dialer.Option) (net.PacketConn, error) {
metadata := &C.Metadata{
NetWork: C.UDP,
}
err := metadata.SetRemoteAddress(addr)
host, port, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
if !metadata.Resolved() {
// udp must resolve host first
dstIP, err := resolver.ResolveIPWithResolver(ctx, metadata.Host, r)
if err != nil {
return nil, err
}
metadata.DstIP = dstIP
uintPort, err := strconv.ParseUint(port, 10, 16)
if err != nil {
return nil, err
}
var rule C.Rule
if proxyAdapter == nil {
if proxyName == RespectRules {
proxyAdapter, rule, err = tunnel.ResolveMetadata(metadata)
if err != nil {
return nil, err
}
} else {
var ok bool
proxyAdapter, ok = tunnel.Proxies()[proxyName]
if !ok {
opts = append(opts, dialer.WithInterface(proxyName))
}
var ok bool
proxyAdapter, ok = tunnel.Proxies()[proxyName]
if !ok {
opts = append(opts, dialer.WithInterface(proxyName))
}
}
// udp must resolve host first
dstIP, err := resolver.ResolveIPWithResolver(ctx, host, r)
if err != nil {
return nil, err
}
metadata := &C.Metadata{
NetWork: C.UDP,
Host: "",
DstIP: dstIP,
DstPort: uint16(uintPort),
}
if proxyAdapter == nil {
return dialer.NewDialer(opts...).ListenPacket(ctx, network, "", netip.AddrPortFrom(metadata.DstIP, metadata.DstPort))
}
@ -317,14 +286,7 @@ func listenPacket(ctx context.Context, proxyAdapter C.ProxyAdapter, proxyName st
return nil, fmt.Errorf("proxy adapter [%s] UDP is not supported", proxyAdapter)
}
packetConn, err := proxyAdapter.ListenPacketContext(ctx, metadata, opts...)
if err != nil {
return nil, err
}
packetConn = statistic.NewUDPTracker(packetConn, statistic.DefaultManager, metadata, rule, 0, 0, false)
return packetConn, nil
return proxyAdapter.ListenPacketContext(ctx, metadata, opts...)
}
func batchExchange(ctx context.Context, clients []dnsClient, m *D.Msg) (msg *D.Msg, cache bool, err error) {

View File

@ -209,7 +209,7 @@ tunnels: # one line config
dns:
cache-algorithm: arc
enable: false # 关闭将使用系统 DNS
prefer-h3: false # 是否开启 DoH 支持 HTTP/3将并发尝试
prefer-h3: true # 开启 DoH 支持 HTTP/3将并发尝试
listen: 0.0.0.0:53 # 开启 DNS 服务器监听
# ipv6: false # false 将返回 AAAA 的空结果
# ipv6-timeout: 300 # 单位ms内部双栈并发时向上游查询 AAAA 时,等待 AAAA 的时间,默认 100ms
@ -227,13 +227,6 @@ dns:
# use-hosts: true # 查询 hosts
# 配置后面的nameserver、fallback和nameserver-policy向dns服务器的连接过程是否遵守遵守rules规则
# 如果为false默认值则这三部分的dns服务器在未特别指定的情况下会直连
# 如果为true将会按照rules的规则匹配链接方式走代理或直连如果有特别指定则任然以指定值为准
# 仅当proxy-server-nameserver非空时可以开启此选项, 强烈不建议和prefer-h3一起使用
# 此外这三者配置中的dns服务器如果出现域名会采用default-nameserver配置项解析也请确保正确配置default-nameserver
respect-rules: false
# 配置不使用 fake-ip 的域名
# fake-ip-filter:
# - '*.lan'
@ -251,7 +244,6 @@ dns:
- https://mozilla.cloudflare-dns.com/dns-query#DNS&h3=true # 指定策略组和使用 HTTP/3
- dhcp://en0 # dns from dhcp
- quic://dns.adguard.com:784 # DNS over QUIC
# - '8.8.8.8#RULES' # 效果同respect-rules但仅对该服务器生效
# - '8.8.8.8#en0' # 兼容指定 DNS 出口网卡
# 当配置 fallback 时,会查询 nameserver 中返回的 IP 是否为 CN非必要配置

View File

@ -278,7 +278,7 @@ func preHandleMetadata(metadata *C.Metadata) error {
return nil
}
func ResolveMetadata(metadata *C.Metadata) (proxy C.Proxy, rule C.Rule, err error) {
func resolveMetadata(metadata *C.Metadata) (proxy C.Proxy, rule C.Rule, err error) {
if metadata.SpecialProxy != "" {
var exist bool
proxy, exist = proxies[metadata.SpecialProxy]
@ -375,7 +375,7 @@ func handleUDPConn(packet C.PacketAdapter) {
cond.Broadcast()
}()
proxy, rule, err := ResolveMetadata(metadata)
proxy, rule, err := resolveMetadata(metadata)
if err != nil {
log.Warnln("[UDP] Parse metadata failed: %s", err.Error())
return
@ -486,7 +486,7 @@ func handleTCPConn(connCtx C.ConnContext) {
}()
}
proxy, rule, err := ResolveMetadata(metadata)
proxy, rule, err := resolveMetadata(metadata)
if err != nil {
log.Warnln("[Metadata] parse failed: %s", err.Error())
return