全部文章
共 21 篇 · 46,057 字
202621 篇
- 为什么这个站没有 JavaScript
零脚本、零外链资源,CSP 才能收紧到 default-src 'none',不需要任何信任清单。文中给出用纯 CSS 替代脚本的具体做法、可审计性的收益、会失去的能力与替代方案,并说明 JSON-LD 这类 data block 为何不算脚本。
- 把 SSH 换个端口:一次完整的迁移流程
在只有一条 SSH 入口的机器上把端口从 22 换到 2222:为什么用 reload 而非 restart、Port 指令会叠加监听的坑、fail2ban 与防火墙必须同步改、先开后关的顺序,以及换端口为何只是降噪。
- UFW 管不到 Docker 发布的端口——原理与补法
容器发布端口走的是 FORWARD 而不是 INPUT,所以 ufw 的 deny incoming 对它完全无效。给出 DOCKER-USER 守卫的写法、验证因果的实验方法,以及三个已经踩过的坑。
- 用一条 Cloudflare Tunnel 收敛全部对外服务
把"逐个暴露端口 + 逐条挂 DNS"改成一条隧道统一出口后,宿主不再监听任何对外端口。记录 ingress 顺序、多副本 HA 的真实作用边界,以及 metrics 默认绑定带来的意外暴露。
- 三百个包与一次内核升级:什么时候必须重启
长期未更新的生产机做一次完整升级,实际要处理的是四件事:先算清包数与内核差距,用 full-upgrade 加非交互 conffile 策略跑完,判断"装了但没生效"并挑重启时机,最后清掉 rc 残留包和 depmod 生成的无主文件。
- iptables、nftables 与 legacy 表:一次封禁规则「消失」的排查
现代发行版里 iptables 命令指向的其实是 iptables-nft,规则被翻译进 nftables 表;fail2ban 的链则要到第一次封禁才创建。常有人说规则不见了,多半是观测后端选错,或链本就还没被创建。
- SSH 主机密钥漂移:声明了三个,只有一个存在
sshd_config 里声明了 ed25519/ecdsa/rsa 三种 HostKey,但实际只有 RSA 密钥文件存在,导致大量老客户端在密钥交换阶段就失败。记录判断依据,以及分批启用新主机密钥时避免把自己锁在外面的做法。
- OpenSSH 8.9 下 RSA 密钥还能不能用?实测三种协商策略
新版 OpenSSH 禁用的是 SHA-1 签名,不是 RSA 本身。用同一把 RSA 密钥强制三种不同算法策略,得到明确结论:默认可用、强制 rsa-sha2-256 可用、强制 ssh-rsa 被拒。
- 自动更新开了,但只覆盖一部分源——怎么验证它真的按你预期在跑
unattended-upgrades 的默认 Allowed-Origins 只含 release 与 security 两个 pocket,universe 组件的补丁不会自动装。记录用 --dry-run --debug 读 apt 的 pin 行为来验证覆盖范围的方法,以及两个容易误读的输出。
- 用 Cloudflare Access 替代应用的弱认证
隧道只解决了网络暴露,认证责任仍默认落在应用自身,而自托管应用的门锁往往很弱。本文比较应用层、反代层与边缘层三种认证位置的能力差异,给出用 curl 首跳 302 判断 Access 是否生效的方法,并划清它不能替代应用授权的边界。
- 每次开机都报 swap 单元已存在——一次 fstab 重复项排查
systemd-fstab-generator 每次开机都失败,原因只是 fstab 里多了一行。记录用生成器二进制复现、用时间窗对比日志来证明修复的方法,以及一处我自己的取证失误。
- Docker 网络排查手册:容器连不上时按什么顺序看
容器连不上其实是三条互不相干的路径:容器间靠嵌入式 DNS 解析服务名,宿主访问靠端口发布加 DNAT,外部访问再叠一层防火墙。按网络成员、监听地址、NAT 规则的顺序查,多数问题在前两步就能定位。
- 自托管笔记应用:配置项覆盖与反代要点
环境变量不是默认值而是强制值——每次启动都会覆盖界面里的修改,这是"改了密码不生效"的根因。另记单/多用户模式、数据卷属主、共享网络下的监听地址与 TLS 终止边界。
- 把 QQ 机器人接进 Agent:OneBot 反向 WebSocket 的工程细节
用 QQ 协议端把群消息桥接给 Agent 框架的工程笔记:对比正向与反向 WebSocket 的连接方向、反向 WS 为何适合容器、监听地址如何构成安全边界,以及无配置项时的补丁与回归检测、array 与 string 事件格式、登录态持久化与网络模式取舍。
- 「正常时静默」:一个存活看护脚本的设计
Docker 的健康检查只报告不自愈,隧道存活要靠外部看护。记录一个「正常时静默」的检查脚本:检查项如何取舍、端口绑定范围为什么必须单独看、15 分钟频率的理由,以及告警通道自己失效时该怎么办。
- systemd 单元的依赖语义与 reload 的真实行为
Wants/Requires/PartOf 的区别在于故障方向与传播方向;enabled 与「当前生效」是两件事;生成器可以用任意输出目录直接调用,因此能低成本复现开机行为。附本次实际遇到的三个反直觉现象。
- 域名卫生:TXT、SPF、DMARC 与一个「看起来像真站」的域名
一个没有任何 TXT 记录的域名,比没有网站更早暴露「临时域」的身份。SPF、DMARC、CAA 各在防什么、最小写法如何,以及一组可执行的 dig 检查序列和每项有值与留空的判读依据。
- 公开面审计:哪些服务该公网可读,哪些必须私有
把「有登录页」当成安全的后果,是域名下堆起一片产品名的登录墙:匿名访客一无所获,风险却照单全收。给出三种暴露形态的判据、一次可复现的公开面审计流程,以及按代价排序的四档处置与「门面静态化」原则。
- 把 Cloudflare API 接进 Agent 工具链
通过 MCP 把云平台 API 暴露给 Agent 之后,真正需要设计的不是连接本身,而是权限边界与回滚路径:token 按最小范围发放、写操作前先导出快照、下发脚本保持幂等,并警惕 PUT 整表语义。
- 因果对照:证明「是这条规则挡住的」
「加了规则之后就连不上了」只证明时间相关,不证明因果。用三组对照把它升级为因果:有规则时阻断、移除同一条规则后放行、计数器增量落在该规则上;并说明时间窗对比为何必须确认窗口内确有触发事件,以及两类常见的取证失误。
- tmux 实用要点:会话、窗格与脚本化用法
会话独立于终端连接而存在,这是远程运维里最核心的价值;以及 send-keys / capture-pane 让交互式程序可被脚本驱动。最后说明何时该改用 systemd 而不是「挂在 tmux 里」。