diff --git a/cmd/gost/vendor/github.com/ginuerzh/gosocks5/socks5.go b/cmd/gost/vendor/github.com/ginuerzh/gosocks5/socks5.go index c712f66..d492571 100644 --- a/cmd/gost/vendor/github.com/ginuerzh/gosocks5/socks5.go +++ b/cmd/gost/vendor/github.com/ginuerzh/gosocks5/socks5.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" "net" "strconv" "sync" @@ -591,7 +592,6 @@ func NewUDPDatagram(header *UDPHeader, data []byte) *UDPDatagram { } func ReadUDPDatagram(r io.Reader) (*UDPDatagram, error) { - // b := make([]byte, 65797) b := lPool.Get().([]byte) defer lPool.Put(b) @@ -621,17 +621,21 @@ func ReadUDPDatagram(r io.Reader) (*UDPDatagram, error) { return nil, ErrBadAddrType } - // extended feature, for udp over tcp, using reserved field for data length 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 { return nil, err } n = hlen + dlen } - if dlen == 0 { - dlen = n - hlen - } header.Addr = new(Addr) if err := header.Addr.Decode(b[3:hlen]); err != nil { diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/README.md b/cmd/gost/vendor/github.com/ginuerzh/gost/README.md index be5ee72..dfbc18e 100644 --- a/cmd/gost/vendor/github.com/ginuerzh/gost/README.md +++ b/cmd/gost/vendor/github.com/ginuerzh/gost/README.md @@ -164,9 +164,10 @@ gost -L=tcp://:2222/192.168.1.1:22 -F=... #### 本地端口转发(UDP) ```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上。 +每条转发通道都有超时时间,当超过此时间,且在此时间段内无任何数据交互,则此通道将关闭。可以通过`ttl`参数来设置超时时间,默认值为60秒。 **注:** 转发UDP数据时,如果有代理链,则代理链的末端(最后一个-F参数)必须是gost SOCKS5类型代理。 diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/README_en.md b/cmd/gost/vendor/github.com/ginuerzh/gost/README_en.md index bfb5474..5daa2b5 100644 --- a/cmd/gost/vendor/github.com/ginuerzh/gost/README_en.md +++ b/cmd/gost/vendor/github.com/ginuerzh/gost/README_en.md @@ -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 ```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. diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/socks.go b/cmd/gost/vendor/github.com/ginuerzh/gost/socks.go index 97dc18a..59d801d 100644 --- a/cmd/gost/vendor/github.com/ginuerzh/gost/socks.go +++ b/cmd/gost/vendor/github.com/ginuerzh/gost/socks.go @@ -321,7 +321,7 @@ func (s *Socks5Server) handleUDPRelay(req *gosocks5.Request) { cc.SetReadDeadline(time.Time{}) 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) @@ -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(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) return } @@ -535,7 +535,7 @@ func (s *Socks5Server) transportUDP(relay, peer *net.UDPConn) (err error) { 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) var clientAddr *net.UDPAddr @@ -551,32 +551,22 @@ func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err return } - var dgram *gosocks5.UDPDatagram - if client { // pipe from relay to tunnel - dgram, err = gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n])) - if err != nil { - errc <- err - return - } - if clientAddr == nil { - clientAddr = addr - } - dgram.Header.Rsv = uint16(len(dgram.Data)) - if err := dgram.Write(cc); err != nil { - errc <- err - return - } - 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)) + // glog.V(LDEBUG).Infof("read udp %d, % #x", n, b[:n]) + // pipe from relay to tunnel + dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n])) + if err != nil { + errc <- err + return } + if clientAddr == nil { + clientAddr = addr + } + dgram.Header.Rsv = uint16(len(dgram.Data)) + if err := dgram.Write(cc); err != nil { + errc <- err + return + } + glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data)) } }() @@ -589,31 +579,75 @@ func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err return } - if client { // pipe from tunnel to relay - if clientAddr == nil { - continue - } - dgram.Header.Rsv = 0 - - buf := bytes.Buffer{} - dgram.Write(&buf) - if _, err := uc.WriteToUDP(buf.Bytes(), clientAddr); err != nil { - errc <- err - return - } - glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data)) - } else { // pipe from tunnel to peer - addr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String()) - if err != nil { - continue // drop silently - } - if _, err := uc.WriteToUDP(dgram.Data, addr); err != nil { - glog.V(LWARNING).Infof("[udp-tun] %s -> %s : %s", cc.RemoteAddr(), addr, err) - errc <- err - return - } - glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", cc.RemoteAddr(), addr, len(dgram.Data)) + // pipe from tunnel to relay + if clientAddr == nil { + continue } + dgram.Header.Rsv = 0 + + buf := bytes.Buffer{} + dgram.Write(&buf) + if _, err := uc.WriteToUDP(buf.Bytes(), clientAddr); err != nil { + errc <- err + return + } + glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data)) + } + }() + + 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()) + if err != nil { + continue // drop silently + } + if _, err := uc.WriteToUDP(dgram.Data, addr); err != nil { + glog.V(LWARNING).Infof("[udp-tun] %s -> %s : %s", cc.RemoteAddr(), addr, err) + errc <- err + return + } + glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", cc.RemoteAddr(), addr, len(dgram.Data)) } }() diff --git a/cmd/gost/vendor/vendor.json b/cmd/gost/vendor/vendor.json index 8016fd2..972750c 100644 --- a/cmd/gost/vendor/vendor.json +++ b/cmd/gost/vendor/vendor.json @@ -9,16 +9,16 @@ "revisionTime": "2015-11-07T02:50:05Z" }, { - "checksumSHA1": "8MJEwmyaAHcaQs6QdWRaNxPMeVU=", + "checksumSHA1": "5TwW96Afcvo+zm0tAn+DSNIQreQ=", "path": "github.com/ginuerzh/gosocks5", - "revision": "3d7715d71db0b8717afd7f07c326d6c88f2c3922", - "revisionTime": "2017-01-14T09:14:19Z" + "revision": "0f737bddba2abd1496dc03c8b39b817cc5f33fa7", + "revisionTime": "2017-01-19T05:34:58Z" }, { - "checksumSHA1": "v717b3fIhWDBx/Q4TQjkQ/qk+dg=", + "checksumSHA1": "g55EnuSESwa92RY7U+shNoPi900=", "path": "github.com/ginuerzh/gost", - "revision": "a6c43e8641e0c342a59c1b59a105cbb09b6820ac", - "revisionTime": "2017-01-14T09:42:47Z" + "revision": "c58981e8583d2df5a09f7244ffd9e36bb4beecc7", + "revisionTime": "2017-01-15T09:50:29Z" }, { "checksumSHA1": "URsJa4y/sUUw/STmbeYx9EKqaYE=", diff --git a/socks.go b/socks.go index 97dc18a..59d801d 100644 --- a/socks.go +++ b/socks.go @@ -321,7 +321,7 @@ func (s *Socks5Server) handleUDPRelay(req *gosocks5.Request) { cc.SetReadDeadline(time.Time{}) 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) @@ -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(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) return } @@ -535,7 +535,7 @@ func (s *Socks5Server) transportUDP(relay, peer *net.UDPConn) (err error) { 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) var clientAddr *net.UDPAddr @@ -551,32 +551,22 @@ func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err return } - var dgram *gosocks5.UDPDatagram - if client { // pipe from relay to tunnel - dgram, err = gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n])) - if err != nil { - errc <- err - return - } - if clientAddr == nil { - clientAddr = addr - } - dgram.Header.Rsv = uint16(len(dgram.Data)) - if err := dgram.Write(cc); err != nil { - errc <- err - return - } - 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)) + // glog.V(LDEBUG).Infof("read udp %d, % #x", n, b[:n]) + // pipe from relay to tunnel + dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n])) + if err != nil { + errc <- err + return } + if clientAddr == nil { + clientAddr = addr + } + dgram.Header.Rsv = uint16(len(dgram.Data)) + if err := dgram.Write(cc); err != nil { + errc <- err + return + } + glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data)) } }() @@ -589,31 +579,75 @@ func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err return } - if client { // pipe from tunnel to relay - if clientAddr == nil { - continue - } - dgram.Header.Rsv = 0 - - buf := bytes.Buffer{} - dgram.Write(&buf) - if _, err := uc.WriteToUDP(buf.Bytes(), clientAddr); err != nil { - errc <- err - return - } - glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data)) - } else { // pipe from tunnel to peer - addr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String()) - if err != nil { - continue // drop silently - } - if _, err := uc.WriteToUDP(dgram.Data, addr); err != nil { - glog.V(LWARNING).Infof("[udp-tun] %s -> %s : %s", cc.RemoteAddr(), addr, err) - errc <- err - return - } - glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", cc.RemoteAddr(), addr, len(dgram.Data)) + // pipe from tunnel to relay + if clientAddr == nil { + continue } + dgram.Header.Rsv = 0 + + buf := bytes.Buffer{} + dgram.Write(&buf) + if _, err := uc.WriteToUDP(buf.Bytes(), clientAddr); err != nil { + errc <- err + return + } + glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data)) + } + }() + + 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()) + if err != nil { + continue // drop silently + } + if _, err := uc.WriteToUDP(dgram.Data, addr); err != nil { + glog.V(LWARNING).Infof("[udp-tun] %s -> %s : %s", cc.RemoteAddr(), addr, err) + errc <- err + return + } + glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", cc.RemoteAddr(), addr, len(dgram.Data)) } }()