mirror of
https://github.com/wweir/sower.git
synced 2024-04-21 12:42:15 +00:00
Merge branch 'bug/suggest' @release
This commit is contained in:
+7
-1
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user