socks udp tunnel
This commit is contained in:
parent
467ea676d3
commit
c4a1b96ba2
11
README.md
11
README.md
@ -67,7 +67,7 @@ gost -L=admin:123456@localhost:8080
|
|||||||
|
|
||||||
* 多端口监听
|
* 多端口监听
|
||||||
```bash
|
```bash
|
||||||
gost -L=http://localhost:8080 -L=socks://localhost:8081 -L=ss://aes-256-cfb:123456@:8082
|
gost -L=:8080 -L=ss://aes-256-cfb:123456@:8081
|
||||||
```
|
```
|
||||||
|
|
||||||
##### 设置转发代理
|
##### 设置转发代理
|
||||||
@ -88,28 +88,29 @@ gost -L=:8080 -F=http://admin:123456@192.168.1.1:8081
|
|||||||
```bash
|
```bash
|
||||||
gost -L=:8080 -F=http://192.168.1.1:8081 -F=socks://192.168.1.2:8082 -F=a.b.c.d:NNNN
|
gost -L=:8080 -F=http://192.168.1.1:8081 -F=socks://192.168.1.2:8082 -F=a.b.c.d:NNNN
|
||||||
```
|
```
|
||||||
gost按照-F设置顺序通过转发链将请求最终转发给a.b.c.d:NNNN处理,每一个转发代理可以是任意一种类型的代理(http/socks5)。
|
gost按照-F设置顺序通过转发链将请求最终转发给a.b.c.d:NNNN处理,每一个转发代理可以是任意http/socks5类型代理。
|
||||||
|
|
||||||
|
|
||||||
#### SOCKS5 UDP数据处理
|
#### SOCKS5 UDP数据处理
|
||||||
|
|
||||||
##### 不设置转发代理
|
##### 不设置转发代理
|
||||||
|
|
||||||
<img src="https://ginuerzh.github.io/images/udp01.png" height=110 />
|
<img src="https://ginuerzh.github.io/images/udp01.png" height=100 />
|
||||||
|
|
||||||
gost作为标准socks5代理处理UDP数据
|
gost作为标准socks5代理处理UDP数据
|
||||||
|
|
||||||
##### 设置转发代理
|
##### 设置转发代理
|
||||||
|
|
||||||
<img src="https://ginuerzh.github.io/images/udp02.png" height=110 />
|
<img src="https://ginuerzh.github.io/images/udp02.png" height=100 />
|
||||||
|
|
||||||
##### 设置多个转发代理(转发链)
|
##### 设置多个转发代理(转发链)
|
||||||
|
|
||||||
<img src="https://ginuerzh.github.io/images/udp03.png" height=200 />
|
<img src="https://ginuerzh.github.io/images/udp03.png" height=200 />
|
||||||
|
|
||||||
当设置转发代理时,gost会使用UDP over TCP方式转发UDP数据。
|
当设置转发代理时,gost会使用UDP-Over-TCP方式转发UDP数据。proxy1 - proxyN可以为任意http/socks5类型代理。
|
||||||
|
|
||||||
##### 限制条件
|
##### 限制条件
|
||||||
|
|
||||||
如果要转发socks5的BIND和UDP请求,转发链的末端(最后一个-F参数)必须是gost socks5类型代理,且转发链中的http代理必须支持CONNECT方法。
|
如果要转发socks5的BIND和UDP请求,转发链的末端(最后一个-F参数)必须是gost socks5类型代理,且转发链中的http代理必须支持CONNECT方法。
|
||||||
|
|
||||||
|
|
||||||
|
35
http.go
35
http.go
@ -34,29 +34,21 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
|
|||||||
"Proxy-Agent: gost/" + Version + "\r\n\r\n"
|
"Proxy-Agent: gost/" + Version + "\r\n\r\n"
|
||||||
|
|
||||||
if _, err := conn.Write([]byte(resp)); err != nil {
|
if _, err := conn.Write([]byte(resp)); err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln(err)
|
||||||
glog.Warningln(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if glog.V(LDEBUG) {
|
|
||||||
glog.Infoln(resp)
|
|
||||||
}
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("http: proxy authentication required")
|
|
||||||
}
|
}
|
||||||
|
glog.V(LDEBUG).Infoln(resp)
|
||||||
|
|
||||||
|
glog.V(LWARNING).Infoln("http: proxy authentication required")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := Connect(req.Host)
|
c, err := Connect(req.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln(err)
|
||||||
glog.Warningln(err)
|
|
||||||
}
|
|
||||||
b := []byte("HTTP/1.1 503 Service unavailable\r\n" +
|
b := []byte("HTTP/1.1 503 Service unavailable\r\n" +
|
||||||
"Proxy-Agent: gost/" + Version + "\r\n\r\n")
|
"Proxy-Agent: gost/" + Version + "\r\n\r\n")
|
||||||
if glog.V(LDEBUG) {
|
glog.V(LDEBUG).Infoln(string(b))
|
||||||
glog.Infoln(string(b))
|
|
||||||
}
|
|
||||||
conn.Write(b)
|
conn.Write(b)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -65,13 +57,10 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
|
|||||||
if req.Method == "CONNECT" {
|
if req.Method == "CONNECT" {
|
||||||
b := []byte("HTTP/1.1 200 Connection established\r\n" +
|
b := []byte("HTTP/1.1 200 Connection established\r\n" +
|
||||||
"Proxy-Agent: gost/" + Version + "\r\n\r\n")
|
"Proxy-Agent: gost/" + Version + "\r\n\r\n")
|
||||||
if glog.V(LDEBUG) {
|
glog.V(LDEBUG).Infoln(string(b))
|
||||||
glog.Infoln(string(b))
|
|
||||||
}
|
|
||||||
if _, err := conn.Write(b); err != nil {
|
if _, err := conn.Write(b); err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln(err)
|
||||||
glog.Warningln(err)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -81,9 +70,7 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
|
|||||||
err = req.Write(c)
|
err = req.Write(c)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln(err)
|
||||||
glog.Warningln(err)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
613
socks.go
613
socks.go
@ -47,27 +47,19 @@ func (selector *clientSelector) OnSelected(method uint8, conn net.Conn) (net.Con
|
|||||||
|
|
||||||
req := gosocks5.NewUserPassRequest(gosocks5.UserPassVer, username, password)
|
req := gosocks5.NewUserPassRequest(gosocks5.UserPassVer, username, password)
|
||||||
if err := req.Write(conn); err != nil {
|
if err := req.Write(conn); err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("socks5 auth:", err)
|
||||||
glog.Warningln("socks5 auth:", err)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if glog.V(LDEBUG) {
|
glog.V(LDEBUG).Infoln(req)
|
||||||
glog.Infoln(req)
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err := gosocks5.ReadUserPassResponse(conn)
|
resp, err := gosocks5.ReadUserPassResponse(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("socks5 auth:", err)
|
||||||
glog.Warningln("socks5 auth:", err)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if glog.V(LDEBUG) {
|
glog.V(LDEBUG).Infoln(resp)
|
||||||
glog.Infoln(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
if res.Status != gosocks5.Succeeded {
|
if resp.Status != gosocks5.Succeeded {
|
||||||
return nil, gosocks5.ErrAuthFailure
|
return nil, gosocks5.ErrAuthFailure
|
||||||
}
|
}
|
||||||
case gosocks5.MethodNoAcceptable:
|
case gosocks5.MethodNoAcceptable:
|
||||||
@ -87,9 +79,7 @@ func (selector *serverSelector) Methods() []uint8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (selector *serverSelector) Select(methods ...uint8) (method uint8) {
|
func (selector *serverSelector) Select(methods ...uint8) (method uint8) {
|
||||||
if glog.V(LDEBUG) {
|
glog.V(LDEBUG).Infof("%d %d % d", gosocks5.Ver5, len(methods), methods)
|
||||||
glog.Infof("%d %d % d", gosocks5.Ver5, len(methods), methods)
|
|
||||||
}
|
|
||||||
|
|
||||||
method = gosocks5.MethodNoAuth
|
method = gosocks5.MethodNoAuth
|
||||||
for _, m := range methods {
|
for _, m := range methods {
|
||||||
@ -113,9 +103,7 @@ func (selector *serverSelector) Select(methods ...uint8) (method uint8) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Conn, error) {
|
func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Conn, error) {
|
||||||
if glog.V(LDEBUG) {
|
glog.V(LDEBUG).Infof("%d %d", gosocks5.Ver5, method)
|
||||||
glog.Infof("%d %d", gosocks5.Ver5, method)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch method {
|
switch method {
|
||||||
case MethodTLS:
|
case MethodTLS:
|
||||||
@ -128,14 +116,10 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con
|
|||||||
|
|
||||||
req, err := gosocks5.ReadUserPassRequest(conn)
|
req, err := gosocks5.ReadUserPassRequest(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("socks5 auth:", err)
|
||||||
glog.Warningln("socks5 auth:", err)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if glog.V(LDEBUG) {
|
glog.V(LDEBUG).Infoln(req.String())
|
||||||
glog.Infoln(req.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
var username, password string
|
var username, password string
|
||||||
if selector.arg.User != nil {
|
if selector.arg.User != nil {
|
||||||
@ -146,30 +130,21 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con
|
|||||||
if (username != "" && req.Username != username) || (password != "" && req.Password != password) {
|
if (username != "" && req.Username != username) || (password != "" && req.Password != password) {
|
||||||
resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Failure)
|
resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Failure)
|
||||||
if err := resp.Write(conn); err != nil {
|
if err := resp.Write(conn); err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("socks5 auth:", err)
|
||||||
glog.Warningln("socks5 auth:", err)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if glog.V(LDEBUG) {
|
glog.V(LDEBUG).Infoln(resp)
|
||||||
glog.Infoln(resp)
|
glog.V(LWARNING).Infoln("socks5: proxy authentication required")
|
||||||
}
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5: proxy authentication required")
|
|
||||||
}
|
|
||||||
return nil, gosocks5.ErrAuthFailure
|
return nil, gosocks5.ErrAuthFailure
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Succeeded)
|
resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Succeeded)
|
||||||
if err := resp.Write(conn); err != nil {
|
if err := resp.Write(conn); err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("socks5 auth:", err)
|
||||||
glog.Warningln("socks5 auth:", err)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if glog.V(LDEBUG) {
|
glog.V(LDEBUG).Infoln(resp)
|
||||||
glog.Infoln(resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
case gosocks5.MethodNoAcceptable:
|
case gosocks5.MethodNoAcceptable:
|
||||||
return nil, gosocks5.ErrBadMethod
|
return nil, gosocks5.ErrBadMethod
|
||||||
@ -179,29 +154,20 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
||||||
if glog.V(LDEBUG) {
|
glog.V(LDEBUG).Infoln(req)
|
||||||
glog.Infoln(req)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch req.Cmd {
|
switch req.Cmd {
|
||||||
case gosocks5.CmdConnect:
|
case gosocks5.CmdConnect:
|
||||||
if glog.V(LINFO) {
|
glog.V(LINFO).Infoln(">>> socks5 connect:", req.Addr.String())
|
||||||
glog.Infoln("socks5 connect:", req.Addr.String())
|
|
||||||
}
|
|
||||||
tconn, err := Connect(req.Addr.String())
|
tconn, err := Connect(req.Addr.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("socks5 connect:", err)
|
||||||
glog.Warningln("socks5 connect:", err)
|
|
||||||
}
|
|
||||||
rep := gosocks5.NewReply(gosocks5.HostUnreachable, nil)
|
rep := gosocks5.NewReply(gosocks5.HostUnreachable, nil)
|
||||||
if err := rep.Write(conn); err != nil {
|
if err := rep.Write(conn); err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("socks5 connect:", err)
|
||||||
glog.Warningln("socks5 connect:", err)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if glog.V(LDEBUG) {
|
glog.V(LDEBUG).Infoln(rep)
|
||||||
glog.Infoln(rep)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -209,43 +175,31 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
|||||||
|
|
||||||
rep := gosocks5.NewReply(gosocks5.Succeeded, nil)
|
rep := gosocks5.NewReply(gosocks5.Succeeded, nil)
|
||||||
if err := rep.Write(conn); err != nil {
|
if err := rep.Write(conn); err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("socks5 connect:", err)
|
||||||
glog.Warningln("socks5 connect:", err)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if glog.V(LDEBUG) {
|
glog.V(LDEBUG).Infoln(rep)
|
||||||
glog.Infoln(rep)
|
|
||||||
}
|
|
||||||
|
|
||||||
Transport(conn, tconn)
|
Transport(conn, tconn)
|
||||||
case gosocks5.CmdBind:
|
case gosocks5.CmdBind:
|
||||||
if glog.V(LINFO) {
|
glog.V(LINFO).Infoln(">>> socks5 bind:", req.Addr)
|
||||||
glog.Infoln("socks5 bind:", req.Addr)
|
|
||||||
}
|
|
||||||
if len(forwardArgs) > 0 {
|
if len(forwardArgs) > 0 {
|
||||||
forwardBind(req, conn)
|
forwardBind(req, conn)
|
||||||
} else {
|
} else {
|
||||||
serveBind(conn)
|
serveBind(conn)
|
||||||
}
|
}
|
||||||
case gosocks5.CmdUdp:
|
case gosocks5.CmdUdp:
|
||||||
if glog.V(LINFO) {
|
glog.V(LINFO).Infoln(">>> socks5 udp associate:", req.Addr)
|
||||||
glog.Infoln("socks5 udp associate:", req.Addr)
|
|
||||||
}
|
|
||||||
uconn, err := net.ListenUDP("udp", nil)
|
uconn, err := net.ListenUDP("udp", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("socks5 udp listen:", err)
|
||||||
glog.Warningln("socks5 udp listen:", err)
|
|
||||||
}
|
|
||||||
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
if err := rep.Write(conn); err != nil {
|
if err := rep.Write(conn); err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("socks5 udp listen:", err)
|
||||||
glog.Warningln("socks5 udp listen:", err)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if glog.V(LDEBUG) {
|
glog.V(LDEBUG).Infoln(rep)
|
||||||
glog.Infoln(rep)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -253,47 +207,166 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
|||||||
|
|
||||||
addr := ToSocksAddr(uconn.LocalAddr())
|
addr := ToSocksAddr(uconn.LocalAddr())
|
||||||
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
||||||
if glog.V(LINFO) {
|
glog.V(LINFO).Infoln("socks5 udp listen:", addr)
|
||||||
glog.Infoln("socks5 udp listen:", addr)
|
|
||||||
}
|
|
||||||
rep := gosocks5.NewReply(gosocks5.Succeeded, addr)
|
rep := gosocks5.NewReply(gosocks5.Succeeded, addr)
|
||||||
if err := rep.Write(conn); err != nil {
|
if err := rep.Write(conn); err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||||
glog.Warningln("socks5 udp:", err)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
if glog.V(LDEBUG) {
|
glog.V(LDEBUG).Infoln(rep)
|
||||||
glog.Infoln(rep)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//clientConn, dgram, err := createClientConn(conn, uconn)
|
cc, dgram, err := createClientConn(conn, uconn)
|
||||||
_, dgram, err := createClientConn(conn, uconn)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||||
glog.Warningln("socks5 udp:", err)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if glog.V(LDEBUG) {
|
glog.V(LDEBUG).Infof("[udp] to %s, length %d", dgram.Header.Addr, len(dgram.Data))
|
||||||
glog.Infof("[udp] length %d, to %s", len(dgram.Data), dgram.Header.Addr)
|
|
||||||
|
raddr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String())
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sc, err := createServerConn(uconn, raddr)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//serverConn, err := createServerConn(uconn)
|
if err = sc.WriteUDP(dgram); err != nil {
|
||||||
_, err = createServerConn(uconn)
|
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dgram, err = sc.ReadUDP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||||
glog.Warningln("socks5 udp forward:", err)
|
return
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
glog.V(LDEBUG).Infof("[udp] from %s, length %d", dgram.Header.Addr, len(dgram.Data))
|
||||||
|
|
||||||
|
if err = cc.WriteUDP(dgram); err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
TransportUDP(cc, sc)
|
||||||
default:
|
default:
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("Unrecognized request: ", req)
|
||||||
glog.Warningln("Unrecognized request: ", req)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func serveBind(conn net.Conn) error {
|
||||||
|
l, err := net.ListenTCP("tcp", nil)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("socks5 bind listen:", err)
|
||||||
|
|
||||||
|
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
|
if err := rep.Write(conn); err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("socks5 bind listen:", err)
|
||||||
|
} else {
|
||||||
|
glog.V(LDEBUG).Infoln(rep)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
addr := ToSocksAddr(l.Addr())
|
||||||
|
// Issue: may not reachable when host has two interfaces
|
||||||
|
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
||||||
|
glog.V(LINFO).Infoln("socks5 bind:", addr)
|
||||||
|
|
||||||
|
rep := gosocks5.NewReply(gosocks5.Succeeded, addr)
|
||||||
|
if err := rep.Write(conn); err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("socks5 bind:", err)
|
||||||
|
l.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
glog.V(LDEBUG).Infoln(rep)
|
||||||
|
|
||||||
|
tconn, err := l.AcceptTCP()
|
||||||
|
l.Close() // only accept one peer
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("socks5 bind accept:", err)
|
||||||
|
|
||||||
|
rep = gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
|
if err := rep.Write(conn); err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("socks5 bind accept:", err)
|
||||||
|
} else {
|
||||||
|
glog.V(LDEBUG).Infoln(rep)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer tconn.Close()
|
||||||
|
|
||||||
|
addr = ToSocksAddr(tconn.RemoteAddr())
|
||||||
|
glog.V(LINFO).Infoln("socks5 bind accept:", addr.String())
|
||||||
|
|
||||||
|
rep = gosocks5.NewReply(gosocks5.Succeeded, addr)
|
||||||
|
if err := rep.Write(conn); err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("socks5 bind accept:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
glog.V(LDEBUG).Infoln(rep)
|
||||||
|
|
||||||
|
return Transport(conn, tconn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func forwardBind(req *gosocks5.Request, conn net.Conn) error {
|
||||||
|
fconn, _, err := forwardChain(forwardArgs...)
|
||||||
|
if err != nil {
|
||||||
|
if fconn != nil {
|
||||||
|
fconn.Close()
|
||||||
|
}
|
||||||
|
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
|
if err := rep.Write(conn); err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("socks5 bind forward:", err)
|
||||||
|
} else {
|
||||||
|
glog.V(LDEBUG).Infoln(rep)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer fconn.Close()
|
||||||
|
|
||||||
|
if err := req.Write(fconn); err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("socks5 bind forward:", err)
|
||||||
|
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
glog.V(LDEBUG).Infoln(req)
|
||||||
|
|
||||||
|
// first reply
|
||||||
|
if err := peekReply(conn, fconn); err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("socks5 bind forward:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// second reply
|
||||||
|
if err := peekReply(conn, fconn); err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("socks5 bind forward:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Transport(conn, fconn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func peekReply(dst io.Writer, src io.Reader) error {
|
||||||
|
rep, err := gosocks5.ReadReply(src)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infoln(err)
|
||||||
|
rep = gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
|
}
|
||||||
|
if err := rep.Write(dst); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
glog.V(LDEBUG).Infoln(rep)
|
||||||
|
|
||||||
|
if rep.Rep != gosocks5.Succeeded {
|
||||||
|
return errors.New("Failure")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func createClientConn(conn net.Conn, uconn *net.UDPConn) (c *UDPConn, dgram *gosocks5.UDPDatagram, err error) {
|
func createClientConn(conn net.Conn, uconn *net.UDPConn) (c *UDPConn, dgram *gosocks5.UDPDatagram, err error) {
|
||||||
var raddr *net.UDPAddr
|
var raddr *net.UDPAddr
|
||||||
dgramChan := make(chan *gosocks5.UDPDatagram, 1)
|
dgramChan := make(chan *gosocks5.UDPDatagram, 1)
|
||||||
@ -338,7 +411,7 @@ func createClientConn(conn net.Conn, uconn *net.UDPConn) (c *UDPConn, dgram *gos
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func createServerConn(uconn *net.UDPConn) (c *UDPConn, err error) {
|
func createServerConn(uconn *net.UDPConn, addr net.Addr) (c *UDPConn, err error) {
|
||||||
if len(forwardArgs) == 0 {
|
if len(forwardArgs) == 0 {
|
||||||
c = Server(uconn)
|
c = Server(uconn)
|
||||||
return
|
return
|
||||||
@ -351,291 +424,30 @@ func createServerConn(uconn *net.UDPConn) (c *UDPConn, err error) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
glog.V(LINFO).Infoln("forward udp associate")
|
||||||
|
|
||||||
|
req := gosocks5.NewRequest(gosocks5.CmdUdp, nil)
|
||||||
|
if err = req.Write(fconn); err != nil {
|
||||||
|
fconn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
glog.V(LDEBUG).Infoln(req)
|
||||||
|
|
||||||
|
rep, err := gosocks5.ReadReply(fconn)
|
||||||
|
if err != nil {
|
||||||
|
fconn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
glog.V(LDEBUG).Infoln(rep)
|
||||||
|
if rep.Rep != gosocks5.Succeeded {
|
||||||
|
fconn.Close()
|
||||||
|
return nil, errors.New("Failure")
|
||||||
|
}
|
||||||
|
|
||||||
c = Server(fconn)
|
c = Server(fconn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
func forwardUDP(req *gosocks5.Request) (conn net.Conn, err error) {
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if conn != nil {
|
|
||||||
conn.Close()
|
|
||||||
}
|
|
||||||
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
|
||||||
if err := rep.Write(conn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 udp forward:", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if glog.V(LDEBUG) {
|
|
||||||
glog.Infoln(rep)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = req.Write(fconn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 udp forward:", err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = peekReply(conn, fconn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 udp forward:", err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
func serveBind(conn net.Conn) error {
|
|
||||||
l, err := net.ListenTCP("tcp", nil)
|
|
||||||
if err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind listen:", err)
|
|
||||||
}
|
|
||||||
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
|
||||||
if err := rep.Write(conn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind listen:", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if glog.V(LDEBUG) {
|
|
||||||
glog.Infoln(rep)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
addr := ToSocksAddr(l.Addr())
|
|
||||||
// Issue: may not reachable when host has two interfaces
|
|
||||||
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
|
||||||
if glog.V(LINFO) {
|
|
||||||
glog.Infoln("socks5 bind:", addr)
|
|
||||||
}
|
|
||||||
rep := gosocks5.NewReply(gosocks5.Succeeded, addr)
|
|
||||||
if err := rep.Write(conn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind:", err)
|
|
||||||
}
|
|
||||||
l.Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if glog.V(LDEBUG) {
|
|
||||||
glog.Infoln(rep)
|
|
||||||
}
|
|
||||||
|
|
||||||
tconn, err := l.AcceptTCP()
|
|
||||||
l.Close() // only accept one peer
|
|
||||||
if err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind accept:", err)
|
|
||||||
}
|
|
||||||
rep = gosocks5.NewReply(gosocks5.Failure, nil)
|
|
||||||
if err := rep.Write(conn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind accept:", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if glog.V(LDEBUG) {
|
|
||||||
glog.Infoln(rep)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer tconn.Close()
|
|
||||||
|
|
||||||
addr = ToSocksAddr(tconn.RemoteAddr())
|
|
||||||
if glog.V(LINFO) {
|
|
||||||
glog.Infoln("socks5 bind accept:", addr.String())
|
|
||||||
}
|
|
||||||
rep = gosocks5.NewReply(gosocks5.Succeeded, addr)
|
|
||||||
if err := rep.Write(conn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind accept:", err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if glog.V(LDEBUG) {
|
|
||||||
glog.Infoln(rep)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Transport(conn, tconn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func forwardBind(req *gosocks5.Request, conn net.Conn) error {
|
|
||||||
fconn, _, err := forwardChain(forwardArgs...)
|
|
||||||
if err != nil {
|
|
||||||
if fconn != nil {
|
|
||||||
fconn.Close()
|
|
||||||
}
|
|
||||||
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
|
||||||
if err := rep.Write(conn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind forward:", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if glog.V(LDEBUG) {
|
|
||||||
glog.Infoln(rep)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer fconn.Close()
|
|
||||||
|
|
||||||
if err := req.Write(fconn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind forward:", err)
|
|
||||||
}
|
|
||||||
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if glog.V(LDEBUG) {
|
|
||||||
glog.Infoln(req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// first reply
|
|
||||||
if err := peekReply(conn, fconn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind forward:", err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// second reply
|
|
||||||
if err := peekReply(conn, fconn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind forward:", err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return Transport(conn, fconn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func peekReply(dst io.Writer, src io.Reader) error {
|
|
||||||
rep, err := gosocks5.ReadReply(src)
|
|
||||||
if err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln(err)
|
|
||||||
}
|
|
||||||
rep = gosocks5.NewReply(gosocks5.Failure, nil)
|
|
||||||
}
|
|
||||||
if err := rep.Write(dst); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if glog.V(LDEBUG) {
|
|
||||||
glog.Infoln(rep)
|
|
||||||
}
|
|
||||||
if rep.Rep != gosocks5.Succeeded {
|
|
||||||
return errors.New("Failure")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
func cliTunnelUDP(uconn *net.UDPConn, sconn net.Conn) {
|
|
||||||
var raddr *net.UDPAddr
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
b := make([]byte, 16*1024)
|
|
||||||
for {
|
|
||||||
n, addr, err := uconn.ReadFromUDP(b)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
raddr = addr
|
|
||||||
r := bytes.NewBuffer(b[:n])
|
|
||||||
udp, err := gosocks5.ReadUDPDatagram(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
udp.Header.Rsv = uint16(len(udp.Data))
|
|
||||||
//log.Println("r", raddr.String(), udp.Header)
|
|
||||||
|
|
||||||
if err := udp.Write(sconn); err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
for {
|
|
||||||
b := lpool.Take()
|
|
||||||
defer lpool.put(b)
|
|
||||||
|
|
||||||
udp, err := gosocks5.ReadUDPDatagram(sconn)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//log.Println("w", udp.Header)
|
|
||||||
udp.Header.Rsv = 0
|
|
||||||
buf := bytes.NewBuffer(b[0:0])
|
|
||||||
udp.Write(buf)
|
|
||||||
if _, err := uconn.WriteTo(buf.Bytes(), raddr); err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func srvTunnelUDP(conn net.Conn, uconn *net.UDPConn) {
|
|
||||||
go func() {
|
|
||||||
b := make([]byte, 16*1024)
|
|
||||||
|
|
||||||
for {
|
|
||||||
n, addr, err := uconn.ReadFromUDP(b)
|
|
||||||
if err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln(err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
udp := gosocks5.NewUDPDatagram(
|
|
||||||
gosocks5.NewUDPHeader(uint16(n), 0, ToSocksAddr(addr)), b[:n])
|
|
||||||
//log.Println("r", udp.Header)
|
|
||||||
if err := udp.Write(conn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln(err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
for {
|
|
||||||
udp, err := gosocks5.ReadUDPDatagram(conn)
|
|
||||||
if err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln(err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//log.Println("w", udp.Header)
|
|
||||||
addr, err := net.ResolveUDPAddr("udp", udp.Header.Addr.String())
|
|
||||||
if err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln(err)
|
|
||||||
}
|
|
||||||
continue // drop silently
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := uconn.WriteToUDP(udp.Data, addr); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln(err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
func ToSocksAddr(addr net.Addr) *gosocks5.Addr {
|
func ToSocksAddr(addr net.Addr) *gosocks5.Addr {
|
||||||
host, port, _ := net.SplitHostPort(addr.String())
|
host, port, _ := net.SplitHostPort(addr.String())
|
||||||
p, _ := strconv.Atoi(port)
|
p, _ := strconv.Atoi(port)
|
||||||
@ -646,3 +458,40 @@ func ToSocksAddr(addr net.Addr) *gosocks5.Addr {
|
|||||||
Port: uint16(p),
|
Port: uint16(p),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PipeUDP(src, dst *UDPConn, ch chan<- error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
for {
|
||||||
|
var dgram *gosocks5.UDPDatagram
|
||||||
|
dgram, err = src.ReadUDP()
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
glog.V(LDEBUG).Infof("[udp] addr %s, length %d", dgram.Header.Addr, len(dgram.Data))
|
||||||
|
|
||||||
|
if err = dst.WriteUDP(dgram); err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ch <- err
|
||||||
|
close(ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TransportUDP(cc, sc *UDPConn) (err error) {
|
||||||
|
rChan := make(chan error, 1)
|
||||||
|
wChan := make(chan error, 1)
|
||||||
|
|
||||||
|
go PipeUDP(cc, sc, wChan)
|
||||||
|
go PipeUDP(sc, cc, rChan)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case err = <-wChan:
|
||||||
|
//log.Println("w exit", err)
|
||||||
|
case err = <-rChan:
|
||||||
|
//log.Println("r exit", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
21
ss.go
21
ss.go
@ -16,9 +16,7 @@ func handleShadow(conn net.Conn, arg Args) {
|
|||||||
password, _ := arg.User.Password()
|
password, _ := arg.User.Password()
|
||||||
cipher, err := shadowsocks.NewCipher(method, password)
|
cipher, err := shadowsocks.NewCipher(method, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("shadowsocks:", err)
|
||||||
glog.Warningln("shadowsocks:", err)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
conn = shadowsocks.NewConn(conn, cipher)
|
conn = shadowsocks.NewConn(conn, cipher)
|
||||||
@ -26,28 +24,21 @@ func handleShadow(conn net.Conn, arg Args) {
|
|||||||
|
|
||||||
addr, extra, err := getShadowRequest(conn)
|
addr, extra, err := getShadowRequest(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("shadowsocks:", err)
|
||||||
glog.Warningln("shadowsocks:", err)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if glog.V(LINFO) {
|
glog.V(LINFO).Infoln("shadowsocks connect:", addr.String())
|
||||||
glog.Infoln("shadowsocks connect:", addr.String())
|
|
||||||
}
|
|
||||||
sconn, err := Connect(addr.String())
|
sconn, err := Connect(addr.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("shadowsocks:", err)
|
||||||
glog.Warningln("shadowsocks:", err)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer sconn.Close()
|
defer sconn.Close()
|
||||||
|
|
||||||
if extra != nil {
|
if extra != nil {
|
||||||
if _, err := sconn.Write(extra); err != nil {
|
if _, err := sconn.Write(extra); err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln("shadowsocks:", err)
|
||||||
glog.Warningln("shadowsocks:", err)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
135
udp.go
135
udp.go
@ -1,39 +1,148 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
//"github.com/ginuerzh/gosocks5"
|
"bytes"
|
||||||
//"github.com/golang/glog"
|
"github.com/ginuerzh/gosocks5"
|
||||||
|
"github.com/golang/glog"
|
||||||
"net"
|
"net"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UDPConn struct {
|
type UDPConn struct {
|
||||||
isClient bool
|
isClient bool
|
||||||
udpConn *net.UDPConn
|
udp *net.UDPConn
|
||||||
addr net.Addr
|
addr net.Addr
|
||||||
tcpConn net.Conn
|
tcp net.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
func Client(conn net.Conn, addr net.Addr) *UDPConn {
|
func Client(conn net.Conn, addr net.Addr) *UDPConn {
|
||||||
client := &UDPConn{isClient: true}
|
c := &UDPConn{isClient: true}
|
||||||
|
|
||||||
switch conn := conn.(type) {
|
switch conn := conn.(type) {
|
||||||
case *net.UDPConn:
|
case *net.UDPConn:
|
||||||
client.udpConn = conn
|
c.udp = conn
|
||||||
client.addr = addr
|
c.addr = addr
|
||||||
default:
|
default:
|
||||||
client.tcpConn = conn
|
c.tcp = conn
|
||||||
}
|
}
|
||||||
|
|
||||||
return client
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func Server(conn net.Conn) *UDPConn {
|
func Server(conn net.Conn) *UDPConn {
|
||||||
server := &UDPConn{}
|
c := &UDPConn{}
|
||||||
|
|
||||||
switch conn := conn.(type) {
|
switch conn := conn.(type) {
|
||||||
case *net.UDPConn:
|
case *net.UDPConn:
|
||||||
server.udpConn = conn
|
c.udp = conn
|
||||||
default:
|
default:
|
||||||
server.tcpConn = conn
|
c.tcp = conn
|
||||||
}
|
}
|
||||||
return server
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPConn) ReadUDP() (*gosocks5.UDPDatagram, error) {
|
||||||
|
if c.isClient {
|
||||||
|
return c.readUDPClient()
|
||||||
|
}
|
||||||
|
return c.readUDPServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPConn) readUDPClient() (*gosocks5.UDPDatagram, error) {
|
||||||
|
if c.udp != nil {
|
||||||
|
return gosocks5.ReadUDPDatagram(c.udp)
|
||||||
|
}
|
||||||
|
return gosocks5.ReadUDPDatagram(c.tcp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPConn) readUDPServer() (*gosocks5.UDPDatagram, error) {
|
||||||
|
if c.udp != nil {
|
||||||
|
b := make([]byte, 65535)
|
||||||
|
n, addr, err := c.udp.ReadFromUDP(b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
dgram := gosocks5.NewUDPDatagram(
|
||||||
|
gosocks5.NewUDPHeader(0, 0, ToSocksAddr(addr)), b[:n])
|
||||||
|
return dgram, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return gosocks5.ReadUDPDatagram(c.tcp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPConn) WriteUDP(dgram *gosocks5.UDPDatagram) error {
|
||||||
|
if c.isClient {
|
||||||
|
return c.writeUDPClient(dgram)
|
||||||
|
}
|
||||||
|
return c.writeUDPServer(dgram)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPConn) writeUDPClient(dgram *gosocks5.UDPDatagram) error {
|
||||||
|
if c.udp != nil {
|
||||||
|
dgram.Header.Rsv = 0
|
||||||
|
buffer := bytes.Buffer{}
|
||||||
|
dgram.Write(&buffer)
|
||||||
|
_, err := c.udp.WriteTo(buffer.Bytes(), c.addr)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
dgram.Header.Rsv = uint16(len(dgram.Data))
|
||||||
|
return dgram.Write(c.tcp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPConn) writeUDPServer(dgram *gosocks5.UDPDatagram) error {
|
||||||
|
if c.udp != nil {
|
||||||
|
addr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String())
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infoln(err)
|
||||||
|
return nil // drop silently
|
||||||
|
}
|
||||||
|
_, err = c.udp.WriteTo(dgram.Data, addr)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dgram.Header.Rsv = uint16(len(dgram.Data))
|
||||||
|
return dgram.Write(c.tcp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPConn) Close() error {
|
||||||
|
if c.udp != nil {
|
||||||
|
return c.udp.Close()
|
||||||
|
}
|
||||||
|
return c.tcp.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPConn) LocalAddr() net.Addr {
|
||||||
|
if c.udp != nil {
|
||||||
|
return c.udp.LocalAddr()
|
||||||
|
}
|
||||||
|
return c.tcp.LocalAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPConn) RemoteAddr() net.Addr {
|
||||||
|
if c.udp != nil {
|
||||||
|
return c.udp.RemoteAddr()
|
||||||
|
}
|
||||||
|
return c.tcp.RemoteAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPConn) SetDeadline(t time.Time) error {
|
||||||
|
if c.udp != nil {
|
||||||
|
return c.udp.SetDeadline(t)
|
||||||
|
}
|
||||||
|
return c.tcp.SetDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPConn) SetReadDeadline(t time.Time) error {
|
||||||
|
if c.udp != nil {
|
||||||
|
return c.udp.SetReadDeadline(t)
|
||||||
|
}
|
||||||
|
return c.tcp.SetReadDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPConn) SetWriteDeadline(t time.Time) error {
|
||||||
|
if c.udp != nil {
|
||||||
|
return c.udp.SetWriteDeadline(t)
|
||||||
|
}
|
||||||
|
return c.tcp.SetWriteDeadline(t)
|
||||||
}
|
}
|
||||||
|
17
util.go
17
util.go
@ -62,12 +62,11 @@ nh/BAoGBAMY5z2f1pmMhrvtPDSlEVjgjELbaInxFaxPLR4Pdyzn83gtIIU14+R8X
|
|||||||
func init() {
|
func init() {
|
||||||
var err error
|
var err error
|
||||||
if cert, err = tls.LoadX509KeyPair("cert.pem", "key.pem"); err != nil {
|
if cert, err = tls.LoadX509KeyPair("cert.pem", "key.pem"); err != nil {
|
||||||
if glog.V(LFATAL) {
|
glog.V(LWARNING).Infoln(err)
|
||||||
glog.Warningln(err)
|
|
||||||
}
|
|
||||||
cert, err = tls.X509KeyPair([]byte(rawCert), []byte(rawKey))
|
cert, err = tls.X509KeyPair([]byte(rawCert), []byte(rawKey))
|
||||||
if err != nil && glog.V(LFATAL) {
|
if err != nil {
|
||||||
glog.Warningln(err)
|
glog.V(LFATAL).Infoln(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,9 +111,7 @@ func parseArgs(ss []string) (args []Args) {
|
|||||||
}
|
}
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if glog.V(LWARNING) {
|
glog.V(LWARNING).Infoln(err)
|
||||||
glog.Warningln(err)
|
|
||||||
}
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,9 +183,9 @@ func Copy(dst io.Writer, src io.Reader) (written int64, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Pipe(src io.Reader, dst io.Writer, c chan<- error) {
|
func Pipe(src io.Reader, dst io.Writer, ch chan<- error) {
|
||||||
_, err := Copy(dst, src)
|
_, err := Copy(dst, src)
|
||||||
c <- err
|
ch <- err
|
||||||
}
|
}
|
||||||
|
|
||||||
func Transport(conn, conn2 net.Conn) (err error) {
|
func Transport(conn, conn2 net.Conn) (err error) {
|
||||||
|
4
ws.go
4
ws.go
@ -105,9 +105,7 @@ func (s *ws) handle(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
conn, err := s.upgrader.Upgrade(w, r, nil)
|
conn, err := s.upgrader.Upgrade(w, r, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if glog.V(LERROR) {
|
glog.V(LERROR).Infoln(err)
|
||||||
glog.Errorln(err)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handleConn(wsServer(conn), s.arg)
|
handleConn(wsServer(conn), s.arg)
|
||||||
|
Loading…
Reference in New Issue
Block a user