2018-12-05 13:13:29 +00:00
|
|
|
package dns
|
|
|
|
|
|
|
|
import (
|
2019-06-28 04:29:08 +00:00
|
|
|
"crypto/tls"
|
2020-02-17 14:13:15 +00:00
|
|
|
"net"
|
2018-12-05 13:13:29 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/Dreamacro/clash/common/cache"
|
|
|
|
"github.com/Dreamacro/clash/log"
|
|
|
|
|
|
|
|
D "github.com/miekg/dns"
|
|
|
|
)
|
|
|
|
|
2020-05-07 07:10:14 +00:00
|
|
|
func putMsgToCache(c *cache.LruCache, key string, msg *D.Msg) {
|
|
|
|
var ttl uint32
|
2019-10-14 09:13:23 +00:00
|
|
|
switch {
|
|
|
|
case len(msg.Answer) != 0:
|
2020-05-07 07:10:14 +00:00
|
|
|
ttl = msg.Answer[0].Header().Ttl
|
2019-10-14 09:13:23 +00:00
|
|
|
case len(msg.Ns) != 0:
|
2020-05-07 07:10:14 +00:00
|
|
|
ttl = msg.Ns[0].Header().Ttl
|
2019-10-14 09:13:23 +00:00
|
|
|
case len(msg.Extra) != 0:
|
2020-05-07 07:10:14 +00:00
|
|
|
ttl = msg.Extra[0].Header().Ttl
|
2019-10-14 09:13:23 +00:00
|
|
|
default:
|
2020-06-12 15:39:03 +00:00
|
|
|
log.Debugln("[DNS] response msg empty: %#v", msg)
|
2018-12-05 13:13:29 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-05-07 07:10:14 +00:00
|
|
|
c.SetWithExpire(key, msg.Copy(), time.Now().Add(time.Second*time.Duration(ttl)))
|
2019-02-23 12:31:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func setMsgTTL(msg *D.Msg, ttl uint32) {
|
|
|
|
for _, answer := range msg.Answer {
|
|
|
|
answer.Header().Ttl = ttl
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, ns := range msg.Ns {
|
|
|
|
ns.Header().Ttl = ttl
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, extra := range msg.Extra {
|
|
|
|
extra.Header().Ttl = ttl
|
|
|
|
}
|
2018-12-05 13:13:29 +00:00
|
|
|
}
|
2019-06-28 04:29:08 +00:00
|
|
|
|
|
|
|
func isIPRequest(q D.Question) bool {
|
2020-06-12 15:39:03 +00:00
|
|
|
return q.Qclass == D.ClassINET && (q.Qtype == D.TypeA || q.Qtype == D.TypeAAAA)
|
2019-06-28 04:29:08 +00:00
|
|
|
}
|
|
|
|
|
2020-02-15 13:42:46 +00:00
|
|
|
func transform(servers []NameServer, resolver *Resolver) []dnsClient {
|
|
|
|
ret := []dnsClient{}
|
2019-06-28 04:29:08 +00:00
|
|
|
for _, s := range servers {
|
2021-09-06 15:07:34 +00:00
|
|
|
switch s.Net {
|
|
|
|
case "https":
|
2020-02-15 13:42:46 +00:00
|
|
|
ret = append(ret, newDoHClient(s.Addr, resolver))
|
2019-06-28 04:29:08 +00:00
|
|
|
continue
|
2021-09-06 15:07:34 +00:00
|
|
|
case "dhcp":
|
|
|
|
ret = append(ret, newDHCPClient(s.Addr))
|
|
|
|
continue
|
2019-06-28 04:29:08 +00:00
|
|
|
}
|
|
|
|
|
2020-02-17 14:13:15 +00:00
|
|
|
host, port, _ := net.SplitHostPort(s.Addr)
|
2019-06-28 04:29:08 +00:00
|
|
|
ret = append(ret, &client{
|
|
|
|
Client: &D.Client{
|
|
|
|
Net: s.Net,
|
|
|
|
TLSConfig: &tls.Config{
|
|
|
|
// alpn identifier, see https://tools.ietf.org/html/draft-hoffman-dprive-dns-tls-alpn-00#page-6
|
|
|
|
NextProtos: []string{"dns"},
|
2020-04-17 03:29:59 +00:00
|
|
|
ServerName: host,
|
2019-06-28 04:29:08 +00:00
|
|
|
},
|
|
|
|
UDPSize: 4096,
|
2020-01-10 06:13:44 +00:00
|
|
|
Timeout: 5 * time.Second,
|
2019-06-28 04:29:08 +00:00
|
|
|
},
|
2021-10-05 05:31:19 +00:00
|
|
|
port: port,
|
|
|
|
host: host,
|
|
|
|
iface: s.Interface,
|
|
|
|
r: resolver,
|
2019-06-28 04:29:08 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
2020-10-12 16:15:49 +00:00
|
|
|
|
|
|
|
func handleMsgWithEmptyAnswer(r *D.Msg) *D.Msg {
|
|
|
|
msg := &D.Msg{}
|
|
|
|
msg.Answer = []D.RR{}
|
|
|
|
|
|
|
|
msg.SetRcode(r, D.RcodeSuccess)
|
|
|
|
msg.Authoritative = true
|
|
|
|
msg.RecursionAvailable = true
|
|
|
|
|
|
|
|
return msg
|
|
|
|
}
|
2021-01-23 06:49:46 +00:00
|
|
|
|
|
|
|
func msgToIP(msg *D.Msg) []net.IP {
|
|
|
|
ips := []net.IP{}
|
|
|
|
|
|
|
|
for _, answer := range msg.Answer {
|
|
|
|
switch ans := answer.(type) {
|
|
|
|
case *D.AAAA:
|
|
|
|
ips = append(ips, ans.AAAA)
|
|
|
|
case *D.A:
|
|
|
|
ips = append(ips, ans.A)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ips
|
|
|
|
}
|