This commit is contained in:
rui.zheng 2017-01-19 13:40:53 +08:00
parent c58981e858
commit 0585749a81
6 changed files with 193 additions and 119 deletions

View File

@ -8,6 +8,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net" "net"
"strconv" "strconv"
"sync" "sync"
@ -591,7 +592,6 @@ func NewUDPDatagram(header *UDPHeader, data []byte) *UDPDatagram {
} }
func ReadUDPDatagram(r io.Reader) (*UDPDatagram, error) { func ReadUDPDatagram(r io.Reader) (*UDPDatagram, error) {
// b := make([]byte, 65797)
b := lPool.Get().([]byte) b := lPool.Get().([]byte)
defer lPool.Put(b) defer lPool.Put(b)
@ -621,17 +621,21 @@ func ReadUDPDatagram(r io.Reader) (*UDPDatagram, error) {
return nil, ErrBadAddrType return nil, ErrBadAddrType
} }
// extended feature, for udp over tcp, using reserved field for data length
dlen := int(header.Rsv) dlen := int(header.Rsv)
if n < hlen+dlen { if dlen == 0 { // standard SOCKS5 UDP datagram
extra, err := ioutil.ReadAll(r) // we assume no redundant data
if err != nil {
return nil, err
}
copy(b[n:], extra)
n += len(extra) // total length
dlen = n - hlen // data length
} else { // extended feature, for UDP over TCP, using reserved field as data length
if _, err := io.ReadFull(r, b[n:hlen+dlen]); err != nil { if _, err := io.ReadFull(r, b[n:hlen+dlen]); err != nil {
return nil, err return nil, err
} }
n = hlen + dlen n = hlen + dlen
} }
if dlen == 0 {
dlen = n - hlen
}
header.Addr = new(Addr) header.Addr = new(Addr)
if err := header.Addr.Decode(b[3:hlen]); err != nil { if err := header.Addr.Decode(b[3:hlen]); err != nil {

View File

@ -164,9 +164,10 @@ gost -L=tcp://:2222/192.168.1.1:22 -F=...
#### 本地端口转发(UDP) #### 本地端口转发(UDP)
```bash ```bash
gost -L=udp://:5353/192.168.1.1:53 -F=... gost -L=udp://:5353/192.168.1.1:53?ttl=60 -F=...
``` ```
将本地UDP端口5353上的数据(通过代理链)转发到192.168.1.1:53上。 将本地UDP端口5353上的数据(通过代理链)转发到192.168.1.1:53上。
每条转发通道都有超时时间,当超过此时间,且在此时间段内无任何数据交互,则此通道将关闭。可以通过`ttl`参数来设置超时时间默认值为60秒。
**注:** 转发UDP数据时如果有代理链则代理链的末端(最后一个-F参数)必须是gost SOCKS5类型代理。 **注:** 转发UDP数据时如果有代理链则代理链的末端(最后一个-F参数)必须是gost SOCKS5类型代理。

View File

@ -164,9 +164,10 @@ The data on the local TCP port 2222 is forwarded to 192.168.1.1:22 (through the
#### Local UDP port forwarding #### Local UDP port forwarding
```bash ```bash
gost -L=udp://:5353/192.168.1.1:53 -F=... gost -L=udp://:5353/192.168.1.1:53?ttl=60 -F=...
``` ```
The data on the local UDP port 5353 is forwarded to 192.168.1.1:53 (through the proxy chain). The data on the local UDP port 5353 is forwarded to 192.168.1.1:53 (through the proxy chain).
Each forwarding channel has a timeout period. When this time is exceeded and there is no data interaction during this time period, the channel will be closed. The timeout value can be set by the `ttl` parameter. The default value is 60 seconds.
**NOTE:** When forwarding UDP data, if there is a proxy chain, the end of the chain (the last -F parameter) must be gost SOCKS5 proxy. **NOTE:** When forwarding UDP data, if there is a proxy chain, the end of the chain (the last -F parameter) must be gost SOCKS5 proxy.

View File

@ -321,7 +321,7 @@ func (s *Socks5Server) handleUDPRelay(req *gosocks5.Request) {
cc.SetReadDeadline(time.Time{}) cc.SetReadDeadline(time.Time{})
glog.V(LINFO).Infof("[socks5-udp] %s <-> %s [tun: %s]", s.conn.RemoteAddr(), socksAddr, reply.Addr) glog.V(LINFO).Infof("[socks5-udp] %s <-> %s [tun: %s]", s.conn.RemoteAddr(), socksAddr, reply.Addr)
go s.tunnelUDP(relay, cc, true) go s.tunnelClientUDP(relay, cc)
} }
glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr) glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr)
@ -368,7 +368,7 @@ func (s *Socks5Server) handleUDPTunnel(req *gosocks5.Request) {
glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), socksAddr, reply) glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), socksAddr, reply)
glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr) glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr)
s.tunnelUDP(uc, s.conn, false) s.tunnelServerUDP(s.conn, uc)
glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", s.conn.RemoteAddr(), socksAddr) glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", s.conn.RemoteAddr(), socksAddr)
return return
} }
@ -535,7 +535,7 @@ func (s *Socks5Server) transportUDP(relay, peer *net.UDPConn) (err error) {
return return
} }
func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err error) { func (s *Socks5Server) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error) {
errc := make(chan error, 2) errc := make(chan error, 2)
var clientAddr *net.UDPAddr var clientAddr *net.UDPAddr
@ -551,9 +551,9 @@ func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err
return return
} }
var dgram *gosocks5.UDPDatagram // glog.V(LDEBUG).Infof("read udp %d, % #x", n, b[:n])
if client { // pipe from relay to tunnel // pipe from relay to tunnel
dgram, err = gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n])) dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n]))
if err != nil { if err != nil {
errc <- err errc <- err
return return
@ -567,16 +567,6 @@ func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err
return return
} }
glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data)) glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data))
} else { // pipe from peer to tunnel
dgram = gosocks5.NewUDPDatagram(
gosocks5.NewUDPHeader(uint16(n), 0, ToSocksAddr(addr)), b[:n])
if err := dgram.Write(cc); err != nil {
glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), dgram.Header.Addr, err)
errc <- err
return
}
glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", cc.RemoteAddr(), dgram.Header.Addr, len(dgram.Data))
}
} }
}() }()
@ -589,7 +579,7 @@ func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err
return return
} }
if client { // pipe from tunnel to relay // pipe from tunnel to relay
if clientAddr == nil { if clientAddr == nil {
continue continue
} }
@ -602,7 +592,52 @@ func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err
return return
} }
glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data)) glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data))
} else { // pipe from tunnel to peer }
}()
select {
case err = <-errc:
}
return
}
func (s *Socks5Server) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error) {
errc := make(chan error, 2)
go func() {
b := make([]byte, LargeBufferSize)
for {
n, addr, err := uc.ReadFromUDP(b)
if err != nil {
glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), addr, err)
errc <- err
return
}
// pipe from peer to tunnel
dgram := gosocks5.NewUDPDatagram(
gosocks5.NewUDPHeader(uint16(n), 0, ToSocksAddr(addr)), b[:n])
if err := dgram.Write(cc); err != nil {
glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), dgram.Header.Addr, err)
errc <- err
return
}
glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", cc.RemoteAddr(), dgram.Header.Addr, len(dgram.Data))
}
}()
go func() {
for {
dgram, err := gosocks5.ReadUDPDatagram(cc)
if err != nil {
glog.V(LWARNING).Infof("[udp-tun] %s -> 0 : %s", cc.RemoteAddr(), err)
errc <- err
return
}
// pipe from tunnel to peer
addr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String()) addr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String())
if err != nil { if err != nil {
continue // drop silently continue // drop silently
@ -614,7 +649,6 @@ func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err
} }
glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", cc.RemoteAddr(), addr, len(dgram.Data)) glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", cc.RemoteAddr(), addr, len(dgram.Data))
} }
}
}() }()
select { select {

View File

@ -9,16 +9,16 @@
"revisionTime": "2015-11-07T02:50:05Z" "revisionTime": "2015-11-07T02:50:05Z"
}, },
{ {
"checksumSHA1": "8MJEwmyaAHcaQs6QdWRaNxPMeVU=", "checksumSHA1": "5TwW96Afcvo+zm0tAn+DSNIQreQ=",
"path": "github.com/ginuerzh/gosocks5", "path": "github.com/ginuerzh/gosocks5",
"revision": "3d7715d71db0b8717afd7f07c326d6c88f2c3922", "revision": "0f737bddba2abd1496dc03c8b39b817cc5f33fa7",
"revisionTime": "2017-01-14T09:14:19Z" "revisionTime": "2017-01-19T05:34:58Z"
}, },
{ {
"checksumSHA1": "v717b3fIhWDBx/Q4TQjkQ/qk+dg=", "checksumSHA1": "g55EnuSESwa92RY7U+shNoPi900=",
"path": "github.com/ginuerzh/gost", "path": "github.com/ginuerzh/gost",
"revision": "a6c43e8641e0c342a59c1b59a105cbb09b6820ac", "revision": "c58981e8583d2df5a09f7244ffd9e36bb4beecc7",
"revisionTime": "2017-01-14T09:42:47Z" "revisionTime": "2017-01-15T09:50:29Z"
}, },
{ {
"checksumSHA1": "URsJa4y/sUUw/STmbeYx9EKqaYE=", "checksumSHA1": "URsJa4y/sUUw/STmbeYx9EKqaYE=",

View File

@ -321,7 +321,7 @@ func (s *Socks5Server) handleUDPRelay(req *gosocks5.Request) {
cc.SetReadDeadline(time.Time{}) cc.SetReadDeadline(time.Time{})
glog.V(LINFO).Infof("[socks5-udp] %s <-> %s [tun: %s]", s.conn.RemoteAddr(), socksAddr, reply.Addr) glog.V(LINFO).Infof("[socks5-udp] %s <-> %s [tun: %s]", s.conn.RemoteAddr(), socksAddr, reply.Addr)
go s.tunnelUDP(relay, cc, true) go s.tunnelClientUDP(relay, cc)
} }
glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr) glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr)
@ -368,7 +368,7 @@ func (s *Socks5Server) handleUDPTunnel(req *gosocks5.Request) {
glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), socksAddr, reply) glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), socksAddr, reply)
glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr) glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr)
s.tunnelUDP(uc, s.conn, false) s.tunnelServerUDP(s.conn, uc)
glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", s.conn.RemoteAddr(), socksAddr) glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", s.conn.RemoteAddr(), socksAddr)
return return
} }
@ -535,7 +535,7 @@ func (s *Socks5Server) transportUDP(relay, peer *net.UDPConn) (err error) {
return return
} }
func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err error) { func (s *Socks5Server) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error) {
errc := make(chan error, 2) errc := make(chan error, 2)
var clientAddr *net.UDPAddr var clientAddr *net.UDPAddr
@ -551,9 +551,9 @@ func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err
return return
} }
var dgram *gosocks5.UDPDatagram // glog.V(LDEBUG).Infof("read udp %d, % #x", n, b[:n])
if client { // pipe from relay to tunnel // pipe from relay to tunnel
dgram, err = gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n])) dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n]))
if err != nil { if err != nil {
errc <- err errc <- err
return return
@ -567,16 +567,6 @@ func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err
return return
} }
glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data)) glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data))
} else { // pipe from peer to tunnel
dgram = gosocks5.NewUDPDatagram(
gosocks5.NewUDPHeader(uint16(n), 0, ToSocksAddr(addr)), b[:n])
if err := dgram.Write(cc); err != nil {
glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), dgram.Header.Addr, err)
errc <- err
return
}
glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", cc.RemoteAddr(), dgram.Header.Addr, len(dgram.Data))
}
} }
}() }()
@ -589,7 +579,7 @@ func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err
return return
} }
if client { // pipe from tunnel to relay // pipe from tunnel to relay
if clientAddr == nil { if clientAddr == nil {
continue continue
} }
@ -602,7 +592,52 @@ func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err
return return
} }
glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data)) glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data))
} else { // pipe from tunnel to peer }
}()
select {
case err = <-errc:
}
return
}
func (s *Socks5Server) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error) {
errc := make(chan error, 2)
go func() {
b := make([]byte, LargeBufferSize)
for {
n, addr, err := uc.ReadFromUDP(b)
if err != nil {
glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), addr, err)
errc <- err
return
}
// pipe from peer to tunnel
dgram := gosocks5.NewUDPDatagram(
gosocks5.NewUDPHeader(uint16(n), 0, ToSocksAddr(addr)), b[:n])
if err := dgram.Write(cc); err != nil {
glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), dgram.Header.Addr, err)
errc <- err
return
}
glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", cc.RemoteAddr(), dgram.Header.Addr, len(dgram.Data))
}
}()
go func() {
for {
dgram, err := gosocks5.ReadUDPDatagram(cc)
if err != nil {
glog.V(LWARNING).Infof("[udp-tun] %s -> 0 : %s", cc.RemoteAddr(), err)
errc <- err
return
}
// pipe from tunnel to peer
addr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String()) addr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String())
if err != nil { if err != nil {
continue // drop silently continue // drop silently
@ -614,7 +649,6 @@ func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err
} }
glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", cc.RemoteAddr(), addr, len(dgram.Data)) glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", cc.RemoteAddr(), addr, len(dgram.Data))
} }
}
}() }()
select { select {