diff --git a/direct.go b/direct.go index 084a3e7..b0084dd 100644 --- a/direct.go +++ b/direct.go @@ -30,15 +30,15 @@ func (d *direct) Dial(network, addr string) (net.Conn, error) { } // DialUDP connects to the given address via the proxy. -func (d *direct) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) { - pc, err = net.ListenPacket(network, "") +func (d *direct) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) { + pc, err := net.ListenPacket(network, "") if err != nil { logf("ListenPacket error: %s", err) return nil, nil, err } uAddr, err := net.ResolveUDPAddr("udp", addr) - return pc, uAddr, nil + return pc, uAddr, err } func (d *direct) NextDialer(dstAddr string) Dialer { return d } diff --git a/forwarder.go b/forwarder.go index ea34525..d48a220 100644 --- a/forwarder.go +++ b/forwarder.go @@ -25,6 +25,11 @@ func (p *Forwarder) Dial(network, addr string) (net.Conn, error) { return p.cDialer.Dial(network, addr) } +// DialUDP to remote addr via cDialer +func (p *Forwarder) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) { + return p.cDialer.DialUDP(network, addr) +} + // NextDialer returns the next cDialer func (p *Forwarder) NextDialer(dstAddr string) Dialer { return p.cDialer diff --git a/ss.go b/ss.go index 512214e..87fbee0 100644 --- a/ss.go +++ b/ss.go @@ -5,7 +5,6 @@ import ( "log" "net" "strings" - "sync" "time" "github.com/shadowsocks/go-shadowsocks2/core" @@ -139,7 +138,6 @@ func (s *SS) ServeTCP(c net.Conn) { } // ListenAndServeUDP serves udp ss requests. -// TODO: Forwarder chain not supported now. func (s *SS) ListenAndServeUDP() { c, err := net.ListenPacket("udp", s.addr) if err != nil { @@ -151,8 +149,6 @@ func (s *SS) ListenAndServeUDP() { logf("proxy-ss-udp listening UDP on %s", s.addr) c = s.PacketConn(c) - - var nm sync.Map buf := make([]byte, udpBufSize) for { @@ -168,41 +164,34 @@ func (s *SS) ListenAndServeUDP() { continue } - tgtUDPAddr, err := net.ResolveUDPAddr("udp", tgtAddr.String()) - if err != nil { - logf("proxy-ss-udp failed to resolve target UDP address: %v", err) - continue - } - logf("proxy-ss-udp %s <-> %s", raddr, tgtAddr) payload := buf[len(tgtAddr):n] - var pc net.PacketConn - v, ok := nm.Load(raddr.String()) - if !ok && v == nil { - pc, err = net.ListenPacket("udp", "") - if err != nil { - logf("proxy-ss-udp remote listen error: %v", err) - continue - } - - nm.Store(raddr.String(), pc) - go func() { - timedCopy(c, raddr, pc, 5*time.Minute, true) - pc.Close() - nm.Delete(raddr.String()) - }() - } else { - pc = v.(net.PacketConn) + rc, nexHop, err := s.sDialer.DialUDP("udp", tgtAddr.String()) + if err != nil { + logf("proxy-ss-udp remote listen error: %v", err) + continue } - _, err = pc.WriteTo(payload, tgtUDPAddr) // accept only UDPAddr despite the signature + _, err = rc.WriteTo(payload, nexHop) // accept only UDPAddr despite the signature if err != nil { logf("proxy-ss-udp remote write error: %v", err) continue } + rcBuf := make([]byte, udpBufSize) + rc.SetReadDeadline(time.Now().Add(time.Minute)) + copy(rcBuf, tgtAddr) + + n, _, err = rc.ReadFrom(rcBuf[len(tgtAddr):]) + if err != nil { + logf("proxy-ss-udp rc.Read error: %v", err) + return + } + rc.Close() + + c.WriteTo(rcBuf[:len(tgtAddr)+n], raddr) } } @@ -244,20 +233,15 @@ func (s *SS) Dial(network, addr string) (net.Conn, error) { } // DialUDP connects to the given address via the proxy. -func (s *SS) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) { - // TODO: check forward chain - pc, nextHop, err := s.cDialer.DialUDP(network, addr) +func (s *SS) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) { + pc, nextHop, err := s.cDialer.DialUDP(network, s.addr) if err != nil { - logf("proxy-ss dialudp to %s error: %s", addr, err) + logf("proxy-ss dialudp to %s error: %s", s.addr, err) return nil, nil, err } - nextHopAddr := ParseAddr(nextHop.String()) - writeTo, err = net.ResolveUDPAddr("udp", s.Addr()) - - pkc := NewPktConn(s.PacketConn(pc), writeTo, nextHopAddr, true) - - return pkc, writeTo, err + pkc := NewPktConn(s.PacketConn(pc), nextHop, ParseAddr(addr), true) + return pkc, nextHop, err } // PktConn wraps a net.PacketConn and support Write method like net.Conn @@ -271,7 +255,6 @@ type PktConn struct { // NewPktConn returns a PktConn func NewPktConn(c net.PacketConn, addr net.Addr, target Addr, tgtHeader bool) *PktConn { - pc := &PktConn{ PacketConn: c, addr: addr, @@ -312,8 +295,6 @@ func (pc *PktConn) Write(b []byte) (int, error) { copy(buf, pc.target) copy(buf[len(pc.target):], b) - // logf("Write: \n%s", hex.Dump(buf)) - return pc.PacketConn.WriteTo(buf, pc.addr) } diff --git a/udptun.go b/udptun.go index aafc1ff..3ffcb1c 100644 --- a/udptun.go +++ b/udptun.go @@ -1,7 +1,6 @@ package main import ( - "encoding/hex" "net" "time" ) @@ -45,9 +44,6 @@ func (s *UDPTun) ListenAndServe() { continue } - logf("ClientAddr: %s", clientAddr) - logf("ReadFrom:\n%s", hex.Dump(buf[:n])) - go func() { rc, wt, err := s.sDialer.DialUDP("udp", s.raddr) if err != nil { @@ -55,15 +51,12 @@ func (s *UDPTun) ListenAndServe() { return } - logf("WriteTo") n, err = rc.WriteTo(buf[:n], wt) if err != nil { logf("proxy-udptun rc.Write error: %v", err) return } - logf("ReadFrom") - rcBuf := make([]byte, udpBufSize) rc.SetReadDeadline(time.Now().Add(time.Minute)) @@ -74,9 +67,6 @@ func (s *UDPTun) ListenAndServe() { } rc.Close() - // logf("rc resp: \n%s", hex.Dump(buf[:n])) - - logf("c.WriteTo") c.WriteTo(rcBuf[:n], clientAddr) logf("proxy-udptun %s <-> %s", clientAddr, s.raddr) }()