mirror of
				https://github.com/nadoo/glider.git
				synced 2025-11-04 07:42:38 +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