support config reference

This commit is contained in:
wweir
2020-07-13 07:24:40 +08:00
parent 47b8fc601f
commit 56b8e35fe7
19 changed files with 546 additions and 328 deletions
+60 -13
View File
@@ -1,27 +1,36 @@
package conf
import (
"bufio"
"flag"
"io"
"net/http"
"os"
"path/filepath"
"strings"
"sync"
toml "github.com/pelletier/go-toml"
"github.com/wweir/sower/util"
"github.com/wweir/utils/log"
"github.com/wweir/util-go/log"
"golang.org/x/xerrors"
)
type Client struct {
Address string `toml:"address"`
HTTPProxy string `toml:"http_proxy"`
DNSServeIP string `toml:"dns_serve_ip"`
DNSUpstream string `toml:"dns_upstream"`
Socks5Proxy string `toml:"socks5"`
HTTPProxy string `toml:"http_proxy"`
PortForward map[string]string `toml:"port_forward"`
Router struct {
DetectLevel int `toml:"detect_level"`
ProxyList []string `toml:"proxy_list"`
ProxyRefs []string `toml:"proxy_refs"`
DirectList []string `toml:"direct_list"`
DirectRefs []string `toml:"direct_refs"`
BlockList []string `toml:"block_list"`
BlockRefs []string `toml:"block_refs"`
} `toml:"router"`
}
type Server struct {
@@ -59,7 +68,7 @@ func Init() (*Client, *Server, string) {
flag.Parse()
}
defer log.Infow("starting", "config", &conf)
defer log.Infow("starting", "version", version, "date", date, "config", &conf)
if conf.file == "" {
return &conf.Client, &conf.Server, conf.Password
}
@@ -76,16 +85,61 @@ func Init() (*Client, *Server, string) {
var loadConfigFns = []struct {
step string
fn func() error
}{{"load_config", func() error {
}{{"parse file", func() error {
f, err := os.OpenFile(conf.file, os.O_RDONLY, 0644)
if err != nil {
return err
return xerrors.New(err.Error())
}
defer f.Close()
return toml.NewDecoder(f).Decode(&conf)
}}, {"load referenced rule", func() error {
for _, addr := range conf.Client.Router.BlockRefs {
lines, err := getRemoteRuleLines(addr)
if err != nil {
return err
}
conf.Client.Router.BlockList = append(conf.Client.Router.BlockList, lines...)
}
for _, addr := range conf.Client.Router.ProxyRefs {
lines, err := getRemoteRuleLines(addr)
if err != nil {
return err
}
conf.Client.Router.ProxyList = append(conf.Client.Router.ProxyList, lines...)
}
for _, addr := range conf.Client.Router.DirectRefs {
lines, err := getRemoteRuleLines(addr)
if err != nil {
return err
}
conf.Client.Router.DirectList = append(conf.Client.Router.DirectList, lines...)
}
return nil
}}}
func getRemoteRuleLines(addr string) ([]string, error) {
resp, err := http.Get(addr)
if err != nil {
return nil, xerrors.New(err.Error())
}
defer resp.Body.Close()
br := bufio.NewReader(resp.Body)
lines := []string{}
for {
line, _, err := br.ReadLine()
if err == io.EOF {
return lines, nil
} else if err != nil {
return nil, xerrors.New(err.Error())
}
lines = append(lines, "**."+strings.TrimSpace(string(line)))
}
}
// flushCh to avoid parallel persist
var flushCh = make(chan struct{})
var flushOnce = sync.Once{}
@@ -138,12 +192,5 @@ func flushConfDaemon() {
continue
}
}
// reload config
for i := range loadConfigFns {
if err := loadConfigFns[i].fn(); err != nil {
log.Errorw("flush config", "step", loadConfigFns[i].step, "err", err)
}
}
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ import (
"path/filepath"
"time"
"github.com/wweir/utils/log"
"github.com/wweir/util-go/log"
)
const svcPath = "/Library/LaunchDaemons/sower.plist"
+1 -8
View File
@@ -12,7 +12,7 @@ import (
"path/filepath"
"time"
"github.com/wweir/utils/log"
"github.com/wweir/util-go/log"
)
const svcPath = "/etc/systemd/system/sower.service"
@@ -66,13 +66,6 @@ func afterInitFlag() {
case uninstallFlag:
uninstall()
default:
if conf.Client.DNSServeIP != "" {
log.Infow("setting system DNS", "DNS", conf.Client.DNSServeIP)
if err := execute(fmt.Sprintf("grep '%s' || sed -i '1inameserver %s' /etc/resolv.conf",
conf.Client.DNSServeIP, conf.Client.DNSServeIP)); err != nil {
log.Errorf("set DNS fail, please set DNS to %s manually", conf.Client.DNSServeIP)
}
}
return
}
os.Exit(0)
+1 -1
View File
@@ -13,7 +13,7 @@ import (
"syscall"
"time"
"github.com/wweir/utils/log"
"github.com/wweir/util-go/log"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/eventlog"
+59 -48
View File
@@ -1,54 +1,65 @@
password="" # sower password
password = "" # sower password
[client]
address = "" # aa.bb.cc, socks5h://127.0.0.1:1080
http_proxy=":8080"
dns_serve_ip="" # eg: 127.0.0.1. keep empty to disable DNS solution
dns_upstream="" # keep empty to set via dhcp, not effective in any environment
address = "" # aa.bb.cc, socks5h://127.0.0.1:1080
dns_upstream = "" # keep empty to set via dhcp, not effective in any environment
http_proxy = ""
socks5 = ""
[client.port_forward]
# eg: ":2222"="aa.bb.cc:22"
[client.router]
detect_level = 0 # [-4, 4], the bigger the harder to add
direct_list = [
"**.in-addr.arpa",
"imap.*.*",
"imap.*.*.*",
"smtp.*.*",
"smtp.*.*.*",
"pop.*.*",
"pop.*.*.*",
"**.cn",
]
proxy_list = [
"**.google.*",
"**.goo.gl",
"**.googleusercontent.com",
"**.googleapis.com",
"*.googlesource.com",
"**.youtube.com",
"**.ytimg.com",
"**.ggpht.com",
"**.googlevideo.com",
"**.facebook.com",
"**.fbcdn.net",
"**.twitter.com",
"**.twimg.com",
"**.blogspot.com",
"**.appspot.com",
"**.wikipedia.org",
"*.cloudfront.net",
"**.amazon.com",
"**.amazonaws.com",
"*.githubusercontent.com",
"*.githubassets.com",
"*.github.*",
]
[client.port_forward]
# eg: ":2222"="aa.bb.cc:22"
[client.router]
block_refs = [
"https://cdn.jsdelivr.net/gh/pexcn/daily@gh-pages/adlist/adlist.txt",
]
detect_level = 0 # [-4, 4], the bigger the harder to add
direct_cird_refs = [
"https://cdn.jsdelivr.net/gh/pexcn/daily@gh-pages/chnroute/chnroute.txt",
]
direct_list = [
"**.in-addr.arpa",
"imap.*.*",
"imap.*.*.*",
"smtp.*.*",
"smtp.*.*.*",
"pop.*.*",
"pop.*.*.*",
"**.cn",
]
direct_refs = [
"https://cdn.jsdelivr.net/gh/pexcn/daily@gh-pages/chinalist/chinalist.txt",
]
proxy_list = [
"**.google.*",
"**.goo.gl",
"**.googleusercontent.com",
"**.googleapis.com",
"*.googlesource.com",
"**.youtube.com",
"**.ytimg.com",
"**.ggpht.com",
"**.googlevideo.com",
"**.facebook.com",
"**.fbcdn.net",
"**.twitter.com",
"**.twimg.com",
"**.blogspot.com",
"**.appspot.com",
"**.wikipedia.org",
"*.cloudfront.net",
"**.amazon.com",
"**.amazonaws.com",
"*.githubusercontent.com",
"*.githubassets.com",
"*.github.*",
]
proxy_refs = [
"https://cdn.jsdelivr.net/gh/pexcn/daily@gh-pages/gfwlist/gfwlist.txt",
]
[server]
cert_email = "" # eg: user@aa.bb.cc
cert_file = "" # eg: /etc/ssl/server.crt
key_file = "" # eg: /etc/ssl/server.key
upstream = "" # eg: 127.0.0.1:8080
cert_email = "" # eg: user@aa.bb.cc
cert_file = "" # eg: /etc/ssl/server.crt
key_file = "" # eg: /etc/ssl/server.key
upstream = "" # eg: 127.0.0.1:8080
+7 -6
View File
@@ -4,11 +4,12 @@ go 1.14
require (
github.com/krolaw/dhcp4 v0.0.0-20190909130307-a50d88189771
github.com/libp2p/go-reuseport v0.0.1
github.com/miekg/dns v1.1.29
github.com/pelletier/go-toml v1.7.0
github.com/libp2p/go-reuseport v0.0.2
github.com/miekg/dns v1.1.30
github.com/pelletier/go-toml v1.8.0
github.com/pkg/errors v0.9.1
github.com/wweir/utils v0.0.0-20200401081845-fc35af3737dc
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4
github.com/wweir/util-go/log v0.0.0-20200701032032-3cff7b4a46ea
github.com/wweir/util-go/mem v0.0.0-20200701032032-3cff7b4a46ea
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
)
+21 -43
View File
@@ -1,64 +1,47 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/guregu/null v3.4.0+incompatible h1:a4mw37gBO7ypcBlTJeZGuMpSxxFTV9qFfFKgWxQSGaM=
github.com/guregu/null v3.4.0+incompatible/go.mod h1:ePGpQaN9cw0tj45IR5E5ehMvsFlLlQZAkkOXZurJ3NM=
github.com/influxdata/influxdb v1.7.9/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/krolaw/dhcp4 v0.0.0-20190909130307-a50d88189771 h1:t2c2B9g1ZVhMYduqmANSEGVD3/1WlsrEYNPtVoFlENk=
github.com/krolaw/dhcp4 v0.0.0-20190909130307-a50d88189771/go.mod h1:0AqAH3ZogsCrvrtUpvc6EtVKbc3w6xwZhkvGLuqyi3o=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
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/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/miekg/dns v1.1.29 h1:xHBEhR+t5RzcFJjBLJlax2daXOrTYtr9z4WdKEfWFzg=
github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI=
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
github.com/libp2p/go-reuseport v0.0.2 h1:XSG94b1FJfGA01BUrT82imejHQyTxO4jEWqheyCXYvU=
github.com/libp2p/go-reuseport v0.0.2/go.mod h1:SPD+5RwGC7rcnzngoYC86GjPzjSywuQyMVAheVBD9nQ=
github.com/miekg/dns v1.1.30 h1:Qww6FseFn8PRfw07jueqIXqodm0JKiiKuK0DeXSqfyo=
github.com/miekg/dns v1.1.30/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw=
github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/ulule/deepcopier v0.0.0-20200117111125-792cfb847af8 h1:iCslye9fWwp1ExDu06BcKM8/gjDRAlX9DBL+T8CjuWU=
github.com/ulule/deepcopier v0.0.0-20200117111125-792cfb847af8/go.mod h1:wUZg40sMUnY+1FU5F9rZwwCruLb8h1bHF8HzI09kgok=
github.com/wweir/utils v0.0.0-20200401081845-fc35af3737dc h1:XvNZju71btZ0/hammNDOu0Jqv7qi0kR0x9KaXYRKOAY=
github.com/wweir/utils v0.0.0-20200401081845-fc35af3737dc/go.mod h1:5PfQ9g8nWDRNkzu2gyjtFo/Xo6+s5ZCpulQADjvGz7M=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6 h1:TtyC78WMafNW8QFfv3TeP3yWNDG+uxNkk9vOrnDu6JA=
github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6/go.mod h1:h8272+G2omSmi30fBXiZDMkmHuOgonplfKIKjQWzlfs=
github.com/wweir/util-go v0.0.0-20200701032032-3cff7b4a46ea h1:V/bIKmS5Bv4zMwQ5qE7ugJiHpcAVFnAxvxRbb7OCwug=
github.com/wweir/util-go/log v0.0.0-20200701032032-3cff7b4a46ea h1:IlO7d9R0I/l2syxJkx4/PURW9yVf4hy/Qf2IzdR4y38=
github.com/wweir/util-go/log v0.0.0-20200701032032-3cff7b4a46ea/go.mod h1:OObmMboiahxgJ1P3twG+AN8EAZ/wz14vstI4E5kaZzI=
github.com/wweir/util-go/mem v0.0.0-20200701032032-3cff7b4a46ea h1:nXgUp7CflDJnuR+zd43DHKxRA/hvuMkFtueSRLY7mEc=
github.com/wweir/util-go/mem v0.0.0-20200701032032-3cff7b4a46ea/go.mod h1:gp1gaDO1K4uV/B8NfrTjVim99Xq5xAmm1SHVamRsVW0=
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.14.1 h1:nYDKopTbvAPq/NrUVZwT15y2lpROBiLLyoRTbXOYWOo=
go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM=
go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 h1:bXoxMPcSLOq08zI3/c5dEBT6lE4eh+jOh886GHrn6V8=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg=
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
@@ -67,31 +50,26 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 h1:VvQyQJN0tSuecqgcIxMWnnfG5kSmgy9KZR9sW3W5QeA=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+8 -14
View File
@@ -19,13 +19,12 @@ func main() {
server.CertFile, server.KeyFile, server.CertEmail)
case client.Address != "":
route := &router.Route{
ProxyAddress: client.Address,
ProxyPassword: password,
DetectLevel: client.Router.DetectLevel,
DirectList: client.Router.DirectList,
ProxyList: client.Router.ProxyList,
PersistFn: conf.PersistRule,
route := router.NewRoute(client.Address, password, client.Router.DetectLevel,
client.Router.BlockList, client.Router.ProxyList, client.Router.DirectList,
conf.PersistRule)
if client.Socks5Proxy != "" {
go proxy.StartSocks5Proxy(client.Socks5Proxy, client.Address, []byte(password))
}
if client.HTTPProxy != "" {
@@ -33,15 +32,10 @@ func main() {
[]byte(password), route.GenProxyCheck(true))
}
enableDNSSolution := client.DNSServeIP != ""
if enableDNSSolution {
transport.SetDNS(nil, client.DNSUpstream)
go proxy.StartDNS(client.DNSServeIP, client.DNSUpstream,
route.GenProxyCheck(false))
}
transport.SetDNS(nil, client.DNSUpstream)
go proxy.StartDNS(client.DNSUpstream, route.GenProxyCheck(false))
proxy.StartClient(client.Address, password,
client.DNSServeIP, enableDNSSolution,
client.PortForward, route.GenProxyCheck(true))
default:
+10 -10
View File
@@ -8,7 +8,7 @@ import (
"github.com/miekg/dns"
"github.com/wweir/sower/dhcp"
"github.com/wweir/utils/log"
"github.com/wweir/util-go/log"
)
type msgCache struct {
@@ -18,12 +18,7 @@ type msgCache struct {
var cache sync.Map
func StartDNS(redirectIP, relayServer string, shouldProxy func(string) bool) {
serveIP := net.ParseIP(redirectIP)
if redirectIP == "" || serveIP.String() != redirectIP {
log.Fatalw("invalid listen ip", "ip", redirectIP)
}
func StartDNS(relayServer string, shouldProxy func(string) (bool, bool)) {
var err error
if relayServer, err = pickRelayAddr(relayServer); err != nil {
log.Fatalw("pick upstream dns server", "err", err)
@@ -47,8 +42,13 @@ func StartDNS(redirectIP, relayServer string, shouldProxy func(string) bool) {
domain = domain[:idx] // trim port
}
if shouldProxy(domain) {
w.WriteMsg(localA(r, domain, serveIP))
if isblock, isproxy := shouldProxy(domain); isblock {
m := new(dns.Msg)
m.SetReply(r)
w.WriteMsg(m)
} else if isproxy {
host, _, _ := net.SplitHostPort(w.LocalAddr().String())
w.WriteMsg(localA(r, domain, net.ParseIP(host)))
} else if val, ok := cache.Load(domain); ok && val.(*msgCache).After(time.Now()) {
msg := val.(*msgCache)
@@ -82,7 +82,7 @@ func StartDNS(redirectIP, relayServer string, shouldProxy func(string) bool) {
}
})
server := &dns.Server{Addr: net.JoinHostPort(redirectIP, "53"), Net: "udp"}
server := &dns.Server{Addr: ":53", Net: "udp"}
log.Infow("start dns", "addr", server.Addr)
log.Fatalw("dns serve fail", "err", server.ListenAndServe())
}
+5 -5
View File
@@ -10,20 +10,20 @@ import (
"github.com/wweir/sower/transport"
"github.com/wweir/sower/util"
"github.com/wweir/utils/log"
"github.com/wweir/util-go/log"
)
// StartHTTPProxy start http reverse proxy.
// The httputil.ReverseProxy do not supply enough support for https request.
func StartHTTPProxy(httpProxyAddr, serverAddr string, password []byte,
shouldProxy func(string) bool) {
shouldProxy func(string) (bool, bool)) {
proxy := httputil.ReverseProxy{
Director: func(r *http.Request) {},
Transport: &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
return transport.Dial(serverAddr, func(host string) (string, []byte) {
if shouldProxy(host) {
if _, ok := shouldProxy(host); ok {
return httpProxyAddr, password
}
return "", nil
@@ -51,7 +51,7 @@ func StartHTTPProxy(httpProxyAddr, serverAddr string, password []byte,
}
func httpsProxy(w http.ResponseWriter, r *http.Request,
serverAddr string, password []byte, shouldProxy func(string) bool) {
serverAddr string, password []byte, shouldProxy func(string) (bool, bool)) {
conn, _, err := w.(http.Hijacker).Hijack()
if err != nil {
@@ -68,7 +68,7 @@ func httpsProxy(w http.ResponseWriter, r *http.Request,
target, _ := util.WithDefaultPort(r.Host, "443")
rc, err := transport.Dial(target, func(host string) (string, []byte) {
if shouldProxy(host) {
if _, ok := shouldProxy(host); ok {
return serverAddr, password
}
return "", nil
+10 -13
View File
@@ -6,17 +6,17 @@ import (
"net/http"
"github.com/wweir/sower/transport"
"github.com/wweir/utils/log"
"github.com/wweir/util-go/log"
"golang.org/x/crypto/acme/autocert"
)
func StartClient(serverAddr, password, serveIP string, enableDNS bool,
forwards map[string]string, shouldProxy func(string) bool) {
func StartClient(serverAddr, password string,
forwards map[string]string, shouldProxy func(string) (bool, bool)) {
passwordData := []byte(password)
relayToRemote := func(lnAddr, target string,
parseFn func(net.Conn) (net.Conn, string, error),
shouldProxy func(string) bool) {
shouldProxy func(string) (bool, bool)) {
ln, err := net.Listen("tcp", lnAddr)
if err != nil {
@@ -41,14 +41,13 @@ func StartClient(serverAddr, password, serveIP string, enableDNS bool,
}
rc, err := transport.Dial(target, func(domain string) (string, []byte) {
if shouldProxy(domain) {
if _, ok := shouldProxy(domain); ok {
return serverAddr, passwordData
}
return "", nil
})
if err != nil {
host, _, _ := net.SplitHostPort(target)
log.Warnw("dial", "addr", target, "proxy", shouldProxy(host), "err", err)
log.Warnw("dial", "addr", target, "err", err)
return
}
defer rc.Close()
@@ -59,15 +58,13 @@ func StartClient(serverAddr, password, serveIP string, enableDNS bool,
}
for from, to := range forwards {
go relayToRemote(from, to, nil, func(string) bool { return true })
go relayToRemote(from, to, nil, func(string) (bool, bool) { return false, true })
}
if enableDNS {
go relayToRemote(net.JoinHostPort(serveIP, "http"), "", ParseHTTP, shouldProxy)
go relayToRemote(net.JoinHostPort(serveIP, "https"), "", ParseHTTPS, shouldProxy)
}
go relayToRemote(":http", "", ParseHTTP, shouldProxy)
go relayToRemote(":https", "", ParseHTTPS, shouldProxy)
log.Infow("start sower client", "dns solution", enableDNS, "forwards", forwards)
log.Infow("start sower client", "forwards", forwards)
select {}
}
+43
View File
@@ -0,0 +1,43 @@
package proxy
import (
"net"
"github.com/wweir/sower/transport"
"github.com/wweir/util-go/log"
)
func StartSocks5Proxy(listenAddr, serverAddr string, password []byte) {
ln, err := net.Listen("tcp", listenAddr)
if err != nil {
log.Fatalw("socks5 proxy", "addr", listenAddr, "err", err)
}
serveSocks5(ln, serverAddr, password)
}
func serveSocks5(ln net.Listener, serverAddr string, password []byte) {
conn, err := ln.Accept()
if err != nil {
log.Fatalw("socks5 proxy", "err", err)
}
go serveSocks5(ln, serverAddr, password)
tgtAddr, err := transport.ParseSocks5(conn)
if err != nil {
log.Errorw("socks5 proxy", "err", err)
return
}
rc, err := transport.Dial(tgtAddr, func(host string) (string, []byte) {
return serverAddr, password
})
if err != nil {
log.Errorw("socks5 proxy", "err", err)
return
}
relay(conn, rc)
conn.Close()
rc.Close()
}
+31 -21
View File
@@ -9,8 +9,8 @@ import (
"github.com/wweir/sower/transport"
"github.com/wweir/sower/util"
"github.com/wweir/utils/log"
"github.com/wweir/utils/mem"
"github.com/wweir/util-go/log"
"github.com/wweir/util-go/mem"
)
// Route implement a router for each request
@@ -18,27 +18,33 @@ type Route struct {
once sync.Once
cache *mem.Cache
ProxyAddress string
ProxyPassword string
password []byte
ProxyAddress string
password []byte
DetectLevel int // dynamic detect proxy level
DirectList []string
directRule *util.Node
ProxyList []string
blockRule *util.Node
proxyRule *util.Node
directRule *util.Node
PersistFn func(string)
}
// ShouldProxy check if the domain shoule request though proxy
func (r *Route) GenProxyCheck(sync bool) func(string) bool {
r.once.Do(func() {
r.cache = mem.New(4 * time.Hour)
r.password = []byte(r.ProxyPassword)
r.directRule = util.NewNodeFromRules(r.DirectList...)
r.proxyRule = util.NewNodeFromRules(r.ProxyList...)
})
func NewRoute(address, password string, detectLevel int,
blocklist, proxylist, directlist []string, persist func(string)) *Route {
return &Route{
cache: mem.New(4 * time.Hour),
ProxyAddress: address,
password: []byte(password),
DetectLevel: detectLevel,
blockRule: util.NewNodeFromRules(blocklist...),
proxyRule: util.NewNodeFromRules(proxylist...),
directRule: util.NewNodeFromRules(directlist...),
PersistFn: persist,
}
}
// ShouldProxy check if the domain shoule request though proxy
func (r *Route) GenProxyCheck(sync bool) func(string) (bool, bool) {
detect := func(domain string) bool {
go r.cache.Remember(r, domain)
return true
@@ -53,21 +59,25 @@ func (r *Route) GenProxyCheck(sync bool) func(string) bool {
}
}
return func(domain string) bool {
return func(domain string) (bool, bool) {
domain = strings.TrimSuffix(domain, ".")
// break deadlook, for wildcard
if sepCount := strings.Count(domain, "."); sepCount == 0 || sepCount >= 5 {
return false
return false, false
}
if r.blockRule.Match(domain) {
return true, false
}
if r.proxyRule.Match(domain) {
return true
return false, true
}
if r.directRule.Match(domain) {
return false
return false, false
}
return detect(domain)
return false, detect(domain)
}
}
-125
View File
@@ -1,125 +0,0 @@
package transport
import (
"encoding/binary"
"fmt"
"io"
"net"
"strings"
)
func IsSocks5Schema(addr string) (string, bool) {
if strings.HasPrefix(addr, "socks5://") {
return strings.TrimPrefix(addr, "socks5://"), true
}
if strings.HasPrefix(addr, "socks5h://") {
return strings.TrimPrefix(addr, "socks5h://"), true
}
return addr, false
}
func ToSocks5(c net.Conn, host string, port uint16) (net.Conn, error) {
return &conn{
init: make(chan struct{}),
Conn: c,
domain: host,
port: port,
}, nil
}
type conn struct {
init chan struct{}
domain string
port uint16
net.Conn
}
func (c *conn) Read(b []byte) (n int, err error) {
<-c.init
return c.Conn.Read(b)
}
func (c *conn) Write(b []byte) (n int, err error) {
select {
case <-c.init:
return c.Conn.Write(b)
default:
}
{
req := &authReq{
VER: 5,
NMETHODS: 1,
METHODS: [1]byte{0}, // NO AUTHENTICATION REQUIRED
}
if err := binary.Write(c.Conn, binary.BigEndian, req); err != nil {
return 0, err
}
}
{
resp := &authResp{}
if err := binary.Read(c.Conn, binary.BigEndian, resp); err != nil {
return 0, err
}
}
{
portBuf := make([]byte, 2)
binary.BigEndian.PutUint16(portBuf, c.port)
req := &request{
req: req{
VER: 5, // socks5
CMD: 1, // CONNECT
RSV: 0, // RESERVED
ATYP: 3, // DOMAINNAME
},
DST_ADDR: append([]byte{byte(len(c.domain))}, []byte(c.domain)...),
DST_PORT: portBuf,
}
if _, err := c.Conn.Write(req.Bytes()); err != nil {
return 0, err
}
}
{
resp := &response{}
if err := binary.Read(c.Conn, binary.BigEndian, &(resp.resp)); err != nil {
return 0, err
}
switch resp.REP {
case 0x00:
default:
return 0, fmt.Errorf("socks5 handshake fail, return code: %d", resp.REP)
}
switch resp.ATYP {
case 0x01: // IPv4
resp.DST_ADDR = make([]byte, net.IPv4len)
if _, err := io.ReadFull(c.Conn, resp.DST_ADDR); err != nil {
return 0, err
}
case 0x03: // domain name
if _, err := io.ReadFull(c.Conn, resp.DST_ADDR[:1]); err != nil {
return 0, err
}
if _, err := io.ReadFull(c.Conn, resp.DST_ADDR[1:1+int(resp.DST_ADDR[0])]); err != nil {
return 0, err
}
case 0x04:
resp.DST_ADDR = make([]byte, net.IPv6len)
if _, err := io.ReadFull(c.Conn, resp.DST_ADDR); err != nil {
return 0, err
}
}
resp.DST_PORT = make([]byte, 2)
if _, err := io.ReadFull(c.Conn, resp.DST_PORT); err != nil {
return 0, err
}
}
close(c.init)
return c.Conn.Write(b)
}
+124
View File
@@ -0,0 +1,124 @@
package transport
import (
"encoding/binary"
"net"
"strings"
"golang.org/x/xerrors"
)
func IsSocks5Schema(addr string) (string, bool) {
if strings.HasPrefix(addr, "socks5://") {
return strings.TrimPrefix(addr, "socks5://"), true
}
if strings.HasPrefix(addr, "socks5h://") {
return strings.TrimPrefix(addr, "socks5h://"), true
}
return addr, false
}
func ToSocks5(c net.Conn, host string, port uint16) (net.Conn, error) {
return &conn{
init: make(chan struct{}),
Conn: c,
domain: host,
port: port,
}, nil
}
type conn struct {
init chan struct{}
domain string
port uint16
net.Conn
}
func (c *conn) Read(b []byte) (n int, err error) {
select {
case <-c.init:
return c.Conn.Read(b)
default:
return 0, c.clientHandshake()
}
}
func (c *conn) Write(b []byte) (n int, err error) {
select {
case <-c.init:
return c.Conn.Write(b)
default:
return 0, c.clientHandshake()
}
}
func (c *conn) clientHandshake() error {
{
req := &authReq{
VER: 5,
NMETHODS: 1,
METHODS: [1]byte{0}, // NO AUTHENTICATION REQUIRED
}
if err := binary.Write(c.Conn, binary.BigEndian, req); err != nil {
return xerrors.New(err.Error())
}
}
{
resp := &authResp{}
if err := binary.Read(c.Conn, binary.BigEndian, resp); err != nil {
return xerrors.New(err.Error())
}
}
{
reqHead := requestHead{
VER: 5, // socks5
CMD: 1, // CONNECT
RSV: 0, // RESERVED
ATYP: 3, // DOMAINNAME
}
if err := binary.Write(c.Conn, binary.BigEndian, reqHead); err != nil {
return xerrors.New(err.Error())
}
buf := make([]byte, 0, 1 /*LEN*/ +len(c.domain)+2 /*PORT*/)
buf = append(buf, byte(len(c.domain)))
buf = append(buf, []byte(c.domain)...)
buf = append(buf, byte(c.port>>8), byte(c.port))
if _, err := c.Conn.Write(buf); err != nil {
return xerrors.New(err.Error())
}
}
{
head := replyHead{}
if err := binary.Read(c.Conn, binary.BigEndian, &head); err != nil {
return xerrors.New(err.Error())
}
switch head.REP {
case 0x00:
default:
return xerrors.Errorf("socks5 handshake fail, return code: %d", head.REP)
}
var bindAddr addrType
switch head.ATYP {
case 0x01: // IPv4
bindAddr = addrTypeIPv4{}
case 0x03: // domain name
bindAddr = addrTypeDomain{}
case 0x04: // IPv6
bindAddr = addrTypeIPv6{}
default:
return xerrors.New("invalid connect type")
}
if err := bindAddr.Fullfill(c.Conn); err != nil {
return xerrors.New(err.Error())
}
}
close(c.init)
return nil
}
+89 -18
View File
@@ -1,44 +1,115 @@
package transport
import (
"encoding/binary"
"io"
"net"
"strconv"
"golang.org/x/xerrors"
)
// https://tools.ietf.org/html/rfc1928
// 1. client send auth request
type authReq struct {
VER byte
NMETHODS byte
METHODS [1]byte // 1 to 255, fix to no authentication
}
// 2. server response auth request
type authResp struct {
VER byte
METHOD byte
}
type request struct {
req
DST_ADDR []byte // first byte is length
DST_PORT []byte // two bytes
}
type req struct {
// 3. client request with target address
type requestHead struct {
VER byte
CMD byte
RSV byte
ATYP byte
}
func (r *request) Bytes() []byte {
out := []byte{r.VER, r.CMD, r.RSV, r.ATYP}
out = append(out, r.DST_ADDR...)
return append(out, r.DST_PORT...)
}
type response struct {
resp
DST_ADDR []byte // first byte is length
DST_PORT []byte // two bytes
}
type resp struct {
// 4. server response with the address that assigned to connect to target address
type replyHead struct {
VER byte
REP byte
RSV byte
ATYP byte
}
type addrType interface {
Fullfill(r io.Reader) error
String() string
}
// ATYP:
// 0x01 -> net.IPv4len
// 0x03 -> first byte is length
// 0x04 -> net.IPv6len
type addrTypeIPv4 struct {
DST_ADDR [4]byte
DST_PORT uint16
}
func (a addrTypeIPv4) Fullfill(r io.Reader) error {
return binary.Read(r, binary.BigEndian, &a)
}
func (a addrTypeIPv4) String() string {
return net.JoinHostPort(
net.IP(a.DST_ADDR[:]).String(),
strconv.FormatUint(uint64(a.DST_PORT), 10),
)
}
type addrTypeDomain struct {
DST_ADDR_LEN uint8
DST_ADDR []byte
DST_PORT uint16
}
func (a addrTypeDomain) Fullfill(r io.Reader) error {
buf := make([]byte, 256)
// domain length
if _, err := io.ReadFull(r, buf[:1]); err != nil {
return xerrors.New(err.Error())
}
a.DST_ADDR_LEN = uint8(buf[0])
// domain
if _, err := io.ReadFull(r, buf[:int(buf[0])]); err != nil {
return xerrors.New(err.Error())
}
a.DST_ADDR = buf[:int(buf[0])]
// port
if _, err := io.ReadFull(r, buf[:2]); err != nil {
return xerrors.New(err.Error())
}
a.DST_PORT = binary.BigEndian.Uint16(buf[:2])
return nil
}
func (a addrTypeDomain) String() string {
return net.JoinHostPort(
net.IP(a.DST_ADDR[:]).String(),
strconv.FormatUint(uint64(a.DST_PORT), 10),
)
}
type addrTypeIPv6 struct {
DST_ADDR [16]byte
DST_PORT uint16
}
func (a addrTypeIPv6) Fullfill(r io.Reader) error {
return binary.Read(r, binary.BigEndian, &a)
}
func (a addrTypeIPv6) String() string {
return net.JoinHostPort(
net.IP(a.DST_ADDR[:]).String(),
strconv.FormatUint(uint64(a.DST_PORT), 10),
)
}
+74
View File
@@ -0,0 +1,74 @@
package transport
import (
"encoding/binary"
"net"
"golang.org/x/xerrors"
)
func ParseSocks5(conn net.Conn) (tgtaddr string, err error) {
{
authReq := new(authReq)
if err := binary.Read(conn, binary.BigEndian, authReq); err != nil {
return "", xerrors.New(err.Error())
}
if authReq.VER != 5 || // socks5
authReq.NMETHODS != 1 ||
authReq.METHODS[0] != 0 { // NO_AUTH
return "", xerrors.New("invalid socks5 auth method")
}
}
{
if err := binary.Write(conn, binary.BigEndian, &authResp{
VER: 5,
METHOD: 1,
}); err != nil {
return "", xerrors.New(err.Error())
}
}
{
head := &requestHead{}
if err := binary.Read(conn, binary.BigEndian, head); err != nil {
return "", xerrors.New(err.Error())
}
if head.VER != 5 ||
head.CMD != 1 {
return "", xerrors.New("invalid socks5 connect request")
}
var addr addrType
switch head.ATYP {
case 0x01: // IPv4
addr = addrTypeIPv4{}
case 0x03: // domain name
addr = addrTypeDomain{}
case 0x04: // IPv6
addr = addrTypeIPv6{}
default:
return "", xerrors.New("invalid connect type")
}
if err := addr.Fullfill(conn); err != nil {
return "", xerrors.New(err.Error())
}
tgtaddr = addr.String()
}
{
if err := binary.Write(conn, binary.BigEndian, &replyHead{
VER: 5,
REP: 0,
RSV: 0,
ATYP: 1,
}); err != nil {
return "", xerrors.New(err.Error())
}
// FIXME: return the real address
if _, err := conn.Write(make([]byte, 6)); err != nil {
return "", xerrors.New(err.Error())
}
}
return tgtaddr, nil
}
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"strconv"
"github.com/wweir/sower/dhcp"
"github.com/wweir/utils/log"
"github.com/wweir/util-go/log"
)
var (
+1 -1
View File
@@ -49,7 +49,7 @@ func (n *node) add(secs []string) {
case 0:
return
case 1:
n.node[secs[length-1]] = &node{node: map[string]*node{"": &node{}}}
n.node[secs[length-1]] = &node{node: map[string]*node{"": {}}}
default:
sec := secs[length-1]
if sec == "**" {