transport_local.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package dns
  2. import (
  3. "context"
  4. "net"
  5. "net/netip"
  6. "os"
  7. "sort"
  8. "github.com/sagernet/sing/common"
  9. "github.com/sagernet/sing-box/adapter"
  10. C "github.com/sagernet/sing-box/constant"
  11. "golang.org/x/net/dns/dnsmessage"
  12. )
  13. var LocalTransportConstructor func() adapter.DNSTransport
  14. func NewLocalTransport() adapter.DNSTransport {
  15. if LocalTransportConstructor != nil {
  16. return LocalTransportConstructor()
  17. }
  18. return &LocalTransport{}
  19. }
  20. var _ adapter.DNSTransport = (*LocalTransport)(nil)
  21. type LocalTransport struct {
  22. resolver net.Resolver
  23. }
  24. func (t *LocalTransport) Start() error {
  25. return nil
  26. }
  27. func (t *LocalTransport) Close() error {
  28. return nil
  29. }
  30. func (t *LocalTransport) Raw() bool {
  31. return false
  32. }
  33. func (t *LocalTransport) Exchange(ctx context.Context, message *dnsmessage.Message) (*dnsmessage.Message, error) {
  34. return nil, os.ErrInvalid
  35. }
  36. func (t *LocalTransport) Lookup(ctx context.Context, domain string, strategy C.DomainStrategy) ([]netip.Addr, error) {
  37. var network string
  38. switch strategy {
  39. case C.DomainStrategyAsIS, C.DomainStrategyPreferIPv4, C.DomainStrategyPreferIPv6:
  40. network = "ip"
  41. case C.DomainStrategyUseIPv4:
  42. network = "ip4"
  43. case C.DomainStrategyUseIPv6:
  44. network = "ip6"
  45. }
  46. addrs, err := t.resolver.LookupNetIP(ctx, network, domain)
  47. if err != nil {
  48. return nil, err
  49. }
  50. addrs = common.Map(addrs, func(it netip.Addr) netip.Addr {
  51. if it.Is4In6() {
  52. return netip.AddrFrom4(it.As4())
  53. }
  54. return it
  55. })
  56. switch strategy {
  57. case C.DomainStrategyPreferIPv4:
  58. sort.Slice(addrs, func(i, j int) bool {
  59. return addrs[i].Is4() && addrs[j].Is6()
  60. })
  61. case C.DomainStrategyPreferIPv6:
  62. sort.Slice(addrs, func(i, j int) bool {
  63. return addrs[i].Is6() && addrs[j].Is4()
  64. })
  65. }
  66. return addrs, nil
  67. }