diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 12967bf..cd4a296 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -44,6 +44,10 @@ export default defineConfig({ search: { provider: 'local' + }, + + footer: { + copyright: 'Copyright © 2023-2026 Kegongteng' } } }) diff --git a/.vitepress/sidebar.mts b/.vitepress/sidebar.mts index 1cc119f..ee275a8 100644 --- a/.vitepress/sidebar.mts +++ b/.vitepress/sidebar.mts @@ -32,6 +32,7 @@ type SidebarDocMeta = { order: number text: string link: string + subOrder?: number } type OrderedSidebarItem = { @@ -39,7 +40,7 @@ type OrderedSidebarItem = { text: string item: SidebarItem subOrder?: number - source: 'doc' | 'subheading' + source: 'doc' } type HeadingBucket = { @@ -107,7 +108,7 @@ function toDirectoryLink(relativePath: string) { function toDocMeta(absDir: string, relativeDir: string, fileName: string): SidebarDocMeta { const full = path.join(absDir, fileName) - const { order, title } = readFrontmatterAndTitle(full) + const { order, title, subOrder } = readFrontmatterAndTitle(full) const baseName = path.basename(fileName, '.md') const rel = relativeDir ? `${relativeDir}/${baseName}` : baseName @@ -118,6 +119,8 @@ function toDocMeta(absDir: string, relativeDir: string, fileName: string): Sideb order, text: title, link + , + subOrder } } @@ -126,6 +129,7 @@ function toOrderedSidebarItem(doc: SidebarDocMeta): OrderedSidebarItem { order: doc.order, text: doc.text, item: { text: doc.text, link: doc.link }, + subOrder: doc.subOrder, source: 'doc' } } @@ -134,24 +138,8 @@ function toOrderedSidebarItems(docs: SidebarDocMeta[]): OrderedSidebarItem[] { return docs.map(toOrderedSidebarItem) } -function createSubheadingEntry( - label: string, - order: number, - subOrder: number | undefined, - items: SidebarItem[] -): OrderedSidebarItem { - return { - order, - text: label, - subOrder, - source: 'subheading', - item: { - text: label, - collapsed: true, - items - } - } -} +// NOTE: subheading/collapsible groups removed in refactor. Files' `sub-order` is used +// to position items within their heading instead. function pushEntryToContainer( entry: OrderedSidebarItem, @@ -229,12 +217,8 @@ function sortBySubOrderAndText(a: } function buildOrderedItems(entries: OrderedSidebarItem[]): SidebarItem[] { - const pinned = entries - .filter((entry) => entry.source === 'subheading' && entry.subOrder !== undefined) - .sort(sortBySubOrderAndText) - const floating = entries - .filter((entry) => entry.source !== 'subheading' || entry.subOrder === undefined) - .sort(sortByOrderAndText) + const pinned = entries.filter((entry) => entry.subOrder !== undefined).sort(sortBySubOrderAndText) + const floating = entries.filter((entry) => entry.subOrder === undefined).sort(sortByOrderAndText) const arranged = [...floating] @@ -287,16 +271,7 @@ function generateSidebarGroups(entry: SidebarAutoItem): OrderedGroup[] { }) } - const addSubheadingToTarget = ( - targetHeadingKey: string | undefined, - label: string, - order: number, - subOrder: number | undefined, - items: SidebarItem[] - ) => { - const entry = createSubheadingEntry(label, order, subOrder, items) - pushEntryToContainer(entry, rootEntries, headingBuckets, targetHeadingKey) - } + // subheading handling removed const walkDirectories = (parentAbsDir: string, parentRelativeDir: string, activeHeadingKey?: string) => { const childDirs = fs.readdirSync(parentAbsDir, { withFileTypes: true }) @@ -316,11 +291,8 @@ function generateSidebarGroups(entry: SidebarAutoItem): OrderedGroup[] { nextActiveHeadingKey = headingKey } - if (meta?.subheading && childItems.length) { - const subOrder = meta.subOrder ?? meta.order - const parentHeadingKey = meta?.heading ? nextActiveHeadingKey : activeHeadingKey - addSubheadingToTarget(parentHeadingKey, meta.subheading, subOrder, meta.subOrder, toSidebarLinkItems(childItems)) - } + // ignore `subheading` frontmatter; child files may use `sub-order` to control + // their position within the parent heading walkDirectories(childAbsDir, childRelativeDir, nextActiveHeadingKey) } diff --git a/columba/dev/index.md b/columba/v1/dev.md similarity index 99% rename from columba/dev/index.md rename to columba/v1/dev.md index c02a2bb..3f803cd 100644 --- a/columba/dev/index.md +++ b/columba/v1/dev.md @@ -1,7 +1,5 @@ --- outline: deep -order: 1 -heading: 开发 sub-order: 4 --- diff --git a/columba/use.md b/columba/v1/index.md similarity index 85% rename from columba/use.md rename to columba/v1/index.md index 5ac578a..b4ec704 100644 --- a/columba/use.md +++ b/columba/v1/index.md @@ -1,7 +1,12 @@ --- outline: deep order: 2 +heading: v1.x +sub-order: 1 --- +::: info 版本提示 +本板块文档仅供V1.x使用 +::: # 使用指南 @@ -12,7 +17,7 @@ order: 2 3. 软件本体无窗口界面,运行后静默驻留系统托盘。您可右键托盘中的“小鸽子”,点击`编辑配置`配置 SMTP 邮件参数、通知模板以及要监控的登录类型。 > [!TIP] -> 您可以参考[《配置文件说明》](/columba/ini)自定义您的配置文件 +> 您可以参考[《配置文件说明》](/columba/v1/ini)自定义您的配置文件 4. 按要求编辑并保存配置之后,您可以右键托盘中的“小鸽子”,点击`测试邮件`来检查 SMTP 邮件参数是否正确,以便后续的通知。 diff --git a/columba/ini.md b/columba/v1/ini.md similarity index 99% rename from columba/ini.md rename to columba/v1/ini.md index ade6aaa..d09c62d 100644 --- a/columba/ini.md +++ b/columba/v1/ini.md @@ -1,6 +1,6 @@ --- outline: deep -order: 3 +sub-order: 2 --- # 配置文件说明 diff --git a/columba/dev/package.md b/columba/v1/package.md similarity index 98% rename from columba/dev/package.md rename to columba/v1/package.md index 60cb11b..3c47534 100644 --- a/columba/dev/package.md +++ b/columba/v1/package.md @@ -1,6 +1,6 @@ --- outline: deep -order: 2 +sub-order: 3 --- # 依赖与打包 diff --git a/columba/v2/index.md b/columba/v2/index.md new file mode 100644 index 0000000..fb493f1 --- /dev/null +++ b/columba/v2/index.md @@ -0,0 +1,65 @@ +--- +outline: deep +order: 1 +heading: v2.x +sub-order: 1 +--- +::: info 版本提示 +本板块文档仅供V2.x使用。 +::: + +# 使用指南 + +1. 较于v1.x,v2.x配置文件存在破坏性修改,请您重新配置。 +2. v2.0版本为归档版本,不按照本说明配置,本说明支持v2.1往后的版本。 + +## 安装 + +1. 加载安装包,并按安装指引其安装至电脑中 + +2. 由于软件需要监听 Windows 安全日志中的登录事件,如首次使用需要通过弹出 UAC 窗口请求管理员权限,请点击 UAC 窗口中的`是`。 + +3. 软件本体无窗口界面,运行后静默驻留系统托盘。您可右键托盘中的“小鸽子”,点击`编辑配置`配置 SMTP 邮件参数、通知模板以及要监控的登录类型。 + +> [!TIP] +> 您可以参考[《配置文件说明》](/columba/v2/ini)自定义您的配置文件 + +4. 按要求编辑并保存配置之后,您可以右键托盘中的“小鸽子”,点击`测试邮件`来检查 SMTP 邮件参数是否正确,以便后续的通知。 + +5. 正确接收到测试邮件之后,软件即可正确运行。 + +::: danger 无法监控? +如果无法正常监控登录事件,您可以右键托盘中的“小鸽子”,点击`查看日志`或`查看失败登录记录`来排查问题。日志文件大小限制为2MB,超过后自动清空,防止磁盘空间被无限占用。 +::: + +## 登录失败每日汇总与防火墙黑名单 + +在该版本中,我们将原先每次失败都发送邮件,改为了每日凌晨12:00发送登录失败每日汇总,以避免短时间内爆破导致邮箱爆炸。 + +另外,您可以通过设置配置文件中的`ban_frequency`来自动添加黑名单,超过该数值则添加至防火墙黑名单(留空或为0则无加入黑名单,只记录)。Columba产生的黑名单策略名称为`Columba Block {ip_str}`,您可以打开Windows 防火墙来手动管理。 + +## 冷却机制 + +为避免登陆类型叠加,而导致同一次登陆成功发送多次邮件,本版本添加冷却机制。在本60s内,同一用户名同 IP 只发一封成功邮件,进而合并那些短时间内由不同登录类型(如交互式和远程交互式)触发的重复通知。 + +## 开机自启 + +您可以通过以下方式,将本软件开机自启: + +### 用户级自启动 + +1. 按下 Win + R 打开“运行”窗口。 + +2. 输`shell:startup`,将需要开机启动的程序 快捷方式 拖入弹出的文件夹。 + +3. 重启电脑验证程序是否自动运行。 + +### 系统级自启动 + +1. 按下 Win + R 打开“运行”窗口。 + +2. 输`shell:common startup`,将需要开机启动的程序 快捷方式 拖入弹出的文件夹。 + +3. 重启电脑验证程序是否自动运行。 + + diff --git a/columba/v2/ini.md b/columba/v2/ini.md new file mode 100644 index 0000000..ba4e52a --- /dev/null +++ b/columba/v2/ini.md @@ -0,0 +1,121 @@ +--- +outline: deep +sub-order: 2 +--- + +# 配置文件说明 + +Columba 的配置文件为 `config.ini`,采用标准 INI 格式,放置于程序同目录下。首次运行前请按需修改,保存时请使用 **UTF-8** 编码。 + +## 文件结构 + +```ini +[SMTP] +server = +port = +username = +password = +from_addr = +to_addr = +use_tls = + +[MESSAGE] +subject_success = +body_success = +subject_failure = +body_failure = + +[SETTINGS] +logon_types = +ban_frequency = +``` + +--- + +## [SMTP] 邮件服务器设置 + +| 键名 | 说明 | 必需 | 示例值 | +|------------|------------------------------------------------------------------------|------|------------------------| +| server | SMTP 服务器地址 | 是 | `smtp.qq.com` | +| port | SMTP 服务器端口(SSL 一般为 465,TLS 一般为 587) | 是 | `465` | +| username | 登录邮箱的用户名(通常为完整邮箱地址) | 是 | `your@qq.com` | +| password | 邮箱密码或授权码(推荐使用授权码) | 是 | `xxxxxxxxxxxxxx` | +| from_addr | 发件人邮箱地址(通常与 username 相同) | 是 | `your@qq.com` | +| to_addr | 收件人邮箱地址,可多个(用逗号分隔) | 是 | `admin@example.com` | +| use_tls | 是否使用 TLS 加密(`true` / `false`)。若端口为 465 一般设为 `false` 使用 SSL,端口 587 设为 `true` | 是 | `false` | + + +## [MESSAGE] 邮件内容模板 + +支持在主题和正文中使用变量,程序会自动替换为实际值。 + +### 主题与正文 + +| 键名 | 说明 | 默认值(示例) | +|-----------------|--------------------|----------------------------------------------------------------------| +| subject_success | 成功登录邮件主题 | `[通知] 用户 {username} 已登录 {computer}` | +| body_success | 成功登录邮件正文 | `用户 {username} 于 {time} 从 {source_ip} 登录 {computer},登录类型:{logon_type_desc}` | + + +### 可用变量 + +| 变量名 | 说明 | 适用事件 | +|--------------------|--------------------------------------------------------------------|----------| +| `{username}` | 登录用户名 | 成功/失败 | +| `{domain}` | 登录域(若为本地账户则为计算机名) | 成功/失败 | +| `{time}` | 登录时间(格式 `YYYY-MM-DD HH:MM:SS`) | 成功/失败 | +| `{computer}` | 计算机名 | 成功/失败 | +| `{source_ip}` | 来源 IP 地址(远程登录时显示,本地登录可能为 `-`) | 成功/失败 | +| `{logon_type}` | 登录类型代码(如 10) | 成功 | +| `{logon_type_desc}`| 登录类型描述(如“远程交互式登录”) | 成功 | +| `{process_name}` | 触发登录的进程名(如 `C:\Windows\System32\svchost.exe`) | 成功 | +| `{failure_reason}` | 失败原因(包含状态码和子状态,如“状态码: 0xC0000064, 子状态: 0”) | 失败 | + +--- + +## [SETTINGS] 配置 + +| 键名 | 说明 | 默认值 | +|--------------|-------------------------------------------------------------------|------------| +| logon_types | 需要监控的登录类型列表,用英文逗号分隔,仅支持数字代码。留空则监控所有类型。 | `2,7,10` | +| ban_frequency | IP失败最大次数,超过添加至防火墙黑名单。留空或为0则无加入黑名单,只记录。 | `5` | + +### 常用登录类型代码 + +| 代码 | 描述 | 典型场景 | +|------|------------------------------|----------------------------| +| 2 | 交互式登录 | 本地控制台登录 | +| 3 | 网络登录 | 访问共享文件夹 | +| 4 | 批处理登录 | 计划任务 | +| 5 | 服务登录 | 系统服务启动 | +| 7 | 解锁登录 | 从屏保或锁屏恢复 | +| 8 | 网络明文登录 | IIS 基本认证 | +| 9 | 新凭证登录 | RunAs 不同用户 | +| 10 | 远程交互式登录 | 远程桌面(RDP) | +| 11 | 缓存交互式登录 | 域控不可达时使用缓存凭证 | + +## 完整配置示例 + +```ini +[SMTP] +server = smtp.qq.com +port = 465 +username = columba@qq.com +password = xxxxxxxxxxxxxx +from_addr = columba@qq.com +to_addr = admin@example.com, backup@example.com +use_tls = false + +[SETTINGS] +logon_types = 2,7,10 +ban_frequency = 5 + +[MESSAGE] +subject_success = Columba 登录通知 - 成功 +body_success = 用户 {username} 在计算机 {computer} 上登录成功 + 登录类型: {logon_type_desc} + 时间: {time} + 来源 IP: {source_ip} + 进程: {process_name} + +--- diff --git a/columba/v2/package.md b/columba/v2/package.md new file mode 100644 index 0000000..1025f84 --- /dev/null +++ b/columba/v2/package.md @@ -0,0 +1,28 @@ +--- +outline: deep +sub-order: 3 +--- + +# 打包与安装包 + +## 打包(Nuitka) + +可使用以下命令生成独立可执行文件: + +```bash +nuitka --standalone --windows-console-mode=disable --windows-uac-admin --include-data-files=config.ini=./config.ini --include-data-files=login_notifier.log=./login_notifier.log --include-data-files=columba.ico=./columba.ico --include-data-files=failure_login.json=./failure_login.json --windows-icon-from-ico=columba.ico 2.py +``` + +## 制作安装包(Inno Setup) + +[Inno Setup](https://jrsoftware.org/isinfo.php)是一个非常好用的安装包制作软件。本软件由于需要管理员权限,直接打包会出现「要求的操作需要提升的权限」的错误消息,您可以参考一下步骤编辑iss脚本配置权限: + +1. 在 Inno Setup 的 Script 的 [Setup] 中加上:`PrivilegesRequired=admin` + +2. 在 [Run] 所有的 Flags 都加上:`runascurrentuser`,例如: + +``` +[Run] +Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent runascurrentuser + +``` \ No newline at end of file