fix shadowsocks UDP relay

This commit is contained in:
rui.zheng 2017-08-01 21:23:40 +08:00
parent f8702c670e
commit 88c204899b
3 changed files with 52 additions and 20 deletions

View File

@ -245,7 +245,22 @@ func shadowUDPServer() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
h := gost.ShadowUDPdHandler() h := gost.ShadowUDPdHandler(
/*
gost.ChainHandlerOption(gost.NewChain(
gost.Node{
Protocol: "socks5",
Transport: "tcp",
Addr: "localhost:11080",
User: url.UserPassword("admin", "123456"),
Client: &gost.Client{
Connector: gost.SOCKS5Connector(url.UserPassword("admin", "123456")),
Transporter: gost.TCPTransporter(),
},
},
)),
*/
)
log.Fatal(s.Serve(ln, h)) log.Fatal(s.Serve(ln, h))
} }

View File

@ -19,7 +19,8 @@ func ssuClient() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
conn, err := net.ListenUDP("udp", nil) laddr, _ := net.ResolveUDPAddr("udp", ":10800")
conn, err := net.ListenUDP("udp", laddr)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -29,13 +30,22 @@ func ssuClient() {
} }
cc := ss.NewSecurePacketConn(conn, cp, false) cc := ss.NewSecurePacketConn(conn, cp, false)
raddr, _ := net.ResolveTCPAddr("udp", ":8080") raddr, _ := net.ResolveUDPAddr("udp", ":8080")
msg := []byte(`abcdefghijklmnopqrstuvwxyz`) msg := []byte(`abcdefghijklmnopqrstuvwxyz`)
dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(0, 0, toSocksAddr(raddr)), msg) dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(0, 0, toSocksAddr(raddr)), msg)
buf := bytes.Buffer{} buf := bytes.Buffer{}
dgram.Write(&buf) dgram.Write(&buf)
if _, err := cc.WriteTo(buf.Bytes()[3:], addr); err != nil { for {
log.Fatal(err) log.Printf("%# x", buf.Bytes()[3:])
if _, err := cc.WriteTo(buf.Bytes()[3:], addr); err != nil {
log.Fatal(err)
}
b := make([]byte, 1024)
n, adr, err := cc.ReadFrom(b)
if err != nil {
log.Fatal(err)
}
log.Printf("%s: %# x", adr, b[:n])
} }
} }

View File

@ -240,7 +240,7 @@ func ShadowUDPListener(addr string, cipher *url.Userinfo, ttl time.Duration) (Li
ln.Close() ln.Close()
return nil, err return nil, err
} }
l := &udpDirectForwardListener{ l := &shadowUDPListener{
ln: ss.NewSecurePacketConn(ln, cp, false), ln: ss.NewSecurePacketConn(ln, cp, false),
conns: make(map[string]*udpServerConn), conns: make(map[string]*udpServerConn),
connChan: make(chan net.Conn, 1024), connChan: make(chan net.Conn, 1024),
@ -254,7 +254,7 @@ func ShadowUDPListener(addr string, cipher *url.Userinfo, ttl time.Duration) (Li
func (l *shadowUDPListener) listenLoop() { func (l *shadowUDPListener) listenLoop() {
for { for {
b := make([]byte, mediumBufferSize) b := make([]byte, mediumBufferSize)
n, raddr, err := l.ln.ReadFrom(b[3:]) // add rsv and frag fields to make it the standard SOCKS5 UDP datagram n, raddr, err := l.ln.ReadFrom(b)
if err != nil { if err != nil {
log.Logf("[ssu] peer -> %s : %s", l.Addr(), err) log.Logf("[ssu] peer -> %s : %s", l.Addr(), err)
l.ln.Close() l.ln.Close()
@ -266,7 +266,6 @@ func (l *shadowUDPListener) listenLoop() {
log.Logf("[ssu] %s >>> %s : length %d", raddr, l.Addr(), n) log.Logf("[ssu] %s >>> %s : length %d", raddr, l.Addr(), n)
} }
b[3] &= ss.AddrMask // remove OTA flag
conn, ok := l.conns[raddr.String()] conn, ok := l.conns[raddr.String()]
if !ok || conn.Closed() { if !ok || conn.Closed() {
conn = newUDPServerConn(l.ln, raddr, l.ttl) conn = newUDPServerConn(l.ln, raddr, l.ttl)
@ -281,7 +280,7 @@ func (l *shadowUDPListener) listenLoop() {
} }
select { select {
case conn.rChan <- b[:n+3]: // we keep the addr info so that the handler can identify the destination. case conn.rChan <- b[:n]: // we keep the addr info so that the handler can identify the destination.
default: default:
log.Logf("[ssu] %s -> %s : read queue is full", raddr, l.Addr()) log.Logf("[ssu] %s -> %s : read queue is full", raddr, l.Addr())
} }
@ -315,7 +314,7 @@ type shadowUDPdHandler struct {
// ShadowUDPdHandler creates a server Handler for shadowsocks UDP relay server. // ShadowUDPdHandler creates a server Handler for shadowsocks UDP relay server.
func ShadowUDPdHandler(opts ...HandlerOption) Handler { func ShadowUDPdHandler(opts ...HandlerOption) Handler {
h := &udpDirectForwardHandler{ h := &shadowUDPdHandler{
options: &HandlerOptions{}, options: &HandlerOptions{},
} }
for _, opt := range opts { for _, opt := range opts {
@ -332,37 +331,45 @@ func (h *shadowUDPdHandler) Handle(conn net.Conn) {
if h.options.Chain.IsEmpty() { if h.options.Chain.IsEmpty() {
cc, err = net.ListenUDP("udp", nil) cc, err = net.ListenUDP("udp", nil)
if err != nil { if err != nil {
log.Logf("[udp] %s - : %s", conn.LocalAddr(), err) log.Logf("[ssu] %s - : %s", conn.LocalAddr(), err)
return return
} }
} else { } else {
var c net.Conn var c net.Conn
c, err = getSOCKS5UDPTunnel(h.options.Chain, nil) c, err = getSOCKS5UDPTunnel(h.options.Chain, nil)
if err != nil { if err != nil {
log.Logf("[udp] %s - : %s", conn.LocalAddr(), err) log.Logf("[ssu] %s - : %s", conn.LocalAddr(), err)
return return
} }
cc = &udpTunnelConn{Conn: c} cc = &udpTunnelConn{Conn: c}
} }
defer cc.Close() defer cc.Close()
log.Logf("[udp] %s <-> %s", conn.RemoteAddr(), conn.LocalAddr()) log.Logf("[ssu] %s <-> %s", conn.RemoteAddr(), conn.LocalAddr())
transportUDP(conn, cc) transportUDP(conn, cc)
log.Logf("[udp] %s >-< %s", conn.RemoteAddr(), conn.LocalAddr()) log.Logf("[ssu] %s >-< %s", conn.RemoteAddr(), conn.LocalAddr())
} }
func transportUDP(sc net.Conn, cc net.PacketConn) error { func transportUDP(sc net.Conn, cc net.PacketConn) error {
errc := make(chan error, 1) errc := make(chan error, 1)
go func() { go func() {
for { for {
dgram, err := gosocks5.ReadUDPDatagram(sc) b := make([]byte, mediumBufferSize)
n, err := sc.Read(b[3:]) // add rsv and frag fields to make it the standard SOCKS5 UDP datagram
if err != nil { if err != nil {
// log.Logf("[ssu] %s - %s : %s", sc.RemoteAddr(), sc.LocalAddr(), err)
errc <- err errc <- err
return return
} }
if Debug { dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n+3]))
log.Logf("[ssu] %s >>> %s length: %d", sc.RemoteAddr(), dgram.Header.Addr.String(), len(dgram.Data)) if err != nil {
log.Logf("[ssu] %s - %s : %s", sc.RemoteAddr(), sc.LocalAddr(), err)
errc <- err
return
} }
//if Debug {
// log.Logf("[ssu] %s >>> %s length: %d", sc.RemoteAddr(), dgram.Header.Addr.String(), len(dgram.Data))
//}
addr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String()) addr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String())
if err != nil { if err != nil {
errc <- err errc <- err
@ -383,9 +390,9 @@ func transportUDP(sc net.Conn, cc net.PacketConn) error {
errc <- err errc <- err
return return
} }
if Debug { //if Debug {
log.Logf("[ssu] %s <<< %s length: %d", sc.RemoteAddr(), addr, n) // log.Logf("[ssu] %s <<< %s length: %d", sc.RemoteAddr(), addr, n)
} //}
dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(0, 0, toSocksAddr(addr)), b[:n]) dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(0, 0, toSocksAddr(addr)), b[:n])
buf := bytes.Buffer{} buf := bytes.Buffer{}
dgram.Write(&buf) dgram.Write(&buf)