fix socks5 bind

This commit is contained in:
rui.zheng 2016-10-06 13:50:41 +08:00
parent 0991952f0c
commit 538e5ba977
2 changed files with 65 additions and 66 deletions

View File

@ -61,7 +61,7 @@ func (s *HttpServer) HandleRequest(req *http.Request) {
return return
} }
// TODO: forward http request // forward http request
lastNode := s.Base.Chain.lastNode lastNode := s.Base.Chain.lastNode
if lastNode != nil && (lastNode.Protocol == "http" || lastNode.Protocol == "") { if lastNode != nil && (lastNode.Protocol == "http" || lastNode.Protocol == "") {
s.forwardRequest(req) s.forwardRequest(req)

115
socks.go
View File

@ -3,7 +3,7 @@ package gost
import ( import (
"bytes" "bytes"
"crypto/tls" "crypto/tls"
"errors" //"errors"
"github.com/ginuerzh/gosocks5" "github.com/ginuerzh/gosocks5"
"github.com/golang/glog" "github.com/golang/glog"
//"os/exec" //"os/exec"
@ -174,7 +174,7 @@ func NewSocks5Server(conn net.Conn, base *ProxyServer) *Socks5Server {
} }
func (s *Socks5Server) HandleRequest(req *gosocks5.Request) { func (s *Socks5Server) HandleRequest(req *gosocks5.Request) {
glog.V(LDEBUG).Infof("[socks5] %s - %s\n%s", s.conn.RemoteAddr(), req.Addr, req) glog.V(LDEBUG).Infof("[socks5] %s -> %s\n%s", s.conn.RemoteAddr(), req.Addr, req)
switch req.Cmd { switch req.Cmd {
case gosocks5.CmdConnect: case gosocks5.CmdConnect:
@ -228,10 +228,7 @@ func (s *Socks5Server) handleConnect(req *gosocks5.Request) {
func (s *Socks5Server) handleBind(req *gosocks5.Request) { func (s *Socks5Server) handleBind(req *gosocks5.Request) {
cc, err := s.Base.Chain.GetConn() cc, err := s.Base.Chain.GetConn()
// forward request
if err == nil {
req.Write(cc)
}
// connection error // connection error
if err != nil && err != ErrEmptyChain { if err != nil && err != ErrEmptyChain {
glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err) glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err)
@ -242,17 +239,13 @@ func (s *Socks5Server) handleBind(req *gosocks5.Request) {
} }
// serve socks5 bind // serve socks5 bind
if err == ErrEmptyChain { if err == ErrEmptyChain {
cc, err = s.bind(req.Addr.String()) s.bindOn(req.Addr.String())
if err != nil {
glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err)
reply := gosocks5.NewReply(gosocks5.Failure, nil)
reply.Write(s.conn)
glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", s.conn.RemoteAddr(), req.Addr, reply)
return return
} }
}
defer cc.Close() defer cc.Close()
// forward request
req.Write(cc)
glog.V(LINFO).Infof("[socks5-bind] %s <-> %s", s.conn.RemoteAddr(), cc.RemoteAddr()) glog.V(LINFO).Infof("[socks5-bind] %s <-> %s", s.conn.RemoteAddr(), cc.RemoteAddr())
s.Base.transport(s.conn, cc) s.Base.transport(s.conn, cc)
@ -422,11 +415,13 @@ func (s *Socks5Server) handleUDPTunnel(req *gosocks5.Request) {
glog.V(LINFO).Infof("[socks5-udp] %s >-< %s [tun]", s.conn.RemoteAddr(), cc.RemoteAddr()) glog.V(LINFO).Infof("[socks5-udp] %s >-< %s [tun]", s.conn.RemoteAddr(), cc.RemoteAddr())
} }
func (s *Socks5Server) bind(addr string) (net.Conn, error) { func (s *Socks5Server) bindOn(addr string) {
bindAddr, _ := net.ResolveTCPAddr("tcp", addr) bindAddr, _ := net.ResolveTCPAddr("tcp", addr)
ln, err := net.ListenTCP("tcp", bindAddr) // strict mode: if the port already in use, it will return error ln, err := net.ListenTCP("tcp", bindAddr) // strict mode: if the port already in use, it will return error
if err != nil { if err != nil {
return nil, err glog.V(LWARNING).Infof("[socks5-bind] %s -> %s : %s", s.conn.RemoteAddr(), addr, err)
gosocks5.NewReply(gosocks5.Failure, nil).Write(s.conn)
return
} }
socksAddr := ToSocksAddr(ln.Addr()) socksAddr := ToSocksAddr(ln.Addr())
@ -436,70 +431,74 @@ func (s *Socks5Server) bind(addr string) (net.Conn, error) {
if err := reply.Write(s.conn); err != nil { if err := reply.Write(s.conn); err != nil {
glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), addr, err) glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), addr, err)
ln.Close() ln.Close()
return nil, err return
} }
glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", s.conn.RemoteAddr(), addr, reply) glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", s.conn.RemoteAddr(), addr, reply)
glog.V(LINFO).Infof("[socks5-bind] %s - %s BIND ON %s OK", s.conn.RemoteAddr(), addr, socksAddr) glog.V(LINFO).Infof("[socks5-bind] %s - %s BIND ON %s OK", s.conn.RemoteAddr(), addr, socksAddr)
lnChan := make(chan net.Conn, 1) var pconn net.Conn
accept := func() <-chan error {
errc := make(chan error, 1)
go func() { go func() {
defer close(lnChan) defer close(errc)
defer ln.Close()
c, err := ln.AcceptTCP() c, err := ln.AcceptTCP()
if err != nil { if err != nil {
errc <- err
return return
} }
lnChan <- c pconn = c
}() }()
peerChan := make(chan error, 1) return errc
}
pc1, pc2 := net.Pipe()
pipe := func() <-chan error {
errc := make(chan error, 1)
go func() { go func() {
defer close(peerChan) defer close(errc)
b := make([]byte, SmallBufferSize) defer pc1.Close()
_, err := s.conn.Read(b)
if err != nil { errc <- s.Base.transport(s.conn, pc1)
if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
return
}
peerChan <- err
}
}() }()
var pconn net.Conn return errc
}
defer pc2.Close()
for { for {
select { select {
case c := <-lnChan: case err := <-accept():
ln.Close() // only accept one peer
if c == nil {
return nil, errors.New("accept error")
}
pconn = c
lnChan = nil
ln = nil
// TODO: implement deadline
s.conn.SetReadDeadline(time.Now()) // timeout right now ,so we can break out of blocking
case err := <-peerChan:
if err != nil || pconn == nil { if err != nil || pconn == nil {
if ln != nil { glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), addr, err)
ln.Close() return
}
if pconn != nil {
pconn.Close()
}
if err == nil {
err = errors.New("Oops, some mysterious error!")
}
return nil, err
}
goto out
}
} }
defer pconn.Close()
out: reply := gosocks5.NewReply(gosocks5.Succeeded, ToSocksAddr(pconn.RemoteAddr()))
s.conn.SetReadDeadline(time.Time{}) if err := reply.Write(pc2); err != nil {
glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), addr, err)
}
glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", s.conn.RemoteAddr(), addr, reply)
glog.V(LINFO).Infof("[socks5-bind] %s <- %s PEER %s ACCEPTED", s.conn.RemoteAddr(), socksAddr, pconn.RemoteAddr()) glog.V(LINFO).Infof("[socks5-bind] %s <- %s PEER %s ACCEPTED", s.conn.RemoteAddr(), socksAddr, pconn.RemoteAddr())
return pconn, nil
glog.V(LINFO).Infof("[socks5-bind] %s <-> %s", s.conn.RemoteAddr(), pconn.RemoteAddr())
if err = s.Base.transport(pc2, pconn); err != nil {
glog.V(LWARNING).Infoln(err)
}
glog.V(LINFO).Infof("[socks5-bind] %s >-< %s", s.conn.RemoteAddr(), pconn.RemoteAddr())
return
case err := <-pipe():
glog.V(LWARNING).Infof("[socks5-bind] %s -> %s : %s", s.conn.RemoteAddr(), addr, err)
ln.Close()
return
}
}
} }
func (s *Socks5Server) udpConnect(addr string) { func (s *Socks5Server) udpConnect(addr string) {