router_test.go 89 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705
  1. package dns
  2. import (
  3. "context"
  4. "net"
  5. "net/netip"
  6. "strings"
  7. "sync"
  8. "testing"
  9. "time"
  10. "github.com/sagernet/sing-box/adapter"
  11. C "github.com/sagernet/sing-box/constant"
  12. "github.com/sagernet/sing-box/experimental/deprecated"
  13. "github.com/sagernet/sing-box/log"
  14. "github.com/sagernet/sing-box/option"
  15. rulepkg "github.com/sagernet/sing-box/route/rule"
  16. "github.com/sagernet/sing-tun"
  17. E "github.com/sagernet/sing/common/exceptions"
  18. "github.com/sagernet/sing/common/json/badoption"
  19. N "github.com/sagernet/sing/common/network"
  20. "github.com/sagernet/sing/common/x/list"
  21. "github.com/sagernet/sing/service"
  22. mDNS "github.com/miekg/dns"
  23. "github.com/stretchr/testify/require"
  24. "go4.org/netipx"
  25. )
  26. type fakeDNSTransport struct {
  27. tag string
  28. transportType string
  29. }
  30. func (t *fakeDNSTransport) Start(adapter.StartStage) error { return nil }
  31. func (t *fakeDNSTransport) Close() error { return nil }
  32. func (t *fakeDNSTransport) Type() string { return t.transportType }
  33. func (t *fakeDNSTransport) Tag() string { return t.tag }
  34. func (t *fakeDNSTransport) Dependencies() []string { return nil }
  35. func (t *fakeDNSTransport) Reset() {}
  36. func (t *fakeDNSTransport) Exchange(context.Context, *mDNS.Msg) (*mDNS.Msg, error) {
  37. return nil, E.New("unused transport exchange")
  38. }
  39. type fakeDNSTransportManager struct {
  40. defaultTransport adapter.DNSTransport
  41. transports map[string]adapter.DNSTransport
  42. }
  43. func (m *fakeDNSTransportManager) Start(adapter.StartStage) error { return nil }
  44. func (m *fakeDNSTransportManager) Close() error { return nil }
  45. func (m *fakeDNSTransportManager) Transports() []adapter.DNSTransport {
  46. transports := make([]adapter.DNSTransport, 0, len(m.transports))
  47. for _, transport := range m.transports {
  48. transports = append(transports, transport)
  49. }
  50. return transports
  51. }
  52. func (m *fakeDNSTransportManager) Transport(tag string) (adapter.DNSTransport, bool) {
  53. transport, loaded := m.transports[tag]
  54. return transport, loaded
  55. }
  56. func (m *fakeDNSTransportManager) Default() adapter.DNSTransport { return m.defaultTransport }
  57. func (m *fakeDNSTransportManager) FakeIP() adapter.FakeIPTransport {
  58. return nil
  59. }
  60. func (m *fakeDNSTransportManager) Remove(string) error { return nil }
  61. func (m *fakeDNSTransportManager) Create(context.Context, log.ContextLogger, string, string, any) error {
  62. return E.New("unsupported")
  63. }
  64. type fakeDNSClient struct {
  65. beforeExchange func(ctx context.Context, transport adapter.DNSTransport, message *mDNS.Msg)
  66. exchange func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error)
  67. lookupWithCtx func(ctx context.Context, transport adapter.DNSTransport, domain string, options adapter.DNSQueryOptions) ([]netip.Addr, *mDNS.Msg, error)
  68. lookup func(transport adapter.DNSTransport, domain string, options adapter.DNSQueryOptions) ([]netip.Addr, *mDNS.Msg, error)
  69. }
  70. type fakeDeprecatedManager struct {
  71. features []deprecated.Note
  72. }
  73. type fakeRouter struct {
  74. access sync.RWMutex
  75. ruleSets map[string]adapter.RuleSet
  76. }
  77. func (r *fakeRouter) Start(adapter.StartStage) error { return nil }
  78. func (r *fakeRouter) Close() error { return nil }
  79. func (r *fakeRouter) PreMatch(metadata adapter.InboundContext, _ tun.DirectRouteContext, _ time.Duration, _ bool) (tun.DirectRouteDestination, error) {
  80. return nil, nil
  81. }
  82. func (r *fakeRouter) RouteConnection(context.Context, net.Conn, adapter.InboundContext) error {
  83. return nil
  84. }
  85. func (r *fakeRouter) RoutePacketConnection(context.Context, N.PacketConn, adapter.InboundContext) error {
  86. return nil
  87. }
  88. func (r *fakeRouter) RouteConnectionEx(context.Context, net.Conn, adapter.InboundContext, N.CloseHandlerFunc) {
  89. }
  90. func (r *fakeRouter) RoutePacketConnectionEx(context.Context, N.PacketConn, adapter.InboundContext, N.CloseHandlerFunc) {
  91. }
  92. func (r *fakeRouter) RuleSet(tag string) (adapter.RuleSet, bool) {
  93. r.access.RLock()
  94. defer r.access.RUnlock()
  95. ruleSet, loaded := r.ruleSets[tag]
  96. return ruleSet, loaded
  97. }
  98. func (r *fakeRouter) setRuleSet(tag string, ruleSet adapter.RuleSet) {
  99. r.access.Lock()
  100. defer r.access.Unlock()
  101. if r.ruleSets == nil {
  102. r.ruleSets = make(map[string]adapter.RuleSet)
  103. }
  104. r.ruleSets[tag] = ruleSet
  105. }
  106. func (r *fakeRouter) Rules() []adapter.Rule { return nil }
  107. func (r *fakeRouter) NeedFindProcess() bool { return false }
  108. func (r *fakeRouter) NeedFindNeighbor() bool { return false }
  109. func (r *fakeRouter) NeighborResolver() adapter.NeighborResolver { return nil }
  110. func (r *fakeRouter) AppendTracker(adapter.ConnectionTracker) {}
  111. func (r *fakeRouter) ResetNetwork() {}
  112. type fakeRuleSet struct {
  113. access sync.Mutex
  114. metadata adapter.RuleSetMetadata
  115. metadataRead func(adapter.RuleSetMetadata) adapter.RuleSetMetadata
  116. match func(*adapter.InboundContext) bool
  117. callbacks list.List[adapter.RuleSetUpdateCallback]
  118. refs int
  119. afterIncrementReference func()
  120. beforeDecrementReference func()
  121. }
  122. func (s *fakeRuleSet) Name() string { return "fake-rule-set" }
  123. func (s *fakeRuleSet) StartContext(context.Context, *adapter.HTTPStartContext) error { return nil }
  124. func (s *fakeRuleSet) PostStart() error { return nil }
  125. func (s *fakeRuleSet) Metadata() adapter.RuleSetMetadata {
  126. s.access.Lock()
  127. metadata := s.metadata
  128. metadataRead := s.metadataRead
  129. s.access.Unlock()
  130. if metadataRead != nil {
  131. return metadataRead(metadata)
  132. }
  133. return metadata
  134. }
  135. func (s *fakeRuleSet) ExtractIPSet() []*netipx.IPSet { return nil }
  136. func (s *fakeRuleSet) IncRef() {
  137. s.access.Lock()
  138. s.refs++
  139. afterIncrementReference := s.afterIncrementReference
  140. s.access.Unlock()
  141. if afterIncrementReference != nil {
  142. afterIncrementReference()
  143. }
  144. }
  145. func (s *fakeRuleSet) DecRef() {
  146. s.access.Lock()
  147. beforeDecrementReference := s.beforeDecrementReference
  148. s.access.Unlock()
  149. if beforeDecrementReference != nil {
  150. beforeDecrementReference()
  151. }
  152. s.access.Lock()
  153. defer s.access.Unlock()
  154. s.refs--
  155. if s.refs < 0 {
  156. panic("rule-set: negative refs")
  157. }
  158. }
  159. func (s *fakeRuleSet) Cleanup() {}
  160. func (s *fakeRuleSet) RegisterCallback(callback adapter.RuleSetUpdateCallback) *list.Element[adapter.RuleSetUpdateCallback] {
  161. s.access.Lock()
  162. defer s.access.Unlock()
  163. return s.callbacks.PushBack(callback)
  164. }
  165. func (s *fakeRuleSet) UnregisterCallback(element *list.Element[adapter.RuleSetUpdateCallback]) {
  166. s.access.Lock()
  167. defer s.access.Unlock()
  168. s.callbacks.Remove(element)
  169. }
  170. func (s *fakeRuleSet) Close() error { return nil }
  171. func (s *fakeRuleSet) Match(metadata *adapter.InboundContext) bool {
  172. s.access.Lock()
  173. match := s.match
  174. s.access.Unlock()
  175. if match != nil {
  176. return match(metadata)
  177. }
  178. return true
  179. }
  180. func (s *fakeRuleSet) String() string { return "fake-rule-set" }
  181. func (s *fakeRuleSet) updateMetadata(metadata adapter.RuleSetMetadata) {
  182. s.access.Lock()
  183. s.metadata = metadata
  184. callbacks := s.callbacks.Array()
  185. s.access.Unlock()
  186. for _, callback := range callbacks {
  187. callback(s)
  188. }
  189. }
  190. func (s *fakeRuleSet) snapshotCallbacks() []adapter.RuleSetUpdateCallback {
  191. s.access.Lock()
  192. defer s.access.Unlock()
  193. return s.callbacks.Array()
  194. }
  195. func (s *fakeRuleSet) refCount() int {
  196. s.access.Lock()
  197. defer s.access.Unlock()
  198. return s.refs
  199. }
  200. func (m *fakeDeprecatedManager) ReportDeprecated(feature deprecated.Note) {
  201. m.features = append(m.features, feature)
  202. }
  203. func (c *fakeDNSClient) Start() {}
  204. func (c *fakeDNSClient) Exchange(ctx context.Context, transport adapter.DNSTransport, message *mDNS.Msg, _ adapter.DNSQueryOptions, _ func(*mDNS.Msg) bool) (*mDNS.Msg, error) {
  205. if c.beforeExchange != nil {
  206. c.beforeExchange(ctx, transport, message)
  207. }
  208. if c.exchange == nil {
  209. if len(message.Question) != 1 {
  210. return nil, E.New("unused client exchange")
  211. }
  212. var (
  213. addresses []netip.Addr
  214. response *mDNS.Msg
  215. err error
  216. )
  217. if c.lookupWithCtx != nil {
  218. addresses, response, err = c.lookupWithCtx(ctx, transport, FqdnToDomain(message.Question[0].Name), adapter.DNSQueryOptions{})
  219. } else if c.lookup != nil {
  220. addresses, response, err = c.lookup(transport, FqdnToDomain(message.Question[0].Name), adapter.DNSQueryOptions{})
  221. } else {
  222. return nil, E.New("unused client exchange")
  223. }
  224. if err != nil {
  225. return nil, err
  226. }
  227. if response != nil {
  228. return response, nil
  229. }
  230. return FixedResponse(0, message.Question[0], addresses, 60), nil
  231. }
  232. return c.exchange(transport, message)
  233. }
  234. func (c *fakeDNSClient) Lookup(ctx context.Context, transport adapter.DNSTransport, domain string, options adapter.DNSQueryOptions, responseChecker func(*mDNS.Msg) bool) ([]netip.Addr, error) {
  235. if c.lookup == nil && c.lookupWithCtx == nil {
  236. return nil, E.New("unused client lookup")
  237. }
  238. var (
  239. addresses []netip.Addr
  240. response *mDNS.Msg
  241. err error
  242. )
  243. if c.lookupWithCtx != nil {
  244. addresses, response, err = c.lookupWithCtx(ctx, transport, domain, options)
  245. } else {
  246. addresses, response, err = c.lookup(transport, domain, options)
  247. }
  248. if err != nil {
  249. return nil, err
  250. }
  251. if response == nil {
  252. response = FixedResponse(0, fixedQuestion(domain, mDNS.TypeA), addresses, 60)
  253. }
  254. if responseChecker != nil && !responseChecker(response) {
  255. return nil, ErrResponseRejected
  256. }
  257. if addresses != nil {
  258. return addresses, nil
  259. }
  260. return MessageToAddresses(response), nil
  261. }
  262. func (c *fakeDNSClient) ClearCache() {}
  263. func newTestRouter(t *testing.T, rules []option.DNSRule, transportManager *fakeDNSTransportManager, client *fakeDNSClient) *Router {
  264. router := newTestRouterWithContext(t, context.Background(), rules, transportManager, client)
  265. t.Cleanup(func() {
  266. router.Close()
  267. })
  268. return router
  269. }
  270. func newTestRouterWithContext(t *testing.T, ctx context.Context, rules []option.DNSRule, transportManager *fakeDNSTransportManager, client *fakeDNSClient) *Router {
  271. return newTestRouterWithContextAndLogger(t, ctx, rules, transportManager, client, log.NewNOPFactory().NewLogger("dns"))
  272. }
  273. func newTestRouterWithContextAndLogger(t *testing.T, ctx context.Context, rules []option.DNSRule, transportManager *fakeDNSTransportManager, client *fakeDNSClient, dnsLogger log.ContextLogger) *Router {
  274. t.Helper()
  275. router := &Router{
  276. ctx: ctx,
  277. logger: dnsLogger,
  278. transport: transportManager,
  279. client: client,
  280. rawRules: make([]option.DNSRule, 0, len(rules)),
  281. rules: make([]adapter.DNSRule, 0, len(rules)),
  282. defaultDomainStrategy: C.DomainStrategyAsIS,
  283. }
  284. if rules != nil {
  285. err := router.Initialize(rules)
  286. require.NoError(t, err)
  287. err = router.Start(adapter.StartStateStart)
  288. require.NoError(t, err)
  289. }
  290. return router
  291. }
  292. func waitForLogMessageContaining(t *testing.T, entries <-chan log.Entry, done <-chan struct{}, substring string) log.Entry {
  293. t.Helper()
  294. timeout := time.After(time.Second)
  295. for {
  296. select {
  297. case entry, ok := <-entries:
  298. if !ok {
  299. t.Fatal("log subscription closed")
  300. }
  301. if strings.Contains(entry.Message, substring) {
  302. return entry
  303. }
  304. case <-done:
  305. t.Fatal("log subscription closed")
  306. case <-timeout:
  307. t.Fatalf("timed out waiting for log message containing %q", substring)
  308. }
  309. }
  310. }
  311. func fixedQuestion(name string, qType uint16) mDNS.Question {
  312. return mDNS.Question{
  313. Name: mDNS.Fqdn(name),
  314. Qtype: qType,
  315. Qclass: mDNS.ClassINET,
  316. }
  317. }
  318. func mustRecord(t *testing.T, record string) option.DNSRecordOptions {
  319. t.Helper()
  320. var value option.DNSRecordOptions
  321. require.NoError(t, value.UnmarshalJSON([]byte(`"`+record+`"`)))
  322. return value
  323. }
  324. func TestInitializeRejectsDirectLegacyRuleWhenRuleSetForcesNew(t *testing.T) {
  325. t.Parallel()
  326. ctx := context.Background()
  327. ruleSet, err := rulepkg.NewRuleSet(ctx, log.NewNOPFactory().NewLogger("router"), option.RuleSet{
  328. Type: C.RuleSetTypeInline,
  329. Tag: "query-set",
  330. InlineOptions: option.PlainRuleSet{
  331. Rules: []option.HeadlessRule{{
  332. Type: C.RuleTypeDefault,
  333. DefaultOptions: option.DefaultHeadlessRule{
  334. QueryType: badoption.Listable[option.DNSQueryType]{option.DNSQueryType(mDNS.TypeA)},
  335. },
  336. }},
  337. },
  338. })
  339. require.NoError(t, err)
  340. ctx = service.ContextWith[adapter.Router](ctx, &fakeRouter{
  341. ruleSets: map[string]adapter.RuleSet{
  342. "query-set": ruleSet,
  343. },
  344. })
  345. router := &Router{
  346. ctx: ctx,
  347. logger: log.NewNOPFactory().NewLogger("dns"),
  348. transport: &fakeDNSTransportManager{},
  349. client: &fakeDNSClient{},
  350. rawRules: make([]option.DNSRule, 0, 2),
  351. defaultDomainStrategy: C.DomainStrategyAsIS,
  352. }
  353. err = router.Initialize([]option.DNSRule{
  354. {
  355. Type: C.RuleTypeDefault,
  356. DefaultOptions: option.DefaultDNSRule{
  357. RawDefaultDNSRule: option.RawDefaultDNSRule{
  358. RuleSet: badoption.Listable[string]{"query-set"},
  359. },
  360. DNSRuleAction: option.DNSRuleAction{
  361. Action: C.RuleActionTypeRoute,
  362. RouteOptions: option.DNSRouteActionOptions{Server: "default"},
  363. },
  364. },
  365. },
  366. {
  367. Type: C.RuleTypeDefault,
  368. DefaultOptions: option.DefaultDNSRule{
  369. RawDefaultDNSRule: option.RawDefaultDNSRule{
  370. IPIsPrivate: true,
  371. },
  372. DNSRuleAction: option.DNSRuleAction{
  373. Action: C.RuleActionTypeRoute,
  374. RouteOptions: option.DNSRouteActionOptions{Server: "private"},
  375. },
  376. },
  377. },
  378. })
  379. require.ErrorContains(t, err, "Response Match Fields")
  380. require.ErrorContains(t, err, "require match_response")
  381. }
  382. func TestLookupLegacyDNSModeDefersRuleSetDestinationIPMatch(t *testing.T) {
  383. t.Parallel()
  384. ctx := context.Background()
  385. ruleSet, err := rulepkg.NewRuleSet(ctx, log.NewNOPFactory().NewLogger("router"), option.RuleSet{
  386. Type: C.RuleSetTypeInline,
  387. Tag: "legacy-ipcidr-set",
  388. InlineOptions: option.PlainRuleSet{
  389. Rules: []option.HeadlessRule{{
  390. Type: C.RuleTypeDefault,
  391. DefaultOptions: option.DefaultHeadlessRule{
  392. IPCIDR: badoption.Listable[string]{"10.0.0.0/8"},
  393. },
  394. }},
  395. },
  396. })
  397. require.NoError(t, err)
  398. ctx = service.ContextWith[adapter.Router](ctx, &fakeRouter{
  399. ruleSets: map[string]adapter.RuleSet{
  400. "legacy-ipcidr-set": ruleSet,
  401. },
  402. })
  403. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  404. privateTransport := &fakeDNSTransport{tag: "private", transportType: C.DNSTypeUDP}
  405. router := newTestRouterWithContext(t, ctx, []option.DNSRule{{
  406. Type: C.RuleTypeDefault,
  407. DefaultOptions: option.DefaultDNSRule{
  408. RawDefaultDNSRule: option.RawDefaultDNSRule{
  409. RuleSet: badoption.Listable[string]{"legacy-ipcidr-set"},
  410. },
  411. DNSRuleAction: option.DNSRuleAction{
  412. Action: C.RuleActionTypeRoute,
  413. RouteOptions: option.DNSRouteActionOptions{Server: "private"},
  414. },
  415. },
  416. }}, &fakeDNSTransportManager{
  417. defaultTransport: defaultTransport,
  418. transports: map[string]adapter.DNSTransport{
  419. "default": defaultTransport,
  420. "private": privateTransport,
  421. },
  422. }, &fakeDNSClient{
  423. lookup: func(transport adapter.DNSTransport, domain string, options adapter.DNSQueryOptions) ([]netip.Addr, *mDNS.Msg, error) {
  424. require.Equal(t, "example.com", domain)
  425. require.Equal(t, "private", transport.Tag())
  426. response := FixedResponse(0, fixedQuestion(domain, mDNS.TypeA), []netip.Addr{netip.MustParseAddr("10.0.0.1")}, 60)
  427. return MessageToAddresses(response), response, nil
  428. },
  429. })
  430. require.True(t, router.legacyDNSMode)
  431. addresses, err := router.Lookup(context.Background(), "example.com", adapter.DNSQueryOptions{
  432. LookupStrategy: C.DomainStrategyIPv4Only,
  433. })
  434. require.NoError(t, err)
  435. require.Equal(t, []netip.Addr{netip.MustParseAddr("10.0.0.1")}, addresses)
  436. }
  437. func TestRuleSetUpdateReleasesOldRuleSetRefs(t *testing.T) {
  438. t.Parallel()
  439. fakeSet := &fakeRuleSet{}
  440. ctx := service.ContextWith[adapter.Router](context.Background(), &fakeRouter{
  441. ruleSets: map[string]adapter.RuleSet{
  442. "dynamic-set": fakeSet,
  443. },
  444. })
  445. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  446. router := newTestRouterWithContext(t, ctx, []option.DNSRule{{
  447. Type: C.RuleTypeDefault,
  448. DefaultOptions: option.DefaultDNSRule{
  449. RawDefaultDNSRule: option.RawDefaultDNSRule{
  450. RuleSet: badoption.Listable[string]{"dynamic-set"},
  451. },
  452. DNSRuleAction: option.DNSRuleAction{
  453. Action: C.RuleActionTypeRoute,
  454. RouteOptions: option.DNSRouteActionOptions{Server: "default"},
  455. },
  456. },
  457. }}, &fakeDNSTransportManager{
  458. defaultTransport: defaultTransport,
  459. transports: map[string]adapter.DNSTransport{
  460. "default": defaultTransport,
  461. },
  462. }, &fakeDNSClient{})
  463. require.Equal(t, 1, fakeSet.refCount())
  464. fakeSet.updateMetadata(adapter.RuleSetMetadata{})
  465. require.Equal(t, 1, fakeSet.refCount())
  466. fakeSet.updateMetadata(adapter.RuleSetMetadata{})
  467. require.Equal(t, 1, fakeSet.refCount())
  468. require.NoError(t, router.Close())
  469. require.Zero(t, fakeSet.refCount())
  470. }
  471. func TestValidateRuleSetMetadataUpdateRejectsRuleSetThatWouldDisableLegacyDNSMode(t *testing.T) {
  472. t.Parallel()
  473. fakeSet := &fakeRuleSet{
  474. metadata: adapter.RuleSetMetadata{
  475. ContainsIPCIDRRule: true,
  476. },
  477. }
  478. routerService := &fakeRouter{
  479. ruleSets: map[string]adapter.RuleSet{
  480. "dynamic-set": fakeSet,
  481. },
  482. }
  483. ctx := service.ContextWith[adapter.Router](context.Background(), routerService)
  484. router := newTestRouterWithContext(t, ctx, []option.DNSRule{
  485. {
  486. Type: C.RuleTypeDefault,
  487. DefaultOptions: option.DefaultDNSRule{
  488. RawDefaultDNSRule: option.RawDefaultDNSRule{
  489. RuleSet: badoption.Listable[string]{"dynamic-set"},
  490. },
  491. DNSRuleAction: option.DNSRuleAction{
  492. Action: C.RuleActionTypeRoute,
  493. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  494. },
  495. },
  496. },
  497. {
  498. Type: C.RuleTypeDefault,
  499. DefaultOptions: option.DefaultDNSRule{
  500. RawDefaultDNSRule: option.RawDefaultDNSRule{
  501. IPIsPrivate: true,
  502. },
  503. DNSRuleAction: option.DNSRuleAction{
  504. Action: C.RuleActionTypeRoute,
  505. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  506. },
  507. },
  508. },
  509. }, &fakeDNSTransportManager{
  510. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  511. transports: map[string]adapter.DNSTransport{
  512. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  513. "selected": &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP},
  514. },
  515. }, &fakeDNSClient{
  516. lookup: func(adapter.DNSTransport, string, adapter.DNSQueryOptions) ([]netip.Addr, *mDNS.Msg, error) {
  517. return []netip.Addr{netip.MustParseAddr("10.0.0.1")}, nil, nil
  518. },
  519. })
  520. require.True(t, router.legacyDNSMode)
  521. err := router.ValidateRuleSetMetadataUpdate("dynamic-set", adapter.RuleSetMetadata{
  522. ContainsDNSQueryTypeRule: true,
  523. })
  524. require.ErrorContains(t, err, "require match_response")
  525. }
  526. func TestValidateRuleSetMetadataUpdateRejectsRuleSetOnlyLegacyModeSwitchToNew(t *testing.T) {
  527. t.Parallel()
  528. fakeSet := &fakeRuleSet{
  529. metadata: adapter.RuleSetMetadata{
  530. ContainsIPCIDRRule: true,
  531. },
  532. }
  533. routerService := &fakeRouter{
  534. ruleSets: map[string]adapter.RuleSet{
  535. "dynamic-set": fakeSet,
  536. },
  537. }
  538. ctx := service.ContextWith[adapter.Router](context.Background(), routerService)
  539. router := newTestRouterWithContext(t, ctx, []option.DNSRule{{
  540. Type: C.RuleTypeDefault,
  541. DefaultOptions: option.DefaultDNSRule{
  542. RawDefaultDNSRule: option.RawDefaultDNSRule{
  543. RuleSet: badoption.Listable[string]{"dynamic-set"},
  544. },
  545. DNSRuleAction: option.DNSRuleAction{
  546. Action: C.RuleActionTypeRoute,
  547. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  548. },
  549. },
  550. }}, &fakeDNSTransportManager{
  551. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  552. transports: map[string]adapter.DNSTransport{
  553. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  554. "selected": &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP},
  555. },
  556. }, &fakeDNSClient{
  557. lookup: func(adapter.DNSTransport, string, adapter.DNSQueryOptions) ([]netip.Addr, *mDNS.Msg, error) {
  558. return []netip.Addr{netip.MustParseAddr("10.0.0.1")}, nil, nil
  559. },
  560. })
  561. require.True(t, router.legacyDNSMode)
  562. err := router.ValidateRuleSetMetadataUpdate("dynamic-set", adapter.RuleSetMetadata{
  563. ContainsIPCIDRRule: true,
  564. ContainsDNSQueryTypeRule: true,
  565. })
  566. require.ErrorContains(t, err, "Address Filter Fields")
  567. }
  568. func TestValidateRuleSetMetadataUpdateBeforeStartUsesStartupValidation(t *testing.T) {
  569. t.Parallel()
  570. fakeSet := &fakeRuleSet{}
  571. routerService := &fakeRouter{
  572. ruleSets: map[string]adapter.RuleSet{
  573. "dynamic-set": fakeSet,
  574. },
  575. }
  576. ctx := service.ContextWith[adapter.Router](context.Background(), routerService)
  577. router := &Router{
  578. ctx: ctx,
  579. logger: log.NewNOPFactory().NewLogger("dns"),
  580. transport: &fakeDNSTransportManager{},
  581. client: &fakeDNSClient{},
  582. rawRules: make([]option.DNSRule, 0, 2),
  583. rules: make([]adapter.DNSRule, 0, 2),
  584. defaultDomainStrategy: C.DomainStrategyAsIS,
  585. }
  586. err := router.Initialize([]option.DNSRule{
  587. {
  588. Type: C.RuleTypeDefault,
  589. DefaultOptions: option.DefaultDNSRule{
  590. RawDefaultDNSRule: option.RawDefaultDNSRule{
  591. RuleSet: badoption.Listable[string]{"dynamic-set"},
  592. },
  593. DNSRuleAction: option.DNSRuleAction{
  594. Action: C.RuleActionTypeRoute,
  595. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  596. },
  597. },
  598. },
  599. {
  600. Type: C.RuleTypeDefault,
  601. DefaultOptions: option.DefaultDNSRule{
  602. RawDefaultDNSRule: option.RawDefaultDNSRule{
  603. IPIsPrivate: true,
  604. },
  605. DNSRuleAction: option.DNSRuleAction{
  606. Action: C.RuleActionTypeRoute,
  607. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  608. },
  609. },
  610. },
  611. })
  612. require.NoError(t, err)
  613. require.False(t, router.started)
  614. err = router.ValidateRuleSetMetadataUpdate("dynamic-set", adapter.RuleSetMetadata{
  615. ContainsDNSQueryTypeRule: true,
  616. })
  617. require.ErrorContains(t, err, "require match_response")
  618. }
  619. func TestValidateRuleSetMetadataUpdateRejectsRuleSetThatWouldRequireLegacyDNSMode(t *testing.T) {
  620. t.Parallel()
  621. fakeSet := &fakeRuleSet{}
  622. routerService := &fakeRouter{
  623. ruleSets: map[string]adapter.RuleSet{
  624. "dynamic-set": fakeSet,
  625. },
  626. }
  627. ctx := service.ContextWith[adapter.Router](context.Background(), routerService)
  628. router := newTestRouterWithContext(t, ctx, []option.DNSRule{{
  629. Type: C.RuleTypeDefault,
  630. DefaultOptions: option.DefaultDNSRule{
  631. RawDefaultDNSRule: option.RawDefaultDNSRule{
  632. RuleSet: badoption.Listable[string]{"dynamic-set"},
  633. },
  634. DNSRuleAction: option.DNSRuleAction{
  635. Action: C.RuleActionTypeRoute,
  636. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  637. },
  638. },
  639. }}, &fakeDNSTransportManager{
  640. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  641. transports: map[string]adapter.DNSTransport{
  642. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  643. "selected": &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP},
  644. },
  645. }, &fakeDNSClient{
  646. lookup: func(adapter.DNSTransport, string, adapter.DNSQueryOptions) ([]netip.Addr, *mDNS.Msg, error) {
  647. return []netip.Addr{netip.MustParseAddr("1.1.1.1")}, nil, nil
  648. },
  649. })
  650. require.False(t, router.legacyDNSMode)
  651. err := router.ValidateRuleSetMetadataUpdate("dynamic-set", adapter.RuleSetMetadata{
  652. ContainsIPCIDRRule: true,
  653. })
  654. require.ErrorContains(t, err, "Address Filter Fields")
  655. }
  656. func TestValidateRuleSetMetadataUpdateAllowsRuleSetThatKeepsNonLegacyDNSMode(t *testing.T) {
  657. t.Parallel()
  658. fakeSet := &fakeRuleSet{}
  659. routerService := &fakeRouter{
  660. ruleSets: map[string]adapter.RuleSet{
  661. "dynamic-set": fakeSet,
  662. },
  663. }
  664. ctx := service.ContextWith[adapter.Router](context.Background(), routerService)
  665. router := newTestRouterWithContext(t, ctx, []option.DNSRule{
  666. {
  667. Type: C.RuleTypeDefault,
  668. DefaultOptions: option.DefaultDNSRule{
  669. RawDefaultDNSRule: option.RawDefaultDNSRule{
  670. Domain: badoption.Listable[string]{"example.com"},
  671. },
  672. DNSRuleAction: option.DNSRuleAction{
  673. Action: C.RuleActionTypeEvaluate,
  674. RouteOptions: option.DNSRouteActionOptions{Server: "upstream"},
  675. },
  676. },
  677. },
  678. {
  679. Type: C.RuleTypeDefault,
  680. DefaultOptions: option.DefaultDNSRule{
  681. RawDefaultDNSRule: option.RawDefaultDNSRule{
  682. RuleSet: badoption.Listable[string]{"dynamic-set"},
  683. },
  684. DNSRuleAction: option.DNSRuleAction{
  685. Action: C.RuleActionTypeRoute,
  686. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  687. },
  688. },
  689. },
  690. }, &fakeDNSTransportManager{
  691. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  692. transports: map[string]adapter.DNSTransport{
  693. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  694. "selected": &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP},
  695. "upstream": &fakeDNSTransport{tag: "upstream", transportType: C.DNSTypeUDP},
  696. },
  697. }, &fakeDNSClient{})
  698. require.False(t, router.legacyDNSMode)
  699. err := router.ValidateRuleSetMetadataUpdate("dynamic-set", adapter.RuleSetMetadata{
  700. ContainsIPCIDRRule: true,
  701. ContainsNonIPCIDRRule: true,
  702. })
  703. require.NoError(t, err)
  704. }
  705. func TestValidateRuleSetMetadataUpdateAllowsRelaxingLegacyRequirement(t *testing.T) {
  706. t.Parallel()
  707. fakeSet := &fakeRuleSet{
  708. metadata: adapter.RuleSetMetadata{
  709. ContainsIPCIDRRule: true,
  710. },
  711. }
  712. routerService := &fakeRouter{
  713. ruleSets: map[string]adapter.RuleSet{
  714. "dynamic-set": fakeSet,
  715. },
  716. }
  717. ctx := service.ContextWith[adapter.Router](context.Background(), routerService)
  718. router := newTestRouterWithContext(t, ctx, []option.DNSRule{{
  719. Type: C.RuleTypeDefault,
  720. DefaultOptions: option.DefaultDNSRule{
  721. RawDefaultDNSRule: option.RawDefaultDNSRule{
  722. RuleSet: badoption.Listable[string]{"dynamic-set"},
  723. },
  724. DNSRuleAction: option.DNSRuleAction{
  725. Action: C.RuleActionTypeRoute,
  726. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  727. },
  728. },
  729. }}, &fakeDNSTransportManager{
  730. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  731. transports: map[string]adapter.DNSTransport{
  732. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  733. "selected": &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP},
  734. },
  735. }, &fakeDNSClient{
  736. lookup: func(adapter.DNSTransport, string, adapter.DNSQueryOptions) ([]netip.Addr, *mDNS.Msg, error) {
  737. return []netip.Addr{netip.MustParseAddr("10.0.0.1")}, nil, nil
  738. },
  739. })
  740. require.True(t, router.legacyDNSMode)
  741. err := router.ValidateRuleSetMetadataUpdate("dynamic-set", adapter.RuleSetMetadata{})
  742. require.NoError(t, err)
  743. }
  744. func TestInitializeRejectsPureIPRuleSetWhenLegacyDNSModeDisabled(t *testing.T) {
  745. t.Parallel()
  746. fakeSet := &fakeRuleSet{
  747. metadata: adapter.RuleSetMetadata{
  748. ContainsIPCIDRRule: true,
  749. },
  750. }
  751. routerService := &fakeRouter{
  752. ruleSets: map[string]adapter.RuleSet{
  753. "pure-ip": fakeSet,
  754. },
  755. }
  756. ctx := service.ContextWith[adapter.Router](context.Background(), routerService)
  757. router := &Router{
  758. ctx: ctx,
  759. logger: log.NewNOPFactory().NewLogger("dns"),
  760. transport: &fakeDNSTransportManager{},
  761. client: &fakeDNSClient{},
  762. rawRules: make([]option.DNSRule, 0, 2),
  763. rules: make([]adapter.DNSRule, 0, 2),
  764. defaultDomainStrategy: C.DomainStrategyAsIS,
  765. }
  766. err := router.Initialize([]option.DNSRule{
  767. {
  768. Type: C.RuleTypeDefault,
  769. DefaultOptions: option.DefaultDNSRule{
  770. RawDefaultDNSRule: option.RawDefaultDNSRule{
  771. QueryType: badoption.Listable[option.DNSQueryType]{option.DNSQueryType(mDNS.TypeA)},
  772. },
  773. DNSRuleAction: option.DNSRuleAction{
  774. Action: C.RuleActionTypeRoute,
  775. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  776. },
  777. },
  778. },
  779. {
  780. Type: C.RuleTypeDefault,
  781. DefaultOptions: option.DefaultDNSRule{
  782. RawDefaultDNSRule: option.RawDefaultDNSRule{
  783. RuleSet: badoption.Listable[string]{"pure-ip"},
  784. },
  785. DNSRuleAction: option.DNSRuleAction{
  786. Action: C.RuleActionTypeRoute,
  787. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  788. },
  789. },
  790. },
  791. })
  792. require.ErrorContains(t, err, "Address Filter Fields")
  793. }
  794. func TestInitializeAllowsMixedRuleSetWhenLegacyDNSModeDisabled(t *testing.T) {
  795. t.Parallel()
  796. fakeSet := &fakeRuleSet{
  797. metadata: adapter.RuleSetMetadata{
  798. ContainsIPCIDRRule: true,
  799. ContainsNonIPCIDRRule: true,
  800. },
  801. }
  802. routerService := &fakeRouter{
  803. ruleSets: map[string]adapter.RuleSet{
  804. "mixed": fakeSet,
  805. },
  806. }
  807. ctx := service.ContextWith[adapter.Router](context.Background(), routerService)
  808. router := newTestRouterWithContext(t, ctx, []option.DNSRule{
  809. {
  810. Type: C.RuleTypeDefault,
  811. DefaultOptions: option.DefaultDNSRule{
  812. RawDefaultDNSRule: option.RawDefaultDNSRule{
  813. QueryType: badoption.Listable[option.DNSQueryType]{option.DNSQueryType(mDNS.TypeA)},
  814. },
  815. DNSRuleAction: option.DNSRuleAction{
  816. Action: C.RuleActionTypeRoute,
  817. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  818. },
  819. },
  820. },
  821. {
  822. Type: C.RuleTypeDefault,
  823. DefaultOptions: option.DefaultDNSRule{
  824. RawDefaultDNSRule: option.RawDefaultDNSRule{
  825. RuleSet: badoption.Listable[string]{"mixed"},
  826. },
  827. DNSRuleAction: option.DNSRuleAction{
  828. Action: C.RuleActionTypeRoute,
  829. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  830. },
  831. },
  832. },
  833. }, &fakeDNSTransportManager{
  834. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  835. transports: map[string]adapter.DNSTransport{
  836. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  837. "selected": &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP},
  838. },
  839. }, &fakeDNSClient{})
  840. require.False(t, router.legacyDNSMode)
  841. }
  842. func TestValidateRuleSetMetadataUpdateRejectsRuleSetFlippingToPureIP(t *testing.T) {
  843. t.Parallel()
  844. fakeSet := &fakeRuleSet{
  845. metadata: adapter.RuleSetMetadata{
  846. ContainsIPCIDRRule: true,
  847. ContainsNonIPCIDRRule: true,
  848. },
  849. }
  850. routerService := &fakeRouter{
  851. ruleSets: map[string]adapter.RuleSet{
  852. "mixed": fakeSet,
  853. },
  854. }
  855. ctx := service.ContextWith[adapter.Router](context.Background(), routerService)
  856. router := newTestRouterWithContext(t, ctx, []option.DNSRule{
  857. {
  858. Type: C.RuleTypeDefault,
  859. DefaultOptions: option.DefaultDNSRule{
  860. RawDefaultDNSRule: option.RawDefaultDNSRule{
  861. QueryType: badoption.Listable[option.DNSQueryType]{option.DNSQueryType(mDNS.TypeA)},
  862. },
  863. DNSRuleAction: option.DNSRuleAction{
  864. Action: C.RuleActionTypeRoute,
  865. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  866. },
  867. },
  868. },
  869. {
  870. Type: C.RuleTypeDefault,
  871. DefaultOptions: option.DefaultDNSRule{
  872. RawDefaultDNSRule: option.RawDefaultDNSRule{
  873. RuleSet: badoption.Listable[string]{"mixed"},
  874. },
  875. DNSRuleAction: option.DNSRuleAction{
  876. Action: C.RuleActionTypeRoute,
  877. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  878. },
  879. },
  880. },
  881. }, &fakeDNSTransportManager{
  882. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  883. transports: map[string]adapter.DNSTransport{
  884. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  885. "selected": &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP},
  886. },
  887. }, &fakeDNSClient{})
  888. require.False(t, router.legacyDNSMode)
  889. err := router.ValidateRuleSetMetadataUpdate("mixed", adapter.RuleSetMetadata{
  890. ContainsIPCIDRRule: true,
  891. })
  892. require.ErrorContains(t, err, "Address Filter Fields")
  893. }
  894. func TestCloseWaitsForInFlightLookupUntilContextCancellation(t *testing.T) {
  895. t.Parallel()
  896. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  897. selectedTransport := &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP}
  898. lookupStarted := make(chan struct{})
  899. var lookupStartedOnce sync.Once
  900. router := newTestRouter(t, []option.DNSRule{{
  901. Type: C.RuleTypeDefault,
  902. DefaultOptions: option.DefaultDNSRule{
  903. RawDefaultDNSRule: option.RawDefaultDNSRule{
  904. Domain: badoption.Listable[string]{"example.com"},
  905. },
  906. DNSRuleAction: option.DNSRuleAction{
  907. Action: C.RuleActionTypeRoute,
  908. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  909. },
  910. },
  911. }}, &fakeDNSTransportManager{
  912. defaultTransport: defaultTransport,
  913. transports: map[string]adapter.DNSTransport{
  914. "default": defaultTransport,
  915. "selected": selectedTransport,
  916. },
  917. }, &fakeDNSClient{
  918. lookupWithCtx: func(ctx context.Context, transport adapter.DNSTransport, domain string, options adapter.DNSQueryOptions) ([]netip.Addr, *mDNS.Msg, error) {
  919. require.Equal(t, "selected", transport.Tag())
  920. require.Equal(t, "example.com", domain)
  921. lookupStartedOnce.Do(func() {
  922. close(lookupStarted)
  923. })
  924. <-ctx.Done()
  925. return nil, nil, ctx.Err()
  926. },
  927. })
  928. lookupCtx, cancelLookup := context.WithCancel(context.Background())
  929. defer cancelLookup()
  930. var (
  931. lookupErr error
  932. closeErr error
  933. )
  934. lookupDone := make(chan struct{})
  935. go func() {
  936. _, lookupErr = router.Lookup(lookupCtx, "example.com", adapter.DNSQueryOptions{})
  937. close(lookupDone)
  938. }()
  939. select {
  940. case <-lookupStarted:
  941. case <-time.After(time.Second):
  942. t.Fatal("lookup did not reach DNS client")
  943. }
  944. closeDone := make(chan struct{})
  945. go func() {
  946. closeErr = router.Close()
  947. close(closeDone)
  948. }()
  949. select {
  950. case <-closeDone:
  951. t.Fatal("close finished before lookup context cancellation")
  952. default:
  953. }
  954. cancelLookup()
  955. select {
  956. case <-lookupDone:
  957. case <-time.After(time.Second):
  958. t.Fatal("lookup did not finish after cancellation")
  959. }
  960. select {
  961. case <-closeDone:
  962. case <-time.After(time.Second):
  963. t.Fatal("close did not finish after lookup cancellation")
  964. }
  965. require.ErrorIs(t, lookupErr, context.Canceled)
  966. require.NoError(t, closeErr)
  967. }
  968. func TestLookupLegacyDNSModeDefersDirectDestinationIPMatch(t *testing.T) {
  969. t.Parallel()
  970. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  971. privateTransport := &fakeDNSTransport{tag: "private", transportType: C.DNSTypeUDP}
  972. client := &fakeDNSClient{
  973. lookup: func(transport adapter.DNSTransport, domain string, options adapter.DNSQueryOptions) ([]netip.Addr, *mDNS.Msg, error) {
  974. require.Equal(t, "example.com", domain)
  975. require.Equal(t, C.DomainStrategyIPv4Only, options.LookupStrategy)
  976. switch transport.Tag() {
  977. case "private":
  978. response := FixedResponse(0, fixedQuestion(domain, mDNS.TypeA), []netip.Addr{netip.MustParseAddr("10.0.0.1")}, 60)
  979. return MessageToAddresses(response), response, nil
  980. case "default":
  981. t.Fatal("default transport should not be used when legacy rule matches after response")
  982. }
  983. return nil, nil, E.New("unexpected transport")
  984. },
  985. }
  986. router := newTestRouter(t, []option.DNSRule{{
  987. Type: C.RuleTypeDefault,
  988. DefaultOptions: option.DefaultDNSRule{
  989. RawDefaultDNSRule: option.RawDefaultDNSRule{
  990. IPIsPrivate: true,
  991. },
  992. DNSRuleAction: option.DNSRuleAction{
  993. Action: C.RuleActionTypeRoute,
  994. RouteOptions: option.DNSRouteActionOptions{Server: "private"},
  995. },
  996. },
  997. }}, &fakeDNSTransportManager{
  998. defaultTransport: defaultTransport,
  999. transports: map[string]adapter.DNSTransport{
  1000. "default": defaultTransport,
  1001. "private": privateTransport,
  1002. },
  1003. }, client)
  1004. require.True(t, router.legacyDNSMode)
  1005. addresses, err := router.Lookup(context.Background(), "example.com", adapter.DNSQueryOptions{
  1006. LookupStrategy: C.DomainStrategyIPv4Only,
  1007. })
  1008. require.NoError(t, err)
  1009. require.Equal(t, []netip.Addr{netip.MustParseAddr("10.0.0.1")}, addresses)
  1010. }
  1011. func TestLookupLegacyDNSModeFallsBackAfterRejectedAddressLimitResponse(t *testing.T) {
  1012. t.Parallel()
  1013. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  1014. privateTransport := &fakeDNSTransport{tag: "private", transportType: C.DNSTypeUDP}
  1015. var lookupAccess sync.Mutex
  1016. var lookupTags []string
  1017. recordLookup := func(tag string) {
  1018. lookupAccess.Lock()
  1019. lookupTags = append(lookupTags, tag)
  1020. lookupAccess.Unlock()
  1021. }
  1022. currentLookupTags := func() []string {
  1023. lookupAccess.Lock()
  1024. defer lookupAccess.Unlock()
  1025. return append([]string(nil), lookupTags...)
  1026. }
  1027. client := &fakeDNSClient{
  1028. lookup: func(transport adapter.DNSTransport, domain string, options adapter.DNSQueryOptions) ([]netip.Addr, *mDNS.Msg, error) {
  1029. require.Equal(t, "example.com", domain)
  1030. require.Equal(t, C.DomainStrategyIPv4Only, options.LookupStrategy)
  1031. recordLookup(transport.Tag())
  1032. switch transport.Tag() {
  1033. case "private":
  1034. response := FixedResponse(0, fixedQuestion(domain, mDNS.TypeA), []netip.Addr{netip.MustParseAddr("8.8.8.8")}, 60)
  1035. return MessageToAddresses(response), response, nil
  1036. case "default":
  1037. response := FixedResponse(0, fixedQuestion(domain, mDNS.TypeA), []netip.Addr{netip.MustParseAddr("9.9.9.9")}, 60)
  1038. return MessageToAddresses(response), response, nil
  1039. }
  1040. return nil, nil, E.New("unexpected transport")
  1041. },
  1042. }
  1043. router := newTestRouter(t, []option.DNSRule{{
  1044. Type: C.RuleTypeDefault,
  1045. DefaultOptions: option.DefaultDNSRule{
  1046. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1047. IPIsPrivate: true,
  1048. },
  1049. DNSRuleAction: option.DNSRuleAction{
  1050. Action: C.RuleActionTypeRoute,
  1051. RouteOptions: option.DNSRouteActionOptions{Server: "private"},
  1052. },
  1053. },
  1054. }}, &fakeDNSTransportManager{
  1055. defaultTransport: defaultTransport,
  1056. transports: map[string]adapter.DNSTransport{
  1057. "default": defaultTransport,
  1058. "private": privateTransport,
  1059. },
  1060. }, client)
  1061. addresses, err := router.Lookup(context.Background(), "example.com", adapter.DNSQueryOptions{
  1062. LookupStrategy: C.DomainStrategyIPv4Only,
  1063. })
  1064. require.NoError(t, err)
  1065. require.Equal(t, []netip.Addr{netip.MustParseAddr("9.9.9.9")}, addresses)
  1066. require.Equal(t, []string{"private", "default"}, currentLookupTags())
  1067. }
  1068. func TestLookupLegacyDNSModeRuleSetAcceptEmptyDoesNotTreatMismatchAsEmpty(t *testing.T) {
  1069. t.Parallel()
  1070. ctx := context.Background()
  1071. ruleSet, err := rulepkg.NewRuleSet(ctx, log.NewNOPFactory().NewLogger("router"), option.RuleSet{
  1072. Type: C.RuleSetTypeInline,
  1073. Tag: "legacy-ipcidr-set",
  1074. InlineOptions: option.PlainRuleSet{
  1075. Rules: []option.HeadlessRule{{
  1076. Type: C.RuleTypeDefault,
  1077. DefaultOptions: option.DefaultHeadlessRule{
  1078. IPCIDR: badoption.Listable[string]{"10.0.0.0/8"},
  1079. },
  1080. }},
  1081. },
  1082. })
  1083. require.NoError(t, err)
  1084. ctx = service.ContextWith[adapter.Router](ctx, &fakeRouter{
  1085. ruleSets: map[string]adapter.RuleSet{
  1086. "legacy-ipcidr-set": ruleSet,
  1087. },
  1088. })
  1089. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  1090. privateTransport := &fakeDNSTransport{tag: "private", transportType: C.DNSTypeUDP}
  1091. var lookupAccess sync.Mutex
  1092. var lookupTags []string
  1093. recordLookup := func(tag string) {
  1094. lookupAccess.Lock()
  1095. lookupTags = append(lookupTags, tag)
  1096. lookupAccess.Unlock()
  1097. }
  1098. currentLookupTags := func() []string {
  1099. lookupAccess.Lock()
  1100. defer lookupAccess.Unlock()
  1101. return append([]string(nil), lookupTags...)
  1102. }
  1103. router := newTestRouterWithContext(t, ctx, []option.DNSRule{
  1104. {
  1105. Type: C.RuleTypeDefault,
  1106. DefaultOptions: option.DefaultDNSRule{
  1107. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1108. RuleSet: badoption.Listable[string]{"legacy-ipcidr-set"},
  1109. RuleSetIPCIDRAcceptEmpty: true,
  1110. },
  1111. DNSRuleAction: option.DNSRuleAction{
  1112. Action: C.RuleActionTypeRoute,
  1113. RouteOptions: option.DNSRouteActionOptions{Server: "private"},
  1114. },
  1115. },
  1116. },
  1117. {
  1118. Type: C.RuleTypeDefault,
  1119. DefaultOptions: option.DefaultDNSRule{
  1120. DNSRuleAction: option.DNSRuleAction{
  1121. Action: C.RuleActionTypeRoute,
  1122. RouteOptions: option.DNSRouteActionOptions{Server: "default"},
  1123. },
  1124. },
  1125. },
  1126. }, &fakeDNSTransportManager{
  1127. defaultTransport: defaultTransport,
  1128. transports: map[string]adapter.DNSTransport{
  1129. "default": defaultTransport,
  1130. "private": privateTransport,
  1131. },
  1132. }, &fakeDNSClient{
  1133. lookup: func(transport adapter.DNSTransport, domain string, options adapter.DNSQueryOptions) ([]netip.Addr, *mDNS.Msg, error) {
  1134. require.Equal(t, "example.com", domain)
  1135. require.Equal(t, C.DomainStrategyIPv4Only, options.LookupStrategy)
  1136. recordLookup(transport.Tag())
  1137. switch transport.Tag() {
  1138. case "private":
  1139. response := FixedResponse(0, fixedQuestion(domain, mDNS.TypeA), []netip.Addr{netip.MustParseAddr("8.8.8.8")}, 60)
  1140. return MessageToAddresses(response), response, nil
  1141. case "default":
  1142. response := FixedResponse(0, fixedQuestion(domain, mDNS.TypeA), []netip.Addr{netip.MustParseAddr("9.9.9.9")}, 60)
  1143. return MessageToAddresses(response), response, nil
  1144. }
  1145. return nil, nil, E.New("unexpected transport")
  1146. },
  1147. })
  1148. require.True(t, router.legacyDNSMode)
  1149. addresses, err := router.Lookup(context.Background(), "example.com", adapter.DNSQueryOptions{
  1150. LookupStrategy: C.DomainStrategyIPv4Only,
  1151. })
  1152. require.NoError(t, err)
  1153. require.Equal(t, []netip.Addr{netip.MustParseAddr("9.9.9.9")}, addresses)
  1154. require.Equal(t, []string{"private", "default"}, currentLookupTags())
  1155. }
  1156. func TestExchangeLegacyDNSModeDisabledEvaluateMatchResponseRoute(t *testing.T) {
  1157. t.Parallel()
  1158. transportManager := &fakeDNSTransportManager{
  1159. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1160. transports: map[string]adapter.DNSTransport{
  1161. "upstream": &fakeDNSTransport{tag: "upstream", transportType: C.DNSTypeUDP},
  1162. "selected": &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP},
  1163. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1164. },
  1165. }
  1166. client := &fakeDNSClient{
  1167. exchange: func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error) {
  1168. switch transport.Tag() {
  1169. case "upstream":
  1170. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("1.1.1.1")}, 60), nil
  1171. case "selected":
  1172. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("8.8.8.8")}, 60), nil
  1173. default:
  1174. return nil, E.New("unexpected transport")
  1175. }
  1176. },
  1177. }
  1178. rules := []option.DNSRule{
  1179. {
  1180. Type: C.RuleTypeDefault,
  1181. DefaultOptions: option.DefaultDNSRule{
  1182. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1183. Domain: badoption.Listable[string]{"example.com"},
  1184. },
  1185. DNSRuleAction: option.DNSRuleAction{
  1186. Action: C.RuleActionTypeEvaluate,
  1187. RouteOptions: option.DNSRouteActionOptions{Server: "upstream"},
  1188. },
  1189. },
  1190. },
  1191. {
  1192. Type: C.RuleTypeDefault,
  1193. DefaultOptions: option.DefaultDNSRule{
  1194. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1195. MatchResponse: true,
  1196. ResponseAnswer: badoption.Listable[option.DNSRecordOptions]{mustRecord(t, "example.com. IN A 1.1.1.1")},
  1197. },
  1198. DNSRuleAction: option.DNSRuleAction{
  1199. Action: C.RuleActionTypeRoute,
  1200. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  1201. },
  1202. },
  1203. },
  1204. }
  1205. router := newTestRouter(t, rules, transportManager, client)
  1206. response, err := router.Exchange(context.Background(), &mDNS.Msg{
  1207. Question: []mDNS.Question{fixedQuestion("example.com", mDNS.TypeA)},
  1208. }, adapter.DNSQueryOptions{})
  1209. require.NoError(t, err)
  1210. require.Equal(t, []netip.Addr{netip.MustParseAddr("8.8.8.8")}, MessageToAddresses(response))
  1211. }
  1212. func TestExchangeLegacyDNSModeDisabledEvaluateMatchResponseRcodeRoute(t *testing.T) {
  1213. t.Parallel()
  1214. transportManager := &fakeDNSTransportManager{
  1215. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1216. transports: map[string]adapter.DNSTransport{
  1217. "upstream": &fakeDNSTransport{tag: "upstream", transportType: C.DNSTypeUDP},
  1218. "selected": &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP},
  1219. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1220. },
  1221. }
  1222. client := &fakeDNSClient{
  1223. exchange: func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error) {
  1224. switch transport.Tag() {
  1225. case "upstream":
  1226. return &mDNS.Msg{
  1227. MsgHdr: mDNS.MsgHdr{
  1228. Response: true,
  1229. Rcode: mDNS.RcodeNameError,
  1230. },
  1231. Question: []mDNS.Question{message.Question[0]},
  1232. }, nil
  1233. case "selected":
  1234. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("8.8.8.8")}, 60), nil
  1235. default:
  1236. return nil, E.New("unexpected transport")
  1237. }
  1238. },
  1239. }
  1240. rcode := option.DNSRCode(mDNS.RcodeNameError)
  1241. rules := []option.DNSRule{
  1242. {
  1243. Type: C.RuleTypeDefault,
  1244. DefaultOptions: option.DefaultDNSRule{
  1245. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1246. Domain: badoption.Listable[string]{"example.com"},
  1247. },
  1248. DNSRuleAction: option.DNSRuleAction{
  1249. Action: C.RuleActionTypeEvaluate,
  1250. RouteOptions: option.DNSRouteActionOptions{Server: "upstream"},
  1251. },
  1252. },
  1253. },
  1254. {
  1255. Type: C.RuleTypeDefault,
  1256. DefaultOptions: option.DefaultDNSRule{
  1257. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1258. MatchResponse: true,
  1259. ResponseRcode: &rcode,
  1260. },
  1261. DNSRuleAction: option.DNSRuleAction{
  1262. Action: C.RuleActionTypeRoute,
  1263. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  1264. },
  1265. },
  1266. },
  1267. }
  1268. router := newTestRouter(t, rules, transportManager, client)
  1269. response, err := router.Exchange(context.Background(), &mDNS.Msg{
  1270. Question: []mDNS.Question{fixedQuestion("example.com", mDNS.TypeA)},
  1271. }, adapter.DNSQueryOptions{})
  1272. require.NoError(t, err)
  1273. require.Equal(t, []netip.Addr{netip.MustParseAddr("8.8.8.8")}, MessageToAddresses(response))
  1274. }
  1275. func TestExchangeLegacyDNSModeDisabledEvaluateMatchResponseNsRoute(t *testing.T) {
  1276. t.Parallel()
  1277. transportManager := &fakeDNSTransportManager{
  1278. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1279. transports: map[string]adapter.DNSTransport{
  1280. "upstream": &fakeDNSTransport{tag: "upstream", transportType: C.DNSTypeUDP},
  1281. "selected": &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP},
  1282. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1283. },
  1284. }
  1285. nsRecord := mustRecord(t, "example.com. IN NS ns1.example.com.")
  1286. client := &fakeDNSClient{
  1287. exchange: func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error) {
  1288. switch transport.Tag() {
  1289. case "upstream":
  1290. return &mDNS.Msg{
  1291. MsgHdr: mDNS.MsgHdr{
  1292. Response: true,
  1293. Rcode: mDNS.RcodeSuccess,
  1294. },
  1295. Question: []mDNS.Question{message.Question[0]},
  1296. Ns: []mDNS.RR{nsRecord.Build()},
  1297. }, nil
  1298. case "selected":
  1299. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("8.8.8.8")}, 60), nil
  1300. default:
  1301. return nil, E.New("unexpected transport")
  1302. }
  1303. },
  1304. }
  1305. rules := []option.DNSRule{
  1306. {
  1307. Type: C.RuleTypeDefault,
  1308. DefaultOptions: option.DefaultDNSRule{
  1309. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1310. Domain: badoption.Listable[string]{"example.com"},
  1311. },
  1312. DNSRuleAction: option.DNSRuleAction{
  1313. Action: C.RuleActionTypeEvaluate,
  1314. RouteOptions: option.DNSRouteActionOptions{Server: "upstream"},
  1315. },
  1316. },
  1317. },
  1318. {
  1319. Type: C.RuleTypeDefault,
  1320. DefaultOptions: option.DefaultDNSRule{
  1321. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1322. MatchResponse: true,
  1323. ResponseNs: badoption.Listable[option.DNSRecordOptions]{nsRecord},
  1324. },
  1325. DNSRuleAction: option.DNSRuleAction{
  1326. Action: C.RuleActionTypeRoute,
  1327. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  1328. },
  1329. },
  1330. },
  1331. }
  1332. router := newTestRouter(t, rules, transportManager, client)
  1333. response, err := router.Exchange(context.Background(), &mDNS.Msg{
  1334. Question: []mDNS.Question{fixedQuestion("example.com", mDNS.TypeA)},
  1335. }, adapter.DNSQueryOptions{})
  1336. require.NoError(t, err)
  1337. require.Equal(t, []netip.Addr{netip.MustParseAddr("8.8.8.8")}, MessageToAddresses(response))
  1338. }
  1339. func TestExchangeLegacyDNSModeDisabledEvaluateMatchResponseExtraRoute(t *testing.T) {
  1340. t.Parallel()
  1341. transportManager := &fakeDNSTransportManager{
  1342. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1343. transports: map[string]adapter.DNSTransport{
  1344. "upstream": &fakeDNSTransport{tag: "upstream", transportType: C.DNSTypeUDP},
  1345. "selected": &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP},
  1346. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1347. },
  1348. }
  1349. extraRecord := mustRecord(t, "ns1.example.com. IN A 192.0.2.53")
  1350. client := &fakeDNSClient{
  1351. exchange: func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error) {
  1352. switch transport.Tag() {
  1353. case "upstream":
  1354. return &mDNS.Msg{
  1355. MsgHdr: mDNS.MsgHdr{
  1356. Response: true,
  1357. Rcode: mDNS.RcodeSuccess,
  1358. },
  1359. Question: []mDNS.Question{message.Question[0]},
  1360. Extra: []mDNS.RR{extraRecord.Build()},
  1361. }, nil
  1362. case "selected":
  1363. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("8.8.8.8")}, 60), nil
  1364. default:
  1365. return nil, E.New("unexpected transport")
  1366. }
  1367. },
  1368. }
  1369. rules := []option.DNSRule{
  1370. {
  1371. Type: C.RuleTypeDefault,
  1372. DefaultOptions: option.DefaultDNSRule{
  1373. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1374. Domain: badoption.Listable[string]{"example.com"},
  1375. },
  1376. DNSRuleAction: option.DNSRuleAction{
  1377. Action: C.RuleActionTypeEvaluate,
  1378. RouteOptions: option.DNSRouteActionOptions{Server: "upstream"},
  1379. },
  1380. },
  1381. },
  1382. {
  1383. Type: C.RuleTypeDefault,
  1384. DefaultOptions: option.DefaultDNSRule{
  1385. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1386. MatchResponse: true,
  1387. ResponseExtra: badoption.Listable[option.DNSRecordOptions]{extraRecord},
  1388. },
  1389. DNSRuleAction: option.DNSRuleAction{
  1390. Action: C.RuleActionTypeRoute,
  1391. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  1392. },
  1393. },
  1394. },
  1395. }
  1396. router := newTestRouter(t, rules, transportManager, client)
  1397. response, err := router.Exchange(context.Background(), &mDNS.Msg{
  1398. Question: []mDNS.Question{fixedQuestion("example.com", mDNS.TypeA)},
  1399. }, adapter.DNSQueryOptions{})
  1400. require.NoError(t, err)
  1401. require.Equal(t, []netip.Addr{netip.MustParseAddr("8.8.8.8")}, MessageToAddresses(response))
  1402. }
  1403. func TestExchangeLegacyDNSModeDisabledEvaluateDoesNotLeakAddressesToNextQuery(t *testing.T) {
  1404. t.Parallel()
  1405. transportManager := &fakeDNSTransportManager{
  1406. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1407. transports: map[string]adapter.DNSTransport{
  1408. "upstream": &fakeDNSTransport{tag: "upstream", transportType: C.DNSTypeUDP},
  1409. "selected": &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP},
  1410. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1411. },
  1412. }
  1413. var inspectedSelected bool
  1414. client := &fakeDNSClient{
  1415. beforeExchange: func(ctx context.Context, transport adapter.DNSTransport, message *mDNS.Msg) {
  1416. if transport.Tag() != "selected" {
  1417. return
  1418. }
  1419. inspectedSelected = true
  1420. metadata := adapter.ContextFrom(ctx)
  1421. require.NotNil(t, metadata)
  1422. require.Empty(t, metadata.DestinationAddresses)
  1423. require.NotNil(t, metadata.DNSResponse)
  1424. },
  1425. exchange: func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error) {
  1426. switch transport.Tag() {
  1427. case "upstream":
  1428. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("1.1.1.1")}, 60), nil
  1429. case "selected":
  1430. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("8.8.8.8")}, 60), nil
  1431. default:
  1432. return nil, E.New("unexpected transport")
  1433. }
  1434. },
  1435. }
  1436. rules := []option.DNSRule{
  1437. {
  1438. Type: C.RuleTypeDefault,
  1439. DefaultOptions: option.DefaultDNSRule{
  1440. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1441. Domain: badoption.Listable[string]{"example.com"},
  1442. },
  1443. DNSRuleAction: option.DNSRuleAction{
  1444. Action: C.RuleActionTypeEvaluate,
  1445. RouteOptions: option.DNSRouteActionOptions{Server: "upstream"},
  1446. },
  1447. },
  1448. },
  1449. {
  1450. Type: C.RuleTypeDefault,
  1451. DefaultOptions: option.DefaultDNSRule{
  1452. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1453. MatchResponse: true,
  1454. ResponseAnswer: badoption.Listable[option.DNSRecordOptions]{mustRecord(t, "example.com. IN A 1.1.1.1")},
  1455. },
  1456. DNSRuleAction: option.DNSRuleAction{
  1457. Action: C.RuleActionTypeRoute,
  1458. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  1459. },
  1460. },
  1461. },
  1462. }
  1463. router := newTestRouter(t, rules, transportManager, client)
  1464. response, err := router.Exchange(context.Background(), &mDNS.Msg{
  1465. Question: []mDNS.Question{fixedQuestion("example.com", mDNS.TypeA)},
  1466. }, adapter.DNSQueryOptions{})
  1467. require.NoError(t, err)
  1468. require.True(t, inspectedSelected)
  1469. require.Equal(t, []netip.Addr{netip.MustParseAddr("8.8.8.8")}, MessageToAddresses(response))
  1470. }
  1471. func TestExchangeLegacyDNSModeDisabledEvaluateRouteResolutionFailureClearsResponse(t *testing.T) {
  1472. t.Parallel()
  1473. transportManager := &fakeDNSTransportManager{
  1474. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1475. transports: map[string]adapter.DNSTransport{
  1476. "upstream": &fakeDNSTransport{tag: "upstream", transportType: C.DNSTypeUDP},
  1477. "selected": &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP},
  1478. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1479. },
  1480. }
  1481. client := &fakeDNSClient{
  1482. exchange: func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error) {
  1483. switch transport.Tag() {
  1484. case "upstream":
  1485. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("1.1.1.1")}, 60), nil
  1486. case "selected":
  1487. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("8.8.8.8")}, 60), nil
  1488. case "default":
  1489. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("4.4.4.4")}, 60), nil
  1490. default:
  1491. return nil, E.New("unexpected transport")
  1492. }
  1493. },
  1494. }
  1495. rules := []option.DNSRule{
  1496. {
  1497. Type: C.RuleTypeDefault,
  1498. DefaultOptions: option.DefaultDNSRule{
  1499. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1500. Domain: badoption.Listable[string]{"example.com"},
  1501. },
  1502. DNSRuleAction: option.DNSRuleAction{
  1503. Action: C.RuleActionTypeEvaluate,
  1504. RouteOptions: option.DNSRouteActionOptions{Server: "upstream"},
  1505. },
  1506. },
  1507. },
  1508. {
  1509. Type: C.RuleTypeDefault,
  1510. DefaultOptions: option.DefaultDNSRule{
  1511. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1512. Domain: badoption.Listable[string]{"example.com"},
  1513. },
  1514. DNSRuleAction: option.DNSRuleAction{
  1515. Action: C.RuleActionTypeEvaluate,
  1516. RouteOptions: option.DNSRouteActionOptions{Server: "missing"},
  1517. },
  1518. },
  1519. },
  1520. {
  1521. Type: C.RuleTypeDefault,
  1522. DefaultOptions: option.DefaultDNSRule{
  1523. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1524. MatchResponse: true,
  1525. ResponseAnswer: badoption.Listable[option.DNSRecordOptions]{mustRecord(t, "example.com. IN A 1.1.1.1")},
  1526. },
  1527. DNSRuleAction: option.DNSRuleAction{
  1528. Action: C.RuleActionTypeRoute,
  1529. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  1530. },
  1531. },
  1532. },
  1533. }
  1534. router := newTestRouter(t, rules, transportManager, client)
  1535. response, err := router.Exchange(context.Background(), &mDNS.Msg{
  1536. Question: []mDNS.Question{fixedQuestion("example.com", mDNS.TypeA)},
  1537. }, adapter.DNSQueryOptions{})
  1538. require.NoError(t, err)
  1539. require.Equal(t, []netip.Addr{netip.MustParseAddr("4.4.4.4")}, MessageToAddresses(response))
  1540. }
  1541. func TestExchangeLegacyDNSModeDisabledSecondEvaluateOverwritesFirstResponse(t *testing.T) {
  1542. t.Parallel()
  1543. transportManager := &fakeDNSTransportManager{
  1544. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1545. transports: map[string]adapter.DNSTransport{
  1546. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1547. "first-upstream": &fakeDNSTransport{tag: "first-upstream", transportType: C.DNSTypeUDP},
  1548. "second-upstream": &fakeDNSTransport{tag: "second-upstream", transportType: C.DNSTypeUDP},
  1549. "first-match": &fakeDNSTransport{tag: "first-match", transportType: C.DNSTypeUDP},
  1550. "second-match": &fakeDNSTransport{tag: "second-match", transportType: C.DNSTypeUDP},
  1551. },
  1552. }
  1553. client := &fakeDNSClient{
  1554. exchange: func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error) {
  1555. switch transport.Tag() {
  1556. case "first-upstream":
  1557. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("1.1.1.1")}, 60), nil
  1558. case "second-upstream":
  1559. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("2.2.2.2")}, 60), nil
  1560. case "first-match":
  1561. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("7.7.7.7")}, 60), nil
  1562. case "second-match":
  1563. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("8.8.8.8")}, 60), nil
  1564. case "default":
  1565. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("4.4.4.4")}, 60), nil
  1566. default:
  1567. return nil, E.New("unexpected transport")
  1568. }
  1569. },
  1570. }
  1571. rules := []option.DNSRule{
  1572. {
  1573. Type: C.RuleTypeDefault,
  1574. DefaultOptions: option.DefaultDNSRule{
  1575. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1576. Domain: badoption.Listable[string]{"example.com"},
  1577. },
  1578. DNSRuleAction: option.DNSRuleAction{
  1579. Action: C.RuleActionTypeEvaluate,
  1580. RouteOptions: option.DNSRouteActionOptions{Server: "first-upstream"},
  1581. },
  1582. },
  1583. },
  1584. {
  1585. Type: C.RuleTypeDefault,
  1586. DefaultOptions: option.DefaultDNSRule{
  1587. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1588. Domain: badoption.Listable[string]{"example.com"},
  1589. },
  1590. DNSRuleAction: option.DNSRuleAction{
  1591. Action: C.RuleActionTypeEvaluate,
  1592. RouteOptions: option.DNSRouteActionOptions{Server: "second-upstream"},
  1593. },
  1594. },
  1595. },
  1596. {
  1597. Type: C.RuleTypeDefault,
  1598. DefaultOptions: option.DefaultDNSRule{
  1599. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1600. MatchResponse: true,
  1601. ResponseAnswer: badoption.Listable[option.DNSRecordOptions]{mustRecord(t, "example.com. IN A 1.1.1.1")},
  1602. },
  1603. DNSRuleAction: option.DNSRuleAction{
  1604. Action: C.RuleActionTypeRoute,
  1605. RouteOptions: option.DNSRouteActionOptions{Server: "first-match"},
  1606. },
  1607. },
  1608. },
  1609. {
  1610. Type: C.RuleTypeDefault,
  1611. DefaultOptions: option.DefaultDNSRule{
  1612. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1613. MatchResponse: true,
  1614. ResponseAnswer: badoption.Listable[option.DNSRecordOptions]{mustRecord(t, "example.com. IN A 2.2.2.2")},
  1615. },
  1616. DNSRuleAction: option.DNSRuleAction{
  1617. Action: C.RuleActionTypeRoute,
  1618. RouteOptions: option.DNSRouteActionOptions{Server: "second-match"},
  1619. },
  1620. },
  1621. },
  1622. }
  1623. router := newTestRouter(t, rules, transportManager, client)
  1624. response, err := router.Exchange(context.Background(), &mDNS.Msg{
  1625. Question: []mDNS.Question{fixedQuestion("example.com", mDNS.TypeA)},
  1626. }, adapter.DNSQueryOptions{})
  1627. require.NoError(t, err)
  1628. require.Equal(t, []netip.Addr{netip.MustParseAddr("8.8.8.8")}, MessageToAddresses(response))
  1629. }
  1630. func TestExchangeLegacyDNSModeDisabledEvaluateExchangeFailureUsesMatchResponseBooleanSemantics(t *testing.T) {
  1631. t.Parallel()
  1632. testCases := []struct {
  1633. name string
  1634. invert bool
  1635. expectedAddr netip.Addr
  1636. }{
  1637. {
  1638. name: "plain match_response rule stays false",
  1639. expectedAddr: netip.MustParseAddr("4.4.4.4"),
  1640. },
  1641. {
  1642. name: "invert match_response rule becomes true",
  1643. invert: true,
  1644. expectedAddr: netip.MustParseAddr("8.8.8.8"),
  1645. },
  1646. }
  1647. for _, testCase := range testCases {
  1648. t.Run(testCase.name, func(t *testing.T) {
  1649. t.Parallel()
  1650. transportManager := &fakeDNSTransportManager{
  1651. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1652. transports: map[string]adapter.DNSTransport{
  1653. "upstream": &fakeDNSTransport{tag: "upstream", transportType: C.DNSTypeUDP},
  1654. "selected": &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP},
  1655. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1656. },
  1657. }
  1658. client := &fakeDNSClient{
  1659. exchange: func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error) {
  1660. switch transport.Tag() {
  1661. case "upstream":
  1662. return nil, E.New("upstream exchange failed")
  1663. case "selected":
  1664. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("8.8.8.8")}, 60), nil
  1665. case "default":
  1666. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("4.4.4.4")}, 60), nil
  1667. default:
  1668. return nil, E.New("unexpected transport")
  1669. }
  1670. },
  1671. }
  1672. rules := []option.DNSRule{
  1673. {
  1674. Type: C.RuleTypeDefault,
  1675. DefaultOptions: option.DefaultDNSRule{
  1676. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1677. Domain: badoption.Listable[string]{"example.com"},
  1678. },
  1679. DNSRuleAction: option.DNSRuleAction{
  1680. Action: C.RuleActionTypeEvaluate,
  1681. RouteOptions: option.DNSRouteActionOptions{Server: "upstream"},
  1682. },
  1683. },
  1684. },
  1685. {
  1686. Type: C.RuleTypeDefault,
  1687. DefaultOptions: option.DefaultDNSRule{
  1688. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1689. MatchResponse: true,
  1690. Invert: testCase.invert,
  1691. },
  1692. DNSRuleAction: option.DNSRuleAction{
  1693. Action: C.RuleActionTypeRoute,
  1694. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  1695. },
  1696. },
  1697. },
  1698. }
  1699. router := newTestRouter(t, rules, transportManager, client)
  1700. response, err := router.Exchange(context.Background(), &mDNS.Msg{
  1701. Question: []mDNS.Question{fixedQuestion("example.com", mDNS.TypeA)},
  1702. }, adapter.DNSQueryOptions{})
  1703. require.NoError(t, err)
  1704. require.Equal(t, []netip.Addr{testCase.expectedAddr}, MessageToAddresses(response))
  1705. })
  1706. }
  1707. }
  1708. func TestExchangeLegacyDNSModeDisabledRespondReturnsEvaluatedResponse(t *testing.T) {
  1709. t.Parallel()
  1710. var exchanges []string
  1711. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  1712. router := newTestRouter(t, []option.DNSRule{
  1713. {
  1714. Type: C.RuleTypeDefault,
  1715. DefaultOptions: option.DefaultDNSRule{
  1716. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1717. Domain: badoption.Listable[string]{"example.com"},
  1718. },
  1719. DNSRuleAction: option.DNSRuleAction{
  1720. Action: C.RuleActionTypeEvaluate,
  1721. RouteOptions: option.DNSRouteActionOptions{Server: "upstream"},
  1722. },
  1723. },
  1724. },
  1725. {
  1726. Type: C.RuleTypeDefault,
  1727. DefaultOptions: option.DefaultDNSRule{
  1728. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1729. Domain: badoption.Listable[string]{"example.com"},
  1730. },
  1731. DNSRuleAction: option.DNSRuleAction{
  1732. Action: C.RuleActionTypeRespond,
  1733. },
  1734. },
  1735. },
  1736. }, &fakeDNSTransportManager{
  1737. defaultTransport: defaultTransport,
  1738. transports: map[string]adapter.DNSTransport{
  1739. "default": defaultTransport,
  1740. "upstream": &fakeDNSTransport{tag: "upstream", transportType: C.DNSTypeUDP},
  1741. },
  1742. }, &fakeDNSClient{
  1743. exchange: func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error) {
  1744. exchanges = append(exchanges, transport.Tag())
  1745. require.Equal(t, "upstream", transport.Tag())
  1746. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("1.1.1.1")}, 60), nil
  1747. },
  1748. })
  1749. require.False(t, router.legacyDNSMode)
  1750. response, err := router.Exchange(context.Background(), &mDNS.Msg{
  1751. Question: []mDNS.Question{fixedQuestion("example.com", mDNS.TypeA)},
  1752. }, adapter.DNSQueryOptions{})
  1753. require.NoError(t, err)
  1754. require.Equal(t, []string{"upstream"}, exchanges)
  1755. require.Equal(t, []netip.Addr{netip.MustParseAddr("1.1.1.1")}, MessageToAddresses(response))
  1756. }
  1757. func TestLookupLegacyDNSModeDisabledRespondReturnsEvaluatedResponse(t *testing.T) {
  1758. t.Parallel()
  1759. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  1760. router := newTestRouter(t, []option.DNSRule{
  1761. {
  1762. Type: C.RuleTypeDefault,
  1763. DefaultOptions: option.DefaultDNSRule{
  1764. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1765. Domain: badoption.Listable[string]{"example.com"},
  1766. },
  1767. DNSRuleAction: option.DNSRuleAction{
  1768. Action: C.RuleActionTypeEvaluate,
  1769. RouteOptions: option.DNSRouteActionOptions{Server: "upstream"},
  1770. },
  1771. },
  1772. },
  1773. {
  1774. Type: C.RuleTypeDefault,
  1775. DefaultOptions: option.DefaultDNSRule{
  1776. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1777. Domain: badoption.Listable[string]{"example.com"},
  1778. },
  1779. DNSRuleAction: option.DNSRuleAction{
  1780. Action: C.RuleActionTypeRespond,
  1781. },
  1782. },
  1783. },
  1784. }, &fakeDNSTransportManager{
  1785. defaultTransport: defaultTransport,
  1786. transports: map[string]adapter.DNSTransport{
  1787. "default": defaultTransport,
  1788. "upstream": &fakeDNSTransport{tag: "upstream", transportType: C.DNSTypeUDP},
  1789. },
  1790. }, &fakeDNSClient{
  1791. exchange: func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error) {
  1792. require.Equal(t, "upstream", transport.Tag())
  1793. switch message.Question[0].Qtype {
  1794. case mDNS.TypeA:
  1795. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("1.1.1.1")}, 60), nil
  1796. case mDNS.TypeAAAA:
  1797. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("2001:db8::1")}, 60), nil
  1798. default:
  1799. return nil, E.New("unexpected qtype")
  1800. }
  1801. },
  1802. })
  1803. require.False(t, router.legacyDNSMode)
  1804. addresses, err := router.Lookup(context.Background(), "example.com", adapter.DNSQueryOptions{})
  1805. require.NoError(t, err)
  1806. require.Equal(t, []netip.Addr{
  1807. netip.MustParseAddr("1.1.1.1"),
  1808. netip.MustParseAddr("2001:db8::1"),
  1809. }, addresses)
  1810. }
  1811. func TestExchangeLegacyDNSModeDisabledRespondWithoutEvaluatedResponseReturnsError(t *testing.T) {
  1812. t.Parallel()
  1813. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  1814. router := newTestRouter(t, []option.DNSRule{
  1815. {
  1816. Type: C.RuleTypeDefault,
  1817. DefaultOptions: option.DefaultDNSRule{
  1818. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1819. Domain: badoption.Listable[string]{"example.com"},
  1820. },
  1821. DNSRuleAction: option.DNSRuleAction{
  1822. Action: C.RuleActionTypeEvaluate,
  1823. RouteOptions: option.DNSRouteActionOptions{Server: "upstream"},
  1824. },
  1825. },
  1826. },
  1827. {
  1828. Type: C.RuleTypeDefault,
  1829. DefaultOptions: option.DefaultDNSRule{
  1830. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1831. Domain: badoption.Listable[string]{"example.com"},
  1832. },
  1833. DNSRuleAction: option.DNSRuleAction{
  1834. Action: C.RuleActionTypeRespond,
  1835. },
  1836. },
  1837. },
  1838. }, &fakeDNSTransportManager{
  1839. defaultTransport: defaultTransport,
  1840. transports: map[string]adapter.DNSTransport{
  1841. "default": defaultTransport,
  1842. "upstream": &fakeDNSTransport{tag: "upstream", transportType: C.DNSTypeUDP},
  1843. },
  1844. }, &fakeDNSClient{
  1845. exchange: func(transport adapter.DNSTransport, _ *mDNS.Msg) (*mDNS.Msg, error) {
  1846. require.Equal(t, "upstream", transport.Tag())
  1847. return nil, E.New("upstream exchange failed")
  1848. },
  1849. })
  1850. require.False(t, router.legacyDNSMode)
  1851. response, err := router.Exchange(context.Background(), &mDNS.Msg{
  1852. Question: []mDNS.Question{fixedQuestion("example.com", mDNS.TypeA)},
  1853. }, adapter.DNSQueryOptions{})
  1854. require.Nil(t, response)
  1855. require.ErrorContains(t, err, dnsRespondMissingResponseMessage)
  1856. }
  1857. func TestLookupLegacyDNSModeDisabledAllowsPartialSuccessForExchangeFailure(t *testing.T) {
  1858. t.Parallel()
  1859. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  1860. router := newTestRouter(t, nil, &fakeDNSTransportManager{
  1861. defaultTransport: defaultTransport,
  1862. transports: map[string]adapter.DNSTransport{
  1863. "default": defaultTransport,
  1864. },
  1865. }, &fakeDNSClient{
  1866. exchange: func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error) {
  1867. require.Equal(t, "default", transport.Tag())
  1868. switch message.Question[0].Qtype {
  1869. case mDNS.TypeA:
  1870. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("1.1.1.1")}, 60), nil
  1871. case mDNS.TypeAAAA:
  1872. return nil, E.New("ipv6 failed")
  1873. default:
  1874. return nil, E.New("unexpected qtype")
  1875. }
  1876. },
  1877. })
  1878. router.legacyDNSMode = false
  1879. addresses, err := router.Lookup(context.Background(), "example.com", adapter.DNSQueryOptions{})
  1880. require.NoError(t, err)
  1881. require.Equal(t, []netip.Addr{netip.MustParseAddr("1.1.1.1")}, addresses)
  1882. }
  1883. func TestLookupLegacyDNSModeDisabledAllowsPartialSuccessForRcodeError(t *testing.T) {
  1884. t.Parallel()
  1885. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  1886. router := newTestRouter(t, nil, &fakeDNSTransportManager{
  1887. defaultTransport: defaultTransport,
  1888. transports: map[string]adapter.DNSTransport{
  1889. "default": defaultTransport,
  1890. },
  1891. }, &fakeDNSClient{
  1892. exchange: func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error) {
  1893. require.Equal(t, "default", transport.Tag())
  1894. switch message.Question[0].Qtype {
  1895. case mDNS.TypeA:
  1896. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("1.1.1.1")}, 60), nil
  1897. case mDNS.TypeAAAA:
  1898. return &mDNS.Msg{
  1899. MsgHdr: mDNS.MsgHdr{
  1900. Response: true,
  1901. Rcode: mDNS.RcodeNameError,
  1902. },
  1903. Question: []mDNS.Question{message.Question[0]},
  1904. }, nil
  1905. default:
  1906. return nil, E.New("unexpected qtype")
  1907. }
  1908. },
  1909. })
  1910. router.legacyDNSMode = false
  1911. addresses, err := router.Lookup(context.Background(), "example.com", adapter.DNSQueryOptions{})
  1912. require.NoError(t, err)
  1913. require.Equal(t, []netip.Addr{netip.MustParseAddr("1.1.1.1")}, addresses)
  1914. }
  1915. func TestLookupLegacyDNSModeDisabledSkipsFakeIPRule(t *testing.T) {
  1916. t.Parallel()
  1917. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  1918. router := newTestRouter(t, []option.DNSRule{{
  1919. Type: C.RuleTypeDefault,
  1920. DefaultOptions: option.DefaultDNSRule{
  1921. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1922. Domain: badoption.Listable[string]{"example.com"},
  1923. },
  1924. DNSRuleAction: option.DNSRuleAction{
  1925. Action: C.RuleActionTypeRoute,
  1926. RouteOptions: option.DNSRouteActionOptions{Server: "fake"},
  1927. },
  1928. },
  1929. }}, &fakeDNSTransportManager{
  1930. defaultTransport: defaultTransport,
  1931. transports: map[string]adapter.DNSTransport{
  1932. "default": defaultTransport,
  1933. "fake": &fakeDNSTransport{tag: "fake", transportType: C.DNSTypeFakeIP},
  1934. },
  1935. }, &fakeDNSClient{
  1936. exchange: func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error) {
  1937. require.Equal(t, "default", transport.Tag())
  1938. if message.Question[0].Qtype == mDNS.TypeA {
  1939. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("2.2.2.2")}, 60), nil
  1940. }
  1941. return FixedResponse(0, message.Question[0], nil, 60), nil
  1942. },
  1943. })
  1944. router.legacyDNSMode = false
  1945. addresses, err := router.Lookup(context.Background(), "example.com", adapter.DNSQueryOptions{})
  1946. require.NoError(t, err)
  1947. require.Equal(t, []netip.Addr{netip.MustParseAddr("2.2.2.2")}, addresses)
  1948. }
  1949. func TestExchangeLegacyDNSModeDisabledAllowsRouteFakeIPRule(t *testing.T) {
  1950. t.Parallel()
  1951. fakeTransport := &fakeDNSTransport{tag: "fake", transportType: C.DNSTypeFakeIP}
  1952. router := newTestRouter(t, []option.DNSRule{{
  1953. Type: C.RuleTypeDefault,
  1954. DefaultOptions: option.DefaultDNSRule{
  1955. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1956. Domain: badoption.Listable[string]{"example.com"},
  1957. },
  1958. DNSRuleAction: option.DNSRuleAction{
  1959. Action: C.RuleActionTypeRoute,
  1960. RouteOptions: option.DNSRouteActionOptions{Server: "fake"},
  1961. },
  1962. },
  1963. }}, &fakeDNSTransportManager{
  1964. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1965. transports: map[string]adapter.DNSTransport{
  1966. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  1967. "fake": fakeTransport,
  1968. },
  1969. }, &fakeDNSClient{
  1970. exchange: func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error) {
  1971. require.Same(t, fakeTransport, transport)
  1972. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("198.18.0.1")}, 60), nil
  1973. },
  1974. })
  1975. response, err := router.Exchange(context.Background(), &mDNS.Msg{
  1976. Question: []mDNS.Question{fixedQuestion("example.com", mDNS.TypeA)},
  1977. }, adapter.DNSQueryOptions{})
  1978. require.NoError(t, err)
  1979. require.Equal(t, []netip.Addr{netip.MustParseAddr("198.18.0.1")}, MessageToAddresses(response))
  1980. }
  1981. func TestInitializeRejectsDNSRuleStrategyWhenLegacyDNSModeIsDisabledByEvaluate(t *testing.T) {
  1982. t.Parallel()
  1983. router := &Router{
  1984. ctx: context.Background(),
  1985. logger: log.NewNOPFactory().NewLogger("dns"),
  1986. transport: &fakeDNSTransportManager{},
  1987. client: &fakeDNSClient{},
  1988. rawRules: make([]option.DNSRule, 0, 1),
  1989. defaultDomainStrategy: C.DomainStrategyAsIS,
  1990. }
  1991. err := router.Initialize([]option.DNSRule{{
  1992. Type: C.RuleTypeDefault,
  1993. DefaultOptions: option.DefaultDNSRule{
  1994. RawDefaultDNSRule: option.RawDefaultDNSRule{
  1995. Domain: badoption.Listable[string]{"example.com"},
  1996. },
  1997. DNSRuleAction: option.DNSRuleAction{
  1998. Action: C.RuleActionTypeEvaluate,
  1999. RouteOptions: option.DNSRouteActionOptions{
  2000. Server: "default",
  2001. Strategy: option.DomainStrategy(C.DomainStrategyIPv4Only),
  2002. },
  2003. },
  2004. },
  2005. }})
  2006. require.ErrorContains(t, err, "strategy")
  2007. require.ErrorContains(t, err, "deprecated")
  2008. }
  2009. func TestInitializeRejectsEvaluateFakeIPServerInDefaultRule(t *testing.T) {
  2010. t.Parallel()
  2011. router := &Router{
  2012. ctx: context.Background(),
  2013. logger: log.NewNOPFactory().NewLogger("dns"),
  2014. transport: &fakeDNSTransportManager{transports: map[string]adapter.DNSTransport{"fake": &fakeDNSTransport{tag: "fake", transportType: C.DNSTypeFakeIP}}},
  2015. client: &fakeDNSClient{},
  2016. rawRules: make([]option.DNSRule, 0, 1),
  2017. defaultDomainStrategy: C.DomainStrategyAsIS,
  2018. }
  2019. err := router.Initialize([]option.DNSRule{{
  2020. Type: C.RuleTypeDefault,
  2021. DefaultOptions: option.DefaultDNSRule{
  2022. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2023. Domain: badoption.Listable[string]{"example.com"},
  2024. },
  2025. DNSRuleAction: option.DNSRuleAction{
  2026. Action: C.RuleActionTypeEvaluate,
  2027. RouteOptions: option.DNSRouteActionOptions{Server: "fake"},
  2028. },
  2029. },
  2030. }})
  2031. require.ErrorContains(t, err, "evaluate action cannot use fakeip server")
  2032. require.ErrorContains(t, err, "fake")
  2033. }
  2034. func TestInitializeRejectsEvaluateFakeIPServerInLogicalRule(t *testing.T) {
  2035. t.Parallel()
  2036. router := &Router{
  2037. ctx: context.Background(),
  2038. logger: log.NewNOPFactory().NewLogger("dns"),
  2039. transport: &fakeDNSTransportManager{transports: map[string]adapter.DNSTransport{"fake": &fakeDNSTransport{tag: "fake", transportType: C.DNSTypeFakeIP}}},
  2040. client: &fakeDNSClient{},
  2041. rawRules: make([]option.DNSRule, 0, 1),
  2042. defaultDomainStrategy: C.DomainStrategyAsIS,
  2043. }
  2044. err := router.Initialize([]option.DNSRule{{
  2045. Type: C.RuleTypeLogical,
  2046. LogicalOptions: option.LogicalDNSRule{
  2047. RawLogicalDNSRule: option.RawLogicalDNSRule{
  2048. Mode: C.LogicalTypeOr,
  2049. Rules: []option.DNSRule{{
  2050. Type: C.RuleTypeDefault,
  2051. DefaultOptions: option.DefaultDNSRule{
  2052. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2053. Domain: badoption.Listable[string]{"example.com"},
  2054. },
  2055. },
  2056. }},
  2057. },
  2058. DNSRuleAction: option.DNSRuleAction{
  2059. Action: C.RuleActionTypeEvaluate,
  2060. RouteOptions: option.DNSRouteActionOptions{Server: "fake"},
  2061. },
  2062. },
  2063. }})
  2064. require.ErrorContains(t, err, "evaluate action cannot use fakeip server")
  2065. require.ErrorContains(t, err, "fake")
  2066. }
  2067. func TestInitializeRejectsDNSRuleStrategyWhenLegacyDNSModeIsDisabledByMatchResponse(t *testing.T) {
  2068. t.Parallel()
  2069. router := &Router{
  2070. ctx: context.Background(),
  2071. logger: log.NewNOPFactory().NewLogger("dns"),
  2072. transport: &fakeDNSTransportManager{},
  2073. client: &fakeDNSClient{},
  2074. rawRules: make([]option.DNSRule, 0, 1),
  2075. defaultDomainStrategy: C.DomainStrategyAsIS,
  2076. }
  2077. err := router.Initialize([]option.DNSRule{{
  2078. Type: C.RuleTypeDefault,
  2079. DefaultOptions: option.DefaultDNSRule{
  2080. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2081. MatchResponse: true,
  2082. },
  2083. DNSRuleAction: option.DNSRuleAction{
  2084. Action: C.RuleActionTypeRouteOptions,
  2085. RouteOptionsOptions: option.DNSRouteOptionsActionOptions{
  2086. Strategy: option.DomainStrategy(C.DomainStrategyIPv4Only),
  2087. },
  2088. },
  2089. },
  2090. }})
  2091. require.ErrorContains(t, err, "strategy")
  2092. require.ErrorContains(t, err, "deprecated")
  2093. }
  2094. func TestInitializeRejectsDNSMatchResponseWithoutPrecedingEvaluate(t *testing.T) {
  2095. t.Parallel()
  2096. router := &Router{
  2097. ctx: context.Background(),
  2098. logger: log.NewNOPFactory().NewLogger("dns"),
  2099. transport: &fakeDNSTransportManager{},
  2100. client: &fakeDNSClient{},
  2101. rawRules: make([]option.DNSRule, 0, 1),
  2102. defaultDomainStrategy: C.DomainStrategyAsIS,
  2103. }
  2104. err := router.Initialize([]option.DNSRule{{
  2105. Type: C.RuleTypeDefault,
  2106. DefaultOptions: option.DefaultDNSRule{
  2107. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2108. MatchResponse: true,
  2109. ResponseAnswer: badoption.Listable[option.DNSRecordOptions]{mustRecord(t, "example.com. IN A 1.1.1.1")},
  2110. },
  2111. DNSRuleAction: option.DNSRuleAction{
  2112. Action: C.RuleActionTypeRoute,
  2113. RouteOptions: option.DNSRouteActionOptions{Server: "default"},
  2114. },
  2115. },
  2116. }})
  2117. require.ErrorContains(t, err, "preceding evaluate action")
  2118. }
  2119. func TestInitializeRejectsDNSRespondWithoutPrecedingEvaluate(t *testing.T) {
  2120. t.Parallel()
  2121. router := &Router{
  2122. ctx: context.Background(),
  2123. logger: log.NewNOPFactory().NewLogger("dns"),
  2124. transport: &fakeDNSTransportManager{},
  2125. client: &fakeDNSClient{},
  2126. rawRules: make([]option.DNSRule, 0, 1),
  2127. defaultDomainStrategy: C.DomainStrategyAsIS,
  2128. }
  2129. err := router.Initialize([]option.DNSRule{{
  2130. Type: C.RuleTypeDefault,
  2131. DefaultOptions: option.DefaultDNSRule{
  2132. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2133. Domain: badoption.Listable[string]{"example.com"},
  2134. },
  2135. DNSRuleAction: option.DNSRuleAction{
  2136. Action: C.RuleActionTypeRespond,
  2137. },
  2138. },
  2139. }})
  2140. require.ErrorContains(t, err, "preceding evaluate action")
  2141. }
  2142. func TestInitializeRejectsLogicalDNSRespondWithoutPrecedingEvaluate(t *testing.T) {
  2143. t.Parallel()
  2144. router := &Router{
  2145. ctx: context.Background(),
  2146. logger: log.NewNOPFactory().NewLogger("dns"),
  2147. transport: &fakeDNSTransportManager{},
  2148. client: &fakeDNSClient{},
  2149. rawRules: make([]option.DNSRule, 0, 1),
  2150. defaultDomainStrategy: C.DomainStrategyAsIS,
  2151. }
  2152. err := router.Initialize([]option.DNSRule{{
  2153. Type: C.RuleTypeLogical,
  2154. LogicalOptions: option.LogicalDNSRule{
  2155. RawLogicalDNSRule: option.RawLogicalDNSRule{
  2156. Mode: C.LogicalTypeOr,
  2157. Rules: []option.DNSRule{{
  2158. Type: C.RuleTypeDefault,
  2159. DefaultOptions: option.DefaultDNSRule{
  2160. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2161. Domain: badoption.Listable[string]{"example.com"},
  2162. },
  2163. },
  2164. }},
  2165. },
  2166. DNSRuleAction: option.DNSRuleAction{
  2167. Action: C.RuleActionTypeRespond,
  2168. },
  2169. },
  2170. }})
  2171. require.ErrorContains(t, err, "preceding evaluate action")
  2172. }
  2173. func TestInitializeRejectsEvaluateRuleWithResponseMatchWithoutPrecedingEvaluate(t *testing.T) {
  2174. t.Parallel()
  2175. router := &Router{
  2176. ctx: context.Background(),
  2177. logger: log.NewNOPFactory().NewLogger("dns"),
  2178. transport: &fakeDNSTransportManager{},
  2179. client: &fakeDNSClient{},
  2180. rawRules: make([]option.DNSRule, 0, 1),
  2181. defaultDomainStrategy: C.DomainStrategyAsIS,
  2182. }
  2183. err := router.Initialize([]option.DNSRule{{
  2184. Type: C.RuleTypeLogical,
  2185. LogicalOptions: option.LogicalDNSRule{
  2186. RawLogicalDNSRule: option.RawLogicalDNSRule{
  2187. Mode: C.LogicalTypeOr,
  2188. Rules: []option.DNSRule{
  2189. {
  2190. Type: C.RuleTypeDefault,
  2191. DefaultOptions: option.DefaultDNSRule{
  2192. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2193. Domain: badoption.Listable[string]{"example.com"},
  2194. },
  2195. },
  2196. },
  2197. {
  2198. Type: C.RuleTypeDefault,
  2199. DefaultOptions: option.DefaultDNSRule{
  2200. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2201. MatchResponse: true,
  2202. ResponseAnswer: badoption.Listable[option.DNSRecordOptions]{mustRecord(t, "example.com. IN A 1.1.1.1")},
  2203. },
  2204. },
  2205. },
  2206. },
  2207. },
  2208. DNSRuleAction: option.DNSRuleAction{
  2209. Action: C.RuleActionTypeEvaluate,
  2210. RouteOptions: option.DNSRouteActionOptions{Server: "default"},
  2211. },
  2212. },
  2213. }})
  2214. require.ErrorContains(t, err, "preceding evaluate action")
  2215. }
  2216. func TestInitializeAllowsEvaluateRuleWithResponseMatchAfterPrecedingEvaluate(t *testing.T) {
  2217. t.Parallel()
  2218. router := &Router{
  2219. ctx: context.Background(),
  2220. logger: log.NewNOPFactory().NewLogger("dns"),
  2221. transport: &fakeDNSTransportManager{},
  2222. client: &fakeDNSClient{},
  2223. rawRules: make([]option.DNSRule, 0, 2),
  2224. defaultDomainStrategy: C.DomainStrategyAsIS,
  2225. }
  2226. err := router.Initialize([]option.DNSRule{
  2227. {
  2228. Type: C.RuleTypeDefault,
  2229. DefaultOptions: option.DefaultDNSRule{
  2230. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2231. Domain: badoption.Listable[string]{"bootstrap.example"},
  2232. },
  2233. DNSRuleAction: option.DNSRuleAction{
  2234. Action: C.RuleActionTypeEvaluate,
  2235. RouteOptions: option.DNSRouteActionOptions{Server: "bootstrap"},
  2236. },
  2237. },
  2238. },
  2239. {
  2240. Type: C.RuleTypeLogical,
  2241. LogicalOptions: option.LogicalDNSRule{
  2242. RawLogicalDNSRule: option.RawLogicalDNSRule{
  2243. Mode: C.LogicalTypeOr,
  2244. Rules: []option.DNSRule{
  2245. {
  2246. Type: C.RuleTypeDefault,
  2247. DefaultOptions: option.DefaultDNSRule{
  2248. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2249. Domain: badoption.Listable[string]{"example.com"},
  2250. },
  2251. },
  2252. },
  2253. {
  2254. Type: C.RuleTypeDefault,
  2255. DefaultOptions: option.DefaultDNSRule{
  2256. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2257. MatchResponse: true,
  2258. ResponseAnswer: badoption.Listable[option.DNSRecordOptions]{mustRecord(t, "example.com. IN A 1.1.1.1")},
  2259. },
  2260. },
  2261. },
  2262. },
  2263. },
  2264. DNSRuleAction: option.DNSRuleAction{
  2265. Action: C.RuleActionTypeEvaluate,
  2266. RouteOptions: option.DNSRouteActionOptions{Server: "default"},
  2267. },
  2268. },
  2269. },
  2270. })
  2271. require.NoError(t, err)
  2272. }
  2273. func TestLookupLegacyDNSModeDisabledReturnsRejectedErrorForRejectAction(t *testing.T) {
  2274. t.Parallel()
  2275. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  2276. router := newTestRouter(t, []option.DNSRule{
  2277. {
  2278. Type: C.RuleTypeDefault,
  2279. DefaultOptions: option.DefaultDNSRule{
  2280. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2281. Domain: badoption.Listable[string]{"example.com"},
  2282. },
  2283. DNSRuleAction: option.DNSRuleAction{
  2284. Action: C.RuleActionTypeReject,
  2285. RejectOptions: option.RejectActionOptions{
  2286. Method: C.RuleActionRejectMethodDefault,
  2287. },
  2288. },
  2289. },
  2290. },
  2291. }, &fakeDNSTransportManager{
  2292. defaultTransport: defaultTransport,
  2293. transports: map[string]adapter.DNSTransport{
  2294. "default": defaultTransport,
  2295. },
  2296. }, &fakeDNSClient{})
  2297. require.False(t, router.legacyDNSMode)
  2298. addresses, err := router.Lookup(context.Background(), "example.com", adapter.DNSQueryOptions{})
  2299. require.Nil(t, addresses)
  2300. require.Error(t, err)
  2301. require.True(t, rulepkg.IsRejected(err))
  2302. }
  2303. func TestExchangeLegacyDNSModeDisabledReturnsRefusedResponseForRejectAction(t *testing.T) {
  2304. t.Parallel()
  2305. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  2306. router := newTestRouter(t, []option.DNSRule{
  2307. {
  2308. Type: C.RuleTypeDefault,
  2309. DefaultOptions: option.DefaultDNSRule{
  2310. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2311. Domain: badoption.Listable[string]{"example.com"},
  2312. },
  2313. DNSRuleAction: option.DNSRuleAction{
  2314. Action: C.RuleActionTypeReject,
  2315. RejectOptions: option.RejectActionOptions{
  2316. Method: C.RuleActionRejectMethodDefault,
  2317. },
  2318. },
  2319. },
  2320. },
  2321. }, &fakeDNSTransportManager{
  2322. defaultTransport: defaultTransport,
  2323. transports: map[string]adapter.DNSTransport{
  2324. "default": defaultTransport,
  2325. },
  2326. }, &fakeDNSClient{})
  2327. require.False(t, router.legacyDNSMode)
  2328. response, err := router.Exchange(context.Background(), &mDNS.Msg{
  2329. Question: []mDNS.Question{fixedQuestion("example.com", mDNS.TypeA)},
  2330. }, adapter.DNSQueryOptions{})
  2331. require.NoError(t, err)
  2332. require.Equal(t, mDNS.RcodeRefused, response.Rcode)
  2333. require.Equal(t, []mDNS.Question{fixedQuestion("example.com", mDNS.TypeA)}, response.Question)
  2334. }
  2335. func TestExchangeLegacyDNSModeDisabledReturnsDropErrorForRejectDropAction(t *testing.T) {
  2336. t.Parallel()
  2337. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  2338. router := newTestRouter(t, []option.DNSRule{
  2339. {
  2340. Type: C.RuleTypeDefault,
  2341. DefaultOptions: option.DefaultDNSRule{
  2342. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2343. Domain: badoption.Listable[string]{"example.com"},
  2344. },
  2345. DNSRuleAction: option.DNSRuleAction{
  2346. Action: C.RuleActionTypeReject,
  2347. RejectOptions: option.RejectActionOptions{
  2348. Method: C.RuleActionRejectMethodDrop,
  2349. },
  2350. },
  2351. },
  2352. },
  2353. }, &fakeDNSTransportManager{
  2354. defaultTransport: defaultTransport,
  2355. transports: map[string]adapter.DNSTransport{
  2356. "default": defaultTransport,
  2357. },
  2358. }, &fakeDNSClient{})
  2359. require.False(t, router.legacyDNSMode)
  2360. response, err := router.Exchange(context.Background(), &mDNS.Msg{
  2361. Question: []mDNS.Question{fixedQuestion("example.com", mDNS.TypeA)},
  2362. }, adapter.DNSQueryOptions{})
  2363. require.Nil(t, response)
  2364. require.ErrorIs(t, err, tun.ErrDrop)
  2365. }
  2366. func TestLookupLegacyDNSModeDisabledFiltersPerQueryTypeAddressesBeforeMerging(t *testing.T) {
  2367. t.Parallel()
  2368. defaultTransport := &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP}
  2369. router := newTestRouter(t, []option.DNSRule{
  2370. {
  2371. Type: C.RuleTypeDefault,
  2372. DefaultOptions: option.DefaultDNSRule{
  2373. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2374. Domain: badoption.Listable[string]{"example.com"},
  2375. },
  2376. DNSRuleAction: option.DNSRuleAction{
  2377. Action: C.RuleActionTypePredefined,
  2378. PredefinedOptions: option.DNSRouteActionPredefined{
  2379. Answer: badoption.Listable[option.DNSRecordOptions]{
  2380. mustRecord(t, "example.com. IN A 1.1.1.1"),
  2381. mustRecord(t, "example.com. IN AAAA 2001:db8::1"),
  2382. },
  2383. },
  2384. },
  2385. },
  2386. },
  2387. }, &fakeDNSTransportManager{
  2388. defaultTransport: defaultTransport,
  2389. transports: map[string]adapter.DNSTransport{
  2390. "default": defaultTransport,
  2391. },
  2392. }, &fakeDNSClient{})
  2393. require.False(t, router.legacyDNSMode)
  2394. addresses, err := router.Lookup(context.Background(), "example.com", adapter.DNSQueryOptions{})
  2395. require.NoError(t, err)
  2396. require.Equal(t, []netip.Addr{
  2397. netip.MustParseAddr("1.1.1.1"),
  2398. netip.MustParseAddr("2001:db8::1"),
  2399. }, addresses)
  2400. }
  2401. func TestExchangeLegacyDNSModeDisabledLogicalMatchResponseIPCIDRFallsThrough(t *testing.T) {
  2402. t.Parallel()
  2403. transportManager := &fakeDNSTransportManager{
  2404. defaultTransport: &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  2405. transports: map[string]adapter.DNSTransport{
  2406. "upstream": &fakeDNSTransport{tag: "upstream", transportType: C.DNSTypeUDP},
  2407. "selected": &fakeDNSTransport{tag: "selected", transportType: C.DNSTypeUDP},
  2408. "default": &fakeDNSTransport{tag: "default", transportType: C.DNSTypeUDP},
  2409. },
  2410. }
  2411. client := &fakeDNSClient{
  2412. exchange: func(transport adapter.DNSTransport, message *mDNS.Msg) (*mDNS.Msg, error) {
  2413. switch transport.Tag() {
  2414. case "upstream":
  2415. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("9.9.9.9")}, 60), nil
  2416. case "selected":
  2417. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("8.8.8.8")}, 60), nil
  2418. case "default":
  2419. return FixedResponse(0, message.Question[0], []netip.Addr{netip.MustParseAddr("4.4.4.4")}, 60), nil
  2420. default:
  2421. return nil, E.New("unexpected transport")
  2422. }
  2423. },
  2424. }
  2425. rules := []option.DNSRule{
  2426. {
  2427. Type: C.RuleTypeDefault,
  2428. DefaultOptions: option.DefaultDNSRule{
  2429. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2430. Domain: badoption.Listable[string]{"example.com"},
  2431. },
  2432. DNSRuleAction: option.DNSRuleAction{
  2433. Action: C.RuleActionTypeEvaluate,
  2434. RouteOptions: option.DNSRouteActionOptions{Server: "upstream"},
  2435. },
  2436. },
  2437. },
  2438. {
  2439. Type: C.RuleTypeLogical,
  2440. LogicalOptions: option.LogicalDNSRule{
  2441. RawLogicalDNSRule: option.RawLogicalDNSRule{
  2442. Mode: C.LogicalTypeOr,
  2443. Rules: []option.DNSRule{{
  2444. Type: C.RuleTypeDefault,
  2445. DefaultOptions: option.DefaultDNSRule{
  2446. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2447. MatchResponse: true,
  2448. IPCIDR: badoption.Listable[string]{"1.1.1.0/24"},
  2449. },
  2450. },
  2451. }},
  2452. },
  2453. DNSRuleAction: option.DNSRuleAction{
  2454. Action: C.RuleActionTypeRoute,
  2455. RouteOptions: option.DNSRouteActionOptions{Server: "selected"},
  2456. },
  2457. },
  2458. },
  2459. }
  2460. router := newTestRouter(t, rules, transportManager, client)
  2461. response, err := router.Exchange(context.Background(), &mDNS.Msg{
  2462. Question: []mDNS.Question{fixedQuestion("example.com", mDNS.TypeA)},
  2463. }, adapter.DNSQueryOptions{})
  2464. require.NoError(t, err)
  2465. require.Equal(t, []netip.Addr{netip.MustParseAddr("4.4.4.4")}, MessageToAddresses(response))
  2466. }
  2467. func TestLegacyDNSModeReportsLegacyAddressFilterDeprecation(t *testing.T) {
  2468. t.Parallel()
  2469. manager := &fakeDeprecatedManager{}
  2470. ctx := service.ContextWith[deprecated.Manager](context.Background(), manager)
  2471. router := &Router{
  2472. ctx: ctx,
  2473. logger: log.NewNOPFactory().NewLogger("dns"),
  2474. client: &fakeDNSClient{},
  2475. defaultDomainStrategy: C.DomainStrategyAsIS,
  2476. }
  2477. err := router.Initialize([]option.DNSRule{{
  2478. Type: C.RuleTypeDefault,
  2479. DefaultOptions: option.DefaultDNSRule{
  2480. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2481. IPCIDR: badoption.Listable[string]{"1.1.1.0/24"},
  2482. },
  2483. DNSRuleAction: option.DNSRuleAction{
  2484. Action: C.RuleActionTypeRoute,
  2485. RouteOptions: option.DNSRouteActionOptions{Server: "default"},
  2486. },
  2487. },
  2488. }})
  2489. require.NoError(t, err)
  2490. err = router.Start(adapter.StartStateStart)
  2491. require.NoError(t, err)
  2492. require.Len(t, manager.features, 1)
  2493. require.Equal(t, deprecated.OptionLegacyDNSAddressFilter.Name, manager.features[0].Name)
  2494. }
  2495. func TestLegacyDNSModeReportsDNSRuleStrategyDeprecation(t *testing.T) {
  2496. t.Parallel()
  2497. manager := &fakeDeprecatedManager{}
  2498. ctx := service.ContextWith[deprecated.Manager](context.Background(), manager)
  2499. router := &Router{
  2500. ctx: ctx,
  2501. logger: log.NewNOPFactory().NewLogger("dns"),
  2502. client: &fakeDNSClient{},
  2503. defaultDomainStrategy: C.DomainStrategyAsIS,
  2504. }
  2505. err := router.Initialize([]option.DNSRule{{
  2506. Type: C.RuleTypeDefault,
  2507. DefaultOptions: option.DefaultDNSRule{
  2508. RawDefaultDNSRule: option.RawDefaultDNSRule{
  2509. Domain: badoption.Listable[string]{"example.com"},
  2510. },
  2511. DNSRuleAction: option.DNSRuleAction{
  2512. Action: C.RuleActionTypeRoute,
  2513. RouteOptions: option.DNSRouteActionOptions{
  2514. Server: "default",
  2515. Strategy: option.DomainStrategy(C.DomainStrategyIPv4Only),
  2516. },
  2517. },
  2518. },
  2519. }})
  2520. require.NoError(t, err)
  2521. err = router.Start(adapter.StartStateStart)
  2522. require.NoError(t, err)
  2523. require.Len(t, manager.features, 1)
  2524. require.Equal(t, deprecated.OptionLegacyDNSRuleStrategy.Name, manager.features[0].Name)
  2525. }