|
|
|
@ -47,27 +47,19 @@ func (selector *clientSelector) OnSelected(method uint8, conn net.Conn) (net.Con |
|
|
|
|
|
|
|
req := gosocks5.NewUserPassRequest(gosocks5.UserPassVer, username, password) |
|
|
|
if err := req.Write(conn); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 auth:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 auth:", err) |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(req) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(req) |
|
|
|
|
|
|
|
res, err := gosocks5.ReadUserPassResponse(conn) |
|
|
|
resp, err := gosocks5.ReadUserPassResponse(conn) |
|
|
|
if err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 auth:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 auth:", err) |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(res) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(resp) |
|
|
|
|
|
|
|
if res.Status != gosocks5.Succeeded { |
|
|
|
if resp.Status != gosocks5.Succeeded { |
|
|
|
return nil, gosocks5.ErrAuthFailure |
|
|
|
} |
|
|
|
case gosocks5.MethodNoAcceptable: |
|
|
|
@ -87,9 +79,7 @@ func (selector *serverSelector) Methods() []uint8 { |
|
|
|
} |
|
|
|
|
|
|
|
func (selector *serverSelector) Select(methods ...uint8) (method uint8) { |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infof("%d %d % d", gosocks5.Ver5, len(methods), methods) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infof("%d %d % d", gosocks5.Ver5, len(methods), methods) |
|
|
|
|
|
|
|
method = gosocks5.MethodNoAuth |
|
|
|
for _, m := range methods { |
|
|
|
@ -113,9 +103,7 @@ func (selector *serverSelector) Select(methods ...uint8) (method uint8) { |
|
|
|
} |
|
|
|
|
|
|
|
func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Conn, error) { |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infof("%d %d", gosocks5.Ver5, method) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infof("%d %d", gosocks5.Ver5, method) |
|
|
|
|
|
|
|
switch method { |
|
|
|
case MethodTLS: |
|
|
|
@ -128,14 +116,10 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con |
|
|
|
|
|
|
|
req, err := gosocks5.ReadUserPassRequest(conn) |
|
|
|
if err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 auth:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 auth:", err) |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(req.String()) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(req.String()) |
|
|
|
|
|
|
|
var username, password string |
|
|
|
if selector.arg.User != nil { |
|
|
|
@ -146,30 +130,21 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con |
|
|
|
if (username != "" && req.Username != username) || (password != "" && req.Password != password) { |
|
|
|
resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Failure) |
|
|
|
if err := resp.Write(conn); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 auth:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 auth:", err) |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(resp) |
|
|
|
} |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5: proxy authentication required") |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(resp) |
|
|
|
glog.V(LWARNING).Infoln("socks5: proxy authentication required") |
|
|
|
|
|
|
|
return nil, gosocks5.ErrAuthFailure |
|
|
|
} |
|
|
|
|
|
|
|
resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Succeeded) |
|
|
|
if err := resp.Write(conn); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 auth:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 auth:", err) |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(resp) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(resp) |
|
|
|
|
|
|
|
case gosocks5.MethodNoAcceptable: |
|
|
|
return nil, gosocks5.ErrBadMethod |
|
|
|
@ -179,29 +154,20 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con |
|
|
|
} |
|
|
|
|
|
|
|
func handleSocks5Request(req *gosocks5.Request, conn net.Conn) { |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(req) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(req) |
|
|
|
|
|
|
|
switch req.Cmd { |
|
|
|
case gosocks5.CmdConnect: |
|
|
|
if glog.V(LINFO) { |
|
|
|
glog.Infoln("socks5 connect:", req.Addr.String()) |
|
|
|
} |
|
|
|
glog.V(LINFO).Infoln(">>> socks5 connect:", req.Addr.String()) |
|
|
|
|
|
|
|
tconn, err := Connect(req.Addr.String()) |
|
|
|
if err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 connect:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 connect:", err) |
|
|
|
rep := gosocks5.NewReply(gosocks5.HostUnreachable, nil) |
|
|
|
if err := rep.Write(conn); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 connect:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 connect:", err) |
|
|
|
} else { |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(rep) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(rep) |
|
|
|
} |
|
|
|
return |
|
|
|
} |
|
|
|
@ -209,43 +175,31 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) { |
|
|
|
|
|
|
|
rep := gosocks5.NewReply(gosocks5.Succeeded, nil) |
|
|
|
if err := rep.Write(conn); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 connect:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 connect:", err) |
|
|
|
return |
|
|
|
} |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(rep) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(rep) |
|
|
|
|
|
|
|
Transport(conn, tconn) |
|
|
|
case gosocks5.CmdBind: |
|
|
|
if glog.V(LINFO) { |
|
|
|
glog.Infoln("socks5 bind:", req.Addr) |
|
|
|
} |
|
|
|
glog.V(LINFO).Infoln(">>> socks5 bind:", req.Addr) |
|
|
|
|
|
|
|
if len(forwardArgs) > 0 { |
|
|
|
forwardBind(req, conn) |
|
|
|
} else { |
|
|
|
serveBind(conn) |
|
|
|
} |
|
|
|
case gosocks5.CmdUdp: |
|
|
|
if glog.V(LINFO) { |
|
|
|
glog.Infoln("socks5 udp associate:", req.Addr) |
|
|
|
} |
|
|
|
glog.V(LINFO).Infoln(">>> socks5 udp associate:", req.Addr) |
|
|
|
uconn, err := net.ListenUDP("udp", nil) |
|
|
|
if err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 udp listen:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 udp listen:", err) |
|
|
|
|
|
|
|
rep := gosocks5.NewReply(gosocks5.Failure, nil) |
|
|
|
if err := rep.Write(conn); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 udp listen:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 udp listen:", err) |
|
|
|
} else { |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(rep) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(rep) |
|
|
|
} |
|
|
|
return |
|
|
|
} |
|
|
|
@ -253,160 +207,66 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) { |
|
|
|
|
|
|
|
addr := ToSocksAddr(uconn.LocalAddr()) |
|
|
|
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) |
|
|
|
if glog.V(LINFO) { |
|
|
|
glog.Infoln("socks5 udp listen:", addr) |
|
|
|
} |
|
|
|
glog.V(LINFO).Infoln("socks5 udp listen:", addr) |
|
|
|
|
|
|
|
rep := gosocks5.NewReply(gosocks5.Succeeded, addr) |
|
|
|
if err := rep.Write(conn); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 udp:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 udp:", err) |
|
|
|
return |
|
|
|
} else { |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(rep) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(rep) |
|
|
|
} |
|
|
|
|
|
|
|
//clientConn, dgram, err := createClientConn(conn, uconn)
|
|
|
|
_, dgram, err := createClientConn(conn, uconn) |
|
|
|
cc, dgram, err := createClientConn(conn, uconn) |
|
|
|
if err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 udp:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 udp:", err) |
|
|
|
return |
|
|
|
} |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infof("[udp] length %d, to %s", len(dgram.Data), dgram.Header.Addr) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infof("[udp] to %s, length %d", dgram.Header.Addr, len(dgram.Data)) |
|
|
|
|
|
|
|
//serverConn, err := createServerConn(uconn)
|
|
|
|
_, err = createServerConn(uconn) |
|
|
|
raddr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String()) |
|
|
|
if err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 udp forward:", err) |
|
|
|
} |
|
|
|
} |
|
|
|
default: |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("Unrecognized request: ", req) |
|
|
|
glog.V(LWARNING).Infoln("socks5 udp:", err) |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func createClientConn(conn net.Conn, uconn *net.UDPConn) (c *UDPConn, dgram *gosocks5.UDPDatagram, err error) { |
|
|
|
var raddr *net.UDPAddr |
|
|
|
dgramChan := make(chan *gosocks5.UDPDatagram, 1) |
|
|
|
errChan := make(chan error, 1) |
|
|
|
go func() { |
|
|
|
b := make([]byte, 64*1024+262) |
|
|
|
|
|
|
|
n, addr, err := uconn.ReadFromUDP(b) |
|
|
|
sc, err := createServerConn(uconn, raddr) |
|
|
|
if err != nil { |
|
|
|
errChan <- err |
|
|
|
glog.V(LWARNING).Infoln("socks5 udp:", err) |
|
|
|
return |
|
|
|
} |
|
|
|
raddr = addr |
|
|
|
|
|
|
|
dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n])) |
|
|
|
if err != nil { |
|
|
|
errChan <- err |
|
|
|
if err = sc.WriteUDP(dgram); err != nil { |
|
|
|
glog.V(LWARNING).Infoln("socks5 udp:", err) |
|
|
|
return |
|
|
|
} |
|
|
|
dgramChan <- dgram |
|
|
|
}() |
|
|
|
|
|
|
|
go func() { |
|
|
|
dgram, err := gosocks5.ReadUDPDatagram(conn) |
|
|
|
dgram, err = sc.ReadUDP() |
|
|
|
if err != nil { |
|
|
|
errChan <- err |
|
|
|
glog.V(LWARNING).Infoln("socks5 udp:", err) |
|
|
|
return |
|
|
|
} |
|
|
|
dgramChan <- dgram |
|
|
|
}() |
|
|
|
glog.V(LDEBUG).Infof("[udp] from %s, length %d", dgram.Header.Addr, len(dgram.Data)) |
|
|
|
|
|
|
|
select { |
|
|
|
case dgram = <-dgramChan: |
|
|
|
if raddr != nil { |
|
|
|
c = Client(uconn, raddr) |
|
|
|
} else { |
|
|
|
c = Client(conn, nil) |
|
|
|
if err = cc.WriteUDP(dgram); err != nil { |
|
|
|
glog.V(LWARNING).Infoln("socks5 udp:", err) |
|
|
|
return |
|
|
|
} |
|
|
|
case err = <-errChan: |
|
|
|
} |
|
|
|
|
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
func createServerConn(uconn *net.UDPConn) (c *UDPConn, err error) { |
|
|
|
if len(forwardArgs) == 0 { |
|
|
|
c = Server(uconn) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
fconn, _, err := forwardChain(forwardArgs...) |
|
|
|
if err != nil { |
|
|
|
if fconn != nil { |
|
|
|
fconn.Close() |
|
|
|
} |
|
|
|
return |
|
|
|
TransportUDP(cc, sc) |
|
|
|
default: |
|
|
|
glog.V(LWARNING).Infoln("Unrecognized request: ", req) |
|
|
|
} |
|
|
|
|
|
|
|
c = Server(fconn) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
func forwardUDP(req *gosocks5.Request) (conn net.Conn, err error) { |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
if conn != nil { |
|
|
|
conn.Close() |
|
|
|
} |
|
|
|
rep := gosocks5.NewReply(gosocks5.Failure, nil) |
|
|
|
if err := rep.Write(conn); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 udp forward:", err) |
|
|
|
} |
|
|
|
} else { |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(rep) |
|
|
|
} |
|
|
|
} |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
if err = req.Write(fconn); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 udp forward:", err) |
|
|
|
} |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
if err = peekReply(conn, fconn); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 udp forward:", err) |
|
|
|
} |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
*/ |
|
|
|
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) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("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) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 bind listen:", err) |
|
|
|
} else { |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(rep) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(rep) |
|
|
|
} |
|
|
|
return err |
|
|
|
} |
|
|
|
@ -414,55 +274,40 @@ func serveBind(conn net.Conn) error { |
|
|
|
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) |
|
|
|
} |
|
|
|
glog.V(LINFO).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) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 bind:", err) |
|
|
|
l.Close() |
|
|
|
return err |
|
|
|
} |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(rep) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).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) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("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) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 bind accept:", err) |
|
|
|
} else { |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(rep) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(rep) |
|
|
|
} |
|
|
|
return err |
|
|
|
} |
|
|
|
defer tconn.Close() |
|
|
|
|
|
|
|
addr = ToSocksAddr(tconn.RemoteAddr()) |
|
|
|
if glog.V(LINFO) { |
|
|
|
glog.Infoln("socks5 bind accept:", addr.String()) |
|
|
|
} |
|
|
|
glog.V(LINFO).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) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 bind accept:", err) |
|
|
|
return err |
|
|
|
} |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(rep) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(rep) |
|
|
|
|
|
|
|
return Transport(conn, tconn) |
|
|
|
} |
|
|
|
@ -475,41 +320,29 @@ func forwardBind(req *gosocks5.Request, conn net.Conn) error { |
|
|
|
} |
|
|
|
rep := gosocks5.NewReply(gosocks5.Failure, nil) |
|
|
|
if err := rep.Write(conn); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 bind forward:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 bind forward:", err) |
|
|
|
} else { |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(rep) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(rep) |
|
|
|
} |
|
|
|
return err |
|
|
|
} |
|
|
|
defer fconn.Close() |
|
|
|
|
|
|
|
if err := req.Write(fconn); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 bind forward:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 bind forward:", err) |
|
|
|
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn) |
|
|
|
return err |
|
|
|
} |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(req) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(req) |
|
|
|
|
|
|
|
// first reply
|
|
|
|
if err := peekReply(conn, fconn); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 bind forward:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 bind forward:", err) |
|
|
|
return err |
|
|
|
} |
|
|
|
// second reply
|
|
|
|
if err := peekReply(conn, fconn); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln("socks5 bind forward:", err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln("socks5 bind forward:", err) |
|
|
|
return err |
|
|
|
} |
|
|
|
|
|
|
|
@ -519,17 +352,14 @@ func forwardBind(req *gosocks5.Request, conn net.Conn) error { |
|
|
|
func peekReply(dst io.Writer, src io.Reader) error { |
|
|
|
rep, err := gosocks5.ReadReply(src) |
|
|
|
if err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln(err) |
|
|
|
} |
|
|
|
glog.V(LWARNING).Infoln(err) |
|
|
|
rep = gosocks5.NewReply(gosocks5.Failure, nil) |
|
|
|
} |
|
|
|
if err := rep.Write(dst); err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
if glog.V(LDEBUG) { |
|
|
|
glog.Infoln(rep) |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(rep) |
|
|
|
|
|
|
|
if rep.Rep != gosocks5.Succeeded { |
|
|
|
return errors.New("Failure") |
|
|
|
} |
|
|
|
@ -537,105 +367,87 @@ func peekReply(dst io.Writer, src io.Reader) error { |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
func cliTunnelUDP(uconn *net.UDPConn, sconn net.Conn) { |
|
|
|
func createClientConn(conn net.Conn, uconn *net.UDPConn) (c *UDPConn, dgram *gosocks5.UDPDatagram, err error) { |
|
|
|
var raddr *net.UDPAddr |
|
|
|
|
|
|
|
dgramChan := make(chan *gosocks5.UDPDatagram, 1) |
|
|
|
errChan := make(chan error, 1) |
|
|
|
go func() { |
|
|
|
b := make([]byte, 16*1024) |
|
|
|
for { |
|
|
|
n, addr, err := uconn.ReadFromUDP(b) |
|
|
|
if err != nil { |
|
|
|
log.Println(err) |
|
|
|
return |
|
|
|
} |
|
|
|
raddr = addr |
|
|
|
r := bytes.NewBuffer(b[:n]) |
|
|
|
udp, err := gosocks5.ReadUDPDatagram(r) |
|
|
|
if err != nil { |
|
|
|
return |
|
|
|
} |
|
|
|
udp.Header.Rsv = uint16(len(udp.Data)) |
|
|
|
//log.Println("r", raddr.String(), udp.Header)
|
|
|
|
b := make([]byte, 64*1024+262) |
|
|
|
|
|
|
|
if err := udp.Write(sconn); err != nil { |
|
|
|
log.Println(err) |
|
|
|
return |
|
|
|
} |
|
|
|
n, addr, err := uconn.ReadFromUDP(b) |
|
|
|
if err != nil { |
|
|
|
errChan <- err |
|
|
|
return |
|
|
|
} |
|
|
|
}() |
|
|
|
|
|
|
|
for { |
|
|
|
b := lpool.Take() |
|
|
|
defer lpool.put(b) |
|
|
|
raddr = addr |
|
|
|
|
|
|
|
udp, err := gosocks5.ReadUDPDatagram(sconn) |
|
|
|
dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n])) |
|
|
|
if err != nil { |
|
|
|
log.Println(err) |
|
|
|
errChan <- err |
|
|
|
return |
|
|
|
} |
|
|
|
//log.Println("w", udp.Header)
|
|
|
|
udp.Header.Rsv = 0 |
|
|
|
buf := bytes.NewBuffer(b[0:0]) |
|
|
|
udp.Write(buf) |
|
|
|
if _, err := uconn.WriteTo(buf.Bytes(), raddr); err != nil { |
|
|
|
log.Println(err) |
|
|
|
dgramChan <- dgram |
|
|
|
}() |
|
|
|
|
|
|
|
go func() { |
|
|
|
dgram, err := gosocks5.ReadUDPDatagram(conn) |
|
|
|
if err != nil { |
|
|
|
errChan <- err |
|
|
|
return |
|
|
|
} |
|
|
|
dgramChan <- dgram |
|
|
|
}() |
|
|
|
|
|
|
|
select { |
|
|
|
case dgram = <-dgramChan: |
|
|
|
if raddr != nil { |
|
|
|
c = Client(uconn, raddr) |
|
|
|
} else { |
|
|
|
c = Client(conn, nil) |
|
|
|
} |
|
|
|
case err = <-errChan: |
|
|
|
} |
|
|
|
|
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
func srvTunnelUDP(conn net.Conn, uconn *net.UDPConn) { |
|
|
|
go func() { |
|
|
|
b := make([]byte, 16*1024) |
|
|
|
|
|
|
|
for { |
|
|
|
n, addr, err := uconn.ReadFromUDP(b) |
|
|
|
if err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln(err) |
|
|
|
} |
|
|
|
return |
|
|
|
} |
|
|
|
func createServerConn(uconn *net.UDPConn, addr net.Addr) (c *UDPConn, err error) { |
|
|
|
if len(forwardArgs) == 0 { |
|
|
|
c = Server(uconn) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
udp := gosocks5.NewUDPDatagram( |
|
|
|
gosocks5.NewUDPHeader(uint16(n), 0, ToSocksAddr(addr)), b[:n]) |
|
|
|
//log.Println("r", udp.Header)
|
|
|
|
if err := udp.Write(conn); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln(err) |
|
|
|
} |
|
|
|
return |
|
|
|
} |
|
|
|
fconn, _, err := forwardChain(forwardArgs...) |
|
|
|
if err != nil { |
|
|
|
if fconn != nil { |
|
|
|
fconn.Close() |
|
|
|
} |
|
|
|
}() |
|
|
|
return |
|
|
|
} |
|
|
|
glog.V(LINFO).Infoln("forward udp associate") |
|
|
|
|
|
|
|
for { |
|
|
|
udp, err := gosocks5.ReadUDPDatagram(conn) |
|
|
|
if err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln(err) |
|
|
|
} |
|
|
|
return |
|
|
|
} |
|
|
|
//log.Println("w", udp.Header)
|
|
|
|
addr, err := net.ResolveUDPAddr("udp", udp.Header.Addr.String()) |
|
|
|
if err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln(err) |
|
|
|
} |
|
|
|
continue // drop silently
|
|
|
|
} |
|
|
|
req := gosocks5.NewRequest(gosocks5.CmdUdp, nil) |
|
|
|
if err = req.Write(fconn); err != nil { |
|
|
|
fconn.Close() |
|
|
|
return |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(req) |
|
|
|
|
|
|
|
if _, err := uconn.WriteToUDP(udp.Data, addr); err != nil { |
|
|
|
if glog.V(LWARNING) { |
|
|
|
glog.Warningln(err) |
|
|
|
} |
|
|
|
return |
|
|
|
} |
|
|
|
rep, err := gosocks5.ReadReply(fconn) |
|
|
|
if err != nil { |
|
|
|
fconn.Close() |
|
|
|
return |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infoln(rep) |
|
|
|
if rep.Rep != gosocks5.Succeeded { |
|
|
|
fconn.Close() |
|
|
|
return nil, errors.New("Failure") |
|
|
|
} |
|
|
|
|
|
|
|
c = Server(fconn) |
|
|
|
return |
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
func ToSocksAddr(addr net.Addr) *gosocks5.Addr { |
|
|
|
host, port, _ := net.SplitHostPort(addr.String()) |
|
|
|
p, _ := strconv.Atoi(port) |
|
|
|
@ -646,3 +458,40 @@ func ToSocksAddr(addr net.Addr) *gosocks5.Addr { |
|
|
|
Port: uint16(p), |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func PipeUDP(src, dst *UDPConn, ch chan<- error) { |
|
|
|
var err error |
|
|
|
|
|
|
|
for { |
|
|
|
var dgram *gosocks5.UDPDatagram |
|
|
|
dgram, err = src.ReadUDP() |
|
|
|
if err != nil { |
|
|
|
break |
|
|
|
} |
|
|
|
glog.V(LDEBUG).Infof("[udp] addr %s, length %d", dgram.Header.Addr, len(dgram.Data)) |
|
|
|
|
|
|
|
if err = dst.WriteUDP(dgram); err != nil { |
|
|
|
break |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ch <- err |
|
|
|
close(ch) |
|
|
|
} |
|
|
|
|
|
|
|
func TransportUDP(cc, sc *UDPConn) (err error) { |
|
|
|
rChan := make(chan error, 1) |
|
|
|
wChan := make(chan error, 1) |
|
|
|
|
|
|
|
go PipeUDP(cc, sc, wChan) |
|
|
|
go PipeUDP(sc, cc, rChan) |
|
|
|
|
|
|
|
select { |
|
|
|
case err = <-wChan: |
|
|
|
//log.Println("w exit", err)
|
|
|
|
case err = <-rChan: |
|
|
|
//log.Println("r exit", err)
|
|
|
|
} |
|
|
|
|
|
|
|
return |
|
|
|
} |
|
|
|
|