#69 KCP client now supports proxy chain
This commit is contained in:
parent
c1d7927257
commit
2dd7ace3ce
21
README.md
21
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的透明代理。
|
||||
|
@ -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
|
||||
|
73
chain.go
73
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
|
||||
}
|
||||
|
71
cmd/gost/vendor/github.com/ginuerzh/gost/chain.go
generated
vendored
71
cmd/gost/vendor/github.com/ginuerzh/gost/chain.go
generated
vendored
@ -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
|
||||
}
|
||||
|
6
cmd/gost/vendor/vendor.json
vendored
6
cmd/gost/vendor/vendor.json
vendored
@ -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=",
|
||||
|
Loading…
Reference in New Issue
Block a user