add UDP remote port forwarding support

This commit is contained in:
rui.zheng 2017-08-01 14:13:02 +08:00
parent be68f616aa
commit 89681dd582
9 changed files with 303 additions and 183 deletions

View File

@ -5,6 +5,7 @@ import (
"flag" "flag"
"log" "log"
"net/url" "net/url"
"time"
"github.com/ginuerzh/gost/gost" "github.com/ginuerzh/gost/gost"
) )
@ -132,13 +133,13 @@ func tcpForwardServer() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
h := gost.TCPForwardHandler("localhost:22") h := gost.TCPDirectForwardHandler("localhost:22")
log.Fatal(s.Serve(ln, h)) log.Fatal(s.Serve(ln, h))
} }
func rtcpForwardServer() { func rtcpForwardServer() {
s := &gost.Server{} s := &gost.Server{}
ln, err := gost.RTCPForwardListener( ln, err := gost.TCPRemoteForwardListener(
":1222", ":1222",
gost.NewChain( gost.NewChain(
gost.Node{ gost.Node{
@ -156,7 +157,7 @@ func rtcpForwardServer() {
if err != nil { if err != nil {
log.Fatal() log.Fatal()
} }
h := gost.RTCPForwardHandler( h := gost.TCPRemoteForwardHandler(
":1222", ":1222",
gost.AddrHandlerOption("127.0.0.1:22"), gost.AddrHandlerOption("127.0.0.1:22"),
) )
@ -165,7 +166,7 @@ func rtcpForwardServer() {
func rudpForwardServer() { func rudpForwardServer() {
s := &gost.Server{} s := &gost.Server{}
ln, err := gost.RUDPForwardListener( ln, err := gost.UDPRemoteForwardListener(
":10053", ":10053",
gost.NewChain( gost.NewChain(
gost.Node{ gost.Node{
@ -179,11 +180,12 @@ func rudpForwardServer() {
}, },
}, },
), ),
30*time.Second,
) )
if err != nil { if err != nil {
log.Fatal() log.Fatal()
} }
h := gost.RUDPForwardHandler(":10053", "localhost:53") h := gost.UDPRemoteForwardHandler("localhost:53")
log.Fatal(s.Serve(ln, h)) log.Fatal(s.Serve(ln, h))
} }

View File

@ -26,7 +26,7 @@ func tcpForward() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
h := gost.TCPForwardHandler( h := gost.TCPDirectForwardHandler(
"localhost:22", "localhost:22",
gost.ChainHandlerOption(chain), gost.ChainHandlerOption(chain),
) )

View File

@ -24,11 +24,11 @@ func sshRemoteForward() {
) )
s := &gost.Server{} s := &gost.Server{}
ln, err := gost.RTCPForwardListener(":11800", chain) ln, err := gost.TCPRemoteForwardListener(":11800", chain)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
h := gost.RTCPForwardHandler( h := gost.TCPRemoteForwardHandler(
"localhost:10000", "localhost:10000",
) )
log.Fatal(s.Serve(ln, h)) log.Fatal(s.Serve(ln, h))

View File

@ -0,0 +1,57 @@
package main
import (
"flag"
"log"
"time"
"github.com/ginuerzh/gost/gost"
)
var (
laddr, faddr string
quiet bool
)
func init() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
flag.StringVar(&laddr, "L", ":18080", "listen address")
flag.StringVar(&faddr, "F", ":8080", "forward address")
flag.BoolVar(&quiet, "q", false, "quiet mode")
flag.BoolVar(&gost.Debug, "d", false, "debug mode")
flag.Parse()
if quiet {
gost.SetLogger(&gost.NopLogger{})
}
}
func main() {
udpDirectForwardServer()
}
func udpDirectForwardServer() {
s := &gost.Server{}
ln, err := gost.UDPDirectForwardListener(laddr, time.Second*30)
if err != nil {
log.Fatal(err)
}
h := gost.UDPDirectForwardHandler(
faddr,
/*
gost.ChainHandlerOption(gost.NewChain(gost.Node{
Protocol: "socks5",
Transport: "tcp",
Addr: ":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))
}

View File

@ -27,19 +27,15 @@ func init() {
} }
} }
func main() { func main() {
udpForwardServer() udpRemoteForwardServer()
} }
func udpForwardServer() { func udpRemoteForwardServer() {
s := &gost.Server{} s := &gost.Server{}
ln, err := gost.UDPForwardListener(laddr, time.Second*30) ln, err := gost.UDPRemoteForwardListener(
if err != nil { laddr,
log.Fatal(err)
}
h := gost.UDPForwardHandler(
faddr,
/* /*
gost.ChainHandlerOption(gost.NewChain(gost.Node{ gost.NewChain(gost.Node{
Protocol: "socks5", Protocol: "socks5",
Transport: "tcp", Transport: "tcp",
Addr: ":11080", Addr: ":11080",
@ -50,8 +46,15 @@ func udpForwardServer() {
), ),
Transporter: gost.TCPTransporter(), Transporter: gost.TCPTransporter(),
}, },
})), }),
*/ */
nil,
time.Second*30)
if err != nil {
log.Fatal(err)
}
h := gost.UDPRemoteForwardHandler(
faddr,
) )
log.Fatal(s.Serve(ln, h)) log.Fatal(s.Serve(ln, h))
} }

View File

@ -12,15 +12,15 @@ import (
"github.com/go-log/log" "github.com/go-log/log"
) )
type tcpForwardHandler struct { type tcpDirectForwardHandler struct {
raddr string raddr string
options *HandlerOptions options *HandlerOptions
} }
// TCPForwardHandler creates a server Handler for TCP port forwarding server. // TCPDirectForwardHandler creates a server Handler for TCP port forwarding server.
// The raddr is the remote address that the server will forward to. // The raddr is the remote address that the server will forward to.
func TCPForwardHandler(raddr string, opts ...HandlerOption) Handler { func TCPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler {
h := &tcpForwardHandler{ h := &tcpDirectForwardHandler{
raddr: raddr, raddr: raddr,
options: &HandlerOptions{}, options: &HandlerOptions{},
} }
@ -30,7 +30,7 @@ func TCPForwardHandler(raddr string, opts ...HandlerOption) Handler {
return h return h
} }
func (h *tcpForwardHandler) Handle(conn net.Conn) { func (h *tcpDirectForwardHandler) Handle(conn net.Conn) {
defer conn.Close() defer conn.Close()
log.Logf("[tcp] %s - %s", conn.RemoteAddr(), h.raddr) log.Logf("[tcp] %s - %s", conn.RemoteAddr(), h.raddr)
@ -46,16 +46,16 @@ func (h *tcpForwardHandler) Handle(conn net.Conn) {
log.Logf("[tcp] %s >-< %s", conn.RemoteAddr(), h.raddr) log.Logf("[tcp] %s >-< %s", conn.RemoteAddr(), h.raddr)
} }
type udpForwardHandler struct { type udpDirectForwardHandler struct {
raddr string raddr string
ttl time.Duration ttl time.Duration
options *HandlerOptions options *HandlerOptions
} }
// UDPForwardHandler creates a server Handler for UDP port forwarding server. // UDPDirectForwardHandler creates a server Handler for UDP port forwarding server.
// The raddr is the remote address that the server will forward to. // The raddr is the remote address that the server will forward to.
func UDPForwardHandler(raddr string, opts ...HandlerOption) Handler { func UDPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler {
h := &udpForwardHandler{ h := &udpDirectForwardHandler{
raddr: raddr, raddr: raddr,
options: &HandlerOptions{}, options: &HandlerOptions{},
} }
@ -65,7 +65,7 @@ func UDPForwardHandler(raddr string, opts ...HandlerOption) Handler {
return h return h
} }
func (h *udpForwardHandler) Handle(conn net.Conn) { func (h *udpDirectForwardHandler) Handle(conn net.Conn) {
defer conn.Close() defer conn.Close()
var cc net.Conn var cc net.Conn
@ -82,7 +82,7 @@ func (h *udpForwardHandler) Handle(conn net.Conn) {
} }
} else { } else {
var err error var err error
cc, err = getSOCKS5UDPTunnel(h.options.Chain) cc, err = getSOCKS5UDPTunnel(h.options.Chain, nil)
if err != nil { if err != nil {
log.Logf("[udp] %s - %s : %s", conn.LocalAddr(), h.raddr, err) log.Logf("[udp] %s - %s : %s", conn.LocalAddr(), h.raddr, err)
return return
@ -97,15 +97,15 @@ func (h *udpForwardHandler) Handle(conn net.Conn) {
log.Logf("[udp] %s >-< %s", conn.RemoteAddr(), h.raddr) log.Logf("[udp] %s >-< %s", conn.RemoteAddr(), h.raddr)
} }
type rtcpForwardHandler struct { type tcpRemoteForwardHandler struct {
raddr string raddr string
options *HandlerOptions options *HandlerOptions
} }
// RTCPForwardHandler creates a server Handler for TCP remote port forwarding server. // TCPRemoteForwardHandler creates a server Handler for TCP remote port forwarding server.
// The raddr is the remote address that the server will forward to. // The raddr is the remote address that the server will forward to.
func RTCPForwardHandler(raddr string, opts ...HandlerOption) Handler { func TCPRemoteForwardHandler(raddr string, opts ...HandlerOption) Handler {
h := &rtcpForwardHandler{ h := &tcpRemoteForwardHandler{
raddr: raddr, raddr: raddr,
options: &HandlerOptions{}, options: &HandlerOptions{},
} }
@ -115,7 +115,7 @@ func RTCPForwardHandler(raddr string, opts ...HandlerOption) Handler {
return h return h
} }
func (h *rtcpForwardHandler) Handle(conn net.Conn) { func (h *tcpRemoteForwardHandler) Handle(conn net.Conn) {
defer conn.Close() defer conn.Close()
cc, err := net.DialTimeout("tcp", h.raddr, DialTimeout) cc, err := net.DialTimeout("tcp", h.raddr, DialTimeout)
@ -130,17 +130,15 @@ func (h *rtcpForwardHandler) Handle(conn net.Conn) {
log.Logf("[rtcp] %s >-< %s", conn.LocalAddr(), h.raddr) log.Logf("[rtcp] %s >-< %s", conn.LocalAddr(), h.raddr)
} }
type rudpForwardHandler struct { type udpRemoteForwardHandler struct {
laddr string
raddr string raddr string
options *HandlerOptions options *HandlerOptions
} }
// RUDPForwardHandler creates a server Handler for UDP remote port forwarding server. // UDPRemoteForwardHandler creates a server Handler for UDP remote port forwarding server.
// The raddr is the remote address that the server will forward to. // The raddr is the remote address that the server will forward to.
func RUDPForwardHandler(laddr, raddr string, opts ...HandlerOption) Handler { func UDPRemoteForwardHandler(raddr string, opts ...HandlerOption) Handler {
h := &rudpForwardHandler{ h := &udpRemoteForwardHandler{
laddr: laddr,
raddr: raddr, raddr: raddr,
options: &HandlerOptions{}, options: &HandlerOptions{},
} }
@ -150,74 +148,35 @@ func RUDPForwardHandler(laddr, raddr string, opts ...HandlerOption) Handler {
return h return h
} }
func (h *rudpForwardHandler) Handle(conn net.Conn) { func (h *udpRemoteForwardHandler) Handle(conn net.Conn) {
defer conn.Close() defer conn.Close()
// TODO: handle connection raddr, err := net.ResolveUDPAddr("udp", h.raddr)
/*
ra, err := net.ResolveUDPAddr("udp", h.raddr)
if err != nil { if err != nil {
log.Logf("[rudp] %s - %s : %s", h.laddr, h.raddr, err) log.Logf("[rudp] %s - %s : %s", conn.RemoteAddr(), h.raddr, err)
return return
} }
cc, err := net.DialUDP("udp", nil, raddr)
for {
dgram, err := gosocks5.ReadUDPDatagram(conn)
if err != nil { if err != nil {
log.Logf("[rudp] %s -> %s : %s", h.laddr, h.raddr, err) log.Logf("[rudp] %s - %s : %s", conn.RemoteAddr(), h.raddr, err)
return return
} }
go func() { log.Logf("[rudp] %s <-> %s", conn.RemoteAddr(), h.raddr)
b := make([]byte, mediumBufferSize) transport(conn, cc)
log.Logf("[rudp] %s >-< %s", conn.RemoteAddr(), h.raddr)
relay, err := net.DialUDP("udp", nil, ra)
if err != nil {
log.Logf("[rudp] %s -> %s : %s", h.laddr, h.raddr, err)
return
}
defer relay.Close()
if _, err := relay.Write(dgram.Data); err != nil {
log.Logf("[rudp] %s -> %s : %s", h.laddr, h.raddr, err)
return
}
if Debug {
log.Logf("[rudp] %s >>> %s length: %d", h.laddr, h.raddr, len(dgram.Data))
}
relay.SetReadDeadline(time.Now().Add(ReadTimeout))
n, err := relay.Read(b)
if err != nil {
log.Logf("[rudp] %s <- %s : %s", h.laddr, h.raddr, err)
return
}
relay.SetReadDeadline(time.Time{})
if Debug {
log.Logf("[rudp] %s <<< %s length: %d", h.laddr, h.raddr, n)
}
conn.SetWriteDeadline(time.Now().Add(WriteTimeout))
if err := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(n), 0, dgram.Header.Addr), b[:n]).Write(conn); err != nil {
log.Logf("[rudp] %s <- %s : %s", h.laddr, h.raddr, err)
return
}
conn.SetWriteDeadline(time.Time{})
}()
}
*/
} }
type udpForwardListener struct { type udpDirectForwardListener struct {
ln *net.UDPConn ln *net.UDPConn
conns map[string]*udpServerConn conns map[string]*udpServerConn
connMutex sync.Mutex
connChan chan net.Conn connChan chan net.Conn
errChan chan error errChan chan error
ttl time.Duration ttl time.Duration
} }
// UDPForwardListener creates a Listener for UDP port forwarding server. // UDPDirectForwardListener creates a Listener for UDP port forwarding server.
func UDPForwardListener(addr string, ttl time.Duration) (Listener, error) { func UDPDirectForwardListener(addr string, ttl time.Duration) (Listener, error) {
laddr, err := net.ResolveUDPAddr("udp", addr) laddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil { if err != nil {
return nil, err return nil, err
@ -226,7 +185,7 @@ func UDPForwardListener(addr string, ttl time.Duration) (Listener, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
l := &udpForwardListener{ l := &udpDirectForwardListener{
ln: ln, ln: ln,
conns: make(map[string]*udpServerConn), conns: make(map[string]*udpServerConn),
connChan: make(chan net.Conn, 1024), connChan: make(chan net.Conn, 1024),
@ -237,7 +196,7 @@ func UDPForwardListener(addr string, ttl time.Duration) (Listener, error) {
return l, nil return l, nil
} }
func (l *udpForwardListener) listenLoop() { func (l *udpDirectForwardListener) listenLoop() {
for { for {
b := make([]byte, mediumBufferSize) b := make([]byte, mediumBufferSize)
n, raddr, err := l.ln.ReadFromUDP(b) n, raddr, err := l.ln.ReadFromUDP(b)
@ -246,6 +205,7 @@ func (l *udpForwardListener) listenLoop() {
l.ln.Close() l.ln.Close()
l.errChan <- err l.errChan <- err
close(l.errChan) close(l.errChan)
return
} }
if Debug { if Debug {
log.Logf("[udp] %s >>> %s : length %d", raddr, l.Addr(), n) log.Logf("[udp] %s >>> %s : length %d", raddr, l.Addr(), n)
@ -271,7 +231,7 @@ func (l *udpForwardListener) listenLoop() {
} }
} }
func (l *udpForwardListener) Accept() (conn net.Conn, err error) { func (l *udpDirectForwardListener) Accept() (conn net.Conn, err error) {
var ok bool var ok bool
select { select {
case conn = <-l.connChan: case conn = <-l.connChan:
@ -283,17 +243,17 @@ func (l *udpForwardListener) Accept() (conn net.Conn, err error) {
return return
} }
func (l *udpForwardListener) Addr() net.Addr { func (l *udpDirectForwardListener) Addr() net.Addr {
return l.ln.LocalAddr() return l.ln.LocalAddr()
} }
func (l *udpForwardListener) Close() error { func (l *udpDirectForwardListener) Close() error {
return l.ln.Close() return l.ln.Close()
} }
type udpServerConn struct { type udpServerConn struct {
conn *net.UDPConn conn net.PacketConn
raddr *net.UDPAddr raddr net.Addr
rChan, wChan chan []byte rChan, wChan chan []byte
closed chan struct{} closed chan struct{}
brokenChan chan struct{} brokenChan chan struct{}
@ -302,7 +262,7 @@ type udpServerConn struct {
nopChan chan int nopChan chan int
} }
func newUDPServerConn(conn *net.UDPConn, raddr *net.UDPAddr, ttl time.Duration) *udpServerConn { func newUDPServerConn(conn net.PacketConn, raddr net.Addr, ttl time.Duration) *udpServerConn {
c := &udpServerConn{ c := &udpServerConn{
conn: conn, conn: conn,
raddr: raddr, raddr: raddr,
@ -391,9 +351,9 @@ func (c *udpServerConn) writeLoop() {
if !ok { if !ok {
return return
} }
n, err := c.conn.WriteToUDP(b, c.raddr) n, err := c.conn.WriteTo(b, c.raddr)
if err != nil { if err != nil {
log.Logf("[udp] %s <<< %s : %s", c.RemoteAddr(), c.LocalAddr(), err) log.Logf("[udp] %s - %s : %s", c.RemoteAddr(), c.LocalAddr(), err)
return return
} }
if Debug { if Debug {
@ -443,53 +403,27 @@ func (c *udpServerConn) SetWriteDeadline(t time.Time) error {
return nil return nil
} }
type udpTunnelConn struct { type tcpRemoteForwardListener struct {
raddr string
net.Conn
}
func (c *udpTunnelConn) Read(b []byte) (n int, err error) {
dgram, err := gosocks5.ReadUDPDatagram(c.Conn)
if err != nil {
return
}
n = copy(b, dgram.Data)
return
}
func (c *udpTunnelConn) Write(b []byte) (n int, err error) {
addr, err := net.ResolveUDPAddr("udp", c.raddr)
if err != nil {
return
}
dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(len(b)), 0, toSocksAddr(addr)), b)
if err = dgram.Write(c.Conn); err != nil {
return
}
return len(b), nil
}
type rtcpForwardListener struct {
addr net.Addr addr net.Addr
chain *Chain chain *Chain
closed chan struct{} closed chan struct{}
} }
// RTCPForwardListener creates a Listener for TCP remote port forwarding server. // TCPRemoteForwardListener creates a Listener for TCP remote port forwarding server.
func RTCPForwardListener(addr string, chain *Chain) (Listener, error) { func TCPRemoteForwardListener(addr string, chain *Chain) (Listener, error) {
laddr, err := net.ResolveTCPAddr("tcp", addr) laddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &rtcpForwardListener{ return &tcpRemoteForwardListener{
addr: laddr, addr: laddr,
chain: chain, chain: chain,
closed: make(chan struct{}), closed: make(chan struct{}),
}, nil }, nil
} }
func (l *rtcpForwardListener) Accept() (net.Conn, error) { func (l *tcpRemoteForwardListener) Accept() (net.Conn, error) {
select { select {
case <-l.closed: case <-l.closed:
return nil, errors.New("closed") return nil, errors.New("closed")
@ -516,7 +450,7 @@ func (l *rtcpForwardListener) Accept() (net.Conn, error) {
} }
} }
func (l *rtcpForwardListener) accept() (conn net.Conn, err error) { func (l *tcpRemoteForwardListener) accept() (conn net.Conn, err error) {
lastNode := l.chain.LastNode() lastNode := l.chain.LastNode()
if lastNode.Protocol == "forward" && lastNode.Transport == "ssh" { if lastNode.Protocol == "forward" && lastNode.Transport == "ssh" {
conn, err = l.chain.Dial(l.addr.String()) conn, err = l.chain.Dial(l.addr.String())
@ -535,7 +469,7 @@ func (l *rtcpForwardListener) accept() (conn net.Conn, err error) {
return return
} }
func (l *rtcpForwardListener) waitConnectSOCKS5(conn net.Conn) (net.Conn, error) { func (l *tcpRemoteForwardListener) waitConnectSOCKS5(conn net.Conn) (net.Conn, error) {
conn, err := socks5Handshake(conn, l.chain.LastNode().User) conn, err := socks5Handshake(conn, l.chain.LastNode().User)
if err != nil { if err != nil {
return nil, err return nil, err
@ -575,45 +509,111 @@ func (l *rtcpForwardListener) waitConnectSOCKS5(conn net.Conn) (net.Conn, error)
return conn, nil return conn, nil
} }
func (l *rtcpForwardListener) Addr() net.Addr { func (l *tcpRemoteForwardListener) Addr() net.Addr {
return l.addr return l.addr
} }
func (l *rtcpForwardListener) Close() error { func (l *tcpRemoteForwardListener) Close() error {
close(l.closed) close(l.closed)
return nil return nil
} }
type rudpForwardListener struct { type udpRemoteForwardListener struct {
addr *net.UDPAddr addr *net.UDPAddr
chain *Chain chain *Chain
conns map[string]*udpServerConn
connChan chan net.Conn
errChan chan error
ttl time.Duration
closed chan struct{} closed chan struct{}
} }
// RUDPForwardListener creates a Listener for UDP remote port forwarding server. // UDPRemoteForwardListener creates a Listener for UDP remote port forwarding server.
func RUDPForwardListener(addr string, chain *Chain) (Listener, error) { func UDPRemoteForwardListener(addr string, chain *Chain, ttl time.Duration) (Listener, error) {
laddr, err := net.ResolveUDPAddr("udp", addr) laddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &rudpForwardListener{ ln := &udpRemoteForwardListener{
addr: laddr, addr: laddr,
chain: chain, chain: chain,
conns: make(map[string]*udpServerConn),
connChan: make(chan net.Conn, 1024),
errChan: make(chan error, 1),
ttl: ttl,
closed: make(chan struct{}), closed: make(chan struct{}),
}, nil }
go ln.listenLoop()
return ln, nil
} }
func (l *rudpForwardListener) Accept() (net.Conn, error) { func (l *udpRemoteForwardListener) listenLoop() {
for {
conn, err := l.connect()
if err != nil {
log.Logf("[rudp] %s : %s", l.Addr(), err)
return
}
defer conn.Close()
for {
b := make([]byte, mediumBufferSize)
n, raddr, err := conn.ReadFrom(b)
if err != nil {
log.Logf("[rudp] %s : %s", l.Addr(), err)
break
}
if Debug {
log.Logf("[udp] %s >>> %s : length %d", raddr, l.Addr(), n)
}
uc, ok := l.conns[raddr.String()]
if !ok || uc.Closed() {
uc = newUDPServerConn(conn, raddr, l.ttl)
l.conns[raddr.String()] = uc
select {
case l.connChan <- uc:
default:
uc.Close()
log.Logf("[rudp] %s - %s: connection queue is full", raddr, l.Addr())
}
}
select {
case uc.rChan <- b[:n]:
default:
log.Logf("[rudp] %s -> %s : write queue is full", raddr, l.Addr())
}
}
}
}
func (l *udpRemoteForwardListener) connect() (conn net.PacketConn, err error) {
var tempDelay time.Duration
for {
select { select {
case <-l.closed: case <-l.closed:
return nil, errors.New("closed") return nil, errors.New("closed")
default: default:
} }
var tempDelay time.Duration lastNode := l.chain.LastNode()
for { if lastNode.Protocol == "socks5" {
conn, err := l.accept() var cc net.Conn
cc, err = getSOCKS5UDPTunnel(l.chain, l.addr)
if err != nil {
log.Logf("[rudp] %s : %s", l.Addr(), err)
} else {
conn = &udpTunnelConn{Conn: cc}
}
} else {
conn, err = net.ListenUDP("udp", l.addr)
}
if err != nil { if err != nil {
if tempDelay == 0 { if tempDelay == 0 {
tempDelay = 1000 * time.Millisecond tempDelay = 1000 * time.Millisecond
@ -627,25 +627,27 @@ func (l *rudpForwardListener) Accept() (net.Conn, error) {
time.Sleep(tempDelay) time.Sleep(tempDelay)
continue continue
} }
return conn, nil return
} }
} }
func (l *rudpForwardListener) accept() (conn net.Conn, err error) { func (l *udpRemoteForwardListener) Accept() (conn net.Conn, err error) {
lastNode := l.chain.LastNode() var ok bool
if lastNode.Protocol == "socks5" { select {
conn, err = getSOCKS5UDPTunnel(l.chain) case conn = <-l.connChan:
} else { case err, ok = <-l.errChan:
conn, err = net.ListenUDP("udp", l.addr) if !ok {
err = errors.New("accpet on closed listener")
}
} }
return return
} }
func (l *rudpForwardListener) Addr() net.Addr { func (l *udpRemoteForwardListener) Addr() net.Addr {
return l.addr return l.addr
} }
func (l *rudpForwardListener) Close() error { func (l *udpRemoteForwardListener) Close() error {
close(l.closed) close(l.closed)
return nil return nil
} }

View File

@ -747,7 +747,7 @@ func (h *socks5Handler) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error
var clientAddr *net.UDPAddr var clientAddr *net.UDPAddr
go func() { go func() {
b := make([]byte, largeBufferSize) b := make([]byte, mediumBufferSize)
for { for {
n, addr, err := uc.ReadFromUDP(b) n, addr, err := uc.ReadFromUDP(b)
@ -876,12 +876,12 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error
errc := make(chan error, 2) errc := make(chan error, 2)
go func() { go func() {
b := make([]byte, largeBufferSize) b := make([]byte, mediumBufferSize)
for { for {
n, addr, err := uc.ReadFromUDP(b) n, addr, err := uc.ReadFromUDP(b)
if err != nil { if err != nil {
// log.Logf("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), addr, err) log.Logf("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), addr, err)
errc <- err errc <- err
return return
} }
@ -904,7 +904,7 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error
for { for {
dgram, err := gosocks5.ReadUDPDatagram(cc) dgram, err := gosocks5.ReadUDPDatagram(cc)
if err != nil { if err != nil {
// log.Logf("[udp-tun] %s -> 0 : %s", cc.RemoteAddr(), err) log.Logf("[udp-tun] %s -> 0 : %s", cc.RemoteAddr(), err)
errc <- err errc <- err
return return
} }
@ -1057,7 +1057,7 @@ func (h *socks4Handler) handleBind(conn net.Conn, req *gosocks4.Request) {
log.Logf("[socks4-bind] %s >-< %s", conn.RemoteAddr(), cc.RemoteAddr()) log.Logf("[socks4-bind] %s >-< %s", conn.RemoteAddr(), cc.RemoteAddr())
} }
func getSOCKS5UDPTunnel(chain *Chain) (net.Conn, error) { func getSOCKS5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
conn, err := chain.Conn() conn, err := chain.Conn()
if err != nil { if err != nil {
return nil, err return nil, err
@ -1070,10 +1070,14 @@ func getSOCKS5UDPTunnel(chain *Chain) (net.Conn, error) {
conn = cc conn = cc
conn.SetWriteDeadline(time.Now().Add(WriteTimeout)) conn.SetWriteDeadline(time.Now().Add(WriteTimeout))
if err = gosocks5.NewRequest(CmdUDPTun, nil).Write(conn); err != nil { req := gosocks5.NewRequest(CmdUDPTun, toSocksAddr(addr))
if err := req.Write(conn); err != nil {
conn.Close() conn.Close()
return nil, err return nil, err
} }
if Debug {
log.Log("[socks5]", req)
}
conn.SetWriteDeadline(time.Time{}) conn.SetWriteDeadline(time.Time{})
conn.SetReadDeadline(time.Now().Add(ReadTimeout)) conn.SetReadDeadline(time.Now().Add(ReadTimeout))
@ -1083,6 +1087,9 @@ func getSOCKS5UDPTunnel(chain *Chain) (net.Conn, error) {
return nil, err return nil, err
} }
conn.SetReadDeadline(time.Time{}) conn.SetReadDeadline(time.Time{})
if Debug {
log.Log("[socks5]", reply)
}
if reply.Rep != gosocks5.Succeeded { if reply.Rep != gosocks5.Succeeded {
conn.Close() conn.Close()
@ -1107,3 +1114,47 @@ func socks5Handshake(conn net.Conn, user *url.Userinfo) (net.Conn, error) {
} }
return cc, nil return cc, nil
} }
type udpTunnelConn struct {
raddr string
net.Conn
}
func (c *udpTunnelConn) Read(b []byte) (n int, err error) {
dgram, err := gosocks5.ReadUDPDatagram(c.Conn)
if err != nil {
return
}
n = copy(b, dgram.Data)
return
}
func (c *udpTunnelConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
dgram, err := gosocks5.ReadUDPDatagram(c.Conn)
if err != nil {
return
}
n = copy(b, dgram.Data)
addr, err = net.ResolveUDPAddr("udp", dgram.Header.Addr.String())
return
}
func (c *udpTunnelConn) Write(b []byte) (n int, err error) {
addr, err := net.ResolveUDPAddr("udp", c.raddr)
if err != nil {
return
}
dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(len(b)), 0, toSocksAddr(addr)), b)
if err = dgram.Write(c.Conn); err != nil {
return
}
return len(b), nil
}
func (c *udpTunnelConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(len(b)), 0, toSocksAddr(addr)), b)
if err = dgram.Write(c.Conn); err != nil {
return
}
return len(b), nil
}

View File

@ -4,6 +4,7 @@
package gosocks5 package gosocks5
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
@ -658,10 +659,14 @@ func (d *UDPDatagram) Write(w io.Writer) error {
if h == nil { if h == nil {
h = &UDPHeader{} h = &UDPHeader{}
} }
if err := h.Write(w); err != nil { buf := bytes.Buffer{}
if err := h.Write(&buf); err != nil {
return err
}
if _, err := buf.Write(d.Data); err != nil {
return err return err
} }
_, err := w.Write(d.Data)
_, err := buf.WriteTo(w)
return err return err
} }

6
vendor/vendor.json vendored
View File

@ -15,10 +15,10 @@
"revisionTime": "2017-02-09T14:09:51Z" "revisionTime": "2017-02-09T14:09:51Z"
}, },
{ {
"checksumSHA1": "5TwW96Afcvo+zm0tAn+DSNIQreQ=", "checksumSHA1": "4JEexBJToQeQm7fAo2PHVdCU3zM=",
"path": "github.com/ginuerzh/gosocks5", "path": "github.com/ginuerzh/gosocks5",
"revision": "0f737bddba2abd1496dc03c8b39b817cc5f33fa7", "revision": "cb895c2f7a2cdceaf74ac6497f709b71a999168a",
"revisionTime": "2017-01-19T05:34:58Z" "revisionTime": "2017-08-01T04:47:37Z"
}, },
{ {
"checksumSHA1": "9e9tjPDTESeCEdUMElph250lurs=", "checksumSHA1": "9e9tjPDTESeCEdUMElph250lurs=",