mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 17:35:40 +08:00
ss: add nat map in ListenAndServeUDP
This commit is contained in:
parent
65e6caaa39
commit
38de018d91
1
.gitignore
vendored
1
.gitignore
vendored
@ -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
16
conn.go
@ -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
113
ss.go
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user