Compare commits

...
9 Commits
Author SHA1 Message Date
wweir f256ab686d Fix default config file path 2019-05-05 09:32:23 +08:00
wweir 0c0f0699c1 Change config 2019-04-18 14:03:53 +08:00
wweir 8532a2e16c Merge branch 'feature/more-protocol' 2019-04-16 08:08:26 +08:00
wweir bad338033c Fix code 2019-04-16 08:04:37 +08:00
wweir a57f85ab1b Changes for unit test 2019-04-04 10:57:25 +08:00
wweir aed2afbe6d Fix protocol 2019-04-04 10:57:25 +08:00
wweir 2becd42176 Fix protocol 2019-03-31 08:06:00 +08:00
wweir d3664dc2b9 Add more protocols support 2019-03-30 12:31:02 +08:00
wweir a6fd60b5a2 Fix proxy port 2019-03-30 07:33:10 +08:00
29 changed files with 547 additions and 264 deletions
+11 -6
View File
@@ -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 -3
View File
@@ -18,16 +18,17 @@ import (
)
func initArgs() {
flag.StringVar(&Conf.ConfigFile, "f", filepath.Dir(os.Args[0])+"/sower.toml", "config file location")
cfgFile, _ := filepath.Abs(filepath.Join(filepath.Dir(os.Args[0]), "sower.toml"))
flag.StringVar(&Conf.ConfigFile, "f", cfgFile, "config file location")
flag.StringVar(&Conf.NetType, "n", "TCP", "net type (socks5 client only): "+strings.Join(transport.ListTransports(), ","))
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() {
+2 -1
View File
@@ -25,7 +25,8 @@ const name = "sower"
const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown | svc.AcceptPauseAndContinue
func initArgs() {
flag.StringVar(&Conf.ConfigFile, "f", filepath.Dir(os.Args[0])+"\\sower.toml", "config file location")
cfgFile, _ := filepath.Abs(filepath.Join(filepath.Dir(os.Args[0]), "sower.toml"))
flag.StringVar(&Conf.ConfigFile, "f", cfgFile, "config file location")
flag.BoolVar(&Conf.VersionOnly, "V", false, "print sower version")
install := flag.Bool("install", false, "install sower as a service")
uninstall := flag.Bool("uninstall", false, "uninstall sower from service list")
+7 -7
View File
@@ -2,12 +2,12 @@ net_type="TCP" # TCP, KCP, QUIC, SOCKS5(client only)
cipher="AES_128_GCM" # AES_128_GCM, AES_192_GCM, AES_256_GCM, CHACHA20_IETF_POLY1305, XCHACHA20_IETF_POLY1305
password="12345678"
server_port="5533"
# server_addr="remote-server:5533" # replce it to remote server
http_proxy=":8080" # eg: 192.168.0.2:8080
dns_server="" # Keep empty for dynamic setting from net env
client_ip="127.0.0.1" # listen the IP, dns target is the IP
# server_addr="remote-server" # replce it to remote server
http_proxy=":8080" # eg: 192.168.0.2:8080
dns_server="" # Keep empty for dynamic setting from net env
client_ip="127.0.0.1" # listen the IP, dns target is the IP
# clear_dns_cache="pkill mDNSResponder || true" # Windows: "ipconfig /flushdnss"
suggest_level="SPEEDUP" # DISABLE, BLOCK, SPEEDUP
suggest_level="SPEEDUP" # DISABLE, BLOCK, SPEEDUP
blocklist=[
"**.google.*", # google
"**.goo.gl",
@@ -33,8 +33,8 @@ blocklist=[
]
whitelist=[
"**.in-addr.arpa",
"iamp.*.*",
"iamp.*.*.*",
"imap.*.*",
"imap.*.*.*",
"smtp.*.*",
"smtp.*.*.*",
"pop.*.*",
+11 -2
View File
@@ -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)
+27 -38
View File
@@ -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{})
@@ -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()
@@ -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*/
@@ -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)
+16
View File
@@ -0,0 +1,16 @@
// Code generated by "stringer -type=level util.go"; DO NOT EDIT.
package dns
import "strconv"
const _level_name = "DISABLEBLOCKSPEEDUPlevelEnd"
var _level_index = [...]uint8{0, 7, 12, 19, 27}
func (i level) String() string {
if i < 0 || i >= level(len(_level_index)-1) {
return "level(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _level_name[_level_index[i]:_level_index[i+1]]
}
-16
View File
@@ -1,16 +0,0 @@
// Code generated by "stringer -type=suggestLevel util.go"; DO NOT EDIT.
package dns
import "strconv"
const _suggestLevel_name = "DISABLEBLOCKSPEEDUPlevelEnd"
var _suggestLevel_index = [...]uint8{0, 7, 12, 19, 27}
func (i suggestLevel) String() string {
if i < 0 || i >= suggestLevel(len(_suggestLevel_index)-1) {
return "suggestLevel(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _suggestLevel_name[_suggestLevel_index[i]:_suggestLevel_index[i+1]]
}
+8 -8
View File
@@ -46,11 +46,11 @@ 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
@@ -58,19 +58,19 @@ const (
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
}
+5 -12
View File
@@ -3,27 +3,20 @@ module github.com/wweir/sower
go 1.12
require (
github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861 // indirect; lock for quic
github.com/cheekybits/genny v1.0.0 // indirect
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/hashicorp/golang-lru v0.5.1 // indirect
github.com/klauspost/cpuid v1.2.0 // indirect
github.com/klauspost/reedsolomon v1.9.1 // indirect
github.com/krolaw/dhcp4 v0.0.0-20180925202202-7cead472c414
github.com/libp2p/go-reuseport v0.0.1
github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f // indirect
github.com/lucas-clemente/quic-go v0.10.1
github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced // indirect
github.com/miekg/dns v1.1.6
github.com/pelletier/go-toml v1.2.0
github.com/lucas-clemente/quic-go v0.11.1
github.com/miekg/dns v1.1.8
github.com/pelletier/go-toml v1.3.0
github.com/pkg/errors v0.8.1
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b // indirect
github.com/tjfoc/gmsm v1.0.1 // indirect
github.com/ulule/deepcopier v0.0.0-20171107155558-ca99b135e50f // indirect
github.com/wweir/mem-go v0.0.0-20190109100331-8673ab596296
github.com/xtaci/kcp-go v5.0.7+incompatible
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a
golang.org/x/net v0.0.0-20190313220215-9f648a60d977 // indirect
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e
github.com/xtaci/kcp-go v5.2.3+incompatible
golang.org/x/crypto v0.0.0-20190417174047-f416ebab96af
)
+33 -22
View File
@@ -1,12 +1,14 @@
github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861 h1:x17NvoJaphEzay72TFej4OSSsgu3xRYBLkbIwdofS/4=
github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/reedsolomon v1.9.1 h1:kYrT1MlR4JH6PqOpC+okdb9CDTcwEC/BqpzK4WFyXL8=
@@ -15,16 +17,17 @@ github.com/krolaw/dhcp4 v0.0.0-20180925202202-7cead472c414 h1:6wnYc2S/lVM7BvR32B
github.com/krolaw/dhcp4 v0.0.0-20180925202202-7cead472c414/go.mod h1:0AqAH3ZogsCrvrtUpvc6EtVKbc3w6xwZhkvGLuqyi3o=
github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw=
github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA=
github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f h1:sSeNEkJrs+0F9TUau0CgWTTNEwF23HST3Eq0A+QIx+A=
github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f/go.mod h1:JpH9J1c9oX6otFSgdUHwUBUizmKlrMjxWnIAjff4m04=
github.com/lucas-clemente/quic-go v0.10.1 h1:ipcMmYP9RT+b1YytOKGUY1qndxPGOczVEQkAVz3CZrs=
github.com/lucas-clemente/quic-go v0.10.1/go.mod h1:wuD+2XqEx8G9jtwx5ou2BEYBsE+whgQmlj0Vz/77PrY=
github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced h1:zqEC1GJZFbGZA0tRyNZqRjep92K5fujFtFsu5ZW7Aug=
github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced/go.mod h1:NCcRLrOTZbzhZvixZLlERbJtDtYsmMw8Jc4vS8Z0g58=
github.com/miekg/dns v1.1.6 h1:jVwb4GDwD65q/gtItR/lIZHjNH93QfeGxZUkzJcW9mc=
github.com/miekg/dns v1.1.6/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/lucas-clemente/quic-go v0.11.1 h1:zasajC848Dqq/+WqfqBCkmPw+YHNe1MBts/z7y7nXf4=
github.com/lucas-clemente/quic-go v0.11.1/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw=
github.com/marten-seemann/qtls v0.2.3 h1:0yWJ43C62LsZt08vuQJDK1uC1czUc3FJeCLPoNAI4vA=
github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk=
github.com/miekg/dns v1.1.8 h1:1QYRAKU3lN5cRfLCkPU08hwvLJFhvjP6MqNMmQz6ZVI=
github.com/miekg/dns v1.1.8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pelletier/go-toml v1.3.0 h1:e5+lF2E4Y2WCIxBefVowBuB0iHrUH4HZ8q+6mGF7fJc=
github.com/pelletier/go-toml v1.3.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -40,14 +43,22 @@ github.com/ulule/deepcopier v0.0.0-20171107155558-ca99b135e50f h1:QatZ4lsJBY3x1+
github.com/ulule/deepcopier v0.0.0-20171107155558-ca99b135e50f/go.mod h1:BNLmYJ8oMJPIPpNx5968jCyUhwEU1XT3YsuOqtbo5qo=
github.com/wweir/mem-go v0.0.0-20190109100331-8673ab596296 h1:/HkUfg+ZMx/tNdnyJdVlhyv+xO3A7ZlpfL9nFLWLYcc=
github.com/wweir/mem-go v0.0.0-20190109100331-8673ab596296/go.mod h1:k7rjBGWoJ+JKwvfe8juAX0zgybjo/Yo3JGkca5f/06s=
github.com/xtaci/kcp-go v5.0.7+incompatible h1:zs9tc8XRID0m+aetu3qPWZFyRt2UIMqbXIBgw+vcnlE=
github.com/xtaci/kcp-go v5.0.7+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exqr0evNhKRNe5K/gi+zKh4U=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977 h1:actzWV6iWn3GLqN8dZjzsB+CLt+gaV2+wsxroxiQI8I=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
github.com/xtaci/kcp-go v5.2.3+incompatible h1:LD/Go8xYxtcyvOvFzeo387BV3UNPcwJvMY+8H+JDhfk=
github.com/xtaci/kcp-go v5.2.3+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190417174047-f416ebab96af h1:6qGQw30u837TXZbCmLFR9AVA+RjJU1LIbvk0oIkDZGY=
golang.org/x/crypto v0.0.0-20190417174047-f416ebab96af/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e h1:ZytStCyV048ZqDsWHiYDdoI2Vd4msMcrDECFxS+tL9c=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+4 -4
View File
@@ -33,18 +33,18 @@ func main() {
} else {
conf.AddRefreshFn(true, func() (string, error) {
host, _, _ := net.SplitHostPort(cfg.ServerAddr)
dns.LoadRules(cfg.BlockList, cfg.Suggestions, cfg.WhiteList, host)
dns.LoadRules(cfg.BlockList, cfg.Suggestions, cfg.WhiteList, cfg.ServerAddr)
return "load rules", nil
})
isSocks5 := (cfg.NetType == "SOCKS5")
serverAddr := net.JoinHostPort(cfg.ServerAddr, cfg.ServerPort)
if cfg.HTTPProxy != "" {
go proxy.StartHttpProxy(tran, isSocks5, cfg.ServerAddr, cfg.Cipher, cfg.Password, cfg.HTTPProxy)
go proxy.StartHttpProxy(tran, isSocks5, serverAddr, cfg.Cipher, cfg.Password, cfg.HTTPProxy)
}
go dns.StartDNS(cfg.DNSServer, cfg.ClientIP, conf.SuggestCh, cfg.SuggestLevel)
proxy.StartClient(tran, isSocks5, cfg.ServerAddr, cfg.Cipher, cfg.Password, cfg.ClientIP)
proxy.StartClient(tran, isSocks5, serverAddr, cfg.Cipher, cfg.Password, cfg.ClientIP)
}
}
+56 -23
View File
@@ -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)
@@ -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
}
} else {
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
}
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
}
}()
conn.(*net.TCPConn).SetKeepAlive(true)
connCh <- conn
}
}(ports[i])
}
glog.Infoln("listening ports:", ports)
glog.Infoln("listening port:", port)
return connCh
}
+20 -8
View File
@@ -10,7 +10,9 @@ import (
"time"
"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"
)
@@ -34,7 +36,7 @@ func StartHttpProxy(tran transport.Transport, isSocks5 bool, server, cipher, pas
glog.Fatalln(srv.ListenAndServe())
}
func httpProxy(w http.ResponseWriter, req *http.Request,
func httpProxy(w http.ResponseWriter, r *http.Request,
tran transport.Transport, isSocks5 bool, server, cipher, password string) {
roundTripper := &http.Transport{
@@ -55,11 +57,13 @@ func httpProxy(w http.ResponseWriter, req *http.Request,
if err != nil {
return nil, err
}
return shadow.Shadow(conn, cipher, password), nil
conn = shadow.Shadow(conn, cipher, password)
return parser.NewHttpConn(conn), nil
}
}
resp, err := roundTripper.RoundTrip(req)
resp, err := roundTripper.RoundTrip(r)
if err != nil {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
glog.Errorln("serve https proxy, get remote data:", err)
@@ -88,6 +92,7 @@ func httpsProxy(w http.ResponseWriter, r *http.Request,
conn.(*net.TCPConn).SetKeepAlive(true)
if _, err := conn.Write([]byte(r.Proto + " 200 Connection established\r\n\r\n")); err != nil {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
conn.Close()
glog.Errorln("serve https proxy, write data fail:", err)
return
@@ -96,19 +101,26 @@ func httpsProxy(w http.ResponseWriter, r *http.Request,
// remote conn
rc, err := tran.Dial(server)
if err != nil {
conn.Close()
http.Error(w, err.Error(), http.StatusServiceUnavailable)
conn.Close()
glog.Errorln("serve https proxy, dial remote fail:", err)
return
}
host, port, err := net.SplitHostPort(r.Host)
if err != nil {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
conn.Close()
glog.Errorln("serve https proxy, dial remote fail:", err)
return
}
if isSocks5 {
if rc, conn, err = buildSocks5Conn(rc, conn); err != nil {
glog.Errorln(err)
return
}
rc = socks5.ToSocks5(rc, host, port)
} else {
rc = shadow.Shadow(rc, cipher, password)
rc = parser.NewHttpsConn(rc, port)
}
relay(rc, conn)
+12
View File
@@ -0,0 +1,12 @@
// Package parser transter conn to be a parser conn
//
// init request payload:
// <type>(1) + <size>(2))(+Overhead) + <data>(size+Overhead)
// data definition:
// 0x00(any): [size](1) + [addr:port] + content
// 0x01(http): content
// 0x02(https): [port](2) + content
//
// init response payload:
// ([status code](2) + <size>(2))(+Overhead) + <content>(size+Overhead)
package parser
+163
View File
@@ -0,0 +1,163 @@
package parser
import (
"bufio"
"io"
"net"
"net/http"
"strconv"
"strings"
"github.com/pkg/errors"
"github.com/wweir/sower/util"
)
const (
OTHER byte = iota
HTTP
HTTPS
)
// Write Addr
type conn struct {
typ byte
domain string
port string
init bool
net.Conn
}
func NewOtherConn(c net.Conn, domain, port string) net.Conn {
return &conn{
typ: OTHER,
domain: domain,
port: port,
init: true,
Conn: c,
}
}
func NewHttpConn(c net.Conn) net.Conn {
return &conn{
typ: HTTP,
init: true,
Conn: c,
}
}
func NewHttpsConn(c net.Conn, port string) net.Conn {
return &conn{
typ: HTTPS,
port: port,
init: true,
Conn: c,
}
}
func (c *conn) Write(b []byte) (n int, err error) {
if c.init {
var pkg []byte
var prefixLen int
switch c.typ {
case OTHER:
// type + domain + ':' + port + data
prefixLen = 1 + len(c.domain) + 1 + len(c.port)
pkg = make([]byte, 0, prefixLen+len(b))
pkg = append(pkg, OTHER)
pkg = append(pkg, byte(len(c.domain)+1+len(c.port)))
pkg = append(pkg, []byte(c.domain+":"+c.port)...)
case HTTP:
// type + data
prefixLen = 1
pkg = make([]byte, 0, prefixLen+len(b))
pkg = append(pkg, HTTP)
case HTTPS:
// type + port + data
prefixLen = 1 + 2
pkg = make([]byte, 0, prefixLen+len(b))
pkg = append(pkg, HTTPS)
port, _ := strconv.Atoi(c.port)
pkg = append(pkg, byte(port>>8), byte(port))
}
c.init = false
n, err := c.Conn.Write(append(pkg, b...))
// n should larger than prefix length, if not, err is not nil
return n - prefixLen, err
}
return c.Conn.Write(b)
}
// Read Addr
func ParseAddr(conn net.Conn) (net.Conn, string, string, error) {
buf := make([]byte, 1)
if _, err := io.ReadFull(conn, buf); err != nil {
return conn, "", "", err
}
switch buf[0] {
case OTHER:
if _, err := io.ReadFull(conn, buf); err != nil {
return conn, "", "", err
}
buf = make([]byte, int(buf[0]))
if _, err := io.ReadFull(conn, buf); err != nil {
return conn, "", "", err
}
addr := string(buf)
if idx := strings.LastIndex(addr, ":"); idx != -1 {
return conn, addr[:idx], addr[idx+1:], nil
}
return conn, "", "", errors.New("invalid payload")
case HTTP:
return ParseHttpAddr(conn)
case HTTPS:
buf = make([]byte, 2)
if _, err := io.ReadFull(conn, buf); err != nil {
return conn, "", "", err
}
port := strconv.Itoa(int(buf[0])<<8 + int(buf[1]))
conn, domain, err := ParseHttpsHost(conn)
return conn, domain, port, err
default:
return conn, "", "", errors.Errorf("not supported type (%v)", buf[0])
}
}
func ParseHttpAddr(conn net.Conn) (net.Conn, string, string, error) {
teeConn := &util.TeeConn{Conn: conn}
teeConn.StartOrReset()
defer teeConn.Stop()
b := bufio.NewReader(teeConn)
resp, err := http.ReadRequest(b)
if err != nil {
return teeConn, "", "", err
}
if idx := strings.LastIndex(resp.Host, ":"); idx != -1 {
return teeConn, resp.Host[:idx], resp.Host[idx+1:], nil
}
return teeConn, resp.Host, "80", nil
}
func ParseHttpsHost(conn net.Conn) (net.Conn, string, error) {
teeConn := &util.TeeConn{Conn: conn}
teeConn.StartOrReset()
defer teeConn.Stop()
domain, _, err := extractSNI(teeConn)
if err != nil {
return teeConn, "", err
} else if domain == "" {
return teeConn, "", errors.New("ClientHello did not present an SNI extension")
}
return teeConn, domain, nil
}
-48
View File
@@ -1,48 +0,0 @@
package parser
import (
"bufio"
"fmt"
"io"
"net"
"net/http"
"strings"
"github.com/wweir/sower/util"
)
func ParseAddr(conn net.Conn) (teeConn *util.TeeConn, addr string, err error) {
teeConn = &util.TeeConn{Conn: conn}
teeConn.StartOrReset()
defer teeConn.Stop()
buf := make([]byte, 1)
if n, err := teeConn.Read(buf); err != nil {
return teeConn, "", fmt.Errorf("Read conn fail: %v, readed: %v", err, buf[:n])
}
teeConn.StartOrReset()
// https
if buf[0] == 0x16 { // SSL handleshake
host, _, err := extractSNI(io.Reader(teeConn))
if err != nil {
return teeConn, "", err
}
if strings.Contains(host, ":") {
return teeConn, host, nil
}
return teeConn, host + ":443", nil
}
// http
b := bufio.NewReader(teeConn)
resp, err := http.ReadRequest(b)
if err != nil {
return teeConn, "", err
}
if strings.Contains(resp.Host, ":") {
return teeConn, resp.Host, nil
}
return teeConn, resp.Host + ":80", nil
}
+97
View File
@@ -0,0 +1,97 @@
package parser
import (
"bufio"
"bytes"
"io/ioutil"
"net"
"net/http"
"testing"
"github.com/wweir/sower/proxy/shadow"
"github.com/wweir/sower/util"
)
func TestParseAddr1(t *testing.T) {
c1, c2 := net.Pipe()
go func() {
c1 = NewHttpConn(c1)
req, _ := http.NewRequest("GET", "http://wweir.cc", bytes.NewReader([]byte{1, 2, 3}))
req.Write(c1)
}()
c2, host, port, err := ParseAddr(c2)
if err != nil || host != "wweir.cc" || port != "80" {
t.Error(err, host, port)
}
req, err := http.ReadRequest(bufio.NewReader(c2))
if err != nil {
t.Error(err)
}
data, err := ioutil.ReadAll(req.Body)
if err != nil || len(data) != 3 || data[0] != 1 {
t.Error(err, data)
}
}
func TestParseAddr2(t *testing.T) {
c1, c2 := net.Pipe()
go func() {
c1 = NewHttpsConn(c1, "443")
c1.Write(util.HTTPS.PingMsg("wweir.cc"))
}()
_, host, port, err := ParseAddr(c2)
if err != nil || host != "wweir.cc" || port != "443" {
t.Error(err, host, port)
}
}
func TestParseAddr3(t *testing.T) {
c1, c2 := net.Pipe()
go func() {
c1 = NewOtherConn(c1, "wweir.cc", "1080")
c1.Write(util.HTTPS.PingMsg("wweir.cc"))
}()
_, host, port, err := ParseAddr(c2)
if err != nil || host != "wweir.cc" || port != "1080" {
t.Error(err, host, port)
}
}
func TestParseAddr4(t *testing.T) {
c1, c2 := net.Pipe()
go func() {
c1 = shadow.Shadow(c1, "AES_128_GCM", "12345678")
c1 = NewHttpConn(c1)
req, _ := http.NewRequest("GET", "http://wweir.cc", bytes.NewReader([]byte{1, 2, 3}))
req.Write(c1)
}()
c2 = shadow.Shadow(c2, "AES_128_GCM", "12345678")
c2, host, port, err := ParseAddr(c2)
if err != nil || host != "wweir.cc" || port != "80" {
t.Error(err, host, port)
}
req, err := http.ReadRequest(bufio.NewReader(c2))
if err != nil {
t.Error(err)
}
data, err := ioutil.ReadAll(req.Body)
if err != nil || len(data) != 3 || data[0] != 1 {
t.Error(err, data)
}
}
+7 -9
View File
@@ -14,7 +14,7 @@ func StartServer(tran transport.Transport, port, cipher, password string) {
if port == "" {
glog.Fatalln("port must set")
}
if !strings.Contains(port, ":") {
if !strings.HasPrefix(port, ":") {
port = ":" + port
}
@@ -25,23 +25,21 @@ func StartServer(tran transport.Transport, port, cipher, password string) {
glog.Infoln("Server started.")
for {
conn := <-connCh
conn = shadow.Shadow(conn, cipher, password)
go handle(conn)
go handle(<-connCh, cipher, password)
}
}
func handle(conn net.Conn) {
conn, addr, err := parser.ParseAddr(conn)
func handle(conn net.Conn, cipher, password string) {
conn = shadow.Shadow(conn, cipher, password)
conn, host, port, err := parser.ParseAddr(conn)
if err != nil {
conn.Close()
glog.Warningln(err)
return
}
glog.V(1).Infof("new conn from %s to %s", conn.RemoteAddr(), addr)
glog.V(1).Infof("new conn from %s to %s:%s", conn.RemoteAddr(), host, port)
rc, err := net.Dial("tcp", addr)
rc, err := net.Dial("tcp", net.JoinHostPort(host, port))
if err != nil {
conn.Close()
glog.Warningln(err)
+7 -7
View File
@@ -8,11 +8,11 @@ import (
"golang.org/x/crypto/chacha20poly1305"
)
//go:generate stringer -type=cipherType $GOFILE
type cipherType int
//go:generate stringer -type=typ $GOFILE
type typ int
const (
AES_128_GCM cipherType = iota
AES_128_GCM typ = iota
AES_192_GCM
AES_256_GCM
CHACHA20_IETF_POLY1305
@@ -22,15 +22,15 @@ const (
func ListCiphers() []string {
list := make([]string, 0, int(cipherEnd))
for i := cipherType(0); i < cipherEnd; i++ {
for i := typ(0); i < cipherEnd; i++ {
list = append(list, i.String())
}
return list
}
func pickCipher(cipherType, password string) (cipher.AEAD, error) {
func pickCipher(typ, password string) (cipher.AEAD, error) {
var blockSize int
switch cipherType {
switch typ {
case AES_128_GCM.String():
blockSize = 16
case AES_192_GCM.String():
@@ -44,7 +44,7 @@ func pickCipher(cipherType, password string) (cipher.AEAD, error) {
return chacha20poly1305.NewX(genKey(password, 256))
default:
return nil, errors.New("do not support cipher type: " + cipherType)
return nil, errors.New("do not support cipher type: " + typ)
}
// aes gcm
-16
View File
@@ -1,16 +0,0 @@
// Code generated by "stringer -type=cipherType cipher.go"; DO NOT EDIT.
package shadow
import "strconv"
const _cipherType_name = "AES_128_GCMAES_192_GCMAES_256_GCMCHACHA20_IETF_POLY1305XCHACHA20_IETF_POLY1305cipherEnd"
var _cipherType_index = [...]uint8{0, 11, 22, 33, 55, 78, 87}
func (i cipherType) String() string {
if i < 0 || i >= cipherType(len(_cipherType_index)-1) {
return "cipherType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _cipherType_name[_cipherType_index[i]:_cipherType_index[i+1]]
}
+2 -1
View File
@@ -1,4 +1,5 @@
// Package shadow transter conn to be a crypto conn
// support aead mode only
// payload: [size](2+Overhead bytes) + [content](size+Overhead bytes)
// data payload:
// <size>(2+Overhead) + <content>(size+Overhead)
package shadow
+1 -1
View File
@@ -71,7 +71,7 @@ func (c *conn) Write(b []byte) (n int, err error) {
}
// BigEndian
c.writeBuf[0], c.writeBuf[1] = byte((dataSize&0xFF00)>>8), byte(dataSize&0xFF)
c.writeBuf[0], c.writeBuf[1] = byte(dataSize>>8), byte(dataSize)
c.aead.Seal(c.writeBuf[:0], c.encryptNonce(), c.writeBuf[:2], nil)
c.aead.Seal(c.writeBuf[:2+c.aead.Overhead()], c.encryptNonce(), b[:dataSize], nil)
+22
View File
@@ -0,0 +1,22 @@
package shadow
import (
"net"
"testing"
)
func TestShadow(t *testing.T) {
c1, c2 := net.Pipe()
go func() {
conn := Shadow(c1, "AES_128_GCM", "12345678")
conn.Write([]byte{1, 2})
}()
conn := Shadow(c2, "AES_128_GCM", "12345678")
buf := make([]byte, 3)
n, _ := conn.Read(buf)
if n!=2|| buf[0] != 1 || buf[1] != 2 {
t.Error(buf)
}
}
+16
View File
@@ -0,0 +1,16 @@
// Code generated by "stringer -type=typ cipher.go"; DO NOT EDIT.
package shadow
import "strconv"
const _typ_name = "AES_128_GCMAES_192_GCMAES_256_GCMCHACHA20_IETF_POLY1305XCHACHA20_IETF_POLY1305cipherEnd"
var _typ_index = [...]uint8{0, 11, 22, 33, 55, 78, 87}
func (i typ) String() string {
if i < 0 || i >= typ(len(_typ_index)-1) {
return "typ(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _typ_name[_typ_index[i]:_typ_index[i+1]]
}
+4 -8
View File
@@ -4,19 +4,15 @@ import (
"encoding/binary"
"io"
"net"
"strconv"
"github.com/pkg/errors"
)
func ToSocks5(c net.Conn, domain, port string) net.Conn {
switch port {
case "80":
return &conn{init: make(chan struct{}), Conn: c, domain: domain, port: []byte{0x00, 0x50}}
case "443":
return &conn{init: make(chan struct{}), Conn: c, domain: domain, port: []byte{0x01, 0xbb}}
default:
panic("invalid port: " + port)
}
num, _ := strconv.Atoi(port)
bytes := []byte{byte(num >> 8), byte(num)}
return &conn{init: make(chan struct{}), Conn: c, domain: domain, port: bytes}
}
type conn struct {
+1 -20
View File
@@ -8,8 +8,6 @@ import (
"time"
"github.com/golang/glog"
"github.com/wweir/sower/proxy/parser"
"github.com/wweir/sower/proxy/socks5"
)
// race safe
@@ -20,30 +18,13 @@ func resolveAddr(server *string) {
if addr, err := net.ResolveTCPAddr("tcp", *server); err != nil {
glog.Errorln(err)
} else {
glog.Infof("remote server (%s)=>(%s)", *server, addr)
*server = addr.String()
resolved = true
}
}
}
func buildSocks5Conn(c, relay net.Conn) (net.Conn, net.Conn, error) {
conn, addr, err := parser.ParseAddr(relay)
if err != nil {
c.Close()
relay.Close()
return nil, nil, err
}
host, port, err := net.SplitHostPort(addr)
if err != nil {
c.Close()
relay.Close()
return nil, nil, err
}
return socks5.ToSocks5(c, host, port), conn, nil
}
func relay(conn1, conn2 net.Conn) {
wg := &sync.WaitGroup{}
exitFlag := new(int32)
+3 -3
View File
@@ -1,4 +1,4 @@
package dns
package util
import (
"bytes"
@@ -18,7 +18,7 @@ func HTTPPing(viaHost, domain string, port Port, timeout time.Duration) (err err
defer conn.Close()
conn.SetDeadline(time.Now().Add(timeout))
if _, err = conn.Write(port.pingMsg(domain)); err != nil {
if _, err = conn.Write(port.PingMsg(domain)); err != nil {
return err
}
@@ -51,7 +51,7 @@ func (p Port) JoinAddr(addr string) string {
}
}
func (p Port) pingMsg(domain string) []byte {
func (p Port) PingMsg(domain string) []byte {
switch p {
case HTTP:
return []byte("TRACE / HTTP/1.1\r\nHost: " + domain + "\r\n\r\n")
+8 -1
View File
@@ -1,11 +1,18 @@
package util
import (
"runtime"
"testing"
)
func TestPickInterface(t *testing.T) {
t.Skip("skip for some enviroment not have net interface")
switch runtime.GOOS {
case "windows":
case "darwin":
default:
t.Skip("skip for some enviroment not have net interface")
return
}
got, err := PickInterface()
if err != nil {