From b16f878c39bf8d89f36265e069cf518e1079af8c Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Sat, 10 Nov 2018 12:16:46 +0800 Subject: [PATCH] add ConnectOptions for Connector.Connect --- chain.go | 6 +++--- client.go | 25 ++++++++++++++++++++----- forward.go | 2 +- gost.go | 2 +- handler.go | 2 +- http.go | 2 +- http2.go | 13 +++++++++++-- reload.go | 4 +--- sni.go | 2 +- socks.go | 34 +++++++++++++++++++++------------- ss.go | 2 +- ssh.go | 4 ++-- 12 files changed, 64 insertions(+), 34 deletions(-) diff --git a/chain.go b/chain.go index d9d6682..22ea44f 100644 --- a/chain.go +++ b/chain.go @@ -132,10 +132,10 @@ func (c *Chain) dialWithOptions(addr string, options *ChainOptions) (net.Conn, e return nil, err } - addr = c.resolve(addr, options.Resolver, options.Hosts) + ipAddr := c.resolve(addr, options.Resolver, options.Hosts) if route.IsEmpty() { - return net.DialTimeout("tcp", addr, options.Timeout) + return net.DialTimeout("tcp", ipAddr, options.Timeout) } conn, err := route.getConn() @@ -143,7 +143,7 @@ func (c *Chain) dialWithOptions(addr string, options *ChainOptions) (net.Conn, e return nil, err } - cc, err := route.LastNode().Client.Connect(conn, addr) + cc, err := route.LastNode().Client.Connect(conn, addr, IPAddrConnectOption(ipAddr)) if err != nil { conn.Close() return nil, err diff --git a/client.go b/client.go index 920dd30..e563059 100644 --- a/client.go +++ b/client.go @@ -27,8 +27,8 @@ func (c *Client) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, } // Connect connects to the address addr via the proxy over connection conn. -func (c *Client) Connect(conn net.Conn, addr string) (net.Conn, error) { - return c.Connector.Connect(conn, addr) +func (c *Client) Connect(conn net.Conn, addr string, options ...ConnectOption) (net.Conn, error) { + return c.Connector.Connect(conn, addr, options...) } // DefaultClient is a standard HTTP proxy client. @@ -51,7 +51,7 @@ func Connect(conn net.Conn, addr string) (net.Conn, error) { // Connector is responsible for connecting to the destination address. type Connector interface { - Connect(conn net.Conn, addr string) (net.Conn, error) + Connect(conn net.Conn, addr string, options ...ConnectOption) (net.Conn, error) } // Transporter is responsible for handshaking with the proxy server. @@ -96,7 +96,7 @@ type DialOptions struct { Chain *Chain } -// DialOption allows a common way to set dial options. +// DialOption allows a common way to set DialOptions. type DialOption func(opts *DialOptions) // TimeoutDialOption specifies the timeout used by Transporter.Dial @@ -127,7 +127,7 @@ type HandshakeOptions struct { QUICConfig *QUICConfig } -// HandshakeOption allows a common way to set handshake options. +// HandshakeOption allows a common way to set HandshakeOptions. type HandshakeOption func(opts *HandshakeOptions) // AddrHandshakeOption specifies the server address @@ -199,3 +199,18 @@ func QUICConfigHandshakeOption(config *QUICConfig) HandshakeOption { opts.QUICConfig = config } } + +// ConnectOptions describes the options for Connector.Connect. +type ConnectOptions struct { + IPAddr string +} + +// ConnectOption allows a common way to set ConnectOptions. +type ConnectOption func(opts *ConnectOptions) + +// IPAddrConnectOption specifies the corresponding IP:PORT of the connected target address. +func IPAddrConnectOption(ipAddr string) ConnectOption { + return func(opts *ConnectOptions) { + opts.IPAddr = ipAddr + } +} diff --git a/forward.go b/forward.go index 715e4a6..ab67c2b 100644 --- a/forward.go +++ b/forward.go @@ -22,7 +22,7 @@ func ForwardConnector() Connector { return &forwardConnector{} } -func (c *forwardConnector) Connect(conn net.Conn, addr string) (net.Conn, error) { +func (c *forwardConnector) Connect(conn net.Conn, addr string, options ...ConnectOption) (net.Conn, error) { return conn, nil } diff --git a/gost.go b/gost.go index db4f621..bec6f23 100644 --- a/gost.go +++ b/gost.go @@ -14,7 +14,7 @@ import ( ) // Version is the gost version. -const Version = "2.6" +const Version = "2.7-dev" // Debug is a flag that enables the debug log. var Debug bool diff --git a/handler.go b/handler.go index d19855b..705ac62 100644 --- a/handler.go +++ b/handler.go @@ -145,7 +145,7 @@ func (h *autoHandler) Handle(conn net.Conn) { br := bufio.NewReader(conn) b, err := br.Peek(1) if err != nil { - log.Log(err) + log.Logf("[auto] %s - %s: %s", conn.RemoteAddr(), conn.LocalAddr(), err) conn.Close() return } diff --git a/http.go b/http.go index 5287232..8ea090d 100644 --- a/http.go +++ b/http.go @@ -24,7 +24,7 @@ func HTTPConnector(user *url.Userinfo) Connector { return &httpConnector{User: user} } -func (c *httpConnector) Connect(conn net.Conn, addr string) (net.Conn, error) { +func (c *httpConnector) Connect(conn net.Conn, addr string, options ...ConnectOption) (net.Conn, error) { req := &http.Request{ Method: http.MethodConnect, URL: &url.URL{Host: addr}, diff --git a/http2.go b/http2.go index 6fc0392..988d2cd 100644 --- a/http2.go +++ b/http2.go @@ -28,7 +28,12 @@ func HTTP2Connector(user *url.Userinfo) Connector { return &http2Connector{User: user} } -func (c *http2Connector) Connect(conn net.Conn, addr string) (net.Conn, error) { +func (c *http2Connector) Connect(conn net.Conn, addr string, options ...ConnectOption) (net.Conn, error) { + var cOpts ConnectOptions + for _, opt := range options { + opt(&cOpts) + } + cc, ok := conn.(*http2ClientConn) if !ok { return nil, errors.New("wrong connection type") @@ -75,6 +80,10 @@ func (c *http2Connector) Connect(conn net.Conn, addr string) (net.Conn, error) { w: pw, closed: make(chan struct{}), } + + if cOpts.IPAddr != "" { + addr = cOpts.IPAddr + } hc.remoteAddr, _ = net.ResolveTCPAddr("tcp", addr) hc.localAddr, _ = net.ResolveTCPAddr("tcp", cc.addr) @@ -526,7 +535,7 @@ func H2CListener(addr string) (Listener, error) { l := &h2Listener{ Listener: tcpKeepAliveListener{ln.(*net.TCPListener)}, server: &http2.Server{ - // MaxConcurrentStreams: 1000, + // MaxConcurrentStreams: 1000, }, connChan: make(chan net.Conn, 1024), errChan: make(chan error, 1), diff --git a/reload.go b/reload.go index 6e7bfa5..5b96d8c 100644 --- a/reload.go +++ b/reload.go @@ -30,9 +30,7 @@ func PeriodReload(r Reloader, configFile string) error { } mt := finfo.ModTime() if !mt.Equal(lastMod) { - if Debug { - log.Log("[reload]", configFile) - } + log.Log("[reload]", configFile) r.Reload(f) lastMod = mt } diff --git a/sni.go b/sni.go index 30c65a2..e9b3615 100644 --- a/sni.go +++ b/sni.go @@ -28,7 +28,7 @@ func SNIConnector(host string) Connector { return &sniConnector{host: host} } -func (c *sniConnector) Connect(conn net.Conn, addr string) (net.Conn, error) { +func (c *sniConnector) Connect(conn net.Conn, addr string, options ...ConnectOption) (net.Conn, error) { return &sniClientConn{addr: addr, host: c.host, Conn: conn}, nil } diff --git a/socks.go b/socks.go index b1bb24a..8881471 100644 --- a/socks.go +++ b/socks.go @@ -148,11 +148,11 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con req, err := gosocks5.ReadUserPassRequest(conn) if err != nil { - log.Log("[socks5]", err) + log.Logf("[socks5] %s - %s: %s", conn.RemoteAddr(), conn.LocalAddr(), err) return nil, err } if Debug { - log.Log("[socks5]", req.String()) + log.Logf("[socks5] %s - %s: %s", conn.RemoteAddr(), conn.LocalAddr(), req.String()) } valid := false for _, user := range selector.Users { @@ -168,23 +168,23 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con if len(selector.Users) > 0 && !valid { resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Failure) if err := resp.Write(conn); err != nil { - log.Log("[socks5]", err) + log.Logf("[socks5] %s - %s: %s", conn.RemoteAddr(), conn.LocalAddr(), err) return nil, err } if Debug { - log.Log("[socks5]", resp) + log.Log("[socks5] %s - %s: %s", conn.RemoteAddr(), conn.LocalAddr(), resp) } - log.Log("[socks5] proxy authentication required") + log.Logf("[socks5] %s - %s: proxy authentication required", conn.RemoteAddr(), conn.LocalAddr()) return nil, gosocks5.ErrAuthFailure } resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Succeeded) if err := resp.Write(conn); err != nil { - log.Log("[socks5]", err) + log.Logf("[socks5] %s - %s: %s", conn.RemoteAddr(), conn.LocalAddr(), err) return nil, err } if Debug { - log.Log("[socks5]", resp) + log.Logf("[socks5] %s - %s: %s", conn.RemoteAddr(), conn.LocalAddr(), resp) } case gosocks5.MethodNoAcceptable: return nil, gosocks5.ErrBadMethod @@ -203,7 +203,7 @@ func SOCKS5Connector(user *url.Userinfo) Connector { return &socks5Connector{User: user} } -func (c *socks5Connector) Connect(conn net.Conn, addr string) (net.Conn, error) { +func (c *socks5Connector) Connect(conn net.Conn, addr string, options ...ConnectOption) (net.Conn, error) { selector := &clientSelector{ TLSConfig: &tls.Config{InsecureSkipVerify: true}, User: c.User, @@ -261,7 +261,15 @@ func SOCKS4Connector() Connector { return &socks4Connector{} } -func (c *socks4Connector) Connect(conn net.Conn, addr string) (net.Conn, error) { +func (c *socks4Connector) Connect(conn net.Conn, addr string, options ...ConnectOption) (net.Conn, error) { + var cOpts ConnectOptions + for _, opt := range options { + opt(&cOpts) + } + if cOpts.IPAddr != "" { + addr = cOpts.IPAddr + } + taddr, err := net.ResolveTCPAddr("tcp4", addr) if err != nil { return nil, err @@ -308,7 +316,7 @@ func SOCKS4AConnector() Connector { return &socks4aConnector{} } -func (c *socks4aConnector) Connect(conn net.Conn, addr string) (net.Conn, error) { +func (c *socks4aConnector) Connect(conn net.Conn, addr string, options ...ConnectOption) (net.Conn, error) { host, port, err := net.SplitHostPort(addr) if err != nil { return nil, err @@ -322,7 +330,7 @@ func (c *socks4aConnector) Connect(conn net.Conn, addr string) (net.Conn, error) } if Debug { - log.Logf("[socks4] %s", req) + log.Logf("[socks4a] %s", req) } reply, err := gosocks4.ReadReply(conn) @@ -331,11 +339,11 @@ func (c *socks4aConnector) Connect(conn net.Conn, addr string) (net.Conn, error) } if Debug { - log.Logf("[socks4] %s", reply) + log.Logf("[socks4a] %s", reply) } if reply.Code != gosocks4.Granted { - return nil, fmt.Errorf("[socks4] %d", reply.Code) + return nil, fmt.Errorf("[socks4a] %d", reply.Code) } return conn, nil diff --git a/ss.go b/ss.go index 42cd419..b44d726 100644 --- a/ss.go +++ b/ss.go @@ -67,7 +67,7 @@ func ShadowConnector(cipher *url.Userinfo) Connector { return &shadowConnector{Cipher: cipher} } -func (c *shadowConnector) Connect(conn net.Conn, addr string) (net.Conn, error) { +func (c *shadowConnector) Connect(conn net.Conn, addr string, options ...ConnectOption) (net.Conn, error) { rawaddr, err := ss.RawAddr(addr) if err != nil { return nil, err diff --git a/ssh.go b/ssh.go index 67ddfbe..d649a7f 100644 --- a/ssh.go +++ b/ssh.go @@ -39,7 +39,7 @@ func SSHDirectForwardConnector() Connector { return &sshDirectForwardConnector{} } -func (c *sshDirectForwardConnector) Connect(conn net.Conn, raddr string) (net.Conn, error) { +func (c *sshDirectForwardConnector) Connect(conn net.Conn, raddr string, options ...ConnectOption) (net.Conn, error) { cc, ok := conn.(*sshNopConn) // TODO: this is an ugly type assertion, need to find a better solution. if !ok { return nil, errors.New("ssh: wrong connection type") @@ -60,7 +60,7 @@ func SSHRemoteForwardConnector() Connector { return &sshRemoteForwardConnector{} } -func (c *sshRemoteForwardConnector) Connect(conn net.Conn, addr string) (net.Conn, error) { +func (c *sshRemoteForwardConnector) Connect(conn net.Conn, addr string, options ...ConnectOption) (net.Conn, error) { cc, ok := conn.(*sshNopConn) // TODO: this is an ugly type assertion, need to find a better solution. if !ok { return nil, errors.New("ssh: wrong connection type")