diff --git a/dialer.go b/dialer.go index 4c17b32..50733b3 100644 --- a/dialer.go +++ b/dialer.go @@ -14,9 +14,6 @@ type Dialer interface { // Dial connects to the given address via the proxy. Dial(network, addr string) (c net.Conn, err error) - // DialUDP returns a UDP PacketConn - DialUDP(network, addr string) (c net.PacketConn, err error) - // Get the dialer by dstAddr NextDialer(dstAddr string) Dialer } diff --git a/direct.go b/direct.go index a83a2a9..33013e7 100644 --- a/direct.go +++ b/direct.go @@ -3,8 +3,7 @@ package main import "net" // direct proxy -type direct struct { -} +type direct struct{} // Direct proxy var Direct = &direct{} @@ -12,6 +11,10 @@ var Direct = &direct{} func (d *direct) Addr() string { return "DIRECT" } func (d *direct) Dial(network, addr string) (net.Conn, error) { + if network == "uot" { + network = "udp" + } + c, err := net.Dial(network, addr) if c, ok := c.(*net.TCPConn); ok { c.SetKeepAlive(true) @@ -19,14 +22,4 @@ func (d *direct) Dial(network, addr string) (net.Conn, error) { return c, err } -func (d *direct) DialUDP(network, addr string) (net.PacketConn, error) { - uAddr, err := net.ResolveUDPAddr(network, addr) - if err != nil { - logf("ResolveUDPAddr error: %s", err) - return nil, err - } - - return net.DialUDP("udp", nil, uAddr) -} - func (d *direct) NextDialer(dstAddr string) Dialer { return d } diff --git a/http.go b/http.go index 1beb95e..335a569 100644 --- a/http.go +++ b/http.go @@ -236,11 +236,6 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, error) { return nil, errors.New("proxy-http cound not connect remote address: " + addr + ". error code: " + code) } -// DialUDP . -func (s *HTTP) DialUDP(network, addr string) (net.PacketConn, error) { - return nil, errors.New("proxy-http udp not supported by http proxy now") -} - // parseFirstLine parses "GET /foo HTTP/1.1" OR "HTTP/1.1 200 OK" into its three parts. func parseFirstLine(tp *textproto.Reader) (r1, r2, r3 string, ok bool) { line, err := tp.ReadLine() diff --git a/rule.go b/rule.go index ad9d186..3102909 100644 --- a/rule.go +++ b/rule.go @@ -113,11 +113,6 @@ func (rd *RuleDialer) Dial(network, addr string) (net.Conn, error) { return rd.NextDialer(addr).Dial(network, addr) } -// DialUDP . -func (rd *RuleDialer) DialUDP(network, addr string) (net.PacketConn, error) { - return rd.NextDialer(addr).DialUDP(network, addr) -} - // AddDomainIP used to update ipMap rules according to domainMap rule func (rd *RuleDialer) AddDomainIP(domain, ip string) error { if ip != "" { diff --git a/socks5.go b/socks5.go index bad9425..3e686fd 100644 --- a/socks5.go +++ b/socks5.go @@ -156,11 +156,6 @@ func (s *SOCKS5) Dial(network, addr string) (net.Conn, error) { return c, nil } -// DialUDP . -func (s *SOCKS5) DialUDP(network, addr string) (net.PacketConn, error) { - return nil, errors.New("udp not supported by socks5 proxy now") -} - // connect takes an existing connection to a socks5 proxy server, // and commands the server to extend that connection to target, // which must be a canonical address with a host and port. diff --git a/ss.go b/ss.go index f31a949..3674b87 100644 --- a/ss.go +++ b/ss.go @@ -207,6 +207,11 @@ func (s *SS) ListenAndServeUDP() { } +// ListCipher . +func ListCipher() string { + return strings.Join(core.ListCipher(), " ") +} + // Dial connects to the address addr on the network net via the proxy. func (s *SS) Dial(network, addr string) (net.Conn, error) { target := ParseAddr(addr) @@ -216,12 +221,12 @@ func (s *SS) Dial(network, addr string) (net.Conn, error) { switch network { case "tcp": - return s.DialTCP(target) - case "udp": + return s.dialTCP(target) + case "uot": target[0] = target[0] | 0x8 - return s.DialTCP(target) - // case "udp": - // return s.DialUDP(target) + return s.dialTCP(target) + case "udp": + return s.dialUDP(target) default: return nil, errors.New("Unknown schema: " + network) } @@ -229,7 +234,7 @@ func (s *SS) Dial(network, addr string) (net.Conn, error) { } // DialTCP connects to the address addr via the proxy. -func (s *SS) DialTCP(target Addr) (net.Conn, error) { +func (s *SS) dialTCP(target Addr) (net.Conn, error) { c, err := s.cDialer.Dial("tcp", s.addr) if err != nil { logf("dial to %s error: %s", s.addr, err) @@ -249,20 +254,58 @@ func (s *SS) DialTCP(target Addr) (net.Conn, error) { return c, err } -// DialUDP . -func (s *SS) DialUDP(network, addr string) (net.PacketConn, error) { - target := ParseAddr(addr) - if target == nil { - return nil, errors.New("Unable to parse address: " + addr) +// TODO: support forwarder chain +func (s *SS) dialUDP(target Addr) (net.Conn, error) { + c, err := net.ListenPacket("udp", "") + if err != nil { + logf("proxy-ss dialudp failed to listen packet: %v", err) + return nil, err } - c, _ := net.ListenPacket(network, "") - c = s.PacketConn(c) + sUDPAddr, err := net.ResolveUDPAddr("udp", s.Addr()) + suc := &ssUDPConn{ + PacketConn: s.PacketConn(c), + addr: sUDPAddr, + target: target, + } - return c, nil + return suc, err } -// ListCipher . -func ListCipher() string { - return strings.Join(core.ListCipher(), " ") +type ssUDPConn struct { + net.PacketConn + + addr net.Addr + target Addr +} + +func (uc *ssUDPConn) Read(b []byte) (int, error) { + buf := make([]byte, len(b)) + n, raddr, err := uc.PacketConn.ReadFrom(buf) + if err != nil { + return 0, err + } + + srcAddr := ParseAddr(raddr.String()) + copy(b, buf[len(srcAddr):]) + + return n - len(srcAddr), err +} + +func (uc *ssUDPConn) Write(b []byte) (int, error) { + buf := make([]byte, len(uc.target)+len(b)) + copy(buf, uc.target) + copy(buf[len(uc.target):], b) + + // logf("Write: \n%s", hex.Dump(buf)) + + return uc.PacketConn.WriteTo(buf, uc.addr) +} + +func (uc *ssUDPConn) WriteTo(b []byte, addr net.Addr) (int, error) { + return 0, errors.New("not available") +} + +func (uc *ssUDPConn) RemoteAddr() net.Addr { + return uc.addr } diff --git a/strategy.go b/strategy.go index 2852dcc..1af69d0 100644 --- a/strategy.go +++ b/strategy.go @@ -67,10 +67,6 @@ func (rr *rrDialer) Dial(network, addr string) (net.Conn, error) { return rr.NextDialer(addr).Dial(network, addr) } -func (rr *rrDialer) DialUDP(network, addr string) (net.PacketConn, error) { - return rr.NextDialer(addr).DialUDP(network, addr) -} - func (rr *rrDialer) NextDialer(dstAddr string) Dialer { n := len(rr.dialers) if n == 1 { diff --git a/udptun.go b/udptun.go index e21dcc9..46990b8 100644 --- a/udptun.go +++ b/udptun.go @@ -2,7 +2,6 @@ package main import ( "net" - "time" ) // UDPTun struct @@ -35,18 +34,7 @@ func (s *UDPTun) ListenAndServe() { logf("proxy-udptun listening UDP on %s", s.addr) - if s.sDialer.Addr() == "DIRECT" { - s.ServeDirect(c) - } else { - s.ServeSS(c) - } - -} - -// ServeDirect . -func (s *UDPTun) ServeDirect(c net.PacketConn) { buf := make([]byte, udpBufSize) - for { n, clientAddr, err := c.ReadFrom(buf) if err != nil { @@ -57,57 +45,26 @@ func (s *UDPTun) ServeDirect(c net.PacketConn) { rc, err := s.sDialer.Dial("udp", s.raddr) if err != nil { logf("proxy-udptun failed to connect to server %v: %v", s.raddr, err) - return - } - - if urc, ok := rc.(*net.UDPConn); ok { - urc.Write(buf[:n]) - go func() { - timedCopy(c, clientAddr, urc, 5*time.Minute, false) - urc.Close() - }() - } - - logf("proxy-udptun %s <-> %s", clientAddr, s.raddr) - } -} - -// ServeSS . -func (s *UDPTun) ServeSS(c net.PacketConn) { - // var nm sync.Map - buf := make([]byte, udpBufSize) - tgt := ParseAddr(s.raddr) - copy(buf, tgt) - - for { - n, clientAddr, err := c.ReadFrom(buf[len(tgt):]) - if err != nil { - logf("proxy-udptun read error: %v", err) continue } - go func() { - rc, err := s.sDialer.DialUDP("udp", s.raddr) - if err != nil { - logf("proxy-udptun failed to connect to server %v: %v", s.raddr, err) - return - } + n, err = rc.Write(buf[:n]) + if err != nil { + logf("proxy-udptun rc.Write error: %v", err) + continue + } - // TODO: check here, get the correct sDialer's addr - sUDPAddr, err := net.ResolveUDPAddr("udp", s.sDialer.Addr()) - if err != nil { - logf("proxy-udptun failed to ResolveUDPAddr %s", s.sDialer.Addr()) - return - } + buf = make([]byte, udpBufSize) + n, err = rc.Read(buf) + if err != nil { + logf("proxy-udptun rc.Read error: %v", err) + continue + } + rc.Close() - rc.WriteTo(buf[:len(tgt)+n], sUDPAddr) + // logf("rc resp: \n%s", hex.Dump(buf[:n])) - go func() { - timedCopy(c, clientAddr, rc, 5*time.Minute, false) - rc.Close() - }() - - logf("proxy-udptun %s <-> %s", clientAddr, s.raddr) - }() + c.WriteTo(buf[:n], clientAddr) + logf("proxy-udptun %s <-> %s", clientAddr, s.raddr) } } diff --git a/uottun.go b/uottun.go index fabf99a..a87c886 100644 --- a/uottun.go +++ b/uottun.go @@ -45,34 +45,32 @@ func (s *UoTTun) ListenAndServe() { continue } - go func() { - rc, err := s.sDialer.Dial("udp", s.raddr) + rc, err := s.sDialer.Dial("uot", s.raddr) + if err != nil { + logf("proxy-uottun failed to connect to server %v: %v", s.raddr, err) + return + } + + rc.Write(buf[:n]) + + // no remote forwarder, just a local udp forwarder + if urc, ok := rc.(*net.UDPConn); ok { + + go func() { + timedCopy(c, clientAddr, urc, 5*time.Minute, false) + urc.Close() + }() + + } else { // remote forwarder, udp over tcp + resp, err := ioutil.ReadAll(rc) if err != nil { - logf("proxy-uottun failed to connect to server %v: %v", s.raddr, err) + logf("error in ioutil.ReadAll: %s\n", err) return } + rc.Close() + c.WriteTo(resp, clientAddr) + } - rc.Write(buf[:n]) - - // no remote forwarder, just a local udp forwarder - if urc, ok := rc.(*net.UDPConn); ok { - - go func() { - timedCopy(c, clientAddr, urc, 5*time.Minute, false) - urc.Close() - }() - - } else { // remote forwarder, udp over tcp - resp, err := ioutil.ReadAll(rc) - if err != nil { - logf("error in ioutil.ReadAll: %s\n", err) - return - } - rc.Close() - c.WriteTo(resp, clientAddr) - } - - logf("proxy-uottun %s <-> %s", clientAddr, s.raddr) - }() + logf("proxy-uottun %s <-> %s", clientAddr, s.raddr) } }