dns.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. package option
  2. import (
  3. "context"
  4. "net/netip"
  5. C "github.com/sagernet/sing-box/constant"
  6. E "github.com/sagernet/sing/common/exceptions"
  7. "github.com/sagernet/sing/common/json"
  8. "github.com/sagernet/sing/common/json/badjson"
  9. "github.com/sagernet/sing/common/json/badoption"
  10. M "github.com/sagernet/sing/common/metadata"
  11. "github.com/sagernet/sing/service"
  12. )
  13. type RawDNSOptions struct {
  14. Servers []DNSServerOptions `json:"servers,omitempty"`
  15. Rules []DNSRule `json:"rules,omitempty"`
  16. Final string `json:"final,omitempty"`
  17. ReverseMapping bool `json:"reverse_mapping,omitempty"`
  18. DNSClientOptions
  19. }
  20. type DNSOptions struct {
  21. RawDNSOptions
  22. }
  23. const (
  24. legacyDNSFakeIPRemovedMessage = "legacy DNS fakeip options are deprecated in sing-box 1.12.0 and removed in sing-box 1.14.0, checkout migration: https://sing-box.sagernet.org/migration/#migrate-to-new-dns-server-formats"
  25. legacyDNSServerRemovedMessage = "legacy DNS server formats are deprecated in sing-box 1.12.0 and removed in sing-box 1.14.0, checkout migration: https://sing-box.sagernet.org/migration/#migrate-to-new-dns-server-formats"
  26. )
  27. type removedLegacyDNSOptions struct {
  28. FakeIP json.RawMessage `json:"fakeip,omitempty"`
  29. }
  30. func (o *DNSOptions) UnmarshalJSONContext(ctx context.Context, content []byte) error {
  31. var legacyOptions removedLegacyDNSOptions
  32. err := json.UnmarshalContext(ctx, content, &legacyOptions)
  33. if err != nil {
  34. return err
  35. }
  36. if len(legacyOptions.FakeIP) != 0 {
  37. return E.New(legacyDNSFakeIPRemovedMessage)
  38. }
  39. return badjson.UnmarshallExcludedContext(ctx, content, legacyOptions, &o.RawDNSOptions)
  40. }
  41. type DNSClientOptions struct {
  42. Strategy DomainStrategy `json:"strategy,omitempty"`
  43. DisableCache bool `json:"disable_cache,omitempty"`
  44. DisableExpire bool `json:"disable_expire,omitempty"`
  45. IndependentCache bool `json:"independent_cache,omitempty"`
  46. CacheCapacity uint32 `json:"cache_capacity,omitempty"`
  47. Optimistic *OptimisticDNSOptions `json:"optimistic,omitempty"`
  48. ClientSubnet *badoption.Prefixable `json:"client_subnet,omitempty"`
  49. }
  50. type _OptimisticDNSOptions struct {
  51. Enabled bool `json:"enabled,omitempty"`
  52. Timeout badoption.Duration `json:"timeout,omitempty"`
  53. }
  54. type OptimisticDNSOptions _OptimisticDNSOptions
  55. func (o OptimisticDNSOptions) MarshalJSON() ([]byte, error) {
  56. if o.Timeout == 0 {
  57. return json.Marshal(o.Enabled)
  58. }
  59. return json.Marshal((_OptimisticDNSOptions)(o))
  60. }
  61. func (o *OptimisticDNSOptions) UnmarshalJSON(bytes []byte) error {
  62. err := json.Unmarshal(bytes, &o.Enabled)
  63. if err == nil {
  64. return nil
  65. }
  66. return json.UnmarshalDisallowUnknownFields(bytes, (*_OptimisticDNSOptions)(o))
  67. }
  68. type DNSTransportOptionsRegistry interface {
  69. CreateOptions(transportType string) (any, bool)
  70. }
  71. type _DNSServerOptions struct {
  72. Type string `json:"type,omitempty"`
  73. Tag string `json:"tag,omitempty"`
  74. Options any `json:"-"`
  75. }
  76. type DNSServerOptions _DNSServerOptions
  77. func (o *DNSServerOptions) MarshalJSONContext(ctx context.Context) ([]byte, error) {
  78. return badjson.MarshallObjectsContext(ctx, (*_DNSServerOptions)(o), o.Options)
  79. }
  80. func (o *DNSServerOptions) UnmarshalJSONContext(ctx context.Context, content []byte) error {
  81. err := json.UnmarshalContext(ctx, content, (*_DNSServerOptions)(o))
  82. if err != nil {
  83. return err
  84. }
  85. registry := service.FromContext[DNSTransportOptionsRegistry](ctx)
  86. if registry == nil {
  87. return E.New("missing DNS transport options registry in context")
  88. }
  89. var options any
  90. switch o.Type {
  91. case "", C.DNSTypeLegacy:
  92. return E.New(legacyDNSServerRemovedMessage)
  93. default:
  94. var loaded bool
  95. options, loaded = registry.CreateOptions(o.Type)
  96. if !loaded {
  97. return E.New("unknown transport type: ", o.Type)
  98. }
  99. }
  100. err = badjson.UnmarshallExcludedContext(ctx, content, (*_DNSServerOptions)(o), options)
  101. if err != nil {
  102. return err
  103. }
  104. o.Options = options
  105. return nil
  106. }
  107. type DNSServerAddressOptions struct {
  108. Server string `json:"server"`
  109. ServerPort uint16 `json:"server_port,omitempty"`
  110. }
  111. func (o DNSServerAddressOptions) Build() M.Socksaddr {
  112. return M.ParseSocksaddrHostPort(o.Server, o.ServerPort)
  113. }
  114. func (o DNSServerAddressOptions) ServerIsDomain() bool {
  115. return o.Build().IsDomain()
  116. }
  117. func (o *DNSServerAddressOptions) TakeServerOptions() ServerOptions {
  118. return ServerOptions(*o)
  119. }
  120. func (o *DNSServerAddressOptions) ReplaceServerOptions(options ServerOptions) {
  121. *o = DNSServerAddressOptions(options)
  122. }
  123. type HostsDNSServerOptions struct {
  124. Path badoption.Listable[string] `json:"path,omitempty"`
  125. Predefined *badjson.TypedMap[string, badoption.Listable[netip.Addr]] `json:"predefined,omitempty"`
  126. }
  127. type RawLocalDNSServerOptions struct {
  128. DialerOptions
  129. }
  130. type LocalDNSServerOptions struct {
  131. RawLocalDNSServerOptions
  132. PreferGo bool `json:"prefer_go,omitempty"`
  133. }
  134. type RemoteDNSServerOptions struct {
  135. RawLocalDNSServerOptions
  136. DNSServerAddressOptions
  137. }
  138. type RemoteTLSDNSServerOptions struct {
  139. RemoteDNSServerOptions
  140. OutboundTLSOptionsContainer
  141. }
  142. type RemoteHTTPSDNSServerOptions struct {
  143. RemoteTLSDNSServerOptions
  144. Path string `json:"path,omitempty"`
  145. Method string `json:"method,omitempty"`
  146. Headers badoption.HTTPHeader `json:"headers,omitempty"`
  147. }
  148. type FakeIPDNSServerOptions struct {
  149. Inet4Range *badoption.Prefix `json:"inet4_range,omitempty"`
  150. Inet6Range *badoption.Prefix `json:"inet6_range,omitempty"`
  151. }
  152. type DHCPDNSServerOptions struct {
  153. LocalDNSServerOptions
  154. Interface string `json:"interface,omitempty"`
  155. }