From 006b7fbfd2c223c082a778c9d658199098cad340 Mon Sep 17 00:00:00 2001 From: mzz2017 <2017@duck.com> Date: Sun, 2 Apr 2023 11:07:53 +0800 Subject: [PATCH] feat: support must_xxx outbounds --- common/consts/ebpf.go | 5 +- component/dns/request_routing.go | 6 ++ component/dns/response_routing.go | 6 ++ .../routing/domain_matcher/benchmark_test.go | 4 +- component/routing/matcher_builder.go | 13 +++- config/config.go | 2 +- config/patch.go | 22 +++++++ control/control_plane.go | 4 -- control/kern/tproxy.c | 59 +++++++++++-------- control/routing_matcher_builder.go | 12 +++- control/tcp.go | 2 - control/udp.go | 6 +- docs/dns.md | 6 +- docs/getting-started/README.md | 2 +- docs/getting-started/README_zh.md | 4 +- docs/getting-started/external-dns.md | 12 ++-- docs/routing.md | 8 ++- example.dae | 4 +- 18 files changed, 115 insertions(+), 62 deletions(-) diff --git a/common/consts/ebpf.go b/common/consts/ebpf.go index 4c8819d..82f82b8 100644 --- a/common/consts/ebpf.go +++ b/common/consts/ebpf.go @@ -64,14 +64,13 @@ const ( OutboundDirect OutboundIndex = iota OutboundBlock - OutboundMustDirect OutboundIndex = 0xFC OutboundControlPlaneRouting OutboundIndex = 0xFD OutboundLogicalOr OutboundIndex = 0xFE OutboundLogicalAnd OutboundIndex = 0xFF OutboundLogicalMask OutboundIndex = 0xFE OutboundMax = OutboundLogicalAnd - OutboundUserDefinedMax = OutboundMustDirect - 1 + OutboundUserDefinedMax = OutboundControlPlaneRouting - 1 ) func (i OutboundIndex) String() string { @@ -80,8 +79,6 @@ func (i OutboundIndex) String() string { return "direct" case OutboundBlock: return "block" - case OutboundMustDirect: - return "must_direct" case OutboundControlPlaneRouting: return "" case OutboundLogicalOr: diff --git a/component/dns/request_routing.go b/component/dns/request_routing.go index bc44ec2..e704afb 100644 --- a/component/dns/request_routing.go +++ b/component/dns/request_routing.go @@ -112,6 +112,12 @@ func (b *RequestMatcherBuilder) addFallback(fallbackOutbound config.FunctionOrSt if err != nil { return err } + if upstream.Must { + return fmt.Errorf("unsupported param: must") + } + if upstream.Mark != 0 { + return fmt.Errorf("unsupported param: mark") + } upstreamId, err := b.upstreamToId(upstream.Name) if err != nil { return err diff --git a/component/dns/response_routing.go b/component/dns/response_routing.go index 26d03e9..9f21963 100644 --- a/component/dns/response_routing.go +++ b/component/dns/response_routing.go @@ -195,6 +195,12 @@ func (b *ResponseMatcherBuilder) addFallback(fallbackOutbound config.FunctionOrS if err != nil { return err } + if upstream.Must { + return fmt.Errorf("unsupported param: must") + } + if upstream.Mark != 0 { + return fmt.Errorf("unsupported param: mark") + } upstreamId, err := b.upstreamToId(upstream.Name) if err != nil { return err diff --git a/component/routing/domain_matcher/benchmark_test.go b/component/routing/domain_matcher/benchmark_test.go index e7f6ebb..30b9c51 100644 --- a/component/routing/domain_matcher/benchmark_test.go +++ b/component/routing/domain_matcher/benchmark_test.go @@ -7,11 +7,11 @@ package domain_matcher import ( "fmt" - "github.com/sirupsen/logrus" "github.com/daeuniverse/dae/common/consts" "github.com/daeuniverse/dae/component/routing" "github.com/daeuniverse/dae/config" "github.com/daeuniverse/dae/pkg/config_parser" + "github.com/sirupsen/logrus" "hash/fnv" "math/rand" "reflect" @@ -132,7 +132,7 @@ func getDomain() (simulatedDomainSet []routing.DomainSet, err error) { sections, err := config_parser.Parse(` routing { domain(geosite:bing)->us - domain(full:dns.google) -> direct + domain(full:dns.google.com) -> direct domain(geosite:category-ads-all) -> block domain(geosite:cn) -> direct }`) diff --git a/component/routing/matcher_builder.go b/component/routing/matcher_builder.go index afb2754..135b872 100644 --- a/component/routing/matcher_builder.go +++ b/component/routing/matcher_builder.go @@ -7,9 +7,9 @@ package routing import ( "fmt" - "github.com/sirupsen/logrus" "github.com/daeuniverse/dae/common/consts" "github.com/daeuniverse/dae/pkg/config_parser" + "github.com/sirupsen/logrus" "strconv" ) @@ -22,6 +22,7 @@ type DomainSet struct { type Outbound struct { Name string Mark uint32 + Must bool } type RulesBuilder struct { @@ -62,6 +63,7 @@ func (b *RulesBuilder) Apply(rules []*config_parser.RoutingRule) (err error) { overrideOutbound := &Outbound{ Name: consts.OutboundLogicalOr.String(), Mark: outbound.Mark, + Must: outbound.Must, } if jMatchSet == len(keyOrder)-1 { overrideOutbound.Name = consts.OutboundLogicalAnd.String() @@ -103,6 +105,7 @@ func ParseOutbound(rawOutbound *config_parser.Function) (outbound *Outbound, err outbound = &Outbound{ Name: rawOutbound.Name, Mark: 0, + Must: false, } for _, p := range rawOutbound.Params { switch p.Key { @@ -113,8 +116,14 @@ func ParseOutbound(rawOutbound *config_parser.Function) (outbound *Outbound, err return nil, fmt.Errorf("failed to parse mark: %v", err) } outbound.Mark = uint32(_mark) + case "": + if p.Val == "must" { + outbound.Must = true + } else { + return nil, fmt.Errorf("unknown outbound param: %v", p.Val) + } default: - return nil, fmt.Errorf("unknown outbound param: %v", p.Key) + return nil, fmt.Errorf("unknown outbound param key: %v", p.Key) } } return outbound, nil diff --git a/config/config.go b/config/config.go index e1daa36..9628024 100644 --- a/config/config.go +++ b/config/config.go @@ -18,7 +18,7 @@ type Global struct { // We use DirectTcpCheckUrl to check (tcp)*(ipv4/ipv6) connectivity for direct. //DirectTcpCheckUrl string `mapstructure:"direct_tcp_check_url" default:"http://www.qualcomm.cn/generate_204"` TcpCheckUrl string `mapstructure:"tcp_check_url" default:"http://keep-alv.google.com/generate_204"` - UdpCheckDns string `mapstructure:"udp_check_dns" default:"dns.google:53"` + UdpCheckDns string `mapstructure:"udp_check_dns" default:"dns.google.com:53"` CheckInterval time.Duration `mapstructure:"check_interval" default:"30s"` CheckTolerance time.Duration `mapstructure:"check_tolerance" default:"0"` LanInterface []string `mapstructure:"lan_interface"` diff --git a/config/patch.go b/config/patch.go index d4c7003..215600d 100644 --- a/config/patch.go +++ b/config/patch.go @@ -7,12 +7,15 @@ package config import ( "github.com/daeuniverse/dae/common/consts" + "github.com/daeuniverse/dae/pkg/config_parser" + "strings" ) type patch func(params *Config) error var patches = []patch{ patchEmptyDns, + patchMustOutbound, } func patchEmptyDns(params *Config) error { @@ -24,3 +27,22 @@ func patchEmptyDns(params *Config) error { } return nil } + +func patchMustOutbound(params *Config) error { + for i := range params.Routing.Rules { + if strings.HasPrefix(params.Routing.Rules[i].Outbound.Name, "must_") { + params.Routing.Rules[i].Outbound.Name = strings.TrimPrefix(params.Routing.Rules[i].Outbound.Name, "must_") + params.Routing.Rules[i].Outbound.Params = append(params.Routing.Rules[i].Outbound.Params, &config_parser.Param{ + Val: "must", + }) + } + } + if f := FunctionOrStringToFunction(params.Routing.Fallback); strings.HasPrefix(f.Name, "must_") { + f.Name = strings.TrimPrefix(f.Name, "must_") + f.Params = append(f.Params, &config_parser.Param{ + Val: "must", + }) + params.Routing.Fallback = f + } + return nil +} diff --git a/control/control_plane.go b/control/control_plane.go index efb3573..ded2eac 100644 --- a/control/control_plane.go +++ b/control/control_plane.go @@ -757,10 +757,6 @@ func (c *ControlPlane) chooseBestDnsDialer( if err != nil { return nil, err } - // Already "must direct". - if outboundIndex == consts.OutboundMustDirect { - outboundIndex = consts.OutboundDirect - } if int(outboundIndex) >= len(c.outbounds) { return nil, fmt.Errorf("bad outbound index: %v", outboundIndex) } diff --git a/control/kern/tproxy.c b/control/kern/tproxy.c index 89a9715..8da8412 100644 --- a/control/kern/tproxy.c +++ b/control/kern/tproxy.c @@ -60,7 +60,6 @@ #define OUTBOUND_DIRECT 0 #define OUTBOUND_BLOCK 1 -#define OUTBOUND_MUST_DIRECT 0xFC #define OUTBOUND_CONTROL_PLANE_ROUTING 0xFD #define OUTBOUND_LOGICAL_OR 0xFE #define OUTBOUND_LOGICAL_AND 0xFF @@ -135,6 +134,7 @@ struct ip_port { struct routing_result { __u32 mark; + __u8 must; __u8 mac[6]; __u8 outbound; __u8 pname[TASK_COMM_LEN]; @@ -307,7 +307,7 @@ struct match_set { bool not ; // A subrule flag (this is not a match_set flag). enum MatchType type; __u8 outbound; // User-defined value range is [0, 252]. - __u8 unused; + bool must; __u32 mark; }; struct { @@ -1133,11 +1133,13 @@ routing(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4], // DNS requests should routed by control plane if outbound is not // must_direct. - if (match_set->outbound != OUTBOUND_MUST_DIRECT && h_dport == 53 && + if (!match_set->must && h_dport == 53 && _l4proto_type == L4ProtoType_UDP) { - return OUTBOUND_CONTROL_PLANE_ROUTING | (match_set->mark << 8); + return (__s64)OUTBOUND_CONTROL_PLANE_ROUTING | + ((__s64)match_set->mark << 8) | ((__s64)match_set->must << 40); } - return match_set->outbound | (match_set->mark << 8); + return (__s64)match_set->outbound | ((__s64)match_set->mark << 8) | + ((__s64)match_set->must << 40); } bad_rule = false; } @@ -1325,14 +1327,16 @@ new_connection: bpf_htonl((ethh.h_source[2] << 24) + (ethh.h_source[3] << 16) + (ethh.h_source[4] << 8) + (ethh.h_source[5])), }; - if ((ret = routing(flag, l4hdr, tuples.sip.u6_addr32, tuples.dip.u6_addr32, - mac)) < 0) { - bpf_printk("shot routing: %d", ret); + __s64 s64_ret; + if ((s64_ret = routing(flag, l4hdr, tuples.sip.u6_addr32, + tuples.dip.u6_addr32, mac)) < 0) { + bpf_printk("shot routing: %d", s64_ret); return TC_ACT_SHOT; } struct routing_result routing_result = {0}; - routing_result.outbound = ret; - routing_result.mark = ret >> 8; + routing_result.outbound = s64_ret; + routing_result.mark = s64_ret >> 8; + routing_result.must = (s64_ret >> 40) & 1; __builtin_memcpy(routing_result.mac, ethh.h_source, sizeof(routing_result.mac)); /// NOTICE: No pid pname info for LAN packet. @@ -1361,8 +1365,7 @@ new_connection: bpf_ntohs(tuples.dport)); } #endif - if (routing_result.outbound == OUTBOUND_DIRECT || - routing_result.outbound == OUTBOUND_MUST_DIRECT) { + if (routing_result.outbound == OUTBOUND_DIRECT) { skb->mark = routing_result.mark; goto direct; } else if (unlikely(routing_result.outbound == OUTBOUND_BLOCK)) { @@ -1593,6 +1596,7 @@ int tproxy_wan_egress(struct __sk_buff *skb) { __builtin_memcpy(&key_src.ip, &tuples.dip, IPV6_BYTE_LENGTH); key_src.port = tcph.source; __u8 outbound; + bool must; __u32 mark; struct pid_pname *pid_pname = NULL; if (unlikely(tcp_state_syn)) { @@ -1618,14 +1622,16 @@ int tproxy_wan_egress(struct __sk_buff *skb) { bpf_htonl((ethh.h_source[2] << 24) + (ethh.h_source[3] << 16) + (ethh.h_source[4] << 8) + (ethh.h_source[5])), }; - if ((ret = routing(flag, &tcph, tuples.sip.u6_addr32, - tuples.dip.u6_addr32, mac)) < 0) { - bpf_printk("shot routing: %d", ret); + __s64 s64_ret; + if ((s64_ret = routing(flag, &tcph, tuples.sip.u6_addr32, + tuples.dip.u6_addr32, mac)) < 0) { + bpf_printk("shot routing: %d", s64_ret); return TC_ACT_SHOT; } - outbound = ret; - mark = ret >> 8; + outbound = s64_ret; + mark = s64_ret >> 8; + must = (s64_ret >> 40) & 1; #if defined(__DEBUG_ROUTING) || defined(__PRINT_ROUTING_RESULT) // Print only new connection. @@ -1646,9 +1652,10 @@ int tproxy_wan_egress(struct __sk_buff *skb) { } outbound = dst->routing_result.outbound; mark = dst->routing_result.mark; + must = dst->routing_result.must; } - if ((outbound == OUTBOUND_DIRECT || outbound == OUTBOUND_MUST_DIRECT) && + if (outbound == OUTBOUND_DIRECT && mark == 0 // If mark is not zero, we should re-route it, so we send it // to control plane in WAN. ) { @@ -1678,6 +1685,7 @@ int tproxy_wan_egress(struct __sk_buff *skb) { routing_info.port = tcph.dest; routing_info.routing_result.outbound = outbound; routing_info.routing_result.mark = mark; + routing_info.routing_result.must = must; __builtin_memcpy(routing_info.routing_result.mac, ethh.h_source, sizeof(ethh.h_source)); if (pid_pname) { @@ -1726,9 +1734,10 @@ int tproxy_wan_egress(struct __sk_buff *skb) { bpf_htonl((ethh.h_source[2] << 24) + (ethh.h_source[3] << 16) + (ethh.h_source[4] << 8) + (ethh.h_source[5])), }; - if ((ret = routing(flag, &udph, tuples.sip.u6_addr32, - tuples.dip.u6_addr32, mac)) < 0) { - bpf_printk("shot routing: %d", ret); + __s64 s64_ret; + if ((s64_ret = routing(flag, &udph, tuples.sip.u6_addr32, + tuples.dip.u6_addr32, mac)) < 0) { + bpf_printk("shot routing: %d", s64_ret); return TC_ACT_SHOT; } // Construct new hdr to encap. @@ -1736,8 +1745,9 @@ int tproxy_wan_egress(struct __sk_buff *skb) { __builtin_memset(&new_hdr, 0, sizeof(new_hdr)); __builtin_memcpy(new_hdr.ip, &tuples.dip, IPV6_BYTE_LENGTH); new_hdr.port = udph.dest; - new_hdr.routing_result.outbound = ret; - new_hdr.routing_result.mark = ret >> 8; + new_hdr.routing_result.outbound = s64_ret; + new_hdr.routing_result.mark = s64_ret >> 8; + new_hdr.routing_result.must = (s64_ret >> 40) & 1; __builtin_memcpy(new_hdr.routing_result.mac, ethh.h_source, sizeof(ethh.h_source)); if (pid_pname) { @@ -1754,8 +1764,7 @@ int tproxy_wan_egress(struct __sk_buff *skb) { bpf_ntohs(tuples.dport)); #endif - if ((new_hdr.routing_result.outbound == OUTBOUND_DIRECT || - new_hdr.routing_result.outbound == OUTBOUND_MUST_DIRECT) && + if (new_hdr.routing_result.outbound == OUTBOUND_DIRECT && new_hdr.routing_result.mark == 0 // If mark is not zero, we should re-route it, so we // send it to control plane in WAN. diff --git a/control/routing_matcher_builder.go b/control/routing_matcher_builder.go index 00eede1..7417d0d 100644 --- a/control/routing_matcher_builder.go +++ b/control/routing_matcher_builder.go @@ -56,8 +56,6 @@ func NewRoutingMatcherBuilder(log *logrus.Logger, rules []*config_parser.Routing func (b *RoutingMatcherBuilder) outboundToId(outbound string) (uint8, error) { var outboundId uint8 switch outbound { - case consts.OutboundMustDirect.String(): - outboundId = uint8(consts.OutboundMustDirect) case consts.OutboundLogicalOr.String(): outboundId = uint8(consts.OutboundLogicalOr) case consts.OutboundLogicalAnd.String(): @@ -95,6 +93,7 @@ func (b *RoutingMatcherBuilder) addDomain(f *config_parser.Function, key string, Not: f.Not, Outbound: outboundId, Mark: outbound.Mark, + Must: outbound.Must, }) return nil } @@ -119,6 +118,7 @@ func (b *RoutingMatcherBuilder) addSourceMac(f *config_parser.Function, macAddrs Not: f.Not, Outbound: outboundId, Mark: outbound.Mark, + Must: outbound.Must, } binary.LittleEndian.PutUint32(set.Value[:], uint32(lpmTrieIndex)) b.rules = append(b.rules, set) @@ -138,6 +138,7 @@ func (b *RoutingMatcherBuilder) addIp(f *config_parser.Function, values []netip. Not: f.Not, Outbound: outboundId, Mark: outbound.Mark, + Must: outbound.Must, } binary.LittleEndian.PutUint32(set.Value[:], uint32(lpmTrieIndex)) b.rules = append(b.rules, set) @@ -163,6 +164,7 @@ func (b *RoutingMatcherBuilder) addPort(f *config_parser.Function, values [][2]u Not: f.Not, Outbound: outboundId, Mark: outbound.Mark, + Must: outbound.Must, }) } return nil @@ -181,6 +183,7 @@ func (b *RoutingMatcherBuilder) addSourceIp(f *config_parser.Function, values [] Not: f.Not, Outbound: outboundId, Mark: outbound.Mark, + Must: outbound.Must, } binary.LittleEndian.PutUint32(set.Value[:], uint32(lpmTrieIndex)) b.rules = append(b.rules, set) @@ -206,6 +209,7 @@ func (b *RoutingMatcherBuilder) addSourcePort(f *config_parser.Function, values Not: f.Not, Outbound: outboundId, Mark: outbound.Mark, + Must: outbound.Must, }) } return nil @@ -222,6 +226,7 @@ func (b *RoutingMatcherBuilder) addL4Proto(f *config_parser.Function, values con Not: f.Not, Outbound: outboundId, Mark: outbound.Mark, + Must: outbound.Must, }) return nil } @@ -237,6 +242,7 @@ func (b *RoutingMatcherBuilder) addIpVersion(f *config_parser.Function, values c Not: f.Not, Outbound: outboundId, Mark: outbound.Mark, + Must: outbound.Must, }) return nil } @@ -256,6 +262,7 @@ func (b *RoutingMatcherBuilder) addProcessName(f *config_parser.Function, values Not: f.Not, Outbound: outboundId, Mark: outbound.Mark, + Must: outbound.Must, } copy(matchSet.Value[:], value[:]) b.rules = append(b.rules, matchSet) @@ -276,6 +283,7 @@ func (b *RoutingMatcherBuilder) addFallback(fallbackOutbound config.FunctionOrSt Type: uint8(consts.MatchType_Fallback), Outbound: outboundId, Mark: outbound.Mark, + Must: outbound.Must, }) return nil } diff --git a/control/tcp.go b/control/tcp.go index eec8941..217b334 100644 --- a/control/tcp.go +++ b/control/tcp.go @@ -70,8 +70,6 @@ func (c *ControlPlane) handleConn(lConn net.Conn) (err error) { switch outboundIndex { case consts.OutboundDirect: - case consts.OutboundMustDirect: - outboundIndex = consts.OutboundDirect case consts.OutboundControlPlaneRouting: if outboundIndex, routingResult.Mark, err = c.Route(src, dst, domain, consts.L4ProtoType_TCP, routingResult); err != nil { return err diff --git a/control/udp.go b/control/udp.go index 7b707ce..fdad8d5 100644 --- a/control/udp.go +++ b/control/udp.go @@ -143,11 +143,11 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r outboundIndex = consts.OutboundControlPlaneRouting } + if routingResult.Must > 0 { + isDns = false // Regard as plain traffic. + } switch outboundIndex { case consts.OutboundDirect: - case consts.OutboundMustDirect: - outboundIndex = consts.OutboundDirect - isDns = false // Regard as plain traffic. case consts.OutboundControlPlaneRouting: if isDns { // Routing of DNS packets are managed by DNS controller. diff --git a/docs/dns.md b/docs/dns.md index 78cfb53..c3f7675 100644 --- a/docs/dns.md +++ b/docs/dns.md @@ -15,7 +15,7 @@ dns { # If dial_mode is "ip", the upstream DNS answer SHOULD NOT be polluted, so domestic public DNS is not recommended. alidns: 'udp://dns.alidns.com:53' - googledns: 'tcp+udp://dns.google:53' + googledns: 'tcp+udp://dns.google.com:53' } # The routing format of 'request' and 'response' is similar with section 'routing'. # See https://github.com/daeuniverse/dae/blob/main/docs/routing.md @@ -64,7 +64,7 @@ dns { # Use alidns for China mainland domains and googledns for others. dns { upstream { - googledns: 'tcp+udp://dns.google:53' + googledns: 'tcp+udp://dns.google.com:53' alidns: 'udp://dns.alidns.com:53' } routing { @@ -84,7 +84,7 @@ dns { # Use alidns for all DNS queries and fallback to googledns if pollution result detected. dns { upstream { - googledns: 'tcp+udp://dns.google:53' + googledns: 'tcp+udp://dns.google.com:53' alidns: 'udp://dns.alidns.com:53' } routing { diff --git a/docs/getting-started/README.md b/docs/getting-started/README.md index a4640e4..0fd5fa7 100644 --- a/docs/getting-started/README.md +++ b/docs/getting-started/README.md @@ -137,7 +137,7 @@ subscription { # See https://github.com/daeuniverse/dae/blob/main/docs/dns.md for full examples. dns { upstream { - googledns: 'tcp+udp://dns.google:53' + googledns: 'tcp+udp://dns.google.com:53' alidns: 'udp://dns.alidns.com:53' } routing { diff --git a/docs/getting-started/README_zh.md b/docs/getting-started/README_zh.md index 8d6acc3..814f35e 100644 --- a/docs/getting-started/README_zh.md +++ b/docs/getting-started/README_zh.md @@ -133,7 +133,7 @@ subscription { # 更多的 DNS 样例见 https://github.com/daeuniverse/dae/blob/main/docs/dns.md dns { upstream { - googledns: 'tcp+udp://dns.google:53' + googledns: 'tcp+udp://dns.google.com:53' alidns: 'udp://dns.alidns.com:53' } routing { @@ -174,7 +174,7 @@ routing { ```shell dns { upstream { - googledns: 'tcp+udp://dns.google:53' + googledns: 'tcp+udp://dns.google.com:53' alidns: 'udp://dns.alidns.com:53' } routing { diff --git a/docs/getting-started/external-dns.md b/docs/getting-started/external-dns.md index 44f7457..207c5c0 100644 --- a/docs/getting-started/external-dns.md +++ b/docs/getting-started/external-dns.md @@ -7,13 +7,13 @@ If you use a external DNS like AdguardHome, you could refer to the following gui ## External DNS on localhost -If you set up a external DNS on localhost, you may want to let the DNS queries to dns.google proxied. For example, if you have following configuration in AdguardHome: +If you set up a external DNS on localhost, you may want to let the DNS queries to dns.google.com proxied. For example, if you have following configuration in AdguardHome: ``` Listen on: the same machine with dae, port 53. China mainland: udp://223.5.5.5:53 -Others: https://dns.google/dns-query +Others: https://dns.google.com/dns-query ``` You should configure dae as follows: @@ -26,7 +26,7 @@ You should configure dae as follows: pname(AdGuardHome) && l4proto(udp) && dport(53) -> must_direct ``` - And make sure domain `dns.google` will be proxied in routing rules. + And make sure domain `dns.google.com` will be proxied in routing rules. 3. Add upstream and request to section "dns". @@ -51,13 +51,13 @@ You should configure dae as follows: ## External DNS on another machine in LAN -If you set up a external DNS on another machine in LAN, you may want to let the DNS queries to dns.google proxied. For example, if you have following configuration in AdguardHome: +If you set up a external DNS on another machine in LAN, you may want to let the DNS queries to dns.google.com proxied. For example, if you have following configuration in AdguardHome: ``` Listen on: 192.168.30.3:53 (mac address: 8c:16:45:36:1c:5a) China mainland: udp://223.5.5.5:53 -Others: https://dns.google/dns-query +Others: https://dns.google.com/dns-query ``` You should configure dae as follows: @@ -72,7 +72,7 @@ You should configure dae as follows: # mac(8c:16:45:36:1c:5a) && l4proto(udp) && dport(53) -> must_direct ``` - And make sure domain `dns.google` will be proxied in routing rules. + And make sure domain `dns.google.com` will be proxied in routing rules. 3. Add upstream and request to section "dns". diff --git a/docs/routing.md b/docs/routing.md index 9fe2e27..2e09795 100644 --- a/docs/routing.md +++ b/docs/routing.md @@ -3,9 +3,11 @@ ## Examples: ```shell -### Built-in outbounds: block, direct, must_direct -# The difference between "direct" and "must_direct" is that "direct" will intercept and process DNS request (for traffic +### Built-in outbounds: block, direct +# The difference between "direct" and "must_direct" is that "direct" will hijack and process DNS request (for traffic # split use), but "must_direct" will not. "must_direct" is useful when there are traffic loops of DNS requests. +# "must_direct" can be written as "direct(must)". +# Similarly, "must_groupname" is also supported to NOT hijack and process DNS traffic, which equals to "groupname(must)". ### fallback outbound # If no rule matches, traffic will go through the outbound defined by fallback. @@ -14,7 +16,7 @@ fallback: my_group ### Domain rule domain(suffix: v2raya.org) -> my_group # equals to domain(v2raya.org) -> my_group -domain(full: dns.google) -> my_group +domain(full: dns.google.com) -> my_group domain(keyword: facebook) -> my_group domain(regexp: '\.goo.*\.com$') -> my_group domain(geosite:category-ads) -> block diff --git a/example.dae b/example.dae index be7704b..1df4e36 100644 --- a/example.dae +++ b/example.dae @@ -15,7 +15,7 @@ global { # This DNS will be used to check UDP connectivity of nodes. And if dns_upstream below contains tcp, it also be used to check # TCP DNS connectivity of nodes. # This DNS should have both IPv4 and IPv6 if you have double stack in local. - udp_check_dns: 'dns.google:53' + udp_check_dns: 'dns.google.com:53' check_interval: 30s @@ -87,7 +87,7 @@ dns { # If dial_mode is "ip", the upstream DNS answer SHOULD NOT be polluted, so domestic public DNS is not recommended. alidns: 'udp://dns.alidns.com:53' - googledns: 'tcp+udp://dns.google:53' + googledns: 'tcp+udp://dns.google.com:53' } routing { # According to the request of dns query, decide to use which DNS upstream.