-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
rui.zheng
committed
Oct 26, 2015
1 parent
ab6e857
commit f598779
Showing
4 changed files
with
159 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
gost 2.0 - GO Simple Tunnel | ||
gost - GO Simple Tunnel | ||
==== | ||
|
||
### GO语言实现的安全隧道 | ||
|
@@ -15,7 +15,25 @@ gost 2.0 - GO Simple Tunnel | |
|
||
Google讨论组: https://groups.google.com/d/forum/go-gost | ||
|
||
在gost 2.0中,没有了客户端-服务器的概念,gost与其他代理服务都被看作是代理节点(proxy node),gost可以自己处理请求,或者将请求转发给任意一个或多个代理节点。 | ||
在gost中,gost与其他代理服务都被看作是代理节点(proxy node),gost可以自己处理请求,或者将请求转发给任意一个或多个代理节点。 | ||
|
||
#### 参数说明 | ||
|
||
-L和-F参数格式:[scheme://][user:pass@host]:port | ||
|
||
scheme分为两部分: protocol - 代理协议类型(http, socks5, shadowsocks), transport - 数据传输方式(tcp, websocket, tls)。 | ||
|
||
> http - 作为标准http代理: http://:8080 | ||
> http+tls - 作为http代理,使用tls传输数据: http+tls://:8080 | ||
> socks - 作为标准socks5代理: socks://:8080 | ||
> socks+ws -作为socks5代理,使用websocket传输数据: socks+ws://:8080 | ||
> tls - 作为http/socks5代理,使用tls传输数据: tls://:8080 | ||
> ss - 作为shadowsocks服务,ss://aes-256-cfb:123456@:8080 | ||
#### 使用方法 | ||
|
||
|
@@ -34,23 +52,9 @@ gost -L=admin:123456@localhost:8080 | |
|
||
* 多端口监听 | ||
```bash | ||
gost -L=http://localhost:8080 -L=socks://localhost:8081 | ||
gost -L=http://localhost:8080 -L=socks://localhost:8081 -L=ss://aes-256-cfb:123456@:8082 | ||
``` | ||
|
||
-L参数格式:[scheme://][user:pass@host]:port | ||
|
||
scheme分为两部分: protocol - 代理协议类型(http, socks5, shadowsocks), transport - 数据传输方式(tcp, websocket, tls)。 | ||
|
||
> http - 作为http代理: http://:8080 | ||
> http+tls - 作为http代理,使用tls传输数据: http+tls://:8080 | ||
> socks - 作为socks5代理: socks://:8080 | ||
> socks+ws -作为socks5代理,使用websocket传输数据: socks+ws://:8080 | ||
|
||
|
||
##### 设置转发代理 | ||
|
||
<img src="https://ginuerzh.github.io/images/gost_02.png" /> | ||
|
@@ -60,14 +64,14 @@ gost -L=:8080 -F=192.168.1.1:8081 | |
|
||
* 转发代理认证 | ||
```bash | ||
gost -L=:8080 -F=admin:[email protected]:8081 | ||
gost -L=:8080 -F=http://admin:[email protected]:8081 | ||
``` | ||
|
||
##### 设置多个转发代理(转发链) | ||
|
||
<img src="https://ginuerzh.github.io/images/gost_03.png" /> | ||
```bash | ||
gost -L=:8080 -F=http://192.168.1.1:8081 -F socks://192.168.1.2:8082 -F=··· -F=a.b.c.d:NNNN | ||
gost -L=:8080 -F=http+tls://192.168.1.1:8081 -F socks+ws://192.168.1.2:8082 -F=··· -F=a.b.c.d:NNNN | ||
``` | ||
gost通过转发链按照-F设置顺序将请求最终转发给a.b.c.d:NNNN处理,每一个转发代理可以是任意一种类型的代理(http/socks5) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/binary" | ||
"fmt" | ||
"github.com/ginuerzh/gosocks5" | ||
"github.com/golang/glog" | ||
"github.com/shadowsocks/shadowsocks-go/shadowsocks" | ||
"io" | ||
"net" | ||
) | ||
|
||
func handleShadow(conn net.Conn, arg Args) { | ||
if arg.User != nil { | ||
method := arg.User.Username() | ||
password, _ := arg.User.Password() | ||
cipher, err := shadowsocks.NewCipher(method, password) | ||
if err != nil { | ||
if glog.V(LWARNING) { | ||
glog.Warningln("shadowsocks:", err) | ||
} | ||
return | ||
} | ||
conn = shadowsocks.NewConn(conn, cipher) | ||
} | ||
|
||
addr, extra, err := getShadowRequest(conn) | ||
if err != nil { | ||
if glog.V(LWARNING) { | ||
glog.Warningln("shadowsocks:", err) | ||
} | ||
return | ||
} | ||
if glog.V(LINFO) { | ||
glog.Infoln("shadowsocks connect:", addr.String()) | ||
} | ||
sconn, err := Connect(addr.String()) | ||
if err != nil { | ||
if glog.V(LWARNING) { | ||
glog.Warningln("shadowsocks:", err) | ||
} | ||
return | ||
} | ||
defer sconn.Close() | ||
|
||
if extra != nil { | ||
if _, err := sconn.Write(extra); err != nil { | ||
if glog.V(LWARNING) { | ||
glog.Warningln("shadowsocks:", err) | ||
} | ||
return | ||
} | ||
} | ||
|
||
Transport(conn, sconn) | ||
} | ||
|
||
func getShadowRequest(conn net.Conn) (addr *gosocks5.Addr, extra []byte, err error) { | ||
const ( | ||
idType = 0 // address type index | ||
idIP0 = 1 // ip addres start index | ||
idDmLen = 1 // domain address length index | ||
idDm0 = 2 // domain address start index | ||
|
||
typeIPv4 = 1 // type is ipv4 address | ||
typeDm = 3 // type is domain address | ||
typeIPv6 = 4 // type is ipv6 address | ||
|
||
lenIPv4 = 1 + net.IPv4len + 2 // 1addrType + ipv4 + 2port | ||
lenIPv6 = 1 + net.IPv6len + 2 // 1addrType + ipv6 + 2port | ||
lenDmBase = 1 + 1 + 2 // 1addrType + 1addrLen + 2port, plus addrLen | ||
) | ||
|
||
// buf size should at least have the same size with the largest possible | ||
// request size (when addrType is 3, domain name has at most 256 bytes) | ||
// 1(addrType) + 1(lenByte) + 256(max length address) + 2(port) | ||
buf := make([]byte, 1024) | ||
|
||
var n int | ||
// read till we get possible domain length field | ||
//shadowsocks.SetReadTimeout(conn) | ||
if n, err = io.ReadAtLeast(conn, buf, idDmLen+1); err != nil { | ||
return | ||
} | ||
|
||
addr = &gosocks5.Addr{ | ||
Type: buf[idType], | ||
} | ||
|
||
reqLen := -1 | ||
switch buf[idType] { | ||
case typeIPv4: | ||
reqLen = lenIPv4 | ||
case typeIPv6: | ||
reqLen = lenIPv6 | ||
case typeDm: | ||
reqLen = int(buf[idDmLen]) + lenDmBase | ||
default: | ||
err = fmt.Errorf("addr type %d not supported", buf[idType]) | ||
return | ||
} | ||
|
||
if n < reqLen { // rare case | ||
//ss.SetReadTimeout(conn) | ||
if _, err = io.ReadFull(conn, buf[n:reqLen]); err != nil { | ||
return | ||
} | ||
} else if n > reqLen { | ||
// it's possible to read more than just the request head | ||
extra = buf[reqLen:n] | ||
} | ||
|
||
// Return string for typeIP is not most efficient, but browsers (Chrome, | ||
// Safari, Firefox) all seems using typeDm exclusively. So this is not a | ||
// big problem. | ||
switch buf[idType] { | ||
case typeIPv4: | ||
addr.Host = net.IP(buf[idIP0 : idIP0+net.IPv4len]).String() | ||
case typeIPv6: | ||
addr.Host = net.IP(buf[idIP0 : idIP0+net.IPv6len]).String() | ||
case typeDm: | ||
addr.Host = string(buf[idDm0 : idDm0+buf[idDmLen]]) | ||
} | ||
// parse port | ||
addr.Port = binary.BigEndian.Uint16(buf[reqLen-2 : reqLen]) | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters