ss: add nat map in ListenAndServeUDP

This commit is contained in:
nadoo 2018-01-20 15:08:23 +08:00
parent 65e6caaa39
commit 38de018d91
4 changed files with 59 additions and 73 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
# Binaries for programs and plugins # Binaries for programs and plugins
*.exe *.exe
*.exe~
*.dll *.dll
*.so *.so
*.dylib *.dylib

16
conn.go
View File

@ -54,26 +54,16 @@ func relay(left, right net.Conn) (int64, int64, error) {
} }
// copy from src to dst at target with read timeout // copy from src to dst at target with read timeout
func timedCopy(dst net.PacketConn, target net.Addr, src net.PacketConn, timeout time.Duration, srcIncluded bool) error { func timedCopy(dst net.PacketConn, target net.Addr, src net.PacketConn, timeout time.Duration) error {
buf := make([]byte, udpBufSize) buf := make([]byte, udpBufSize)
for { for {
src.SetReadDeadline(time.Now().Add(timeout)) src.SetReadDeadline(time.Now().Add(timeout))
n, raddr, err := src.ReadFrom(buf) n, _, err := src.ReadFrom(buf)
if err != nil { if err != nil {
return err return err
} }
if srcIncluded { // server -> client: add original packet source _, err = dst.WriteTo(buf[:n], target)
srcAddr := ParseAddr(raddr.String())
copy(buf[len(srcAddr):], buf[:n])
copy(buf, srcAddr)
_, err = dst.WriteTo(buf[:len(srcAddr)+n], target)
} else { // client -> user: strip original packet source
srcAddr := SplitAddr(buf[:n])
_, err = dst.WriteTo(buf[len(srcAddr):n], target)
}
if err != nil { if err != nil {
return err return err
} }

113
ss.go
View File

@ -5,6 +5,7 @@ import (
"log" "log"
"net" "net"
"strings" "strings"
"sync"
"time" "time"
"github.com/shadowsocks/go-shadowsocks2/core" "github.com/shadowsocks/go-shadowsocks2/core"
@ -139,61 +140,59 @@ func (s *SS) ServeTCP(c net.Conn) {
// ListenAndServeUDP serves udp ss requests. // ListenAndServeUDP serves udp ss requests.
func (s *SS) ListenAndServeUDP() { func (s *SS) ListenAndServeUDP() {
c, err := net.ListenPacket("udp", s.addr) lc, err := net.ListenPacket("udp", s.addr)
if err != nil { if err != nil {
logf("proxy-ss-udp failed to listen on %s: %v", s.addr, err) logf("proxy-ss-udp failed to listen on %s: %v", s.addr, err)
return return
} }
defer c.Close() defer lc.Close()
lc = s.PacketConn(lc)
logf("proxy-ss-udp listening UDP on %s", s.addr) logf("proxy-ss-udp listening UDP on %s", s.addr)
c = s.PacketConn(c) var nm sync.Map
buf := make([]byte, udpBufSize) buf := make([]byte, udpBufSize)
for { for {
c := NewPktConn(lc, nil, nil, true)
n, raddr, err := c.ReadFrom(buf) n, raddr, err := c.ReadFrom(buf)
if err != nil { if err != nil {
logf("proxy-ss-udp remote read error: %v", err) logf("proxy-ss-udp remote read error: %v", err)
continue continue
} }
tgtAddr := SplitAddr(buf[:n]) logf("proxy-ss-udp %s <-> %s", raddr, c.tgtAddr)
if tgtAddr == nil {
logf("proxy-ss-udp failed to split target address from packet: %q", buf[:n]) var pc *PktConn
continue v, ok := nm.Load(raddr.String())
if !ok && v == nil {
lpc, nextHop, err := s.sDialer.DialUDP("udp", c.tgtAddr.String())
if err != nil {
logf("proxy-ss-udp remote listen error: %v", err)
continue
}
pc = NewPktConn(lpc, nextHop, nil, false)
nm.Store(raddr.String(), pc)
go func() {
timedCopy(c, raddr, pc, 1*time.Minute)
pc.Close()
nm.Delete(raddr.String())
}()
} else {
pc = v.(*PktConn)
} }
logf("proxy-ss-udp %s <-> %s", raddr, tgtAddr) _, err = pc.WriteTo(buf[:n], pc.writeAddr)
payload := buf[len(tgtAddr):n]
rc, nexHop, err := s.sDialer.DialUDP("udp", tgtAddr.String())
if err != nil {
logf("proxy-ss-udp remote listen error: %v", err)
continue
}
_, err = rc.WriteTo(payload, nexHop) // accept only UDPAddr despite the signature
if err != nil { if err != nil {
logf("proxy-ss-udp remote write error: %v", err) logf("proxy-ss-udp remote write error: %v", err)
continue 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)
} }
} }
// ListCipher . // ListCipher .
@ -248,28 +247,23 @@ func (s *SS) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
type PktConn struct { type PktConn struct {
net.PacketConn net.PacketConn
addr net.Addr // write to and read from addr writeAddr net.Addr // write to and read from addr
target Addr
tgtAddr Addr
tgtHeader bool tgtHeader bool
} }
// NewPktConn returns a PktConn // NewPktConn returns a PktConn
func NewPktConn(c net.PacketConn, addr net.Addr, target Addr, tgtHeader bool) *PktConn { func NewPktConn(c net.PacketConn, writeAddr net.Addr, tgtAddr Addr, tgtHeader bool) *PktConn {
pc := &PktConn{ pc := &PktConn{
PacketConn: c, PacketConn: c,
addr: addr, writeAddr: writeAddr,
target: target, tgtAddr: tgtAddr,
tgtHeader: tgtHeader} tgtHeader: tgtHeader}
return pc return pc
} }
func (pc *PktConn) Read(b []byte) (int, error) {
n, _, err := pc.ReadFrom(b)
return n, err
}
func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) { func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
if !pc.tgtHeader { if !pc.tgtHeader {
return pc.PacketConn.ReadFrom(b) return pc.PacketConn.ReadFrom(b)
} }
@ -280,28 +274,29 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
return n, raddr, err return n, raddr, err
} }
srcAddr := ParseAddr(raddr.String()) tgtAddr := SplitAddr(buf)
copy(b, buf[len(srcAddr):]) copy(b, buf[len(tgtAddr):])
return n - len(srcAddr), raddr, err //test
} if pc.writeAddr == nil {
pc.writeAddr = raddr
func (pc *PktConn) Write(b []byte) (int, error) {
if !pc.tgtHeader {
return pc.PacketConn.WriteTo(b, pc.addr)
} }
buf := make([]byte, len(pc.target)+len(b)) if pc.tgtAddr == nil {
copy(buf, pc.target) pc.tgtAddr = tgtAddr
copy(buf[len(pc.target):], b) }
return pc.PacketConn.WriteTo(buf, pc.addr) return n - len(tgtAddr), raddr, err
} }
func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) { func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) {
return pc.Write(b) if !pc.tgtHeader {
} return pc.PacketConn.WriteTo(b, addr)
}
func (pc *PktConn) RemoteAddr() net.Addr { buf := make([]byte, len(pc.tgtAddr)+len(b))
return pc.addr copy(buf, pc.tgtAddr)
copy(buf[len(pc.tgtAddr):], b)
return pc.PacketConn.WriteTo(buf, pc.writeAddr)
} }

View File

@ -56,7 +56,7 @@ func (s *UoTTun) ListenAndServe() {
// no remote forwarder, just a local udp forwarder // no remote forwarder, just a local udp forwarder
if urc, ok := rc.(*net.UDPConn); ok { if urc, ok := rc.(*net.UDPConn); ok {
go func() { go func() {
timedCopy(c, clientAddr, urc, 5*time.Minute, false) timedCopy(c, clientAddr, urc, 5*time.Minute)
urc.Close() urc.Close()
}() }()
} else { // remote forwarder, udp over tcp } else { // remote forwarder, udp over tcp