fix udp port forwarding

This commit is contained in:
rui.zheng 2016-08-31 13:28:10 +08:00
parent 3c79cf44b7
commit a8bd16715f
4 changed files with 94 additions and 16 deletions

View File

@ -11,6 +11,7 @@ gost - GO Simple Tunnel
* socks5代理支持tls协商加密
* Tunnel UDP over TCP
* 兼容shadowsocks协议
* 支持端口转发(2.1及以上版本)
二进制文件下载https://github.com/ginuerzh/gost/releases
@ -20,13 +21,16 @@ Google讨论组: https://groups.google.com/d/forum/go-gost
参数说明
------
#### -L和-F参数格式
#### 代理及转发链
适用于-L和-F参数
```bash
[scheme://][user:pass@host]:port
```
scheme分为两部分: protocol+transport
protocol: 代理协议类型(http, socks5, shadowsocks), transport: 数据传输方式(tcp, ws, wss, tls), 二者可以任意组合,或单独使用
protocol: 代理协议类型(http, socks5, shadowsocks), transport: 数据传输方式(ws, wss, tls), 二者可以任意组合,或单独使用:
> http - 作为http代理: http://:8080
@ -40,6 +44,21 @@ protocol: 代理协议类型(http, socks5, shadowsocks), transport: 数据传输
> ss - 作为shadowsocks服务ss://aes-256-cfb:123456@:8080
#### 本地端口转发
适用于-L参数
```bash
scheme://[bind_address]:port/[host]:hostport
```
> scheme - 端口转发类型: tcp, udp
> bind_address:port - 本地监听地址
> host:hostport - 远程监听地址
当在bind_address:port上收到连接信息则会(通过转发链)与host:hostport建立连接创建一条数据通道。
#### 开启日志
> -logtostderr : 输出到控制台
@ -90,6 +109,22 @@ gost -L=:8080 -F=http+tls://192.168.1.1:443 -F=socks+ws://192.168.1.2:1080 -F=ss
```
gost按照-F设置顺序通过转发链将请求最终转发给a.b.c.d:NNNN处理每一个转发代理可以是任意http(s)/socks5/shadowsocks类型代理。
#### 本地端口转发(TCP)
```bash
gost -L=tcp://:2222/192.168.1.1:22 -F=...
```
将本地TCP端口2222上的数据(通过转发链)转发到192.168.1.1:22上。
#### 本地端口转发(UDP)
```bash
gost -L=udp://:5353/192.168.1.1:53 -F=...
```
将本地UDP端口5353上的数据(通过转发链)转发到192.168.1.1:53上。
**注: 如果有转发链,则转发链的末端(最后一个-F参数)必须是gost socks5类型代理。**
加密机制
------
#### HTTP

View File

@ -5,11 +5,15 @@ import (
"github.com/golang/glog"
"net"
"strings"
"time"
)
func handleTcpForward(conn net.Conn, arg Args) {
defer conn.Close()
glog.V(LINFO).Infof("[tcp-forward] %s -> %s", conn.RemoteAddr(), arg.Forward)
if !strings.Contains(arg.Forward, ":") {
arg.Forward += ":22" // default is ssh service
}
glog.V(LINFO).Infof("[tcp-forward] %s - %s", conn.RemoteAddr(), arg.Forward)
c, err := Connect(arg.Forward)
if err != nil {
glog.V(LWARNING).Infof("[tcp-forward] %s -> %s : %s", conn.RemoteAddr(), arg.Forward, err)
@ -24,9 +28,48 @@ func handleTcpForward(conn net.Conn, arg Args) {
func handleUdpForward(conn *net.UDPConn, raddr *net.UDPAddr, data []byte, arg Args) {
if !strings.Contains(arg.Forward, ":") {
arg.Forward += ":53"
arg.Forward += ":53" // default is dns service
}
glog.V(LINFO).Infof("[udp-forward] %s -> %s", raddr, arg.Forward)
faddr, err := net.ResolveUDPAddr("udp", arg.Forward)
if err != nil {
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
return
}
glog.V(LINFO).Infof("[udp-forward] %s - %s", raddr, faddr)
if len(forwardArgs) == 0 {
lconn, err := net.ListenUDP("udp", nil)
if err != nil {
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
return
}
defer lconn.Close()
if _, err := lconn.WriteToUDP(data, faddr); err != nil {
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
return
}
glog.V(LINFO).Infof("[udp-forward] %s >>> %s length %d", raddr, arg.Forward, len(data))
b := udpPool.Get().([]byte)
defer udpPool.Put(b)
lconn.SetReadDeadline(time.Now().Add(time.Second * 60))
n, addr, err := lconn.ReadFromUDP(b)
if err != nil {
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
return
}
glog.V(LINFO).Infof("[udp-forward] %s <<< %s length %d", raddr, addr, n)
if _, err := conn.WriteToUDP(b[:n], raddr); err != nil {
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
}
glog.V(LINFO).Infof("[udp-forward] %s >-< %s DONE", raddr, arg.Forward)
return
}
fconn, _, err := forwardChain(forwardArgs...)
if err != nil {
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
@ -58,27 +101,27 @@ func handleUdpForward(conn *net.UDPConn, raddr *net.UDPAddr, data []byte, arg Ar
}
glog.V(LINFO).Infof("[udp-forward] %s <-> %s ASSOCIATE ON %s OK", raddr, arg.Forward, rep.Addr)
addr, err := net.ResolveUDPAddr("udp", arg.Forward)
if err != nil {
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
return
}
dgram := gosocks5.NewUDPDatagram(
gosocks5.NewUDPHeader(uint16(len(data)), 0, ToSocksAddr(addr)), data)
gosocks5.NewUDPHeader(uint16(len(data)), 0, ToSocksAddr(faddr)), data)
fconn.SetWriteDeadline(time.Now().Add(time.Second * 60))
if err = dgram.Write(fconn); err != nil {
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
return
}
glog.V(LINFO).Infof("[udp-forward] %s >>> %s length %d", raddr, arg.Forward, len(data))
fconn.SetReadDeadline(time.Now().Add(time.Second * 60))
dgram, err = gosocks5.ReadUDPDatagram(fconn)
if err != nil {
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
return
}
glog.V(LINFO).Infof("[udp-forward] %s <<< %s length %d", raddr, arg.Forward, len(dgram.Data))
glog.V(LINFO).Infof("[udp-forward] %s <<< %s length %d", raddr, dgram.Header.Addr, len(dgram.Data))
if _, err = conn.WriteToUDP(dgram.Data, raddr); err != nil {
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
}
glog.V(LINFO).Infof("[udp-forward] %s >-< %s DONE", raddr, arg.Forward)
}

View File

@ -18,7 +18,7 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
glog.Infoln(string(dump))
}
}
glog.V(LINFO).Infof("[http] %s -> %s", conn.RemoteAddr(), req.Host)
glog.V(LINFO).Infof("[http] %s - %s", conn.RemoteAddr(), req.Host)
var username, password string
if arg.User != nil {

View File

@ -166,7 +166,7 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
switch req.Cmd {
case gosocks5.CmdConnect:
glog.V(LINFO).Infof("[socks5-connect] %s -> %s", conn.RemoteAddr(), req.Addr)
glog.V(LINFO).Infof("[socks5-connect] %s - %s", conn.RemoteAddr(), req.Addr)
tconn, err := Connect(req.Addr.String())
if err != nil {
@ -192,7 +192,7 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
Transport(conn, tconn)
glog.V(LINFO).Infof("[socks5-connect] %s >-< %s DISCONNECTED", conn.RemoteAddr(), req.Addr)
case gosocks5.CmdBind:
glog.V(LINFO).Infof("[socks5-bind] %s -> %s", conn.RemoteAddr(), req.Addr)
glog.V(LINFO).Infof("[socks5-bind] %s - %s", conn.RemoteAddr(), req.Addr)
if len(forwardArgs) > 0 {
forwardBind(req, conn)
@ -202,7 +202,7 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
glog.V(LINFO).Infof("[socks5-bind] %s >-< %s DISCONNECTED", conn.RemoteAddr(), req.Addr)
case gosocks5.CmdUdp, CmdUdpTun:
// TODO: udp tunnel <-> forward chain
glog.V(LINFO).Infof("[socks5-udp] %s -> %s ASSOCIATE", conn.RemoteAddr(), req.Addr)
glog.V(LINFO).Infof("[socks5-udp] %s - %s ASSOCIATE", conn.RemoteAddr(), req.Addr)
uconn, err := net.ListenUDP("udp", nil)
if err != nil {
glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)