parent
a1a9ca2596
commit
809118f3e9
4
.gitignore
vendored
4
.gitignore
vendored
@ -24,3 +24,7 @@ web/build
|
|||||||
# next terminal
|
# next terminal
|
||||||
/data/
|
/data/
|
||||||
/logs/
|
/logs/
|
||||||
|
/server/resource/static/
|
||||||
|
/server/resource/*.html
|
||||||
|
/server/resource/*.json
|
||||||
|
/server/resource/*.ico
|
||||||
|
@ -13,6 +13,7 @@ RUN apk add gcc g++
|
|||||||
RUN go mod tidy
|
RUN go mod tidy
|
||||||
RUN sh get_arch.sh
|
RUN sh get_arch.sh
|
||||||
RUN echo "Hello, my CPU architecture is $(uname -m)"
|
RUN echo "Hello, my CPU architecture is $(uname -m)"
|
||||||
|
RUN cp -r /app/web/build /app/server/resource/
|
||||||
RUN go env;CGO_ENABLED=1 GOOS=linux GOARCH=$ARCH go build -a -ldflags '-linkmode external -extldflags "-static"' -o next-terminal main.go
|
RUN go env;CGO_ENABLED=1 GOOS=linux GOARCH=$ARCH go build -a -ldflags '-linkmode external -extldflags "-static"' -o next-terminal main.go
|
||||||
|
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
@ -34,7 +35,7 @@ RUN touch config.yml
|
|||||||
|
|
||||||
COPY --from=builder /app/next-terminal ./
|
COPY --from=builder /app/next-terminal ./
|
||||||
COPY --from=builder /app/LICENSE ./
|
COPY --from=builder /app/LICENSE ./
|
||||||
COPY --from=builder /app/web/build ./web/build
|
#COPY --from=builder /app/web/build ./web/build
|
||||||
|
|
||||||
EXPOSE $SERVER_PORT $SSHD_PORT
|
EXPOSE $SERVER_PORT $SSHD_PORT
|
||||||
|
|
||||||
|
2
go.mod
2
go.mod
@ -30,14 +30,12 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect
|
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
||||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
|
||||||
github.com/fsnotify/fsnotify v1.4.7 // indirect
|
github.com/fsnotify/fsnotify v1.4.7 // indirect
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.1 // indirect
|
|
||||||
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
|
11
go.sum
11
go.sum
@ -11,8 +11,6 @@ cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqCl
|
|||||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
|
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
@ -24,6 +22,8 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuW
|
|||||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||||
|
github.com/benbjohnson/hashfs v0.2.1 h1:pxfukDsRT7iwBcICHCNsqQoopYV+gUQw5yPDiYt8A6M=
|
||||||
|
github.com/benbjohnson/hashfs v0.2.1/go.mod h1:7OMXaMVo1YkfiIPxKrl7OXkUTUgWjmsAKyR+E6xDIRM=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
@ -46,8 +46,6 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMSRhl4D7AQ=
|
|
||||||
github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI=
|
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
@ -57,12 +55,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
|
|||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/gliderlabs/ssh v0.3.3 h1:mBQ8NiOgDkINJrZtoizkC3nDNYgSaWtxyem6S2XHBtA=
|
github.com/gliderlabs/ssh v0.3.3 h1:mBQ8NiOgDkINJrZtoizkC3nDNYgSaWtxyem6S2XHBtA=
|
||||||
github.com/gliderlabs/ssh v0.3.3/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914=
|
github.com/gliderlabs/ssh v0.3.3/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=
|
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.1 h1:fU/0xli6HY02ocbMuozHAYsaHLcnkLjvho2r5a34BUU=
|
|
||||||
github.com/go-ldap/ldap/v3 v3.4.1/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
|
|
||||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||||
@ -258,7 +252,6 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
|
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
|
||||||
|
@ -2,6 +2,8 @@ version: '3.3'
|
|||||||
services:
|
services:
|
||||||
guacd:
|
guacd:
|
||||||
image: dushixiang/guacd:latest
|
image: dushixiang/guacd:latest
|
||||||
|
environment:
|
||||||
|
GUACD_LOG_LEVEL: debug
|
||||||
volumes:
|
volumes:
|
||||||
- ../data:/usr/local/next-terminal/data
|
- ../data:/usr/local/next-terminal/data
|
||||||
ports:
|
ports:
|
||||||
|
@ -3,6 +3,7 @@ package api
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -105,14 +106,9 @@ func (api GuacamoleApi) Guacamole(c echo.Context) error {
|
|||||||
utils.Disconnect(ws, AccessGatewayCreateError, "创建SSH隧道失败:"+err.Error())
|
utils.Disconnect(ws, AccessGatewayCreateError, "创建SSH隧道失败:"+err.Error())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
defer g.CloseSshTunnel(s.ID)
|
|
||||||
ip = exposedIP
|
ip = exposedIP
|
||||||
port = exposedPort
|
port = exposedPort
|
||||||
}
|
defer g.CloseSshTunnel(s.ID)
|
||||||
active, err := utils.Tcping(ip, port)
|
|
||||||
if !active {
|
|
||||||
utils.Disconnect(ws, AssetNotActive, "目标资产不在线: "+err.Error())
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configuration.SetParameter("hostname", ip)
|
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)
|
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)
|
guacdTunnel, err := guacd.NewTunnel(addr, configuration)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if connectionId == "" {
|
if connectionId == "" {
|
||||||
utils.Disconnect(ws, NewTunnelError, err.Error())
|
utils.Disconnect(ws, NewTunnelError, err.Error())
|
||||||
}
|
}
|
||||||
log.Printf("[%v:%v] 建立连接失败: %v", sessionId, connectionId, err.Error())
|
log.Printf("[%v] 建立连接失败: %v", sessionId, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +161,7 @@ func (api GuacamoleApi) Guacamole(c echo.Context) error {
|
|||||||
|
|
||||||
nextSession.Observer = session.NewObserver(sessionId)
|
nextSession.Observer = session.NewObserver(sessionId)
|
||||||
session.GlobalSessionManager.Add <- nextSession
|
session.GlobalSessionManager.Add <- nextSession
|
||||||
go nextSession.Observer.Run()
|
go nextSession.Observer.Start()
|
||||||
sess := model.Session{
|
sess := model.Session{
|
||||||
ConnectionId: guacdTunnel.UUID,
|
ConnectionId: guacdTunnel.UUID,
|
||||||
Width: intWidth,
|
Width: intWidth,
|
||||||
@ -177,7 +174,7 @@ func (api GuacamoleApi) Guacamole(c echo.Context) error {
|
|||||||
sess.Reviewed = true
|
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 {
|
if err := repository.SessionRepository.UpdateById(ctx, &sess, sessionId); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -199,7 +196,7 @@ func (api GuacamoleApi) Guacamole(c echo.Context) error {
|
|||||||
for {
|
for {
|
||||||
_, message, err := ws.ReadMessage()
|
_, message, err := ws.ReadMessage()
|
||||||
if err != nil {
|
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.Read() 会阻塞,所以要先把guacdTunnel客户端关闭,才能退出Guacd循环
|
||||||
_ = guacdTunnel.Close()
|
_ = guacdTunnel.Close()
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ func (api WebTerminalApi) SshEndpoint(c echo.Context) error {
|
|||||||
NextTerminal: nextTerminal,
|
NextTerminal: nextTerminal,
|
||||||
Observer: session.NewObserver(s.ID),
|
Observer: session.NewObserver(s.ID),
|
||||||
}
|
}
|
||||||
go nextSession.Observer.Run()
|
go nextSession.Observer.Start()
|
||||||
session.GlobalSessionManager.Add <- nextSession
|
session.GlobalSessionManager.Add <- nextSession
|
||||||
|
|
||||||
termHandler := NewTermHandler(sessionId, isRecording, ws, nextTerminal)
|
termHandler := NewTermHandler(sessionId, isRecording, ws, nextTerminal)
|
||||||
|
@ -1,26 +1,56 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
"next-terminal/server/api"
|
"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"
|
||||||
"github.com/labstack/echo/v4/middleware"
|
"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 {
|
func setupRoutes() *echo.Echo {
|
||||||
|
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
e.HideBanner = true
|
e.HideBanner = true
|
||||||
//e.Logger = log.GetEchoLogger()
|
//e.Logger = log.GetEchoLogger()
|
||||||
//e.Use(log.Hook())
|
//e.Use(log.Hook())
|
||||||
e.File("/", "web/build/index.html")
|
|
||||||
e.File("/asciinema.html", "web/build/asciinema.html")
|
fsys := getFS(config.GlobalCfg.Debug)
|
||||||
e.File("/", "web/build/index.html")
|
fileServer := http.FileServer(http.FS(fsys))
|
||||||
e.File("/favicon.ico", "web/build/favicon.ico")
|
handler := WrapHandler(fileServer)
|
||||||
e.File("/logo.png", "web/build/logo.png")
|
e.GET("/", handler)
|
||||||
e.Static("/static", "web/build/static")
|
e.GET("/asciinema.html", handler)
|
||||||
|
e.GET("/favicon.ico", handler)
|
||||||
|
e.GET("/static/*", handler)
|
||||||
|
|
||||||
e.Use(middleware.Recover())
|
e.Use(middleware.Recover())
|
||||||
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
|
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
|
||||||
|
@ -44,7 +44,7 @@ func (g *Gateway) Run() {
|
|||||||
select {
|
select {
|
||||||
case t := <-g.Add:
|
case t := <-g.Add:
|
||||||
g.tunnels[t.ID] = t
|
g.tunnels[t.ID] = t
|
||||||
go t.Run()
|
go t.Open()
|
||||||
case k := <-g.Del:
|
case k := <-g.Del:
|
||||||
if _, ok := g.tunnels[k]; ok {
|
if _, ok := g.tunnels[k]; ok {
|
||||||
g.tunnels[k].Close()
|
g.tunnels[k].Close()
|
||||||
|
@ -15,7 +15,7 @@ func NewManager() *Manager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) Run() {
|
func (m *Manager) Start() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case g := <-m.Add:
|
case g := <-m.Add:
|
||||||
@ -38,5 +38,5 @@ var GlobalGatewayManager *Manager
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
GlobalGatewayManager = NewManager()
|
GlobalGatewayManager = NewManager()
|
||||||
go GlobalGatewayManager.Run()
|
go GlobalGatewayManager.Start()
|
||||||
}
|
}
|
||||||
|
@ -22,36 +22,35 @@ type Tunnel struct {
|
|||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Tunnel) Run() {
|
func (r *Tunnel) Open() {
|
||||||
localAddr := fmt.Sprintf("%s:%d", r.LocalHost, r.LocalPort)
|
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()
|
localConn, err := r.listener.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.err = err
|
r.err = err
|
||||||
return
|
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)
|
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)
|
remoteConn, err := r.Gateway.SshClient.Dial("tcp", remoteAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("连接远程主机 [%v] 失败", remoteAddr)
|
log.Debugf("连接远程主机 %v 失败", remoteAddr)
|
||||||
r.err = err
|
r.err = err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("连接远程主机 [%v] 成功", remoteAddr)
|
log.Debugf("连接远程主机 %v 成功", remoteAddr)
|
||||||
go copyConn(localConn, remoteConn)
|
go copyConn(localConn, remoteConn)
|
||||||
go copyConn(remoteConn, localConn)
|
go copyConn(remoteConn, localConn)
|
||||||
log.Debugf("开始转发数据 [%v]->[%v]", localAddr, remoteAddr)
|
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)
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Tunnel) Close() {
|
func (r Tunnel) Close() {
|
||||||
|
@ -25,7 +25,7 @@ func NewManager() *Manager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) Run() {
|
func (m *Manager) Start() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case s := <-m.Add:
|
case s := <-m.Add:
|
||||||
@ -66,5 +66,5 @@ var GlobalSecurityManager *Manager
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
GlobalSecurityManager = NewManager()
|
GlobalSecurityManager = NewManager()
|
||||||
go GlobalSecurityManager.Run()
|
go GlobalSecurityManager.Start()
|
||||||
}
|
}
|
||||||
|
@ -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)
|
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 {
|
for {
|
||||||
select {
|
select {
|
||||||
case s := <-m.Add:
|
case s := <-m.Add:
|
||||||
@ -94,5 +94,5 @@ var GlobalSessionManager *Manager
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
GlobalSessionManager = NewManager()
|
GlobalSessionManager = NewManager()
|
||||||
go GlobalSessionManager.Run()
|
go GlobalSessionManager.Start()
|
||||||
}
|
}
|
||||||
|
6
server/resource/resource.go
Normal file
6
server/resource/resource.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package resource
|
||||||
|
|
||||||
|
import "embed"
|
||||||
|
|
||||||
|
//go:embed *
|
||||||
|
var Resource embed.FS
|
@ -268,7 +268,7 @@ func (gui Gui) handleAccessAsset(sess *ssh.Session, sessionId string) (err error
|
|||||||
NextTerminal: nextTerminal,
|
NextTerminal: nextTerminal,
|
||||||
Observer: session.NewObserver(s.ID),
|
Observer: session.NewObserver(s.ID),
|
||||||
}
|
}
|
||||||
go nextSession.Observer.Run()
|
go nextSession.Observer.Start()
|
||||||
session.GlobalSessionManager.Add <- nextSession
|
session.GlobalSessionManager.Add <- nextSession
|
||||||
|
|
||||||
if err := sshSession.Wait(); err != nil {
|
if err := sshSession.Wait(); err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user