From 59dfa934a2a3bbdb7cfae74e5788a2f79ddc8485 Mon Sep 17 00:00:00 2001 From: wweir Date: Thu, 29 Jul 2021 17:50:39 +0800 Subject: [PATCH] optimize code, comment / log / flag --- cmd/sower/main.go | 57 +++++++++++++++++++++++--------------- pkg/deferlog/init.go | 6 ++-- router/country.go | 4 ++- router/dns.go | 10 +++---- router/ping.go | 9 ++++-- router/router.go | 2 +- transport/socks5/socks5.go | 14 ++++------ transport/sower/sower.go | 2 +- 8 files changed, 61 insertions(+), 43 deletions(-) diff --git a/cmd/sower/main.go b/cmd/sower/main.go index eb4ff77..2564aaa 100644 --- a/cmd/sower/main.go +++ b/cmd/sower/main.go @@ -26,39 +26,43 @@ var ( conf = struct { Remote struct { - Type string `default:"sower" required:"true" usage:"remote proxy protocol, optional: sower/trojan/socks5"` - Addr string `required:"true" usage:"remote proxy address, eg: proxy.com/127.0.0.1:7890"` + Type string `default:"sower" required:"true" usage:"optional: sower/trojan/socks5"` + Addr string `required:"true" usage:"proxy address, eg: proxy.com/127.0.0.1:7890"` Password string `usage:"remote proxy password"` } DNS struct { - Disable bool `usage:"disable DNS proxy"` + Disable bool `default:"false" usage:"disable DNS proxy"` Serve string `default:"127.0.0.1" required:"true" usage:"dns server ip"` Fallback string `default:"223.5.5.5" usage:"fallback dns server"` } Socks5 struct { - Disable bool `usage:"disable sock5 proxy"` + Disable bool `default:"false" usage:"disable sock5 proxy"` Addr string `default:":1080" usage:"socks5 listen address"` } `flag:"socks5"` Router struct { Block struct { - File string `usage:"block list file, parsed as '**.line_text'"` - Rules []string `usage:"block list rules"` + File string `usage:"block list file, local file or remote"` + FilePrefix string `default:"**." usage:"parsed as 'prefix.line_text'"` + Rules []string `usage:"block list rules"` } Direct struct { - File string `usage:"direct list file, parsed as '**.line_text'"` - Rules []string `usage:"direct list rules"` + File string `usage:"direct list file, local file or remote"` + FilePrefix string `default:"**." usage:"parsed as 'prefix.line_text'"` + Rules []string `usage:"direct list rules"` } Proxy struct { - File string `usage:"proxy list file, parsed as '**.line_text'"` - Rules []string `usage:"proxy list rules"` + File string `usage:"proxy list file, local file or remote"` + FilePrefix string `default:"**." usage:"parsed as 'prefix.line_text'"` + Rules []string `usage:"proxy list rules"` } Country struct { - MMDB string `usage:"mmdb file"` - File string `usage:"CIDR block list file"` - Rules []string `usage:"CIDR list rules"` + MMDB string `usage:"mmdb file"` + File string `usage:"CIDR block list file, local file or remote"` + FilePrefix string `default:"" usage:"parsed as 'prefix.line_text'"` + Rules []string `usage:"CIDR list rules"` } } }{} @@ -67,7 +71,7 @@ var ( func init() { if err := aconfig.LoaderFor(&conf, aconfig.Config{ AllowUnknownFields: true, - FileFlag: "conf", + FileFlag: "f", FileDecoders: map[string]aconfig.FileDecoder{ ".yml": aconfigyaml.New(), ".yaml": aconfigyaml.New(), @@ -76,7 +80,7 @@ func init() { }, }).Load(); err != nil { log.Fatal().Err(err). - Interface("conf", conf). + Interface("config", conf). Msg("Load config") } @@ -113,10 +117,11 @@ func main() { } go ServeHTTPS(lnHTTPS, r) + addr := net.JoinHostPort(conf.DNS.Serve, "53") log.Info(). - Str("ip", conf.DNS.Serve). + Str("listen_on", addr). Msg("DNS proxy started") - if err := dns.ListenAndServe(net.JoinHostPort(conf.DNS.Serve, "53"), "udp", r); err != nil { + if err := dns.ListenAndServe(addr, "udp", r); err != nil { log.Fatal().Err(err).Msg("serve dns") } }() @@ -132,14 +137,18 @@ func main() { log.Fatal().Err(err).Msg("listen port") } log.Info().Msgf("SOCKS5 proxy listening on %s", conf.Socks5.Addr) - ServeSocks5(ln, r) + go ServeSocks5(ln, r) }() start := time.Now() - conf.Router.Block.Rules = append(conf.Router.Block.Rules, loadRules(proxtDial, conf.Router.Block.File, "**.")...) - conf.Router.Direct.Rules = append(conf.Router.Direct.Rules, loadRules(proxtDial, conf.Router.Direct.File, "**.")...) - conf.Router.Proxy.Rules = append(conf.Router.Proxy.Rules, loadRules(proxtDial, conf.Router.Proxy.File, "**.")...) - conf.Router.Country.Rules = append(conf.Router.Country.Rules, loadRules(proxtDial, conf.Router.Country.File, "")...) + conf.Router.Block.Rules = append(conf.Router.Block.Rules, + loadRules(proxtDial, conf.Router.Block.File, conf.Router.Block.FilePrefix)...) + conf.Router.Direct.Rules = append(conf.Router.Direct.Rules, + loadRules(proxtDial, conf.Router.Direct.File, conf.Router.Direct.FilePrefix)...) + conf.Router.Proxy.Rules = append(conf.Router.Proxy.Rules, + loadRules(proxtDial, conf.Router.Proxy.File, conf.Router.Proxy.FilePrefix)...) + conf.Router.Country.Rules = append(conf.Router.Country.Rules, + loadRules(proxtDial, conf.Router.Country.File, conf.Router.Country.FilePrefix)...) r.SetRules(conf.Router.Block.Rules, conf.Router.Direct.Rules, conf.Router.Proxy.Rules, conf.Router.Country.Rules) @@ -156,6 +165,7 @@ func main() { func loadRules(proxyDial router.ProxyDialFn, file, linePrefix string) []string { var loadFn func() (io.ReadCloser, error) if _, err := url.Parse(file); err == nil { + // load rule file from remote by HTTP client := &http.Client{ Transport: &http.Transport{ Dial: func(network, addr string) (net.Conn, error) { @@ -181,11 +191,13 @@ func loadRules(proxyDial router.ProxyDialFn, file, linePrefix string) []string { } } else { + // load rule file from local file loadFn = func() (io.ReadCloser, error) { return os.Open(file) } } + // load rule file, retry 10 times rc, err := loadFn() for i := time.Duration(1); i < 10; i++ { if err == nil { @@ -203,6 +215,7 @@ func loadRules(proxyDial router.ProxyDialFn, file, linePrefix string) []string { } defer rc.Close() + // parse rule file into rule tree var lines []string br := bufio.NewReader(rc) for { diff --git a/pkg/deferlog/init.go b/pkg/deferlog/init.go index 2877a0a..4195003 100644 --- a/pkg/deferlog/init.go +++ b/pkg/deferlog/init.go @@ -12,7 +12,7 @@ import ( ) var StructLogger = zerolog.New(os.Stdout). - With().Caller().Timestamp().Logger() + With().Timestamp().Logger() var ConsoleLogger = zerolog.New(zerolog.ConsoleWriter{ Out: os.Stdout, @@ -27,7 +27,7 @@ var ConsoleLogger = zerolog.New(zerolog.ConsoleWriter{ } return caller }, -}).With().Timestamp().Caller().Logger() +}).With().Timestamp().Logger() func init() { zerolog.ErrorStackMarshaler = func(err error) interface{} { @@ -46,6 +46,6 @@ func init() { } func SetDefaultLogger(logger zerolog.Logger, deferSkip int, logLevel zerolog.Level) { - log.Logger = logger.Level(logLevel) + log.Logger = logger.With().Caller().Logger().Level(logLevel) Logger = logger.With().CallerWithSkipFrameCount(deferSkip + 2).Logger().Level(logLevel) } diff --git a/router/country.go b/router/country.go index 68607b8..01521ab 100644 --- a/router/country.go +++ b/router/country.go @@ -9,7 +9,7 @@ import ( ) func (r *Router) localSite(domain string) bool { - + // parse domain to IP ip := net.ParseIP(domain) if ip == nil { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) @@ -27,12 +27,14 @@ func (r *Router) localSite(domain string) bool { ip = ips[0] } + // CIDR match for _, cidr := range r.country.cidrs { if cidr.Contains(ip) { return true } } + // MMDB match CN if r.country.Reader != nil { city, err := r.country.City(ip) if err != nil { diff --git a/router/dns.go b/router/dns.go index e1a236f..0087412 100644 --- a/router/dns.go +++ b/router/dns.go @@ -11,32 +11,32 @@ import ( func (r *Router) ServeDNS(w dns.ResponseWriter, req *dns.Msg) { // https://stackoverflow.com/questions/4082081/requesting-a-and-aaaa-records-in-single-dns-query/4083071#4083071 if len(req.Question) == 0 { - w.WriteMsg(r.dnsFail(req, dns.RcodeFormatError)) + _ = w.WriteMsg(r.dnsFail(req, dns.RcodeFormatError)) return } domain := req.Question[0].Name switch { case r.blockRule.Match(domain): - w.WriteMsg(r.dnsFail(req, dns.RcodeNameError)) + _ = w.WriteMsg(r.dnsFail(req, dns.RcodeNameError)) return case r.directRule.Match(domain): case r.proxyRule.Match(domain): - w.WriteMsg(r.dnsProxyA(domain, r.dns.serveIP, req)) + _ = w.WriteMsg(r.dnsProxyA(domain, r.dns.serveIP, req)) return } c := &dnsCache{Router: r, Req: req} if err := r.dns.cache.Remember(c, req.Question[0].String()); err != nil { - w.WriteMsg(r.dnsFail(req, dns.RcodeServerFailure)) + _ = w.WriteMsg(r.dnsFail(req, dns.RcodeServerFailure)) return } c.Resp.SetReply(req) c.Resp.Compress = true - w.WriteMsg(c.Resp) + _ = w.WriteMsg(c.Resp) } func (r *Router) dnsFail(req *dns.Msg, rcode int) *dns.Msg { diff --git a/router/ping.go b/router/ping.go index c3f6d93..8ef6680 100644 --- a/router/ping.go +++ b/router/ping.go @@ -4,6 +4,8 @@ import ( "net" "net/http" "time" + + "github.com/wweir/sower/pkg/deferlog" ) var pingClient = http.Client{ @@ -19,7 +21,7 @@ func (r *Router) isAccess(domain string, port uint16) bool { } p := &ping{} - r.accessCache.Remember(p, domain) + _ = r.accessCache.Remember(p, domain) return p.isAccess } @@ -28,7 +30,10 @@ type ping struct { } func (p *ping) Fulfill(key string) error { - _, err := http.Head(net.JoinHostPort(key, "80")) + _, err := pingClient.Head(net.JoinHostPort(key, "80")) + deferlog.Std.DebugWarn(err). + Str("domain", key). + Msg("detect if site is accessible") p.isAccess = (err == nil) return nil } diff --git a/router/router.go b/router/router.go index 2974181..11761fb 100644 --- a/router/router.go +++ b/router/router.go @@ -130,7 +130,7 @@ func (r *Router) ProxyHandle(conn net.Conn, domain string, port uint16) error { start := time.Now() rc, err := r.ProxyDial("tcp", domain, port) if err != nil { - return errors.Wrapf(err, "dial proxy to (%s:%d), spend (%s)", domain, port, time.Since(start)) + return errors.Wrapf(err, "proxy dial (%s:%d), spend (%s)", domain, port, time.Since(start)) } defer rc.Close() diff --git a/transport/socks5/socks5.go b/transport/socks5/socks5.go index c7d8c7f..1451472 100644 --- a/transport/socks5/socks5.go +++ b/transport/socks5/socks5.go @@ -22,8 +22,7 @@ func (h *AddrHead) String() string { // Socks5 is a SOCKS5 proxy. It implements the teeconn.Conn interface. // It is used to be a second relay of other proxy tools. // user -> sower -socks5-> third-party proxy -> target -type Socks5 struct { -} +type Socks5 struct{} func New() *Socks5 { return &Socks5{} @@ -33,7 +32,7 @@ var noAuthResp = authResp{VER: 5, METHOD: 0} var succHeadResp = respHead{VER: 5, REP: 0, RSV: 0, ATYP: 1} func (s *Socks5) Unwrap(conn net.Conn) (net.Addr, error) { - { + { //auth auth := new(authReq) if err := auth.Fulfill(conn); err != nil && !auth.IsValid() { return nil, errors.Wrap(err, "read auth") @@ -45,7 +44,7 @@ func (s *Socks5) Unwrap(conn net.Conn) (net.Addr, error) { } var addr addrType - { + { // head head := new(reqHead) if err := binary.Read(conn, binary.BigEndian, head); err != nil || !head.IsValid() { return nil, errors.Wrap(err, "read head") @@ -80,10 +79,10 @@ var noAuthReq = struct { NMETHODS uint8 METHODS byte }{5, 1, 0} -var domainHead = reqHead{VER: 5, CMD: 1, RSV: 0, ATYP: 0x03} +var domainHead = reqHead{VER: 5, CMD: 1, RSV: 0, ATYP: 3} func (s *Socks5) Wrap(conn net.Conn, tgtHost string, tgtPort uint16) error { - { + { // auth if err := binary.Write(conn, binary.BigEndian, &noAuthReq); err != nil { return errors.WithStack(err) } @@ -93,8 +92,7 @@ func (s *Socks5) Wrap(conn net.Conn, tgtHost string, tgtPort uint16) error { return errors.WithStack(err) } } - - { + { // head buf := bytes.NewBuffer(make([]byte, 0, binary.Size(domainHead)+1+len(tgtHost)+2)) _ = binary.Write(buf, binary.BigEndian, domainHead) buf.WriteByte(uint8(len(tgtHost))) diff --git a/transport/sower/sower.go b/transport/sower/sower.go index 4b5839f..95db105 100644 --- a/transport/sower/sower.go +++ b/transport/sower/sower.go @@ -48,7 +48,7 @@ func (s *Sower) Unwrap(conn net.Conn) (net.Addr, error) { } h := &Head{} - binary.Read(bytes.NewReader(buf), binary.BigEndian, h) + _ = binary.Read(bytes.NewReader(buf), binary.BigEndian, h) switch h.Cmd { case 0x80: default: