Merge branch 'bug/suggest' @release

This commit is contained in:
wweir
2019-02-13 21:08:00 +08:00
4 changed files with 70 additions and 57 deletions
+7 -1
View File
@@ -18,13 +18,19 @@ blocklist=[
"**.ggpht.com",
"**.googlevideo.com",
"**.facebook.com", # facebook
"**.xx.fbcdn.net",
"**.fbcdn.net",
"**.twitter.com", # twitter
"**.twimg.com",
"**.blogspot.com", # blogspot
"**.appspot.com",
"**.wikipedia.org", # wikipeida
"*.cloudfront.net",
"**.amazon.com",
"**.amazonaws.com",
"*.githubusercontent.com",
"**.mozilla.com",
"**.mozilla.net",
"**.akadns.net",
]
whitelist=[
"iamp.*.*.*",
+27 -30
View File
@@ -3,6 +3,7 @@ package dns
import (
"net"
"strings"
"sync/atomic"
"time"
"github.com/golang/glog"
@@ -16,7 +17,7 @@ const colon = byte(':')
func StartDNS(dnsServer, listenIP string) {
ip := net.ParseIP(listenIP)
suggest := &intelliSuggest{listenIP, 2 * time.Second, []string{"80", "443"}}
suggest := &intelliSuggest{listenIP, 2 * time.Second}
mem.DefaultCache = mem.New(time.Hour)
var dhcpCh chan struct{}
if dnsServer != "" {
@@ -93,11 +94,10 @@ func matchAndServe(w dns.ResponseWriter, r *dns.Msg, domain, listenIP, dnsServer
type intelliSuggest struct {
listenIP string
timeout time.Duration
ports []string
}
func (i *intelliSuggest) GetOne(domain interface{}) (iface interface{}, e error) {
iface = struct{}{}
iface, e = struct{}{}, nil
// kill deadloop, for ugly wildcard setting dns setting
addr := strings.TrimSuffix(domain.(string), ".")
@@ -105,36 +105,33 @@ func (i *intelliSuggest) GetOne(domain interface{}) (iface interface{}, e error)
return
}
for _, port := range i.ports {
// give local dial a hand, make it not so easy to be added into suggestions
<-util.HTTPPing(net.JoinHostPort(addr, port), addr, i.timeout/50)
localCh := util.HTTPPing(net.JoinHostPort(addr, port), addr, i.timeout)
remoteCh := util.HTTPPing(net.JoinHostPort(i.listenIP, port), addr, i.timeout)
// give local dial a hand, make it not so easy to be added into suggestions
util.HTTPPing(addr, addr, util.Http, i.timeout/50)
select {
case err := <-localCh:
if err == nil {
glog.V(2).Infoln("PING", addr, "local first, succ")
continue
}
if e := <-remoteCh; e != nil {
glog.V(2).Infoln("PING", addr, "local first, all fail:", err)
continue
}
glog.V(2).Infoln("PING", addr, "local first, remote succ")
conf.AddSuggest(addr)
case err := <-remoteCh:
pings := []struct {
viaAddr string
port util.Port
}{
{addr, util.Http},
{addr, util.Https},
{i.listenIP, util.Http},
{i.listenIP, util.Https},
}
var finish = new(uint32)
for idx := range pings {
go func(idx int) {
err := util.HTTPPing(pings[idx].viaAddr, addr, pings[idx].port, i.timeout)
if err != nil {
glog.V(2).Infoln("PING", addr, "remote first, fail:", err)
continue
if atomic.LoadUint32(finish) == 0 { // fails before first succ
glog.V(1).Infof("PING %s via %s fail: %s", addr, pings[idx].viaAddr, err)
}
} else if atomic.CompareAndSwapUint32(finish, 0, 1) { // first succ
if pings[idx].viaAddr == i.listenIP {
conf.AddSuggest(addr)
glog.Infof("added suggest domain: %s\t via: %s", addr, pings[idx].viaAddr)
}
}
glog.V(2).Infoln("PING", addr, "remote first, succ")
conf.AddSuggest(addr)
}
glog.Infof("added suggest domain: %s", addr)
return
}(idx)
}
return
}
+1 -1
View File
@@ -35,7 +35,7 @@ func init() {
func loadRules(name string, list []string) *util.Node {
rule := util.NewNodeFromRules(".", list...)
glog.V(2).Infof("load %s rule:\n%s", name, rule)
glog.V(3).Infof("load %s rule:\n%s", name, rule)
return rule
}
+35 -25
View File
@@ -10,36 +10,15 @@ import (
)
// HTTPPing try connect to a http(s) server with domain though the http addr
func HTTPPing(tcpAddr, domain string, timeout time.Duration) <-chan error {
errCh := make(chan error)
go func() {
errCh <- httpPing(tcpAddr, domain, timeout)
}()
return errCh
}
func httpPing(tcpAddr, domain string, timeout time.Duration) error {
conn, err := net.DialTimeout("tcp", tcpAddr, timeout)
func HTTPPing(viaHost, domain string, port Port, timeout time.Duration) (err error) {
conn, err := net.DialTimeout("tcp", port.JoinAddr(viaHost), timeout)
if err != nil {
return err
}
defer conn.Close()
host, port, err := net.SplitHostPort(tcpAddr)
if err != nil {
return err
}
var msg []byte
switch port {
case ":80":
msg = []byte("TRACE / HTTP/1.1\r\nHost: " + domain + "\r\n\r\n")
case ":443":
msg = NewClientHelloSNIMsg(domain)
}
conn.SetDeadline(time.Now().Add(timeout))
if _, err = conn.Write(msg); err != nil {
if _, err = conn.Write(port.pingMsg(domain)); err != nil {
return err
}
@@ -47,12 +26,43 @@ func httpPing(tcpAddr, domain string, timeout time.Duration) error {
// err -> io.EOF: no such domain or connection refused
// err -> timeout: tcp package has been dropped
_, err = conn.Read(make([]byte, 1))
if err == io.EOF && host == domain {
if err == io.EOF && viaHost == domain {
return nil
}
return err
}
// Port ==========================
type Port uint16
const (
Http Port = iota
Https
)
func (p Port) JoinAddr(addr string) string {
switch p {
case Http:
return addr + ":80"
case Https:
return addr + ":443"
default:
panic("invalid port")
}
}
func (p Port) pingMsg(domain string) []byte {
switch p {
case Http:
return []byte("TRACE / HTTP/1.1\r\nHost: " + domain + "\r\n\r\n")
case Https:
return NewClientHelloSNIMsg(domain)
default:
panic("invalid port")
}
}
// SNI ==========================
type clientHelloSNI struct {
ContentType uint8
Version uint16