add bind forward
This commit is contained in:
parent
706e22e7a7
commit
d7dfb3edaa
75
conn.go
75
conn.go
@ -111,7 +111,7 @@ func handleConn(conn net.Conn, arg Args) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handleSocks5Request(req, conn, arg)
|
handleSocks5Request(req, conn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +162,7 @@ func handleConn(conn net.Conn, arg Args) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handleSocks5Request(req, conn, arg)
|
handleSocks5Request(req, conn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,41 +198,43 @@ func (r *reqReader) Read(p []byte) (n int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func connect(addr string) (conn net.Conn, err error) {
|
func Connect(addr string) (conn net.Conn, err error) {
|
||||||
if !strings.Contains(addr, ":") {
|
if !strings.Contains(addr, ":") {
|
||||||
addr += ":80"
|
addr += ":80"
|
||||||
}
|
}
|
||||||
if len(forwardArgs) == 0 {
|
if len(forwardArgs) == 0 {
|
||||||
return net.Dial("tcp", addr)
|
return net.Dial("tcp", addr)
|
||||||
}
|
}
|
||||||
return forwardChain(addr, forwardArgs[0], forwardArgs[1:]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func forwardChain(addr string, level1 Args, chain ...Args) (conn net.Conn, err error) {
|
var end Args
|
||||||
if glog.V(LINFO) {
|
conn, end, err = forwardChain(forwardArgs...)
|
||||||
glog.Infof("forward: %s/%s %s", level1.Protocol, level1.Transport, level1.Addr)
|
|
||||||
}
|
|
||||||
if conn, err = net.Dial("tcp", level1.Addr); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c, err := forward(conn, level1)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if conn != nil {
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := establish(conn, addr, end); err != nil {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func forwardChain(chain ...Args) (conn net.Conn, end Args, err error) {
|
||||||
|
end = chain[0]
|
||||||
|
if conn, err = net.Dial("tcp", end.Addr); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c, err := forward(conn, end)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
conn = c
|
conn = c
|
||||||
|
|
||||||
if len(chain) == 0 {
|
chain = chain[1:]
|
||||||
if err := establish(conn, addr, level1); err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cur := level1
|
|
||||||
for _, arg := range chain {
|
for _, arg := range chain {
|
||||||
if err = establish(conn, arg.Addr, cur); err != nil {
|
if err = establish(conn, arg.Addr, end); err != nil {
|
||||||
goto exit
|
goto exit
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,26 +243,18 @@ func forwardChain(addr string, level1 Args, chain ...Args) (conn net.Conn, err e
|
|||||||
goto exit
|
goto exit
|
||||||
}
|
}
|
||||||
conn = c
|
conn = c
|
||||||
cur = arg
|
end = arg
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := establish(conn, addr, cur); err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func forward(conn net.Conn, arg Args) (net.Conn, error) {
|
func forward(conn net.Conn, arg Args) (net.Conn, error) {
|
||||||
var err error
|
var err error
|
||||||
|
if glog.V(LINFO) {
|
||||||
|
glog.Infof("forward: %s/%s %s", arg.Protocol, arg.Transport, arg.Addr)
|
||||||
|
}
|
||||||
switch arg.Transport {
|
switch arg.Transport {
|
||||||
case "ws": // websocket connection
|
case "ws": // websocket connection
|
||||||
conn, err = wsClient(conn, arg.Addr)
|
conn, err = wsClient(conn, arg.Addr)
|
||||||
@ -312,10 +306,19 @@ func establish(conn net.Conn, addr string, arg Args) error {
|
|||||||
Host: host,
|
Host: host,
|
||||||
Port: uint16(p),
|
Port: uint16(p),
|
||||||
})
|
})
|
||||||
rep, err := requestSocks5(conn, req)
|
if err := req.Write(conn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if glog.V(LDEBUG) {
|
||||||
|
glog.Infoln(req)
|
||||||
|
}
|
||||||
|
rep, err := gosocks5.ReadReply(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if glog.V(LDEBUG) {
|
||||||
|
glog.Infoln(rep)
|
||||||
|
}
|
||||||
if rep.Rep != gosocks5.Succeeded {
|
if rep.Rep != gosocks5.Succeeded {
|
||||||
return errors.New("Service unavailable")
|
return errors.New("Service unavailable")
|
||||||
}
|
}
|
||||||
|
2
http.go
2
http.go
@ -47,7 +47,7 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := connect(req.Host)
|
c, err := Connect(req.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if glog.V(LWARNING) {
|
if glog.V(LWARNING) {
|
||||||
glog.Warningln(err)
|
glog.Warningln(err)
|
||||||
|
261
socks.go
261
socks.go
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
"github.com/ginuerzh/gosocks5"
|
"github.com/ginuerzh/gosocks5"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"net"
|
"net"
|
||||||
@ -175,24 +176,7 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con
|
|||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestSocks5(conn net.Conn, req *gosocks5.Request) (*gosocks5.Reply, error) {
|
func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
||||||
if err := req.Write(conn); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if glog.V(LDEBUG) {
|
|
||||||
glog.Infoln(req.String())
|
|
||||||
}
|
|
||||||
rep, err := gosocks5.ReadReply(conn)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if glog.V(LDEBUG) {
|
|
||||||
glog.Infoln(rep.String())
|
|
||||||
}
|
|
||||||
return rep, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleSocks5Request(req *gosocks5.Request, conn net.Conn, arg Args) {
|
|
||||||
if glog.V(LDEBUG) {
|
if glog.V(LDEBUG) {
|
||||||
glog.Infoln(req)
|
glog.Infoln(req)
|
||||||
}
|
}
|
||||||
@ -202,7 +186,7 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn, arg Args) {
|
|||||||
if glog.V(LINFO) {
|
if glog.V(LINFO) {
|
||||||
glog.Infoln("socks5 connect:", req.Addr.String())
|
glog.Infoln("socks5 connect:", req.Addr.String())
|
||||||
}
|
}
|
||||||
tconn, err := connect(req.Addr.String())
|
tconn, err := Connect(req.Addr.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if glog.V(LWARNING) {
|
if glog.V(LWARNING) {
|
||||||
glog.Warningln("socks5 connect:", err)
|
glog.Warningln("socks5 connect:", err)
|
||||||
@ -234,78 +218,10 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn, arg Args) {
|
|||||||
|
|
||||||
Transport(conn, tconn)
|
Transport(conn, tconn)
|
||||||
case gosocks5.CmdBind:
|
case gosocks5.CmdBind:
|
||||||
l, err := net.ListenTCP("tcp", nil)
|
if len(forwardArgs) > 0 {
|
||||||
if err != nil {
|
forwardBind(req, conn)
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind listen:", err)
|
|
||||||
}
|
|
||||||
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
|
||||||
if err := rep.Write(conn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind listen:", err)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if glog.V(LDEBUG) {
|
serveBind(conn)
|
||||||
glog.Infoln(rep)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
addr := ToSocksAddr(l.Addr())
|
|
||||||
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
|
||||||
if glog.V(LINFO) {
|
|
||||||
glog.Infoln("socks5 bind:", addr)
|
|
||||||
}
|
|
||||||
rep := gosocks5.NewReply(gosocks5.Succeeded, addr)
|
|
||||||
if err := rep.Write(conn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind:", err)
|
|
||||||
}
|
|
||||||
l.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if glog.V(LDEBUG) {
|
|
||||||
glog.Infoln(rep)
|
|
||||||
}
|
|
||||||
|
|
||||||
tconn, err := l.AcceptTCP()
|
|
||||||
l.Close() // only accept one peer
|
|
||||||
if err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind accept:", err)
|
|
||||||
}
|
|
||||||
rep = gosocks5.NewReply(gosocks5.Failure, nil)
|
|
||||||
if err := rep.Write(conn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind accept:", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if glog.V(LDEBUG) {
|
|
||||||
glog.Infoln(rep)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer tconn.Close()
|
|
||||||
|
|
||||||
addr = ToSocksAddr(tconn.RemoteAddr())
|
|
||||||
if glog.V(LINFO) {
|
|
||||||
glog.Infoln("socks5 bind accept:", addr.String())
|
|
||||||
}
|
|
||||||
rep = gosocks5.NewReply(gosocks5.Succeeded, addr)
|
|
||||||
if err := rep.Write(conn); err != nil {
|
|
||||||
if glog.V(LWARNING) {
|
|
||||||
glog.Warningln("socks5 bind accept:", err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if glog.V(LDEBUG) {
|
|
||||||
glog.Infoln(rep)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := Transport(conn, tconn); err != nil {
|
|
||||||
//log.Println(err)
|
|
||||||
}
|
}
|
||||||
case gosocks5.CmdUdp:
|
case gosocks5.CmdUdp:
|
||||||
uconn, err := net.ListenUDP("udp", nil)
|
uconn, err := net.ListenUDP("udp", nil)
|
||||||
@ -347,6 +263,171 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn, arg Args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func serveBind(conn net.Conn) error {
|
||||||
|
l, err := net.ListenTCP("tcp", nil)
|
||||||
|
if err != nil {
|
||||||
|
if glog.V(LWARNING) {
|
||||||
|
glog.Warningln("socks5 bind listen:", err)
|
||||||
|
}
|
||||||
|
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
|
if err := rep.Write(conn); err != nil {
|
||||||
|
if glog.V(LWARNING) {
|
||||||
|
glog.Warningln("socks5 bind listen:", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if glog.V(LDEBUG) {
|
||||||
|
glog.Infoln(rep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
addr := ToSocksAddr(l.Addr())
|
||||||
|
// Issue: may not reachable when host has two interfaces
|
||||||
|
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
||||||
|
if glog.V(LINFO) {
|
||||||
|
glog.Infoln("socks5 bind:", addr)
|
||||||
|
}
|
||||||
|
rep := gosocks5.NewReply(gosocks5.Succeeded, addr)
|
||||||
|
if err := rep.Write(conn); err != nil {
|
||||||
|
if glog.V(LWARNING) {
|
||||||
|
glog.Warningln("socks5 bind:", err)
|
||||||
|
}
|
||||||
|
l.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if glog.V(LDEBUG) {
|
||||||
|
glog.Infoln(rep)
|
||||||
|
}
|
||||||
|
|
||||||
|
tconn, err := l.AcceptTCP()
|
||||||
|
l.Close() // only accept one peer
|
||||||
|
if err != nil {
|
||||||
|
if glog.V(LWARNING) {
|
||||||
|
glog.Warningln("socks5 bind accept:", err)
|
||||||
|
}
|
||||||
|
rep = gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
|
if err := rep.Write(conn); err != nil {
|
||||||
|
if glog.V(LWARNING) {
|
||||||
|
glog.Warningln("socks5 bind accept:", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if glog.V(LDEBUG) {
|
||||||
|
glog.Infoln(rep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer tconn.Close()
|
||||||
|
|
||||||
|
addr = ToSocksAddr(tconn.RemoteAddr())
|
||||||
|
if glog.V(LINFO) {
|
||||||
|
glog.Infoln("socks5 bind accept:", addr.String())
|
||||||
|
}
|
||||||
|
rep = gosocks5.NewReply(gosocks5.Succeeded, addr)
|
||||||
|
if err := rep.Write(conn); err != nil {
|
||||||
|
if glog.V(LWARNING) {
|
||||||
|
glog.Warningln("socks5 bind accept:", err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if glog.V(LDEBUG) {
|
||||||
|
glog.Infoln(rep)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Transport(conn, tconn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func forwardBind(req *gosocks5.Request, conn net.Conn) error {
|
||||||
|
fc, _, err := forwardChain(forwardArgs...)
|
||||||
|
if err != nil {
|
||||||
|
if fc != nil {
|
||||||
|
fc.Close()
|
||||||
|
}
|
||||||
|
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
|
if err := rep.Write(conn); err != nil {
|
||||||
|
if glog.V(LWARNING) {
|
||||||
|
glog.Warningln("socks5 bind:", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if glog.V(LDEBUG) {
|
||||||
|
glog.Infoln(rep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer fc.Close()
|
||||||
|
|
||||||
|
if err := req.Write(fc); err != nil {
|
||||||
|
if glog.V(LWARNING) {
|
||||||
|
glog.Warningln("socks5 bind:", err)
|
||||||
|
}
|
||||||
|
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if glog.V(LDEBUG) {
|
||||||
|
glog.Infoln(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// first reply
|
||||||
|
if err := peekBindReply(conn, fc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// second reply
|
||||||
|
if err := peekBindReply(conn, fc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Transport(conn, fc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func peekBindReply(conn, fc net.Conn) error {
|
||||||
|
rep, err := gosocks5.ReadReply(fc)
|
||||||
|
if err != nil {
|
||||||
|
if glog.V(LWARNING) {
|
||||||
|
glog.Warningln("socks5 bind:", err)
|
||||||
|
}
|
||||||
|
rep = gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
|
}
|
||||||
|
if err := rep.Write(conn); err != nil {
|
||||||
|
if glog.V(LWARNING) {
|
||||||
|
glog.Warningln("socks5 bind:", err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if glog.V(LDEBUG) {
|
||||||
|
glog.Infoln(rep)
|
||||||
|
}
|
||||||
|
if rep.Rep != gosocks5.Succeeded {
|
||||||
|
return errors.New("Bind failure")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func forwardUDP() error {
|
||||||
|
fc, _, err := forwardChain(forwardArgs...)
|
||||||
|
if err != nil {
|
||||||
|
if fc != nil {
|
||||||
|
fc.Close()
|
||||||
|
}
|
||||||
|
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
|
if err := rep.Write(conn); err != nil {
|
||||||
|
if glog.V(LWARNING) {
|
||||||
|
glog.Warningln("socks5 bind:", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if glog.V(LDEBUG) {
|
||||||
|
glog.Infoln(rep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer fc.Close()
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
func srvTunnelUDP(conn net.Conn, uconn *net.UDPConn) {
|
func srvTunnelUDP(conn net.Conn, uconn *net.UDPConn) {
|
||||||
go func() {
|
go func() {
|
||||||
b := make([]byte, 16*1024)
|
b := make([]byte, 16*1024)
|
||||||
|
Loading…
Reference in New Issue
Block a user