Skip to content

Commit

Permalink
Change intelligent detect logic @Release
Browse files Browse the repository at this point in the history
  • Loading branch information
wweir committed Jan 23, 2019
1 parent 41a1adc commit 04193eb
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 52 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ kill:
sudo pkill -9 sower || true

client: build kill
sudo $(PWD)/sower -f conf/sower.toml
sudo $(PWD)/sower -f /usr/local/etc/sower.toml

server: build kill
$(PWD)/sower -n TCP -v 1

run: build kill
$(PWD)/sower -n TCP -v 1 &
sudo $(PWD)/sower -f conf/sower.toml &
sudo $(PWD)/sower -f /usr/local/etc/sower.toml &
@sleep 1
curl 127.0.0.1
@sleep 1
Expand Down
2 changes: 1 addition & 1 deletion conf/sower.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ server_port="5533"
# server_addr="remote-server:5533" # replce it to remote server
http_proxy=":8080" # eg: 192.168.0.2:8080
dns_server="223.5.5.5" # Alibaba public dns
client_ip="127.0.0.1"
client_ip="127.0.0.1" # listen the IP, dns target is the IP
# clear_dns_cache="killall -HUP mDNSResponder"
blocklist=[
"*.google.com", # google
Expand Down
81 changes: 32 additions & 49 deletions dns/dns.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package dns

import (
"errors"
"net"
"strings"
"time"
Expand All @@ -10,6 +9,7 @@ import (
"github.com/miekg/dns"
mem "github.com/wweir/mem-go"
"github.com/wweir/sower/conf"
"github.com/wweir/sower/util"
)

const colon = byte(':')
Expand Down Expand Up @@ -42,7 +42,9 @@ func StartDNS(dnsServer, listenIP string) {
glog.Fatalln(server.ListenAndServe())
}

func matchAndServe(w dns.ResponseWriter, r *dns.Msg, domain, listenIP, dnsServer string, ipNet net.IP, suggest *intelliSuggest) {
func matchAndServe(w dns.ResponseWriter, r *dns.Msg, domain, listenIP,
dnsServer string, ipNet net.IP, suggest *intelliSuggest) {

inWriteList := whiteList.Match(domain)

if !inWriteList && (blockList.Match(domain) || suggestList.Match(domain)) {
Expand All @@ -69,64 +71,45 @@ type intelliSuggest struct {
ports []string
}

func (i *intelliSuggest) GetOne(domain interface{}) (ret interface{}, err error) {
ret = false
func (i *intelliSuggest) GetOne(domain interface{}) (iface interface{}, e error) {
iface = struct{}{}

// kill deadloop, for ugly wildcard setting dns setting
addr := strings.TrimSuffix(domain.(string), ".")
if len(strings.Split(addr, ".")) > 10 {
return
}

var conn net.Conn
for idx, port := range i.ports {
// First: test direct connect
conn, err = net.DialTimeout("tcp", addr+port, i.timeout)
if err == nil {
conn.Close()
return
}
glog.V(2).Infoln("first dial fail:", addr)

// Second: test remote connect
conn, err = net.DialTimeout("tcp", i.listenIP+port, i.timeout/100)
if err != nil {
glog.V(1).Infoln("dial self service fail:", err)
return
}
defer conn.Close()

conn.SetReadDeadline(time.Now().Add(2 * time.Second))
if _, err = conn.Write([]byte("TRACE / HTTP/1.1\r\nHost: " + addr + "\r\n\r\n")); err != nil {
glog.V(1).Infoln("dial self service fail:", err)
return
}

// err -> nil: read something succ
// err -> io.EOF: no such domain or connection refused
// err -> timeout: tcp package has been dropped
if _, err = conn.Read(make([]byte, 1)); err != nil {
if idx+1 == len(i.ports) {
return ret, errors.New("remote connect fail")
for _, port := range i.ports {
// give local dial a hand, make it not so easy to be added into suggestions
util.HTTPPing(addr+port, addr, i.timeout/10)
localCh := util.HTTPPing(addr+port, addr, i.timeout)
remoteCh := util.HTTPPing(i.listenIP+port, addr, i.timeout)

select {
case err := <-localCh:
if err == nil {
glog.V(2).Infoln(addr, "local first, succ")
return
}
continue
}

glog.V(2).Infoln("remote dial succ:", addr)
if err = <-remoteCh; err != nil {
glog.V(2).Infoln(addr, "local first, all fail")
return
}
glog.V(2).Infoln(addr, "local first, remote succ")
conf.AddSuggest(addr)

// Third: retest direct connect
conn, err = net.DialTimeout("tcp", addr+port, i.timeout)
if err == nil {
conn.Close()
return
case err := <-remoteCh:
if err != nil {
glog.V(2).Infoln(addr, "remote first, fail")
return
}
glog.V(2).Infoln(addr, "remote first, succ")
conf.AddSuggest(addr)
}

glog.V(2).Infoln("retry dial fail:", addr)
break
glog.Infof("added suggest domain: %s", addr)
return
}

// After three round test, most probably the addr is blocked
conf.AddSuggest(addr)
glog.Infof("added suggest domain: %s", addr)
return
}
44 changes: 44 additions & 0 deletions util/http_ping.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package util

import (
"io"
"net"
"strings"
"time"
)

// HTTPPing try connect to a http 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)
if err != nil {
return err
}
defer conn.Close()

conn.SetDeadline(time.Now().Add(timeout))
if _, err = conn.Write(
[]byte("TRACE / HTTP/1.1\r\nHost: " + domain + "\r\n\r\n")); err != nil {
return err
}

// err -> nil: read something succ
// 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 {
idx := strings.Index(tcpAddr, ":")
if idx >= 0 && tcpAddr[:idx] == domain {
return nil
}
}
return err
}

0 comments on commit 04193eb

Please sign in to comment.