Feature: dns server could lookup hosts (#872)
This commit is contained in:
@ -1,9 +1,11 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/Dreamacro/clash/component/fakeip"
|
||||
"github.com/Dreamacro/clash/component/trie"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
|
||||
D "github.com/miekg/dns"
|
||||
@ -12,6 +14,52 @@ import (
|
||||
type handler func(w D.ResponseWriter, r *D.Msg)
|
||||
type middleware func(next handler) handler
|
||||
|
||||
func withHosts(hosts *trie.DomainTrie) middleware {
|
||||
return func(next handler) handler {
|
||||
return func(w D.ResponseWriter, r *D.Msg) {
|
||||
q := r.Question[0]
|
||||
|
||||
if !isIPRequest(q) {
|
||||
next(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
record := hosts.Search(strings.TrimRight(q.Name, "."))
|
||||
if record == nil {
|
||||
next(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
ip := record.Data.(net.IP)
|
||||
msg := r.Copy()
|
||||
|
||||
if v4 := ip.To4(); v4 != nil && q.Qtype == D.TypeA {
|
||||
rr := &D.A{}
|
||||
rr.Hdr = D.RR_Header{Name: q.Name, Rrtype: D.TypeA, Class: D.ClassINET, Ttl: dnsDefaultTTL}
|
||||
rr.A = v4
|
||||
|
||||
msg.Answer = []D.RR{rr}
|
||||
} else if v6 := ip.To16(); v6 != nil && q.Qtype == D.TypeAAAA {
|
||||
rr := &D.AAAA{}
|
||||
rr.Hdr = D.RR_Header{Name: q.Name, Rrtype: D.TypeAAAA, Class: D.ClassINET, Ttl: dnsDefaultTTL}
|
||||
rr.AAAA = v6
|
||||
|
||||
msg.Answer = []D.RR{rr}
|
||||
} else {
|
||||
next(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
msg.SetRcode(r, D.RcodeSuccess)
|
||||
msg.Authoritative = true
|
||||
msg.RecursionAvailable = true
|
||||
|
||||
w.WriteMsg(msg)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func withFakeIP(fakePool *fakeip.Pool) middleware {
|
||||
return func(next handler) handler {
|
||||
return func(w D.ResponseWriter, r *D.Msg) {
|
||||
@ -100,6 +148,10 @@ func compose(middlewares []middleware, endpoint handler) handler {
|
||||
func newHandler(resolver *Resolver) handler {
|
||||
middlewares := []middleware{}
|
||||
|
||||
if resolver.hosts != nil {
|
||||
middlewares = append(middlewares, withHosts(resolver.hosts))
|
||||
}
|
||||
|
||||
if resolver.FakeIPEnabled() {
|
||||
middlewares = append(middlewares, withFakeIP(resolver.pool))
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/Dreamacro/clash/common/picker"
|
||||
"github.com/Dreamacro/clash/component/fakeip"
|
||||
"github.com/Dreamacro/clash/component/resolver"
|
||||
"github.com/Dreamacro/clash/component/trie"
|
||||
|
||||
D "github.com/miekg/dns"
|
||||
"golang.org/x/sync/singleflight"
|
||||
@ -37,6 +38,7 @@ type Resolver struct {
|
||||
ipv6 bool
|
||||
mapping bool
|
||||
fakeip bool
|
||||
hosts *trie.DomainTrie
|
||||
pool *fakeip.Pool
|
||||
main []dnsClient
|
||||
fallback []dnsClient
|
||||
@ -308,6 +310,7 @@ type Config struct {
|
||||
EnhancedMode EnhancedMode
|
||||
FallbackFilter FallbackFilter
|
||||
Pool *fakeip.Pool
|
||||
Hosts *trie.DomainTrie
|
||||
}
|
||||
|
||||
func New(config Config) *Resolver {
|
||||
@ -323,6 +326,7 @@ func New(config Config) *Resolver {
|
||||
mapping: config.EnhancedMode == MAPPING,
|
||||
fakeip: config.EnhancedMode == FAKEIP,
|
||||
pool: config.Pool,
|
||||
hosts: config.Hosts,
|
||||
}
|
||||
|
||||
if len(config.Fallback) != 0 {
|
||||
|
Reference in New Issue
Block a user