From edcb21236a75e05b24625501214fe25a3feebc36 Mon Sep 17 00:00:00 2001 From: nadoo <287492+nadoo@users.noreply.github.com> Date: Wed, 18 Sep 2019 19:40:14 +0800 Subject: [PATCH] proxy: add a new interface proxy to distinguish client and server --- dns/client.go | 10 +-- dns/server.go | 4 +- main.go | 12 +-- proxy/dialer.go | 15 ++-- proxy/direct.go | 7 +- proxy/http/http.go | 33 ++++----- proxy/kcp/kcp.go | 43 ++++++----- proxy/mixed/mixed.go | 24 +++--- proxy/obfs/obfs.go | 15 ++-- proxy/proxy.go | 15 ++++ proxy/redir/redir_linux.go | 24 +++--- proxy/reject/reject.go | 13 ++-- proxy/server.go | 8 +- proxy/socks5/socks5.go | 57 +++++++------- proxy/ss/ss.go | 41 +++++------ proxy/ssr/ssr.go | 31 ++++---- proxy/tcptun/tcptun.go | 22 +++--- proxy/tls/tls.go | 42 +++++------ proxy/tproxy/tproxy_linux.go | 18 ++--- proxy/udptun/udptun.go | 22 +++--- proxy/unix/unix.go | 34 ++++----- proxy/uottun/uottun.go | 22 +++--- proxy/vmess/vmess.go | 16 ++-- proxy/ws/ws.go | 22 +++--- rule/rule.go | 74 ++++++++++--------- strategy/forward.go | 6 +- strategy/strategy.go | 139 ++++++++++++++++------------------- 27 files changed, 371 insertions(+), 398 deletions(-) create mode 100644 proxy/proxy.go diff --git a/dns/client.go b/dns/client.go index f12351c..2fc1afc 100644 --- a/dns/client.go +++ b/dns/client.go @@ -28,7 +28,7 @@ type Config struct { // Client is a dns client struct. type Client struct { - dialer proxy.Dialer + proxy proxy.Proxy cache *Cache config *Config upServers []string @@ -37,9 +37,9 @@ type Client struct { } // NewClient returns a new dns client. -func NewClient(dialer proxy.Dialer, config *Config) (*Client, error) { +func NewClient(proxy proxy.Proxy, config *Config) (*Client, error) { c := &Client{ - dialer: dialer, + proxy: proxy, cache: NewCache(), config: config, upServers: config.Servers, @@ -126,7 +126,7 @@ func (c *Client) Exchange(reqBytes []byte, clientAddr string, preferTCP bool) ([ func (c *Client) exchange(qname string, reqBytes []byte, preferTCP bool) (server, network string, respBytes []byte, err error) { // use tcp to connect upstream server default network = "tcp" - dialer := c.dialer.NextDialer(qname + ":53") + dialer := c.proxy.NextDialer(qname + ":53") // if we are resolving the dialer's domain, then use Direct to avoid denpency loop // TODO: dialer.Addr() == "reject", tricky @@ -143,7 +143,7 @@ func (c *Client) exchange(qname string, reqBytes []byte, preferTCP bool) (server servers := c.GetServers(qname) for _, server = range servers { var rc net.Conn - rc, _, err = dialer.Dial(network, server) + rc, err = dialer.Dial(network, server) if err != nil { log.F("[dns] failed to connect to server %v: %v", server, err) continue diff --git a/dns/server.go b/dns/server.go index ffddc39..542db4f 100644 --- a/dns/server.go +++ b/dns/server.go @@ -22,8 +22,8 @@ type Server struct { } // NewServer returns a new dns server. -func NewServer(addr string, dialer proxy.Dialer, config *Config) (*Server, error) { - c, err := NewClient(dialer, config) +func NewServer(addr string, proxy proxy.Proxy, config *Config) (*Server, error) { + c, err := NewClient(proxy, config) s := &Server{ addr: addr, Client: c, diff --git a/main.go b/main.go index 44f1f77..5a2ae47 100644 --- a/main.go +++ b/main.go @@ -42,15 +42,15 @@ func main() { } } - // global rule dialer - dialer := rule.NewDialer(conf.rules, strategy.NewDialer(conf.Forward, &conf.StrategyConfig)) + // global rule proxy + p := rule.NewProxy(conf.rules, strategy.NewProxy(conf.Forward, &conf.StrategyConfig)) // ipset manager ipsetM, _ := ipset.NewManager(conf.rules) // check and setup dns server if conf.DNS != "" { - d, err := dns.NewServer(conf.DNS, dialer, &conf.DNSConfig) + d, err := dns.NewServer(conf.DNS, p, &conf.DNSConfig) if err != nil { log.Fatal(err) } @@ -65,7 +65,7 @@ func main() { } // add a handler to update proxy rules when a domain resolved - d.AddHandler(dialer.AddDomainIP) + d.AddHandler(p.AddDomainIP) if ipsetM != nil { d.AddHandler(ipsetM.AddDomainIP) } @@ -74,11 +74,11 @@ func main() { } // enable checkers - dialer.Check() + p.Check() // Proxy Servers for _, listen := range conf.Listen { - local, err := proxy.ServerFromURL(listen, dialer) + local, err := proxy.ServerFromURL(listen, p) if err != nil { log.Fatal(err) } diff --git a/proxy/dialer.go b/proxy/dialer.go index 08d4171..ec5df2f 100644 --- a/proxy/dialer.go +++ b/proxy/dialer.go @@ -9,19 +9,16 @@ import ( "github.com/nadoo/glider/common/log" ) -// Dialer means to establish a connection and relay it. +// Dialer is used to create connection. type Dialer interface { - // Addr() + // Addr is the dialer's addr Addr() string - // Dial connects to the given address via the proxy. - Dial(network, addr string) (c net.Conn, proxy string, err error) + // Dial connects to the given address + Dial(network, addr string) (c net.Conn, err error) - // DialUDP connects to the given address via the proxy. + // DialUDP connects to the given address DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) - - // Get the dialer by dstAddr - NextDialer(dstAddr string) Dialer } // DialerCreator is a function to create dialers. @@ -31,7 +28,7 @@ var ( dialerMap = make(map[string]DialerCreator) ) -// RegisterDialer is used to register a dialer +// RegisterDialer is used to register a dialer. func RegisterDialer(name string, c DialerCreator) { dialerMap[name] = c } diff --git a/proxy/direct.go b/proxy/direct.go index e553ccf..5561376 100644 --- a/proxy/direct.go +++ b/proxy/direct.go @@ -39,7 +39,7 @@ func NewDirect(intface string) (*Direct, error) { func (d *Direct) Addr() string { return "DIRECT" } // Dial connects to the address addr on the network net -func (d *Direct) Dial(network, addr string) (c net.Conn, p string, err error) { +func (d *Direct) Dial(network, addr string) (c net.Conn, err error) { if d.iface == nil || d.ip != nil { c, err = dial(network, addr, d.ip) if err == nil { @@ -60,7 +60,7 @@ func (d *Direct) Dial(network, addr string) (c net.Conn, p string, err error) { err = errors.New("dial failed, maybe the interface link is down, please check it") } - return c, "DIRECT", err + return c, err } func dial(network, addr string, localIP net.IP) (net.Conn, error) { @@ -107,9 +107,6 @@ func (d *Direct) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) return pc, uAddr, err } -// NextDialer returns the next dialer -func (d *Direct) NextDialer(dstAddr string) Dialer { return d } - // IFaceIPs returns ip addresses according to the specified interface func (d *Direct) IFaceIPs() (ips []net.IP) { ipnets, err := d.iface.Addrs() diff --git a/proxy/http/http.go b/proxy/http/http.go index ab29634..61f12cc 100644 --- a/proxy/http/http.go +++ b/proxy/http/http.go @@ -24,6 +24,7 @@ import ( // HTTP struct type HTTP struct { dialer proxy.Dialer + proxy proxy.Proxy addr string user string password string @@ -36,7 +37,7 @@ func init() { } // NewHTTP returns a http proxy -func NewHTTP(s string, dialer proxy.Dialer) (*HTTP, error) { +func NewHTTP(s string, d proxy.Dialer, p proxy.Proxy) (*HTTP, error) { u, err := url.Parse(s) if err != nil { log.F("parse err: %s", err) @@ -48,7 +49,8 @@ func NewHTTP(s string, dialer proxy.Dialer) (*HTTP, error) { pass, _ := u.User.Password() h := &HTTP{ - dialer: dialer, + dialer: d, + proxy: p, addr: addr, user: user, password: pass, @@ -64,13 +66,13 @@ func NewHTTP(s string, dialer proxy.Dialer) (*HTTP, error) { } // NewHTTPDialer returns a http proxy dialer -func NewHTTPDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { - return NewHTTP(s, dialer) +func NewHTTPDialer(s string, d proxy.Dialer) (proxy.Dialer, error) { + return NewHTTP(s, d, nil) } // NewHTTPServer returns a http proxy server -func NewHTTPServer(s string, dialer proxy.Dialer) (proxy.Server, error) { - return NewHTTP(s, dialer) +func NewHTTPServer(s string, p proxy.Proxy) (proxy.Server, error) { + return NewHTTP(s, nil, p) } // ListenAndServe . @@ -142,7 +144,7 @@ func (s *HTTP) Serve(c net.Conn) { tgt += ":80" } - rc, p, err := s.dialer.Dial("tcp", tgt) + rc, p, err := s.proxy.Dial("tcp", tgt) if err != nil { fmt.Fprintf(c, "%s 502 ERROR\r\n\r\n", proto) log.F("[http] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p) @@ -200,7 +202,7 @@ func (s *HTTP) Serve(c net.Conn) { } func (s *HTTP) servHTTPS(method, requestURI, proto string, c net.Conn) { - rc, p, err := s.dialer.Dial("tcp", requestURI) + rc, p, err := s.proxy.Dial("tcp", requestURI) if err != nil { c.Write([]byte(proto)) c.Write([]byte(" 502 ERROR\r\n\r\n")) @@ -229,15 +231,12 @@ func (s *HTTP) Addr() string { return s.addr } -// NextDialer returns the next dialer -func (s *HTTP) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) } - // Dial connects to the address addr on the network net via the proxy -func (s *HTTP) Dial(network, addr string) (net.Conn, string, error) { - rc, p, err := s.dialer.Dial(network, s.addr) +func (s *HTTP) Dial(network, addr string) (net.Conn, error) { + rc, err := s.dialer.Dial(network, s.addr) if err != nil { log.F("[http] dial to %s error: %s", s.addr, err) - return nil, p, err + return nil, err } var buf bytes.Buffer @@ -254,7 +253,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, string, error) { buf.Write([]byte("\r\n")) _, err = rc.Write(buf.Bytes()) if err != nil { - return nil, p, err + return nil, err } c := conn.NewConn(rc) @@ -262,7 +261,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, string, error) { _, code, _, ok := parseFirstLine(tpr) if ok && code == "200" { tpr.ReadMIMEHeader() - return c, p, err + return c, err } if code == "407" { @@ -271,7 +270,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, string, error) { log.F("[http] 'CONNECT' method not allowed by proxy %s", s.addr) } - return nil, p, errors.New("[http] can not connect remote address: " + addr + ". error code: " + code) + return nil, errors.New("[http] can not connect remote address: " + addr + ". error code: " + code) } // DialUDP connects to the given address via the proxy diff --git a/proxy/kcp/kcp.go b/proxy/kcp/kcp.go index 48a4342..1dea5a5 100644 --- a/proxy/kcp/kcp.go +++ b/proxy/kcp/kcp.go @@ -18,6 +18,7 @@ import ( // KCP struct type KCP struct { dialer proxy.Dialer + proxy proxy.Proxy addr string key string @@ -36,7 +37,7 @@ func init() { } // NewKCP returns a kcp proxy struct -func NewKCP(s string, dialer proxy.Dialer) (*KCP, error) { +func NewKCP(s string, d proxy.Dialer, p proxy.Proxy) (*KCP, error) { u, err := url.Parse(s) if err != nil { log.F("[kcp] parse url err: %s", err) @@ -73,8 +74,9 @@ func NewKCP(s string, dialer proxy.Dialer) (*KCP, error) { return nil, err } - p := &KCP{ - dialer: dialer, + k := &KCP{ + dialer: d, + proxy: p, addr: addr, key: key, crypt: crypt, @@ -82,10 +84,10 @@ func NewKCP(s string, dialer proxy.Dialer) (*KCP, error) { parityShards: int(parityShards), } - if p.crypt != "" { - pass := pbkdf2.Key([]byte(p.key), []byte("kcp-go"), 4096, 32, sha1.New) + if k.crypt != "" { + pass := pbkdf2.Key([]byte(k.key), []byte("kcp-go"), 4096, 32, sha1.New) var block kcp.BlockCrypt - switch p.crypt { + switch k.crypt { case "sm4": block, _ = kcp.NewSM4BlockCrypt(pass[:16]) case "tea": @@ -113,22 +115,22 @@ func NewKCP(s string, dialer proxy.Dialer) (*KCP, error) { case "salsa20": block, _ = kcp.NewSalsa20BlockCrypt(pass) default: - return nil, errors.New("[kcp] unknown crypt type '" + p.crypt + "'") + return nil, errors.New("[kcp] unknown crypt type '" + k.crypt + "'") } - p.block = block + k.block = block } - return p, nil + return k, nil } // NewKCPDialer returns a kcp proxy dialer -func NewKCPDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { - return NewKCP(s, dialer) +func NewKCPDialer(s string, d proxy.Dialer) (proxy.Dialer, error) { + return NewKCP(s, d, nil) } // NewKCPServer returns a kcp proxy server -func NewKCPServer(s string, dialer proxy.Dialer) (proxy.Server, error) { +func NewKCPServer(s string, p proxy.Proxy) (proxy.Server, error) { transport := strings.Split(s, ",") // prepare transport listener @@ -137,17 +139,17 @@ func NewKCPServer(s string, dialer proxy.Dialer) (proxy.Server, error) { return nil, errors.New("[kcp] malformd listener:" + s) } - p, err := NewKCP(transport[0], dialer) + k, err := NewKCP(transport[0], nil, p) if err != nil { return nil, err } - p.server, err = proxy.ServerFromURL(transport[1], dialer) + k.server, err = proxy.ServerFromURL(transport[1], p) if err != nil { return nil, err } - return p, nil + return k, nil } // ListenAndServe . @@ -193,16 +195,13 @@ func (s *KCP) Serve(c net.Conn) { // Addr returns forwarder's address func (s *KCP) Addr() string { return s.addr } -// NextDialer returns the next dialer -func (s *KCP) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) } - // Dial connects to the address addr on the network net via the proxy -func (s *KCP) Dial(network, addr string) (net.Conn, string, error) { +func (s *KCP) Dial(network, addr string) (net.Conn, error) { // NOTE: kcp uses udp, we should dial remote server directly here c, err := kcp.DialWithOptions(s.addr, s.block, s.dataShards, s.parityShards) if err != nil { - log.F("[tls] dial to %s error: %s", s.addr, err) - return nil, "", err + log.F("[kcp] dial to %s error: %s", s.addr, err) + return nil, err } // TODO: change them to customizable later? @@ -217,7 +216,7 @@ func (s *KCP) Dial(network, addr string) (net.Conn, string, error) { c.SetReadBuffer(4194304) c.SetWriteBuffer(4194304) - return c, "", err + return c, err } // DialUDP connects to the given address via the proxy diff --git a/proxy/mixed/mixed.go b/proxy/mixed/mixed.go index 215b35c..5e206b4 100644 --- a/proxy/mixed/mixed.go +++ b/proxy/mixed/mixed.go @@ -27,11 +27,11 @@ var httpMethods = [...][]byte{ // MixedProxy struct type MixedProxy struct { - dialer proxy.Dialer - addr string + proxy proxy.Proxy + addr string http *http.HTTP - socks5 *socks5.SOCKS5 + socks5 *socks5.Socks5 } func init() { @@ -39,27 +39,27 @@ func init() { } // NewMixedProxy returns a mixed proxy -func NewMixedProxy(s string, dialer proxy.Dialer) (*MixedProxy, error) { +func NewMixedProxy(s string, p proxy.Proxy) (*MixedProxy, error) { u, err := url.Parse(s) if err != nil { log.F("parse err: %s", err) return nil, err } - p := &MixedProxy{ - dialer: dialer, - addr: u.Host, + m := &MixedProxy{ + proxy: p, + addr: u.Host, } - p.http, _ = http.NewHTTP(s, dialer) - p.socks5, _ = socks5.NewSOCKS5(s, dialer) + m.http, _ = http.NewHTTP(s, nil, p) + m.socks5, _ = socks5.NewSocks5(s, nil, p) - return p, nil + return m, nil } // NewMixedProxyServer returns a mixed proxy server -func NewMixedProxyServer(s string, dialer proxy.Dialer) (proxy.Server, error) { - return NewMixedProxy(s, dialer) +func NewMixedProxyServer(s string, p proxy.Proxy) (proxy.Server, error) { + return NewMixedProxy(s, p) } // ListenAndServe . diff --git a/proxy/obfs/obfs.go b/proxy/obfs/obfs.go index cd4d7b0..2ade58f 100644 --- a/proxy/obfs/obfs.go +++ b/proxy/obfs/obfs.go @@ -28,7 +28,7 @@ func init() { } // NewObfs returns a proxy struct -func NewObfs(s string, dialer proxy.Dialer) (*Obfs, error) { +func NewObfs(s string, d proxy.Dialer) (*Obfs, error) { u, err := url.Parse(s) if err != nil { log.F("parse url err: %s", err) @@ -59,7 +59,7 @@ func NewObfs(s string, dialer proxy.Dialer) (*Obfs, error) { } p := &Obfs{ - dialer: dialer, + dialer: d, addr: addr, obfsType: obfsType, obfsHost: obfsHost, @@ -89,19 +89,16 @@ func NewObfsDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { // Addr returns forwarder's address func (s *Obfs) Addr() string { return s.addr } -// NextDialer returns the next dialer -func (s *Obfs) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) } - // Dial connects to the address addr on the network net via the proxy -func (s *Obfs) Dial(network, addr string) (net.Conn, string, error) { - c, p, err := s.dialer.Dial("tcp", s.addr) +func (s *Obfs) Dial(network, addr string) (net.Conn, error) { + c, err := s.dialer.Dial("tcp", s.addr) if err != nil { log.F("[obfs] dial to %s error: %s", s.addr, err) - return nil, p, err + return nil, err } cc, e := s.obfsConn(c) - return cc, p, e + return cc, e } // DialUDP connects to the given address via the proxy diff --git a/proxy/proxy.go b/proxy/proxy.go new file mode 100644 index 0000000..da80bc1 --- /dev/null +++ b/proxy/proxy.go @@ -0,0 +1,15 @@ +package proxy + +import "net" + +// Proxy is a dialer manager +type Proxy interface { + // Dial connects to the given address via the proxy. + Dial(network, addr string) (c net.Conn, proxy string, err error) + + // DialUDP connects to the given address via the proxy. + DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) + + // Get the dialer by dstAddr + NextDialer(dstAddr string) Dialer +} diff --git a/proxy/redir/redir_linux.go b/proxy/redir/redir_linux.go index ea7706e..ca68b9a 100644 --- a/proxy/redir/redir_linux.go +++ b/proxy/redir/redir_linux.go @@ -25,9 +25,9 @@ const ( // RedirProxy struct type RedirProxy struct { - dialer proxy.Dialer - addr string - ipv6 bool + proxy proxy.Proxy + addr string + ipv6 bool } func init() { @@ -36,7 +36,7 @@ func init() { } // NewRedirProxy returns a redirect proxy. -func NewRedirProxy(s string, dialer proxy.Dialer, ipv6 bool) (*RedirProxy, error) { +func NewRedirProxy(s string, p proxy.Proxy, ipv6 bool) (*RedirProxy, error) { u, err := url.Parse(s) if err != nil { log.F("parse err: %s", err) @@ -45,22 +45,22 @@ func NewRedirProxy(s string, dialer proxy.Dialer, ipv6 bool) (*RedirProxy, error addr := u.Host r := &RedirProxy{ - dialer: dialer, - addr: addr, - ipv6: ipv6, + proxy: p, + addr: addr, + ipv6: ipv6, } return r, nil } // NewRedirServer returns a redir server. -func NewRedirServer(s string, dialer proxy.Dialer) (proxy.Server, error) { - return NewRedirProxy(s, dialer, false) +func NewRedirServer(s string, p proxy.Proxy) (proxy.Server, error) { + return NewRedirProxy(s, p, false) } // NewRedir6Server returns a redir server for ipv6. -func NewRedir6Server(s string, dialer proxy.Dialer) (proxy.Server, error) { - return NewRedirProxy(s, dialer, true) +func NewRedir6Server(s string, p proxy.Proxy) (proxy.Server, error) { + return NewRedirProxy(s, p, true) } // ListenAndServe . @@ -104,7 +104,7 @@ func (s *RedirProxy) Serve(c net.Conn) { return } - rc, p, err := s.dialer.Dial("tcp", tgt.String()) + rc, p, err := s.proxy.Dial("tcp", tgt.String()) if err != nil { log.F("[redir] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p) return diff --git a/proxy/reject/reject.go b/proxy/reject/reject.go index 9dc704e..97a6dc5 100644 --- a/proxy/reject/reject.go +++ b/proxy/reject/reject.go @@ -16,24 +16,21 @@ func init() { } // NewReject returns a reject proxy, reject:// -func NewReject(s string, dialer proxy.Dialer) (*Reject, error) { +func NewReject(s string, d proxy.Dialer) (*Reject, error) { return &Reject{}, nil } // NewRejectDialer returns a reject proxy dialer. -func NewRejectDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { - return NewReject(s, dialer) +func NewRejectDialer(s string, d proxy.Dialer) (proxy.Dialer, error) { + return NewReject(s, d) } // Addr returns forwarder's address. func (s *Reject) Addr() string { return "REJECT" } -// NextDialer returns the next dialer. -func (s *Reject) NextDialer(dstAddr string) proxy.Dialer { return s } - // Dial connects to the address addr on the network net via the proxy. -func (s *Reject) Dial(network, addr string) (net.Conn, string, error) { - return nil, "REJECT", errors.New("REJECT") +func (s *Reject) Dial(network, addr string) (net.Conn, error) { + return nil, errors.New("REJECT") } // DialUDP connects to the given address via the proxy. diff --git a/proxy/server.go b/proxy/server.go index 3e1c91a..78fdac1 100644 --- a/proxy/server.go +++ b/proxy/server.go @@ -19,7 +19,7 @@ type Server interface { } // ServerCreator is a function to create proxy servers -type ServerCreator func(s string, dialer Dialer) (Server, error) +type ServerCreator func(s string, proxy Proxy) (Server, error) var ( serverMap = make(map[string]ServerCreator) @@ -32,8 +32,8 @@ func RegisterServer(name string, c ServerCreator) { // ServerFromURL calls the registered creator to create proxy servers // dialer is the default upstream dialer so cannot be nil, we can use Default when calling this function -func ServerFromURL(s string, dialer Dialer) (Server, error) { - if dialer == nil { +func ServerFromURL(s string, p Proxy) (Server, error) { + if p == nil { return nil, errors.New("ServerFromURL: dialer cannot be nil") } @@ -49,7 +49,7 @@ func ServerFromURL(s string, dialer Dialer) (Server, error) { c, ok := serverMap[strings.ToLower(u.Scheme)] if ok { - return c(s, dialer) + return c(s, p) } return nil, errors.New("unknown scheme '" + u.Scheme + "'") diff --git a/proxy/socks5/socks5.go b/proxy/socks5/socks5.go index ad845ed..92e172e 100644 --- a/proxy/socks5/socks5.go +++ b/proxy/socks5/socks5.go @@ -30,9 +30,10 @@ import ( // Version is socks5 version number. const Version = 5 -// SOCKS5 is a base socks5 struct. -type SOCKS5 struct { +// Socks5 is a base socks5 struct. +type Socks5 struct { dialer proxy.Dialer + proxy proxy.Proxy addr string user string password string @@ -43,9 +44,9 @@ func init() { proxy.RegisterServer("socks5", NewSocks5Server) } -// NewSOCKS5 returns a Proxy that makes SOCKS v5 connections to the given address +// NewSocks5 returns a Proxy that makes SOCKS v5 connections to the given address // with an optional username and password. (RFC 1928) -func NewSOCKS5(s string, dialer proxy.Dialer) (*SOCKS5, error) { +func NewSocks5(s string, d proxy.Dialer, p proxy.Proxy) (*Socks5, error) { u, err := url.Parse(s) if err != nil { log.F("parse err: %s", err) @@ -56,8 +57,9 @@ func NewSOCKS5(s string, dialer proxy.Dialer) (*SOCKS5, error) { user := u.User.Username() pass, _ := u.User.Password() - h := &SOCKS5{ - dialer: dialer, + h := &Socks5{ + dialer: d, + proxy: p, addr: addr, user: user, password: pass, @@ -67,23 +69,23 @@ func NewSOCKS5(s string, dialer proxy.Dialer) (*SOCKS5, error) { } // NewSocks5Dialer returns a socks5 proxy dialer. -func NewSocks5Dialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { - return NewSOCKS5(s, dialer) +func NewSocks5Dialer(s string, d proxy.Dialer) (proxy.Dialer, error) { + return NewSocks5(s, d, nil) } // NewSocks5Server returns a socks5 proxy server. -func NewSocks5Server(s string, dialer proxy.Dialer) (proxy.Server, error) { - return NewSOCKS5(s, dialer) +func NewSocks5Server(s string, p proxy.Proxy) (proxy.Server, error) { + return NewSocks5(s, nil, p) } // ListenAndServe serves socks5 requests. -func (s *SOCKS5) ListenAndServe() { +func (s *Socks5) ListenAndServe() { go s.ListenAndServeUDP() s.ListenAndServeTCP() } // ListenAndServeTCP listen and serve on tcp port. -func (s *SOCKS5) ListenAndServeTCP() { +func (s *Socks5) ListenAndServeTCP() { l, err := net.Listen("tcp", s.addr) if err != nil { log.F("[socks5] failed to listen on %s: %v", s.addr, err) @@ -104,7 +106,7 @@ func (s *SOCKS5) ListenAndServeTCP() { } // Serve serves a connection. -func (s *SOCKS5) Serve(c net.Conn) { +func (s *Socks5) Serve(c net.Conn) { defer c.Close() if c, ok := c.(*net.TCPConn); ok { @@ -131,7 +133,7 @@ func (s *SOCKS5) Serve(c net.Conn) { return } - rc, p, err := s.dialer.Dial("tcp", tgt.String()) + rc, p, err := s.proxy.Dial("tcp", tgt.String()) if err != nil { log.F("[socks5] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p) return @@ -150,7 +152,7 @@ func (s *SOCKS5) Serve(c net.Conn) { } // ListenAndServeUDP serves udp requests. -func (s *SOCKS5) ListenAndServeUDP() { +func (s *Socks5) ListenAndServeUDP() { lc, err := net.ListenPacket("udp", s.addr) if err != nil { log.F("[socks5-udp] failed to listen on %s: %v", s.addr, err) @@ -213,41 +215,38 @@ func (s *SOCKS5) ListenAndServeUDP() { } // Addr returns forwarder's address. -func (s *SOCKS5) Addr() string { +func (s *Socks5) Addr() string { if s.addr == "" { return s.dialer.Addr() } return s.addr } -// NextDialer returns the next dialer. -func (s *SOCKS5) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) } - // Dial connects to the address addr on the network net via the SOCKS5 proxy. -func (s *SOCKS5) Dial(network, addr string) (net.Conn, string, error) { +func (s *Socks5) Dial(network, addr string) (net.Conn, error) { switch network { case "tcp", "tcp6", "tcp4": default: - return nil, "", errors.New("[socks5]: no support for connection type " + network) + return nil, errors.New("[socks5]: no support for connection type " + network) } - c, p, err := s.dialer.Dial(network, s.addr) + c, err := s.dialer.Dial(network, s.addr) if err != nil { log.F("[socks5]: dial to %s error: %s", s.addr, err) - return nil, p, err + return nil, err } if err := s.connect(c, addr); err != nil { c.Close() - return nil, p, err + return nil, err } - return c, p, nil + return c, nil } // DialUDP connects to the given address via the proxy. -func (s *SOCKS5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) { - c, _, err := s.dialer.Dial("tcp", s.addr) +func (s *Socks5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) { + c, err := s.dialer.Dial("tcp", s.addr) if err != nil { log.F("[socks5] dialudp dial tcp to %s error: %s", s.addr, err) return nil, nil, err @@ -295,7 +294,7 @@ func (s *SOCKS5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.A // connect takes an existing connection to a socks5 proxy server, // and commands the server to extend that connection to target, // which must be a canonical address with a host and port. -func (s *SOCKS5) connect(conn net.Conn, target string) error { +func (s *Socks5) connect(conn net.Conn, target string) error { host, portStr, err := net.SplitHostPort(target) if err != nil { return err @@ -426,7 +425,7 @@ func (s *SOCKS5) connect(conn net.Conn, target string) error { } // Handshake fast-tracks SOCKS initialization to get target address to connect. -func (s *SOCKS5) handshake(rw io.ReadWriter) (socks.Addr, error) { +func (s *Socks5) handshake(rw io.ReadWriter) (socks.Addr, error) { // Read RFC 1928 for request and reply structure and sizes buf := make([]byte, socks.MaxAddrLen) // read VER, NMETHODS, METHODS diff --git a/proxy/ss/ss.go b/proxy/ss/ss.go index 3e9505b..b4c2ee1 100644 --- a/proxy/ss/ss.go +++ b/proxy/ss/ss.go @@ -19,6 +19,7 @@ import ( // SS is a base ss struct. type SS struct { dialer proxy.Dialer + proxy proxy.Proxy addr string core.Cipher @@ -30,7 +31,7 @@ func init() { } // NewSS returns a ss proxy. -func NewSS(s string, dialer proxy.Dialer) (*SS, error) { +func NewSS(s string, d proxy.Dialer, p proxy.Proxy) (*SS, error) { u, err := url.Parse(s) if err != nil { log.F("parse err: %s", err) @@ -46,23 +47,24 @@ func NewSS(s string, dialer proxy.Dialer) (*SS, error) { log.Fatalf("[ss] PickCipher for '%s', error: %s", method, err) } - p := &SS{ - dialer: dialer, + ss := &SS{ + dialer: d, + proxy: p, addr: addr, Cipher: ciph, } - return p, nil + return ss, nil } // NewSSDialer returns a ss proxy dialer. -func NewSSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { - return NewSS(s, dialer) +func NewSSDialer(s string, d proxy.Dialer) (proxy.Dialer, error) { + return NewSS(s, d, nil) } // NewSSServer returns a ss proxy server. -func NewSSServer(s string, dialer proxy.Dialer) (proxy.Server, error) { - return NewSS(s, dialer) +func NewSSServer(s string, p proxy.Proxy) (proxy.Server, error) { + return NewSS(s, nil, p) } // ListenAndServe serves ss requests. @@ -108,7 +110,7 @@ func (s *SS) Serve(c net.Conn) { return } - dialer := s.dialer.NextDialer(tgt.String()) + dialer := s.proxy.NextDialer(tgt.String()) // udp over tcp? uot := socks.UoT(tgt[0]) @@ -147,14 +149,14 @@ func (s *SS) Serve(c net.Conn) { network = "udp" } - rc, p, err := dialer.Dial(network, tgt.String()) + rc, err := dialer.Dial(network, tgt.String()) if err != nil { - log.F("[ss] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p) + log.F("[ss] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, dialer.Addr()) return } defer rc.Close() - log.F("[ss] %s <-> %s, %s", c.RemoteAddr(), tgt, p) + log.F("[ss] %s <-> %s, %s", c.RemoteAddr(), tgt, dialer.Addr()) _, _, err = conn.Relay(c, rc) if err != nil { @@ -238,33 +240,30 @@ func (s *SS) Addr() string { return s.addr } -// NextDialer returns the next dialer. -func (s *SS) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) } - // Dial connects to the address addr on the network net via the proxy. -func (s *SS) Dial(network, addr string) (net.Conn, string, error) { +func (s *SS) Dial(network, addr string) (net.Conn, error) { target := socks.ParseAddr(addr) if target == nil { - return nil, "", errors.New("[ss] unable to parse address: " + addr) + return nil, errors.New("[ss] unable to parse address: " + addr) } if network == "uot" { target[0] = target[0] | 0x8 } - c, p, err := s.dialer.Dial("tcp", s.addr) + c, err := s.dialer.Dial("tcp", s.addr) if err != nil { log.F("[ss] dial to %s error: %s", s.addr, err) - return nil, p, err + return nil, err } c = s.StreamConn(c) if _, err = c.Write(target); err != nil { c.Close() - return nil, p, err + return nil, err } - return c, p, err + return c, err } diff --git a/proxy/ssr/ssr.go b/proxy/ssr/ssr.go index 32bb5a9..9d3bad7 100644 --- a/proxy/ssr/ssr.go +++ b/proxy/ssr/ssr.go @@ -37,7 +37,7 @@ func init() { } // NewSSR returns a shadowsocksr proxy, ssr://method:pass@host:port/query -func NewSSR(s string, dialer proxy.Dialer) (*SSR, error) { +func NewSSR(s string, d proxy.Dialer) (*SSR, error) { u, err := url.Parse(s) if err != nil { log.F("parse err: %s", err) @@ -49,7 +49,7 @@ func NewSSR(s string, dialer proxy.Dialer) (*SSR, error) { pass, _ := u.User.Password() p := &SSR{ - dialer: dialer, + dialer: d, addr: addr, EncryptMethod: method, EncryptPassword: pass, @@ -65,8 +65,8 @@ func NewSSR(s string, dialer proxy.Dialer) (*SSR, error) { } // NewSSRDialer returns a ssr proxy dialer. -func NewSSRDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { - return NewSSR(s, dialer) +func NewSSRDialer(s string, d proxy.Dialer) (proxy.Dialer, error) { + return NewSSR(s, d) } // Addr returns forwarder's address @@ -77,30 +77,27 @@ func (s *SSR) Addr() string { return s.addr } -// NextDialer returns the next dialer -func (s *SSR) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) } - // Dial connects to the address addr on the network net via the proxy. -func (s *SSR) Dial(network, addr string) (net.Conn, string, error) { +func (s *SSR) Dial(network, addr string) (net.Conn, error) { target := socks.ParseAddr(addr) if target == nil { - return nil, "", errors.New("[ssr] unable to parse address: " + addr) + return nil, errors.New("[ssr] unable to parse address: " + addr) } cipher, err := shadowsocksr.NewStreamCipher(s.EncryptMethod, s.EncryptPassword) if err != nil { - return nil, "", err + return nil, err } - c, p, err := s.dialer.Dial("tcp", s.addr) + c, err := s.dialer.Dial("tcp", s.addr) if err != nil { log.F("[ssr] dial to %s error: %s", s.addr, err) - return nil, p, err + return nil, err } ssrconn := shadowsocksr.NewSSTCPConn(c, cipher) if ssrconn.Conn == nil || ssrconn.RemoteAddr() == nil { - return nil, p, errors.New("[ssr] nil connection") + return nil, errors.New("[ssr] nil connection") } // should initialize obfs/protocol now @@ -109,7 +106,7 @@ func (s *SSR) Dial(network, addr string) (net.Conn, string, error) { ssrconn.IObfs = obfs.NewObfs(s.Obfs) if ssrconn.IObfs == nil { - return nil, p, errors.New("[ssr] unsupported obfs type: " + s.Obfs) + return nil, errors.New("[ssr] unsupported obfs type: " + s.Obfs) } obfsServerInfo := &ssr.ServerInfoForObfs{ @@ -122,7 +119,7 @@ func (s *SSR) Dial(network, addr string) (net.Conn, string, error) { ssrconn.IProtocol = protocol.NewProtocol(s.Protocol) if ssrconn.IProtocol == nil { - return nil, p, errors.New("[ssr] unsupported protocol type: " + s.Protocol) + return nil, errors.New("[ssr] unsupported protocol type: " + s.Protocol) } protocolServerInfo := &ssr.ServerInfoForObfs{ @@ -145,10 +142,10 @@ func (s *SSR) Dial(network, addr string) (net.Conn, string, error) { if _, err := ssrconn.Write(target); err != nil { ssrconn.Close() - return nil, p, err + return nil, err } - return ssrconn, p, err + return ssrconn, err } // DialUDP connects to the given address via the proxy. diff --git a/proxy/tcptun/tcptun.go b/proxy/tcptun/tcptun.go index f6f1807..3240d52 100644 --- a/proxy/tcptun/tcptun.go +++ b/proxy/tcptun/tcptun.go @@ -12,8 +12,8 @@ import ( // TCPTun struct type TCPTun struct { - dialer proxy.Dialer - addr string + proxy proxy.Proxy + addr string raddr string } @@ -23,7 +23,7 @@ func init() { } // NewTCPTun returns a tcptun proxy -func NewTCPTun(s string, dialer proxy.Dialer) (*TCPTun, error) { +func NewTCPTun(s string, p proxy.Proxy) (*TCPTun, error) { u, err := url.Parse(s) if err != nil { log.F("parse err: %s", err) @@ -33,18 +33,18 @@ func NewTCPTun(s string, dialer proxy.Dialer) (*TCPTun, error) { addr := u.Host d := strings.Split(addr, "=") - p := &TCPTun{ - dialer: dialer, - addr: d[0], - raddr: d[1], + t := &TCPTun{ + proxy: p, + addr: d[0], + raddr: d[1], } - return p, nil + return t, nil } // NewTCPTunServer returns a udp tunnel server -func NewTCPTunServer(s string, dialer proxy.Dialer) (proxy.Server, error) { - return NewTCPTun(s, dialer) +func NewTCPTunServer(s string, p proxy.Proxy) (proxy.Server, error) { + return NewTCPTun(s, p) } // ListenAndServe . @@ -76,7 +76,7 @@ func (s *TCPTun) Serve(c net.Conn) { c.SetKeepAlive(true) } - rc, p, err := s.dialer.Dial("tcp", s.raddr) + rc, p, err := s.proxy.Dial("tcp", s.raddr) if err != nil { log.F("[tcptun] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), s.addr, err, p) return diff --git a/proxy/tls/tls.go b/proxy/tls/tls.go index 0e2c471..70c8900 100644 --- a/proxy/tls/tls.go +++ b/proxy/tls/tls.go @@ -14,6 +14,7 @@ import ( // TLS struct type TLS struct { dialer proxy.Dialer + proxy proxy.Proxy addr string tlsConfig *stdtls.Config @@ -34,7 +35,7 @@ func init() { } // NewTLS returns a tls proxy struct -func NewTLS(s string, dialer proxy.Dialer) (*TLS, error) { +func NewTLS(s string, d proxy.Dialer, p proxy.Proxy) (*TLS, error) { u, err := url.Parse(s) if err != nil { log.F("parse url err: %s", err) @@ -53,9 +54,9 @@ func NewTLS(s string, dialer proxy.Dialer) (*TLS, error) { certFile := query.Get("cert") keyFile := query.Get("key") - p := &TLS{ - dialer: dialer, - addr: addr, + t := &TLS{ + dialer: d, + proxy: p, serverName: serverName, skipVerify: false, certFile: certFile, @@ -63,15 +64,15 @@ func NewTLS(s string, dialer proxy.Dialer) (*TLS, error) { } if skipVerify == "true" { - p.skipVerify = true + t.skipVerify = true } - return p, nil + return t, nil } // NewTLSDialer returns a tls proxy dialer -func NewTLSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { - p, err := NewTLS(s, dialer) +func NewTLSDialer(s string, d proxy.Dialer) (proxy.Dialer, error) { + p, err := NewTLS(s, d, nil) if err != nil { return nil, err } @@ -87,7 +88,7 @@ func NewTLSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { } // NewTLSServer returns a tls transport layer before the real server -func NewTLSServer(s string, dialer proxy.Dialer) (proxy.Server, error) { +func NewTLSServer(s string, p proxy.Proxy) (proxy.Server, error) { transport := strings.Split(s, ",") // prepare transport listener @@ -96,28 +97,28 @@ func NewTLSServer(s string, dialer proxy.Dialer) (proxy.Server, error) { return nil, errors.New("[tls] malformd listener:" + s) } - p, err := NewTLS(transport[0], dialer) + t, err := NewTLS(transport[0], nil, p) if err != nil { return nil, err } - cert, err := stdtls.LoadX509KeyPair(p.certFile, p.keyFile) + cert, err := stdtls.LoadX509KeyPair(t.certFile, t.keyFile) if err != nil { - log.F("[tls] unable to load cert: %s, key %s", p.certFile, p.keyFile) + log.F("[tls] unable to load cert: %s, key %s", t.certFile, t.keyFile) return nil, err } - p.tlsConfig = &stdtls.Config{ + t.tlsConfig = &stdtls.Config{ Certificates: []stdtls.Certificate{cert}, MinVersion: stdtls.VersionTLS10, } - p.server, err = proxy.ServerFromURL(transport[1], dialer) + t.server, err = proxy.ServerFromURL(transport[1], p) if err != nil { return nil, err } - return p, nil + return t, nil } // ListenAndServe . @@ -156,20 +157,17 @@ func (s *TLS) Serve(c net.Conn) { // Addr returns forwarder's address func (s *TLS) Addr() string { return s.addr } -// NextDialer returns the next dialer -func (s *TLS) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) } - // Dial connects to the address addr on the network net via the proxy -func (s *TLS) Dial(network, addr string) (net.Conn, string, error) { - cc, p, err := s.dialer.Dial("tcp", s.addr) +func (s *TLS) Dial(network, addr string) (net.Conn, error) { + cc, err := s.dialer.Dial("tcp", s.addr) if err != nil { log.F("[tls] dial to %s error: %s", s.addr, err) - return nil, p, err + return nil, err } c := stdtls.Client(cc, s.tlsConfig) err = c.Handshake() - return c, p, err + return c, err } // DialUDP connects to the given address via the proxy diff --git a/proxy/tproxy/tproxy_linux.go b/proxy/tproxy/tproxy_linux.go index b338803..afe55a0 100644 --- a/proxy/tproxy/tproxy_linux.go +++ b/proxy/tproxy/tproxy_linux.go @@ -19,8 +19,8 @@ import ( // TProxy struct type TProxy struct { - dialer proxy.Dialer - addr string + proxy proxy.Proxy + addr string } func init() { @@ -28,7 +28,7 @@ func init() { } // NewTProxy returns a tproxy. -func NewTProxy(s string, dialer proxy.Dialer) (*TProxy, error) { +func NewTProxy(s string, p proxy.Proxy) (*TProxy, error) { u, err := url.Parse(s) if err != nil { log.F("parse err: %s", err) @@ -37,17 +37,17 @@ func NewTProxy(s string, dialer proxy.Dialer) (*TProxy, error) { addr := u.Host - p := &TProxy{ - dialer: dialer, - addr: addr, + tp := &TProxy{ + proxy: p, + addr: addr, } - return p, nil + return tp, nil } // NewTProxyServer returns a udp tunnel server. -func NewTProxyServer(s string, dialer proxy.Dialer) (proxy.Server, error) { - return NewTProxy(s, dialer) +func NewTProxyServer(s string, p proxy.Proxy) (proxy.Server, error) { + return NewTProxy(s, p) } // ListenAndServe . diff --git a/proxy/udptun/udptun.go b/proxy/udptun/udptun.go index d8e22c3..d2d66a6 100644 --- a/proxy/udptun/udptun.go +++ b/proxy/udptun/udptun.go @@ -14,7 +14,7 @@ import ( // UDPTun is a base udptun struct. type UDPTun struct { - dialer proxy.Dialer + proxy proxy.Proxy addr string taddr string // tunnel addr string tuaddr *net.UDPAddr // tunnel addr @@ -25,7 +25,7 @@ func init() { } // NewUDPTun returns a UDPTun proxy. -func NewUDPTun(s string, dialer proxy.Dialer) (*UDPTun, error) { +func NewUDPTun(s string, p proxy.Proxy) (*UDPTun, error) { u, err := url.Parse(s) if err != nil { log.F("[udptun] parse err: %s", err) @@ -35,19 +35,19 @@ func NewUDPTun(s string, dialer proxy.Dialer) (*UDPTun, error) { addr := u.Host d := strings.Split(addr, "=") - p := &UDPTun{ - dialer: dialer, - addr: d[0], - taddr: d[1], + ut := &UDPTun{ + proxy: p, + addr: d[0], + taddr: d[1], } - p.tuaddr, err = net.ResolveUDPAddr("udp", p.taddr) - return p, err + ut.tuaddr, err = net.ResolveUDPAddr("udp", ut.taddr) + return ut, err } // NewUDPTunServer returns a udp tunnel server. -func NewUDPTunServer(s string, dialer proxy.Dialer) (proxy.Server, error) { - return NewUDPTun(s, dialer) +func NewUDPTunServer(s string, p proxy.Proxy) (proxy.Server, error) { + return NewUDPTun(s, p) } // ListenAndServe listen and serves on the given address. @@ -75,7 +75,7 @@ func (s *UDPTun) ListenAndServe() { v, ok := nm.Load(raddr.String()) if !ok && v == nil { - pc, _, err = s.dialer.DialUDP("udp", s.taddr) + pc, _, err = s.proxy.DialUDP("udp", s.taddr) if err != nil { log.F("[udptun] remote dial error: %v", err) continue diff --git a/proxy/unix/unix.go b/proxy/unix/unix.go index 308220b..16918e4 100644 --- a/proxy/unix/unix.go +++ b/proxy/unix/unix.go @@ -14,6 +14,7 @@ import ( // Unix domain socket struct type Unix struct { dialer proxy.Dialer + proxy proxy.Proxy addr string server proxy.Server @@ -25,28 +26,29 @@ func init() { } // NewUnix returns unix fomain socket proxy -func NewUnix(s string, dialer proxy.Dialer) (*Unix, error) { +func NewUnix(s string, d proxy.Dialer, p proxy.Proxy) (*Unix, error) { u, err := url.Parse(s) if err != nil { log.F("parse url err: %s", err) return nil, err } - p := &Unix{ - dialer: dialer, + unix := &Unix{ + dialer: d, + proxy: p, addr: u.Path, } - return p, nil + return unix, nil } // NewUnixDialer returns a unix domain socket dialer -func NewUnixDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { - return NewUnix(s, dialer) +func NewUnixDialer(s string, d proxy.Dialer) (proxy.Dialer, error) { + return NewUnix(s, d, nil) } // NewUnixServer returns a unix domain socket server -func NewUnixServer(s string, dialer proxy.Dialer) (proxy.Server, error) { +func NewUnixServer(s string, p proxy.Proxy) (proxy.Server, error) { transport := strings.Split(s, ",") // prepare transport listener @@ -55,17 +57,17 @@ func NewUnixServer(s string, dialer proxy.Dialer) (proxy.Server, error) { return nil, errors.New("[unix] malformd listener:" + s) } - p, err := NewUnix(transport[0], dialer) + unix, err := NewUnix(transport[0], nil, p) if err != nil { return nil, err } - p.server, err = proxy.ServerFromURL(transport[1], dialer) + unix.server, err = proxy.ServerFromURL(transport[1], p) if err != nil { return nil, err } - return p, nil + return unix, nil } // ListenAndServe serves requests @@ -109,18 +111,10 @@ func (s *Unix) Addr() string { return s.addr } -// NextDialer returns the next dialer -func (s *Unix) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) } - // Dial connects to the address addr on the network net via the proxy. -func (s *Unix) Dial(network, addr string) (net.Conn, string, error) { +func (s *Unix) Dial(network, addr string) (net.Conn, error) { // NOTE: must be the first dialer in a chain - rc, err := net.Dial("unix", s.addr) - if err != nil { - return nil, "", err - } - - return rc, "", err + return net.Dial("unix", s.addr) } // DialUDP connects to the given address via the proxy diff --git a/proxy/uottun/uottun.go b/proxy/uottun/uottun.go index 4499633..3bc134e 100644 --- a/proxy/uottun/uottun.go +++ b/proxy/uottun/uottun.go @@ -14,8 +14,8 @@ import ( // UoTTun is a base udp over tcp tunnel struct. type UoTTun struct { - dialer proxy.Dialer - addr string + proxy proxy.Proxy + addr string raddr string } @@ -25,7 +25,7 @@ func init() { } // NewUoTTun returns a UoTTun proxy. -func NewUoTTun(s string, dialer proxy.Dialer) (*UoTTun, error) { +func NewUoTTun(s string, p proxy.Proxy) (*UoTTun, error) { u, err := url.Parse(s) if err != nil { log.F("parse err: %s", err) @@ -35,18 +35,18 @@ func NewUoTTun(s string, dialer proxy.Dialer) (*UoTTun, error) { addr := u.Host d := strings.Split(addr, "=") - p := &UoTTun{ - dialer: dialer, - addr: d[0], - raddr: d[1], + ut := &UoTTun{ + proxy: p, + addr: d[0], + raddr: d[1], } - return p, nil + return ut, nil } // NewUoTTunServer returns a uot tunnel server. -func NewUoTTunServer(s string, dialer proxy.Dialer) (proxy.Server, error) { - return NewUoTTun(s, dialer) +func NewUoTTunServer(s string, p proxy.Proxy) (proxy.Server, error) { + return NewUoTTun(s, p) } // ListenAndServe listen and serve on tcp. @@ -69,7 +69,7 @@ func (s *UoTTun) ListenAndServe() { continue } - rc, p, err := s.dialer.Dial("uot", s.raddr) + rc, p, err := s.proxy.Dial("uot", s.raddr) if err != nil { log.F("[uottun] failed to connect to server %v: %v", s.raddr, err) continue diff --git a/proxy/vmess/vmess.go b/proxy/vmess/vmess.go index b9747a4..2ece15e 100644 --- a/proxy/vmess/vmess.go +++ b/proxy/vmess/vmess.go @@ -27,7 +27,7 @@ func init() { } // NewVMess returns a vmess proxy. -func NewVMess(s string, dialer proxy.Dialer) (*VMess, error) { +func NewVMess(s string, d proxy.Dialer) (*VMess, error) { u, err := url.Parse(s) if err != nil { log.F("parse url err: %s", err) @@ -62,7 +62,7 @@ func NewVMess(s string, dialer proxy.Dialer) (*VMess, error) { } p := &VMess{ - dialer: dialer, + dialer: d, addr: addr, uuid: uuid, alterID: int(alterID), @@ -86,18 +86,14 @@ func (s *VMess) Addr() string { return s.addr } -// NextDialer returns the next dialer -func (s *VMess) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) } - // Dial connects to the address addr on the network net via the proxy. -func (s *VMess) Dial(network, addr string) (net.Conn, string, error) { - rc, p, err := s.dialer.Dial("tcp", s.addr) +func (s *VMess) Dial(network, addr string) (net.Conn, error) { + rc, err := s.dialer.Dial("tcp", s.addr) if err != nil { - return nil, p, err + return nil, err } - cc, e := s.client.NewConn(rc, addr) - return cc, p, e + return s.client.NewConn(rc, addr) } // DialUDP connects to the given address via the proxy. diff --git a/proxy/ws/ws.go b/proxy/ws/ws.go index 7da2379..c0b98ce 100644 --- a/proxy/ws/ws.go +++ b/proxy/ws/ws.go @@ -24,7 +24,7 @@ func init() { } // NewWS returns a websocket proxy. -func NewWS(s string, dialer proxy.Dialer) (*WS, error) { +func NewWS(s string, d proxy.Dialer) (*WS, error) { u, err := url.Parse(s) if err != nil { log.F("parse url err: %s", err) @@ -35,7 +35,7 @@ func NewWS(s string, dialer proxy.Dialer) (*WS, error) { // TODO: if addr == "" { - addr = dialer.Addr() + addr = d.Addr() } colonPos := strings.LastIndex(addr, ":") @@ -51,7 +51,7 @@ func NewWS(s string, dialer proxy.Dialer) (*WS, error) { } p := &WS{ - dialer: dialer, + dialer: d, addr: addr, client: client, } @@ -60,8 +60,8 @@ func NewWS(s string, dialer proxy.Dialer) (*WS, error) { } // NewWSDialer returns a ws proxy dialer. -func NewWSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { - return NewWS(s, dialer) +func NewWSDialer(s string, d proxy.Dialer) (proxy.Dialer, error) { + return NewWS(s, d) } // Addr returns forwarder's address. @@ -72,18 +72,14 @@ func (s *WS) Addr() string { return s.addr } -// NextDialer returns the next dialer. -func (s *WS) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) } - // Dial connects to the address addr on the network net via the proxy. -func (s *WS) Dial(network, addr string) (net.Conn, string, error) { - rc, p, err := s.dialer.Dial("tcp", s.addr) +func (s *WS) Dial(network, addr string) (net.Conn, error) { + rc, err := s.dialer.Dial("tcp", s.addr) if err != nil { - return nil, p, err + return nil, err } - cc, e := s.client.NewConn(rc, addr) - return cc, p, e + return s.client.NewConn(rc, addr) } // DialUDP connects to the given address via the proxy. diff --git a/rule/rule.go b/rule/rule.go index edc171f..b8474f9 100644 --- a/rule/rule.go +++ b/rule/rule.go @@ -10,23 +10,23 @@ import ( "github.com/nadoo/glider/strategy" ) -// Dialer struct -type Dialer struct { - gDialer *strategy.Dialer - dialers []*strategy.Dialer +// Proxy struct +type Proxy struct { + proxy *strategy.Proxy + proxies []*strategy.Proxy domainMap sync.Map ipMap sync.Map cidrMap sync.Map } -// NewDialer returns a new rule dialer -func NewDialer(rules []*Config, gDialer *strategy.Dialer) *Dialer { - rd := &Dialer{gDialer: gDialer} +// NewProxy returns a new rule proxy +func NewProxy(rules []*Config, proxy *strategy.Proxy) *Proxy { + rd := &Proxy{proxy: proxy} for _, r := range rules { - sd := strategy.NewDialer(r.Forward, &r.StrategyConfig) - rd.dialers = append(rd.dialers, sd) + sd := strategy.NewProxy(r.Forward, &r.StrategyConfig) + rd.proxies = append(rd.proxies, sd) for _, domain := range r.Domain { rd.domainMap.Store(strings.ToLower(domain), sd) @@ -46,31 +46,38 @@ func NewDialer(rules []*Config, gDialer *strategy.Dialer) *Dialer { return rd } -// Addr returns RuleDialer's address, always be "RULES" -func (rd *Dialer) Addr() string { return "RULE DIALER, DEFAULT: " + rd.gDialer.Addr() } +// Dial dials to targer addr and return a conn +func (p *Proxy) Dial(network, addr string) (net.Conn, string, error) { + return p.nextProxy(addr).Dial(network, addr) +} -// NextDialer return next dialer according to rule -func (rd *Dialer) NextDialer(dstAddr string) proxy.Dialer { +// DialUDP connects to the given address via the proxy +func (p *Proxy) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) { + return p.nextProxy(addr).DialUDP(network, addr) +} + +// nextProxy return next proxy according to rule +func (p *Proxy) nextProxy(dstAddr string) *strategy.Proxy { host, _, err := net.SplitHostPort(dstAddr) if err != nil { // TODO: check here // logf("[rule] SplitHostPort ERROR: %s", err) - return rd.gDialer + return p.proxy } // find ip if ip := net.ParseIP(host); ip != nil { // check ip - if dialer, ok := rd.ipMap.Load(ip.String()); ok { - return dialer.(proxy.Dialer) + if proxy, ok := p.ipMap.Load(ip.String()); ok { + return proxy.(*strategy.Proxy) } - var ret proxy.Dialer + var ret *strategy.Proxy // check cidr - rd.cidrMap.Range(func(key, value interface{}) bool { + p.cidrMap.Range(func(key, value interface{}) bool { cidr := key.(*net.IPNet) if cidr.Contains(ip) { - ret = value.(proxy.Dialer) + ret = value.(*strategy.Proxy) return false } @@ -89,26 +96,21 @@ func (rd *Dialer) NextDialer(dstAddr string) proxy.Dialer { domain := strings.Join(domainParts[i:length], ".") // find in domainMap - if dialer, ok := rd.domainMap.Load(domain); ok { - return dialer.(proxy.Dialer) + if proxy, ok := p.domainMap.Load(domain); ok { + return proxy.(*strategy.Proxy) } } - return rd.gDialer + return p.proxy } -// Dial dials to targer addr and return a conn -func (rd *Dialer) Dial(network, addr string) (net.Conn, string, error) { - return rd.NextDialer(addr).Dial(network, addr) -} - -// DialUDP connects to the given address via the proxy -func (rd *Dialer) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) { - return rd.NextDialer(addr).DialUDP(network, addr) +// NextDialer return next dialer according to rule +func (p *Proxy) NextDialer(dstAddr string) proxy.Dialer { + return p.nextProxy(dstAddr).NextDialer(dstAddr) } // AddDomainIP used to update ipMap rules according to domainMap rule -func (rd *Dialer) AddDomainIP(domain, ip string) error { +func (p *Proxy) AddDomainIP(domain, ip string) error { if ip != "" { domainParts := strings.Split(domain, ".") length := len(domainParts) @@ -116,8 +118,8 @@ func (rd *Dialer) AddDomainIP(domain, ip string) error { pDomain := strings.ToLower(strings.Join(domainParts[i:length], ".")) // find in domainMap - if dialer, ok := rd.domainMap.Load(pDomain); ok { - rd.ipMap.Store(ip, dialer) + if dialer, ok := p.domainMap.Load(pDomain); ok { + p.ipMap.Store(ip, dialer) log.F("[rule] add ip=%s, based on rule: domain=%s & domain/ip: %s/%s\n", ip, pDomain, domain, ip) } } @@ -126,10 +128,10 @@ func (rd *Dialer) AddDomainIP(domain, ip string) error { } // Check . -func (rd *Dialer) Check() { - rd.gDialer.Check() +func (p *Proxy) Check() { + p.proxy.Check() - for _, d := range rd.dialers { + for _, d := range p.proxies { d.Check() } } diff --git a/strategy/forward.go b/strategy/forward.go index 9a34475..81f4b32 100644 --- a/strategy/forward.go +++ b/strategy/forward.go @@ -97,8 +97,8 @@ func (f *Forwarder) Addr() string { } // Dial . -func (f *Forwarder) Dial(network, addr string) (c net.Conn, p string, err error) { - c, p, err = f.Dialer.Dial(network, addr) +func (f *Forwarder) Dial(network, addr string) (c net.Conn, err error) { + c, err = f.Dialer.Dial(network, addr) if err != nil { f.IncFailures() if f.Failures() >= f.MaxFailures() && f.Enabled() { @@ -107,7 +107,7 @@ func (f *Forwarder) Dial(network, addr string) (c net.Conn, p string, err error) } } - return c, p, err + return c, err } // Failures returns the failuer count of forwarder diff --git a/strategy/strategy.go b/strategy/strategy.go index 0ccd9df..ba3e932 100644 --- a/strategy/strategy.go +++ b/strategy/strategy.go @@ -32,8 +32,8 @@ func (p priSlice) Len() int { return len(p) } func (p priSlice) Less(i, j int) bool { return p[i].Priority() > p[j].Priority() } func (p priSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } -// Dialer is base dialer struct. -type Dialer struct { +// Proxy is base proxy struct. +type Proxy struct { config *Config fwdrs priSlice available []*Forwarder @@ -44,8 +44,8 @@ type Dialer struct { nextForwarder func(addr string) *Forwarder } -// NewDialer returns a new strategy dialer. -func NewDialer(s []string, c *Config) *Dialer { +// NewProxy returns a new strategy proxy. +func NewProxy(s []string, c *Config) *Proxy { var fwdrs []*Forwarder for _, chain := range s { fwdr, err := ForwarderFromURL(chain, c.IntFace) @@ -62,12 +62,12 @@ func NewDialer(s []string, c *Config) *Dialer { c.Strategy = "rr" } - return newDialer(fwdrs, c) + return newProxy(fwdrs, c) } -// newDialer returns a new rrDialer -func newDialer(fwdrs []*Forwarder, c *Config) *Dialer { - d := &Dialer{fwdrs: fwdrs, config: c} +// newProxy returns a new rrProxy +func newProxy(fwdrs []*Forwarder, c *Config) *Proxy { + d := &Proxy{fwdrs: fwdrs, config: c} sort.Sort(d.fwdrs) d.initAvailable() @@ -101,112 +101,103 @@ func newDialer(fwdrs []*Forwarder, c *Config) *Dialer { return d } -// Addr returns forwarder's address. -func (d *Dialer) Addr() string { - if d.fwdrs.Len() == 1 { - return d.fwdrs[0].Addr() - } - - return "STRATEGY" -} - // Dial connects to the address addr on the network net. -func (d *Dialer) Dial(network, addr string) (net.Conn, string, error) { - nd := d.NextDialer(addr) - c, _, err := nd.Dial(network, addr) +func (p *Proxy) Dial(network, addr string) (net.Conn, string, error) { + nd := p.NextDialer(addr) + c, err := nd.Dial(network, addr) return c, nd.Addr(), err } // DialUDP connects to the given address. -func (d *Dialer) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) { - return d.NextDialer(addr).DialUDP(network, addr) +func (p *Proxy) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) { + return p.NextDialer(addr).DialUDP(network, addr) } // NextDialer returns the next dialer. -func (d *Dialer) NextDialer(dstAddr string) proxy.Dialer { - d.mu.RLock() - defer d.mu.RUnlock() +func (p *Proxy) NextDialer(dstAddr string) proxy.Dialer { + p.mu.RLock() + defer p.mu.RUnlock() - return d.nextForwarder(dstAddr) + return p.nextForwarder(dstAddr) } // Priority returns the active priority of dialer. -func (d *Dialer) Priority() uint32 { return atomic.LoadUint32(&d.priority) } +func (p *Proxy) Priority() uint32 { return atomic.LoadUint32(&p.priority) } // SetPriority sets the active priority of daler. -func (d *Dialer) SetPriority(p uint32) { atomic.StoreUint32(&d.priority, p) } +func (p *Proxy) SetPriority(pri uint32) { atomic.StoreUint32(&p.priority, pri) } // initAvailable traverse d.fwdrs and init the available forwarder slice. -func (d *Dialer) initAvailable() { - for _, f := range d.fwdrs { +func (p *Proxy) initAvailable() { + for _, f := range p.fwdrs { if f.Enabled() { - d.SetPriority(f.Priority()) + p.SetPriority(f.Priority()) break } } - d.available = nil - for _, f := range d.fwdrs { - if f.Enabled() && f.Priority() >= d.Priority() { - d.available = append(d.available, f) + p.available = nil + for _, f := range p.fwdrs { + if f.Enabled() && f.Priority() >= p.Priority() { + p.available = append(p.available, f) } } - if len(d.available) == 0 { + if len(p.available) == 0 { // no available forwarders, set priority to 0 to check all forwarders in check func - d.SetPriority(0) - log.F("[strategy] no available forwarders, just use: %s, please check your settings or network", d.fwdrs[0].Addr()) - d.available = append(d.available, d.fwdrs[0]) + p.SetPriority(0) + log.F("[strategy] no available forwarders, just use: %s, please check your settings or network", p.fwdrs[0].Addr()) + p.available = append(p.available, p.fwdrs[0]) } } // onStatusChanged will be called when fwdr's status changed. -func (d *Dialer) onStatusChanged(fwdr *Forwarder) { - d.mu.Lock() - defer d.mu.Unlock() +func (p *Proxy) onStatusChanged(fwdr *Forwarder) { + p.mu.Lock() + defer p.mu.Unlock() if fwdr.Enabled() { log.F("[strategy] %s changed status from Disabled to Enabled ", fwdr.Addr()) - if fwdr.Priority() == d.Priority() { - d.available = append(d.available, fwdr) - } else if fwdr.Priority() > d.Priority() { - d.initAvailable() + if fwdr.Priority() == p.Priority() { + p.available = append(p.available, fwdr) + } else if fwdr.Priority() > p.Priority() { + p.initAvailable() } } else { log.F("[strategy] %s changed status from Enabled to Disabled", fwdr.Addr()) - for i, f := range d.available { + for i, f := range p.available { if f == fwdr { - d.available[i], d.available = d.available[len(d.available)-1], d.available[:len(d.available)-1] + p.available[i], p.available = p.available[len(p.available)-1], p.available[:len(p.available)-1] break } } } - if len(d.available) == 0 { - d.initAvailable() + if len(p.available) == 0 { + p.initAvailable() } } // Check implements the Checker interface. -func (d *Dialer) Check() { +func (p *Proxy) Check() { // no need to check when there's only 1 forwarder - if len(d.fwdrs) > 1 { - for i := 0; i < len(d.fwdrs); i++ { - go d.check(i) + if len(p.fwdrs) > 1 { + for i := 0; i < len(p.fwdrs); i++ { + go p.check(i) } } } -func (d *Dialer) check(i int) { - f := d.fwdrs[i] +func (p *Proxy) check(i int) { + f := p.fwdrs[i] retry := 1 buf := make([]byte, 4) for { - time.Sleep(time.Duration(d.config.CheckInterval) * time.Second * time.Duration(retry>>1)) + time.Sleep(time.Duration(p.config.CheckInterval) * time.Second * time.Duration(retry>>1)) // check all forwarders at least one time - if retry > 1 && f.Priority() < d.Priority() { + if retry > 1 && f.Priority() < p.Priority() { continue } @@ -216,10 +207,10 @@ func (d *Dialer) check(i int) { } startTime := time.Now() - rc, _, err := f.Dial("tcp", d.config.CheckWebSite) + rc, err := f.Dial("tcp", p.config.CheckWebSite) if err != nil { f.Disable() - log.F("[check] %s(%d) -> %s, DISABLED. error in dial: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, err) + log.F("[check] %s(%d) -> %s, DISABLED. error in dial: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, err) continue } @@ -228,24 +219,24 @@ func (d *Dialer) check(i int) { _, err = io.ReadFull(rc, buf) if err != nil { f.Disable() - log.F("[check] %s(%d) -> %s, DISABLED. error in read: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, err) + log.F("[check] %s(%d) -> %s, DISABLED. error in read: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, err) } else if bytes.Equal([]byte("HTTP"), buf) { readTime := time.Since(startTime) f.SetLatency(int64(readTime)) - if readTime > time.Duration(d.config.CheckTimeout)*time.Second { + if readTime > time.Duration(p.config.CheckTimeout)*time.Second { f.Disable() - log.F("[check] %s(%d) -> %s, DISABLED. check timeout: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, readTime) + log.F("[check] %s(%d) -> %s, DISABLED. check timeout: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, readTime) } else { retry = 2 f.Enable() - log.F("[check] %s(%d) -> %s, ENABLED. connect time: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, readTime) + log.F("[check] %s(%d) -> %s, ENABLED. connect time: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, readTime) } } else { f.Disable() - log.F("[check] %s(%d) -> %s, DISABLED. server response: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, buf) + log.F("[check] %s(%d) -> %s, DISABLED. server response: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, buf) } rc.Close() @@ -253,20 +244,20 @@ func (d *Dialer) check(i int) { } // Round Robin -func (d *Dialer) scheduleRR(dstAddr string) *Forwarder { - return d.available[atomic.AddUint32(&d.index, 1)%uint32(len(d.available))] +func (p *Proxy) scheduleRR(dstAddr string) *Forwarder { + return p.available[atomic.AddUint32(&p.index, 1)%uint32(len(p.available))] } // High Availability -func (d *Dialer) scheduleHA(dstAddr string) *Forwarder { - return d.available[0] +func (p *Proxy) scheduleHA(dstAddr string) *Forwarder { + return p.available[0] } // Latency based High Availability -func (d *Dialer) scheduleLHA(dstAddr string) *Forwarder { - fwdr := d.available[0] +func (p *Proxy) scheduleLHA(dstAddr string) *Forwarder { + fwdr := p.available[0] lowest := fwdr.Latency() - for _, f := range d.available { + for _, f := range p.available { if f.Latency() < lowest { lowest = f.Latency() fwdr = f @@ -276,8 +267,8 @@ func (d *Dialer) scheduleLHA(dstAddr string) *Forwarder { } // Destination Hashing -func (d *Dialer) scheduleDH(dstAddr string) *Forwarder { +func (p *Proxy) scheduleDH(dstAddr string) *Forwarder { fnv1a := fnv.New32a() fnv1a.Write([]byte(dstAddr)) - return d.available[fnv1a.Sum32()%uint32(len(d.available))] + return p.available[fnv1a.Sum32()%uint32(len(p.available))] }