Skip to content

Commit

Permalink
Merge branch 'feature/more-protocol'
Browse files Browse the repository at this point in the history
  • Loading branch information
wweir committed Apr 16, 2019
2 parents d6dbfd4 + bad3380 commit 8532a2e
Show file tree
Hide file tree
Showing 24 changed files with 493 additions and 216 deletions.
17 changes: 11 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,20 @@ kill:
sudo pkill -9 sower || true

client: build kill
sudo $(PWD)/sower
sudo $(PWD)/sower -s 127.0.0.1:5533 -H "127.0.0.1:8080"

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

run: build kill
$(PWD)/sower -n TCP -v 1 &
sudo $(PWD)/sower &
$(PWD)/sower -f '' &
sudo $(PWD)/sower -f '' -s 127.0.0.1:5533 -H "127.0.0.1:8080" &

@sleep 1
curl localhost
HTTP_PROXY=http://127.0.0.1:8080 curl http://baidu.com || true
@echo
HTTPS_PROXY=http://127.0.0.1:8080 curl https://baidu.com || true
@echo

@sleep 1
@sudo pkill -9 sower || true
4 changes: 2 additions & 2 deletions conf/conf_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ func initArgs() {
flag.StringVar(&Conf.Cipher, "C", "AES_128_GCM", "cipher type: "+strings.Join(shadow.ListCiphers(), ","))
flag.StringVar(&Conf.Password, "p", "12345678", "password")
flag.StringVar(&Conf.ServerPort, "P", "5533", "server mode listen port")
flag.StringVar(&Conf.ServerAddr, "s", "", "server IP (run in CLIENT MODE if set)")
flag.StringVar(&Conf.ServerAddr, "s", "", "server IP (run in CLIENT mode if set)")
flag.StringVar(&Conf.HTTPProxy, "H", "", "http proxy listen addr")
flag.StringVar(&Conf.DNSServer, "d", "114.114.114.114", "client dns server")
flag.StringVar(&Conf.ClientIP, "c", "127.0.0.1", "client dns service redirect IP")
flag.StringVar(&Conf.SuggestLevel, "S", "SPEEDUP", "suggest level setting: "+strings.Join(dns.ListSuggestLevels(), ","))
flag.StringVar(&Conf.SuggestLevel, "l", "SPEEDUP", "suggest level setting: "+strings.Join(dns.ListSuggestLevels(), ","))
flag.BoolVar(&Conf.VersionOnly, "V", false, "print sower version")

if !flag.Parsed() {
Expand Down
13 changes: 11 additions & 2 deletions dns/dhcp_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
package dns

import "testing"
import (
"runtime"
"testing"
)

func TestGetDefaultDNSServer(t *testing.T) {
t.Skip("skip for some enviroment not support dhcp and permission")
switch runtime.GOOS {
case "windows":
case "darwin":
default:
t.Skip("skip for some enviroment not support dhcp and permission set")
return
}

if got, err := GetDefaultDNSServer(); err != nil {
t.Errorf("GetDefaultDNSServer() return error: %s", err)
Expand Down
65 changes: 27 additions & 38 deletions dns/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ import (
"github.com/golang/glog"
"github.com/miekg/dns"
mem "github.com/wweir/mem-go"
"github.com/wweir/sower/util"
)

const colon = byte(':')

func StartDNS(dnsServer, listenIP string, suggestCh chan<- string, suggestLevel string) {
func StartDNS(dnsServer, listenIP string, suggestCh chan<- string, level string) {
ip := net.ParseIP(listenIP)

suggest := &intelliSuggest{suggestCh, parseSuggestLevel(suggestLevel), listenIP, time.Second}
suggest := &intelliSuggest{suggestCh, parseSuggestLevel(level), listenIP, time.Second}
mem.DefaultCache = mem.New(time.Hour)

dhcpCh := make(chan struct{})
Expand Down Expand Up @@ -93,18 +94,7 @@ func matchAndServe(w dns.ResponseWriter, r *dns.Msg, domain, listenIP, dnsServer
return
}

if !inWriteList {
go func() {
ip, err := net.LookupIP(domain)
if err != nil || len(ip) == 0 {
glog.V(1).Infoln(ip, err)
return
}

mem.Remember(suggest, addr{domain, ip[0].String()})
}()
}

go mem.Remember(suggest, domain)
ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
defer cancel()

Expand All @@ -127,40 +117,39 @@ func matchAndServe(w dns.ResponseWriter, r *dns.Msg, domain, listenIP, dnsServer
}

type intelliSuggest struct {
suggestCh chan<- string
suggestLevel suggestLevel
listenIP string
timeout time.Duration
}
type addr struct {
domain string
ip string
suggestCh chan<- string
level level
listenIP string
timeout time.Duration
}

func (i *intelliSuggest) GetOne(key interface{}) (iface interface{}, e error) {
iface, e = struct{}{}, nil
if i.suggestLevel == DISABLE {
if i.level == DISABLE {
return
}

domain := key.(addr).domain
ip := key.(addr).ip

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

ip, err := net.LookupIP(domain)
if err != nil || len(ip) == 0 {
glog.V(1).Infoln(domain, ip, err)
return
}

var (
pings = [...]struct {
viaAddr string
port Port
port util.Port
}{
{ip, HTTP},
{i.listenIP, HTTP},
{ip, HTTPS},
{i.listenIP, HTTPS},
{ip[0].String(), util.HTTP},
{i.listenIP, util.HTTP},
{ip[0].String(), util.HTTPS},
{i.listenIP, util.HTTPS},
}
protos = [...]*int32{
new(int32), /*HTTP*/
Expand All @@ -170,19 +159,19 @@ func (i *intelliSuggest) GetOne(key interface{}) (iface interface{}, e error) {
)
for idx := range pings {
go func(idx int) {
if err := HTTPPing(pings[idx].viaAddr, domain, pings[idx].port, i.timeout); err != nil {
if err := util.HTTPPing(pings[idx].viaAddr, domain, pings[idx].port, i.timeout); err != nil {
// local ping fail
if pings[idx].viaAddr == ip {
atomic.AddInt32(score, 1)
glog.V(1).Infof("local ping %s fail", domain)
} else {
if pings[idx].viaAddr == i.listenIP {
atomic.AddInt32(score, -1)
glog.V(1).Infof("remote ping %s fail", domain)
} else {
atomic.AddInt32(score, 1)
glog.V(1).Infof("local ping %s fail", domain)
}

// remote ping faster
} else if pings[idx].viaAddr == i.listenIP {
if atomic.CompareAndSwapInt32(protos[idx/2], 0, 1) && i.suggestLevel == SPEEDUP {
if atomic.CompareAndSwapInt32(protos[idx/2], 0, 1) && i.level == SPEEDUP {
atomic.AddInt32(score, 1)
}
glog.V(1).Infof("remote ping %s faster", domain)
Expand Down
16 changes: 16 additions & 0 deletions dns/level_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 0 additions & 16 deletions dns/suggestlevel_string.go

This file was deleted.

16 changes: 8 additions & 8 deletions dns/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,31 +46,31 @@ func localA(r *dns.Msg, domain string, localIP net.IP) *dns.Msg {
return m
}

//go:generate stringer -type=suggestLevel $GOFILE
type suggestLevel int32
//go:generate stringer -type=level $GOFILE
type level int32

const (
DISABLE suggestLevel = iota
DISABLE level = iota
BLOCK
SPEEDUP
levelEnd
)

func ListSuggestLevels() []string {
list := make([]string, 0, int(levelEnd))
for i := suggestLevel(0); i < levelEnd; i++ {
for i := level(0); i < levelEnd; i++ {
list = append(list, i.String())
}
return list
}

func parseSuggestLevel(level string) suggestLevel {
for i := suggestLevel(0); i < levelEnd; i++ {
if level == i.String() {
func parseSuggestLevel(suggestLevel string) level {
for i := level(0); i < levelEnd; i++ {
if suggestLevel == i.String() {
return i
}
}

glog.Exitln("invalid suggest level: " + level)
glog.Exitln("invalid suggest level: " + suggestLevel)
return levelEnd
}
79 changes: 56 additions & 23 deletions proxy/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,26 @@ import (
"net"

"github.com/golang/glog"
"github.com/wweir/sower/proxy/parser"
"github.com/wweir/sower/proxy/shadow"
"github.com/wweir/sower/proxy/socks5"
"github.com/wweir/sower/proxy/transport"
)

func StartClient(tran transport.Transport, isSocks5 bool, server, cipher, password, listenIP string) {
connCh := listenLocal(listenIP, []string{"80", "443"})
conn80 := listenLocal(listenIP, "80")
conn443 := listenLocal(listenIP, "443")
var isHttp bool
var conn net.Conn

glog.Infoln("Client started.")
for {
conn := <-connCh
select {
case conn = <-conn80:
isHttp = true
case conn = <-conn443:
isHttp = false
}

resolveAddr(&server)
glog.V(1).Infof("new conn from (%s) to (%s)", conn.RemoteAddr(), server)
Expand All @@ -25,41 +35,64 @@ func StartClient(tran transport.Transport, isSocks5 bool, server, cipher, passwo
continue
}

if isSocks5 {
if rc, conn, err = buildSocks5Conn(rc, conn); err != nil {
switch {
case isSocks5 && isHttp:
c, host, port, err := parser.ParseHttpAddr(conn)
if err != nil {
c.Close()
rc.Close()
glog.Errorln(err)
continue
}

conn = c
rc = socks5.ToSocks5(rc, host, port)

case isSocks5 && !isHttp:
c, host, err := parser.ParseHttpsHost(conn)
if err != nil {
c.Close()
rc.Close()
glog.Errorln(err)
continue
}
} else {

conn = c
rc = socks5.ToSocks5(rc, host, "443")

case !isSocks5 && isHttp:
rc = shadow.Shadow(rc, cipher, password)
rc = parser.NewHttpConn(rc)

case !isSocks5 && !isHttp:
rc = shadow.Shadow(rc, cipher, password)
rc = parser.NewHttpsConn(rc, "443")
}

go relay(conn, rc)
}
}

func listenLocal(listenIP string, ports []string) <-chan net.Conn {
func listenLocal(listenIP string, port string) <-chan net.Conn {
connCh := make(chan net.Conn, 10)
for i := range ports {
go func(port string) {
ln, err := net.Listen("tcp", net.JoinHostPort(listenIP, port))
go func() {
ln, err := net.Listen("tcp", net.JoinHostPort(listenIP, port))
if err != nil {
glog.Fatalln(err)
}

for {
conn, err := ln.Accept()
if err != nil {
glog.Fatalln(err)
glog.Errorln("accept", listenIP+port, "fail:", err)
continue
}

for {
conn, err := ln.Accept()
if err != nil {
glog.Errorln("accept", listenIP+port, "fail:", err)
continue
}

conn.(*net.TCPConn).SetKeepAlive(true)
connCh <- conn
}
}(ports[i])
}
conn.(*net.TCPConn).SetKeepAlive(true)
connCh <- conn
}
}()

glog.Infoln("listening ports:", ports)
glog.Infoln("listening port:", port)
return connCh
}
Loading

0 comments on commit 8532a2e

Please sign in to comment.