diff --git a/README.md b/README.md index dfbc18e..70a5a38 100644 --- a/README.md +++ b/README.md @@ -38,25 +38,25 @@ scheme分为两部分: protocol+transport protocol: 代理协议类型(http, socks5, shadowsocks), transport: 数据传输方式(ws, wss, tls, http2, quic, kcp), 二者可以任意组合,或单独使用: -> http - 作为HTTP代理: http://:8080 +> http - HTTP代理: http://:8080 -> http+tls - 作为HTTPS代理(可能需要提供受信任的证书): http+tls://:443 +> http+tls - HTTPS代理(可能需要提供受信任的证书): http+tls://:443或https://:443 -> http2 - 作为HTTP2代理并向下兼容HTTPS代理: http2://:443 +> http2 - HTTP2代理并向下兼容HTTPS代理: http2://:443 -> socks - 作为标准SOCKS5代理(支持tls协商加密): socks://:1080 +> socks - 标准SOCKS5代理(支持tls协商加密): socks://:1080 -> socks+wss - 作为SOCKS5代理,使用websocket传输数据: socks+wss://:1080 +> socks+wss - SOCKS5代理,使用websocket传输数据: socks+wss://:1080 -> tls - 作为HTTPS/SOCKS5代理,使用tls传输数据: tls://:443 +> tls - HTTPS/SOCKS5代理,使用tls传输数据: tls://:443 -> ss - 作为Shadowsocks服务,ss://aes-256-cfb:123456@:8338 +> ss - Shadowsocks代理,ss://aes-256-cfb:123456@:8338 -> quic - 作为QUIC代理,quic://:6121 +> quic - QUIC代理,quic://:6121 -> kcp - 作为KCP代理,kcp://:8388或kcp://aes:123456@:8388 +> kcp - KCP代理,kcp://:8388或kcp://aes:123456@:8388 -> redirect - 作为透明代理,redirect://:12345 +> redirect - 透明代理,redirect://:12345 #### 端口转发 @@ -251,7 +251,6 @@ gost -L=kcp://:8388?c=/path/to/conf/file ``` **注:** 客户端若要开启KCP转发,当且仅当代理链不为空且首个代理节点(第一个-F参数)为kcp类型。 -当KCP转发开启,代理链中的其他代理节点将被忽略。 #### 透明代理 基于iptables的透明代理。 diff --git a/README_en.md b/README_en.md index 5daa2b5..16ba00e 100644 --- a/README_en.md +++ b/README_en.md @@ -40,7 +40,7 @@ transport: data transmission mode (ws, wss, tls, http2, quic, kcp), may be used > http - standard HTTP proxy: http://:8080 -> http+tls - standard HTTPS proxy (may need to provide a trusted certificate): http+tls://:443 +> http+tls - standard HTTPS proxy (may need to provide a trusted certificate): http+tls://:443 or https://:443 > http2 - HTTP2 proxy and backwards-compatible with HTTPS proxy: http2://:443 @@ -253,7 +253,6 @@ gost -L=kcp://:8388?c=/path/to/conf/file ``` **NOTE:** KCP will be enabled if and only if the proxy chain is not empty and the first proxy node (the first -F parameter) is of type KCP. -When KCP is enabled, other proxy nodes are ignored. #### Transparent proxy Iptables-based transparent proxy diff --git a/chain.go b/chain.go index 08c6638..9178067 100644 --- a/chain.go +++ b/chain.go @@ -69,7 +69,7 @@ func (c *ProxyChain) SetNode(index int, node ProxyNode) { } // Init initialize the proxy chain. -// KCP will be enabled if the first proxy node is KCP proxy (transport == kcp), the remaining nodes are ignored. +// KCP will be enabled if the first proxy node is KCP proxy (transport == kcp). // HTTP2 will be enabled when at least one HTTP2 proxy node (scheme == http2) is present. // // NOTE: Should be called immediately when proxy nodes are ready. @@ -81,6 +81,26 @@ func (c *ProxyChain) Init() { c.lastNode = &c.nodes[length-1] + // HTTP2 restrict: HTTP2 will be enabled when at least one HTTP2 proxy node is present. + for i, node := range c.nodes { + if node.Transport == "http2" { + glog.V(LINFO).Infoln("HTTP2 is enabled") + cfg := &tls.Config{ + InsecureSkipVerify: node.insecureSkipVerify(), + ServerName: node.serverName, + } + c.http2NodeIndex = i + c.initHttp2Client(cfg, c.nodes[:i]...) + break // shortest chain for HTTP2 + } + } + + for i, node := range c.nodes { + if node.Transport == "kcp" && i > 0 { + glog.Fatal("KCP must be the first node in the proxy chain") + } + } + if c.nodes[0].Transport == "kcp" { glog.V(LINFO).Infoln("KCP is enabled") c.kcpEnabled = true @@ -98,20 +118,6 @@ func (c *ProxyChain) Init() { c.kcpConfig = config return } - - // HTTP2 restrict: HTTP2 will be enabled when at least one HTTP2 proxy node is present. - for i, node := range c.nodes { - if node.Transport == "http2" { - glog.V(LINFO).Infoln("HTTP2 is enabled") - cfg := &tls.Config{ - InsecureSkipVerify: node.insecureSkipVerify(), - ServerName: node.serverName, - } - c.http2NodeIndex = i - c.initHttp2Client(cfg, c.nodes[:i]...) - break // shortest chain for HTTP2 - } - } } func (c *ProxyChain) KCPEnabled() bool { @@ -198,19 +204,6 @@ func (c *ProxyChain) GetConn() (net.Conn, error) { return nil, ErrEmptyChain } - if c.KCPEnabled() { - kcpConn, err := c.getKCPConn() - if err != nil { - return nil, err - } - pc := NewProxyConn(kcpConn, c.nodes[0]) - if err := pc.Handshake(); err != nil { - pc.Close() - return nil, err - } - return pc, nil - } - if c.Http2Enabled() { nodes = nodes[c.http2NodeIndex+1:] if len(nodes) == 0 { @@ -243,23 +236,6 @@ func (c *ProxyChain) dialWithNodes(withHttp2 bool, addr string, nodes ...ProxyNo return net.DialTimeout("tcp", addr, DialTimeout) } - if c.KCPEnabled() { - kcpConn, err := c.getKCPConn() - if err != nil { - return nil, err - } - pc := NewProxyConn(kcpConn, nodes[0]) - if err := pc.Handshake(); err != nil { - pc.Close() - return nil, err - } - if err := pc.Connect(addr); err != nil { - pc.Close() - return nil, err - } - return pc, nil - } - if withHttp2 && c.Http2Enabled() { nodes = nodes[c.http2NodeIndex+1:] if len(nodes) == 0 { @@ -291,6 +267,8 @@ func (c *ProxyChain) travelNodes(withHttp2 bool, nodes ...ProxyNode) (conn *Prox if withHttp2 && c.Http2Enabled() { cc, err = c.http2Connect(node.Addr) + } else if node.Transport == "kcp" { + cc, err = c.getKCPConn() } else { cc, err = net.DialTimeout("tcp", node.Addr, DialTimeout) } @@ -300,19 +278,20 @@ func (c *ProxyChain) travelNodes(withHttp2 bool, nodes ...ProxyNode) (conn *Prox setKeepAlive(cc, KeepAliveTime) pc := NewProxyConn(cc, node) + conn = pc if err = pc.Handshake(); err != nil { return } - conn = pc + for _, node := range nodes[1:] { if err = conn.Connect(node.Addr); err != nil { return } pc := NewProxyConn(conn, node) + conn = pc if err = pc.Handshake(); err != nil { return } - conn = pc } return } diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/chain.go b/cmd/gost/vendor/github.com/ginuerzh/gost/chain.go index 08c6638..fafd7ab 100644 --- a/cmd/gost/vendor/github.com/ginuerzh/gost/chain.go +++ b/cmd/gost/vendor/github.com/ginuerzh/gost/chain.go @@ -81,6 +81,26 @@ func (c *ProxyChain) Init() { c.lastNode = &c.nodes[length-1] + // HTTP2 restrict: HTTP2 will be enabled when at least one HTTP2 proxy node is present. + for i, node := range c.nodes { + if node.Transport == "http2" { + glog.V(LINFO).Infoln("HTTP2 is enabled") + cfg := &tls.Config{ + InsecureSkipVerify: node.insecureSkipVerify(), + ServerName: node.serverName, + } + c.http2NodeIndex = i + c.initHttp2Client(cfg, c.nodes[:i]...) + break // shortest chain for HTTP2 + } + } + + for i, node := range c.nodes { + if node.Transport == "kcp" && i > 0 { + glog.Fatal("KCP must be the first node in the proxy chain") + } + } + if c.nodes[0].Transport == "kcp" { glog.V(LINFO).Infoln("KCP is enabled") c.kcpEnabled = true @@ -98,20 +118,6 @@ func (c *ProxyChain) Init() { c.kcpConfig = config return } - - // HTTP2 restrict: HTTP2 will be enabled when at least one HTTP2 proxy node is present. - for i, node := range c.nodes { - if node.Transport == "http2" { - glog.V(LINFO).Infoln("HTTP2 is enabled") - cfg := &tls.Config{ - InsecureSkipVerify: node.insecureSkipVerify(), - ServerName: node.serverName, - } - c.http2NodeIndex = i - c.initHttp2Client(cfg, c.nodes[:i]...) - break // shortest chain for HTTP2 - } - } } func (c *ProxyChain) KCPEnabled() bool { @@ -198,19 +204,6 @@ func (c *ProxyChain) GetConn() (net.Conn, error) { return nil, ErrEmptyChain } - if c.KCPEnabled() { - kcpConn, err := c.getKCPConn() - if err != nil { - return nil, err - } - pc := NewProxyConn(kcpConn, c.nodes[0]) - if err := pc.Handshake(); err != nil { - pc.Close() - return nil, err - } - return pc, nil - } - if c.Http2Enabled() { nodes = nodes[c.http2NodeIndex+1:] if len(nodes) == 0 { @@ -243,23 +236,6 @@ func (c *ProxyChain) dialWithNodes(withHttp2 bool, addr string, nodes ...ProxyNo return net.DialTimeout("tcp", addr, DialTimeout) } - if c.KCPEnabled() { - kcpConn, err := c.getKCPConn() - if err != nil { - return nil, err - } - pc := NewProxyConn(kcpConn, nodes[0]) - if err := pc.Handshake(); err != nil { - pc.Close() - return nil, err - } - if err := pc.Connect(addr); err != nil { - pc.Close() - return nil, err - } - return pc, nil - } - if withHttp2 && c.Http2Enabled() { nodes = nodes[c.http2NodeIndex+1:] if len(nodes) == 0 { @@ -291,6 +267,8 @@ func (c *ProxyChain) travelNodes(withHttp2 bool, nodes ...ProxyNode) (conn *Prox if withHttp2 && c.Http2Enabled() { cc, err = c.http2Connect(node.Addr) + } else if node.Transport == "kcp" { + cc, err = c.getKCPConn() } else { cc, err = net.DialTimeout("tcp", node.Addr, DialTimeout) } @@ -300,19 +278,20 @@ func (c *ProxyChain) travelNodes(withHttp2 bool, nodes ...ProxyNode) (conn *Prox setKeepAlive(cc, KeepAliveTime) pc := NewProxyConn(cc, node) + conn = pc if err = pc.Handshake(); err != nil { return } - conn = pc + for _, node := range nodes[1:] { if err = conn.Connect(node.Addr); err != nil { return } pc := NewProxyConn(conn, node) + conn = pc if err = pc.Handshake(); err != nil { return } - conn = pc } return } diff --git a/cmd/gost/vendor/vendor.json b/cmd/gost/vendor/vendor.json index 29a2d68..af5f577 100644 --- a/cmd/gost/vendor/vendor.json +++ b/cmd/gost/vendor/vendor.json @@ -15,10 +15,10 @@ "revisionTime": "2017-01-19T05:34:58Z" }, { - "checksumSHA1": "g55EnuSESwa92RY7U+shNoPi900=", + "checksumSHA1": "oZV/w2ONwoM0nMDddIJQYDAZOPg=", "path": "github.com/ginuerzh/gost", - "revision": "0585749a819f33404f369650e74716cddf4ed3b7", - "revisionTime": "2017-01-19T05:40:53Z" + "revision": "c1d79272573ada276e5a4234774ea4c2e2b4e9ef", + "revisionTime": "2017-01-19T05:42:02Z" }, { "checksumSHA1": "URsJa4y/sUUw/STmbeYx9EKqaYE=", diff --git a/gost.go b/gost.go index ed2977f..77a5892 100644 --- a/gost.go +++ b/gost.go @@ -11,7 +11,7 @@ import ( ) const ( - Version = "2.3-rc2" + Version = "2.3-rc3" ) // Log level for glog