mirror of
https://github.com/wweir/sower.git
synced 2024-04-21 12:42:15 +00:00
optimize code, comment / log / flag
This commit is contained in:
+35
-22
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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()
|
||||
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user