mirror of
https://github.com/xjasonlyu/tun2socks.git
synced 2025-10-07 09:41:09 +08:00
123 lines
2.4 KiB
Go
123 lines
2.4 KiB
Go
package fakedns
|
|
|
|
import (
|
|
"net"
|
|
"strings"
|
|
|
|
trie "github.com/xjasonlyu/tun2socks/common/domain-trie"
|
|
"github.com/xjasonlyu/tun2socks/common/fakeip"
|
|
|
|
D "github.com/miekg/dns"
|
|
)
|
|
|
|
var (
|
|
BackendDNS []string
|
|
)
|
|
|
|
func dnsExchange(r *D.Msg) (msg *D.Msg) {
|
|
defer func() {
|
|
if msg == nil {
|
|
// empty DNS response
|
|
rr := &D.A{}
|
|
rr.Hdr = D.RR_Header{Name: r.Question[0].Name, Rrtype: D.TypeA, Class: D.ClassINET, Ttl: dnsDefaultTTL}
|
|
msg = r.Copy()
|
|
msg.Answer = []D.RR{rr}
|
|
setMsgTTL(msg, dnsDefaultTTL)
|
|
}
|
|
}()
|
|
|
|
c := new(D.Client)
|
|
c.Net = "tcp"
|
|
for _, dns := range BackendDNS {
|
|
msg, _, _ = c.Exchange(r, dns)
|
|
if msg != nil {
|
|
break
|
|
}
|
|
}
|
|
return msg
|
|
}
|
|
|
|
func resolve(hosts *trie.Trie, pool *fakeip.Pool, r *D.Msg) (msg *D.Msg) {
|
|
defer func() {
|
|
if msg != nil {
|
|
msg.SetReply(r)
|
|
}
|
|
}()
|
|
|
|
if msg = hostResolve(hosts, r); msg != nil {
|
|
return msg
|
|
}
|
|
|
|
q := r.Question[0]
|
|
if q.Qtype != D.TypeA || q.Qclass != D.ClassINET {
|
|
return dnsExchange(r)
|
|
}
|
|
|
|
return fakeResolve(pool, r)
|
|
}
|
|
|
|
func fakeResolve(pool *fakeip.Pool, r *D.Msg) *D.Msg {
|
|
q := r.Question[0]
|
|
host := strings.TrimRight(q.Name, ".")
|
|
|
|
rr := &D.A{}
|
|
rr.Hdr = D.RR_Header{Name: q.Name, Rrtype: D.TypeA, Class: D.ClassINET, Ttl: dnsFakeTTL}
|
|
ip := pool.Lookup(host)
|
|
rr.A = ip
|
|
|
|
msg := r.Copy()
|
|
msg.Answer = []D.RR{rr}
|
|
setMsgTTL(msg, dnsFakeTTL)
|
|
return msg
|
|
}
|
|
|
|
func hostResolve(hosts *trie.Trie, r *D.Msg) *D.Msg {
|
|
if hosts == nil {
|
|
return nil
|
|
}
|
|
|
|
q := r.Question[0]
|
|
if q.Qtype != D.TypeA && q.Qtype != D.TypeAAAA {
|
|
return nil
|
|
}
|
|
|
|
domain := strings.TrimRight(q.Name, ".")
|
|
host := hosts.Search(domain)
|
|
if host == nil {
|
|
return nil
|
|
}
|
|
|
|
ip := host.Data.(net.IP)
|
|
if q.Qtype == D.TypeAAAA && ip.To16() == nil {
|
|
return nil
|
|
} else if q.Qtype == D.TypeA && ip.To4() == nil {
|
|
return nil
|
|
}
|
|
|
|
var rr D.RR
|
|
if q.Qtype == D.TypeAAAA {
|
|
record := &D.AAAA{}
|
|
record.Hdr = D.RR_Header{Name: q.Name, Rrtype: D.TypeAAAA, Class: D.ClassINET, Ttl: dnsDefaultTTL}
|
|
record.AAAA = ip
|
|
rr = record
|
|
} else {
|
|
record := &D.A{}
|
|
record.Hdr = D.RR_Header{Name: q.Name, Rrtype: D.TypeA, Class: D.ClassINET, Ttl: dnsDefaultTTL}
|
|
record.A = ip
|
|
rr = record
|
|
}
|
|
|
|
msg := r.Copy()
|
|
msg.Answer = []D.RR{rr}
|
|
setMsgTTL(msg, dnsDefaultTTL)
|
|
return msg
|
|
}
|
|
|
|
func newHandler(hosts *trie.Trie, pool *fakeip.Pool) D.HandlerFunc {
|
|
return func(w D.ResponseWriter, r *D.Msg) {
|
|
msg := resolve(hosts, pool, r)
|
|
w.WriteMsg(msg)
|
|
return
|
|
}
|
|
}
|