dns_transport.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. package tailscale
  2. import (
  3. "context"
  4. "net"
  5. "net/http"
  6. "net/netip"
  7. "net/url"
  8. "os"
  9. "strings"
  10. "sync"
  11. "github.com/sagernet/sing-box/adapter"
  12. "github.com/sagernet/sing-box/common/dialer"
  13. "github.com/sagernet/sing-box/common/tls"
  14. C "github.com/sagernet/sing-box/constant"
  15. "github.com/sagernet/sing-box/dns"
  16. "github.com/sagernet/sing-box/dns/transport"
  17. "github.com/sagernet/sing-box/log"
  18. "github.com/sagernet/sing-box/option"
  19. "github.com/sagernet/sing/common"
  20. E "github.com/sagernet/sing/common/exceptions"
  21. "github.com/sagernet/sing/common/logger"
  22. M "github.com/sagernet/sing/common/metadata"
  23. N "github.com/sagernet/sing/common/network"
  24. "github.com/sagernet/sing/service"
  25. nDNS "github.com/sagernet/tailscale/net/dns"
  26. "github.com/sagernet/tailscale/types/dnstype"
  27. "github.com/sagernet/tailscale/wgengine/router"
  28. "github.com/sagernet/tailscale/wgengine/wgcfg"
  29. mDNS "github.com/miekg/dns"
  30. "go4.org/netipx"
  31. "golang.org/x/net/http2"
  32. )
  33. func RegistryTransport(registry *dns.TransportRegistry) {
  34. dns.RegisterTransport[option.TailscaleDNSServerOptions](registry, C.DNSTypeTailscale, NewDNSTransport)
  35. }
  36. type DNSTransport struct {
  37. dns.TransportAdapter
  38. ctx context.Context
  39. logger logger.ContextLogger
  40. endpointTag string
  41. acceptDefaultResolvers bool
  42. dnsRouter adapter.DNSRouter
  43. endpointManager adapter.EndpointManager
  44. endpoint *Endpoint
  45. routePrefixes []netip.Prefix
  46. routes map[string][]adapter.DNSTransport
  47. hosts map[string][]netip.Addr
  48. defaultResolvers []adapter.DNSTransport
  49. }
  50. func NewDNSTransport(ctx context.Context, logger log.ContextLogger, tag string, options option.TailscaleDNSServerOptions) (adapter.DNSTransport, error) {
  51. if options.Endpoint == "" {
  52. return nil, E.New("missing tailscale endpoint tag")
  53. }
  54. return &DNSTransport{
  55. TransportAdapter: dns.NewTransportAdapter(C.DNSTypeTailscale, tag, nil),
  56. ctx: ctx,
  57. logger: logger,
  58. endpointTag: options.Endpoint,
  59. acceptDefaultResolvers: options.AcceptDefaultResolvers,
  60. dnsRouter: service.FromContext[adapter.DNSRouter](ctx),
  61. endpointManager: service.FromContext[adapter.EndpointManager](ctx),
  62. }, nil
  63. }
  64. func (t *DNSTransport) Start(stage adapter.StartStage) error {
  65. if stage != adapter.StartStateInitialize {
  66. return nil
  67. }
  68. rawOutbound, loaded := t.endpointManager.Get(t.endpointTag)
  69. if !loaded {
  70. return E.New("endpoint not found: ", t.endpointTag)
  71. }
  72. ep, isTailscale := rawOutbound.(*Endpoint)
  73. if !isTailscale {
  74. return E.New("endpoint is not Tailscale: ", t.endpointTag)
  75. }
  76. if ep.onReconfigHook != nil {
  77. return E.New("only one Tailscale DNS server is allowed for single endpoint")
  78. }
  79. ep.onReconfigHook = t.onReconfig
  80. t.endpoint = ep
  81. return nil
  82. }
  83. func (t *DNSTransport) Reset() {
  84. }
  85. func (t *DNSTransport) onReconfig(cfg *wgcfg.Config, routerCfg *router.Config, dnsCfg *nDNS.Config) {
  86. err := t.updateDNSServers(routerCfg, dnsCfg)
  87. if err != nil {
  88. t.logger.Error(E.Cause(err, "update DNS servers"))
  89. }
  90. }
  91. func (t *DNSTransport) updateDNSServers(routeConfig *router.Config, dnsConfig *nDNS.Config) error {
  92. t.routePrefixes = buildRoutePrefixes(routeConfig)
  93. directDialerOnce := sync.OnceValue(func() N.Dialer {
  94. directDialer := common.Must1(dialer.NewDefault(t.ctx, option.DialerOptions{}))
  95. return &DNSDialer{transport: t, fallbackDialer: directDialer}
  96. })
  97. routes := make(map[string][]adapter.DNSTransport)
  98. for domain, resolvers := range dnsConfig.Routes {
  99. var myResolvers []adapter.DNSTransport
  100. for _, resolver := range resolvers {
  101. myResolver, err := t.createResolver(directDialerOnce, resolver)
  102. if err != nil {
  103. return err
  104. }
  105. myResolvers = append(myResolvers, myResolver)
  106. }
  107. routes[domain.WithTrailingDot()] = myResolvers
  108. }
  109. hosts := make(map[string][]netip.Addr)
  110. for domain, addresses := range dnsConfig.Hosts {
  111. hosts[domain.WithTrailingDot()] = addresses
  112. }
  113. var defaultResolvers []adapter.DNSTransport
  114. for _, resolver := range dnsConfig.DefaultResolvers {
  115. myResolver, err := t.createResolver(directDialerOnce, resolver)
  116. if err != nil {
  117. return err
  118. }
  119. defaultResolvers = append(defaultResolvers, myResolver)
  120. }
  121. t.routes = routes
  122. t.hosts = hosts
  123. t.defaultResolvers = defaultResolvers
  124. if len(defaultResolvers) > 0 {
  125. t.logger.Info("updated ", len(routes), " routes, ", len(hosts), " hosts, default resolvers: ",
  126. strings.Join(common.Map(dnsConfig.DefaultResolvers, func(it *dnstype.Resolver) string { return it.Addr }), " "))
  127. } else {
  128. t.logger.Info("updated ", len(routes), " routes, ", len(hosts), " hosts")
  129. }
  130. return nil
  131. }
  132. func (t *DNSTransport) createResolver(directDialer func() N.Dialer, resolver *dnstype.Resolver) (adapter.DNSTransport, error) {
  133. serverURL, parseURLErr := url.Parse(resolver.Addr)
  134. var myDialer N.Dialer
  135. if parseURLErr == nil && serverURL.Scheme == "http" {
  136. myDialer = t.endpoint
  137. } else {
  138. myDialer = directDialer()
  139. }
  140. if len(resolver.BootstrapResolution) > 0 {
  141. bootstrapTransport := transport.NewUDPRaw(t.logger, t.TransportAdapter, myDialer, M.SocksaddrFrom(resolver.BootstrapResolution[0], 53))
  142. myDialer = dialer.NewResolveDialer(t.ctx, myDialer, false, "", adapter.DNSQueryOptions{Transport: bootstrapTransport}, 0)
  143. }
  144. if serverAddr := M.ParseSocksaddr(resolver.Addr); serverAddr.IsValid() {
  145. if serverAddr.Port == 0 {
  146. serverAddr.Port = 53
  147. }
  148. return transport.NewUDPRaw(t.logger, t.TransportAdapter, myDialer, serverAddr), nil
  149. } else if parseURLErr != nil {
  150. return nil, E.Cause(parseURLErr, "parse resolver address")
  151. } else {
  152. switch serverURL.Scheme {
  153. case "https":
  154. serverAddr = M.ParseSocksaddrHostPortStr(serverURL.Hostname(), serverURL.Port())
  155. if serverAddr.Port == 0 {
  156. serverAddr.Port = 443
  157. }
  158. tlsConfig := common.Must1(tls.NewClient(t.ctx, serverAddr.AddrString(), option.OutboundTLSOptions{
  159. ALPN: []string{http2.NextProtoTLS, "http/1.1"},
  160. }))
  161. return transport.NewHTTPSRaw(t.TransportAdapter, t.logger, myDialer, serverURL, http.Header{}, serverAddr, tlsConfig), nil
  162. case "http":
  163. serverAddr = M.ParseSocksaddrHostPortStr(serverURL.Hostname(), serverURL.Port())
  164. if serverAddr.Port == 0 {
  165. serverAddr.Port = 80
  166. }
  167. return transport.NewHTTPSRaw(t.TransportAdapter, t.logger, myDialer, serverURL, http.Header{}, serverAddr, nil), nil
  168. // case "tls":
  169. default:
  170. return nil, E.New("unknown resolver scheme: ", serverURL.Scheme)
  171. }
  172. }
  173. }
  174. func buildRoutePrefixes(routeConfig *router.Config) []netip.Prefix {
  175. var builder netipx.IPSetBuilder
  176. for _, localAddr := range routeConfig.LocalAddrs {
  177. builder.AddPrefix(localAddr)
  178. }
  179. for _, route := range routeConfig.Routes {
  180. builder.AddPrefix(route)
  181. }
  182. for _, route := range routeConfig.LocalRoutes {
  183. builder.AddPrefix(route)
  184. }
  185. for _, route := range routeConfig.SubnetRoutes {
  186. builder.AddPrefix(route)
  187. }
  188. ipSet, err := builder.IPSet()
  189. if err != nil {
  190. return nil
  191. }
  192. return ipSet.Prefixes()
  193. }
  194. func (t *DNSTransport) Close() error {
  195. return nil
  196. }
  197. func (t *DNSTransport) Raw() bool {
  198. return true
  199. }
  200. func (t *DNSTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
  201. if len(message.Question) != 1 {
  202. return nil, os.ErrInvalid
  203. }
  204. question := message.Question[0]
  205. addresses, hostsLoaded := t.hosts[question.Name]
  206. if hostsLoaded {
  207. switch question.Qtype {
  208. case mDNS.TypeA:
  209. addresses4 := common.Filter(addresses, func(addr netip.Addr) bool {
  210. return addr.Is4()
  211. })
  212. if len(addresses4) > 0 {
  213. return dns.FixedResponse(message.Id, question, addresses4, C.DefaultDNSTTL), nil
  214. }
  215. case mDNS.TypeAAAA:
  216. addresses6 := common.Filter(addresses, func(addr netip.Addr) bool {
  217. return addr.Is6()
  218. })
  219. if len(addresses6) > 0 {
  220. return dns.FixedResponse(message.Id, question, addresses6, C.DefaultDNSTTL), nil
  221. }
  222. }
  223. }
  224. for domainSuffix, transports := range t.routes {
  225. if strings.HasSuffix(question.Name, domainSuffix) {
  226. if len(transports) == 0 {
  227. return &mDNS.Msg{
  228. MsgHdr: mDNS.MsgHdr{
  229. Id: message.Id,
  230. Rcode: mDNS.RcodeNameError,
  231. Response: true,
  232. },
  233. Question: []mDNS.Question{question},
  234. }, nil
  235. }
  236. var lastErr error
  237. for _, dnsTransport := range transports {
  238. response, err := dnsTransport.Exchange(ctx, message)
  239. if err != nil {
  240. lastErr = err
  241. continue
  242. }
  243. return response, nil
  244. }
  245. return nil, lastErr
  246. }
  247. }
  248. if t.acceptDefaultResolvers {
  249. if len(t.defaultResolvers) > 0 {
  250. var lastErr error
  251. for _, resolver := range t.defaultResolvers {
  252. response, err := resolver.Exchange(ctx, message)
  253. if err != nil {
  254. lastErr = err
  255. continue
  256. }
  257. return response, nil
  258. }
  259. return nil, lastErr
  260. } else {
  261. return nil, E.New("missing default resolvers")
  262. }
  263. }
  264. return nil, dns.RcodeNameError
  265. }
  266. type DNSDialer struct {
  267. transport *DNSTransport
  268. fallbackDialer N.Dialer
  269. }
  270. func (d *DNSDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  271. if destination.IsFqdn() {
  272. panic("invalid request here")
  273. }
  274. for _, prefix := range d.transport.routePrefixes {
  275. if prefix.Contains(destination.Addr) {
  276. return d.transport.endpoint.DialContext(ctx, network, destination)
  277. }
  278. }
  279. return d.fallbackDialer.DialContext(ctx, network, destination)
  280. }
  281. func (d *DNSDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  282. if destination.IsFqdn() {
  283. panic("invalid request here")
  284. }
  285. for _, prefix := range d.transport.routePrefixes {
  286. if prefix.Contains(destination.Addr) {
  287. return d.transport.endpoint.ListenPacket(ctx, destination)
  288. }
  289. }
  290. return d.fallbackDialer.ListenPacket(ctx, destination)
  291. }