fix udp port forwarding
This commit is contained in:
parent
3c79cf44b7
commit
a8bd16715f
39
README.md
39
README.md
@ -11,6 +11,7 @@ gost - GO Simple Tunnel
|
|||||||
* socks5代理支持tls协商加密
|
* socks5代理支持tls协商加密
|
||||||
* Tunnel UDP over TCP
|
* Tunnel UDP over TCP
|
||||||
* 兼容shadowsocks协议
|
* 兼容shadowsocks协议
|
||||||
|
* 支持端口转发(2.1及以上版本)
|
||||||
|
|
||||||
二进制文件下载:https://github.com/ginuerzh/gost/releases
|
二进制文件下载:https://github.com/ginuerzh/gost/releases
|
||||||
|
|
||||||
@ -20,13 +21,16 @@ Google讨论组: https://groups.google.com/d/forum/go-gost
|
|||||||
|
|
||||||
参数说明
|
参数说明
|
||||||
------
|
------
|
||||||
#### -L和-F参数格式
|
#### 代理及转发链
|
||||||
|
|
||||||
|
适用于-L和-F参数
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
[scheme://][user:pass@host]:port
|
[scheme://][user:pass@host]:port
|
||||||
```
|
```
|
||||||
scheme分为两部分: protocol+transport
|
scheme分为两部分: protocol+transport
|
||||||
|
|
||||||
protocol: 代理协议类型(http, socks5, shadowsocks), transport: 数据传输方式(tcp, ws, wss, tls), 二者可以任意组合,或单独使用。
|
protocol: 代理协议类型(http, socks5, shadowsocks), transport: 数据传输方式(ws, wss, tls), 二者可以任意组合,或单独使用:
|
||||||
|
|
||||||
> http - 作为http代理: http://:8080
|
> http - 作为http代理: http://:8080
|
||||||
|
|
||||||
@ -40,6 +44,21 @@ protocol: 代理协议类型(http, socks5, shadowsocks), transport: 数据传输
|
|||||||
|
|
||||||
> ss - 作为shadowsocks服务,ss://aes-256-cfb:123456@:8080
|
> 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 : 输出到控制台
|
> -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类型代理。
|
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
|
#### HTTP
|
||||||
|
63
forward.go
63
forward.go
@ -5,11 +5,15 @@ import (
|
|||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleTcpForward(conn net.Conn, arg Args) {
|
func handleTcpForward(conn net.Conn, arg Args) {
|
||||||
defer conn.Close()
|
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)
|
c, err := Connect(arg.Forward)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infof("[tcp-forward] %s -> %s : %s", conn.RemoteAddr(), arg.Forward, err)
|
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) {
|
func handleUdpForward(conn *net.UDPConn, raddr *net.UDPAddr, data []byte, arg Args) {
|
||||||
if !strings.Contains(arg.Forward, ":") {
|
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...)
|
fconn, _, err := forwardChain(forwardArgs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
|
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)
|
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(
|
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 {
|
if err = dgram.Write(fconn); err != nil {
|
||||||
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
|
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
glog.V(LINFO).Infof("[udp-forward] %s >>> %s length %d", raddr, arg.Forward, len(data))
|
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)
|
dgram, err = gosocks5.ReadUDPDatagram(fconn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
|
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
|
||||||
return
|
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 {
|
if _, err = conn.WriteToUDP(dgram.Data, raddr); err != nil {
|
||||||
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
|
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)
|
||||||
}
|
}
|
||||||
|
2
http.go
2
http.go
@ -18,7 +18,7 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
|
|||||||
glog.Infoln(string(dump))
|
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
|
var username, password string
|
||||||
if arg.User != nil {
|
if arg.User != nil {
|
||||||
|
6
socks.go
6
socks.go
@ -166,7 +166,7 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
|||||||
|
|
||||||
switch req.Cmd {
|
switch req.Cmd {
|
||||||
case gosocks5.CmdConnect:
|
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())
|
tconn, err := Connect(req.Addr.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -192,7 +192,7 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
|||||||
Transport(conn, tconn)
|
Transport(conn, tconn)
|
||||||
glog.V(LINFO).Infof("[socks5-connect] %s >-< %s DISCONNECTED", conn.RemoteAddr(), req.Addr)
|
glog.V(LINFO).Infof("[socks5-connect] %s >-< %s DISCONNECTED", conn.RemoteAddr(), req.Addr)
|
||||||
case gosocks5.CmdBind:
|
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 {
|
if len(forwardArgs) > 0 {
|
||||||
forwardBind(req, conn)
|
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)
|
glog.V(LINFO).Infof("[socks5-bind] %s >-< %s DISCONNECTED", conn.RemoteAddr(), req.Addr)
|
||||||
case gosocks5.CmdUdp, CmdUdpTun:
|
case gosocks5.CmdUdp, CmdUdpTun:
|
||||||
// TODO: udp tunnel <-> forward chain
|
// 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)
|
uconn, err := net.ListenUDP("udp", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||||
|
Loading…
Reference in New Issue
Block a user