local.go 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //go:build !darwin
  2. package local
  3. import (
  4. "context"
  5. "github.com/sagernet/sing-box/adapter"
  6. C "github.com/sagernet/sing-box/constant"
  7. "github.com/sagernet/sing-box/dns"
  8. "github.com/sagernet/sing-box/dns/transport/hosts"
  9. "github.com/sagernet/sing-box/log"
  10. "github.com/sagernet/sing-box/option"
  11. E "github.com/sagernet/sing/common/exceptions"
  12. "github.com/sagernet/sing/common/logger"
  13. N "github.com/sagernet/sing/common/network"
  14. mDNS "github.com/miekg/dns"
  15. )
  16. func RegisterTransport(registry *dns.TransportRegistry) {
  17. dns.RegisterTransport[option.LocalDNSServerOptions](registry, C.DNSTypeLocal, NewTransport)
  18. }
  19. var _ adapter.DNSTransport = (*Transport)(nil)
  20. type Transport struct {
  21. dns.TransportAdapter
  22. ctx context.Context
  23. logger logger.ContextLogger
  24. hosts *hosts.File
  25. dialer N.Dialer
  26. preferGo bool
  27. resolved ResolvedResolver
  28. }
  29. func NewTransport(ctx context.Context, logger log.ContextLogger, tag string, options option.LocalDNSServerOptions) (adapter.DNSTransport, error) {
  30. transportDialer, err := dns.NewLocalDialer(ctx, options)
  31. if err != nil {
  32. return nil, err
  33. }
  34. return &Transport{
  35. TransportAdapter: dns.NewTransportAdapterWithLocalOptions(C.DNSTypeLocal, tag, options),
  36. ctx: ctx,
  37. logger: logger,
  38. hosts: hosts.NewFile(hosts.DefaultPath),
  39. dialer: transportDialer,
  40. preferGo: options.PreferGo,
  41. }, nil
  42. }
  43. func (t *Transport) Start(stage adapter.StartStage) error {
  44. switch stage {
  45. case adapter.StartStateInitialize:
  46. if !t.preferGo {
  47. if isSystemdResolvedManaged() {
  48. resolvedResolver, err := NewResolvedResolver(t.ctx, t.logger)
  49. if err == nil {
  50. err = resolvedResolver.Start()
  51. if err == nil {
  52. t.resolved = resolvedResolver
  53. } else {
  54. t.logger.Warn(E.Cause(err, "initialize resolved resolver"))
  55. }
  56. }
  57. }
  58. }
  59. }
  60. return nil
  61. }
  62. func (t *Transport) Close() error {
  63. if t.resolved != nil {
  64. return t.resolved.Close()
  65. }
  66. return nil
  67. }
  68. func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
  69. if t.resolved != nil {
  70. resolverObject := t.resolved.Object()
  71. if resolverObject != nil {
  72. return t.resolved.Exchange(resolverObject, ctx, message)
  73. }
  74. }
  75. question := message.Question[0]
  76. if question.Qtype == mDNS.TypeA || question.Qtype == mDNS.TypeAAAA {
  77. addresses := t.hosts.Lookup(dns.FqdnToDomain(question.Name))
  78. if len(addresses) > 0 {
  79. return dns.FixedResponse(message.Id, question, addresses, C.DefaultDNSTTL), nil
  80. }
  81. }
  82. return t.exchange(ctx, message, question.Name)
  83. }