mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2024-11-12 20:31:17 +08:00
52 lines
1.1 KiB
Go
52 lines
1.1 KiB
Go
package dns
|
|
|
|
import (
|
|
"net/netip"
|
|
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
func setEdns0Subnet(message *dns.Msg, clientSubnet netip.Prefix, override bool) bool {
|
|
var (
|
|
optRecord *dns.OPT
|
|
subnetOption *dns.EDNS0_SUBNET
|
|
)
|
|
findExists:
|
|
for _, record := range message.Extra {
|
|
var isOPTRecord bool
|
|
if optRecord, isOPTRecord = record.(*dns.OPT); isOPTRecord {
|
|
for _, option := range optRecord.Option {
|
|
var isEDNS0Subnet bool
|
|
if subnetOption, isEDNS0Subnet = option.(*dns.EDNS0_SUBNET); isEDNS0Subnet {
|
|
if !override {
|
|
return false
|
|
}
|
|
break findExists
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if optRecord == nil {
|
|
optRecord = &dns.OPT{
|
|
Hdr: dns.RR_Header{
|
|
Name: ".",
|
|
Rrtype: dns.TypeOPT,
|
|
},
|
|
}
|
|
message.Extra = append(message.Extra, optRecord)
|
|
}
|
|
if subnetOption == nil {
|
|
subnetOption = new(dns.EDNS0_SUBNET)
|
|
optRecord.Option = append(optRecord.Option, subnetOption)
|
|
}
|
|
subnetOption.Code = dns.EDNS0SUBNET
|
|
if clientSubnet.Addr().Is4() {
|
|
subnetOption.Family = 1
|
|
} else {
|
|
subnetOption.Family = 2
|
|
}
|
|
subnetOption.SourceNetmask = uint8(clientSubnet.Bits())
|
|
subnetOption.Address = clientSubnet.Addr().AsSlice()
|
|
return true
|
|
}
|