2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 04:22:33 +08:00

feat: 优化ssh

This commit is contained in:
2026-01-09 05:00:35 +08:00
parent 61b2a70e84
commit 84f3a18074
6 changed files with 31 additions and 126 deletions

View File

@@ -17,7 +17,7 @@ type ToolboxSSHPubKeyAuth struct {
// ToolboxSSHRootLogin Root 登录设置
type ToolboxSSHRootLogin struct {
Mode string `form:"mode" json:"mode" validate:"required|in:yes,no,without-password,prohibit-password"`
Mode string `form:"mode" json:"mode" validate:"required|in:yes,no,prohibit-password,forced-commands-only"`
}
// ToolboxSSHRootPassword Root 密码设置

View File

@@ -454,9 +454,6 @@ func (route *Http) Register(r *chi.Mux) {
r.Route("/toolbox_ssh", func(r chi.Router) {
r.Get("/info", route.toolboxSSH.GetInfo)
r.Post("/start", route.toolboxSSH.Start)
r.Post("/stop", route.toolboxSSH.Stop)
r.Post("/restart", route.toolboxSSH.Restart)
r.Post("/port", route.toolboxSSH.UpdatePort)
r.Post("/password_auth", route.toolboxSSH.UpdatePasswordAuth)
r.Post("/pubkey_auth", route.toolboxSSH.UpdatePubKeyAuth)

View File

@@ -5,6 +5,7 @@ import (
"regexp"
"strings"
"github.com/acepanel/panel/pkg/os"
"github.com/leonelquinteros/gotext"
"github.com/libtnb/chix"
"github.com/spf13/cast"
@@ -16,12 +17,19 @@ import (
)
type ToolboxSSHService struct {
t *gotext.Locale
t *gotext.Locale
service string
}
func NewToolboxSSHService(t *gotext.Locale) *ToolboxSSHService {
// 沟槽的大便和乌班图喜欢搞特殊
service := "sshd"
if os.IsDebian() || os.IsUbuntu() {
service = "ssh"
}
return &ToolboxSSHService{
t: t,
t: t,
service: service,
}
}
@@ -34,16 +42,6 @@ func (s *ToolboxSSHService) GetInfo(w http.ResponseWriter, r *http.Request) {
return
}
// 获取 SSH 服务状态
status, err := systemctl.Status("sshd")
if err != nil {
// 尝试 ssh 服务名
status, err = systemctl.Status("ssh")
if err != nil {
status = false
}
}
// 解析端口
port := 22
portMatch := regexp.MustCompile(`(?m)^Port\s+(\d+)`).FindStringSubmatch(sshdConfig)
@@ -73,7 +71,7 @@ func (s *ToolboxSSHService) GetInfo(w http.ResponseWriter, r *http.Request) {
}
Success(w, chix.M{
"status": status,
"service": s.service,
"port": port,
"password_auth": passwordAuth,
"pubkey_auth": pubKeyAuth,
@@ -81,45 +79,6 @@ func (s *ToolboxSSHService) GetInfo(w http.ResponseWriter, r *http.Request) {
})
}
// Start 启动 SSH 服务
func (s *ToolboxSSHService) Start(w http.ResponseWriter, r *http.Request) {
err := systemctl.Start("sshd")
if err != nil {
err = systemctl.Start("ssh")
if err != nil {
Error(w, http.StatusInternalServerError, s.t.Get("failed to start SSH service: %v", err))
return
}
}
Success(w, nil)
}
// Stop 停止 SSH 服务
func (s *ToolboxSSHService) Stop(w http.ResponseWriter, r *http.Request) {
err := systemctl.Stop("sshd")
if err != nil {
err = systemctl.Stop("ssh")
if err != nil {
Error(w, http.StatusInternalServerError, s.t.Get("failed to stop SSH service: %v", err))
return
}
}
Success(w, nil)
}
// Restart 重启 SSH 服务
func (s *ToolboxSSHService) Restart(w http.ResponseWriter, r *http.Request) {
err := systemctl.Restart("sshd")
if err != nil {
err = systemctl.Restart("ssh")
if err != nil {
Error(w, http.StatusInternalServerError, s.t.Get("failed to restart SSH service: %v", err))
return
}
}
Success(w, nil)
}
// UpdatePort 修改 SSH 端口
func (s *ToolboxSSHService) UpdatePort(w http.ResponseWriter, r *http.Request) {
req, err := Bind[request.ToolboxSSHPort](r)
@@ -133,9 +92,8 @@ func (s *ToolboxSSHService) UpdatePort(w http.ResponseWriter, r *http.Request) {
return
}
// 重启 SSH 服务
if err = s.restartSSH(); err != nil {
Error(w, http.StatusInternalServerError, s.t.Get("failed to restart SSH service: %v", err))
if err = systemctl.Restart(s.service); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -160,8 +118,8 @@ func (s *ToolboxSSHService) UpdatePasswordAuth(w http.ResponseWriter, r *http.Re
return
}
if err = s.restartSSH(); err != nil {
Error(w, http.StatusInternalServerError, s.t.Get("failed to restart SSH service: %v", err))
if err = systemctl.Restart(s.service); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -186,8 +144,8 @@ func (s *ToolboxSSHService) UpdatePubKeyAuth(w http.ResponseWriter, r *http.Requ
return
}
if err = s.restartSSH(); err != nil {
Error(w, http.StatusInternalServerError, s.t.Get("failed to restart SSH service: %v", err))
if err = systemctl.Restart(s.service); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -207,8 +165,8 @@ func (s *ToolboxSSHService) UpdateRootLogin(w http.ResponseWriter, r *http.Reque
return
}
if err = s.restartSSH(); err != nil {
Error(w, http.StatusInternalServerError, s.t.Get("failed to restart SSH service: %v", err))
if err = systemctl.Restart(s.service); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -303,7 +261,7 @@ func (s *ToolboxSSHService) GenerateRootKey(w http.ResponseWriter, r *http.Reque
}
}
_ = s.restartSSH()
_ = systemctl.Restart(s.service)
Success(w, privateKey)
}
@@ -328,12 +286,3 @@ func (s *ToolboxSSHService) updateSSHConfig(key, value string) error {
return io.Write("/etc/ssh/sshd_config", sshdConfig, 0600)
}
// restartSSH 重启 SSH 服务
func (s *ToolboxSSHService) restartSSH() error {
err := systemctl.Restart("sshd")
if err != nil {
err = systemctl.Restart("ssh")
}
return err
}

View File

@@ -3,12 +3,6 @@ import { http } from '@/utils'
export default {
// 获取 SSH 信息
info: (): any => http.Get('/toolbox_ssh/info'),
// 启动 SSH 服务
start: (): any => http.Post('/toolbox_ssh/start'),
// 停止 SSH 服务
stop: (): any => http.Post('/toolbox_ssh/stop'),
// 重启 SSH 服务
restart: (): any => http.Post('/toolbox_ssh/restart'),
// 设置 SSH 端口
updatePort: (port: number): any => http.Post('/toolbox_ssh/port', { port }),
// 设置密码认证

View File

@@ -4,6 +4,7 @@ defineOptions({
})
import toolboxSSH from '@/api/panel/toolbox-ssh'
import ServiceStatus from '@/components/common/ServiceStatus.vue'
import TheIcon from '@/components/custom/TheIcon.vue'
import { generateRandomString } from '@/utils'
import { useGettext } from 'vue3-gettext'
@@ -11,13 +12,13 @@ import { useGettext } from 'vue3-gettext'
const { $gettext } = useGettext()
// SSH 基础设置
const sshStatus = ref(false)
const service = ref('')
const sshPort = ref(22)
const passwordAuth = ref(false)
const pubkeyAuth = ref(true)
// Root 设置
const rootLogin = ref('without-password')
const rootLogin = ref('yes')
const rootPassword = ref('')
const rootKey = ref('')
@@ -33,7 +34,7 @@ const keyLoading = ref(false)
// Root 登录选项
const rootLoginOptions = [
{ label: 'yes - ' + $gettext('Allow password and key login'), value: 'yes' },
{ label: 'no - ' + $gettext('Disable root login'), value: 'no' },
{ label: 'no - ' + $gettext('Disable login'), value: 'no' },
{
label: 'prohibit-password - ' + $gettext('Only allow key login (recommended)'),
value: 'prohibit-password'
@@ -49,7 +50,7 @@ const loadData = async () => {
loading.value = true
try {
const info = await toolboxSSH.info()
sshStatus.value = info.status
service.value = info.service
sshPort.value = info.port
passwordAuth.value = info.password_auth
pubkeyAuth.value = info.pubkey_auth
@@ -63,34 +64,6 @@ const loadData = async () => {
}
}
// 切换 SSH 服务状态
const handleToggleSSH = async () => {
loading.value = true
try {
if (sshStatus.value) {
await toolboxSSH.stop()
window.$message.success($gettext('SSH service stopped'))
} else {
await toolboxSSH.start()
window.$message.success($gettext('SSH service started'))
}
sshStatus.value = !sshStatus.value
} finally {
loading.value = false
}
}
// 重启 SSH 服务
const handleRestartSSH = async () => {
loading.value = true
try {
await toolboxSSH.restart()
window.$message.success($gettext('SSH service restarted'))
} finally {
loading.value = false
}
}
// 更新端口
const handleUpdatePort = async () => {
portLoading.value = true
@@ -224,16 +197,10 @@ onMounted(() => {
<template>
<n-spin :show="loading">
<n-flex vertical :size="24">
<service-status v-if="service != ''" :service="service" />
<!-- SSH 服务 -->
<n-card :title="$gettext('SSH Service')">
<n-card :title="$gettext('SSH Settings')">
<n-flex vertical :size="16">
<n-flex align="center" :size="12">
<n-text strong>{{ $gettext('SSH Service Status') }}</n-text>
<n-switch :value="sshStatus" :loading="loading" @update:value="handleToggleSSH" />
<n-button :loading="loading" @click="handleRestartSSH">
{{ $gettext('Restart') }}
</n-button>
</n-flex>
<!-- SSH 密码登录 -->
<n-flex vertical :size="4">
<n-flex align="center" :size="12">
@@ -256,9 +223,7 @@ onMounted(() => {
@update:value="handleTogglePubkeyAuth"
/>
</n-flex>
<n-text depth="3">{{
$gettext('Allow key authentication for SSH login')
}}</n-text>
<n-text depth="3">{{ $gettext('Allow key authentication for SSH login') }}</n-text>
</n-flex>
<!-- SSH 端口 -->
<n-flex vertical :size="4">

View File

@@ -38,7 +38,7 @@ const columns: any = [
{
title: 'Key',
key: 'key',
minWidth: 200,
width: 300,
resizable: true,
ellipsis: { tooltip: true },
render(row: any) {
@@ -298,7 +298,7 @@ onMounted(() => {
<n-data-table
striped
remote
:scroll-x="1400"
:scroll-x="1500"
:loading="loading"
:columns="columns"
:data="data"