fix socks5 tcp bind
This commit is contained in:
parent
28089dfbc6
commit
f20ad492a7
81
conn.go
81
conn.go
@ -58,6 +58,7 @@ func listenAndServe(arg Args) error {
|
||||
return listenAndServeUdpForward(arg)
|
||||
case "rtcp": // Remote TCP port forwarding
|
||||
return serveRTcpForward(arg)
|
||||
case "rudp": // Remote UDP port forwarding
|
||||
default:
|
||||
ln, err = net.Listen("tcp", arg.Addr)
|
||||
}
|
||||
@ -78,49 +79,6 @@ 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 {
|
||||
ln, err := net.Listen("tcp", arg.Addr)
|
||||
if err != nil {
|
||||
@ -165,6 +123,31 @@ func listenAndServeUdpForward(arg Args) error {
|
||||
}
|
||||
}
|
||||
|
||||
func serveRTcpForward(arg Args) error {
|
||||
if len(forwardArgs) == 0 {
|
||||
return errors.New("rtcp: at least one -F must be assigned")
|
||||
}
|
||||
|
||||
retry := 0
|
||||
for {
|
||||
conn, _, err := forwardChain(forwardArgs...)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infof("[rtcp] %s - %s : %s", arg.Addr, arg.Remote, 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 handleConn(conn net.Conn, arg Args) {
|
||||
atomic.AddInt32(&connCounter, 1)
|
||||
glog.V(LDEBUG).Infof("%s connected, connections: %d",
|
||||
@ -207,7 +190,7 @@ func handleConn(conn net.Conn, arg Args) {
|
||||
conn = gosocks5.ServerConn(conn, selector)
|
||||
req, err := gosocks5.ReadRequest(conn)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infoln("[socks5] request:", err)
|
||||
glog.V(LWARNING).Infoln("[socks5]", err)
|
||||
return
|
||||
}
|
||||
handleSocks5Request(req, conn)
|
||||
@ -298,9 +281,6 @@ func Connect(addr string) (conn net.Conn, err error) {
|
||||
var end Args
|
||||
conn, end, err = forwardChain(forwardArgs...)
|
||||
if err != nil {
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if err := establish(conn, addr, end); err != nil {
|
||||
@ -312,6 +292,13 @@ func Connect(addr string) (conn net.Conn, err error) {
|
||||
|
||||
// establish connection throughout the forward chain
|
||||
func forwardChain(chain ...Args) (conn net.Conn, end Args, err error) {
|
||||
defer func() {
|
||||
if err != nil && conn != nil {
|
||||
conn.Close()
|
||||
conn = nil
|
||||
}
|
||||
}()
|
||||
|
||||
end = chain[0]
|
||||
if conn, err = net.DialTimeout("tcp", end.Addr, time.Second*90); err != nil {
|
||||
return
|
||||
|
189
forward.go
189
forward.go
@ -12,30 +12,30 @@ import (
|
||||
func handleTcpForward(conn net.Conn, arg Args) {
|
||||
defer conn.Close()
|
||||
|
||||
if !strings.Contains(arg.Forward, ":") {
|
||||
arg.Forward += ":22" // default is ssh service
|
||||
if !strings.Contains(arg.Remote, ":") {
|
||||
arg.Remote += ":22" // default is ssh service
|
||||
}
|
||||
glog.V(LINFO).Infof("[tcp-forward] %s - %s", conn.RemoteAddr(), arg.Forward)
|
||||
c, err := Connect(arg.Forward)
|
||||
glog.V(LINFO).Infof("[tcp-forward] %s - %s", conn.RemoteAddr(), arg.Remote)
|
||||
c, err := Connect(arg.Remote)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infof("[tcp-forward] %s -> %s : %s", conn.RemoteAddr(), arg.Forward, err)
|
||||
glog.V(LWARNING).Infof("[tcp-forward] %s -> %s : %s", conn.RemoteAddr(), arg.Remote, err)
|
||||
return
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
glog.V(LINFO).Infof("[tcp-forward] %s <-> %s", conn.RemoteAddr(), arg.Forward)
|
||||
glog.V(LINFO).Infof("[tcp-forward] %s <-> %s", conn.RemoteAddr(), arg.Remote)
|
||||
Transport(conn, c)
|
||||
glog.V(LINFO).Infof("[tcp-forward] %s >-< %s", conn.RemoteAddr(), arg.Forward)
|
||||
glog.V(LINFO).Infof("[tcp-forward] %s >-< %s", conn.RemoteAddr(), arg.Remote)
|
||||
}
|
||||
|
||||
func handleUdpForward(conn *net.UDPConn, raddr *net.UDPAddr, data []byte, arg Args) {
|
||||
if !strings.Contains(arg.Forward, ":") {
|
||||
arg.Forward += ":53" // default is dns service
|
||||
if !strings.Contains(arg.Remote, ":") {
|
||||
arg.Remote += ":53" // default is dns service
|
||||
}
|
||||
|
||||
faddr, err := net.ResolveUDPAddr("udp", arg.Forward)
|
||||
faddr, err := net.ResolveUDPAddr("udp", arg.Remote)
|
||||
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.Remote, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -44,235 +44,136 @@ func handleUdpForward(conn *net.UDPConn, raddr *net.UDPAddr, data []byte, arg Ar
|
||||
if len(forwardArgs) == 0 {
|
||||
lconn, err := net.ListenUDP("udp", 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.Remote, err)
|
||||
return
|
||||
}
|
||||
defer lconn.Close()
|
||||
|
||||
if _, err := lconn.WriteToUDP(data, faddr); 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.Remote, err)
|
||||
return
|
||||
}
|
||||
glog.V(LDEBUG).Infof("[udp-forward] %s >>> %s length %d", raddr, arg.Forward, len(data))
|
||||
glog.V(LDEBUG).Infof("[udp-forward] %s >>> %s length %d", raddr, arg.Remote, len(data))
|
||||
|
||||
b := udpPool.Get().([]byte)
|
||||
defer udpPool.Put(b)
|
||||
lconn.SetReadDeadline(time.Now().Add(time.Second * 60))
|
||||
n, addr, err := lconn.ReadFromUDP(b)
|
||||
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.Remote, err)
|
||||
return
|
||||
}
|
||||
glog.V(LDEBUG).Infof("[udp-forward] %s <<< %s length %d", raddr, addr, n)
|
||||
|
||||
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.Remote, err)
|
||||
}
|
||||
glog.V(LINFO).Infof("[udp-forward] %s >-< %s", raddr, arg.Forward)
|
||||
glog.V(LINFO).Infof("[udp-forward] %s >-< %s", raddr, arg.Remote)
|
||||
return
|
||||
}
|
||||
|
||||
fconn, _, err := forwardChain(forwardArgs...)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
|
||||
if fconn != nil {
|
||||
fconn.Close()
|
||||
}
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Remote, err)
|
||||
return
|
||||
}
|
||||
defer fconn.Close()
|
||||
|
||||
glog.V(LINFO).Infof("[udp-forward] %s -> %s ASSOCIATE", raddr, arg.Forward)
|
||||
glog.V(LINFO).Infof("[udp-forward] %s -> %s ASSOCIATE", raddr, arg.Remote)
|
||||
|
||||
req := gosocks5.NewRequest(CmdUdpTun, nil)
|
||||
if err = req.Write(fconn); err != nil {
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s -> %s ASSOCIATE : %s", raddr, arg.Forward, err)
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s -> %s ASSOCIATE : %s", raddr, arg.Remote, err)
|
||||
return
|
||||
}
|
||||
glog.V(LDEBUG).Infof("[udp-forward] %s -> %s\n%s", raddr, arg.Forward, req)
|
||||
glog.V(LDEBUG).Infof("[udp-forward] %s -> %s\n%s", raddr, arg.Remote, req)
|
||||
|
||||
rep, err := gosocks5.ReadReply(fconn)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s <- %s ASSOCIATE : %s", raddr, arg.Forward, err)
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s <- %s ASSOCIATE : %s", raddr, arg.Remote, err)
|
||||
return
|
||||
}
|
||||
glog.V(LDEBUG).Infof("[udp-forward] %s <- %s\n%s", raddr, arg.Forward, rep)
|
||||
glog.V(LDEBUG).Infof("[udp-forward] %s <- %s\n%s", raddr, arg.Remote, rep)
|
||||
if rep.Rep != gosocks5.Succeeded {
|
||||
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.Remote)
|
||||
return
|
||||
}
|
||||
glog.V(LINFO).Infof("[udp-forward] %s <-> %s ASSOCIATE ON %s", raddr, arg.Forward, rep.Addr)
|
||||
glog.V(LINFO).Infof("[udp-forward] %s <-> %s ASSOCIATE ON %s", raddr, arg.Remote, rep.Addr)
|
||||
|
||||
dgram := gosocks5.NewUDPDatagram(
|
||||
gosocks5.NewUDPHeader(uint16(len(data)), 0, ToSocksAddr(faddr)), data)
|
||||
|
||||
fconn.SetWriteDeadline(time.Now().Add(time.Second * 90))
|
||||
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.Remote, err)
|
||||
return
|
||||
}
|
||||
glog.V(LDEBUG).Infof("[udp-forward] %s >>> %s length %d", raddr, arg.Forward, len(data))
|
||||
glog.V(LDEBUG).Infof("[udp-forward] %s >>> %s length %d", raddr, arg.Remote, len(data))
|
||||
|
||||
fconn.SetReadDeadline(time.Now().Add(time.Second * 90))
|
||||
dgram, err = gosocks5.ReadUDPDatagram(fconn)
|
||||
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.Remote, err)
|
||||
return
|
||||
}
|
||||
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 {
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Remote, err)
|
||||
}
|
||||
|
||||
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())
|
||||
glog.V(LINFO).Infof("[udp-forward] %s >-< %s", raddr, arg.Remote)
|
||||
}
|
||||
|
||||
func connectRTcpForward(conn net.Conn, arg Args) error {
|
||||
glog.V(LINFO).Infof("[rtcp] %s - %s", arg.Addr, arg.Forward)
|
||||
glog.V(LINFO).Infof("[rtcp] %s - %s", arg.Addr, arg.Remote)
|
||||
|
||||
addr, _ := net.ResolveTCPAddr("tcp", arg.Bind)
|
||||
addr, _ := net.ResolveTCPAddr("tcp", arg.Addr)
|
||||
req := gosocks5.NewRequest(gosocks5.CmdBind, ToSocksAddr(addr))
|
||||
bindAddr := req.Addr
|
||||
if err := req.Write(conn); err != nil {
|
||||
glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", arg.Addr, arg.Forward, err)
|
||||
glog.V(LWARNING).Infof("[rtcp] %s <- %s : %s", bindAddr, arg.Remote, 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)
|
||||
glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", bindAddr, arg.Remote, 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(LWARNING).Infof("[rtcp] %s -> %s : bind on %s failure", bindAddr, arg.Remote, arg.Addr)
|
||||
return errors.New("Bind on " + arg.Addr + " failure")
|
||||
}
|
||||
glog.V(LINFO).Infof("[rtcp] %s - %s BIND ON %s OK", arg.Addr, arg.Forward, arg.Bind)
|
||||
glog.V(LINFO).Infof("[rtcp] %s - %s BIND ON %s OK", bindAddr, arg.Remote, rep.Addr)
|
||||
|
||||
// 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)
|
||||
glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", bindAddr, arg.Remote, err)
|
||||
return err
|
||||
}
|
||||
if rep.Rep != gosocks5.Succeeded {
|
||||
glog.V(LWARNING).Infof("[rtcp] %s <- %s : peer connect failure", arg.Addr, arg.Forward)
|
||||
glog.V(LWARNING).Infof("[rtcp] %s -> %s : peer connect failure", bindAddr, arg.Remote)
|
||||
return errors.New("peer connect failure")
|
||||
}
|
||||
|
||||
glog.V(LINFO).Infof("[rtcp] %s <- %s PEER %s CONNECTED", conn.RemoteAddr(), req.Addr, rep.Addr)
|
||||
glog.V(LINFO).Infof("[rtcp] %s -> %s PEER %s CONNECTED", bindAddr, arg.Remote, rep.Addr)
|
||||
|
||||
go func() {
|
||||
defer conn.Close()
|
||||
|
||||
lconn, err := net.Dial("tcp", arg.Addr)
|
||||
lconn, err := net.Dial("tcp", arg.Remote)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infof("[rtcp] %s <- %s : %s", arg.Addr, arg.Forward, err)
|
||||
glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", rep.Addr, lconn.RemoteAddr(), 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)
|
||||
glog.V(LINFO).Infof("[rtcp] %s <-> %s", rep.Addr, lconn.RemoteAddr())
|
||||
Transport(lconn, conn)
|
||||
glog.V(LINFO).Infof("[rtcp] %s >-< %s", arg.Addr, arg.Forward)
|
||||
glog.V(LINFO).Infof("[rtcp] %s >-< %s", rep.Addr, lconn.RemoteAddr())
|
||||
}()
|
||||
|
||||
return nil
|
||||
|
3
main.go
3
main.go
@ -45,8 +45,7 @@ func main() {
|
||||
return
|
||||
}
|
||||
if pv {
|
||||
fmt.Fprintln(os.Stderr, "gost", Version)
|
||||
fmt.Fprintln(os.Stderr, runtime.Version())
|
||||
fmt.Fprintf(os.Stderr, "gost %s (%s)\n", Version, runtime.Version())
|
||||
return
|
||||
}
|
||||
|
||||
|
205
socks.go
205
socks.go
@ -192,18 +192,67 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
||||
glog.V(LINFO).Infof("[socks5-connect] %s <-> %s", conn.RemoteAddr(), req.Addr)
|
||||
Transport(conn, tconn)
|
||||
glog.V(LINFO).Infof("[socks5-connect] %s >-< %s", conn.RemoteAddr(), req.Addr)
|
||||
|
||||
case gosocks5.CmdBind:
|
||||
glog.V(LINFO).Infof("[socks5-bind] %s - %s", conn.RemoteAddr(), req.Addr)
|
||||
|
||||
if len(forwardArgs) > 0 {
|
||||
forwardBind(req, conn)
|
||||
} else {
|
||||
tc := conn.(*net.TCPConn)
|
||||
tc.SetKeepAlive(true)
|
||||
tc.SetKeepAlivePeriod(time.Second * 60)
|
||||
|
||||
serveBind(req, conn)
|
||||
reply, fconn, err := socks5Bind(req, conn)
|
||||
if reply != nil {
|
||||
if err := reply.Write(conn); err != nil {
|
||||
glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
if fconn != nil {
|
||||
fconn.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, reply)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infof("[socks5-bind] %s - %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
return
|
||||
}
|
||||
defer fconn.Close()
|
||||
|
||||
glog.V(LINFO).Infof("[socks5-bind] %s <-> %s", conn.RemoteAddr(), fconn.RemoteAddr())
|
||||
Transport(conn, fconn)
|
||||
glog.V(LINFO).Infof("[socks5-bind] %s >-< %s", conn.RemoteAddr(), fconn.RemoteAddr())
|
||||
|
||||
/*
|
||||
case gosocks5.CmdUdp:
|
||||
case CmdUdpTun:
|
||||
glog.V(LINFO).Infof("[socks5-udp] %s - %s ASSOCIATE", conn.RemoteAddr(), req.Addr)
|
||||
if len(forwardArgs) > 0 { // direct forward
|
||||
fconn, _, err := forwardChain(forwardArgs...)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infof("[socks5-udp] %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("[socks5-udp] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
} else {
|
||||
glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
|
||||
}
|
||||
return
|
||||
}
|
||||
defer fconn.Close()
|
||||
if err := req.Write(fconn); err != nil {
|
||||
glog.V(LWARNING).Infof("[socks5-udp] %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("[socks5-udp] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
} else {
|
||||
glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", conn.RemoteAddr(), req.Addr)
|
||||
Transport(conn, fconn)
|
||||
glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", conn.RemoteAddr(), req.Addr)
|
||||
} else {
|
||||
|
||||
}
|
||||
*/
|
||||
case gosocks5.CmdUdp, CmdUdpTun:
|
||||
// TODO: udp tunnel <-> forward chain
|
||||
glog.V(LINFO).Infof("[socks5-udp] %s - %s ASSOCIATE", conn.RemoteAddr(), req.Addr)
|
||||
@ -296,35 +345,35 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
||||
}
|
||||
}
|
||||
|
||||
func serveBind(req *gosocks5.Request, conn net.Conn) error {
|
||||
func socks5Bind(req *gosocks5.Request, conn net.Conn) (*gosocks5.Reply, net.Conn, error) {
|
||||
if len(forwardArgs) > 0 {
|
||||
fconn, _, err := forwardChain(forwardArgs...)
|
||||
if err != nil {
|
||||
return gosocks5.NewReply(gosocks5.Failure, nil), nil, err
|
||||
}
|
||||
|
||||
if err := req.Write(fconn); err != nil {
|
||||
fconn.Close()
|
||||
return gosocks5.NewReply(gosocks5.Failure, nil), nil, err
|
||||
}
|
||||
|
||||
return nil, fconn, nil
|
||||
}
|
||||
|
||||
bindAddr, _ := net.ResolveTCPAddr("tcp", req.Addr.String())
|
||||
ln, err := net.ListenTCP("tcp", bindAddr)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infof("[socks5-bind] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
if bindAddr != nil {
|
||||
ln, err = net.ListenTCP("tcp", nil)
|
||||
}
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infof("[socks5-bind] %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("[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 gosocks5.NewReply(gosocks5.Failure, nil), nil, err
|
||||
}
|
||||
|
||||
addr := ToSocksAddr(ln.Addr())
|
||||
// Issue: may not reachable when host has two interfaces
|
||||
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
||||
|
||||
rep := gosocks5.NewReply(gosocks5.Succeeded, addr)
|
||||
if err := rep.Write(conn); err != nil {
|
||||
glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
ln.Close()
|
||||
return err
|
||||
return nil, nil, err
|
||||
}
|
||||
glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
|
||||
glog.V(LINFO).Infof("[socks5-bind] %s - %s BIND ON %s OK", conn.RemoteAddr(), req.Addr, addr)
|
||||
@ -342,7 +391,9 @@ func serveBind(req *gosocks5.Request, conn net.Conn) error {
|
||||
peerChan := make(chan error, 1)
|
||||
go func() {
|
||||
defer close(peerChan)
|
||||
_, err := ioutil.ReadAll(conn)
|
||||
b := tcpPool.Get().([]byte)
|
||||
defer tcpPool.Put(b)
|
||||
_, err := conn.Read(b)
|
||||
if err != nil {
|
||||
if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
|
||||
return
|
||||
@ -358,14 +409,8 @@ func serveBind(req *gosocks5.Request, conn net.Conn) error {
|
||||
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)
|
||||
return gosocks5.NewReply(gosocks5.Failure, nil), nil, errors.New("[socks5-bind] accept error")
|
||||
}
|
||||
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
|
||||
@ -378,98 +423,23 @@ func serveBind(req *gosocks5.Request, conn net.Conn) error {
|
||||
if pconn != nil {
|
||||
pconn.Close()
|
||||
}
|
||||
glog.V(LWARNING).Infof("[socks5-bind] %s >-< %s", conn.RemoteAddr(), addr)
|
||||
return err
|
||||
if err == nil {
|
||||
err = errors.New("Oops, some mysterious error!")
|
||||
}
|
||||
return nil, nil, err
|
||||
}
|
||||
goto out
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
defer pconn.Close()
|
||||
conn.SetReadDeadline(time.Time{})
|
||||
|
||||
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 {
|
||||
glog.V(LWARNING).Infof("[socks5 bind] %s <- %s : %s", conn.RemoteAddr(), addr, err)
|
||||
return err
|
||||
}
|
||||
glog.V(LDEBUG).Infof("[socks5 bind] %s <- %s\n%s", conn.RemoteAddr(), addr, rep)
|
||||
|
||||
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)
|
||||
glog.V(LINFO).Infof("[socks5-bind] %s <- %s PEER %s ACCEPTED", conn.RemoteAddr(), addr, pconn.RemoteAddr())
|
||||
rep = gosocks5.NewReply(gosocks5.Succeeded, ToSocksAddr(pconn.RemoteAddr()))
|
||||
return rep, pconn, nil
|
||||
}
|
||||
|
||||
func forwardBind(req *gosocks5.Request, conn net.Conn) error {
|
||||
fconn, _, err := forwardChain(forwardArgs...)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infof("[socks5-bind] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
if fconn != nil {
|
||||
fconn.Close()
|
||||
}
|
||||
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
|
||||
}
|
||||
defer fconn.Close()
|
||||
|
||||
if err := req.Write(fconn); err != nil {
|
||||
glog.V(LWARNING).Infoln("[socks5-bind] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn)
|
||||
return err
|
||||
}
|
||||
glog.V(LDEBUG).Infof("[socks5-bind] %s -> %s\n%s", conn.RemoteAddr(), req.Addr, req)
|
||||
|
||||
/*
|
||||
// first reply
|
||||
rep, err := peekReply(conn, fconn)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infoln("[socks5] BIND forward", err)
|
||||
return err
|
||||
}
|
||||
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)
|
||||
*/
|
||||
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)
|
||||
}
|
||||
|
||||
/*
|
||||
func peekReply(dst, src net.Conn) (rep *gosocks5.Reply, err error) {
|
||||
rep, err = gosocks5.ReadReply(src)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infof("[socks5-bind] FORWARD %s <- : %s", dst.RemoteAddr(), err)
|
||||
rep = gosocks5.NewReply(gosocks5.Failure, nil)
|
||||
}
|
||||
if err = rep.Write(dst); err != nil {
|
||||
return
|
||||
}
|
||||
glog.V(LDEBUG).Infof("[socks5-bind] FORWARD %s <-\n%s", dst.RemoteAddr(), rep)
|
||||
|
||||
if rep.Rep != gosocks5.Succeeded {
|
||||
err = errors.New("Failure")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
*/
|
||||
|
||||
func createServerConn(uconn *net.UDPConn) (c *UDPConn, err error) {
|
||||
if len(forwardArgs) == 0 {
|
||||
c = Server(uconn)
|
||||
@ -478,9 +448,6 @@ func createServerConn(uconn *net.UDPConn) (c *UDPConn, err error) {
|
||||
|
||||
fconn, _, err := forwardChain(forwardArgs...)
|
||||
if err != nil {
|
||||
if fconn != nil {
|
||||
fconn.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
glog.V(LINFO).Infoln("[udp] forward associate")
|
||||
@ -509,7 +476,7 @@ func createServerConn(uconn *net.UDPConn) (c *UDPConn, err error) {
|
||||
}
|
||||
|
||||
func ToSocksAddr(addr net.Addr) *gosocks5.Addr {
|
||||
host := ""
|
||||
host := "0.0.0.0"
|
||||
port := 0
|
||||
if addr != nil {
|
||||
h, p, _ := net.SplitHostPort(addr.String())
|
||||
|
17
util.go
17
util.go
@ -25,8 +25,7 @@ type Args struct {
|
||||
Addr string // host:port
|
||||
Protocol string // protocol: http/socks(5)/ss
|
||||
Transport string // transport: ws(s)/tls/tcp/udp/rtcp/rudp
|
||||
Forward string // forward address, used by local tcp/udp port forwarding
|
||||
Bind string // remote binding port, used by remote tcp/udp port forwarding
|
||||
Remote string // remote address, used by tcp/udp port forwarding
|
||||
User *url.Userinfo // authentication for proxy
|
||||
Cert tls.Certificate // tls certificate
|
||||
}
|
||||
@ -37,8 +36,8 @@ func (args Args) String() string {
|
||||
authUser = args.User.Username()
|
||||
authPass, _ = args.User.Password()
|
||||
}
|
||||
return fmt.Sprintf("host: %s, protocol: %s, transport: %s, forward: %s, auth: %s/%s",
|
||||
args.Addr, args.Protocol, args.Transport, args.Forward, authUser, authPass)
|
||||
return fmt.Sprintf("host: %s, protocol: %s, transport: %s, remote: %s, auth: %s/%s",
|
||||
args.Addr, args.Protocol, args.Transport, args.Remote, authUser, authPass)
|
||||
}
|
||||
|
||||
func parseArgs(ss []string) (args []Args) {
|
||||
@ -77,13 +76,9 @@ func parseArgs(ss []string) (args []Args) {
|
||||
switch arg.Transport {
|
||||
case "ws", "wss", "tls":
|
||||
case "tcp", "udp": // started from v2.1, tcp and udp are for local port forwarding
|
||||
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)
|
||||
}
|
||||
arg.Remote = strings.Trim(u.EscapedPath(), "/")
|
||||
case "rtcp", "rudp": // started from v2.1, rtcp and rudp are for remote port forwarding
|
||||
arg.Remote = strings.Trim(u.EscapedPath(), "/")
|
||||
default:
|
||||
arg.Transport = ""
|
||||
}
|
||||
|
5
ws.go
5
ws.go
@ -112,12 +112,13 @@ func NewWs(arg Args) *ws {
|
||||
}
|
||||
|
||||
func (s *ws) handle(w http.ResponseWriter, r *http.Request) {
|
||||
glog.V(LINFO).Infoln("[ws] %s - %s", r.RemoteAddr, s.arg.Addr)
|
||||
if glog.V(LDEBUG) {
|
||||
dump, err := httputil.DumpRequest(r, false)
|
||||
if err != nil {
|
||||
glog.Infoln(err)
|
||||
glog.V(LWARNING).Infoln("[ws] %s - %s : %s", r.RemoteAddr, s.arg.Addr, err)
|
||||
} else {
|
||||
glog.Infoln(string(dump))
|
||||
glog.V(LDEBUG).Infoln("[ws] %s - %s\n%s", r.RemoteAddr, s.arg.Addr, string(dump))
|
||||
}
|
||||
}
|
||||
conn, err := s.upgrader.Upgrade(w, r, nil)
|
||||
|
Loading…
Reference in New Issue
Block a user