mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-10 02:53:12 +00:00
Add custom prefix support in EDNS0 client subnet options
This commit is contained in:
parent
0e120f8a44
commit
da9e22b4e6
|
@ -86,7 +86,7 @@ type DNSRule interface {
|
||||||
Rule
|
Rule
|
||||||
DisableCache() bool
|
DisableCache() bool
|
||||||
RewriteTTL() *uint32
|
RewriteTTL() *uint32
|
||||||
ClientSubnet() *netip.Addr
|
ClientSubnet() *netip.Prefix
|
||||||
WithAddressLimit() bool
|
WithAddressLimit() bool
|
||||||
MatchAddressLimit(metadata *InboundContext) bool
|
MatchAddressLimit(metadata *InboundContext) bool
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,8 @@ problematic in environments such as macOS, where DNS is proxied and cached by th
|
||||||
|
|
||||||
!!! question "Since sing-box 1.9.0"
|
!!! question "Since sing-box 1.9.0"
|
||||||
|
|
||||||
Append a `edns0-subnet` OPT extra record with the specified IP address to every query by default.
|
Append a `edns0-subnet` OPT extra record with the specified IP prefix to every query by default.
|
||||||
|
|
||||||
|
If value is an IP address instead of prefix, `/32` or `/128` will be appended automatically.
|
||||||
|
|
||||||
Can be overrides by `servers.[].client_subnet` or `rules.[].client_subnet`.
|
Can be overrides by `servers.[].client_subnet` or `rules.[].client_subnet`.
|
||||||
|
|
|
@ -71,7 +71,9 @@ icon: material/new-box
|
||||||
|
|
||||||
!!! question "自 sing-box 1.9.0 起"
|
!!! question "自 sing-box 1.9.0 起"
|
||||||
|
|
||||||
默认情况下,将带有指定 IP 地址的 `edns0-subnet` OPT 附加记录附加到每个查询。
|
默认情况下,将带有指定 IP 前缀的 `edns0-subnet` OPT 附加记录附加到每个查询。
|
||||||
|
|
||||||
|
如果值是 IP 地址而不是前缀,则会自动附加 `/32` 或 `/128`。
|
||||||
|
|
||||||
可以被 `servers.[].client_subnet` 或 `rules.[].client_subnet` 覆盖。
|
可以被 `servers.[].client_subnet` 或 `rules.[].client_subnet` 覆盖。
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ icon: material/new-box
|
||||||
"server": "local",
|
"server": "local",
|
||||||
"disable_cache": false,
|
"disable_cache": false,
|
||||||
"rewrite_ttl": 100,
|
"rewrite_ttl": 100,
|
||||||
"client_subnet": "127.0.0.1"
|
"client_subnet": "127.0.0.1/24"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "logical",
|
"type": "logical",
|
||||||
|
@ -134,7 +134,7 @@ icon: material/new-box
|
||||||
"server": "local",
|
"server": "local",
|
||||||
"disable_cache": false,
|
"disable_cache": false,
|
||||||
"rewrite_ttl": 100,
|
"rewrite_ttl": 100,
|
||||||
"client_subnet": "127.0.0.1"
|
"client_subnet": "127.0.0.1/24"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -339,7 +339,9 @@ Rewrite TTL in DNS responses.
|
||||||
|
|
||||||
!!! question "Since sing-box 1.9.0"
|
!!! question "Since sing-box 1.9.0"
|
||||||
|
|
||||||
Append a `edns0-subnet` OPT extra record with the specified IP address to every query by default.
|
Append a `edns0-subnet` OPT extra record with the specified IP prefix to every query by default.
|
||||||
|
|
||||||
|
If value is an IP address instead of prefix, `/32` or `/128` will be appended automatically.
|
||||||
|
|
||||||
Will overrides `dns.client_subnet` and `servers.[].client_subnet`.
|
Will overrides `dns.client_subnet` and `servers.[].client_subnet`.
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ icon: material/new-box
|
||||||
],
|
],
|
||||||
"server": "local",
|
"server": "local",
|
||||||
"disable_cache": false,
|
"disable_cache": false,
|
||||||
"client_subnet": "127.0.0.1"
|
"client_subnet": "127.0.0.1/24"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "logical",
|
"type": "logical",
|
||||||
|
@ -132,7 +132,7 @@ icon: material/new-box
|
||||||
"rules": [],
|
"rules": [],
|
||||||
"server": "local",
|
"server": "local",
|
||||||
"disable_cache": false,
|
"disable_cache": false,
|
||||||
"client_subnet": "127.0.0.1"
|
"client_subnet": "127.0.0.1/24"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -337,7 +337,9 @@ DNS 查询类型。值可以为整数或者类型名称字符串。
|
||||||
|
|
||||||
!!! question "自 sing-box 1.9.0 起"
|
!!! question "自 sing-box 1.9.0 起"
|
||||||
|
|
||||||
默认情况下,将带有指定 IP 地址的 `edns0-subnet` OPT 附加记录附加到每个查询。
|
默认情况下,将带有指定 IP 前缀的 `edns0-subnet` OPT 附加记录附加到每个查询。
|
||||||
|
|
||||||
|
如果值是 IP 地址而不是前缀,则会自动附加 `/32` 或 `/128`。
|
||||||
|
|
||||||
将覆盖 `dns.client_subnet` 与 `servers.[].client_subnet`。
|
将覆盖 `dns.client_subnet` 与 `servers.[].client_subnet`。
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,9 @@ Default outbound will be used if empty.
|
||||||
|
|
||||||
!!! question "Since sing-box 1.9.0"
|
!!! question "Since sing-box 1.9.0"
|
||||||
|
|
||||||
Append a `edns0-subnet` OPT extra record with the specified IP address to every query by default.
|
Append a `edns0-subnet` OPT extra record with the specified IP prefix to every query by default.
|
||||||
|
|
||||||
|
If value is an IP address instead of prefix, `/32` or `/128` will be appended automatically.
|
||||||
|
|
||||||
Can be overrides by `rules.[].client_subnet`.
|
Can be overrides by `rules.[].client_subnet`.
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,9 @@ DNS 服务器的地址。
|
||||||
|
|
||||||
!!! question "自 sing-box 1.9.0 起"
|
!!! question "自 sing-box 1.9.0 起"
|
||||||
|
|
||||||
默认情况下,将带有指定 IP 地址的 `edns0-subnet` OPT 附加记录附加到每个查询。
|
默认情况下,将带有指定 IP 前缀的 `edns0-subnet` OPT 附加记录附加到每个查询。
|
||||||
|
|
||||||
|
如果值是 IP 地址而不是前缀,则会自动附加 `/32` 或 `/128`。
|
||||||
|
|
||||||
可以被 `rules.[].client_subnet` 覆盖。
|
可以被 `rules.[].client_subnet` 覆盖。
|
||||||
|
|
||||||
|
|
|
@ -441,7 +441,7 @@ flowchart TB
|
||||||
{
|
{
|
||||||
"rule_set": "geoip-cn",
|
"rule_set": "geoip-cn",
|
||||||
"server": "google",
|
"server": "google",
|
||||||
"client_subnet": "114.114.114.114" // Any China client IP address
|
"client_subnet": "114.114.114.114/24" // Any China client IP address
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -57,6 +57,7 @@ type CacheFile struct {
|
||||||
type saveRDRCCacheKey struct {
|
type saveRDRCCacheKey struct {
|
||||||
TransportName string
|
TransportName string
|
||||||
QuestionName string
|
QuestionName string
|
||||||
|
QType uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(ctx context.Context, options option.CacheFileOptions) *CacheFile {
|
func New(ctx context.Context, options option.CacheFileOptions) *CacheFile {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/sagernet/sing/common/logger"
|
"github.com/sagernet/sing/common/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
var bucketRDRC = []byte("rdrc")
|
var bucketRDRC = []byte("rdrc2")
|
||||||
|
|
||||||
func (c *CacheFile) StoreRDRC() bool {
|
func (c *CacheFile) StoreRDRC() bool {
|
||||||
return c.storeRDRC
|
return c.storeRDRC
|
||||||
|
@ -19,13 +19,17 @@ func (c *CacheFile) RDRCTimeout() time.Duration {
|
||||||
return c.rdrcTimeout
|
return c.rdrcTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheFile) LoadRDRC(transportName string, qName string) (rejected bool) {
|
func (c *CacheFile) LoadRDRC(transportName string, qName string, qType uint16) (rejected bool) {
|
||||||
c.saveRDRCAccess.RLock()
|
c.saveRDRCAccess.RLock()
|
||||||
rejected, cached := c.saveRDRC[saveRDRCCacheKey{transportName, qName}]
|
rejected, cached := c.saveRDRC[saveRDRCCacheKey{transportName, qName, qType}]
|
||||||
c.saveRDRCAccess.RUnlock()
|
c.saveRDRCAccess.RUnlock()
|
||||||
if cached {
|
if cached {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
key := buf.Get(2 + len(qName))
|
||||||
|
binary.BigEndian.PutUint16(key, qType)
|
||||||
|
copy(key[2:], qName)
|
||||||
|
defer buf.Put(key)
|
||||||
var deleteCache bool
|
var deleteCache bool
|
||||||
err := c.DB.View(func(tx *bbolt.Tx) error {
|
err := c.DB.View(func(tx *bbolt.Tx) error {
|
||||||
bucket := c.bucket(tx, bucketRDRC)
|
bucket := c.bucket(tx, bucketRDRC)
|
||||||
|
@ -36,7 +40,7 @@ func (c *CacheFile) LoadRDRC(transportName string, qName string) (rejected bool)
|
||||||
if bucket == nil {
|
if bucket == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
content := bucket.Get([]byte(qName))
|
content := bucket.Get(key)
|
||||||
if content == nil {
|
if content == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -61,13 +65,13 @@ func (c *CacheFile) LoadRDRC(transportName string, qName string) (rejected bool)
|
||||||
if bucket == nil {
|
if bucket == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return bucket.Delete([]byte(qName))
|
return bucket.Delete(key)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheFile) SaveRDRC(transportName string, qName string) error {
|
func (c *CacheFile) SaveRDRC(transportName string, qName string, qType uint16) error {
|
||||||
return c.DB.Batch(func(tx *bbolt.Tx) error {
|
return c.DB.Batch(func(tx *bbolt.Tx) error {
|
||||||
bucket, err := c.createBucket(tx, bucketRDRC)
|
bucket, err := c.createBucket(tx, bucketRDRC)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -77,20 +81,24 @@ func (c *CacheFile) SaveRDRC(transportName string, qName string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
key := buf.Get(2 + len(qName))
|
||||||
|
binary.BigEndian.PutUint16(key, qType)
|
||||||
|
copy(key[2:], qName)
|
||||||
|
defer buf.Put(key)
|
||||||
expiresAt := buf.Get(8)
|
expiresAt := buf.Get(8)
|
||||||
defer buf.Put(expiresAt)
|
defer buf.Put(expiresAt)
|
||||||
binary.BigEndian.PutUint64(expiresAt, uint64(time.Now().Add(c.rdrcTimeout).Unix()))
|
binary.BigEndian.PutUint64(expiresAt, uint64(time.Now().Add(c.rdrcTimeout).Unix()))
|
||||||
return bucket.Put([]byte(qName), expiresAt)
|
return bucket.Put(key, expiresAt)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheFile) SaveRDRCAsync(transportName string, qName string, logger logger.Logger) {
|
func (c *CacheFile) SaveRDRCAsync(transportName string, qName string, qType uint16, logger logger.Logger) {
|
||||||
saveKey := saveRDRCCacheKey{transportName, qName}
|
saveKey := saveRDRCCacheKey{transportName, qName, qType}
|
||||||
c.saveRDRCAccess.Lock()
|
c.saveRDRCAccess.Lock()
|
||||||
c.saveRDRC[saveKey] = true
|
c.saveRDRC[saveKey] = true
|
||||||
c.saveRDRCAccess.Unlock()
|
c.saveRDRCAccess.Unlock()
|
||||||
go func() {
|
go func() {
|
||||||
err := c.SaveRDRC(transportName, qName)
|
err := c.SaveRDRC(transportName, qName, qType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn("save RDRC: ", err)
|
logger.Warn("save RDRC: ", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ type DNSServerOptions struct {
|
||||||
AddressFallbackDelay Duration `json:"address_fallback_delay,omitempty"`
|
AddressFallbackDelay Duration `json:"address_fallback_delay,omitempty"`
|
||||||
Strategy DomainStrategy `json:"strategy,omitempty"`
|
Strategy DomainStrategy `json:"strategy,omitempty"`
|
||||||
Detour string `json:"detour,omitempty"`
|
Detour string `json:"detour,omitempty"`
|
||||||
ClientSubnet *ListenAddress `json:"client_subnet,omitempty"`
|
ClientSubnet *AddrPrefix `json:"client_subnet,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DNSClientOptions struct {
|
type DNSClientOptions struct {
|
||||||
|
@ -27,7 +27,7 @@ type DNSClientOptions struct {
|
||||||
DisableCache bool `json:"disable_cache,omitempty"`
|
DisableCache bool `json:"disable_cache,omitempty"`
|
||||||
DisableExpire bool `json:"disable_expire,omitempty"`
|
DisableExpire bool `json:"disable_expire,omitempty"`
|
||||||
IndependentCache bool `json:"independent_cache,omitempty"`
|
IndependentCache bool `json:"independent_cache,omitempty"`
|
||||||
ClientSubnet *ListenAddress `json:"client_subnet,omitempty"`
|
ClientSubnet *AddrPrefix `json:"client_subnet,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DNSFakeIPOptions struct {
|
type DNSFakeIPOptions struct {
|
||||||
|
|
|
@ -101,7 +101,7 @@ type DefaultDNSRule struct {
|
||||||
Server string `json:"server,omitempty"`
|
Server string `json:"server,omitempty"`
|
||||||
DisableCache bool `json:"disable_cache,omitempty"`
|
DisableCache bool `json:"disable_cache,omitempty"`
|
||||||
RewriteTTL *uint32 `json:"rewrite_ttl,omitempty"`
|
RewriteTTL *uint32 `json:"rewrite_ttl,omitempty"`
|
||||||
ClientSubnet *ListenAddress `json:"client_subnet,omitempty"`
|
ClientSubnet *AddrPrefix `json:"client_subnet,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r DefaultDNSRule) IsValid() bool {
|
func (r DefaultDNSRule) IsValid() bool {
|
||||||
|
@ -115,13 +115,13 @@ func (r DefaultDNSRule) IsValid() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
type LogicalDNSRule struct {
|
type LogicalDNSRule struct {
|
||||||
Mode string `json:"mode"`
|
Mode string `json:"mode"`
|
||||||
Rules []DNSRule `json:"rules,omitempty"`
|
Rules []DNSRule `json:"rules,omitempty"`
|
||||||
Invert bool `json:"invert,omitempty"`
|
Invert bool `json:"invert,omitempty"`
|
||||||
Server string `json:"server,omitempty"`
|
Server string `json:"server,omitempty"`
|
||||||
DisableCache bool `json:"disable_cache,omitempty"`
|
DisableCache bool `json:"disable_cache,omitempty"`
|
||||||
RewriteTTL *uint32 `json:"rewrite_ttl,omitempty"`
|
RewriteTTL *uint32 `json:"rewrite_ttl,omitempty"`
|
||||||
ClientSubnet *ListenAddress `json:"client_subnet,omitempty"`
|
ClientSubnet *AddrPrefix `json:"client_subnet,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r LogicalDNSRule) IsValid() bool {
|
func (r LogicalDNSRule) IsValid() bool {
|
||||||
|
|
|
@ -51,6 +51,40 @@ func (a *ListenAddress) Build() netip.Addr {
|
||||||
return (netip.Addr)(*a)
|
return (netip.Addr)(*a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AddrPrefix netip.Prefix
|
||||||
|
|
||||||
|
func (a AddrPrefix) MarshalJSON() ([]byte, error) {
|
||||||
|
prefix := netip.Prefix(a)
|
||||||
|
if prefix.Bits() == prefix.Addr().BitLen() {
|
||||||
|
return json.Marshal(prefix.Addr().String())
|
||||||
|
} else {
|
||||||
|
return json.Marshal(prefix.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AddrPrefix) UnmarshalJSON(content []byte) error {
|
||||||
|
var value string
|
||||||
|
err := json.Unmarshal(content, &value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
prefix, prefixErr := netip.ParsePrefix(value)
|
||||||
|
if prefixErr == nil {
|
||||||
|
*a = AddrPrefix(prefix)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
addr, addrErr := netip.ParseAddr(value)
|
||||||
|
if addrErr == nil {
|
||||||
|
*a = AddrPrefix(netip.PrefixFrom(addr, addr.BitLen()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return prefixErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a AddrPrefix) Build() netip.Prefix {
|
||||||
|
return netip.Prefix(a)
|
||||||
|
}
|
||||||
|
|
||||||
type NetworkList string
|
type NetworkList string
|
||||||
|
|
||||||
func (v *NetworkList) UnmarshalJSON(content []byte) error {
|
func (v *NetworkList) UnmarshalJSON(content []byte) error {
|
||||||
|
|
|
@ -27,7 +27,7 @@ import (
|
||||||
"github.com/sagernet/sing-box/outbound"
|
"github.com/sagernet/sing-box/outbound"
|
||||||
"github.com/sagernet/sing-box/transport/fakeip"
|
"github.com/sagernet/sing-box/transport/fakeip"
|
||||||
"github.com/sagernet/sing-dns"
|
"github.com/sagernet/sing-dns"
|
||||||
mux "github.com/sagernet/sing-mux"
|
"github.com/sagernet/sing-mux"
|
||||||
"github.com/sagernet/sing-tun"
|
"github.com/sagernet/sing-tun"
|
||||||
"github.com/sagernet/sing-vmess"
|
"github.com/sagernet/sing-vmess"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
|
@ -235,7 +235,7 @@ func NewRouter(
|
||||||
return nil, E.New("parse dns server[", tag, "]: missing address_resolver")
|
return nil, E.New("parse dns server[", tag, "]: missing address_resolver")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var clientSubnet netip.Addr
|
var clientSubnet netip.Prefix
|
||||||
if server.ClientSubnet != nil {
|
if server.ClientSubnet != nil {
|
||||||
clientSubnet = server.ClientSubnet.Build()
|
clientSubnet = server.ClientSubnet.Build()
|
||||||
} else if dnsOptions.ClientSubnet != nil {
|
} else if dnsOptions.ClientSubnet != nil {
|
||||||
|
|
|
@ -40,7 +40,7 @@ type DefaultDNSRule struct {
|
||||||
abstractDefaultRule
|
abstractDefaultRule
|
||||||
disableCache bool
|
disableCache bool
|
||||||
rewriteTTL *uint32
|
rewriteTTL *uint32
|
||||||
clientSubnet *netip.Addr
|
clientSubnet *netip.Prefix
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options option.DefaultDNSRule) (*DefaultDNSRule, error) {
|
func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options option.DefaultDNSRule) (*DefaultDNSRule, error) {
|
||||||
|
@ -51,7 +51,7 @@ func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options
|
||||||
},
|
},
|
||||||
disableCache: options.DisableCache,
|
disableCache: options.DisableCache,
|
||||||
rewriteTTL: options.RewriteTTL,
|
rewriteTTL: options.RewriteTTL,
|
||||||
clientSubnet: (*netip.Addr)(options.ClientSubnet),
|
clientSubnet: (*netip.Prefix)(options.ClientSubnet),
|
||||||
}
|
}
|
||||||
if len(options.Inbound) > 0 {
|
if len(options.Inbound) > 0 {
|
||||||
item := NewInboundRule(options.Inbound)
|
item := NewInboundRule(options.Inbound)
|
||||||
|
@ -234,7 +234,7 @@ func (r *DefaultDNSRule) RewriteTTL() *uint32 {
|
||||||
return r.rewriteTTL
|
return r.rewriteTTL
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DefaultDNSRule) ClientSubnet() *netip.Addr {
|
func (r *DefaultDNSRule) ClientSubnet() *netip.Prefix {
|
||||||
return r.clientSubnet
|
return r.clientSubnet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +272,7 @@ type LogicalDNSRule struct {
|
||||||
abstractLogicalRule
|
abstractLogicalRule
|
||||||
disableCache bool
|
disableCache bool
|
||||||
rewriteTTL *uint32
|
rewriteTTL *uint32
|
||||||
clientSubnet *netip.Addr
|
clientSubnet *netip.Prefix
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLogicalDNSRule(router adapter.Router, logger log.ContextLogger, options option.LogicalDNSRule) (*LogicalDNSRule, error) {
|
func NewLogicalDNSRule(router adapter.Router, logger log.ContextLogger, options option.LogicalDNSRule) (*LogicalDNSRule, error) {
|
||||||
|
@ -284,7 +284,7 @@ func NewLogicalDNSRule(router adapter.Router, logger log.ContextLogger, options
|
||||||
},
|
},
|
||||||
disableCache: options.DisableCache,
|
disableCache: options.DisableCache,
|
||||||
rewriteTTL: options.RewriteTTL,
|
rewriteTTL: options.RewriteTTL,
|
||||||
clientSubnet: (*netip.Addr)(options.ClientSubnet),
|
clientSubnet: (*netip.Prefix)(options.ClientSubnet),
|
||||||
}
|
}
|
||||||
switch options.Mode {
|
switch options.Mode {
|
||||||
case C.LogicalTypeAnd:
|
case C.LogicalTypeAnd:
|
||||||
|
@ -312,7 +312,7 @@ func (r *LogicalDNSRule) RewriteTTL() *uint32 {
|
||||||
return r.rewriteTTL
|
return r.rewriteTTL
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *LogicalDNSRule) ClientSubnet() *netip.Addr {
|
func (r *LogicalDNSRule) ClientSubnet() *netip.Prefix {
|
||||||
return r.clientSubnet
|
return r.clientSubnet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue