optimize code, comment / log / flag

This commit is contained in:
wweir
2021-07-29 19:06:34 +08:00
parent 8bfb26ba3f
commit 59dfa934a2
8 changed files with 61 additions and 43 deletions
+35 -22
View File
@@ -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 {
+3 -3
View File
@@ -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)
}
+3 -1
View File
@@ -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 {
+5 -5
View File
@@ -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 {
+7 -2
View File
@@ -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
}
+1 -1
View File
@@ -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()
+6 -8
View File
@@ -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)))
+1 -1
View File
@@ -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: