mihomo/dns/util.go

171 lines
3.4 KiB
Go
Raw Normal View History

2018-12-05 21:13:29 +08:00
package dns
import (
2019-06-28 12:29:08 +08:00
"crypto/tls"
2018-12-05 21:13:29 +08:00
"encoding/json"
"errors"
2020-02-17 22:13:15 +08:00
"net"
2018-12-05 21:13:29 +08:00
"time"
"github.com/Dreamacro/clash/common/cache"
"github.com/Dreamacro/clash/log"
D "github.com/miekg/dns"
)
var (
// EnhancedModeMapping is a mapping for EnhancedMode enum
EnhancedModeMapping = map[string]EnhancedMode{
2018-12-05 21:52:31 +08:00
NORMAL.String(): NORMAL,
2018-12-05 21:13:29 +08:00
FAKEIP.String(): FAKEIP,
MAPPING.String(): MAPPING,
}
)
const (
2018-12-05 21:52:31 +08:00
NORMAL EnhancedMode = iota
FAKEIP
2018-12-05 21:13:29 +08:00
MAPPING
)
type EnhancedMode int
// UnmarshalYAML unserialize EnhancedMode with yaml
func (e *EnhancedMode) UnmarshalYAML(unmarshal func(interface{}) error) error {
var tp string
if err := unmarshal(&tp); err != nil {
return err
}
mode, exist := EnhancedModeMapping[tp]
if !exist {
return errors.New("invalid mode")
}
*e = mode
return nil
}
// MarshalYAML serialize EnhancedMode with yaml
func (e EnhancedMode) MarshalYAML() (interface{}, error) {
return e.String(), nil
2018-12-05 21:13:29 +08:00
}
// UnmarshalJSON unserialize EnhancedMode with json
func (e *EnhancedMode) UnmarshalJSON(data []byte) error {
var tp string
json.Unmarshal(data, &tp)
mode, exist := EnhancedModeMapping[tp]
if !exist {
return errors.New("invalid mode")
}
*e = mode
return nil
}
// MarshalJSON serialize EnhancedMode with json
func (e EnhancedMode) MarshalJSON() ([]byte, error) {
return json.Marshal(e.String())
}
func (e EnhancedMode) String() string {
switch e {
2018-12-05 21:52:31 +08:00
case NORMAL:
return "normal"
2018-12-05 21:13:29 +08:00
case FAKEIP:
2019-05-03 00:05:14 +08:00
return "fake-ip"
2018-12-05 21:13:29 +08:00
case MAPPING:
return "redir-host"
default:
return "unknown"
}
}
func putMsgToCache(c *cache.LruCache, key string, msg *D.Msg) {
var ttl uint32
2019-10-14 17:13:23 +08:00
switch {
case len(msg.Answer) != 0:
ttl = msg.Answer[0].Header().Ttl
2019-10-14 17:13:23 +08:00
case len(msg.Ns) != 0:
ttl = msg.Ns[0].Header().Ttl
2019-10-14 17:13:23 +08:00
case len(msg.Extra) != 0:
ttl = msg.Extra[0].Header().Ttl
2019-10-14 17:13:23 +08:00
default:
log.Debugln("[DNS] response msg empty: %#v", msg)
2018-12-05 21:13:29 +08:00
return
}
c.SetWithExpire(key, msg.Copy(), time.Now().Add(time.Second*time.Duration(ttl)))
2019-02-23 20:31:59 +08: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 21:13:29 +08:00
}
2019-06-28 12:29:08 +08:00
func isIPRequest(q D.Question) bool {
return q.Qclass == D.ClassINET && (q.Qtype == D.TypeA || q.Qtype == D.TypeAAAA)
2019-06-28 12:29:08 +08:00
}
func transform(servers []NameServer, resolver *Resolver) []dnsClient {
ret := []dnsClient{}
2019-06-28 12:29:08 +08:00
for _, s := range servers {
if s.Net == "https" {
ret = append(ret, newDoHClient(s.Addr, resolver))
2019-06-28 12:29:08 +08:00
continue
}
2020-02-17 22:13:15 +08:00
host, port, _ := net.SplitHostPort(s.Addr)
2019-06-28 12:29:08 +08:00
ret = append(ret, &client{
Client: &D.Client{
Net: s.Net,
TLSConfig: &tls.Config{
ClientSessionCache: globalSessionCache,
// alpn identifier, see https://tools.ietf.org/html/draft-hoffman-dprive-dns-tls-alpn-00#page-6
NextProtos: []string{"dns"},
ServerName: host,
2019-06-28 12:29:08 +08:00
},
UDPSize: 4096,
Timeout: 5 * time.Second,
2019-06-28 12:29:08 +08:00
},
2020-02-17 22:13:15 +08:00
port: port,
host: host,
r: resolver,
2019-06-28 12:29:08 +08:00
})
}
return ret
}
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
}
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
}