add remote tcp port forwarding
This commit is contained in:
parent
a8bd16715f
commit
28089dfbc6
@ -55,7 +55,7 @@ scheme://[bind_address]:port/[host]:hostport
|
|||||||
|
|
||||||
> bind_address:port - 本地监听地址
|
> bind_address:port - 本地监听地址
|
||||||
|
|
||||||
> host:hostport - 远程监听地址
|
> host:hostport - 远程地址
|
||||||
|
|
||||||
当在bind_address:port上收到连接信息,则会(通过转发链)与host:hostport建立连接,创建一条数据通道。
|
当在bind_address:port上收到连接信息,则会(通过转发链)与host:hostport建立连接,创建一条数据通道。
|
||||||
|
|
||||||
|
73
conn.go
73
conn.go
@ -52,10 +52,12 @@ func listenAndServe(arg Args) error {
|
|||||||
case "tls": // tls connection
|
case "tls": // tls connection
|
||||||
ln, err = tls.Listen("tcp", arg.Addr,
|
ln, err = tls.Listen("tcp", arg.Addr,
|
||||||
&tls.Config{Certificates: []tls.Certificate{arg.Cert}})
|
&tls.Config{Certificates: []tls.Certificate{arg.Cert}})
|
||||||
case "tcp": // TCP port forwarding
|
case "tcp": // Local TCP port forwarding
|
||||||
return listenAndServeTcpForward(arg)
|
return listenAndServeTcpForward(arg)
|
||||||
case "udp": // UDP port forwarding
|
case "udp": // Local UDP port forwarding
|
||||||
return listenAndServeUdpForward(arg)
|
return listenAndServeUdpForward(arg)
|
||||||
|
case "rtcp": // Remote TCP port forwarding
|
||||||
|
return serveRTcpForward(arg)
|
||||||
default:
|
default:
|
||||||
ln, err = net.Listen("tcp", arg.Addr)
|
ln, err = net.Listen("tcp", arg.Addr)
|
||||||
}
|
}
|
||||||
@ -76,6 +78,49 @@ func listenAndServe(arg Args) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func serveRTcpForward(arg Args) error {
|
||||||
|
if arg.Forward == "" {
|
||||||
|
ln, err := net.Listen("tcp", arg.Addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer ln.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
conn, err := ln.Accept()
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infoln(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
tc := conn.(*net.TCPConn)
|
||||||
|
tc.SetKeepAlive(true)
|
||||||
|
tc.SetKeepAlivePeriod(time.Second * 60)
|
||||||
|
|
||||||
|
go handleRTcpForwardConn(conn, arg)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
retry := 0
|
||||||
|
for {
|
||||||
|
conn, err := Connect(arg.Forward)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", arg.Addr, arg.Forward, err)
|
||||||
|
time.Sleep((1 << uint(retry)) * time.Second)
|
||||||
|
if retry < 5 {
|
||||||
|
retry++
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
retry = 0
|
||||||
|
|
||||||
|
if err := connectRTcpForward(conn, arg); err != nil {
|
||||||
|
conn.Close()
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func listenAndServeTcpForward(arg Args) error {
|
func listenAndServeTcpForward(arg Args) error {
|
||||||
ln, err := net.Listen("tcp", arg.Addr)
|
ln, err := net.Listen("tcp", arg.Addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -122,10 +167,10 @@ func listenAndServeUdpForward(arg Args) error {
|
|||||||
|
|
||||||
func handleConn(conn net.Conn, arg Args) {
|
func handleConn(conn net.Conn, arg Args) {
|
||||||
atomic.AddInt32(&connCounter, 1)
|
atomic.AddInt32(&connCounter, 1)
|
||||||
glog.V(LINFO).Infof("%s connected, connections: %d",
|
glog.V(LDEBUG).Infof("%s connected, connections: %d",
|
||||||
conn.RemoteAddr(), atomic.LoadInt32(&connCounter))
|
conn.RemoteAddr(), atomic.LoadInt32(&connCounter))
|
||||||
|
|
||||||
if glog.V(LINFO) {
|
if glog.V(LDEBUG) {
|
||||||
defer func() {
|
defer func() {
|
||||||
glog.Infof("%s disconnected, connections: %d",
|
glog.Infof("%s disconnected, connections: %d",
|
||||||
conn.RemoteAddr(), atomic.LoadInt32(&connCounter))
|
conn.RemoteAddr(), atomic.LoadInt32(&connCounter))
|
||||||
@ -153,7 +198,7 @@ func handleConn(conn net.Conn, arg Args) {
|
|||||||
case "http":
|
case "http":
|
||||||
req, err := http.ReadRequest(bufio.NewReader(conn))
|
req, err := http.ReadRequest(bufio.NewReader(conn))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("http:", err)
|
glog.V(LWARNING).Infoln("[http]", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handleHttpRequest(req, conn, arg)
|
handleHttpRequest(req, conn, arg)
|
||||||
@ -162,7 +207,7 @@ func handleConn(conn net.Conn, arg Args) {
|
|||||||
conn = gosocks5.ServerConn(conn, selector)
|
conn = gosocks5.ServerConn(conn, selector)
|
||||||
req, err := gosocks5.ReadRequest(conn)
|
req, err := gosocks5.ReadRequest(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5:", err)
|
glog.V(LWARNING).Infoln("[socks5] request:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handleSocks5Request(req, conn)
|
handleSocks5Request(req, conn)
|
||||||
@ -177,7 +222,7 @@ func handleConn(conn net.Conn, arg Args) {
|
|||||||
|
|
||||||
n, err := io.ReadAtLeast(conn, b, 2)
|
n, err := io.ReadAtLeast(conn, b, 2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("client:", err)
|
glog.V(LWARNING).Infoln("[client]", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,26 +231,26 @@ func handleConn(conn net.Conn, arg Args) {
|
|||||||
length := 2 + mn
|
length := 2 + mn
|
||||||
if n < length {
|
if n < length {
|
||||||
if _, err := io.ReadFull(conn, b[n:length]); err != nil {
|
if _, err := io.ReadFull(conn, b[n:length]); err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5:", err)
|
glog.V(LWARNING).Infoln("[socks5]", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
methods := b[2 : 2+mn]
|
methods := b[2 : 2+mn]
|
||||||
method := selector.Select(methods...)
|
method := selector.Select(methods...)
|
||||||
if _, err := conn.Write([]byte{gosocks5.Ver5, method}); err != nil {
|
if _, err := conn.Write([]byte{gosocks5.Ver5, method}); err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5 select:", err)
|
glog.V(LWARNING).Infoln("[socks5] select:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c, err := selector.OnSelected(method, conn)
|
c, err := selector.OnSelected(method, conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5 onselected:", err)
|
glog.V(LWARNING).Infoln("[socks5] onselected:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
conn = c
|
conn = c
|
||||||
|
|
||||||
req, err := gosocks5.ReadRequest(conn)
|
req, err := gosocks5.ReadRequest(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5 request:", err)
|
glog.V(LWARNING).Infoln("[socks5] request:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handleSocks5Request(req, conn)
|
handleSocks5Request(req, conn)
|
||||||
@ -214,7 +259,7 @@ func handleConn(conn net.Conn, arg Args) {
|
|||||||
|
|
||||||
req, err := http.ReadRequest(bufio.NewReader(newReqReader(b[:n], conn)))
|
req, err := http.ReadRequest(bufio.NewReader(newReqReader(b[:n], conn)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("http:", err)
|
glog.V(LWARNING).Infoln("[http]", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handleHttpRequest(req, conn, arg)
|
handleHttpRequest(req, conn, arg)
|
||||||
@ -247,7 +292,7 @@ func Connect(addr string) (conn net.Conn, err error) {
|
|||||||
addr += ":80"
|
addr += ":80"
|
||||||
}
|
}
|
||||||
if len(forwardArgs) == 0 {
|
if len(forwardArgs) == 0 {
|
||||||
return net.DialTimeout("tcp", addr, time.Second*60)
|
return net.DialTimeout("tcp", addr, time.Second*90)
|
||||||
}
|
}
|
||||||
|
|
||||||
var end Args
|
var end Args
|
||||||
@ -306,7 +351,7 @@ func forward(conn net.Conn, arg Args) (net.Conn, error) {
|
|||||||
if trans == "" { // default is tcp
|
if trans == "" { // default is tcp
|
||||||
trans = "tcp"
|
trans = "tcp"
|
||||||
}
|
}
|
||||||
glog.Infof("forward: %s/%s %s", proto, trans, arg.Addr)
|
glog.V(LDEBUG).Infof("forward: %s/%s %s", proto, trans, arg.Addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
var tlsUsed bool
|
var tlsUsed bool
|
||||||
|
174
forward.go
174
forward.go
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"github.com/ginuerzh/gosocks5"
|
"github.com/ginuerzh/gosocks5"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"net"
|
"net"
|
||||||
@ -10,6 +11,7 @@ import (
|
|||||||
|
|
||||||
func handleTcpForward(conn net.Conn, arg Args) {
|
func handleTcpForward(conn net.Conn, arg Args) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
if !strings.Contains(arg.Forward, ":") {
|
if !strings.Contains(arg.Forward, ":") {
|
||||||
arg.Forward += ":22" // default is ssh service
|
arg.Forward += ":22" // default is ssh service
|
||||||
}
|
}
|
||||||
@ -21,9 +23,9 @@ func handleTcpForward(conn net.Conn, arg Args) {
|
|||||||
}
|
}
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
glog.V(LINFO).Infof("[tcp-forward] %s <-> %s OK", conn.RemoteAddr(), arg.Forward)
|
glog.V(LINFO).Infof("[tcp-forward] %s <-> %s", conn.RemoteAddr(), arg.Forward)
|
||||||
Transport(conn, c)
|
Transport(conn, c)
|
||||||
glog.V(LINFO).Infof("[tcp-forward] %s >-< %s DISCONNECTED", conn.RemoteAddr(), arg.Forward)
|
glog.V(LINFO).Infof("[tcp-forward] %s >-< %s", conn.RemoteAddr(), arg.Forward)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleUdpForward(conn *net.UDPConn, raddr *net.UDPAddr, data []byte, arg Args) {
|
func handleUdpForward(conn *net.UDPConn, raddr *net.UDPAddr, data []byte, arg Args) {
|
||||||
@ -51,7 +53,7 @@ func handleUdpForward(conn *net.UDPConn, raddr *net.UDPAddr, data []byte, arg Ar
|
|||||||
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
|
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
glog.V(LINFO).Infof("[udp-forward] %s >>> %s length %d", raddr, arg.Forward, len(data))
|
glog.V(LDEBUG).Infof("[udp-forward] %s >>> %s length %d", raddr, arg.Forward, len(data))
|
||||||
|
|
||||||
b := udpPool.Get().([]byte)
|
b := udpPool.Get().([]byte)
|
||||||
defer udpPool.Put(b)
|
defer udpPool.Put(b)
|
||||||
@ -61,12 +63,12 @@ func handleUdpForward(conn *net.UDPConn, raddr *net.UDPAddr, data []byte, arg Ar
|
|||||||
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
|
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
glog.V(LINFO).Infof("[udp-forward] %s <<< %s length %d", raddr, addr, n)
|
glog.V(LDEBUG).Infof("[udp-forward] %s <<< %s length %d", raddr, addr, n)
|
||||||
|
|
||||||
if _, err := conn.WriteToUDP(b[:n], raddr); err != nil {
|
if _, err := conn.WriteToUDP(b[:n], raddr); err != nil {
|
||||||
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
|
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
|
||||||
}
|
}
|
||||||
glog.V(LINFO).Infof("[udp-forward] %s >-< %s DONE", raddr, arg.Forward)
|
glog.V(LINFO).Infof("[udp-forward] %s >-< %s", raddr, arg.Forward)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,29 +101,179 @@ func handleUdpForward(conn *net.UDPConn, raddr *net.UDPAddr, data []byte, arg Ar
|
|||||||
glog.V(LWARNING).Infof("[udp-forward] %s <- %s ASSOCIATE failured", raddr, arg.Forward)
|
glog.V(LWARNING).Infof("[udp-forward] %s <- %s ASSOCIATE failured", raddr, arg.Forward)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
glog.V(LINFO).Infof("[udp-forward] %s <-> %s ASSOCIATE ON %s OK", raddr, arg.Forward, rep.Addr)
|
glog.V(LINFO).Infof("[udp-forward] %s <-> %s ASSOCIATE ON %s", raddr, arg.Forward, rep.Addr)
|
||||||
|
|
||||||
dgram := gosocks5.NewUDPDatagram(
|
dgram := gosocks5.NewUDPDatagram(
|
||||||
gosocks5.NewUDPHeader(uint16(len(data)), 0, ToSocksAddr(faddr)), data)
|
gosocks5.NewUDPHeader(uint16(len(data)), 0, ToSocksAddr(faddr)), data)
|
||||||
|
|
||||||
fconn.SetWriteDeadline(time.Now().Add(time.Second * 60))
|
fconn.SetWriteDeadline(time.Now().Add(time.Second * 90))
|
||||||
if err = dgram.Write(fconn); err != nil {
|
if err = dgram.Write(fconn); err != nil {
|
||||||
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
|
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
glog.V(LINFO).Infof("[udp-forward] %s >>> %s length %d", raddr, arg.Forward, len(data))
|
glog.V(LDEBUG).Infof("[udp-forward] %s >>> %s length %d", raddr, arg.Forward, len(data))
|
||||||
|
|
||||||
fconn.SetReadDeadline(time.Now().Add(time.Second * 60))
|
fconn.SetReadDeadline(time.Now().Add(time.Second * 90))
|
||||||
dgram, err = gosocks5.ReadUDPDatagram(fconn)
|
dgram, err = gosocks5.ReadUDPDatagram(fconn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
|
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
glog.V(LINFO).Infof("[udp-forward] %s <<< %s length %d", raddr, dgram.Header.Addr, len(dgram.Data))
|
glog.V(LDEBUG).Infof("[udp-forward] %s <<< %s length %d", raddr, dgram.Header.Addr, len(dgram.Data))
|
||||||
|
|
||||||
if _, err = conn.WriteToUDP(dgram.Data, raddr); err != nil {
|
if _, err = conn.WriteToUDP(dgram.Data, raddr); err != nil {
|
||||||
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
|
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
glog.V(LINFO).Infof("[udp-forward] %s >-< %s DONE", raddr, arg.Forward)
|
glog.V(LINFO).Infof("[udp-forward] %s >-< %s", raddr, arg.Forward)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleRTcpForwardConn(conn net.Conn, arg Args) {
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
req, err := gosocks5.ReadRequest(conn)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", conn.RemoteAddr(), arg.Addr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bindAddr, _ := net.ResolveTCPAddr("tcp", req.Addr.String())
|
||||||
|
ln, err := net.ListenTCP("tcp", bindAddr)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||||
|
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
|
if err := rep.Write(conn); err != nil {
|
||||||
|
glog.V(LWARNING).Infof("[rtcp] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
addr := ToSocksAddr(ln.Addr())
|
||||||
|
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
||||||
|
|
||||||
|
rep := gosocks5.NewReply(gosocks5.Succeeded, addr)
|
||||||
|
if err := rep.Write(conn); err != nil {
|
||||||
|
glog.V(LWARNING).Infof("[rtcp] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||||
|
ln.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
glog.V(LINFO).Infof("[rtcp] %s - %s BIND ON %s OK", conn.RemoteAddr(), req.Addr, addr)
|
||||||
|
|
||||||
|
lnChan := make(chan net.Conn, 1)
|
||||||
|
go func() {
|
||||||
|
defer close(lnChan)
|
||||||
|
c, err := ln.AcceptTCP()
|
||||||
|
if err != nil {
|
||||||
|
// glog.V(LWARNING).Infof("[rtcp] %s <- %s ACCEPT : %s", conn.RemoteAddr(), addr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lnChan <- c
|
||||||
|
}()
|
||||||
|
|
||||||
|
peerChan := make(chan *gosocks5.Reply, 1)
|
||||||
|
go func() {
|
||||||
|
defer close(peerChan)
|
||||||
|
reply, err := gosocks5.ReadReply(conn)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
peerChan <- reply
|
||||||
|
}()
|
||||||
|
|
||||||
|
var pconn net.Conn
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case c := <-lnChan:
|
||||||
|
ln.Close() // only accept one peer
|
||||||
|
if c == nil {
|
||||||
|
if err := gosocks5.NewReply(gosocks5.Failure, nil).Write(conn); err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("[rtcp] %s <- %s : %s", conn.RemoteAddr(), addr, err)
|
||||||
|
}
|
||||||
|
glog.V(LWARNING).Infof("[rtcp] %s >-< %s : %s", conn.RemoteAddr(), addr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
glog.V(LINFO).Infof("[rtcp] %s <- %s PEER %s ACCEPTED", conn.RemoteAddr(), addr, c.RemoteAddr())
|
||||||
|
gosocks5.NewReply(gosocks5.Succeeded, ToSocksAddr(c.RemoteAddr())).Write(conn)
|
||||||
|
pconn = c
|
||||||
|
lnChan = nil
|
||||||
|
ln = nil
|
||||||
|
case reply := <-peerChan:
|
||||||
|
if reply == nil {
|
||||||
|
if ln != nil {
|
||||||
|
ln.Close()
|
||||||
|
}
|
||||||
|
if pconn != nil {
|
||||||
|
pconn.Close()
|
||||||
|
}
|
||||||
|
glog.V(LWARNING).Infof("[rtcp] %s >-< %s", conn.RemoteAddr(), addr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
goto out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
defer pconn.Close()
|
||||||
|
|
||||||
|
glog.V(LINFO).Infof("[rtcp] %s <-> %s", conn.RemoteAddr(), pconn.RemoteAddr())
|
||||||
|
Transport(conn, pconn)
|
||||||
|
glog.V(LINFO).Infof("[rtcp] %s >-< %s", conn.RemoteAddr(), pconn.RemoteAddr())
|
||||||
|
}
|
||||||
|
|
||||||
|
func connectRTcpForward(conn net.Conn, arg Args) error {
|
||||||
|
glog.V(LINFO).Infof("[rtcp] %s - %s", arg.Addr, arg.Forward)
|
||||||
|
|
||||||
|
addr, _ := net.ResolveTCPAddr("tcp", arg.Bind)
|
||||||
|
req := gosocks5.NewRequest(gosocks5.CmdBind, ToSocksAddr(addr))
|
||||||
|
if err := req.Write(conn); err != nil {
|
||||||
|
glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", arg.Addr, arg.Forward, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// first reply, bind status
|
||||||
|
rep, err := gosocks5.ReadReply(conn)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infof("[rtcp] %s <- %s : %s", arg.Addr, arg.Forward, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if rep.Rep != gosocks5.Succeeded {
|
||||||
|
glog.V(LWARNING).Infof("[rtcp] %s <- %s : bind on %s failure", arg.Addr, arg.Forward, arg.Bind)
|
||||||
|
return errors.New("Bind on " + arg.Bind + " failure")
|
||||||
|
}
|
||||||
|
glog.V(LINFO).Infof("[rtcp] %s - %s BIND ON %s OK", arg.Addr, arg.Forward, arg.Bind)
|
||||||
|
|
||||||
|
// second reply, peer connection
|
||||||
|
rep, err = gosocks5.ReadReply(conn)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infof("[rtcp] %s <- %s : %s", arg.Addr, arg.Forward, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if rep.Rep != gosocks5.Succeeded {
|
||||||
|
glog.V(LWARNING).Infof("[rtcp] %s <- %s : peer connect failure", arg.Addr, arg.Forward)
|
||||||
|
return errors.New("peer connect failure")
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(LINFO).Infof("[rtcp] %s <- %s PEER %s CONNECTED", conn.RemoteAddr(), req.Addr, rep.Addr)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
lconn, err := net.Dial("tcp", arg.Addr)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infof("[rtcp] %s <- %s : %s", arg.Addr, arg.Forward, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer lconn.Close()
|
||||||
|
|
||||||
|
if err := gosocks5.NewReply(gosocks5.Succeeded, nil).Write(conn); err != nil {
|
||||||
|
glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", arg.Addr, arg.Forward, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(LINFO).Infof("[rtcp] %s <-> %s", arg.Addr, arg.Forward)
|
||||||
|
Transport(lconn, conn)
|
||||||
|
glog.V(LINFO).Infof("[rtcp] %s >-< %s", arg.Addr, arg.Forward)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
4
http.go
4
http.go
@ -73,9 +73,9 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glog.V(LINFO).Infof("[http] %s <-> %s OK", conn.RemoteAddr(), req.Host)
|
glog.V(LINFO).Infof("[http] %s <-> %s", conn.RemoteAddr(), req.Host)
|
||||||
Transport(conn, c)
|
Transport(conn, c)
|
||||||
glog.V(LINFO).Infof("[http] %s >-< %s DISCONNECTED", conn.RemoteAddr(), req.Host)
|
glog.V(LINFO).Infof("[http] %s >-< %s", conn.RemoteAddr(), req.Host)
|
||||||
}
|
}
|
||||||
|
|
||||||
func basicAuth(authInfo string) (username, password string, ok bool) {
|
func basicAuth(authInfo string) (username, password string, ok bool) {
|
||||||
|
213
socks.go
213
socks.go
@ -6,7 +6,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"github.com/ginuerzh/gosocks5"
|
"github.com/ginuerzh/gosocks5"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"io"
|
//"os/exec"
|
||||||
|
//"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -124,10 +125,10 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con
|
|||||||
|
|
||||||
req, err := gosocks5.ReadUserPassRequest(conn)
|
req, err := gosocks5.ReadUserPassRequest(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5 auth:", err)
|
glog.V(LWARNING).Infoln("[socks5-auth]", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
glog.V(LDEBUG).Infoln(req.String())
|
glog.V(LDEBUG).Infoln("[socks5]", req.String())
|
||||||
|
|
||||||
var username, password string
|
var username, password string
|
||||||
if selector.user != nil {
|
if selector.user != nil {
|
||||||
@ -138,18 +139,18 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con
|
|||||||
if (username != "" && req.Username != username) || (password != "" && req.Password != password) {
|
if (username != "" && req.Username != username) || (password != "" && req.Password != password) {
|
||||||
resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Failure)
|
resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Failure)
|
||||||
if err := resp.Write(conn); err != nil {
|
if err := resp.Write(conn); err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5 auth:", err)
|
glog.V(LWARNING).Infoln("[socks5-auth]", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
glog.V(LDEBUG).Infoln(resp)
|
glog.V(LDEBUG).Infoln("[socks5]", resp)
|
||||||
glog.V(LWARNING).Infoln("socks5: proxy authentication required")
|
glog.V(LWARNING).Infoln("[socks5-auth] proxy authentication required")
|
||||||
|
|
||||||
return nil, gosocks5.ErrAuthFailure
|
return nil, gosocks5.ErrAuthFailure
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Succeeded)
|
resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Succeeded)
|
||||||
if err := resp.Write(conn); err != nil {
|
if err := resp.Write(conn); err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5 auth:", err)
|
glog.V(LWARNING).Infoln("[socks5-auth]", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
glog.V(LDEBUG).Infoln(resp)
|
glog.V(LDEBUG).Infoln(resp)
|
||||||
@ -162,7 +163,7 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
||||||
glog.V(LDEBUG).Infof("[socks5-connect] %s -> %s\n%s", conn.RemoteAddr(), req.Addr, req)
|
glog.V(LDEBUG).Infof("[socks5] %s -> %s\n%s", conn.RemoteAddr(), req.Addr, req)
|
||||||
|
|
||||||
switch req.Cmd {
|
switch req.Cmd {
|
||||||
case gosocks5.CmdConnect:
|
case gosocks5.CmdConnect:
|
||||||
@ -188,18 +189,21 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
|||||||
}
|
}
|
||||||
glog.V(LDEBUG).Infof("[socks5-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
|
glog.V(LDEBUG).Infof("[socks5-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
|
||||||
|
|
||||||
glog.V(LINFO).Infof("[socks5-connect] %s <-> %s OK", conn.RemoteAddr(), req.Addr)
|
glog.V(LINFO).Infof("[socks5-connect] %s <-> %s", conn.RemoteAddr(), req.Addr)
|
||||||
Transport(conn, tconn)
|
Transport(conn, tconn)
|
||||||
glog.V(LINFO).Infof("[socks5-connect] %s >-< %s DISCONNECTED", conn.RemoteAddr(), req.Addr)
|
glog.V(LINFO).Infof("[socks5-connect] %s >-< %s", conn.RemoteAddr(), req.Addr)
|
||||||
case gosocks5.CmdBind:
|
case gosocks5.CmdBind:
|
||||||
glog.V(LINFO).Infof("[socks5-bind] %s - %s", conn.RemoteAddr(), req.Addr)
|
glog.V(LINFO).Infof("[socks5-bind] %s - %s", conn.RemoteAddr(), req.Addr)
|
||||||
|
|
||||||
if len(forwardArgs) > 0 {
|
if len(forwardArgs) > 0 {
|
||||||
forwardBind(req, conn)
|
forwardBind(req, conn)
|
||||||
} else {
|
} else {
|
||||||
serveBind(conn)
|
tc := conn.(*net.TCPConn)
|
||||||
|
tc.SetKeepAlive(true)
|
||||||
|
tc.SetKeepAlivePeriod(time.Second * 60)
|
||||||
|
|
||||||
|
serveBind(req, conn)
|
||||||
}
|
}
|
||||||
glog.V(LINFO).Infof("[socks5-bind] %s >-< %s DISCONNECTED", conn.RemoteAddr(), req.Addr)
|
|
||||||
case gosocks5.CmdUdp, CmdUdpTun:
|
case gosocks5.CmdUdp, CmdUdpTun:
|
||||||
// TODO: udp tunnel <-> forward chain
|
// TODO: udp tunnel <-> forward chain
|
||||||
glog.V(LINFO).Infof("[socks5-udp] %s - %s ASSOCIATE", conn.RemoteAddr(), req.Addr)
|
glog.V(LINFO).Infof("[socks5-udp] %s - %s ASSOCIATE", conn.RemoteAddr(), req.Addr)
|
||||||
@ -288,119 +292,175 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
|||||||
TransportUDP(cc, sc)
|
TransportUDP(cc, sc)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
glog.V(LWARNING).Infoln("Unrecognized request: ", req)
|
glog.V(LWARNING).Infoln("[socks5] Unrecognized request:", req.Cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func serveBind(conn net.Conn) error {
|
func serveBind(req *gosocks5.Request, conn net.Conn) error {
|
||||||
l, err := net.ListenTCP("tcp", nil)
|
bindAddr, _ := net.ResolveTCPAddr("tcp", req.Addr.String())
|
||||||
|
ln, err := net.ListenTCP("tcp", bindAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5 bind listen:", err)
|
glog.V(LWARNING).Infof("[socks5-bind] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||||
|
if bindAddr != nil {
|
||||||
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
ln, err = net.ListenTCP("tcp", nil)
|
||||||
if err := rep.Write(conn); err != nil {
|
}
|
||||||
glog.V(LWARNING).Infoln("socks5 bind listen:", err)
|
if err != nil {
|
||||||
} else {
|
glog.V(LWARNING).Infof("[socks5-bind] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||||
glog.V(LDEBUG).Infoln(rep)
|
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
|
if err := rep.Write(conn); err != nil {
|
||||||
|
glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||||
|
} else {
|
||||||
|
glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addr := ToSocksAddr(l.Addr())
|
addr := ToSocksAddr(ln.Addr())
|
||||||
// Issue: may not reachable when host has two interfaces
|
// Issue: may not reachable when host has two interfaces
|
||||||
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
||||||
|
|
||||||
rep := gosocks5.NewReply(gosocks5.Succeeded, addr)
|
rep := gosocks5.NewReply(gosocks5.Succeeded, addr)
|
||||||
if err := rep.Write(conn); err != nil {
|
if err := rep.Write(conn); err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5 bind:", err)
|
glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||||
l.Close()
|
ln.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
glog.V(LDEBUG).Infoln(rep)
|
glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
|
||||||
glog.V(LINFO).Infoln("[socks5] BIND on", addr, "OK")
|
glog.V(LINFO).Infof("[socks5-bind] %s - %s BIND ON %s OK", conn.RemoteAddr(), req.Addr, addr)
|
||||||
|
|
||||||
l.SetDeadline(time.Now().Add(time.Minute * 30)) // wait 30 minutes at most
|
lnChan := make(chan net.Conn, 1)
|
||||||
tconn, err := l.AcceptTCP()
|
go func() {
|
||||||
l.Close() // only accept one peer
|
defer close(lnChan)
|
||||||
if err != nil {
|
c, err := ln.AcceptTCP()
|
||||||
glog.V(LWARNING).Infoln("socks5 bind accept:", err)
|
if err != nil {
|
||||||
|
return
|
||||||
rep = gosocks5.NewReply(gosocks5.Failure, nil)
|
}
|
||||||
if err := rep.Write(conn); err != nil {
|
lnChan <- c
|
||||||
glog.V(LWARNING).Infoln("socks5 bind accept:", err)
|
}()
|
||||||
} else {
|
|
||||||
glog.V(LDEBUG).Infoln(rep)
|
peerChan := make(chan error, 1)
|
||||||
|
go func() {
|
||||||
|
defer close(peerChan)
|
||||||
|
_, err := ioutil.ReadAll(conn)
|
||||||
|
if err != nil {
|
||||||
|
if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
peerChan <- err
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var pconn net.Conn
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case c := <-lnChan:
|
||||||
|
ln.Close() // only accept one peer
|
||||||
|
if c == nil {
|
||||||
|
if err := gosocks5.NewReply(gosocks5.Failure, nil).Write(conn); err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("[socks5-bind] %s <- %s : %s", conn.RemoteAddr(), addr, err)
|
||||||
|
}
|
||||||
|
glog.V(LWARNING).Infof("[socks5-bind] %s >-< %s", conn.RemoteAddr(), addr)
|
||||||
|
return errors.New("accept error")
|
||||||
|
}
|
||||||
|
// glog.V(LINFO).Infof("[socks5-bind] %s <- %s PEER %s ACCEPTED", conn.RemoteAddr(), req.Addr, c.RemoteAddr())
|
||||||
|
// gosocks5.NewReply(gosocks5.Succeeded, ToSocksAddr(c.RemoteAddr())).Write(conn)
|
||||||
|
pconn = c
|
||||||
|
lnChan = nil
|
||||||
|
ln = nil
|
||||||
|
conn.SetReadDeadline(time.Now()) // timeout right now ,so we can break out of blocking
|
||||||
|
case err := <-peerChan:
|
||||||
|
if err != nil || pconn == nil {
|
||||||
|
if ln != nil {
|
||||||
|
ln.Close()
|
||||||
|
}
|
||||||
|
if pconn != nil {
|
||||||
|
pconn.Close()
|
||||||
|
}
|
||||||
|
glog.V(LWARNING).Infof("[socks5-bind] %s >-< %s", conn.RemoteAddr(), addr)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
goto out
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
defer tconn.Close()
|
|
||||||
|
|
||||||
addr = ToSocksAddr(tconn.RemoteAddr())
|
out:
|
||||||
glog.V(LINFO).Infoln("[socks5] BIND accept", addr)
|
defer pconn.Close()
|
||||||
|
conn.SetReadDeadline(time.Time{})
|
||||||
|
|
||||||
rep = gosocks5.NewReply(gosocks5.Succeeded, addr)
|
paddr := ToSocksAddr(pconn.RemoteAddr())
|
||||||
|
glog.V(LINFO).Infof("[socks5-bind] %s <- %s PEER %s ACCEPTED", conn.RemoteAddr(), addr, paddr)
|
||||||
|
|
||||||
|
rep = gosocks5.NewReply(gosocks5.Succeeded, paddr)
|
||||||
if err := rep.Write(conn); err != nil {
|
if err := rep.Write(conn); err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5 bind accept:", err)
|
glog.V(LWARNING).Infof("[socks5 bind] %s <- %s : %s", conn.RemoteAddr(), addr, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
glog.V(LDEBUG).Infoln(rep)
|
glog.V(LDEBUG).Infof("[socks5 bind] %s <- %s\n%s", conn.RemoteAddr(), addr, rep)
|
||||||
|
|
||||||
return Transport(conn, tconn)
|
glog.V(LINFO).Infof("[socks5-bind] %s <-> %s", conn.RemoteAddr(), paddr)
|
||||||
|
defer glog.V(LINFO).Infof("[socks5-bind] %s >-< %s", conn.RemoteAddr(), paddr)
|
||||||
|
return Transport(conn, pconn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func forwardBind(req *gosocks5.Request, conn net.Conn) error {
|
func forwardBind(req *gosocks5.Request, conn net.Conn) error {
|
||||||
fconn, _, err := forwardChain(forwardArgs...)
|
fconn, _, err := forwardChain(forwardArgs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("[socks5] BIND forward", req.Addr, err)
|
glog.V(LWARNING).Infof("[socks5-bind] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||||
if fconn != nil {
|
if fconn != nil {
|
||||||
fconn.Close()
|
fconn.Close()
|
||||||
}
|
}
|
||||||
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
if err := rep.Write(conn); err != nil {
|
if err := rep.Write(conn); err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5 bind forward:", err)
|
glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||||
} else {
|
} else {
|
||||||
glog.V(LDEBUG).Infoln(rep)
|
glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer fconn.Close()
|
defer fconn.Close()
|
||||||
|
|
||||||
if err := req.Write(fconn); err != nil {
|
if err := req.Write(fconn); err != nil {
|
||||||
glog.V(LWARNING).Infoln("[socks5] BIND forward", err)
|
glog.V(LWARNING).Infoln("[socks5-bind] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||||
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn)
|
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
glog.V(LDEBUG).Infoln(req)
|
glog.V(LDEBUG).Infof("[socks5-bind] %s -> %s\n%s", conn.RemoteAddr(), req.Addr, req)
|
||||||
|
|
||||||
// first reply
|
/*
|
||||||
rep, err := peekReply(conn, fconn)
|
// first reply
|
||||||
if err != nil {
|
rep, err := peekReply(conn, fconn)
|
||||||
glog.V(LWARNING).Infoln("[socks5] BIND forward", err)
|
if err != nil {
|
||||||
return err
|
glog.V(LWARNING).Infoln("[socks5] BIND forward", err)
|
||||||
}
|
return err
|
||||||
glog.V(LINFO).Infoln("[socks5] BIND forward on", rep.Addr, "OK")
|
}
|
||||||
|
glog.V(LINFO).Infoln("[socks5] BIND forward on", rep.Addr, "OK")
|
||||||
// second reply
|
|
||||||
rep, err = peekReply(conn, fconn)
|
|
||||||
if err != nil {
|
|
||||||
glog.V(LWARNING).Infoln("[socks5] BIND forward accept", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
glog.V(LINFO).Infoln("[socks5] BIND forward accept", rep.Addr)
|
|
||||||
|
|
||||||
|
// second reply
|
||||||
|
rep, err = peekReply(conn, fconn)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infoln("[socks5] BIND forward accept", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
glog.V(LINFO).Infoln("[socks5] BIND forward accept", rep.Addr)
|
||||||
|
*/
|
||||||
|
glog.V(LINFO).Infof("[socks5-bind] %s <-> %s", conn.RemoteAddr(), req.Addr)
|
||||||
|
defer glog.V(LINFO).Infof("[socks5-bind] %s >-< %s", conn.RemoteAddr(), req.Addr)
|
||||||
return Transport(conn, fconn)
|
return Transport(conn, fconn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func peekReply(dst io.Writer, src io.Reader) (rep *gosocks5.Reply, err error) {
|
/*
|
||||||
|
func peekReply(dst, src net.Conn) (rep *gosocks5.Reply, err error) {
|
||||||
rep, err = gosocks5.ReadReply(src)
|
rep, err = gosocks5.ReadReply(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln(err)
|
glog.V(LWARNING).Infof("[socks5-bind] FORWARD %s <- : %s", dst.RemoteAddr(), err)
|
||||||
rep = gosocks5.NewReply(gosocks5.Failure, nil)
|
rep = gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
}
|
}
|
||||||
if err = rep.Write(dst); err != nil {
|
if err = rep.Write(dst); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
glog.V(LDEBUG).Infoln(rep)
|
glog.V(LDEBUG).Infof("[socks5-bind] FORWARD %s <-\n%s", dst.RemoteAddr(), rep)
|
||||||
|
|
||||||
if rep.Rep != gosocks5.Succeeded {
|
if rep.Rep != gosocks5.Succeeded {
|
||||||
err = errors.New("Failure")
|
err = errors.New("Failure")
|
||||||
@ -408,6 +468,7 @@ func peekReply(dst io.Writer, src io.Reader) (rep *gosocks5.Reply, err error) {
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func createServerConn(uconn *net.UDPConn) (c *UDPConn, err error) {
|
func createServerConn(uconn *net.UDPConn) (c *UDPConn, err error) {
|
||||||
if len(forwardArgs) == 0 {
|
if len(forwardArgs) == 0 {
|
||||||
@ -448,13 +509,17 @@ func createServerConn(uconn *net.UDPConn) (c *UDPConn, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ToSocksAddr(addr net.Addr) *gosocks5.Addr {
|
func ToSocksAddr(addr net.Addr) *gosocks5.Addr {
|
||||||
host, port, _ := net.SplitHostPort(addr.String())
|
host := ""
|
||||||
p, _ := strconv.Atoi(port)
|
port := 0
|
||||||
|
if addr != nil {
|
||||||
|
h, p, _ := net.SplitHostPort(addr.String())
|
||||||
|
host = h
|
||||||
|
port, _ = strconv.Atoi(p)
|
||||||
|
}
|
||||||
return &gosocks5.Addr{
|
return &gosocks5.Addr{
|
||||||
Type: gosocks5.AddrIPv4,
|
Type: gosocks5.AddrIPv4,
|
||||||
Host: host,
|
Host: host,
|
||||||
Port: uint16(p),
|
Port: uint16(port),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
28
util.go
28
util.go
@ -22,11 +22,12 @@ func (ss *strSlice) Set(value string) error {
|
|||||||
|
|
||||||
// admin:123456@localhost:8080
|
// admin:123456@localhost:8080
|
||||||
type Args struct {
|
type Args struct {
|
||||||
Addr string // host:port
|
Addr string // host:port
|
||||||
Protocol string // protocol: http/socks(5)/ss
|
Protocol string // protocol: http/socks(5)/ss
|
||||||
Transport string // transport: ws(s)/tls/tcp/udp
|
Transport string // transport: ws(s)/tls/tcp/udp/rtcp/rudp
|
||||||
Forward string // forward address, used by tcp/udp port forwarding
|
Forward string // forward address, used by local tcp/udp port forwarding
|
||||||
User *url.Userinfo
|
Bind string // remote binding port, used by remote tcp/udp port forwarding
|
||||||
|
User *url.Userinfo // authentication for proxy
|
||||||
Cert tls.Certificate // tls certificate
|
Cert tls.Certificate // tls certificate
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,10 +53,9 @@ func parseArgs(ss []string) (args []Args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
arg := Args{
|
arg := Args{
|
||||||
Addr: u.Host,
|
Addr: u.Host,
|
||||||
User: u.User,
|
User: u.User,
|
||||||
Cert: tlsCert,
|
Cert: tlsCert,
|
||||||
Forward: strings.Trim(u.EscapedPath(), "/"),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
schemes := strings.Split(u.Scheme, "+")
|
schemes := strings.Split(u.Scheme, "+")
|
||||||
@ -76,8 +76,14 @@ func parseArgs(ss []string) (args []Args) {
|
|||||||
|
|
||||||
switch arg.Transport {
|
switch arg.Transport {
|
||||||
case "ws", "wss", "tls":
|
case "ws", "wss", "tls":
|
||||||
case "tcp", "udp": // started from v2.1, tcp and udp are for port forwarding
|
case "tcp", "udp": // started from v2.1, tcp and udp are for local port forwarding
|
||||||
arg.Protocol = ""
|
arg.Forward = strings.Trim(u.EscapedPath(), "/")
|
||||||
|
case "rtcp", "rudp": // started from v2.1, rtcp and rudp are for remote port forwarding\
|
||||||
|
if a := strings.Split(strings.Trim(u.EscapedPath(), "/"), ":"); len(a) == 3 {
|
||||||
|
arg.Forward = a[0] + ":" + a[1]
|
||||||
|
arg.Bind = ":" + a[2]
|
||||||
|
glog.V(LINFO).Infoln(arg.Forward, arg.Bind)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
arg.Transport = ""
|
arg.Transport = ""
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user