From aeb0acab33f4add80e44807f2a82eb87caa08a85 Mon Sep 17 00:00:00 2001 From: nadoo <287492+nadoo@users.noreply.github.com> Date: Fri, 8 Sep 2017 12:09:57 +0800 Subject: [PATCH] ss: add udp over tcp support --- README.md | 2 +- server.go | 3 +++ ss.go | 42 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 13e671a..0ee874f 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ General: - Rule proxy based on destinations: [Config Examples](config/examples) TODO: -- [ ] UDP over TCP +- [x] UDP over TCP (ss) - [ ] UDP Tunnel - [ ] Linux tproxy support & UDP Relay - [ ] TUN/TAP device support diff --git a/server.go b/server.go index ea0edc7..1054c45 100644 --- a/server.go +++ b/server.go @@ -57,6 +57,9 @@ func ServerFromURL(s string, sDialer Dialer) (Server, error) { case "dnstun": d := strings.Split(addr, "=") return NewDNSTun(d[0], d[1], sDialer) + case "uottun": + d := strings.Split(addr, "=") + return NewUoTTun(d[0], d[1], sDialer) } return nil, errors.New("unknown schema '" + u.Scheme + "'") diff --git a/ss.go b/ss.go index aa9332e..5d4600a 100644 --- a/ss.go +++ b/ss.go @@ -12,7 +12,7 @@ import ( "github.com/shadowsocks/go-shadowsocks2/socks" ) -const udpBufSize = 64 * 1024 +const udpBufSize = 65536 // SS . type SS struct { @@ -40,7 +40,7 @@ func NewSS(addr, method, pass string, cDialer Dialer, sDialer Dialer) (*SS, erro // ListenAndServe serves ss requests. func (s *SS) ListenAndServe() { - go s.ListenAndServeUDP() + // go s.ListenAndServeUDP() s.ListenAndServeTCP() } @@ -80,6 +80,37 @@ func (s *SS) ServeTCP(c net.Conn) { return } + // udp over tcp + if UoT(tgt[0]) { + rc, err := net.ListenPacket("udp", "") + if err != nil { + logf("UDP remote listen error: %v", err) + } + defer rc.Close() + + req := make([]byte, udpBufSize) + n, err := c.Read(req) + if err != nil { + logf("error in ioutil.ReadAll: %s\n", err) + return + } + + tgtAddr, _ := net.ResolveUDPAddr("udp", tgt.String()) + rc.WriteTo(req[:n], tgtAddr) + + buf := make([]byte, udpBufSize) + n, _, err = rc.ReadFrom(buf) + if err != nil { + logf("proxy-uottun read error: %v", err) + } + + c.Write(buf[:n]) + + logf("proxy-ss %s <-tcp-> %s <-> %s <-udp-> %s ", c.RemoteAddr(), c.LocalAddr(), rc.LocalAddr(), tgt) + + return + } + rc, err := s.sDialer.Dial("tcp", tgt.String()) if err != nil { logf("proxy-ss failed to connect to target: %v", err) @@ -171,7 +202,12 @@ func (s *SS) Dial(network, addr string) (net.Conn, error) { return nil, errors.New("Unable to parse address: " + addr) } - c, err := s.cDialer.Dial(network, s.addr) + // udp over tcp tag + if network == "udp" { + target[0] = target[0] | 0x8 + } + + c, err := s.cDialer.Dial("tcp", s.addr) if err != nil { logf("dial to %s error: %s", s.addr, err) return nil, err