mirror of
https://github.com/chaos-zhu/easynode.git
synced 2026-10-07 15:57:53 +08:00
✨ 支持面板配置IP白名单
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
* 新增服务器定时任务功能(TODO
|
||||
* 连接服务器下拉菜单分组展示(TODO
|
||||
* 增加升级更新内容展示(TODO
|
||||
* 面板支持灵活配置IP白名单
|
||||
|
||||
## [3.0.4](https://github.com/chaos-zhu/easynode/releases) (2025-03-15)
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ docker run -d -p 8082:8082 --restart=always -v /root/easynode/db:/easynode/app/d
|
||||
```
|
||||
环境变量:
|
||||
- `DEBUG`: 启动debug日志 0:关闭 1:开启, 默认关闭
|
||||
- `ALLOWED_IPS`: 可以访问服务的IP白名单, 多个使用逗号分隔, 支持填写部分ip前缀, 例如: `-e ALLOWED_IPS=127.0.0.1,196.168`
|
||||
- `ALLOWED_IPS`: 可以访问服务的IP白名单, 多个使用逗号分隔, 支持填写部分ip前缀,支持在面板设置。例如: `-e ALLOWED_IPS=127.0.0.1,196.168`
|
||||
|
||||
## 监控服务安装
|
||||
|
||||
|
||||
@@ -1,17 +1,27 @@
|
||||
const { LogDB } = require('../utils/db-class')
|
||||
const { KeyDB, LogDB } = require('../utils/db-class')
|
||||
const keyDB = new KeyDB().getInstance()
|
||||
const logDB = new LogDB().getInstance()
|
||||
|
||||
let whiteList = process.env.ALLOWED_IPS ? process.env.ALLOWED_IPS.split(',') : []
|
||||
|
||||
async function getLog({ res }) {
|
||||
let list = await logDB.findAsync({})
|
||||
let { ipWhiteList } = await keyDB.findOneAsync({})
|
||||
list = list.map(item => {
|
||||
return { ...item, id: item._id }
|
||||
})
|
||||
list?.sort((a, b) => Number(b.date) - Number(a.date))
|
||||
res.success({ data: { list, whiteList } })
|
||||
res.success({ data: { list, ipWhiteList } })
|
||||
}
|
||||
|
||||
const saveIpWhiteList = async ({ res, request }) => {
|
||||
const { body: { ipWhiteList } } = request
|
||||
console.log('ipWhiteList:', ipWhiteList)
|
||||
if (!Array.isArray(ipWhiteList)) return res.fail({ msg: 'ip list输入非法' })
|
||||
let { _id } = await keyDB.findOneAsync({})
|
||||
await keyDB.updateAsync({ _id }, { $set: { ipWhiteList } })
|
||||
res.success({ msg: 'success' })
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getLog
|
||||
getLog,
|
||||
saveIpWhiteList
|
||||
}
|
||||
|
||||
+12
-2
@@ -5,8 +5,18 @@ const { KeyDB, GroupDB, NotifyDB, NotifyConfigDB, ScriptGroupDB } = require('./u
|
||||
|
||||
async function initKeyDB() {
|
||||
const keyDB = new KeyDB().getInstance()
|
||||
let count = await keyDB.countAsync({})
|
||||
if (count !== 0) return consola.info('公私钥已存在[重新生成会导致已保存的ssh密钥信息失效]')
|
||||
let keyData = await keyDB.findOneAsync({})
|
||||
if (keyData?.user) {
|
||||
const { _id, ipWhiteList } = keyData
|
||||
let allowedIPs = process.env.ALLOWED_IPS ? process.env.ALLOWED_IPS.split(',') : []
|
||||
if (allowedIPs.length > 0) {
|
||||
consola.info('[存在白名单IP环境变量,合并到本地数据库中]')
|
||||
allowedIPs = [...new Set([...ipWhiteList, ...allowedIPs])].filter(item => item)
|
||||
await keyDB.updateAsync({ _id }, { $set: { ipWhiteList: allowedIPs } })
|
||||
}
|
||||
consola.info('公私钥已存在[重新生成会导致已保存的ssh密钥信息失效]')
|
||||
return
|
||||
}
|
||||
let newConfig = {
|
||||
user: 'admin',
|
||||
pwd: 'admin',
|
||||
|
||||
@@ -6,7 +6,7 @@ const { getGroupList, addGroupList, updateGroupList, removeGroup } = require('..
|
||||
const { getScriptList, getLocalScriptList, addScript, updateScriptList, removeScript, batchRemoveScript, importScript } = require('../controller/scripts')
|
||||
const { getScriptGroupList, addScriptGroup, removeScriptGroup, updateScriptGroup } = require('../controller/script-group')
|
||||
const { getOnekeyRecord, removeOnekeyRecord } = require('../controller/onekey')
|
||||
const { getLog } = require('../controller/log')
|
||||
const { getLog, saveIpWhiteList } = require('../controller/log')
|
||||
|
||||
const ssh = [
|
||||
{
|
||||
@@ -259,6 +259,11 @@ const log = [
|
||||
method: 'get',
|
||||
path: '/log',
|
||||
controller: getLog
|
||||
},
|
||||
{
|
||||
method: 'post',
|
||||
path: '/ip-white-list',
|
||||
controller: saveIpWhiteList
|
||||
}
|
||||
]
|
||||
module.exports = [].concat(ssh, host, user, notify, group, scripts, scriptGroup, onekey, log)
|
||||
|
||||
@@ -58,6 +58,9 @@ export default {
|
||||
getLoginRecord() {
|
||||
return axios({ url: '/log', method: 'get' })
|
||||
},
|
||||
saveIpWhiteList(data) {
|
||||
return axios({ url: '/ip-white-list', method: 'post', data })
|
||||
},
|
||||
updatePwd(data) {
|
||||
return axios({ url: '/pwd', method: 'put', data })
|
||||
},
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
<template>
|
||||
<el-alert v-if="allowedIPs" type="success" :closable="false">
|
||||
<el-alert type="success" :closable="false">
|
||||
<template #title>
|
||||
<span style="letter-spacing: 2px;"> 登录白名单IP: </span>
|
||||
<el-tag
|
||||
v-for="(item, index) in allowedIPs"
|
||||
:key="index"
|
||||
class="allowed_ip_tag"
|
||||
type="warning"
|
||||
>
|
||||
{{ item }}
|
||||
</el-tag>
|
||||
<span style="letter-spacing: 2px;"> 登录白名单IP设置: </span>
|
||||
<el-tooltip placement="top">
|
||||
<template #content>
|
||||
<div class="ip_tips">
|
||||
IP地址为包含匹配, 如输入: 192.168则匹配IP地址包含192.168的所有IP
|
||||
</div>
|
||||
</template>
|
||||
<el-icon >
|
||||
<InfoFilled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
<el-input-tag v-model="allowedIPs" tag-type="success" tag-effect="plain">
|
||||
</el-input-tag>
|
||||
<el-button style="margin-top: 6px;" type="success" :loading="btnLoading"
|
||||
@click="handleSaveAllowedIPs">保存</el-button>
|
||||
</template>
|
||||
</el-alert>
|
||||
<el-table v-loading="loading" :data="loginRecordList">
|
||||
@@ -25,21 +31,23 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, getCurrentInstance } from 'vue'
|
||||
import { InfoFilled } from '@element-plus/icons-vue'
|
||||
|
||||
const { proxy: { $api, $tools } } = getCurrentInstance()
|
||||
const { proxy: { $api, $tools, $message } } = getCurrentInstance()
|
||||
|
||||
const loginRecordList = ref([])
|
||||
const loading = ref(false)
|
||||
const btnLoading = ref(false)
|
||||
const total = ref('')
|
||||
const allowedIPs = ref('')
|
||||
const allowedIPs = ref([])
|
||||
|
||||
const handleLookupLoginRecord = () => {
|
||||
loading.value = true
|
||||
$api.getLoginRecord()
|
||||
.then(({ data }) => {
|
||||
const { list, whiteList } = data
|
||||
const { list, ipWhiteList } = data
|
||||
total.value = list.length
|
||||
allowedIPs.value = whiteList || []
|
||||
allowedIPs.value = ipWhiteList || []
|
||||
loginRecordList.value = list.map((item) => {
|
||||
item.date = $tools.formatTimestamp(item.date)
|
||||
return item
|
||||
@@ -50,6 +58,18 @@ const handleLookupLoginRecord = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleSaveAllowedIPs = async () => {
|
||||
btnLoading.value = true
|
||||
const ipWhiteList = [...new Set(allowedIPs.value)].filter(item => item)
|
||||
try {
|
||||
await $api.saveIpWhiteList({ ipWhiteList })
|
||||
handleLookupLoginRecord()
|
||||
$message.success('success')
|
||||
} finally {
|
||||
btnLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
handleLookupLoginRecord()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user