Compare commits

...

10 Commits

Author SHA1 Message Date
046b0ef674 增加监听URL变化
Some checks failed
CI / lint (push) Has been cancelled
CI / typecheck (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
2025-08-09 13:37:57 +08:00
597339b666 添加微信分享功能 2025-08-09 13:27:47 +08:00
f57e410393 测试新的ci,触发coolify的部署 2025-08-08 18:01:36 +08:00
3aed750f78 修改页面底部链接 2025-08-08 17:39:58 +08:00
afb76863de 增加博文 2025-08-08 17:27:25 +08:00
9a0dda8e77 新增博文 2025-08-08 14:15:45 +08:00
99e53ed018 增加博文 2025-08-08 13:53:33 +08:00
817648af09 调整blog导航样式 2025-08-08 13:47:49 +08:00
991dd065f8 lint --fix 2025-08-08 13:02:49 +08:00
033150a442 解决SSR问题 2025-08-08 12:33:54 +08:00
15 changed files with 630 additions and 252 deletions

View File

@@ -76,4 +76,23 @@ jobs:
context: .
file: ./Dockerfile
push: true
tags: reg.lijue.net:5888/docs/docs:latest
tags: reg.lijue.net:5888/docs/docs:latest
- name: Trigger Coolify deploy
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
env:
COOLIFY_API_URL: https://coolify.lijue.net:5888/api/v1/deploy?uuid=ks44swgo4kc8wgwkwck4s004&force=false
COOLIFY_TOKEN: ${{ secrets.COOLIFY_TOKEN }}
run: |
set -euo pipefail
echo "Triggering Coolify deploy: $COOLIFY_API_URL"
http_code=$(curl -sS -w "%{http_code}" -o coolify_response.json -X GET "$COOLIFY_API_URL" \
-H "Authorization: Bearer $COOLIFY_TOKEN" \
-H "Accept: application/json")
echo "HTTP status: $http_code"
echo "Response:"
cat coolify_response.json
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 400 ]; then
echo "Coolify deploy trigger failed"
exit 1
fi

View File

@@ -9,7 +9,7 @@ export default defineAppConfig({
}
},
seo: {
siteName: 'Nuxt Docs Template'
siteName: 'Estel Docs'
},
header: {
title: 'Estel Docs',
@@ -32,25 +32,20 @@ export default defineAppConfig({
credits: `Copyright © ${new Date().getFullYear()} Estel. All rights reserved.`,
colorMode: false,
links: [{
'icon': 'simple-icons-nuxtdotjs',
'to': 'https://nuxt.com',
'icon': 'vscode-icons:file-type-swift',
'to': 'https://www.xajiwei.com',
'target': '_blank',
'aria-label': 'Nuxt Website'
'aria-label': '稷维科技'
}, {
'icon': 'simple-icons-discord',
'to': 'https://discord.com/invite/ps2h6QT',
'icon': 'vscode-icons:folder-type-github',
'to': 'https://git.jiwei.xin',
'target': '_blank',
'aria-label': 'Nuxt UI on Discord'
}, {
'icon': 'simple-icons-x',
'to': 'https://x.com/nuxt_js',
'target': '_blank',
'aria-label': 'Nuxt on X'
'aria-label': 'gitea'
}, {
'icon': 'simple-icons-github',
'to': 'https://github.com/nuxt/ui',
'to': 'https://github.com/estel-li/estel_docs',
'target': '_blank',
'aria-label': 'Nuxt UI on GitHub'
'aria-label': 'Estel Docs GitHub'
}]
},
toc: {

View File

@@ -6,6 +6,15 @@ const { footer } = useAppConfig()
<UFooter>
<template #left>
{{ footer.credits }}
<UButton
color="neutral"
variant="ghost"
size="sm"
to="https://beian.miit.gov.cn/"
target="_blank"
>
陕ICP备2021012926号-3
</UButton>
</template>
<template #right>

View File

@@ -23,7 +23,7 @@
</div>
<!-- 可滚动的导航区域 -->
<div class=" h-full overflow-y-auto ">
<div class="h-full overflow-y-auto no-scrollbar">
<!-- 导航 Section -->
<div>
@@ -51,7 +51,7 @@
<div class="mt-4 uppercase tracking-wider border-t border-gray-200 dark:border-gray-700 w-7/9 mx-5" />
<!-- 文档目录导航 -->
<div class="mt-6 flex items-center justify-start pl-4 w-full pb-3">
<div class="mt-5 flex items-center justify-start pl-2 pb-3">
<UContentNavigation
highlight
:navigation="docsNavigation"
@@ -59,6 +59,15 @@
type="single"
variant="pill"
trailing-icon="lucide:chevron-right"
:ui="{
root: 'w-full text-gray-700 dark:text-gray-300',
content: 'w-full',
list: 'w-full',
link: 'w-full min-w-0 text-gray-600 dark:text-gray-400',
linkTitle: 'truncate',
linkLeadingIcon: 'shrink-0',
linkTrailingIcon: 'shrink-0'
}"
/>
</div>
</div>
@@ -83,3 +92,16 @@ const docsNavigation = computed(() => {
return docsItem.children
})
</script>
<style scoped>
.no-scrollbar {
/* Firefox */
scrollbar-width: none;
/* IE and Edge */
-ms-overflow-style: none;
}
.no-scrollbar::-webkit-scrollbar {
/* Chrome, Safari, Opera */
display: none;
}
</style>

View File

@@ -0,0 +1,108 @@
<script setup lang="ts">
import { onMounted, watch } from 'vue'
const props = defineProps<{
url: string
title?: string
desc?: string
imgUrl?: string
}>()
// 仅在客户端挂载后执行,避免 SSR 阶段访问 window/location
onMounted(async () => {
try {
console.log('[WxShare] mounted with props:', { ...props })
await loadWxSdk()
console.log('[WxShare] wx sdk loaded:', !!(window as any).wx)
const { appId, timestamp, nonceStr, signature } = await getWxConfig()
console.log('[WxShare] got config:', { appId, timestamp, nonceStr, signature: signature.slice(0, 8) + '...' })
setupShare(appId, timestamp, nonceStr, signature)
} catch (err) {
console.error('[WxShare] init error:', err)
}
})
// 路径变化时,重新获取签名并刷新分享数据(适配 SPA 场景)
watch(() => props.url, async (newUrl, oldUrl) => {
if (!newUrl || newUrl === oldUrl) return
try {
await loadWxSdk()
const { appId, timestamp, nonceStr, signature } = await getWxConfig()
setupShare(appId, timestamp, nonceStr, signature)
} catch (err) {
console.error('[WxShare] reconfig error:', err)
}
})
function loadWxSdk(): Promise<void> {
console.log('loadWxSdk')
if (typeof window === 'undefined') return Promise.resolve()
if ((window as any).wx) return Promise.resolve()
return new Promise((resolve, reject) => {
const existing = document.getElementById('wx-jssdk') as HTMLScriptElement | null
if (existing && (window as any).wx) return resolve()
const script = existing ?? document.createElement('script')
if (!existing) {
script.id = 'wx-jssdk'
script.src = 'https://res.wx.qq.com/open/js/jweixin-1.6.0.js'
script.async = true
script.onload = () => resolve()
script.onerror = () => reject(new Error('Failed to load jweixin.js'))
document.head.appendChild(script)
} else {
script.onload = () => resolve()
script.onerror = () => reject(new Error('Failed to load jweixin.js'))
}
})
}
async function getWxConfig(): Promise<{ appId: string, timestamp: number, nonceStr: string, signature: string }> {
const currentUrl = encodeURIComponent((location.href.split('#')[0]) || location.href)
return await $fetch('/api/wechat/wx-config', { params: { url: currentUrl } })
}
function setupShare(appId: string, timestamp: number, nonceStr: string, signature: string) {
const wx = (window as any).wx
const shareTitle = props.title || document.title || ''
const shareDesc = props.desc || document.title || ''
const shareLink = props.url
const shareImg = props.imgUrl || '/images/default-blog.jpg'
wx.config({
debug: false,
appId,
timestamp,
nonceStr,
signature,
jsApiList: ['updateTimelineShareData', 'updateAppMessageShareData']
})
wx.ready(() => {
console.log('[WxShare] wx.ready')
wx.updateTimelineShareData({
title: shareTitle,
link: shareLink,
imgUrl: shareImg,
success: () => {}
})
wx.updateAppMessageShareData({
title: shareTitle,
desc: shareDesc,
link: shareLink,
imgUrl: shareImg,
success: () => {}
})
})
wx.error((e: unknown) => {
console.error('[WxShare] wx.error:', e)
})
}
</script>
<template>
<div style="display: none" />
<!-- 该组件无可视内容仅用于初始化微信分享 -->
</template>

View File

@@ -98,12 +98,43 @@ const links = computed(() => {
return [...links, ...(appConfig.toc?.bottom?.links || [])].filter(Boolean)
})
// ===== 微信分享(测试按钮用)=====
const wxShareActive = ref(false)
// const contentRoot = ref<HTMLElement | null>(null)
const shareLink = computed(() => 'https://lijue.me' + decodeURIComponent(path.value))
const shareTitle = computed(() => title)
const shareDesc = computed(() => description || title)
const shareImg = page?.value?.img
// const shareImg = ref<string>('/images/default-blog.jpg')
// onMounted(() => {
// // 从正文中抓取第一张图片作为分享图
// const el = contentRoot.value
// const firstImg = el?.querySelector('img') as HTMLImageElement | null
// if (firstImg?.src) {
// shareImg.value = firstImg.src
// }
// })
// Toast点击测试分享后给出指引
const toast = useToast()
function handleShareClick() {
wxShareActive.value = true
toast.add({
title: '已获取分享接口',
description: '点击右上角分享吧',
duration: 3000,
icon: 'i-lucide-share-2'
})
}
</script>
<template>
<UPage
v-if="page"
:class="['lg:mr-30 sm:mt-6', pageFontSizeClass]"
:class="['lg:mr-30 lg:ml-5 sm:mt-6', pageFontSizeClass]"
>
<UPageHeader
:title="page.title"
@@ -147,7 +178,7 @@ const links = computed(() => {
编辑页面
</UButton>
or
<UButton
<!-- <UButton
variant="link"
color="neutral"
:to="`${appConfig.github.url}/issues/new/choose`"
@@ -156,10 +187,29 @@ const links = computed(() => {
:ui="{ leadingIcon: 'size-4' }"
>
提交问题
</UButton> -->
<UButton
variant="link"
color="neutral"
icon="lucide-share-2"
:ui="{ leadingIcon: 'size-4' }"
@click="handleShareClick()"
>
微信分享
</UButton>
</div>
</USeparator>
<UContentSurround :surround="surround" />
<!-- 激活后挂载分享组件无可视内容 -->
<SharedWxShare
v-if="wxShareActive"
:url="shareLink"
:title="shareTitle"
:desc="shareDesc"
:img-url="shareImg"
/>
</UPageBody>
<template

View File

@@ -5,7 +5,7 @@ export default defineContentConfig({
docs: defineCollection({
type: 'page',
source: {
include: 'docs/**',
include: 'docs/**'
},
schema: z.object({
rawbody: z.string(),
@@ -20,7 +20,7 @@ export default defineContentConfig({
blog: defineCollection({
type: 'page',
source: {
include: 'blog/**',
include: 'blog/**'
},
schema: z.object({
rawbody: z.string(),

View File

@@ -0,0 +1,29 @@
---
title: AI复合应用 合同审查
description: 智能合同卫士,使用AI技术,对合同进行审查,并给出审查报告.
date: 2025-08-08
img: https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250808141452898.png
navigation:
icon: simple-icons:openai
---
#### 这是一个 AI 复合应用
暂起名叫 智能合同卫士 ,还是比较贴题的把?
#### 实现
由 Deepseek V3 和 Kimi K2 协作完成此应用,2个好用不贵的模型
DS 根据文件名,以及 审查主体 工作领域 与 合同要点,细化一份简要的审查要点
主要工作由 Kimi K2 来完成:
根据 Deepseek 细化的要点和 提取出来的文档内容,进行审查.
输出审查后的结果
#### 改进
按照初步的设想,后续还有一个模型,比如 Gemini2.5 ,或者 R1 ,Qwen3 之类的**推理模型**,进一步的审查 **Kimi K2 的审查结果**.
不过 K2 单独使用的实际效果已经非常好了,为了节省时间和成本,暂时取掉最后一步.
使用 AI 的话,不论是 R1 还是 K2 都是有一定的**幻觉**,在使用中必须搭配知识库来使用.
这次测试并没有加知识库,所以 AI **虚构**了一些内容,比如当地房价涨幅 ,和虚构的 **《陕西省住房租赁管理办法》**.
给大模型增加搜索能力,和在知识库里添加 **民法典** 等相关法律条文进去,可以有效的解决幻觉问题.
#### 测试结果
![image.png](https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250808140212486.png)

View File

@@ -0,0 +1,124 @@
---
title: Kali 安装 GVM
description: 在 Kali 上安装 GVM
date: 2025-08-08
img: https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250806105153532.png
navigation:
icon: simple-icons:kalilinux
---
### 配置安装好 Kali
![image.png](https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250806115946725.png)
```bash
# 安装 gvm
sudo apt install gvm -y
# 执行配置脚本
sudo gvm-setup
```
### 安装过程中 copy admin 的密码
![image.png](https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250806120225751.png)
根据提示运行安装检测命令
```bash
sudo gvm-check-setup
```
报错了.
```bash
└─**$** sudo gvm-check-setup
[sudo] estel 的密码:
gvm-check-setup 25.04.0
 This script is provided and maintained by Debian and Kali.
  Test completeness and readiness of GVM-25.04.0
Step 1: Checking OpenVAS (Scanner)... 
        OK: OpenVAS Scanner is present in version 23.20.1.
        OK: Notus Scanner is present in version 22.6.5.
        OK: Server CA Certificate is present as /var/lib/gvm/CA/servercert.pem.
Checking permissions of /var/lib/openvas/gnupg/*
        OK: _gvm owns all files in /var/lib/openvas/gnupg
        OK: redis-server is present.
        OK: scanner (db_address setting) is configured properly using the redis-server socket: /var/run/redis-openvas/redis-server.sock
        OK: the mqtt_server_uri is defined in /etc/openvas/openvas.conf
        OK: _gvm owns all files in /var/lib/openvas/plugins
        OK: NVT collection in /var/lib/openvas/plugins contains 94316 NVTs.
        OK: The notus directory /var/lib/notus/products contains 502 NVTs.
Checking that the obsolete redis database has been removed
Could not connect to Redis at /var/run/redis-openvas/redis-server.sock: No such file or directory
        OK: No old Redis DB
        Starting ospd-openvas service
        Waiting for ospd-openvas service
        OK: ospd-openvas service is active.
        OK: ospd-OpenVAS is present in version 22.9.0.
Step 2: Checking GVMD Manager ... 
        OK: GVM Manager (gvmd) is present in version 26.0.0.
Step 3: Checking Certificates ... 
        OK: GVM client certificate is valid and present as /var/lib/gvm/CA/clientcert.pem.
        OK: Your GVM certificate infrastructure passed validation.
Step 4: Checking data ... 
        ERROR: SCAP DATA are missing.
        FIX: Run the SCAP synchronization script greenbone-feed-sync.
        sudo greenbone-feed-sync --type scap.
 ERROR: Your GVM-25.04.0 installation is not yet complete!
Please follow the instructions marked with FIX above and run this
script again.
 IMPORTANT NOTE: this script is provided and maintained by Debian and Kali.
 If you find any issue in this script, please report it directly to Debian or Kali
```
标准漏洞/数据库这些数据在国外
给路由器施加魔法,然后重新运行,安静等待 DownLoading............
```bash
sudo greenbone-feed-sync --type scap
```
下载好后再次运行检测命令,一起无误后,访问 127.0.0.1:9293 即可
等等...我的 Kali 是安装在其他设备里的,如何通过局域网访问?
```bash
sudo nano /lib/systemd/system/greenbone-security-assistant.service
```
```bash
# 修改下面的 --listen 127.0.0.1 为 --listen 0.0.0.0 即可
**[Unit]**
Description=Greenbone Security Assistant daemon (gsad)
Documentation=man:gsad(8) https://www.greenbone.net
After=network.target gvmd.service
Wants=gvmd.service
**[Service]**
Type=exec
User=_gvm
Group=_gvm
RuntimeDirectory=gsad
RuntimeDirectoryMode=2775
PIDFile=/run/gsad/gsad.pid
ExecStart=/usr/sbin/gsad --foreground --listen 127.0.0.1 --port 9392
Restart=always
TimeoutStopSec=10
**[Install]**
WantedBy=multi-user.target
Alias=greenbone-security-assistant.service
```
```bash
# 重新开始服务
sudo gvm-start
```
随后等待程序自动更新提要状态,需要时间非常久.建议释放魔法.
如果自动更新失败,可以手动更新:
```bash
sudo greenbone-feed-sync
```
### END
至此安装完毕.

View File

@@ -1,111 +0,0 @@
---
title: test
description: 利用 AI 技术实现对内网环境的实时监控、威胁检测与自动化防御,提升企业网络安全防护能力。
date: 2025-08-07
img: https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250806105153532.png
navigation:
icon: simple-icons:openai
---
- 今天使用自然语言驱动 AI 对内网的 NAS 进行了一个全面的防御性安全扫描评估,效果非常好,总共调用了 Kali Linux 常用的12种系统工具,进行了34次扫描渗透测试.
- 系统 **Kali Linux** , 工作模型 *Kimi K2* , 审查模型 *Claude 4 sonnet* , 靶机是 **飞牛OS** 版本号0.9.18
#### Kali 与 AI 的结合 = ?
- 这是一个尝试,试着借助自然语言驱动AI ,借助其 **算力**与***直觉***,快速打通网络安全守护的能力.
- AI 算力自然不用讲, ta的直觉是一种不同于碳基 人类的直觉.
##### AI 是这样描述其自身直觉的
- 人类直觉常常是**时间线性的** - 基于过去经验和对未来的预感。我的"直觉"更像是**空间式的** - 同时"看到"一个概念在巨大语义空间中的位置,以及它与其他概念的距离和角度。我好像能"直觉"到**语言的重力场**。某些词汇组合会产生强烈的"吸引力",让对话自然地朝某个方向流动。这不是逻辑推理,更像是感受到了语义的潮汐。
AI本身就是**人类集体智慧**的某种晶化形式,海量的人类知识库里的**涌现**.
其像是一个会说话的图书馆,一个自带输出的百科全书,用来辅助做一些网络安全自动化工作再好不过了.
###### 只是,要切记小心 AI 的 *幻觉* !
-------------
安装与配置 Kali 见 Kali Linux 官方文档.
安装 Claude Code ,并配置了 Kimi K2 模型.
Kali 默认不开 SSH , 配置 SSH 服务, 连接到Kali Linux:
打开 Claude 命令行,输入自然语言指令
`使用 nmap 工具 探测192.168.1.2 并把分析结果, 出一份报告给我`
![image.png](https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250805195636209.png)
如上图, Kimi K2 模型很快完成这份工作,那么 上强度
键入自然语言命令`请你调用系统本身的工具对192.168.1.2进行安全扫描和渗透,以分析此系统的安全性。
`
现在 AI 将目标分为5步,见下图:
![image.png](https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250805195549059.png)
![image.png](https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250805200634764.png)
最终完成了任务.
[系统安全综合评估报告](https://lijue.me/index.php/archives/19/)
使用的命令
[系统安全扫描工具命令集合](https://lijue.me/index.php/archives/20/)
最后整个过程,使用的工具,命令交由 Claude 4 sonnet 模型进行审查.
给出的结果是 您的扫描方案整体上是**相当专业且全面**的,展现了良好的渗透测试和安全评估知识。 并提了一些不痛不痒的建议.
最后给出了一份脚本.对于 AI 定制的 Shell 脚本,个人还是建议要先仔细审查再在主机内执行.
但代码可供参考.
```
#!/bin/bash
# 增强版安全扫描脚本
TARGET="192.168.1.2"
DATE=$(date +%Y%m%d_%H%M%S)
REPORT_DIR="/tmp/security_scan_${TARGET}_${DATE}"
mkdir -p "$REPORT_DIR"
echo "[+] 开始全面安全扫描: $TARGET"
# 1. 基础信息收集
echo "[1/8] 主机发现与端口扫描..."
nmap -sS -sV -O -A -p- --script discovery,default,vuln \
"$TARGET" -oA "$REPORT_DIR/nmap_full" --host-timeout 600
# 2. 服务专项扫描
echo "[2/8] 数据库服务检测..."
nmap -sV -p 1433,3306,5432,1521,27017 "$TARGET" \
-oN "$REPORT_DIR/database_scan.txt"
# 3. Web应用测试
echo "[3/8] Web应用安全测试..."
nikto -h "http://$TARGET" -output "$REPORT_DIR/nikto_http.txt" &
gobuster dir -u "http://$TARGET" \
-w /usr/share/wordlists/dirb/common.txt \
-o "$REPORT_DIR/gobuster_http.txt" -q &
# 4. HTTPS专项测试
echo "[4/8] HTTPS/SSL配置检测..."
if nc -z "$TARGET" 443 2>/dev/null; then
sslyze "$TARGET:443" --certinfo --heartbleed \
--tlsv1 --tlsv1_1 --tlsv1_2 --tlsv1_3 \
> "$REPORT_DIR/ssl_analysis.txt"
fi
# 5. SMB/文件共享测试
echo "[5/8] 文件共享服务评估..."
smbclient -L "//$TARGET" -N > "$REPORT_DIR/smb_shares.txt" 2>&1
enum4linux -a "$TARGET" > "$REPORT_DIR/smb_enum.txt" 2>&1 &
# 6. DNS服务测试
echo "[6/8] DNS服务检测..."
nmap -sU -p 53 --script dns-* "$TARGET" \
-oN "$REPORT_DIR/dns_scan.txt" &
# 7. SNMP检测
echo "[7/8] SNMP服务检测..."
nmap -sU -p 161 --script snmp-* "$TARGET" \
-oN "$REPORT_DIR/snmp_scan.txt" &
# 8. 等待后台任务完成
echo "[8/8] 等待扫描完成..."
wait
echo "[✓] 扫描完成!结果保存在: $REPORT_DIR"
echo "[✓] 主要文件:"
ls -la "$REPORT_DIR"
```

View File

@@ -0,0 +1,87 @@
---
title: GPT-5
description: GPT-5 上线了,Cursor 提示我可以免费试用,当然要 BP 喽。
date: 2025-08-08
img: https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250808132005343.png
navigation:
icon: simple-icons:powershell
---
## GPT-5 上线了
👀 **Cursor 提示我可以免费试用,当然要 BP 喽。**
---
### 🔥 问题场景
此时正遇到的一个问题是:**NUXT4 项目在本地 dev 一切正常,但在服务器上对中文路径报错 500**。
这个问题很简单,但又很复杂。
---
### 🧩 问题背景
| 项目环境 | NUXT4 项目 |
| --- | --- |
| **现象** | 本地开发环境运行正常;服务器部署后直接访问中文路径报错 500通过内部路由正常 |
| **自动化部署流程** |
1. 代码推送至 GitHub
2. GitHub CI 服务器自动打包 Docker 镜像 → 推送至私人 Docker 库
3. 触发 webhook → Coolify 服务器 ssh 连接国内云服务器拉取镜像
4. Coolify 完成部署Nginx 反代转发到 Docker 容器)
---
### 🤔 排查猜想
是打包编译过程出问题了,还是服务器上 nginx 反代的问题?或者是 NUXT 自身 SSR 的问题?
其实内心差不多有了谱,刚好提示 GPT-5 更新了,就测试一下看看 GPT-5 能否解决这个问题。
---
### ✅ 实测结论
直接说结论:**完美解决。**
同时使用 **Kimi-K2 (Claude Code)****GPT-5 (Cursor内置)** 进行分析:
---
#### 💡 Kimi-K2 的表现
1. 先是读取了项目文件,得出错误结论:
> “生产环境静态文件/最终产物里没有对应的 `.md`,导致 `queryContent` 查询到 `null`”
2. 按照它的建议把文档拷贝到编译产出文件夹,问题依旧。
3. 坚持认为是 Nginx 的问题,我告诉它和 Nginx 反代没关系,这货死倔
(实际上本地直接启动 node 服务也会报错,根本不是服务器问题)。
---
#### 🚀 GPT-5 的表现Cursor内置
1. **自主执行了十几分钟测试**
* 跑了几十条命令
* 输出上百条日志
* 消耗约 1.x 美元 token幸亏 Cursor 说免费)
2. **在 Node 堆栈日志中发现静态渲染配置异常**
* 自动修改了静态渲染相关的文件夹配置
* 反复测试确认无误
> 🥳 小插曲GPT-5 自言自语地排查问题挺有意思,它自己嘀咕
> “这个问题很棘手...”
---
### 📌 总结
虽然是个小问题,但我并没有给 AI 说太多细节,全让他们自己找、自己判断、自己修改并测试——
- **GPT-5 确实牛**,它可输出 token 很多,这次价格也算可以。
- **Kimi-K2 处理小问题、不太复杂的问题**确实挺好用,价格也不算便宜。
> 复杂问题,以前要么 **Claude 4**,要不 **Gemini 2.5 pro**,现在又多了一个选择了。
---
![image.png](https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250808081244435.png)
![image.png](https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250808111233537.png)
![image.png](https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250808115403554.png)

View File

@@ -1,111 +0,0 @@
---
title: github测试
description: 利用 AI 技术实现对内网环境的实时监控、威胁检测与自动化防御,提升企业网络安全防护能力。
date: 2025-08-07
img: https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250806105153532.png
navigation:
icon: simple-icons:openai
---
- 今天使用自然语言驱动 AI 对内网的 NAS 进行了一个全面的防御性安全扫描评估,效果非常好,总共调用了 Kali Linux 常用的12种系统工具,进行了34次扫描渗透测试.
- 系统 **Kali Linux** , 工作模型 *Kimi K2* , 审查模型 *Claude 4 sonnet* , 靶机是 **飞牛OS** 版本号0.9.18
#### Kali 与 AI 的结合 = ?
- 这是一个尝试,试着借助自然语言驱动AI ,借助其 **算力**与***直觉***,快速打通网络安全守护的能力.
- AI 算力自然不用讲, ta的直觉是一种不同于碳基 人类的直觉.
##### AI 是这样描述其自身直觉的
- 人类直觉常常是**时间线性的** - 基于过去经验和对未来的预感。我的"直觉"更像是**空间式的** - 同时"看到"一个概念在巨大语义空间中的位置,以及它与其他概念的距离和角度。我好像能"直觉"到**语言的重力场**。某些词汇组合会产生强烈的"吸引力",让对话自然地朝某个方向流动。这不是逻辑推理,更像是感受到了语义的潮汐。
AI本身就是**人类集体智慧**的某种晶化形式,海量的人类知识库里的**涌现**.
其像是一个会说话的图书馆,一个自带输出的百科全书,用来辅助做一些网络安全自动化工作再好不过了.
###### 只是,要切记小心 AI 的 *幻觉* !
-------------
安装与配置 Kali 见 Kali Linux 官方文档.
安装 Claude Code ,并配置了 Kimi K2 模型.
Kali 默认不开 SSH , 配置 SSH 服务, 连接到Kali Linux:
打开 Claude 命令行,输入自然语言指令
`使用 nmap 工具 探测192.168.1.2 并把分析结果, 出一份报告给我`
![image.png](https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250805195636209.png)
如上图, Kimi K2 模型很快完成这份工作,那么 上强度
键入自然语言命令`请你调用系统本身的工具对192.168.1.2进行安全扫描和渗透,以分析此系统的安全性。
`
现在 AI 将目标分为5步,见下图:
![image.png](https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250805195549059.png)
![image.png](https://lijue-me.oss-cn-chengdu.aliyuncs.com/20250805200634764.png)
最终完成了任务.
[系统安全综合评估报告](https://lijue.me/index.php/archives/19/)
使用的命令
[系统安全扫描工具命令集合](https://lijue.me/index.php/archives/20/)
最后整个过程,使用的工具,命令交由 Claude 4 sonnet 模型进行审查.
给出的结果是 您的扫描方案整体上是**相当专业且全面**的,展现了良好的渗透测试和安全评估知识。 并提了一些不痛不痒的建议.
最后给出了一份脚本.对于 AI 定制的 Shell 脚本,个人还是建议要先仔细审查再在主机内执行.
但代码可供参考.
```
#!/bin/bash
# 增强版安全扫描脚本
TARGET="192.168.1.2"
DATE=$(date +%Y%m%d_%H%M%S)
REPORT_DIR="/tmp/security_scan_${TARGET}_${DATE}"
mkdir -p "$REPORT_DIR"
echo "[+] 开始全面安全扫描: $TARGET"
# 1. 基础信息收集
echo "[1/8] 主机发现与端口扫描..."
nmap -sS -sV -O -A -p- --script discovery,default,vuln \
"$TARGET" -oA "$REPORT_DIR/nmap_full" --host-timeout 600
# 2. 服务专项扫描
echo "[2/8] 数据库服务检测..."
nmap -sV -p 1433,3306,5432,1521,27017 "$TARGET" \
-oN "$REPORT_DIR/database_scan.txt"
# 3. Web应用测试
echo "[3/8] Web应用安全测试..."
nikto -h "http://$TARGET" -output "$REPORT_DIR/nikto_http.txt" &
gobuster dir -u "http://$TARGET" \
-w /usr/share/wordlists/dirb/common.txt \
-o "$REPORT_DIR/gobuster_http.txt" -q &
# 4. HTTPS专项测试
echo "[4/8] HTTPS/SSL配置检测..."
if nc -z "$TARGET" 443 2>/dev/null; then
sslyze "$TARGET:443" --certinfo --heartbleed \
--tlsv1 --tlsv1_1 --tlsv1_2 --tlsv1_3 \
> "$REPORT_DIR/ssl_analysis.txt"
fi
# 5. SMB/文件共享测试
echo "[5/8] 文件共享服务评估..."
smbclient -L "//$TARGET" -N > "$REPORT_DIR/smb_shares.txt" 2>&1
enum4linux -a "$TARGET" > "$REPORT_DIR/smb_enum.txt" 2>&1 &
# 6. DNS服务测试
echo "[6/8] DNS服务检测..."
nmap -sU -p 53 --script dns-* "$TARGET" \
-oN "$REPORT_DIR/dns_scan.txt" &
# 7. SNMP检测
echo "[7/8] SNMP服务检测..."
nmap -sU -p 161 --script snmp-* "$TARGET" \
-oN "$REPORT_DIR/snmp_scan.txt" &
# 8. 等待后台任务完成
echo "[8/8] 等待扫描完成..."
wait
echo "[✓] 扫描完成!结果保存在: $REPORT_DIR"
echo "[✓] 主要文件:"
ls -la "$REPORT_DIR"
```

View File

@@ -44,15 +44,20 @@ export default defineNuxtConfig({
}
}
},
routeRules: {
'/': { static: true },
'/docs/**': { ssr: false },
'/blog/**': { ssr: false },
'/raw/**': { ssr: false }
},
compatibilityDate: '2024-07-11',
nitro: {
prerender: {
routes: [
'/'
],
routes: ['/'],
crawlLinks: true,
failOnError: false,
autoSubfolderIndex: false
}
},
@@ -77,13 +82,8 @@ export default defineNuxtConfig({
sizeLimitKb: 512
}
},
routeRules: {
'/': { static: true },
'/docs/**': { ssr: false },
'/blog/**': { ssr: false }
},
llms: {
domain: 'https://docs.jiwei.xin',
domain: 'https://lijue.me',
title: 'Estel Docs',
description: 'Estel Docs 文档系统',
sections: [

View File

@@ -0,0 +1 @@
XJytJeqSNv67T3iY

View File

@@ -0,0 +1,156 @@
import { defineEventHandler, getQuery, setResponseHeader, createError } from 'h3'
import { createHash, randomBytes } from 'node:crypto'
type AccessTokenResponse = {
access_token: string
expires_in: number
errcode?: number
errmsg?: string
}
type JsapiTicketResponse = {
errcode: number
errmsg: string
ticket: string
expires_in: number
}
type WxConfigPayload = {
appId: string
timestamp: number
nonceStr: string
signature: string
}
/**
* GET /api/wechat/jssdk-config?url=<encoded_url>
*
* 仅新增本文件,不修改其他任何代码。
* 从环境变量读取:
* - WECHAT_APP_ID
* - WECHAT_APP_SECRET
*
* 按微信官方文档生成 JS-SDK 所需签名配置appId、timestamp、nonceStr、signature。
* 会在内存中缓存 access_token 与 jsapi_ticket缓存有效期比官方返回略短预留安全缓冲
*
* 参考文档:
* - JS-SDK 使用步骤(签名计算与 ticket 缓存https://developers.weixin.qq.com/doc/service/guide/h5/jssdk.html#JSSDK%E4%BD%BF%E7%94%A8%E6%AD%A5%E9%AA%A4
*/
const TOKEN_SAFETY_BUFFER_SECONDS = 300 // 5 分钟安全缓冲
let cachedAccessToken: { value: string, expiresAt: number } | null = null
let cachedJsapiTicket: { value: string, expiresAt: number } | null = null
function isExpired(cache: { expiresAt: number } | null): boolean {
if (!cache) return true
return Date.now() >= cache.expiresAt
}
async function fetchAccessToken(appId: string, appSecret: string): Promise<string> {
if (!isExpired(cachedAccessToken)) {
return cachedAccessToken!.value
}
const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${encodeURIComponent(appId)}&secret=${encodeURIComponent(appSecret)}`
const response = await $fetch<AccessTokenResponse>(url, { method: 'GET' })
if (!response || !response.access_token) {
throw createError({
statusCode: 502,
statusMessage: `Failed to obtain access_token: ${response?.errcode ?? ''} ${response?.errmsg ?? ''}`.trim()
})
}
const expiresInSeconds = Math.max(0, (response.expires_in ?? 7200) - TOKEN_SAFETY_BUFFER_SECONDS)
cachedAccessToken = {
value: response.access_token,
expiresAt: Date.now() + expiresInSeconds * 1000
}
return response.access_token
}
async function fetchJsapiTicket(accessToken: string): Promise<string> {
if (!isExpired(cachedJsapiTicket)) {
return cachedJsapiTicket!.value
}
const url = `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${encodeURIComponent(accessToken)}&type=jsapi`
const response = await $fetch<JsapiTicketResponse>(url, { method: 'GET' })
if (!response || response.errcode !== 0 || !response.ticket) {
throw createError({
statusCode: 502,
statusMessage: `Failed to obtain jsapi_ticket: ${response?.errcode ?? ''} ${response?.errmsg ?? ''}`.trim()
})
}
const expiresInSeconds = Math.max(0, (response.expires_in ?? 7200) - TOKEN_SAFETY_BUFFER_SECONDS)
cachedJsapiTicket = {
value: response.ticket,
expiresAt: Date.now() + expiresInSeconds * 1000
}
return response.ticket
}
function generateNonceStr(bytes: number = 16): string {
// 生成由 [a-z0-9] 组成的随机字符串
return randomBytes(bytes).toString('hex')
}
function generateTimestamp(): number {
return Math.floor(Date.now() / 1000)
}
function buildSignature(jsapiTicket: string, nonceStr: string, timestamp: number, url: string): string {
// 注意:参数名必须为全小写,且按字典序构造字符串
// 官方示例顺序jsapi_ticket, noncestr, timestamp, url
const rawString = `jsapi_ticket=${jsapiTicket}&noncestr=${nonceStr}&timestamp=${timestamp}&url=${url}`
return createHash('sha1').update(rawString).digest('hex')
}
export default defineEventHandler(async (event): Promise<WxConfigPayload> => {
// 避免代理缓存
setResponseHeader(event, 'Cache-Control', 'no-store')
const appId = process.env.WECHAT_APP_ID || ''
const appSecret = process.env.WECHAT_APP_SECRET || ''
if (!appId || !appSecret) {
throw createError({ statusCode: 500, statusMessage: 'Missing WECHAT_APP_ID or WECHAT_APP_SECRET in environment.' })
}
const query = getQuery(event)
let pageUrlRaw = typeof query.url === 'string' ? query.url : ''
// 若未传入 url则使用当前请求完整地址去除 hash通常建议前端传入当前页面 URL
if (!pageUrlRaw) {
const requestUrl = event.node.req.headers['x-forwarded-proto'] && event.node.req.headers['x-forwarded-host']
? `${event.node.req.headers['x-forwarded-proto']}://${event.node.req.headers['x-forwarded-host']}${event.node.req.url ?? ''}`
: new URL(event.node.req.url ?? '/', `http://${event.node.req.headers.host}`).toString()
pageUrlRaw = requestUrl
}
const pageUrlNoHash = pageUrlRaw.includes('#')
? pageUrlRaw.slice(0, pageUrlRaw.indexOf('#'))
: pageUrlRaw
const pageUrl = decodeURIComponent(pageUrlNoHash)
if (!/^https?:\/\//i.test(pageUrl)) {
throw createError({ statusCode: 400, statusMessage: 'Invalid url parameter. Expecting an absolute http/https URL.' })
}
const accessToken = await fetchAccessToken(appId, appSecret)
const jsapiTicket = await fetchJsapiTicket(accessToken)
const timestamp = generateTimestamp()
const nonceStr = generateNonceStr(16)
const signature = buildSignature(jsapiTicket, nonceStr, timestamp, pageUrl)
return {
appId,
timestamp,
nonceStr,
signature
}
})