mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 17:35:40 +08:00
dns: add experimental codes to specify different remote dns server in rule file
This commit is contained in:
parent
5c0c2e926d
commit
5fef071349
47
dns.go
47
dns.go
@ -6,6 +6,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UDPDNSHeaderLen is the length of UDP dns msg header
|
// UDPDNSHeaderLen is the length of UDP dns msg header
|
||||||
@ -23,23 +24,26 @@ const TCPDNSHEADERLen = 2 + UDPDNSHeaderLen
|
|||||||
// so we should also serve tcp requests.
|
// so we should also serve tcp requests.
|
||||||
const MaxUDPDNSLen = 512
|
const MaxUDPDNSLen = 512
|
||||||
|
|
||||||
type dns struct {
|
type DNS struct {
|
||||||
*proxy
|
*proxy
|
||||||
raddr string
|
dnsServer string
|
||||||
|
|
||||||
|
dnsServerMap map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNSForwarder returns a dns forwarder. client -> dns.udp -> glider -> forwarder -> remote dns addr
|
// DNSForwarder returns a dns forwarder. client -> dns.udp -> glider -> forwarder -> remote dns addr
|
||||||
func DNSForwarder(addr, raddr string, upProxy Proxy) (Proxy, error) {
|
func DNSForwarder(addr, raddr string, upProxy Proxy) (*DNS, error) {
|
||||||
s := &dns{
|
s := &DNS{
|
||||||
proxy: newProxy(addr, upProxy),
|
proxy: newProxy(addr, upProxy),
|
||||||
raddr: raddr,
|
dnsServer: raddr,
|
||||||
|
dnsServerMap: make(map[string]string),
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe .
|
// ListenAndServe .
|
||||||
func (s *dns) ListenAndServe() {
|
func (s *DNS) ListenAndServe() {
|
||||||
l, err := net.ListenPacket("udp", s.addr)
|
l, err := net.ListenPacket("udp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logf("failed to listen on %s: %v", s.addr, err)
|
logf("failed to listen on %s: %v", s.addr, err)
|
||||||
@ -62,16 +66,18 @@ func (s *dns) ListenAndServe() {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
// TODO: check domain rules and get a proper upstream name server.
|
// TODO: check domain rules and get a proper upstream name server.
|
||||||
domain := getDomain(data)
|
domain := string(getDomain(data))
|
||||||
|
|
||||||
rc, err := s.GetProxy(s.raddr).Dial("tcp", s.raddr)
|
dnsServer := s.GetServer(domain)
|
||||||
|
// TODO: check here
|
||||||
|
rc, err := s.GetProxy(domain+":53").GetProxy(domain+":53").Dial("tcp", dnsServer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logf("failed to connect to server %v: %v", s.raddr, err)
|
logf("failed to connect to server %v: %v", dnsServer, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer rc.Close()
|
defer rc.Close()
|
||||||
|
|
||||||
logf("proxy-dns %s, %s <-> %s", domain, clientAddr.String(), s.raddr)
|
logf("proxy-dns %s, %s <-> %s", domain, clientAddr.String(), dnsServer)
|
||||||
|
|
||||||
// 2 bytes length after tcp header, before dns message
|
// 2 bytes length after tcp header, before dns message
|
||||||
length := make([]byte, 2)
|
length := make([]byte, 2)
|
||||||
@ -99,6 +105,27 @@ func (s *dns) ListenAndServe() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetServer .
|
||||||
|
func (s *DNS) SetServer(domain, server string) {
|
||||||
|
s.dnsServerMap[domain] = server
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetServer .
|
||||||
|
func (s *DNS) GetServer(domain string) string {
|
||||||
|
|
||||||
|
domainParts := strings.Split(domain, ".")
|
||||||
|
length := len(domainParts)
|
||||||
|
for i := length - 2; i >= 0; i-- {
|
||||||
|
domain := strings.Join(domainParts[i:length], ".")
|
||||||
|
|
||||||
|
if server, ok := s.dnsServerMap[domain]; ok {
|
||||||
|
return server
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.dnsServer
|
||||||
|
}
|
||||||
|
|
||||||
// getDomain from dns request playload, return []byte like:
|
// getDomain from dns request playload, return []byte like:
|
||||||
// []byte{'w', 'w', 'w', '.', 'm', 's', 'n', '.', 'c', 'o', 'm', '.'}
|
// []byte{'w', 'w', 'w', '.', 'm', 's', 'n', '.', 'c', 'o', 'm', '.'}
|
||||||
// []byte("www.msn.com.")
|
// []byte("www.msn.com.")
|
||||||
|
30
main.go
30
main.go
@ -22,6 +22,11 @@ var conf struct {
|
|||||||
Listen []string
|
Listen []string
|
||||||
Forward []string
|
Forward []string
|
||||||
RuleFile []string
|
RuleFile []string
|
||||||
|
|
||||||
|
DNS string
|
||||||
|
DNSServer []string
|
||||||
|
|
||||||
|
IPSet string
|
||||||
}
|
}
|
||||||
|
|
||||||
var flag = conflag.New()
|
var flag = conflag.New()
|
||||||
@ -118,6 +123,11 @@ func main() {
|
|||||||
flag.StringSliceUniqVar(&conf.Forward, "forward", nil, "forward url, format: SCHEMA://[USER|METHOD:PASSWORD@][HOST]:PORT[,SCHEMA://[USER|METHOD:PASSWORD@][HOST]:PORT]")
|
flag.StringSliceUniqVar(&conf.Forward, "forward", nil, "forward url, format: SCHEMA://[USER|METHOD:PASSWORD@][HOST]:PORT[,SCHEMA://[USER|METHOD:PASSWORD@][HOST]:PORT]")
|
||||||
flag.StringSliceUniqVar(&conf.RuleFile, "rulefile", nil, "rule file path")
|
flag.StringSliceUniqVar(&conf.RuleFile, "rulefile", nil, "rule file path")
|
||||||
|
|
||||||
|
flag.StringVar(&conf.DNS, "dns", "", "dns listen address")
|
||||||
|
flag.StringSliceUniqVar(&conf.DNSServer, "dnsserver", []string{"8.8.8.8:53"}, "remote dns server")
|
||||||
|
|
||||||
|
flag.StringVar(&conf.IPSet, "ipset", "glider", "ipset name")
|
||||||
|
|
||||||
flag.Usage = usage
|
flag.Usage = usage
|
||||||
err := flag.Parse()
|
err := flag.Parse()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -125,7 +135,7 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(conf.Listen) == 0 {
|
if len(conf.Listen) == 0 && conf.DNS == "" {
|
||||||
flag.Usage()
|
flag.Usage()
|
||||||
fmt.Fprintf(os.Stderr, "ERROR: listen url must be specified.\n")
|
fmt.Fprintf(os.Stderr, "ERROR: listen url must be specified.\n")
|
||||||
return
|
return
|
||||||
@ -177,6 +187,24 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if conf.DNS != "" {
|
||||||
|
dns, err := DNSForwarder(conf.DNS, conf.DNSServer[0], forwarder)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// rule
|
||||||
|
for _, frwder := range ruleForwarders {
|
||||||
|
for _, domain := range frwder.Domain {
|
||||||
|
if len(frwder.DNSServer) > 0 {
|
||||||
|
dns.SetServer(domain, frwder.DNSServer[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
go dns.ListenAndServe()
|
||||||
|
}
|
||||||
|
|
||||||
sigCh := make(chan os.Signal, 1)
|
sigCh := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
||||||
<-sigCh
|
<-sigCh
|
||||||
|
6
rule.go
6
rule.go
@ -16,6 +16,9 @@ type ruleForwarder struct {
|
|||||||
CheckWebSite string
|
CheckWebSite string
|
||||||
CheckDuration int
|
CheckDuration int
|
||||||
|
|
||||||
|
DNSServer []string
|
||||||
|
IPSet string
|
||||||
|
|
||||||
Domain []string
|
Domain []string
|
||||||
IP []string
|
IP []string
|
||||||
CIDR []string
|
CIDR []string
|
||||||
@ -34,6 +37,9 @@ func newRuleProxyFromFile(ruleFile string) (*ruleForwarder, error) {
|
|||||||
f.StringVar(&p.CheckWebSite, "checkwebsite", "www.apple.com", "proxy check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80")
|
f.StringVar(&p.CheckWebSite, "checkwebsite", "www.apple.com", "proxy check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80")
|
||||||
f.IntVar(&p.CheckDuration, "checkduration", 30, "proxy check duration(seconds)")
|
f.IntVar(&p.CheckDuration, "checkduration", 30, "proxy check duration(seconds)")
|
||||||
|
|
||||||
|
f.StringSliceUniqVar(&p.DNSServer, "dnsserver", nil, "remote dns server")
|
||||||
|
f.StringVar(&p.IPSet, "ipset", "", "ipset name")
|
||||||
|
|
||||||
f.StringSliceUniqVar(&p.Domain, "domain", nil, "domain")
|
f.StringSliceUniqVar(&p.Domain, "domain", nil, "domain")
|
||||||
f.StringSliceUniqVar(&p.IP, "ip", nil, "ip")
|
f.StringSliceUniqVar(&p.IP, "ip", nil, "ip")
|
||||||
f.StringSliceUniqVar(&p.CIDR, "cidr", nil, "cidr")
|
f.StringSliceUniqVar(&p.CIDR, "cidr", nil, "cidr")
|
||||||
|
2
rules.go
2
rules.go
@ -42,7 +42,7 @@ func newRulesForwarder(ruleForwarders []*ruleForwarder, globalForwarder Proxy) P
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *rulesForwarder) Addr() string { return "rule forwarder" }
|
func (p *rulesForwarder) Addr() string { return "rules forwarder" }
|
||||||
func (p *rulesForwarder) ListenAndServe() {}
|
func (p *rulesForwarder) ListenAndServe() {}
|
||||||
func (p *rulesForwarder) Serve(c net.Conn) {}
|
func (p *rulesForwarder) Serve(c net.Conn) {}
|
||||||
func (p *rulesForwarder) CurrentProxy() Proxy { return p.globalForwarder.CurrentProxy() }
|
func (p *rulesForwarder) CurrentProxy() Proxy { return p.globalForwarder.CurrentProxy() }
|
||||||
|
Loading…
Reference in New Issue
Block a user