修复「接入网关」无法使用的问题 fixed #207 #218

This commit is contained in:
dushixiang
2022-01-23 22:42:47 +08:00
parent a1a9ca2596
commit 809118f3e9
15 changed files with 83 additions and 53 deletions

View File

@ -3,6 +3,7 @@ package api
import (
"context"
"errors"
"fmt"
"net/http"
"path"
"strconv"
@ -105,14 +106,9 @@ func (api GuacamoleApi) Guacamole(c echo.Context) error {
utils.Disconnect(ws, AccessGatewayCreateError, "创建SSH隧道失败"+err.Error())
return nil
}
defer g.CloseSshTunnel(s.ID)
ip = exposedIP
port = exposedPort
}
active, err := utils.Tcping(ip, port)
if !active {
utils.Disconnect(ws, AssetNotActive, "目标资产不在线: "+err.Error())
return nil
defer g.CloseSshTunnel(s.ID)
}
configuration.SetParameter("hostname", ip)
@ -135,14 +131,15 @@ func (api GuacamoleApi) Guacamole(c echo.Context) error {
}
addr := config.GlobalCfg.Guacd.Hostname + ":" + strconv.Itoa(config.GlobalCfg.Guacd.Port)
log.Debugf("[%v:%v] 创建guacd隧道[%v]", sessionId, connectionId, addr)
asset := fmt.Sprintf("%s:%s", configuration.GetParameter("hostname"), configuration.GetParameter("port"))
log.Debugf("[%v] 新建 guacd 会话, guacd=%v, asset=%v", sessionId, addr, asset)
guacdTunnel, err := guacd.NewTunnel(addr, configuration)
if err != nil {
if connectionId == "" {
utils.Disconnect(ws, NewTunnelError, err.Error())
}
log.Printf("[%v:%v] 建立连接失败: %v", sessionId, connectionId, err.Error())
log.Printf("[%v] 建立连接失败: %v", sessionId, err.Error())
return err
}
@ -164,7 +161,7 @@ func (api GuacamoleApi) Guacamole(c echo.Context) error {
nextSession.Observer = session.NewObserver(sessionId)
session.GlobalSessionManager.Add <- nextSession
go nextSession.Observer.Run()
go nextSession.Observer.Start()
sess := model.Session{
ConnectionId: guacdTunnel.UUID,
Width: intWidth,
@ -177,7 +174,7 @@ func (api GuacamoleApi) Guacamole(c echo.Context) error {
sess.Reviewed = true
}
// 创建新会话
log.Debugf("[%v:%v] 创建新会话: %v", sessionId, connectionId, sess.ConnectionId)
log.Debugf("[%v] 新建会话成功: %v", sessionId, sess.ConnectionId)
if err := repository.SessionRepository.UpdateById(ctx, &sess, sessionId); err != nil {
return err
}
@ -199,7 +196,7 @@ func (api GuacamoleApi) Guacamole(c echo.Context) error {
for {
_, message, err := ws.ReadMessage()
if err != nil {
log.Debugf("[%v:%v] WebSocket已关闭", sessionId, connectionId)
log.Debugf("[%v:%v] WebSocket已关闭, %v", sessionId, connectionId, err.Error())
// guacdTunnel.Read() 会阻塞所以要先把guacdTunnel客户端关闭才能退出Guacd循环
_ = guacdTunnel.Close()

View File

@ -152,7 +152,7 @@ func (api WebTerminalApi) SshEndpoint(c echo.Context) error {
NextTerminal: nextTerminal,
Observer: session.NewObserver(s.ID),
}
go nextSession.Observer.Run()
go nextSession.Observer.Start()
session.GlobalSessionManager.Add <- nextSession
termHandler := NewTermHandler(sessionId, isRecording, ws, nextTerminal)

View File

@ -1,26 +1,56 @@
package app
import (
"io/fs"
"net/http"
"os"
"next-terminal/server/api"
"next-terminal/server/config"
"next-terminal/server/log"
"next-terminal/server/resource"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func getFS(useOS bool) fs.FS {
if useOS {
log.Debug("using live mode")
return os.DirFS("web/build")
}
log.Debug("using embed mode")
fsys, err := fs.Sub(resource.Resource, "build")
if err != nil {
panic(err)
}
return fsys
}
func WrapHandler(h http.Handler) echo.HandlerFunc {
return func(c echo.Context) error {
c.Response().Header().Set("Cache-Control", `public, max-age=31536000`)
h.ServeHTTP(c.Response(), c.Request())
return nil
}
}
func setupRoutes() *echo.Echo {
e := echo.New()
e.HideBanner = true
//e.Logger = log.GetEchoLogger()
//e.Use(log.Hook())
e.File("/", "web/build/index.html")
e.File("/asciinema.html", "web/build/asciinema.html")
e.File("/", "web/build/index.html")
e.File("/favicon.ico", "web/build/favicon.ico")
e.File("/logo.png", "web/build/logo.png")
e.Static("/static", "web/build/static")
fsys := getFS(config.GlobalCfg.Debug)
fileServer := http.FileServer(http.FS(fsys))
handler := WrapHandler(fileServer)
e.GET("/", handler)
e.GET("/asciinema.html", handler)
e.GET("/favicon.ico", handler)
e.GET("/static/*", handler)
e.Use(middleware.Recover())
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{

View File

@ -44,7 +44,7 @@ func (g *Gateway) Run() {
select {
case t := <-g.Add:
g.tunnels[t.ID] = t
go t.Run()
go t.Open()
case k := <-g.Del:
if _, ok := g.tunnels[k]; ok {
g.tunnels[k].Close()

View File

@ -15,7 +15,7 @@ func NewManager() *Manager {
}
}
func (m *Manager) Run() {
func (m *Manager) Start() {
for {
select {
case g := <-m.Add:
@ -38,5 +38,5 @@ var GlobalGatewayManager *Manager
func init() {
GlobalGatewayManager = NewManager()
go GlobalGatewayManager.Run()
go GlobalGatewayManager.Start()
}

View File

@ -22,36 +22,35 @@ type Tunnel struct {
err error
}
func (r *Tunnel) Run() {
func (r *Tunnel) Open() {
localAddr := fmt.Sprintf("%s:%d", r.LocalHost, r.LocalPort)
log.Debugf("等待客户端访问 [%v] ...", localAddr)
go func() {
<-r.ctx.Done()
_ = r.listener.Close()
log.Debugf("SSH 隧道 %v 关闭", localAddr)
}()
log.Debugf("等待客户端访问 %v", localAddr)
localConn, err := r.listener.Accept()
if err != nil {
r.err = err
return
}
log.Debugf("客户端 [%v] 已连接至 [%v]", localConn.RemoteAddr().String(), localAddr)
log.Debugf("客户端 %v 连接至 %v", localConn.RemoteAddr().String(), localAddr)
remoteAddr := fmt.Sprintf("%s:%d", r.RemoteHost, r.RemotePort)
log.Debugf("连接远程主机 [%v] ...", remoteAddr)
log.Debugf("连接远程主机 %v ...", remoteAddr)
remoteConn, err := r.Gateway.SshClient.Dial("tcp", remoteAddr)
if err != nil {
log.Debugf("连接远程主机 [%v] 失败", remoteAddr)
log.Debugf("连接远程主机 %v 失败", remoteAddr)
r.err = err
return
}
log.Debugf("连接远程主机 [%v] 成功", remoteAddr)
log.Debugf("连接远程主机 %v 成功", remoteAddr)
go copyConn(localConn, remoteConn)
go copyConn(remoteConn, localConn)
log.Debugf("开始转发数据 [%v]->[%v]", localAddr, remoteAddr)
go func() {
<-r.ctx.Done()
_ = r.listener.Close()
_ = localConn.Close()
_ = remoteConn.Close()
log.Debugf("SSH隧道 [%v]-[%v] 已关闭", localAddr, remoteAddr)
}()
log.Debugf("转发数据 [%v]->[%v]", localAddr, remoteAddr)
}
func (r Tunnel) Close() {

View File

@ -25,7 +25,7 @@ func NewManager() *Manager {
}
}
func (m *Manager) Run() {
func (m *Manager) Start() {
for {
select {
case s := <-m.Add:
@ -66,5 +66,5 @@ var GlobalSecurityManager *Manager
func init() {
GlobalSecurityManager = NewManager()
go GlobalSecurityManager.Run()
go GlobalSecurityManager.Start()
}

View File

@ -47,9 +47,9 @@ func NewObserver(id string) *Manager {
}
}
func (m *Manager) Run() {
func (m *Manager) Start() {
defer fmt.Printf("Session Manager %v End\n", m.id)
fmt.Printf("Session Manager %v Run\n", m.id)
fmt.Printf("Session Manager %v Open\n", m.id)
for {
select {
case s := <-m.Add:
@ -94,5 +94,5 @@ var GlobalSessionManager *Manager
func init() {
GlobalSessionManager = NewManager()
go GlobalSessionManager.Run()
go GlobalSessionManager.Start()
}

View File

@ -0,0 +1,6 @@
package resource
import "embed"
//go:embed *
var Resource embed.FS

View File

@ -268,7 +268,7 @@ func (gui Gui) handleAccessAsset(sess *ssh.Session, sessionId string) (err error
NextTerminal: nextTerminal,
Observer: session.NewObserver(s.ID),
}
go nextSession.Observer.Run()
go nextSession.Observer.Start()
session.GlobalSessionManager.Add <- nextSession
if err := sshSession.Wait(); err != nil {