欢迎来到我的博客

Hugo 使用指南

Hugo 使用指南 适用版本:Hugo v0.168.0(Extended)。命令以 macOS/Linux 的 shell 为例。根据 Hugo 官方文档整理,主题私有配置以实际主题仓库为准。 1. 安装与版本检查 macOS(Homebrew): brew install hugo hugo version hugo env Linux 可使用对应发行版软件包或 Hugo 官方发布的二进制文件。使用 SCSS/Sass 或某些主题资产管道时,需要确认安装版本包含 Extended 功能。 2. 创建项目 hugo new project myblog cd myblog git init 典型目录结构: myblog/ ├── archetypes/ # 新文章模板 ├── assets/ # 需通过资源管道处理的资源 ├── content/ # Markdown 内容 ├── data/ # 数据文件 ├── i18n/ # 主题界面翻译 ├── layouts/ # 自定义模板,可覆盖主题模板 ├── static/ # 原样复制到网站根路径 ├── themes/ # 本地主题或 Git 子模块 ├── hugo.toml # 网站配置(也可使用 YAML 等格式) └── public/ # 构建产物(运行 hugo 后生成) Hugo 本体不附带完整博客外观。若没有可用主题或自定义布局,可能出现 found no layout file for "html" 的警告。 ...

October 17, 2026 · 3 min

Mac 与 iPhone 使用客户端证书访问 mTLS 网站

Mac 与 iPhone 使用客户端证书访问 mTLS 网站 本文记录在 macOS 和 iPhone 上使用客户端证书访问内网 mTLS 网站的方法,涉及 CanoKey PIV、step-ca、Nginx 和 iOS 系统证书安装。 1. 环境与认证流程 当前环境: CA:已有的 CX-Homelab-CA Root CA 和 CX-Homelab-CA Intermediate CA。 证书签发:step-ca。 Web 服务器:Nginx 1.25.0。 测试站点:https://www.home.arpa。 Mac 客户端:CanoKey PIV 9A。 iPhone 客户端:通过 PKCS#12 文件导入客户端证书及私钥。 mTLS 与普通 HTTPS 的区别是:服务器验证客户端证书,客户端也需要验证服务器证书。客户端证书必须包含对应的私钥,单独安装 .crt 文件通常不足以完成客户端身份认证。 基本流程如下: 客户端访问 HTTPS 站点。 Nginx 请求客户端证书。 浏览器或系统选择客户端身份,并使用对应私钥完成 TLS 握手。 Nginx 验证客户端证书的有效性、证书链和用途。 验证通过后,服务器允许访问受保护的资源。 需要注意,客户端证书和服务器 CA 信任是两个不同的问题。安装客户端身份,并不意味着设备已经信任签发网站服务器证书的私有 CA。 2. Mac:使用 CanoKey PIV 9A 2.1 当前方案 Mac 使用 CanoKey 的 PIV 9A 槽保存客户端身份。macOS 通过智能卡相关机制识别证书和私钥,浏览器在 TLS 握手时使用该身份。 ...

October 26, 2026 · 3 min

macOS 与 iOS 使用客户端证书访问 mTLS 网站

macOS 与 iOS 使用客户端证书访问 mTLS 网站 本文介绍如何在 macOS 和 iOS 设备上配置客户端证书,以访问启用双向 TLS(mTLS)的 HTTPS 网站。示例使用私有 CA、step-ca、Nginx、PKCS#12 和 PIV 智能卡。文中的域名、证书名称、文件名和 IP 地址均为示例,请替换为自己的实际值。 1. mTLS 认证流程 普通 HTTPS 主要由客户端验证服务器证书;mTLS 还要求服务器验证客户端证书。 基本流程: 客户端访问 HTTPS 站点。 Nginx 在 TLS 握手期间请求客户端证书。 浏览器或系统选择客户端身份,并使用对应私钥完成签名。 Nginx 根据配置验证客户端证书、证书链和有效期。 验证通过后,连接进入 HTTP 层,由站点策略决定是否允许访问。 客户端身份和服务器 CA 信任是两个独立配置: 客户端身份:客户端证书及与之匹配的私钥,用于向服务器证明身份。 服务器 CA 信任:客户端信任签发网站服务器证书的 CA,用于验证 HTTPS 服务器身份。 安装客户端证书不会自动让设备信任私有 CA。 2. macOS:使用 PIV 硬件密钥 如果客户端私钥保存在支持 PIV 的硬件密钥中,可以让私钥留在硬件设备内,避免导出私钥文件。浏览器是否能使用该身份,取决于 macOS、智能卡中间件、密钥设备和浏览器的支持情况。 一般检查步骤: 插入 PIV 硬件密钥。 确认 macOS 能识别智能卡及其证书。 打开浏览器并访问 mTLS 网站。 如果浏览器请求客户端证书,选择对应的身份。 按提示输入 PIN 或完成硬件操作。 结合页面结果和服务器日志确认认证是否成功。 可用以下命令检查系统状态: ...

October 26, 2026 · 4 min

用 YubiKey 保护 Git:FIDO2 SSH 认证与提交签名

Git 的仓库认证与提交签名是两个独立环节:前者决定能否拉取、推送代码,后者让接收者验证提交由哪把密钥签署。本文使用两对独立的 FIDO2 SSH 密钥,将这两个用途分开管理。 Git 支持使用 SSH 密钥签署 Commit 和 Tag,因此只围绕 Git 开发时,可以直接使用 YubiKey 的 FIDO2 功能,无须额外部署 GnuPG。需要遵循 OpenPGP 验签流程的项目,则应按项目要求选择 GPG 签名。 ...

October 25, 2026 · 5 min

OpenWrt IPv6 有地址却提示网络不可达:一次 mwan3 策略路由排查

WAN6 已拿到 IPv6 地址,但在 OpenWrt 上 ping 公网 IPv6 时,立即返回: ping: sendto: Network unreachable 最后发现,现场存在一条与 mwan3 一致的带标记不可达规则。删除它后,IPv6 恢复。这个案例说明:看到了默认路由,也不代表实际流量一定会使用它。 本文记录一次实际排查。公网源地址已替换为文档示例地址;设备名、规则优先级和 mark 应以自己的设备为准。卸载命令适用于使用 opkg 的 OpenWrt。 默认路由存在,为什么仍然不可达 最初排查时怀疑默认路由缺失,随后输出已经能看到带源地址条件的默认路由: default from 2001:db8:1234:5600::4 via fe80::1 dev eth1 proto static metric 512 pref medium default from 2001:db8:1234:5600::/64 via fe80::1 dev eth1 proto static metric 512 pref medium 排查中还临时补了一条普通默认路由: ip -6 route add default via fe80::1 dev eth1 metric 1024 但 ping 仍立即返回 Network unreachable。此时继续叠加默认路由已经没有帮助,需要检查实际选路和策略规则。 先确认上游网关可达 ping -6 -I eth1 -c 3 fe80::1 三次请求全部收到回复,说明 OpenWrt 到上游网关的链路本地通信正常。IPv6 使用 fe80:: 开头的链路本地地址作为下一跳是正常现象;这里指定设备,是为了确定该地址属于哪条链路。 ...

October 24, 2026 · 2 min

OpenList 夸克 WebDAV 上传内存过高:原因与优化

使用 rclone 将本地文件通过 OpenList 的 WebDAV 接口上传到夸克网盘时,OpenList 的内存占用可能明显增长,甚至触发容器 OOM。排查后发现,关键在于夸克驱动上传前的整文件缓存,以及容器统计中包含的文件页缓存。 本文分析针对 OpenList v4.2.7、普通夸克驱动、Docker 和 cgroup v2。其他驱动、其他版本应重新核对实现。 夸克上传为什么需要缓存 OpenList 的 WebDAV 入口把 HTTP 请求体包装成文件流,再交给目标存储驱动。这一步本身不统一将整个文件读入内存。 但普通夸克驱动会先取得文件的 MD5 和 SHA1。WebDAV 上传路径没有向文件对象提供这两个哈希,因此驱动调用: stream.CacheFullAndWriter(&up, io.MultiWriter(writers...)) 这个调用在计算哈希的同时,缓存完整文件。随后,驱动向夸克提交预上传和哈希请求;如果不能秒传,再从缓存中读取数据、分片上传。 哈希计算可以使用很小的内存,真正占空间的是为后续回读而保留的文件内容。 即使夸克支持分片上传,也不代表前面的整文件缓存不存在。 v4.2.7 的 HybridCache 有内存和文件两类后备方式。允许使用内存时,会尝试扩充缓存,分配受限后再切换至文件;其中部分内存通过匿名 mmap 管理。因此不能仅靠调整 Go GC 参数约束所有缓存占用。 rclone 的 --transfers 控制同时传输的文件数。两个文件并发上传,意味着两份整文件缓存可能同时存在。降低 rclone 自身的 --buffer-size 并不能直接限制 OpenList 进程中的这部分缓存。 为什么有临时目录仍占用内存 例如: "temp_dir": "data/temp" 这只指定临时文件保存位置,不强制每次缓存都写入磁盘。该相对路径还要结合 OpenList 的工作目录、Docker 挂载判断实际位置。 此外,v4.2.7 的缓存扩容检查使用系统可用内存统计,没有在该检查中直接读取容器的 memory.max 和 memory.current。这使得宿主机尚有空闲内存时,容器仍可能先撞上自己的内存限额。 改用磁盘临时文件 先暂停上传并备份配置,在 config.json 顶层设置: "min_free_memory": -1 这是字段片段,不是完整配置文件,修改时应保留其他内容和合法的 JSON 结构。 ...

October 24, 2026 · 2 min

排查旁路由 DNS 超时:sing-box 上游查询走错网络接口

在一台用作旁路由的 Armbian 上同时运行 sing-box 和 WireGuard。旁路由本机可以解析内网域名,下游终端将其设为 DNS 服务器却始终超时。最终发现问题不在 DNS 匹配规则,而在 sing-box 向上游 DNS 发出的流量选错了出口接口。 本文示例地址均为重写后的示意值,不是原始网络配置;保留了私有网络的拓扑关系与协议行为。 网络拓扑与现象 角色 示例地址 作用 下游终端 192.168.10.20 DNS 客户端 旁路由 LAN 192.168.10.254 / eth0 sing-box DNS 监听地址 旁路由 WireGuard 10.77.0.11 / wg0 隧道客户端 内网 DNS 10.77.0.1:53 WireGuard 对端 DNS 拓扑如下: 终端 192.168.10.20 │ DNS 查询 ▼ 旁路由 192.168.10.254:53 (sing-box DNS 入站) │ 期望:由 wg0 向 10.77.0.1:53 查询 ▼ WireGuard 对端 DNS 10.77.0.1:53 内网测试域名采用 service.home.arpa(示例)。现象是: ...

October 23, 2026 · 2 min

Armbian 上 sing-box 开启 auto_redirect 后 IPv6 HTTPS 超时:一次回环地址缺失的排查

在 Armbian 上部署 sing-box TUN 后,我遇到了一个不太直观的问题:IPv6 ping 能通,但开启 auto_redirect 后,IPv6 HTTPS 连接超时。 最终发现,故障并不在 IPv6 公网路由或代理节点,而是 Linux 回环接口 lo 缺少 ::1/128 地址。本文记录定位过程和修复方法。 环境 Linux:Armbian,ARM64,6.18 系列内核 sing-box:1.14.x 网络管理:Netplan + NetworkManager 透明代理:TUN,auto_route: true,auto_redirect: true IPv6:上游自动配置,接口已有全局 IPv6 地址和 RA 默认路由 为保护隐私,本文省略了真实公网地址、MAC、路由器地址、域名及自定义内部路由表编号。以下示例中的 ULA 地址和测试目标用于演示。 故障现象 直接测试 IPv6 HTTPS: curl --noproxy '*' -6 -v --connect-timeout 5 \ --resolve 'cloudflare.com:443:[2606:4700::6810:85e5]' \ https://cloudflare.com/ 开启 sing-box 后: * Trying [2606:4700::6810:85e5]:443... * Connection timed out after 5002 milliseconds curl: (28) Connection timed out 对照实验: ...

October 23, 2026 · 3 min

Docker 信任自签名 CA 证书

Docker 使用私有 CA(例如 step-ca)签发的 HTTPS 证书时,需要区分 Docker Engine 拉取镜像 和 容器内应用访问 HTTPS 两种场景。它们的证书信任库不一定相同。 一、Docker Engine 信任私有 CA 适用于 docker login、docker pull、docker push 访问私有镜像仓库。 仅信任指定 Registry(推荐) 假设 Registry 地址为 registry.example.com:5000: sudo mkdir -p /etc/docker/certs.d/registry.example.com:5000 sudo cp root_ca.crt /etc/docker/certs.d/registry.example.com:5000/ca.crt 目录名称应与实际访问的 Registry 主机名及端口一致;默认 HTTPS 443 端口通常可省略。ca.crt 应为 PEM 格式的 CA 证书,而不是私钥。 验证: docker login registry.example.com:5000 Ubuntu / Debian 宿主机全局信任 sudo cp root_ca.crt /usr/local/share/ca-certificates/my-root-ca.crt sudo update-ca-certificates Linux 上 Docker 通常会使用宿主机的系统 CA 信任库。通常不必重启 Docker;如果仍未生效,可检查 Docker 日志及证书配置,再决定是否重启(重启可能影响运行中的容器)。 ...

October 23, 2026 · 1 min

UFW 与 sing-box TUN auto_redirect 冲突:动态端口被拦截的排查

在 Linux 旁路由上同时运行 UFW 和 sing-box TUN 时,可能出现一种容易误判的故障:sing-box 本机运行正常,但局域网设备通过旁路由访问互联网失败。即使放行了当时被拦截的 TCP 端口,重启 sing-box 后问题也可能再次出现。 本文记录一种实际观察到的原因和待回归验证的修复方式。示例均使用文档保留地址,不对应真实网络。 环境和症状 Linux 旁路由,LAN 接口为 eth0,地址 192.0.2.1(仅作示例)。 下游终端 192.0.2.20,使用旁路由作为 IPv4 网关。 sing-box 的 TUN 接口名为 tun0,开启 auto_route 和 auto_redirect。 UFW 默认拒绝未经允许的入站流量。 sing-box 的关键配置: { "type": "tun", "interface_name": "tun0", "auto_route": true, "auto_redirect": true } 故障期间日志类似: [UFW BLOCK] IN=eth0 OUT= SRC=192.0.2.20 DST=192.0.2.1 PROTO=TCP DPT=24461 SYN DPT=24461 只是一次运行时观察到的动态端口,不应该把它永久写死在 UFW 里。OUT= 为空,提示包正在进入本机的 INPUT 路径,而不只是穿过 FORWARD 路径。 追踪 NAT 重定向 检查 sing-box 监听: sudo ss -lntup | grep sing-box 检查 nftables: ...

October 23, 2026 · 2 min