add UDP remote port forwarding support
This commit is contained in:
parent
be68f616aa
commit
89681dd582
@ -5,6 +5,7 @@ import (
|
||||
"flag"
|
||||
"log"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/ginuerzh/gost/gost"
|
||||
)
|
||||
@ -132,13 +133,13 @@ func tcpForwardServer() {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
h := gost.TCPForwardHandler("localhost:22")
|
||||
h := gost.TCPDirectForwardHandler("localhost:22")
|
||||
log.Fatal(s.Serve(ln, h))
|
||||
}
|
||||
|
||||
func rtcpForwardServer() {
|
||||
s := &gost.Server{}
|
||||
ln, err := gost.RTCPForwardListener(
|
||||
ln, err := gost.TCPRemoteForwardListener(
|
||||
":1222",
|
||||
gost.NewChain(
|
||||
gost.Node{
|
||||
@ -156,7 +157,7 @@ func rtcpForwardServer() {
|
||||
if err != nil {
|
||||
log.Fatal()
|
||||
}
|
||||
h := gost.RTCPForwardHandler(
|
||||
h := gost.TCPRemoteForwardHandler(
|
||||
":1222",
|
||||
gost.AddrHandlerOption("127.0.0.1:22"),
|
||||
)
|
||||
@ -165,7 +166,7 @@ func rtcpForwardServer() {
|
||||
|
||||
func rudpForwardServer() {
|
||||
s := &gost.Server{}
|
||||
ln, err := gost.RUDPForwardListener(
|
||||
ln, err := gost.UDPRemoteForwardListener(
|
||||
":10053",
|
||||
gost.NewChain(
|
||||
gost.Node{
|
||||
@ -179,11 +180,12 @@ func rudpForwardServer() {
|
||||
},
|
||||
},
|
||||
),
|
||||
30*time.Second,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal()
|
||||
}
|
||||
h := gost.RUDPForwardHandler(":10053", "localhost:53")
|
||||
h := gost.UDPRemoteForwardHandler("localhost:53")
|
||||
log.Fatal(s.Serve(ln, h))
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ func tcpForward() {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
h := gost.TCPForwardHandler(
|
||||
h := gost.TCPDirectForwardHandler(
|
||||
"localhost:22",
|
||||
gost.ChainHandlerOption(chain),
|
||||
)
|
||||
|
@ -24,11 +24,11 @@ func sshRemoteForward() {
|
||||
)
|
||||
|
||||
s := &gost.Server{}
|
||||
ln, err := gost.RTCPForwardListener(":11800", chain)
|
||||
ln, err := gost.TCPRemoteForwardListener(":11800", chain)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
h := gost.RTCPForwardHandler(
|
||||
h := gost.TCPRemoteForwardHandler(
|
||||
"localhost:10000",
|
||||
)
|
||||
log.Fatal(s.Serve(ln, h))
|
||||
|
57
gost/examples/forward/udp/direct.go
Normal file
57
gost/examples/forward/udp/direct.go
Normal 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))
|
||||
}
|
@ -27,19 +27,15 @@ func init() {
|
||||
}
|
||||
}
|
||||
func main() {
|
||||
udpForwardServer()
|
||||
udpRemoteForwardServer()
|
||||
}
|
||||
|
||||
func udpForwardServer() {
|
||||
func udpRemoteForwardServer() {
|
||||
s := &gost.Server{}
|
||||
ln, err := gost.UDPForwardListener(laddr, time.Second*30)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
h := gost.UDPForwardHandler(
|
||||
faddr,
|
||||
ln, err := gost.UDPRemoteForwardListener(
|
||||
laddr,
|
||||
/*
|
||||
gost.ChainHandlerOption(gost.NewChain(gost.Node{
|
||||
gost.NewChain(gost.Node{
|
||||
Protocol: "socks5",
|
||||
Transport: "tcp",
|
||||
Addr: ":11080",
|
||||
@ -50,8 +46,15 @@ func udpForwardServer() {
|
||||
),
|
||||
Transporter: gost.TCPTransporter(),
|
||||
},
|
||||
})),
|
||||
}),
|
||||
*/
|
||||
nil,
|
||||
time.Second*30)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
h := gost.UDPRemoteForwardHandler(
|
||||
faddr,
|
||||
)
|
||||
log.Fatal(s.Serve(ln, h))
|
||||
}
|
272
gost/forward.go
272
gost/forward.go
@ -12,15 +12,15 @@ import (
|
||||
"github.com/go-log/log"
|
||||
)
|
||||
|
||||
type tcpForwardHandler struct {
|
||||
type tcpDirectForwardHandler struct {
|
||||
raddr string
|
||||
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.
|
||||
func TCPForwardHandler(raddr string, opts ...HandlerOption) Handler {
|
||||
h := &tcpForwardHandler{
|
||||
func TCPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler {
|
||||
h := &tcpDirectForwardHandler{
|
||||
raddr: raddr,
|
||||
options: &HandlerOptions{},
|
||||
}
|
||||
@ -30,7 +30,7 @@ func TCPForwardHandler(raddr string, opts ...HandlerOption) Handler {
|
||||
return h
|
||||
}
|
||||
|
||||
func (h *tcpForwardHandler) Handle(conn net.Conn) {
|
||||
func (h *tcpDirectForwardHandler) Handle(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
type udpForwardHandler struct {
|
||||
type udpDirectForwardHandler struct {
|
||||
raddr string
|
||||
ttl time.Duration
|
||||
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.
|
||||
func UDPForwardHandler(raddr string, opts ...HandlerOption) Handler {
|
||||
h := &udpForwardHandler{
|
||||
func UDPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler {
|
||||
h := &udpDirectForwardHandler{
|
||||
raddr: raddr,
|
||||
options: &HandlerOptions{},
|
||||
}
|
||||
@ -65,7 +65,7 @@ func UDPForwardHandler(raddr string, opts ...HandlerOption) Handler {
|
||||
return h
|
||||
}
|
||||
|
||||
func (h *udpForwardHandler) Handle(conn net.Conn) {
|
||||
func (h *udpDirectForwardHandler) Handle(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
var cc net.Conn
|
||||
@ -82,7 +82,7 @@ func (h *udpForwardHandler) Handle(conn net.Conn) {
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
cc, err = getSOCKS5UDPTunnel(h.options.Chain)
|
||||
cc, err = getSOCKS5UDPTunnel(h.options.Chain, nil)
|
||||
if err != nil {
|
||||
log.Logf("[udp] %s - %s : %s", conn.LocalAddr(), h.raddr, err)
|
||||
return
|
||||
@ -97,15 +97,15 @@ func (h *udpForwardHandler) Handle(conn net.Conn) {
|
||||
log.Logf("[udp] %s >-< %s", conn.RemoteAddr(), h.raddr)
|
||||
}
|
||||
|
||||
type rtcpForwardHandler struct {
|
||||
type tcpRemoteForwardHandler struct {
|
||||
raddr string
|
||||
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.
|
||||
func RTCPForwardHandler(raddr string, opts ...HandlerOption) Handler {
|
||||
h := &rtcpForwardHandler{
|
||||
func TCPRemoteForwardHandler(raddr string, opts ...HandlerOption) Handler {
|
||||
h := &tcpRemoteForwardHandler{
|
||||
raddr: raddr,
|
||||
options: &HandlerOptions{},
|
||||
}
|
||||
@ -115,7 +115,7 @@ func RTCPForwardHandler(raddr string, opts ...HandlerOption) Handler {
|
||||
return h
|
||||
}
|
||||
|
||||
func (h *rtcpForwardHandler) Handle(conn net.Conn) {
|
||||
func (h *tcpRemoteForwardHandler) Handle(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
type rudpForwardHandler struct {
|
||||
laddr string
|
||||
type udpRemoteForwardHandler struct {
|
||||
raddr string
|
||||
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.
|
||||
func RUDPForwardHandler(laddr, raddr string, opts ...HandlerOption) Handler {
|
||||
h := &rudpForwardHandler{
|
||||
laddr: laddr,
|
||||
func UDPRemoteForwardHandler(raddr string, opts ...HandlerOption) Handler {
|
||||
h := &udpRemoteForwardHandler{
|
||||
raddr: raddr,
|
||||
options: &HandlerOptions{},
|
||||
}
|
||||
@ -150,74 +148,35 @@ func RUDPForwardHandler(laddr, raddr string, opts ...HandlerOption) Handler {
|
||||
return h
|
||||
}
|
||||
|
||||
func (h *rudpForwardHandler) Handle(conn net.Conn) {
|
||||
func (h *udpRemoteForwardHandler) Handle(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
// TODO: handle connection
|
||||
|
||||
/*
|
||||
ra, err := net.ResolveUDPAddr("udp", h.raddr)
|
||||
raddr, err := net.ResolveUDPAddr("udp", h.raddr)
|
||||
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
|
||||
}
|
||||
|
||||
for {
|
||||
dgram, err := gosocks5.ReadUDPDatagram(conn)
|
||||
cc, err := net.DialUDP("udp", nil, raddr)
|
||||
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
|
||||
}
|
||||
|
||||
go func() {
|
||||
b := make([]byte, mediumBufferSize)
|
||||
|
||||
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{})
|
||||
}()
|
||||
}
|
||||
*/
|
||||
log.Logf("[rudp] %s <-> %s", conn.RemoteAddr(), h.raddr)
|
||||
transport(conn, cc)
|
||||
log.Logf("[rudp] %s >-< %s", conn.RemoteAddr(), h.raddr)
|
||||
}
|
||||
|
||||
type udpForwardListener struct {
|
||||
type udpDirectForwardListener struct {
|
||||
ln *net.UDPConn
|
||||
conns map[string]*udpServerConn
|
||||
connMutex sync.Mutex
|
||||
connChan chan net.Conn
|
||||
errChan chan error
|
||||
ttl time.Duration
|
||||
}
|
||||
|
||||
// UDPForwardListener creates a Listener for UDP port forwarding server.
|
||||
func UDPForwardListener(addr string, ttl time.Duration) (Listener, error) {
|
||||
// UDPDirectForwardListener creates a Listener for UDP port forwarding server.
|
||||
func UDPDirectForwardListener(addr string, ttl time.Duration) (Listener, error) {
|
||||
laddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -226,7 +185,7 @@ func UDPForwardListener(addr string, ttl time.Duration) (Listener, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l := &udpForwardListener{
|
||||
l := &udpDirectForwardListener{
|
||||
ln: ln,
|
||||
conns: make(map[string]*udpServerConn),
|
||||
connChan: make(chan net.Conn, 1024),
|
||||
@ -237,7 +196,7 @@ func UDPForwardListener(addr string, ttl time.Duration) (Listener, error) {
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (l *udpForwardListener) listenLoop() {
|
||||
func (l *udpDirectForwardListener) listenLoop() {
|
||||
for {
|
||||
b := make([]byte, mediumBufferSize)
|
||||
n, raddr, err := l.ln.ReadFromUDP(b)
|
||||
@ -246,6 +205,7 @@ func (l *udpForwardListener) listenLoop() {
|
||||
l.ln.Close()
|
||||
l.errChan <- err
|
||||
close(l.errChan)
|
||||
return
|
||||
}
|
||||
if Debug {
|
||||
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
|
||||
select {
|
||||
case conn = <-l.connChan:
|
||||
@ -283,17 +243,17 @@ func (l *udpForwardListener) Accept() (conn net.Conn, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (l *udpForwardListener) Addr() net.Addr {
|
||||
func (l *udpDirectForwardListener) Addr() net.Addr {
|
||||
return l.ln.LocalAddr()
|
||||
}
|
||||
|
||||
func (l *udpForwardListener) Close() error {
|
||||
func (l *udpDirectForwardListener) Close() error {
|
||||
return l.ln.Close()
|
||||
}
|
||||
|
||||
type udpServerConn struct {
|
||||
conn *net.UDPConn
|
||||
raddr *net.UDPAddr
|
||||
conn net.PacketConn
|
||||
raddr net.Addr
|
||||
rChan, wChan chan []byte
|
||||
closed chan struct{}
|
||||
brokenChan chan struct{}
|
||||
@ -302,7 +262,7 @@ type udpServerConn struct {
|
||||
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{
|
||||
conn: conn,
|
||||
raddr: raddr,
|
||||
@ -391,9 +351,9 @@ func (c *udpServerConn) writeLoop() {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
n, err := c.conn.WriteToUDP(b, c.raddr)
|
||||
n, err := c.conn.WriteTo(b, c.raddr)
|
||||
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
|
||||
}
|
||||
if Debug {
|
||||
@ -443,53 +403,27 @@ func (c *udpServerConn) SetWriteDeadline(t time.Time) error {
|
||||
return 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) 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 {
|
||||
type tcpRemoteForwardListener struct {
|
||||
addr net.Addr
|
||||
chain *Chain
|
||||
closed chan struct{}
|
||||
}
|
||||
|
||||
// RTCPForwardListener creates a Listener for TCP remote port forwarding server.
|
||||
func RTCPForwardListener(addr string, chain *Chain) (Listener, error) {
|
||||
// TCPRemoteForwardListener creates a Listener for TCP remote port forwarding server.
|
||||
func TCPRemoteForwardListener(addr string, chain *Chain) (Listener, error) {
|
||||
laddr, err := net.ResolveTCPAddr("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &rtcpForwardListener{
|
||||
return &tcpRemoteForwardListener{
|
||||
addr: laddr,
|
||||
chain: chain,
|
||||
closed: make(chan struct{}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *rtcpForwardListener) Accept() (net.Conn, error) {
|
||||
func (l *tcpRemoteForwardListener) Accept() (net.Conn, error) {
|
||||
select {
|
||||
case <-l.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()
|
||||
if lastNode.Protocol == "forward" && lastNode.Transport == "ssh" {
|
||||
conn, err = l.chain.Dial(l.addr.String())
|
||||
@ -535,7 +469,7 @@ func (l *rtcpForwardListener) accept() (conn net.Conn, err error) {
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -575,45 +509,111 @@ func (l *rtcpForwardListener) waitConnectSOCKS5(conn net.Conn) (net.Conn, error)
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (l *rtcpForwardListener) Addr() net.Addr {
|
||||
func (l *tcpRemoteForwardListener) Addr() net.Addr {
|
||||
return l.addr
|
||||
}
|
||||
|
||||
func (l *rtcpForwardListener) Close() error {
|
||||
func (l *tcpRemoteForwardListener) Close() error {
|
||||
close(l.closed)
|
||||
return nil
|
||||
}
|
||||
|
||||
type rudpForwardListener struct {
|
||||
type udpRemoteForwardListener struct {
|
||||
addr *net.UDPAddr
|
||||
chain *Chain
|
||||
conns map[string]*udpServerConn
|
||||
connChan chan net.Conn
|
||||
errChan chan error
|
||||
ttl time.Duration
|
||||
closed chan struct{}
|
||||
}
|
||||
|
||||
// RUDPForwardListener creates a Listener for UDP remote port forwarding server.
|
||||
func RUDPForwardListener(addr string, chain *Chain) (Listener, error) {
|
||||
// UDPRemoteForwardListener creates a Listener for UDP remote port forwarding server.
|
||||
func UDPRemoteForwardListener(addr string, chain *Chain, ttl time.Duration) (Listener, error) {
|
||||
laddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &rudpForwardListener{
|
||||
ln := &udpRemoteForwardListener{
|
||||
addr: laddr,
|
||||
chain: chain,
|
||||
conns: make(map[string]*udpServerConn),
|
||||
connChan: make(chan net.Conn, 1024),
|
||||
errChan: make(chan error, 1),
|
||||
ttl: ttl,
|
||||
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 {
|
||||
case <-l.closed:
|
||||
return nil, errors.New("closed")
|
||||
default:
|
||||
}
|
||||
|
||||
var tempDelay time.Duration
|
||||
for {
|
||||
conn, err := l.accept()
|
||||
lastNode := l.chain.LastNode()
|
||||
if lastNode.Protocol == "socks5" {
|
||||
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 tempDelay == 0 {
|
||||
tempDelay = 1000 * time.Millisecond
|
||||
@ -627,25 +627,27 @@ func (l *rudpForwardListener) Accept() (net.Conn, error) {
|
||||
time.Sleep(tempDelay)
|
||||
continue
|
||||
}
|
||||
return conn, nil
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (l *rudpForwardListener) accept() (conn net.Conn, err error) {
|
||||
lastNode := l.chain.LastNode()
|
||||
if lastNode.Protocol == "socks5" {
|
||||
conn, err = getSOCKS5UDPTunnel(l.chain)
|
||||
} else {
|
||||
conn, err = net.ListenUDP("udp", l.addr)
|
||||
func (l *udpRemoteForwardListener) Accept() (conn net.Conn, err error) {
|
||||
var ok bool
|
||||
select {
|
||||
case conn = <-l.connChan:
|
||||
case err, ok = <-l.errChan:
|
||||
if !ok {
|
||||
err = errors.New("accpet on closed listener")
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (l *rudpForwardListener) Addr() net.Addr {
|
||||
func (l *udpRemoteForwardListener) Addr() net.Addr {
|
||||
return l.addr
|
||||
}
|
||||
|
||||
func (l *rudpForwardListener) Close() error {
|
||||
func (l *udpRemoteForwardListener) Close() error {
|
||||
close(l.closed)
|
||||
return nil
|
||||
}
|
||||
|
@ -747,7 +747,7 @@ func (h *socks5Handler) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error
|
||||
var clientAddr *net.UDPAddr
|
||||
|
||||
go func() {
|
||||
b := make([]byte, largeBufferSize)
|
||||
b := make([]byte, mediumBufferSize)
|
||||
|
||||
for {
|
||||
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)
|
||||
|
||||
go func() {
|
||||
b := make([]byte, largeBufferSize)
|
||||
b := make([]byte, mediumBufferSize)
|
||||
|
||||
for {
|
||||
n, addr, err := uc.ReadFromUDP(b)
|
||||
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
|
||||
return
|
||||
}
|
||||
@ -904,7 +904,7 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error
|
||||
for {
|
||||
dgram, err := gosocks5.ReadUDPDatagram(cc)
|
||||
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
|
||||
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())
|
||||
}
|
||||
|
||||
func getSOCKS5UDPTunnel(chain *Chain) (net.Conn, error) {
|
||||
func getSOCKS5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
|
||||
conn, err := chain.Conn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -1070,10 +1070,14 @@ func getSOCKS5UDPTunnel(chain *Chain) (net.Conn, error) {
|
||||
conn = cc
|
||||
|
||||
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()
|
||||
return nil, err
|
||||
}
|
||||
if Debug {
|
||||
log.Log("[socks5]", req)
|
||||
}
|
||||
conn.SetWriteDeadline(time.Time{})
|
||||
|
||||
conn.SetReadDeadline(time.Now().Add(ReadTimeout))
|
||||
@ -1083,6 +1087,9 @@ func getSOCKS5UDPTunnel(chain *Chain) (net.Conn, error) {
|
||||
return nil, err
|
||||
}
|
||||
conn.SetReadDeadline(time.Time{})
|
||||
if Debug {
|
||||
log.Log("[socks5]", reply)
|
||||
}
|
||||
|
||||
if reply.Rep != gosocks5.Succeeded {
|
||||
conn.Close()
|
||||
@ -1107,3 +1114,47 @@ func socks5Handshake(conn net.Conn, user *url.Userinfo) (net.Conn, error) {
|
||||
}
|
||||
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
|
||||
}
|
||||
|
9
vendor/github.com/ginuerzh/gosocks5/socks5.go
generated
vendored
9
vendor/github.com/ginuerzh/gosocks5/socks5.go
generated
vendored
@ -4,6 +4,7 @@
|
||||
package gosocks5
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -658,10 +659,14 @@ func (d *UDPDatagram) Write(w io.Writer) error {
|
||||
if h == nil {
|
||||
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
|
||||
}
|
||||
_, err := w.Write(d.Data)
|
||||
|
||||
_, err := buf.WriteTo(w)
|
||||
return err
|
||||
}
|
||||
|
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
@ -15,10 +15,10 @@
|
||||
"revisionTime": "2017-02-09T14:09:51Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "5TwW96Afcvo+zm0tAn+DSNIQreQ=",
|
||||
"checksumSHA1": "4JEexBJToQeQm7fAo2PHVdCU3zM=",
|
||||
"path": "github.com/ginuerzh/gosocks5",
|
||||
"revision": "0f737bddba2abd1496dc03c8b39b817cc5f33fa7",
|
||||
"revisionTime": "2017-01-19T05:34:58Z"
|
||||
"revision": "cb895c2f7a2cdceaf74ac6497f709b71a999168a",
|
||||
"revisionTime": "2017-08-01T04:47:37Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "9e9tjPDTESeCEdUMElph250lurs=",
|
||||
|
Loading…
Reference in New Issue
Block a user