[{"categories":null,"collections":null,"content":"总结小型网络里 RouterOS 脚本和 Scheduler 的维护方式：PCC 模式切换、WireGuard Watchdog、PPPoE Redial、update-blackip、Manifest 和 routerosctl 如何让状态可审计可恢复。","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/","tags":["运维","网络","RouterOS"],"title":"小型网络系列：脚本、Scheduler 和可恢复性","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/"},{"categories":null,"collections":null,"content":"系列导航 小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂 小型网络系列：RouterOS 和 Switch 的职责边界 小型网络系列：LAG、VLAN 和 Macvlan 为什么会一起出现 小型网络系列：PCC 分流逻辑和故障行为 小型网络系列：WireGuard 为什么是日常路径 小型网络系列：脚本、Scheduler 和可恢复性 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/:0:1","tags":["运维","网络","RouterOS"],"title":"小型网络系列：脚本、Scheduler 和可恢复性","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/#系列导航"},{"categories":null,"collections":null,"content":"背景 前面几篇讲的是网络形状：RouterOS 和 Switch 怎么分工，LAG / VLAN / Macvlan 怎么承载 Multi-WAN，PCC 怎么分流，WireGuard 怎么承载日常站点路径。 最后一篇讲一个更运维的问题：这些状态不能只靠手工记忆。 小型网络最容易出现的不是“大型系统崩溃”，而是一些小操作慢慢失控： PCC 模式切错几条规则 WireGuard Peer 偶发 Down 了没人注意 PPPoE 线路长期运行后状态不稳定 黑名单更新靠手工跑 RouterOS 上有哪些脚本、哪些 Scheduler，过几个月没人说得清 DC-101 RouterOS 版本更老，部署能力和新版本不完全一样 所以我现在更倾向于把 RouterOS 的脚本和 Scheduler 做成 repo-backed state。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/:0:2","tags":["运维","网络","RouterOS"],"title":"小型网络系列：脚本、Scheduler 和可恢复性","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/#背景"},{"categories":null,"collections":null,"content":"Manifest 是 Desired State RouterOS 这边的核心不是“把脚本复制过去”，而是 Manifest。 每个 host 有自己的 rsc/\u0026lt;host\u0026gt;/manifest.yml，里面描述： 应该存在的 System Scripts 这些脚本对应哪些文件 Scheduler 应该怎样运行 哪些旧文件或旧脚本应该删除 host 的特殊部署差异 Office-JT、Office-SQ、DC-101 的状态不是一样的。 Site Manifest 重点 Office-JT PCC 模式脚本、WireGuard Watchdog、WireGuard Trigger、print-per-ip-counts、update-blackip Office-SQ WireGuard Watchdog、update-blackip、PPPoE Redial、Watchdog Scheduler DC-101 老 RouterOS 限制更多，保留更简单的 update-blackip 部署方式 这让“当前应该有哪些脚本”变成 repo 里的可审计事实，而不是 RouterOS 终端历史。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/:0:3","tags":["运维","网络","RouterOS"],"title":"小型网络系列：脚本、Scheduler 和可恢复性","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/#manifest-是-desired-state"},{"categories":null,"collections":null,"content":"部署路径 RouterOS 维护现在走 routerosctl.py，不是旧的“复制到某台 PVE 再手工导入”。 常用操作大概是： 1 2 3 make -C router/ros audit HOST=\u0026lt;office-jt\u0026gt; make -C router/ros sync HOST=\u0026lt;office-jt\u0026gt; make -C router/ros install HOST=\u0026lt;office-jt\u0026gt; 这里文章里继续用内部 host label 表达，不展开真实连接方式、密码环境变量或公网 Endpoint。 audit 用来检查 Live State 和 Manifest 是否一致。sync 上传非 secret runtime files。install 会做更完整的安装流程，并留下 pre/post audit evidence。 这个设计的价值在于：我可以知道一次变更之前和之后 RouterOS 长什么样，而不是只知道“我刚刚好像导入了一个脚本”。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/:0:4","tags":["运维","网络","RouterOS"],"title":"小型网络系列：脚本、Scheduler 和可恢复性","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/#部署路径"},{"categories":null,"collections":null,"content":"PCC 脚本的可恢复边界 PCC 脚本是 Office-JT 里最容易出错的一类脚本。 它们的可恢复边界来自前一篇讲的命名： pcc-mark-* 是 Bucket Layer pcc-routing-* 是 Routing Layer 模式切换脚本只禁用 ^pcc-mark- 模式切换脚本只启用自己的 ^pcc-mark-N/ 不动 pcc-routing-* 这意味着 PCC 模式切换可以反复执行。 如果当前想从 1:1:1 切到 0:1:1，脚本不会假设现在的状态干净，而是先把所有 Bucket Rules 收敛，再启用目标组。出问题时，也可以换回另一组模式，而不是手工逐条找哪几条 Mangle Rule 开着。 这不等于完全自动化，但它比手工点规则可靠得多。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/:0:5","tags":["运维","网络","RouterOS"],"title":"小型网络系列：脚本、Scheduler 和可恢复性","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/#pcc-脚本的可恢复边界"},{"categories":null,"collections":null,"content":"WireGuard Watchdog 的边界 WireGuard 是日常路径，但 Watchdog 不应该做太多事。 Office-JT 和 Office-SQ 的 Watchdog 思路都很克制： sequenceDiagram participant Netwatch as RouterOS Netwatch participant Scheduler as Scheduler participant Script as wireguard-watchdog participant Peer as WireGuard Peer Scheduler-\u003e\u003eScript: Run Every 1m Script-\u003e\u003eNetwatch: Read Peer Status alt Peer Down Script-\u003e\u003ePeer: Disable Peer Script-\u003e\u003ePeer: Wait 5s Script-\u003e\u003ePeer: Enable Peer else Peer Up Script--\u003e\u003eScheduler: No Change end sequenceDiagram participant Netwatch as RouterOS Netwatch participant Scheduler as Scheduler participant Script as wireguard-watchdog participant Peer as WireGuard Peer Scheduler-\u003e\u003eScript: Run Every 1m Script-\u003e\u003eNetwatch: Read Peer Status alt Peer Down Script-\u003e\u003ePeer: Disable Peer Script-\u003e\u003ePeer: Wait 5s Script-\u003e\u003ePeer: Enable Peer else Peer Up Script--\u003e\u003eScheduler: No Change end sequenceDiagram participant Netwatch as RouterOS Netwatch participant Scheduler as Scheduler participant Script as wireguard-watchdog participant Peer as WireGuard Peer Scheduler-\u003e\u003eScript: Run Every 1m Script-\u003e\u003eNetwatch: Read Peer Status alt Peer Down Script-\u003e\u003ePeer: Disable Peer Script-\u003e\u003ePeer: Wait 5s Script-\u003e\u003ePeer: Enable Peer else Peer Up Script--\u003e\u003eScheduler: No Change end sequenceDiagram participant Netwatch as RouterOS Netwatch participant Scheduler as Scheduler participant Script as wireguard-watchdog participant Peer as WireGuard Peer Scheduler-\u003e\u003eScript: Run Every 1m Script-\u003e\u003eNetwatch: Read Peer Status alt Peer Down Script-\u003e\u003ePeer: Disable Peer Script-\u003e\u003ePeer: Wait 5s Script-\u003e\u003ePeer: Enable Peer else Peer Up Script--\u003e\u003eScheduler: No Change end 它只做一件事：Peer Down 时重启 Peer。 它不会重写密钥，不会改 Endpoint，不会改 Route，也不会把办公室日常路径切到 NetBird 或 ZeroTier。 这个边界很重要。自动化越小，误伤范围越小。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/:0:6","tags":["运维","网络","RouterOS"],"title":"小型网络系列：脚本、Scheduler 和可恢复性","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/#wireguard-watchdog-的边界"},{"categories":null,"collections":null,"content":"Scheduler 是运行约束 Manifest 里除了脚本，还有 Scheduler。 Office-JT 里有几个典型 Scheduler： pppoe1-redial：周期性重启 PPPoE 接口 watchdog-wg-peer-office-sq：定时执行 WireGuard Watchdog update-blackip：定时更新黑名单 Office-SQ 也有类似的 Watchdog 和 PPPoE Redial。 这些 Scheduler 不是什么高大上的编排系统，它们只是把“我平时会手工做的维护动作”变成固定节奏。 这样做的好处是： 频率明确 目标脚本明确 是否启用可以在 Manifest 里看到 下次换人或过几个月回来排障，不用猜这件事是不是靠某个终端历史在跑 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/:0:7","tags":["运维","网络","RouterOS"],"title":"小型网络系列：脚本、Scheduler 和可恢复性","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/#scheduler-是运行约束"},{"categories":null,"collections":null,"content":"print-per-ip-counts 这种小脚本也有价值 Office-JT 里还有一个很朴素的脚本：统计绑定 DHCP Lease 的客户端，在连接表里找连接数超过阈值的地址。 它不是监控系统，也不负责自动限速。 但它在排障时有用： 某台机器连接数异常高，会影响 PCC 体感 下载器、同步工具、浏览器异常 Tab 都可能把连接表撑大 先看到高连接客户端，再决定要不要调 PCC 或做策略 这也符合这套网络的风格：不追求一次性上完整企业监控和准入治理，但把常见排障动作固化成可以重复执行的小工具。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/:0:8","tags":["运维","网络","RouterOS"],"title":"小型网络系列：脚本、Scheduler 和可恢复性","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/#print-per-ip-counts-这种小脚本也有价值"},{"categories":null,"collections":null,"content":"DC-101 为什么特殊 DC-101 是 RouterOS-based L3 Switching，但它的 RouterOS 版本和能力边界更老。 在部署流程里，它和 Office-JT / Office-SQ 不完全一样： 不支持同样的 import dry-run 流程 不接受较新的 repo-style remote scripts/ directory 方式 Manifest 里需要用更简单的 remote file 形态表达 这类差异要写在稳定文档里，而不是靠人记。 否则自动化最容易在“看起来都是 RouterOS”的地方踩坑。版本不同、设备类型不同，部署能力就可能不同。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/:0:9","tags":["运维","网络","RouterOS"],"title":"小型网络系列：脚本、Scheduler 和可恢复性","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/#dc-101-为什么特殊"},{"categories":null,"collections":null,"content":"最后的结论 这个小型网络不是靠一个巨大的自动化系统维护的。 它更像几层简单机制叠起来： Manifest 描述 RouterOS Desired State routerosctl.py 负责 Audit / Sync / Install PCC 脚本只切 Bucket Layer WireGuard Watchdog 只重启 Peer Scheduler 固化周期性维护动作 小脚本辅助排障，不假装自己是完整监控平台 这套做法很朴素，但适合当前规模。 它的目标不是把网络变成无人值守系统，而是让每次变更和每个自动动作都有边界、有证据、有回退方向。对 300-500 Devices 的小型网络来说，这比堆一套复杂控制平台更现实。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/:0:10","tags":["运维","网络","RouterOS"],"title":"小型网络系列：脚本、Scheduler 和可恢复性","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E8%84%9A%E6%9C%AC-scheduler-%E5%92%8C%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7/#最后的结论"},{"categories":null,"collections":null,"content":"解释 Office-JT、Office-SQ 和 DC-101 为什么用 RouterOS WireGuard 承载日常站点互联、SMB LAN IP Windows 共享、DC 非 HTTP 服务和部分管理流量。","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/","tags":["运维","网络","RouterOS"],"title":"小型网络系列：WireGuard 为什么是日常路径","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/"},{"categories":null,"collections":null,"content":"系列导航 小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂 小型网络系列：RouterOS 和 Switch 的职责边界 小型网络系列：LAG、VLAN 和 Macvlan 为什么会一起出现 小型网络系列：PCC 分流逻辑和故障行为 小型网络系列：WireGuard 为什么是日常路径 小型网络系列：脚本、Scheduler 和可恢复性 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/:0:1","tags":["运维","网络","RouterOS"],"title":"小型网络系列：WireGuard 为什么是日常路径","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/#系列导航"},{"categories":null,"collections":null,"content":"背景 在 Homelab 系列里，我反复提到 NetBird 是 Admin Overlay。 但在这个小型网络系列里，办公室站点互联的主角不是 NetBird，而是 RouterOS 上的 WireGuard。 原因很简单：这里要承载的是日常网络路径，不只是我个人拿 MacBook 从外面管一下设备。 Office-JT、Office-SQ、DC-101 之间有几类真实需求： 技术同事从 Office-JT 访问 DC-101 的非 HTTP 服务，用于日常开发测试 服务名的公共 DNS 记录直接返回 LAN / Internal Address，然后走 DC-101 LAN 运营同事在 Office-JT 和 Office-SQ 之间访问 SMB LAN IP Windows 共享 搬迁后分开的办公室，仍然要延续原来在同一 LAN 里的协作习惯 RouterOS 之间还需要一部分管理和可恢复路径 这些需求不是临时救火，而是日常使用。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/:0:2","tags":["运维","网络","RouterOS"],"title":"小型网络系列：WireGuard 为什么是日常路径","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/#背景"},{"categories":null,"collections":null,"content":"为什么选 WireGuard 这里选 WireGuard，不是因为它最新，也不是因为它名字好听。 它刚好适合这个规模： 只有 Office-JT、Office-SQ、DC-101 这几个核心 RouterOS Peer 其中两个点有相对稳定的公网可达性，包括 PPPoE 拨号拿到动态公网 IP 后通过 DDNS 维持 Endpoint RouterOS 自带 WireGuard，不需要额外 WRT、Linux VM 或 Overlay Appliance 承载主数据面 站点之间是固定 LAN 路由，不是大量动态个人客户端 排障时可以直接在 RouterOS 里看 Peer、Route、Netwatch 和 Scheduler 这和 NetBird / ZeroTier 的定位不一样。 NetBird 更适合 Portable Devices (Admin) 和额外 Admin Overlay。ZeroTier 在这里更像 Backup Path。它们有价值，但不应该承载办公室日常协作的主路径。 主数据面放在 RouterOS WireGuard 里，路径更短，依赖更少，也更符合 RouterOS 作为主网关的角色。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/:0:3","tags":["运维","网络","RouterOS"],"title":"小型网络系列：WireGuard 为什么是日常路径","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/#为什么选-wireguard"},{"categories":null,"collections":null,"content":"日常流量有哪些 WireGuard 这条路径当前至少承载三类日常流量。 第一类是技术同事访问 DC-101 的非 HTTP 服务。 这些服务主要服务日常开发测试，不开放公网。它们可能有服务名，但这里不是靠办公室内部 DNS Rewrite，也不是另外维护一套 Split DNS。 更朴素的做法是：公共 DNS 记录本身就直接返回 LAN / Internal Address。 反正不在可信 LAN / WireGuard 网络里，解析到 LAN 地址也访问不了。用户看起来是在访问熟悉的名字，实际路径是： sequenceDiagram participant User as Office-JT User participant DNS as Public DNS participant JT as Office-JT RouterOS participant WG as WireGuard participant DC as DC-101 LAN User-\u003e\u003eDNS: Resolve Service Name DNS--\u003e\u003eUser: LAN / Internal Address User-\u003e\u003eJT: Access Non-HTTP Service JT-\u003e\u003eWG: Route to DC-101 LAN WG-\u003e\u003eDC: Reach DC-101 Service sequenceDiagram participant User as Office-JT User participant DNS as Public DNS participant JT as Office-JT RouterOS participant WG as WireGuard participant DC as DC-101 LAN User-\u003e\u003eDNS: Resolve Service Name DNS--\u003e\u003eUser: LAN / Internal Address User-\u003e\u003eJT: Access Non-HTTP Service JT-\u003e\u003eWG: Route to DC-101 LAN WG-\u003e\u003eDC: Reach DC-101 Service sequenceDiagram participant User as Office-JT User participant DNS as Public DNS participant JT as Office-JT RouterOS participant WG as WireGuard participant DC as DC-101 LAN User-\u003e\u003eDNS: Resolve Service Name DNS--\u003e\u003eUser: LAN / Internal Address User-\u003e\u003eJT: Access Non-HTTP Service JT-\u003e\u003eWG: Route to DC-101 LAN WG-\u003e\u003eDC: Reach DC-101 Service sequenceDiagram participant User as Office-JT User participant DNS as Public DNS participant JT as Office-JT RouterOS participant WG as WireGuard participant DC as DC-101 LAN User-\u003e\u003eDNS: Resolve Service Name DNS--\u003e\u003eUser: LAN / Internal Address User-\u003e\u003eJT: Access Non-HTTP Service JT-\u003e\u003eWG: Route to DC-101 LAN WG-\u003e\u003eDC: Reach DC-101 Service 这里避免了一个问题：内部非 HTTP 服务不需要绕公网入口，也不需要把所有协议都塞进 HTTP Gateway。 更核心的是安全域边界。公网只暴露 HTTP 服务，非 HTTP 内部服务留在 LAN / WireGuard 里。这样技术同事日常开发测试能访问到需要的资源，但这些协议不直接面向公网。 第二类是运营同事访问 SMB LAN IP Windows 共享。 这个需求很典型，也很现实。最早大家在一起办公，Windows 共享就是 LAN 内工具路径。后面办公室搬迁分开，人的工作习惯没有跟着网络拓扑一起重做。用 WireGuard 把 Office-JT 和 Office-SQ 的 LAN 连起来，可以让这条协作路径继续存在。 它不是一个完美的现代协作平台，但迁移成本低，用户习惯稳定。 第三类是部分管理流量。 RouterOS、PVE、Switch、WRT 都有自己的管理入口。日常管理不应该只依赖公网入口或个人 Overlay。站点 RouterOS 之间的 WireGuard 让一些基础管理路径留在内部网络里。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/:0:4","tags":["运维","网络","RouterOS"],"title":"小型网络系列：WireGuard 为什么是日常路径","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/#日常流量有哪些"},{"categories":null,"collections":null,"content":"为什么不是 NetBird NetBird 在我的网络里很重要，但它解决的是另一类问题。 它更适合： Mobile Devices / MacBook 从外部访问管理网络 Admin 设备按 ACL 访问 Homelab / Hometown / Office 资源 WRT Peer 作为额外管理入口 在主路径出问题时保留第二条进入方式 但 Office-JT / Office-SQ / DC-101 的日常流量，不应该依赖 WRT 上的 NetBird Peer。 原因有几个： WRT 是额外 Admin Layer，不是办公室主网关 日常用户流量应该留在 RouterOS 主数据面 SMB 这类 LAN IP 访问更像站点互联，不像个人 Overlay RouterOS 自带 WireGuard，少一层运行时依赖 故障时更容易判断是 RouterOS Peer、Route 还是具体服务问题 这不是说 NetBird 不好，而是不要把不同用途的 Overlay 混成一层。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/:0:5","tags":["运维","网络","RouterOS"],"title":"小型网络系列：WireGuard 为什么是日常路径","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/#为什么不是-netbird"},{"categories":null,"collections":null,"content":"路由边界 WireGuard 路由边界需要明确。 Office-JT 的 LAN 是 192.168.8.0/21，Office-SQ 的管理地址在 192.168.2.101，DC-101 的管理地址是 172.16.2.101。站点之间通过 WireGuard 互通时，RouterOS 需要知道哪些网段应该走 Tunnel，哪些流量仍然交给 PCC 出 WAN。 这也是为什么 PCC 篇里强调：PCC 不是所有流量的第一答案。 内部站点流量应该先被识别成 LAN / WireGuard 目标，再进入对应 Site Route。否则访问 DC-101 的服务、访问 SMB LAN IP 共享，都可能被错误地当作普通公网访问处理。 日常路径大概是： flowchart LR jtUser[\"Office-JT Users\"] sqUser[\"Office-SQ Users\"] jtROS[\"Office-JT RouterOS192.168.8.1\"] sqROS[\"Office-SQ RouterOS192.168.2.101\"] dcROS[\"DC-101 RouterOS172.16.2.101\"] smb[\"SMB Windows SharesLAN IP Access\"] dcSvc[\"DC-101 Non-HTTP Services\"] jtUser --\u003e jtROS sqUser --\u003e sqROS jtROS \u003c--\u003e|WireGuard Site Path| sqROS jtROS \u003c--\u003e|WireGuard Site Path| dcROS sqROS --\u003e|WireGuard via Office-JT / Site Path| smb jtROS --\u003e dcSvc flowchart LR jtUser[\"Office-JT Users\"] sqUser[\"Office-SQ Users\"] jtROS[\"Office-JT RouterOS192.168.8.1\"] sqROS[\"Office-SQ RouterOS192.168.2.101\"] dcROS[\"DC-101 RouterOS172.16.2.101\"] smb[\"SMB Windows SharesLAN IP Access\"] dcSvc[\"DC-101 Non-HTTP Services\"] jtUser --\u003e jtROS sqUser --\u003e sqROS jtROS \u003c--\u003e|WireGuard Site Path| sqROS jtROS \u003c--\u003e|WireGuard Site Path| dcROS sqROS --\u003e|WireGuard via Office-JT / Site Path| smb jtROS --\u003e dcSvc flowchart LR jtUser[\"Office-JT Users\"] sqUser[\"Office-SQ Users\"] jtROS[\"Office-JT RouterOS192.168.8.1\"] sqROS[\"Office-SQ RouterOS192.168.2.101\"] dcROS[\"DC-101 RouterOS172.16.2.101\"] smb[\"SMB Windows SharesLAN IP Access\"] dcSvc[\"DC-101 Non-HTTP Services\"] jtUser --\u003e jtROS sqUser --\u003e sqROS jtROS \u003c--\u003e|WireGuard Site Path| sqROS jtROS \u003c--\u003e|WireGuard Site Path| dcROS sqROS --\u003e|WireGuard via Office-JT / Site Path| smb jtROS --\u003e dcSvc flowchart LR jtUser[\"Office-JT Users\"] sqUser[\"Office-SQ Users\"] jtROS[\"Office-JT RouterOS192.168.8.1\"] sqROS[\"Office-SQ RouterOS192.168.2.101\"] dcROS[\"DC-101 RouterOS172.16.2.101\"] smb[\"SMB Windows SharesLAN IP Access\"] dcSvc[\"DC-101 Non-HTTP Services\"] jtUser --\u003e jtROS sqUser --\u003e sqROS jtROS \u003c--\u003e|WireGuard Site Path| sqROS jtROS \u003c--\u003e|WireGuard Site Path| dcROS sqROS --\u003e|WireGuard via Office-JT / Site Path| smb jtROS --\u003e dcSvc 图里故意没有画真实服务名、真实域名或公网地址。公开文章只需要说明路径和边界，不需要泄露入口细节。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/:0:6","tags":["运维","网络","RouterOS"],"title":"小型网络系列：WireGuard 为什么是日常路径","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/#路由边界"},{"categories":null,"collections":null,"content":"可恢复性 WireGuard 是日常路径，所以它不能只靠“配置好了应该会通”。 Office-JT 和 Office-SQ 侧都有 Watchdog 思路：通过 Netwatch 观察 Peer 可达性，如果 Peer 被判定 Down，就重启对应 WireGuard Peer。 这个动作很小： 不重写整套配置 不改动 Route 不切换到 WRT Overlay 只对当前 Peer 做 Disable / Enable 它解决的是 RouterOS WireGuard Peer 偶发卡住、Endpoint 状态异常这类小故障。 这也符合小型网络的维护方式：不要一上来做复杂控制系统，先把最常见的可恢复动作固化下来。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/:0:7","tags":["运维","网络","RouterOS"],"title":"小型网络系列：WireGuard 为什么是日常路径","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/#可恢复性"},{"categories":null,"collections":null,"content":"这个方案的取舍 WireGuard 作为日常路径也有成本。 它默认更偏站点级互信，不像 NetBird ACL 那样天然适合按个人设备、用户、Peer 细分权限。对于一个相对宽松的小型互联网公司，这个成本目前可以接受；如果未来真的需要部门级隔离、审计和细粒度访问控制，就不能只靠现在这套 LAN 互通模型。 另一个成本是内部路径会延续历史包袱。 比如 SMB LAN IP Windows 共享。它能快速延续协作路径，但它不是最现代、最云化、最易审计的方式。这里选择它，是因为它符合当前人的工作流，而不是因为它是所有场景的最优解。 所以这篇不是在说“办公室跨站都应该直接 WireGuard 打通 LAN”，而是在说：对这个规模、这几个站点、这些日常需求来说，RouterOS WireGuard 是更合适的主路径。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/:0:8","tags":["运维","网络","RouterOS"],"title":"小型网络系列：WireGuard 为什么是日常路径","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/#这个方案的取舍"},{"categories":null,"collections":null,"content":"最后的结论 WireGuard 在小型网络系列里的定位，是办公室站点之间的日常路径。 它承载的是： Office-JT / Office-SQ 的日常站点互联 运营同事访问 SMB LAN IP Windows 共享 技术同事访问 DC-101 非 HTTP 开发测试服务 公共 DNS 返回 LAN / Internal Address 后的访问路径 一部分 RouterOS 管理和恢复动作 NetBird / ZeroTier / WRT Peer 仍然存在，但它们更像 Admin Overlay 和 Backup Path。 后面写脚本、Scheduler 和可恢复性。日常路径确定之后，真正重要的是让这些 RouterOS 状态不要只靠手工记忆。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/:0:9","tags":["运维","网络","RouterOS"],"title":"小型网络系列：WireGuard 为什么是日常路径","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-wireguard-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A5%E5%B8%B8%E8%B7%AF%E5%BE%84/#最后的结论"},{"categories":null,"collections":null,"content":"基于 Office-JT 的 RouterOS PCC 脚本，解释 both-addresses-and-ports、pcc-mark Bucket Rules、pcc-routing Route Rules、0:1:1 / 1:1:1 / 1:2:2 / 2:3:3 模式和故障切换边界。","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/","tags":["运维","网络","RouterOS"],"title":"小型网络系列：PCC 分流逻辑和故障行为","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/"},{"categories":null,"collections":null,"content":"系列导航 小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂 小型网络系列：RouterOS 和 Switch 的职责边界 小型网络系列：LAG、VLAN 和 Macvlan 为什么会一起出现 小型网络系列：PCC 分流逻辑和故障行为 小型网络系列：WireGuard 为什么是日常路径 小型网络系列：脚本、Scheduler 和可恢复性 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/:0:1","tags":["运维","网络","RouterOS"],"title":"小型网络系列：PCC 分流逻辑和故障行为","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/#系列导航"},{"categories":null,"collections":null,"content":"背景 前一篇讲的是多条 WAN 怎么通过 LAG、VLAN、Macvlan 送到 RouterOS。 这一篇讲 RouterOS 拿到这些路径之后，怎么决定办公流量走哪条 WAN。 Office-JT 用的是 PCC。这里的 PCC 不是“把总带宽揉成一条大管子”，也不是按用户部门做复杂策略。它解决的是连接级分流：新连接按 both-addresses-and-ports 算 Bucket，被打上不同 Connection Mark，再进入不同 Routing Mark。 这件事在小型网络里很实用。 因为线路质量和用途并不总是固定的。有时候 route1 可以参与，有时候只想用 route2 / route3；有时候三条线等比例，有时候 route1 权重要低一些。手工一条条改 Mangle 规则很容易出错，所以最后变成了几组可切换脚本。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/:0:2","tags":["运维","网络","RouterOS"],"title":"小型网络系列：PCC 分流逻辑和故障行为","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/#背景"},{"categories":null,"collections":null,"content":"先分清两层规则 PCC 这部分最重要的边界，是 Bucket Layer 和 Routing Layer 分开。 Office-JT 当前命名大概是这样： 规则层 命名 职责 Bucket Layer pcc-mark-\u0026lt;denominator\u0026gt;/\u0026lt;bucket\u0026gt;-route\u0026lt;route\u0026gt; 新连接按 PCC Bucket 打 Connection Mark Routing Layer pcc-routing-route\u0026lt;route\u0026gt; 根据 Connection Mark 打 Routing Mark 切换 PCC 模式时，脚本只应该动 Bucket Layer。 也就是说： 先禁用所有 ^pcc-mark- Bucket Rules 再启用当前模式对应的 ^pcc-mark-N/ 不碰 pcc-routing-* 这个边界看起来像命名洁癖，实际是在避免事故。 如果切换脚本把 Routing Layer 也误伤了，后续所有已经按 route1 / route2 / route3 设计的路径都会变得不可预测。PCC 模式切换应该只改变“新连接如何分桶”，不应该重写整套路由语义。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/:0:3","tags":["运维","网络","RouterOS"],"title":"小型网络系列：PCC 分流逻辑和故障行为","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/#先分清两层规则"},{"categories":null,"collections":null,"content":"当前几种模式 当前脚本里有四种模式： 模式 Denominator Bucket 分配 使用场景 0:1:1 2 0 -\u0026gt; route3，1 -\u0026gt; route2 route1 暂时不参与，只用 route2 / route3 1:1:1 3 0 -\u0026gt; route3，1 -\u0026gt; route2，2 -\u0026gt; route1 三条线路等比例参与 1:2:2 5 2/3 -\u0026gt; route3，0/1 -\u0026gt; route2，4 -\u0026gt; route1 route1 权重低，route2 / route3 权重高 2:3:3 8 0/1/2 -\u0026gt; route3，3/4/5 -\u0026gt; route2，6/7 -\u0026gt; route1 三条都用，但 route2 / route3 更重 这里的数字不是带宽精确承诺，而是新连接 Bucket 的比例。 例如 1:2:2 不是说总带宽一定会变成这个比例，而是说新连接会按 5 个 Bucket 分配：route1 占 1 个 Bucket，route2 / route3 各占 2 个 Bucket。 实际效果还会受到连接大小、客户端数量、业务类型、单连接时长影响。单连接下载、并发下载、并发上传、短连接 API、SMB 访问、浏览器请求，它们对 PCC 的体感都不一样。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/:0:4","tags":["运维","网络","RouterOS"],"title":"小型网络系列：PCC 分流逻辑和故障行为","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/#当前几种模式"},{"categories":null,"collections":null,"content":"为什么用 both-addresses-and-ports 脚本里实际使用的是 RouterOS 的： per-connection-classifier=both-addresses-and-ports:N/Bucket也就是说，PCC Bucket 不是只看源地址，也不是只看目标地址，而是把两端地址和端口都纳入 Hash。 这个选择的重点是 Connection 粒度稳定。 一条连接被打上 pcc1 / pcc2 / pcc3 之后，后续上下行都应该沿着同一个 Connection Mark / Routing Mark 走。对普通用户来说，这比“每个包都可能换一条线”重要得多。尤其是银行、支付、后台系统这类对公网出口变化比较敏感的业务，如果访问过程中频繁跳公网 IP，很容易触发验证码、风控或重新登录。 所以这里追求的不是“越分散越好”，而是“新连接可以按比例分配，已经建立的连接不要乱跳”。 但它也不是只为了稳定。 对单个用户来说，如果下载器、浏览器、同步工具或上传任务本身会产生多条并发连接，这些连接就有机会被 PCC 分到不同 WAN Path。这样单个用户在并发下载、上传大文件时，确实可以更接近把多条线路榨干的效果。 这里的平衡点在于：单条连接保持路径稳定，多条连接允许分散利用带宽。 这也是为什么没有简单选择“只按源地址分流”。只按源地址会让某个客户端更稳定地落在一条 WAN 上，但单个用户的并发传输也更难吃到多 WAN 的总带宽。both-addresses-and-ports 的取舍，是在连接稳定性和带宽利用率之间找一个更实用的中间点。 不过这也不是应用层会话粘滞。 浏览器访问一个网站时，背后可能有多条 TCP / QUIC 连接。PCC 只能保证连接层面的标记和路由稳定，不能理解“这是同一个银行页面的完整业务会话”。如果某类业务确实对公网出口特别敏感，仍然应该通过例外规则、DNS / 目标地址归类，或者临时 PCC 模式选择来减少跳出口的概率，而不是指望 PCC 自动识别业务语义。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/:0:5","tags":["运维","网络","RouterOS"],"title":"小型网络系列：PCC 分流逻辑和故障行为","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/#为什么用-both-addresses-and-ports"},{"categories":null,"collections":null,"content":"切换脚本怎么工作 PCC 模式切换脚本的核心流程很简单： sequenceDiagram participant Operator as Operator participant Script as RouterOS PCC Script participant Bucket as pcc-mark-* Bucket Rules participant Routing as pcc-routing-* Rules participant Traffic as New Connections Operator-\u003e\u003eScript: Run PCC Mode Script Script-\u003e\u003eBucket: Ensure both-addresses-and-ports Bucket Rules Exist Script-\u003e\u003eBucket: Disable All ^pcc-mark- Script-\u003e\u003eBucket: Enable Target ^pcc-mark-N/ Note over Script,Routing: Do Not Touch pcc-routing-* Traffic-\u003e\u003eBucket: New Connections Hash by Addresses + Ports Bucket-\u003e\u003eRouting: Connection Mark route1 / route2 / route3 Routing--\u003e\u003eTraffic: Routing Mark Decides WAN Path sequenceDiagram participant Operator as Operator participant Script as RouterOS PCC Script participant Bucket as pcc-mark-* Bucket Rules participant Routing as pcc-routing-* Rules participant Traffic as New Connections Operator-\u003e\u003eScript: Run PCC Mode Script Script-\u003e\u003eBucket: Ensure both-addresses-and-ports Bucket Rules Exist Script-\u003e\u003eBucket: Disable All ^pcc-mark- Script-\u003e\u003eBucket: Enable Target ^pcc-mark-N/ Note over Script,Routing: Do Not Touch pcc-routing-* Traffic-\u003e\u003eBucket: New Connections Hash by Addresses + Ports Bucket-\u003e\u003eRouting: Connection Mark route1 / route2 / route3 Routing--\u003e\u003eTraffic: Routing Mark Decides WAN Path sequenceDiagram participant Operator as Operator participant Script as RouterOS PCC Script participant Bucket as pcc-mark-* Bucket Rules participant Routing as pcc-routing-* Rules participant Traffic as New Connections Operator-\u003e\u003eScript: Run PCC Mode Script Script-\u003e\u003eBucket: Ensure both-addresses-and-ports Bucket Rules Exist Script-\u003e\u003eBucket: Disable All ^pcc-mark- Script-\u003e\u003eBucket: Enable Target ^pcc-mark-N/ Note over Script,Routing: Do Not Touch pcc-routing-* Traffic-\u003e\u003eBucket: New Connections Hash by Addresses + Ports Bucket-\u003e\u003eRouting: Connection Mark route1 / route2 / route3 Routing--\u003e\u003eTraffic: Routing Mark Decides WAN Path sequenceDiagram participant Operator as Operator participant Script as RouterOS PCC Script participant Bucket as pcc-mark-* Bucket Rules participant Routing as pcc-routing-* Rules participant Traffic as New Connections Operator-\u003e\u003eScript: Run PCC Mode Script Script-\u003e\u003eBucket: Ensure both-addresses-and-ports Bucket Rules Exist Script-\u003e\u003eBucket: Disable All ^pcc-mark- Script-\u003e\u003eBucket: Enable Target ^pcc-mark-N/ Note over Script,Routing: Do Not Touch pcc-routing-* Traffic-\u003e\u003eBucket: New Connections Hash by Addresses + Ports Bucket-\u003e\u003eRouting: Connection Mark route1 / route2 / route3 Routing--\u003e\u003eTraffic: Routing Mark Decides WAN Path 它有几个关键细节： 目标 Bucket Rule 不存在时，脚本会先补出来 补规则需要找到一个 Anchor，避免规则插错位置 所有 pcc-mark-* 会先统一禁用 只有当前 Denominator 的 pcc-mark-N/ 会启用 pcc-routing-* 保持不动 这让切换动作变得可重复。 不是“我记得上次手动启用了这几条”，而是“当前模式脚本每次都把 Bucket Layer 收敛到同一个状态”。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/:0:6","tags":["运维","网络","RouterOS"],"title":"小型网络系列：PCC 分流逻辑和故障行为","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/#切换脚本怎么工作"},{"categories":null,"collections":null,"content":"PCC 解决不了什么 PCC 很容易被误解成万能负载均衡。 它不是。 它解决的是新连接分桶，不解决这些问题： 单条连接突破单条 WAN 的带宽上限 某条线路只是变慢但没有断时的自动质量判断 对某个业务协议做应用层感知 把一个网站的多连接业务会话绝对固定在同一个公网出口 用户级公平调度 部门级策略隔离 所有回程路径自动正确 比如某条 WAN 没断，只是质量变差。RouterOS 不一定知道这条线应该立刻降权。这个时候把 PCC 模式从 1:1:1 切到 0:1:1 或 1:2:2，其实是一种人为策略判断。 但反过来也要承认：如果一个用户正在做多连接下载、并发上传、云盘同步、开发镜像拉取这类任务，PCC 是有预期内优化效果的。它不能把一条 TCP 连接变成三条 WAN 的总和，但它可以让多条连接分散到 route1 / route2 / route3，从而提高总带宽利用率。 再比如 SMB 这类跨站访问，不应该被错误地当成普通公网出口流量。站点互联应该优先走 WireGuard LAN 路径，而不是被 PCC 当成外网流量分掉。 所以 PCC 的前提是：哪些目标属于 LAN / WireGuard，哪些属于 WAN，边界要先清楚。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/:0:7","tags":["运维","网络","RouterOS"],"title":"小型网络系列：PCC 分流逻辑和故障行为","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/#pcc-解决不了什么"},{"categories":null,"collections":null,"content":"故障行为 PCC 的故障行为要分几类看。 第一类是物理或 VLAN 承载故障。 如果某个 WAN Source 在 Switch 侧接错、PVID 错了、LAG 有问题，PCC 脚本本身救不了。它只能在 RouterOS 看到的接口语义上做分流，不能修 Switch 侧的物理承载。 第二类是线路不可用。 如果 route1 临时不适合参与，可以切到 0:1:1。这样新连接只在 route2 / route3 之间分。老连接是否立刻变化，要看既有 Connection Mark 和连接状态，不应该期待所有流量瞬间重新分配。 第三类是线路质量不均。 如果 route1 能用但不想承担太多，可以切到 1:2:2 或 2:3:3。这不是自动 QoS，而是把新连接权重向 route2 / route3 倾斜。 第四类是规则命名或迁移问题。 这也是为什么当前脚本统一使用 pcc-mark-* 和 pcc-routing-*。旧命名混在一起时，脚本容易误匹配。把 Bucket Layer 和 Routing Layer 命名拆开，是为了让自动化切换更可控。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/:0:8","tags":["运维","网络","RouterOS"],"title":"小型网络系列：PCC 分流逻辑和故障行为","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/#故障行为"},{"categories":null,"collections":null,"content":"怎么观察 PCC 不应该只靠“用户感觉快不快”判断。 我更倾向于看几类证据： 当前启用的是哪组 pcc-mark-N/ 活跃 Bucket Rule 是否仍然使用 both-addresses-and-ports pcc-routing-* 是否仍然存在且未被误禁用 route1 / route2 / route3 的连接数是否符合预期 高连接数客户端是否异常 WireGuard / LAN 目标有没有被错分到 WAN PCC Office-JT 里还保留了一个 print-per-ip-counts 脚本。它会统计 DHCP Lease 里绑定的客户端，在连接表里找连接数超过阈值的地址。 这个脚本很土，但很有用。 当某台机器连接数异常高时，PCC 的体感可能会被它影响。先把高连接客户端找出来，比盲目改权重更靠谱。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/:0:9","tags":["运维","网络","RouterOS"],"title":"小型网络系列：PCC 分流逻辑和故障行为","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/#怎么观察"},{"categories":null,"collections":null,"content":"最后的结论 PCC 在这套小型网络里的位置，是 Multi-WAN 新连接分流。 它依赖前一篇的 LAG / VLAN / Macvlan 把 route1 / route2 / route3 清楚送到 RouterOS，也依赖 WireGuard / LAN 目标先从普通 WAN 流量里排除出来。 真正值得保留的边界是： pcc-mark-* 是 Bucket Layer pcc-routing-* 是 Routing Layer both-addresses-and-ports 提供 Connection 粒度的上下行稳定 单用户多连接下载/上传可以更好利用多 WAN 总带宽 切换脚本只动 Bucket Layer 模式切换影响新连接权重，不等于应用层智能调度 线路质量判断仍然需要人和监控一起参与 后面写 WireGuard 为什么是日常路径。因为办公室站点互联不是 PCC 的出口选择问题，而是另一条明确的内部网络路径。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/:0:10","tags":["运维","网络","RouterOS"],"title":"小型网络系列：PCC 分流逻辑和故障行为","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-pcc-%E5%88%86%E6%B5%81%E9%80%BB%E8%BE%91%E5%92%8C%E6%95%85%E9%9A%9C%E8%A1%8C%E4%B8%BA/#最后的结论"},{"categories":null,"collections":null,"content":"解释 Office-JT 为什么同时使用 LAG、VLAN 和 Macvlan：它们不是部门隔离模板，而是为 3 条 WAN 接入、Bonding 复用、2x1G 全双工承载和独立 WAN 身份服务。","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/","tags":["运维","网络","RouterOS"],"title":"小型网络系列：LAG、VLAN 和 Macvlan 为什么会一起出现","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/"},{"categories":null,"collections":null,"content":"系列导航 小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂 小型网络系列：RouterOS 和 Switch 的职责边界 小型网络系列：LAG、VLAN 和 Macvlan 为什么会一起出现 小型网络系列：PCC 分流逻辑和故障行为 小型网络系列：WireGuard 为什么是日常路径 小型网络系列：脚本、Scheduler 和可恢复性 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/:0:1","tags":["运维","网络","RouterOS"],"title":"小型网络系列：LAG、VLAN 和 Macvlan 为什么会一起出现","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/#系列导航"},{"categories":null,"collections":null,"content":"背景 如果只看名词，LAG、VLAN、Macvlan 很容易让人以为这是在做一套“企业级网络隔离”。 但 Office-JT 当前不是这么用的。 这里的核心问题更朴素： 当前已经是 3 条 WAN Source 从 Switch 侧接入 后续还要预留继续增加 Modem 的可能 RouterOS CHR 在 PVE Host 里，需要通过 Switch Port 扩展有限的有线网口能力 两个 1G 电口最多提供 2G 全双工的 WAN UP/DOWN 承载空间 单条链路不能既承担所有 LAN，又承担多条 WAN 的物理上限和扩展需求 RouterOS 还需要让不同 WAN Path 拥有独立 L2 身份 所以最后才会同时出现： LAG1 / bonding1 VLAN 10 / 20 / 30 macvlan10 / macvlan20 / macvlan30 它不是为了让拓扑看起来高级，而是为了解决物理链路、WAN 复用和 RouterOS 接口语义的问题。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/:0:2","tags":["运维","网络","RouterOS"],"title":"小型网络系列：LAG、VLAN 和 Macvlan 为什么会一起出现","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/#背景"},{"categories":null,"collections":null,"content":"Bonding 不只是冗余 很多时候提到 Bonding，第一反应是“冗余”。 这里当然也有冗余价值：两根 1G 物理链路组成 LAG1，少一根至少不至于整个 RouterOS 到 Switch 的承载直接断掉。 但它还有一个更现实的原因：当前实际已经是 3 条 WAN 接入，多条 WAN 的实际带宽叠起来会超过单个 1G 电口。 如果所有 LAN、WAN Source、PCC 出口都挤在一根 1G 物理链路上，理论拓扑再清楚，实际吞吐也会先撞到物理口上限。LAG1 提供的是 2x1G 的承载空间，也就是最多 2G 全双工的 WAN UP/DOWN 余量，让多客户端、多连接、多 WAN 场景有更大的总带宽空间。 这里也要说清楚：LAG 不是让单条 TCP 连接自动变成 2G。 它更适合解决多客户端、多连接、多 WAN 并发时的总吞吐和链路余量。对 300-500 Devices 的办公室网络来说，这个收益比“看起来多一根线”实在得多。 还有一层原因是扩展。 RouterOS CHR 跑在 PVE Host 里，PVE Host 的有线网口数量有限，不可能为每个 Modem 都准备一根独立直连物理线。把 Modem 接入 Managed Switch，再用 VLAN / LAG 送到 RouterOS，相当于用 Switch Port 扩展 PVE Host 的有线接入面，也给后续继续增加 Modem 留了空间。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/:0:3","tags":["运维","网络","RouterOS"],"title":"小型网络系列：LAG、VLAN 和 Macvlan 为什么会一起出现","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/#bonding-不只是冗余"},{"categories":null,"collections":null,"content":"VLAN 在这里不是部门隔离 当前 VLAN 表可以简化成这样： VLAN 名称 / 角色 用途 1 System-VLAN 普通 LAN 和基础管理承载 10 ppp1 route1 / PPPoE WAN Source 20 pcc2 route2 WAN Source 30 pcc3 route3 WAN Source 这张表里没有“研发部 VLAN”“财务 VLAN”“访客 VLAN”。 原因上一篇已经说过：当前公司环境比较宽松，管理目标是稳定、可理解、可恢复，而不是一上来就做细粒度部门隔离。VLAN 先服务接入问题，而不是组织结构。 LAN 侧 192.168.8.0/21 这个大子网也是同一个取舍。它是延续了快 10 年的初始设计，不是严格规划出来的广播域模型。真正在网设备大概 300-500 Devices，还没逼到必须把地址规划、部门 VLAN、广播域治理一起重做。说白了，也有一部分就是懒得改。 更具体地说，VLAN 做了两件事： 把不同 WAN Source 从 Switch 侧 Access Port 带到 RouterOS 让这些 WAN Source 可以复用同一个 LAG1 / bonding1 承载 也就是说，VLAN 是 WAN Carrier，不是部门边界。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/:0:4","tags":["运维","网络","RouterOS"],"title":"小型网络系列：LAG、VLAN 和 Macvlan 为什么会一起出现","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/#vlan-在这里不是部门隔离"},{"categories":null,"collections":null,"content":"Macvlan 解决什么 有了 VLAN，RouterOS 已经能在 bonding1 上看到 vlan10、vlan20、vlan30。 那为什么还要 Macvlan？ 因为不同 WAN Path 需要独立的 L2 / MAC 身份。 Office-JT 的接口关系可以抽象成这样： Switch VLAN RouterOS Interface Route Role 10 vlan10 -\u0026gt; macvlan10 -\u0026gt; pppoe-out1 route1 / pcc1 20 vlan20 -\u0026gt; macvlan20 route2 / pcc2 30 vlan30 -\u0026gt; macvlan30 route3 / pcc3 文章里不应该放真实 MAC，也不应该放公网地址。这里真正重要的是接口层级： VLAN 负责把 WAN Source 分开带进 RouterOS Macvlan 负责给每条 WAN Path 独立 L2 身份 PCC 再按 route1 / route2 / route3 使用这些路径 没有 Macvlan 时，多个 WAN 身份都压在同一个父接口语义上，后面做 PPPoE、静态 WAN、PCC 标记和排障都会更别扭。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/:0:5","tags":["运维","网络","RouterOS"],"title":"小型网络系列：LAG、VLAN 和 Macvlan 为什么会一起出现","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/#macvlan-解决什么"},{"categories":null,"collections":null,"content":"拓扑展开 这张图只画公共安全的角色名和 LAN 地址，不画公网 IP、真实域名和 MAC： flowchart LR wan1[\"WAN Sourceroute1 / PPPoE\"] wan2[\"WAN Sourceroute2\"] wan3[\"WAN Sourceroute3\"] switch[\"Managed Switch192.168.8.90\"] lag[\"LAG12x1G Full-Duplex Carrier\"] ros[\"RouterOS CHR192.168.8.1\"] lan[\"Office LAN192.168.8.0/21\"] wan1 --\u003e|Access VLAN 10| switch wan2 --\u003e|Access VLAN 20| switch wan3 --\u003e|Access VLAN 30| switch switch --\u003e lag lag --\u003e|bonding1| ros ros --\u003e|br-lan on bonding1| lan ros --\u003e|vlan10 -\u003e macvlan10 -\u003e pppoe-out1| wan1 ros --\u003e|vlan20 -\u003e macvlan20| wan2 ros --\u003e|vlan30 -\u003e macvlan30| wan3 flowchart LR wan1[\"WAN Sourceroute1 / PPPoE\"] wan2[\"WAN Sourceroute2\"] wan3[\"WAN Sourceroute3\"] switch[\"Managed Switch192.168.8.90\"] lag[\"LAG12x1G Full-Duplex Carrier\"] ros[\"RouterOS CHR192.168.8.1\"] lan[\"Office LAN192.168.8.0/21\"] wan1 --\u003e|Access VLAN 10| switch wan2 --\u003e|Access VLAN 20| switch wan3 --\u003e|Access VLAN 30| switch switch --\u003e lag lag --\u003e|bonding1| ros ros --\u003e|br-lan on bonding1| lan ros --\u003e|vlan10 -\u003e macvlan10 -\u003e pppoe-out1| wan1 ros --\u003e|vlan20 -\u003e macvlan20| wan2 ros --\u003e|vlan30 -\u003e macvlan30| wan3 flowchart LR wan1[\"WAN Sourceroute1 / PPPoE\"] wan2[\"WAN Sourceroute2\"] wan3[\"WAN Sourceroute3\"] switch[\"Managed Switch192.168.8.90\"] lag[\"LAG12x1G Full-Duplex Carrier\"] ros[\"RouterOS CHR192.168.8.1\"] lan[\"Office LAN192.168.8.0/21\"] wan1 --\u003e|Access VLAN 10| switch wan2 --\u003e|Access VLAN 20| switch wan3 --\u003e|Access VLAN 30| switch switch --\u003e lag lag --\u003e|bonding1| ros ros --\u003e|br-lan on bonding1| lan ros --\u003e|vlan10 -\u003e macvlan10 -\u003e pppoe-out1| wan1 ros --\u003e|vlan20 -\u003e macvlan20| wan2 ros --\u003e|vlan30 -\u003e macvlan30| wan3 flowchart LR wan1[\"WAN Sourceroute1 / PPPoE\"] wan2[\"WAN Sourceroute2\"] wan3[\"WAN Sourceroute3\"] switch[\"Managed Switch192.168.8.90\"] lag[\"LAG12x1G Full-Duplex Carrier\"] ros[\"RouterOS CHR192.168.8.1\"] lan[\"Office LAN192.168.8.0/21\"] wan1 --\u003e|Access VLAN 10| switch wan2 --\u003e|Access VLAN 20| switch wan3 --\u003e|Access VLAN 30| switch switch --\u003e lag lag --\u003e|bonding1| ros ros --\u003e|br-lan on bonding1| lan ros --\u003e|vlan10 -\u003e macvlan10 -\u003e pppoe-out1| wan1 ros --\u003e|vlan20 -\u003e macvlan20| wan2 ros --\u003e|vlan30 -\u003e macvlan30| wan3 这个图里最反直觉的地方，是 bonding1 同时和 LAN / WAN 有关系。 它不是一个简单的“WAN 口”或“LAN 口”，而是一个复用承载。基础 bonding1 进入 br-lan，让 LAN 继续存在；WAN 则通过 VLAN 子接口从同一条承载上剥离出来。 这也是这套设计看起来复杂的原因之一。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/:0:6","tags":["运维","网络","RouterOS"],"title":"小型网络系列：LAG、VLAN 和 Macvlan 为什么会一起出现","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/#拓扑展开"},{"categories":null,"collections":null,"content":"这个取舍的成本 这套设计不是无成本。 它的成本主要有几个： Switch Port、PVID、VLAN Membership 必须记录清楚 RouterOS 上 bonding1、br-lan、VLAN、Macvlan 的层级不能混 出问题时要先判断是物理承载问题，还是 RouterOS 路由策略问题 后续如果真的要做部门 VLAN 隔离，不能简单复用现在的 WAN VLAN 语义 LAG 的 Hash 行为不是“所有流量平均 2G”，更不是单条 TCP 连接变 2G，需要避免过度期待 但它换来的东西也很实际： 多条 WAN 不需要为每条都拉一条独立 RouterOS 物理口 RouterOS 到 Switch 的总承载空间更大 PVE Host 不需要为了后续 Modem 扩展继续消耗物理网口 route1 / route2 / route3 有清楚的接口语义 PCC 能围绕这些 Route Role 做分流 后续排障时可以按层拆开看 这就是小型网络里经常出现的取舍：它不是标准化得很漂亮，但它解决了当时最具体的物理和容量问题。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/:0:7","tags":["运维","网络","RouterOS"],"title":"小型网络系列：LAG、VLAN 和 Macvlan 为什么会一起出现","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/#这个取舍的成本"},{"categories":null,"collections":null,"content":"最后的结论 Office-JT 里的 LAG、VLAN 和 Macvlan 是一组配套设计。 LAG 解决 Switch 到 RouterOS 的 2x1G 全双工承载空间和冗余，VLAN 解决当前 3 条 WAN Source 复用同一条承载，也给后续 Modem 扩展留空间，Macvlan 解决每条 WAN Path 的独立 L2 身份。 它们不是部门隔离方案，也不是企业网络模板。 它们只是让 RouterOS 能在有限物理条件下，稳定拿到多条 WAN，并把这些 WAN 交给后面的 PCC 使用。 后面继续写 PCC 分流逻辑和故障行为。LAG / VLAN / Macvlan 只是把路径送到 RouterOS；真正决定新连接走哪条 WAN 的，是 PCC。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/:0:8","tags":["运维","网络","RouterOS"],"title":"小型网络系列：LAG、VLAN 和 Macvlan 为什么会一起出现","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-lag-vlan-%E5%92%8C-macvlan-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E4%B8%80%E8%B5%B7%E5%87%BA%E7%8E%B0/#最后的结论"},{"categories":null,"collections":null,"content":"从 Office-JT 的 RouterOS、Managed Switch 和 PVE 管理边界开始，解释小型网络里为什么要把物理承载、L2 复用、PCC、WireGuard 和日常管理分开。","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/","tags":["运维","网络","RouterOS"],"title":"小型网络系列：RouterOS 和 Switch 的职责边界","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/"},{"categories":null,"collections":null,"content":"系列导航 小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂 小型网络系列：RouterOS 和 Switch 的职责边界 小型网络系列：LAG、VLAN 和 Macvlan 为什么会一起出现 小型网络系列：PCC 分流逻辑和故障行为 小型网络系列：WireGuard 为什么是日常路径 小型网络系列：脚本、Scheduler 和可恢复性 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/:0:1","tags":["运维","网络","RouterOS"],"title":"小型网络系列：RouterOS 和 Switch 的职责边界","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/#系列导航"},{"categories":null,"collections":null,"content":"背景 上一篇先把范围定住：这不是企业网络最佳实践，而是一套 300-500 Devices 小型网络里的实用取舍。 这一篇只讲 Office-JT 里的两个核心角色：RouterOS 和 Managed Switch。 它们看起来都在“转发流量”，但职责不能混在一起。Switch 负责物理接入、LAG、VLAN 载体；RouterOS 负责网关、DHCP、NAT、PCC、WireGuard 和路由策略。把这两层拆清楚之后，后面写 LAG / VLAN / Macvlan、PCC、WireGuard 才不会绕成一团。 当前几个管理点是： 组件 LAN 地址 职责 RouterOS CHR 192.168.8.1 主网关、PCC、WireGuard、DHCP、NAT Managed Switch 192.168.8.90 接入口、LAG1、VLAN Carrier PVE 192.168.8.100 承载 CHR、WRT 和相关基础服务 Ubiquiti UniFi AP 不展开 PoE AC AP，无线 Mesh 关闭，2.4G / 5G 分 SSID 接入 这些地址都是 LAN 内拓扑语义。公网地址、真实域名和 MAC 不应该出现在文章里。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/:0:2","tags":["运维","网络","RouterOS"],"title":"小型网络系列：RouterOS 和 Switch 的职责边界","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/#背景"},{"categories":null,"collections":null,"content":"当前拓扑 Office-JT 的形状可以先画成这样： sequenceDiagram participant WAN as Modem / WAN Sources3 WAN Inputs / Future Modems participant Switch as Managed Switch192.168.8.90WAN Access / LAG1 / VLAN participant RouterOS as RouterOS CHR192.168.8.1Gateway / PCC / WireGuard participant LAN as Office LAN192.168.8.0/21Users / PVE / UniFi AP WAN-\u003e\u003eSwitch: Current 3 WAN Physical Access Ports WAN--\u003e\u003eSwitch: Future Modems enter through Switch Ports Switch-\u003e\u003eRouterOS: VLAN 10 / 20 / 30 over LAG1 / bonding1 Switch-\u003e\u003eRouterOS: System-VLAN / LAN over bonding1 RouterOS-\u003e\u003eLAN: DHCP / Gateway / NAT / PCC Policy RouterOS-\u003e\u003eLAN: WireGuard Site Routes to Office-SQ / DC-101 sequenceDiagram participant WAN as Modem / WAN Sources3 WAN Inputs / Future Modems participant Switch as Managed Switch192.168.8.90WAN Access / LAG1 / VLAN participant RouterOS as RouterOS CHR192.168.8.1Gateway / PCC / WireGuard participant LAN as Office LAN192.168.8.0/21Users / PVE / UniFi AP WAN-\u003e\u003eSwitch: Current 3 WAN Physical Access Ports WAN--\u003e\u003eSwitch: Future Modems enter through Switch Ports Switch-\u003e\u003eRouterOS: VLAN 10 / 20 / 30 over LAG1 / bonding1 Switch-\u003e\u003eRouterOS: System-VLAN / LAN over bonding1 RouterOS-\u003e\u003eLAN: DHCP / Gateway / NAT / PCC Policy RouterOS-\u003e\u003eLAN: WireGuard Site Routes to Office-SQ / DC-101 sequenceDiagram participant WAN as Modem / WAN Sources3 WAN Inputs / Future Modems participant Switch as Managed Switch192.168.8.90WAN Access / LAG1 / VLAN participant RouterOS as RouterOS CHR192.168.8.1Gateway / PCC / WireGuard participant LAN as Office LAN192.168.8.0/21Users / PVE / UniFi AP WAN-\u003e\u003eSwitch: Current 3 WAN Physical Access Ports WAN--\u003e\u003eSwitch: Future Modems enter through Switch Ports Switch-\u003e\u003eRouterOS: VLAN 10 / 20 / 30 over LAG1 / bonding1 Switch-\u003e\u003eRouterOS: System-VLAN / LAN over bonding1 RouterOS-\u003e\u003eLAN: DHCP / Gateway / NAT / PCC Policy RouterOS-\u003e\u003eLAN: WireGuard Site Routes to Office-SQ / DC-101 sequenceDiagram participant WAN as Modem / WAN Sources3 WAN Inputs / Future Modems participant Switch as Managed Switch192.168.8.90WAN Access / LAG1 / VLAN participant RouterOS as RouterOS CHR192.168.8.1Gateway / PCC / WireGuard participant LAN as Office LAN192.168.8.0/21Users / PVE / UniFi AP WAN-\u003e\u003eSwitch: Current 3 WAN Physical Access Ports WAN--\u003e\u003eSwitch: Future Modems enter through Switch Ports Switch-\u003e\u003eRouterOS: VLAN 10 / 20 / 30 over LAG1 / bonding1 Switch-\u003e\u003eRouterOS: System-VLAN / LAN over bonding1 RouterOS-\u003e\u003eLAN: DHCP / Gateway / NAT / PCC Policy RouterOS-\u003e\u003eLAN: WireGuard Site Routes to Office-SQ / DC-101 这里按“承载交接”从左到右画：Modem / WAN Sources 先进入 Switch，Switch 再通过 VLAN 和 LAG1 / bonding1 把这些 WAN 角色送到 RouterOS，RouterOS 最后向 Office LAN 提供网关、DHCP、PCC 和 WireGuard Site Routes。 所以 Switch 不是“纯 LAN 交换机”，它同时也是 WAN 接入口的物理承载层。当前实际是 3 条 WAN 接入，后续如果继续增加 Modem，也应该优先从 Switch 侧扩展 Access Port，而不是要求 PVE Host 为每条 WAN 都提供独立有线网口。 RouterOS 也不是直接插了三条清晰独立的 WAN 线，而是通过 bonding1 上的 VLAN 接到不同 WAN 角色。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/:0:3","tags":["运维","网络","RouterOS"],"title":"小型网络系列：RouterOS 和 Switch 的职责边界","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/#当前拓扑"},{"categories":null,"collections":null,"content":"Switch 负责什么 Switch 的职责很具体： 哪些口是普通 LAN 口 哪些口接入 WAN Source 哪些口组成 LAG1 哪些 VLAN 通过 LAG1 送到 RouterOS WAN Source 的 Access Port 应该落在哪个 PVID 如何用 Switch Port 扩展 PVE Host 有限的有线接入能力 RouterOS 侧看到的物理承载是否稳定 这是一层物理和 L2 语义。 例如，Office-JT 里 LAG1 是 Switch 到 RouterOS 的复用通道。LAN 继续走基础 System-VLAN / bonding1，当前 3 条 WAN 通过不同 VLAN 挂在同一条 Bonding 载体上。以后如果再加 Modem，优先增加的是 Switch 侧 Access Port 和对应 VLAN 语义，而不是继续消耗 PVE Host 的物理网口。 Switch 在这里不应该理解 PCC，不应该决定哪台客户端走 route2，也不应该判断 Office-SQ 或 DC-101 的回程路径。它只负责把线接对、VLAN 送对、LAG 稳定。 如果 Switch 侧 PVID 配错，RouterOS 上的 PCC 脚本再漂亮也没用。因为 RouterOS 看到的入口已经不对了。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/:0:4","tags":["运维","网络","RouterOS"],"title":"小型网络系列：RouterOS 和 Switch 的职责边界","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/#switch-负责什么"},{"categories":null,"collections":null,"content":"RouterOS 负责什么 RouterOS 是主网关，所以它负责网络决策： LAN 网关和 DHCP NAT 和基础防火墙 Multi-WAN 的 PCC 分流 route1 / route2 / route3 的路由语义 WireGuard 站点互联 Office-SQ / DC-101 的远端 LAN 访问 管理脚本、Scheduler 和运行状态 RouterOS 看到的是已经由 Switch 承载过来的接口形态： bonding1 是 LAN 和 VLAN 的复用载体 br-lan 承载 LAN，地址是 192.168.8.1/21 vlan10、vlan20、vlan30 对应不同 WAN Role macvlan10、macvlan20、macvlan30 给每条 WAN Path 独立 L2 身份 这就是为什么 RouterOS 和 Switch 的边界必须清楚。 Switch 处理“哪根线、哪个 VLAN、哪个 LAG”；RouterOS 处理“这条路径要不要参与 PCC、哪些网段走 WireGuard、客户端默认网关是什么”。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/:0:5","tags":["运维","网络","RouterOS"],"title":"小型网络系列：RouterOS 和 Switch 的职责边界","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/#routeros-负责什么"},{"categories":null,"collections":null,"content":"为什么不能把边界合起来 小型网络里最容易发生的事情，是一开始觉得“能通就行”，后面所有东西都混在一起。 比如： 看到 VLAN，就想顺手做部门隔离 看到 Switch 管理界面，就想在那里表达业务策略 看到 RouterOS 能做 Bridge，就想把所有物理语义也挪进去 看到 WRT 能跑服务，就想把管理路径也从主网关拿走 这些不是不能做，而是要先问：它解决的是什么问题？ 当前 Office-JT 的 VLAN 不是部门隔离。它解决的是 WAN 接入和 Bonding 复用。RouterOS 的 PCC 不是 Switch 负载均衡。它解决的是连接级出站路径选择。WireGuard 也不是个人 Overlay。它是办公室站点之间的日常路径。 边界一旦混掉，排障会很痛苦。 例如用户说访问 DC-101 的 SMB 或非 HTTP 服务慢，到底该看哪里？ 如果是 Switch 端口或 LAG 问题，看 Switch 如果是 PCC 把流量标错，看 RouterOS Mangle 和 Route 如果是 WireGuard Peer 抖动，看 RouterOS WireGuard / Netwatch 如果是 DNS 解析成了不合适的地址，看 DNS 记录或解析结果 如果是 WRT Admin Overlay 断了，不应该第一时间怀疑办公室日常 WireGuard 边界不是为了文档好看，而是为了排障时问题能落到正确层。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/:0:6","tags":["运维","网络","RouterOS"],"title":"小型网络系列：RouterOS 和 Switch 的职责边界","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/#为什么不能把边界合起来"},{"categories":null,"collections":null,"content":"和 WRT 的关系 Office-JT 也有 WRT，但它不是这套小型网络主数据面的核心。 WRT 更像额外 Admin Layer： NetBird Peer ZeroTier Peer Sing-box 备用入口 管理时的第二条路径 这些能力有价值，但它们不是办公室日常用户访问 Office-SQ / DC-101 的主路径。 日常站点互联在 RouterOS WireGuard 上。普通办公流量、运营同事访问 SMB LAN IP Windows 共享、技术同事访问 DC-101 非 HTTP 服务，都不应该依赖 WRT 这层额外能力。 这和 Homelab 系列不同。 Homelab 里 WRT 承载透明代理和 Admin Overlay，是一个很重要的策略层；Office 网络里，RouterOS / Switch / WireGuard 才是主叙事。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/:0:7","tags":["运维","网络","RouterOS"],"title":"小型网络系列：RouterOS 和 Switch 的职责边界","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/#和-wrt-的关系"},{"categories":null,"collections":null,"content":"最后的结论 这套小型网络里，RouterOS 和 Switch 的职责边界大概是： Switch 负责物理接入、LAG、VLAN Carrier RouterOS 负责网关、PCC、WireGuard、DHCP、NAT PVE 负责承载，不直接表达网络策略 WRT 是额外 Admin Layer，不是日常主数据面 这个边界不花哨，但它能让后面的复杂度有地方放。 后面继续拆 LAG、VLAN 和 Macvlan。这一层才是真正把“多条 WAN 怎么复用到 RouterOS”落到拓扑里的部分。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/:0:8","tags":["运维","网络","RouterOS"],"title":"小型网络系列：RouterOS 和 Switch 的职责边界","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97-routeros-%E5%92%8C-switch-%E7%9A%84%E8%81%8C%E8%B4%A3%E8%BE%B9%E7%95%8C/#最后的结论"},{"categories":null,"collections":null,"content":"从 Office-JT 的 300-500 Devices 小型网络开始，解释 Multi-WAN、Switch Bonding、VLAN、Macvlan、PCC、WireGuard 和管理边界为什么会让网络变复杂。","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/","tags":["运维","网络","RouterOS"],"title":"小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/"},{"categories":null,"collections":null,"content":"系列导航 小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂 小型网络系列：RouterOS 和 Switch 的职责边界 小型网络系列：LAG、VLAN 和 Macvlan 为什么会一起出现 小型网络系列：PCC 分流逻辑和故障行为 小型网络系列：WireGuard 为什么是日常路径 小型网络系列：脚本、Scheduler 和可恢复性 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/:0:1","tags":["运维","网络","RouterOS"],"title":"小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/#系列导航"},{"categories":null,"collections":null,"content":"背景 这个系列我先不叫“企业网络”，也不打算把它写成企业最佳实践。 真实规模大概是 300-500 Devices，最多的时候不到 250 人。按我的理解，这更适合叫小型网络，离那种真正中大型组织网络还有距离。它有复杂度，但复杂度主要来自线路、站点、远程访问、管理路径和历史取舍，而不是来自严格的组织层级、部门边界或合规要求。 所以这套东西的口径会比较朴素： 这是一个小型互联网公司网络 Office-JT 是主要办公地点 Office-SQ 和 DC-101 通过 WireGuard 连到主办公网络 RouterOS 是核心路由和策略承载点 Switch、Bonding、VLAN、Macvlan、PCC 都是在解决现实接入问题 WRT / NetBird / ZeroTier 更偏 Admin Overlay 和 Backup Path，不是办公室日常主数据面 运营同事也会通过 WireGuard 访问 SMB LAN IP Windows 共享，延续搬迁前在同一个 LAN 里的协作方式 无线接入靠 Ubiquiti UniFi PoE AC AP，没开无线 Mesh，2.4G / 5G 拆成两个 SSID 我也不是专职网管。这套网络很多地方都不是教科书式的“企业级拆分”，更像是一个技术同事顺手把它维护到能稳定工作的状态。说难听点有点草台，说好听点就是很实用。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/:0:2","tags":["运维","网络","RouterOS"],"title":"小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/#背景"},{"categories":null,"collections":null,"content":"为什么“小型”也会复杂 如果只看人数和设备数，它确实不大。 但网络复杂度不只来自人数。只要同时出现下面几件事，小型网络也会很快复杂起来： 当前实际已经是 3 条 WAN 接入，需要同时承载办公流量 有的线路是 PPPoE，有的线路是静态地址，有的线路质量和用途不一样 后续还要预留继续增加 Modem 的可能 RouterOS CHR 在 PVE Host 里，Switch 到 RouterOS 之间需要复用链路，不能每条 WAN 都独占一根 PVE 物理网口 两个 1G 电口可以提供最多 2G 全双工的 WAN UP/DOWN 承载，Bonding 不只是冗余，也是在解决带宽上限 远端办公室和 DC 不是偶尔管理，而是要稳定承载日常访问 内部用户访问某些 DC 非 HTTP 服务时，希望看起来仍然是访问服务名，但实际走 LAN / WireGuard 路径 搬迁后分开的办公室，仍然要让运营同事继续用原来的 SMB Windows 共享路径协作 网络设备、PVE、WRT、Overlay Peer 都需要保留管理入口 故障时不能靠“我人在现场插键盘”作为唯一恢复方案 这就是我想写这个系列的原因。 它不是一个庞大企业网络，但它已经超过了“一个路由器加一个交换机就结束”的复杂度。 flowchart LR users[\"Office-JT Users300-500 Devices / Peak \u003c250 People\"] sw[\"Managed SwitchLAG / VLAN Carrier192.168.8.90\"] ros[\"Office-JT RouterOSGateway / PCC / WireGuard192.168.8.1/21\"] wan[\"Multi-WAN3 Inputs / Future Modemsroute1 / route2 / route3\"] sq[\"Office-SQWireGuard Site192.168.2.101\"] dc[\"DC-101WireGuard LAN172.16.2.101\"] pve[\"Office-JT PVE192.168.8.100\"] users --\u003e sw sw --\u003e ros ros --\u003e wan ros \u003c--\u003e|WireGuard| sq ros \u003c--\u003e|WireGuard| dc ros --\u003e pve flowchart LR users[\"Office-JT Users300-500 Devices / Peak \u003c250 People\"] sw[\"Managed SwitchLAG / VLAN Carrier192.168.8.90\"] ros[\"Office-JT RouterOSGateway / PCC / WireGuard192.168.8.1/21\"] wan[\"Multi-WAN3 Inputs / Future Modemsroute1 / route2 / route3\"] sq[\"Office-SQWireGuard Site192.168.2.101\"] dc[\"DC-101WireGuard LAN172.16.2.101\"] pve[\"Office-JT PVE192.168.8.100\"] users --\u003e sw sw --\u003e ros ros --\u003e wan ros \u003c--\u003e|WireGuard| sq ros \u003c--\u003e|WireGuard| dc ros --\u003e pve flowchart LR users[\"Office-JT Users300-500 Devices / Peak \u003c250 People\"] sw[\"Managed SwitchLAG / VLAN Carrier192.168.8.90\"] ros[\"Office-JT RouterOSGateway / PCC / WireGuard192.168.8.1/21\"] wan[\"Multi-WAN3 Inputs / Future Modemsroute1 / route2 / route3\"] sq[\"Office-SQWireGuard Site192.168.2.101\"] dc[\"DC-101WireGuard LAN172.16.2.101\"] pve[\"Office-JT PVE192.168.8.100\"] users --\u003e sw sw --\u003e ros ros --\u003e wan ros \u003c--\u003e|WireGuard| sq ros \u003c--\u003e|WireGuard| dc ros --\u003e pve flowchart LR users[\"Office-JT Users300-500 Devices / Peak \u003c250 People\"] sw[\"Managed SwitchLAG / VLAN Carrier192.168.8.90\"] ros[\"Office-JT RouterOSGateway / PCC / WireGuard192.168.8.1/21\"] wan[\"Multi-WAN3 Inputs / Future Modemsroute1 / route2 / route3\"] sq[\"Office-SQWireGuard Site192.168.2.101\"] dc[\"DC-101WireGuard LAN172.16.2.101\"] pve[\"Office-JT PVE192.168.8.100\"] users --\u003e sw sw --\u003e ros ros --\u003e wan ros \u003c--\u003e|WireGuard| sq ros \u003c--\u003e|WireGuard| dc ros --\u003e pve ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/:0:3","tags":["运维","网络","RouterOS"],"title":"小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/#为什么小型也会复杂"},{"categories":null,"collections":null,"content":"这套网络在解决什么 Office-JT 是主要办公地点，所以它的问题最多。 主网关是 RouterOS CHR，LAN 侧是 192.168.8.1/21。Switch 管理地址是 192.168.8.90，PVE 是 192.168.8.100。这些 LAN 地址可以公开讲，因为它们只是内网拓扑语义；真正需要避免暴露的是公网 IP、真实域名、MAC 和具体地点。 它当前至少要解决几类问题： 普通办公设备稳定出网 Multi-WAN 之间按策略分流 部分线路故障或质量变化时可以切换 PCC 模式 Office-SQ 和 DC-101 通过 WireGuard 保持站点互通 技术同事访问 DC-101 的非 HTTP 服务时，走 WireGuard Peer 到 DC-101 LAN，用于日常开发测试 运营同事在 Office-JT / Office-SQ 之间访问 SMB LAN IP Windows 共享，作为日常协作路径 对内使用服务名访问 DC 资源时，公共 DNS 记录可以直接返回 LAN / Internal Address，而不是把内部访问绕到公网入口 管理入口和 Backup Path 要和日常办公流量区分开 这里最容易误解的是最后几项。 DC-101 不是只给我个人远程管理用的点。对技术同事来说，有些非 HTTP 服务是日常开发测试会访问的资源。它们可以使用服务名，对应的公共 DNS 记录本身就返回 LAN 地址，再经由 WireGuard 到 DC-101。 这里不是办公室内部 DNS Rewrite，也不是维护一套 Split DNS。反正不在可信 LAN / WireGuard 网络里，解析到 LAN 地址也访问不了。真正的边界还是网络可达性：公网只暴露 HTTP 服务，非 HTTP 内部服务留在 LAN / WireGuard 里，不开放公网。 Office-JT 和 Office-SQ 之间的 SMB 访问也类似。它不是为了炫技做跨站访问，而是为了延续历史工具路径：最早大家在一起办公，Windows 共享就是 LAN 内协作方式；后面搬迁把办公室拆开之后，WireGuard 让这条路径不需要立刻重做成另一套系统。 HTTP 服务入口可以有另一套公网边界，但非 HTTP 内部服务更适合放在站点互联路径里解决。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/:0:4","tags":["运维","网络","RouterOS"],"title":"小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/#这套网络在解决什么"},{"categories":null,"collections":null,"content":"VLAN 不是部门隔离 这套网络里有 VLAN，但它当前不是为部门隔离设计的。 Office-JT 的 Switch 到 RouterOS 之间有一个 LAG1，RouterOS 侧是 bonding1。LAN 仍然在基础 bonding1 / br-lan 上，几条 WAN 则通过 VLAN 复用到 RouterOS： VLAN 角色 RouterOS 侧路径 10 PPPoE WAN vlan10 -\u0026gt; macvlan10 -\u0026gt; pppoe-out1 20 PCC route2 vlan20 -\u0026gt; macvlan20 30 PCC route3 vlan30 -\u0026gt; macvlan30 所以这里的 VLAN 主要在解决两个问题： 当前 3 条 WAN 从 Switch 侧接入后，如何复用同一组 Bonding 链路送到 RouterOS，并给后续 Modem 预留空间 RouterOS 上如何为不同 WAN 保留独立的 L2 / Macvlan 身份 它不是在做“研发部一个 VLAN、财务部一个 VLAN、访客一个 VLAN、服务器一个 VLAN”的细分模型。LAN 侧 192.168.8.0/21 这个大子网也不是精心设计出来的广播域治理结果，而是延续了快 10 年的初始设计。懒得改是一部分原因，另一部分原因是实际在线规模也就是 300-500 Devices，暂时还没逼到必须重做地址规划。 为什么不做？ 原因也不复杂。公司本身是相对宽松的互联网公司，没有强到必须按部门拆广播域和访问边界的机密隔离压力。我也不是专职网管，维护目标首先是让网络稳定、可理解、可恢复，而不是追求一套看起来很企业级的细分网络治理。 当然，严格说这不是没有成本。 广播域治理、访客隔离、东西向访问控制、安全审计，这些能力会弱一些。但在当前阶段，复杂度和收益不匹配。把 VLAN 先用于 Multi-WAN 和 Bonding 复用，是更现实的取舍。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/:0:5","tags":["运维","网络","RouterOS"],"title":"小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/#vlan-不是部门隔离"},{"categories":null,"collections":null,"content":"PCC 为什么要单独写 PCC 是这个系列里很重要的一篇，甚至可能不止一篇。 Office-JT 的 PCC 不是一句“多线负载均衡”就能解释完。它实际有几组可切换的模式： 模式 含义 0:1:1 不使用 route1，只在 route2 / route3 之间分流 1:1:1 route1 / route2 / route3 等比例分流 1:2:2 route1 权重低，route2 / route3 权重更高 2:3:3 三条线路都用，但 route2 / route3 权重更高 RouterOS 里的实现不是临时手改规则，而是有一组脚本去切换 pcc-mark-N/ Bucket Rules。 核心边界是： pcc-mark-\u0026lt;denominator\u0026gt;/\u0026lt;bucket\u0026gt;-route\u0026lt;route\u0026gt; 负责 PCC Bucket pcc-routing-route\u0026lt;route\u0026gt; 负责后续 Routing Mark 切换脚本只禁用 ^pcc-mark- 这层 Bucket Rules 切换脚本启用当前模式对应的 pcc-mark-N/ pcc-routing-* 不应该被 PCC 模式切换脚本误伤 这个边界很关键。 因为 PCC 的风险不只是“流量有没有平均分”。更麻烦的是：当一条 WAN 质量变化、某条线路需要临时降权、或者 PPPoE 需要避开时，脚本必须只切 Bucket Layer，而不能把后面的 Routing Layer 一起打乱。 所以后面写 PCC 时，我会基于 Office-JT 的实际脚本讲，而不是泛泛讲 RouterOS PCC 的概念。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/:0:6","tags":["运维","网络","RouterOS"],"title":"小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/#pcc-为什么要单独写"},{"categories":null,"collections":null,"content":"WireGuard 是日常路径，不是临时救火 在 Homelab 系列里，NetBird 是很重要的 Admin Overlay。 但在这个小型网络系列里，主角会换成 WireGuard。 原因是 Office-JT、Office-SQ、DC-101 之间的关系更像站点互联，而不是我个人拿 MacBook 从外面临时访问一下。RouterOS 内部承载 WireGuard，既能跑日常用户流量，也能承担一部分管理职能。 这和 WRT / NetBird / ZeroTier 的位置不一样： WireGuard：办公室站点之间的日常路径 WRT Peer：额外 Admin Layer NetBird Peer：Portable Devices (Admin) 访问和管理辅助 ZeroTier Peer：Backup Path 所以这套网络不能简单套用 Homelab 的分层。 Homelab 里我更关心“主网关要稳，WRT 承载透明代理和 Admin Overlay”。办公室这里更关心“RouterOS / Switch / WireGuard / PCC 如何把日常网络跑稳”。WRT 仍然存在，但它不应该抢走主数据面的叙事。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/:0:7","tags":["运维","网络","RouterOS"],"title":"小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/#wireguard-是日常路径不是临时救火"},{"categories":null,"collections":null,"content":"最后的结论 300-500 Devices、最多的时候不到 250 人，我会把它叫小型网络。 但“小型”不等于“简单”。 只要它开始同时处理 Multi-WAN、PCC、Switch Bonding、VLAN、Macvlan、WireGuard 站点互联、公共 DNS 返回内网地址和远程管理路径，它就已经是一套需要认真记录取舍的网络。 这套网络最核心的特点不是企业级，而是实用： VLAN 先服务当前 3 条 WAN 接入、后续 Modem 预留和 Bonding 复用 PCC 解决不同 WAN 之间的可切换分流 WireGuard 承载站点之间的日常访问 公共 DNS 直接给出 Internal Address，访问能力仍然受 LAN / WireGuard 安全域限制 WRT / NetBird / ZeroTier 保留为 Admin Layer 和 Backup Path 复杂度只在有收益的地方出现 它不完美，也不优雅，但在这个规模和管理方式下，它是更容易长期维护的形态。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/:0:8","tags":["运维","网络","RouterOS"],"title":"小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/#最后的结论"},{"categories":null,"collections":null,"content":"后续准备怎么写 后面几篇我会按决策拆开写。 第一篇先把问题范围定住：这是小型网络，不是企业网络；它复杂，是因为接入、线路、站点和管理路径叠在一起。 完整章节已经放在顶部系列导航里。这个系列会先拆 RouterOS / Switch 的职责边界，再拆 LAG / VLAN / Macvlan，之后单独写 PCC。PCC 那篇会更偏实现细节，因为分流脚本和故障行为都值得展开讲。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/:0:9","tags":["运维","网络","RouterOS"],"title":"小型网络系列：开篇 - 300-500 Devices 的网络为什么也会复杂","uri":"/2026/05/29/%E5%B0%8F%E5%9E%8B%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87-300-500-devices-%E7%9A%84%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B9%9F%E4%BC%9A%E5%A4%8D%E6%9D%82/#后续准备怎么写"},{"categories":null,"collections":null,"content":"总结 Homelab 网络自动化如何处理订阅生成、Sing-box 配置检查、VRRP 健康检查、Route Sync 和可恢复性。","date":"2026-05-29","objectID":"/2026/05/29/homelab-automation-recoverability/","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚","uri":"/2026/05/29/homelab-automation-recoverability/"},{"categories":null,"collections":null,"content":"系列导航 Homelab 网络系列：开篇 - 家庭网络为什么会变复杂 Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工 Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络 Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着 Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-automation-recoverability/:0:1","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚","uri":"/2026/05/29/homelab-automation-recoverability/#系列导航"},{"categories":null,"collections":null,"content":"背景 前面几篇讲的是网络形状：RouterOS 和 WRT 怎么分工，透明代理 VIP 怎么降级，NetBird 和 Backup Path 怎么分层。 这些设计如果只停留在文档里，很快就会变成另一个问题：配置一多，人手操作迟早会漏。 Homelab 网络里真正危险的改动通常不是“大改架构”，而是一些很小的日常操作： 订阅更新后，WRT 上的 Sing-box 配置没有同步 配置生成成功，但目标机器上的 Sing-box 版本不支持某个字段 WRT 服务重启了，但 VRRP Health 还没恢复 RouterOS 的 DHCP Option-set 改了，旧 Route 没有清理 远端站点 Route 能出去，但回程没有跟上 所以最后一篇不继续加功能，而是讲怎么让这些东西可恢复。 我的目标不是“全自动无人值守”，而是把高频操作变成有 Preflight、有校验、有备份、有回滚入口的流程。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-automation-recoverability/:0:2","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚","uri":"/2026/05/29/homelab-automation-recoverability/#背景"},{"categories":null,"collections":null,"content":"自动化不是直接改生产 我不喜欢把自动化理解成“脚本一跑，生产就变了”。 这套网络里，自动化更像三层： 层级 负责什么 失败时应该怎样 生成层 从订阅和模板生成配置 失败就不部署 部署层 分发配置、目标端校验、重启服务 失败就停在当前可用配置 运行层 Health Check、VRRP、Scheduler、日志 触发降级或留下排障证据 这也是为什么 subscriber.sh、subscribe-refresh.sh、restart-sing-box.sh 没有合成一个不可拆的大脚本。 平时用完整刷新入口；排障时可以拆开： 只生成配置 只检查生成结果 只分发并重启 Sing-box 只看 WRT Health 只跑 RouterOS Route Sync 自动化必须能拆开看，才有恢复价值。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-automation-recoverability/:0:3","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚","uri":"/2026/05/29/homelab-automation-recoverability/#自动化不是直接改生产"},{"categories":null,"collections":null,"content":"订阅生成是控制面 订阅生成这部分跑在 Repo 侧控制面里，不直接等同于 WRT Runtime。 输入大概有几类： Provider 和 Bundle 定义 Sing-box / sing-box-compat / Mihomo / Stash 模板 静态节点和运行时选择策略 Operator 本地环境和输出目录 输出默认落到静态目录里： Sing-box Gateway / Client Configs Sing-box Compatibility Configs Mihomo GUI / Client Configs Stash GUI / Client Configs Raw 和 Logs 辅助输出 当前 WRT Runtime Data-plane 用的是 Sing-box。Mihomo 和 Stash 仍然是 Active Generated Output Families，但它们不是 WRT 上的主数据面服务。 这个边界很重要。否则很容易在排障时把“生成了某个 GUI 配置”和“网关上的 Sing-box Runtime 已经生效”混成一件事。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-automation-recoverability/:0:4","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚","uri":"/2026/05/29/homelab-automation-recoverability/#订阅生成是控制面"},{"categories":null,"collections":null,"content":"部署链路 日常更新走的是一个 Preflighted Refresh。 它的顺序不是随便排的： 先检查目标 WRT 是否可 SSH、是否有 /etc/sing-box、是否能执行 Sing-box、是否有 Init 脚本 再跑订阅生成 检查生成出来的 Gateway Config 是否存在且非空 部署前再做一次 WRT Preflight 分发新配置到目标 WRT 在目标 WRT 上执行 sing-box check 备份旧配置，替换新配置，重启服务 sequenceDiagram participant Cron as PVE 10.1.1.100 Cron / Operator participant Refresh as subscribe-refresh.sh participant WRT as Homelab / Office-JT WRT participant Generator as subscriber.sh participant Static as Generated Static Outputs participant Service as Sing-box Service Cron-\u003e\u003eRefresh: Start Refresh Refresh-\u003e\u003eWRT: Preflight Before Generation WRT--\u003e\u003eRefresh: SSH + Sing-box Runtime OK Refresh-\u003e\u003eGenerator: Generate Configs Generator-\u003e\u003eStatic: Write Gateway/Client Outputs Refresh-\u003e\u003eStatic: Validate Gateway Config Exists Refresh-\u003e\u003eWRT: Preflight Before Restart Refresh-\u003e\u003eWRT: Copy config.json.new WRT-\u003e\u003eWRT: Sing-box Check config.json.new WRT-\u003e\u003eService: Backup Current Config, Replace, Restart Service--\u003e\u003eRefresh: Restart Result sequenceDiagram participant Cron as PVE 10.1.1.100 Cron / Operator participant Refresh as subscribe-refresh.sh participant WRT as Homelab / Office-JT WRT participant Generator as subscriber.sh participant Static as Generated Static Outputs participant Service as Sing-box Service Cron-\u003e\u003eRefresh: Start Refresh Refresh-\u003e\u003eWRT: Preflight Before Generation WRT--\u003e\u003eRefresh: SSH + Sing-box Runtime OK Refresh-\u003e\u003eGenerator: Generate Configs Generator-\u003e\u003eStatic: Write Gateway/Client Outputs Refresh-\u003e\u003eStatic: Validate Gateway Config Exists Refresh-\u003e\u003eWRT: Preflight Before Restart Refresh-\u003e\u003eWRT: Copy config.json.new WRT-\u003e\u003eWRT: Sing-box Check config.json.new WRT-\u003e\u003eService: Backup Current Config, Replace, Restart Service--\u003e\u003eRefresh: Restart Result sequenceDiagram participant Cron as PVE 10.1.1.100 Cron / Operator participant Refresh as subscribe-refresh.sh participant WRT as Homelab / Office-JT WRT participant Generator as subscriber.sh participant Static as Generated Static Outputs participant Service as Sing-box Service Cron-\u003e\u003eRefresh: Start Refresh Refresh-\u003e\u003eWRT: Preflight Before Generation WRT--\u003e\u003eRefresh: SSH + Sing-box Runtime OK Refresh-\u003e\u003eGenerator: Generate Configs Generator-\u003e\u003eStatic: Write Gateway/Client Outputs Refresh-\u003e\u003eStatic: Validate Gateway Config Exists Refresh-\u003e\u003eWRT: Preflight Before Restart Refresh-\u003e\u003eWRT: Copy config.json.new WRT-\u003e\u003eWRT: Sing-box Check config.json.new WRT-\u003e\u003eService: Backup Current Config, Replace, Restart Service--\u003e\u003eRefresh: Restart Result sequenceDiagram participant Cron as PVE 10.1.1.100 Cron / Operator participant Refresh as subscribe-refresh.sh participant WRT as Homelab / Office-JT WRT participant Generator as subscriber.sh participant Static as Generated Static Outputs participant Service as Sing-box Service Cron-\u003e\u003eRefresh: Start Refresh Refresh-\u003e\u003eWRT: Preflight Before Generation WRT--\u003e\u003eRefresh: SSH + Sing-box Runtime OK Refresh-\u003e\u003eGenerator: Generate Configs Generator-\u003e\u003eStatic: Write Gateway/Client Outputs Refresh-\u003e\u003eStatic: Validate Gateway Config Exists Refresh-\u003e\u003eWRT: Preflight Before Restart Refresh-\u003e\u003eWRT: Copy config.json.new WRT-\u003e\u003eWRT: Sing-box Check config.json.new WRT-\u003e\u003eService: Backup Current Config, Replace, Restart Service--\u003e\u003eRefresh: Restart Result 这条链路最重要的点，是新配置必须先在目标端 sing-box check 通过，才会替换旧配置。 也就是说，订阅生成成功不代表部署成功；部署成功也不是“文件拷过去就行”。目标机器上的二进制版本、配置字段、服务脚本都必须在链路里被验证。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-automation-recoverability/:0:5","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚","uri":"/2026/05/29/homelab-automation-recoverability/#部署链路"},{"categories":null,"collections":null,"content":"远端执行不要污染环境 订阅生成有两种运行模式。 本地开发时使用 Project Mode，通过项目环境运行，方便测试和开发。 远端或 Cron 路径使用 Ephemeral Mode，通过临时执行环境运行，避免在远端 Checkout 里长期留下 .venv 之类的状态。 这点看起来很小，但对可恢复性很有价值。 Homelab 的自动化脚本经常跑在 PVE Host 或远端管理机上。如果每次 Cron 都可能改本地虚拟环境，之后排障就很难判断问题来自代码、依赖、环境，还是一次失败的半成品更新。 所以远端路径尽量保持轻量：源码和配置是 Truth，运行环境临时解析，生成结果明确写到输出目录。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-automation-recoverability/:0:6","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚","uri":"/2026/05/29/homelab-automation-recoverability/#远端执行不要污染环境"},{"categories":null,"collections":null,"content":"WRT Health 只让必要失败触发 VIP 降级 第三篇讲过透明代理 VIP 的 VRRP Fallback。这里补自动化视角。 WRT 上的 Health Check 分成两层： L1：决定是否还能持有 VIP L2：记录海外访问质量，但不直接让 WRT 释放 VIP L1 看的是基础能力： Sing-box 进程状态 DNS 配置是否符合预期 国内 DNS Lookup TUN 是否存在 Nft Redirect 是否存在 可选的国内 HTTP Smoke L2 看的是海外 DNS、Proxy DNS Smoke、海外 HTTP Smoke。它可以标记 overseas_degraded，但只要 L1 还过，就不应该把 VIP 让给 RouterOS。 这个分层背后的取舍是：海外路径不稳定时，不能轻易让所有代理客户端从 WRT 切到 RouterOS Fallback。RouterOS Fallback 解决的是 WRT / Sing-box 基础不可用，不解决所有海外质量问题。 Health Check 还要防止自己变成故障源。单次探测有 Timeout，Keepalived 的 Track Script 也有 Timeout；慢探测会被限制，不应该一直占着下一轮检查。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-automation-recoverability/:0:7","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚","uri":"/2026/05/29/homelab-automation-recoverability/#wrt-health-只让必要失败触发-vip-降级"},{"categories":null,"collections":null,"content":"RouterOS Manifest 是主网关侧的 Truth RouterOS 这边不能靠手工记忆。 Homelab RouterOS 的 Active State 由 Manifest 描述，里面包括： System Scripts Schedulers PPP Profile PPPoE Profile Binding 要删除的旧脚本、旧 Scheduler、旧文件 例如 NetBird DHCP Route Sync 在 RouterOS 侧是一个明确的 System Script 和 Scheduler： RouterOS 定时读取 WRT 10.1.1.254 上的 NetBird Route Table 只接受私有网段 Route 过滤掉 Homelab 自己的 LAN 生成 DHCP Option 121/249 proxy-netbird 客户端拿到 Site Routes，下一跳指向 10.1.1.254 这里 RouterOS 是 DHCP 控制点，不是 Overlay Data Plane。这个边界由脚本和 Scheduler 固化下来，比“我记得之前手动改过”可靠。 sequenceDiagram participant RouterOS as RouterOS 10.1.1.1 participant Manifest as Repo Manifest participant WRT as WRT 10.1.1.254 participant DHCP as DHCP Option-set participant Client as proxy-netbird Clients Manifest-\u003e\u003eRouterOS: Install Scripts and Schedulers RouterOS-\u003e\u003eWRT: Every 10m Read NetBird Route Table WRT--\u003e\u003eRouterOS: Private Site Routes RouterOS-\u003e\u003eRouterOS: Filter Local LAN and Unchanged Payload RouterOS-\u003e\u003eDHCP: Update Option 121/249 When Changed DHCP--\u003e\u003eClient: Site Routes -\u003e 10.1.1.254 sequenceDiagram participant RouterOS as RouterOS 10.1.1.1 participant Manifest as Repo Manifest participant WRT as WRT 10.1.1.254 participant DHCP as DHCP Option-set participant Client as proxy-netbird Clients Manifest-\u003e\u003eRouterOS: Install Scripts and Schedulers RouterOS-\u003e\u003eWRT: Every 10m Read NetBird Route Table WRT--\u003e\u003eRouterOS: Private Site Routes RouterOS-\u003e\u003eRouterOS: Filter Local LAN and Unchanged Payload RouterOS-\u003e\u003eDHCP: Update Option 121/249 When Changed DHCP--\u003e\u003eClient: Site Routes -\u003e 10.1.1.254 sequenceDiagram participant RouterOS as RouterOS 10.1.1.1 participant Manifest as Repo Manifest participant WRT as WRT 10.1.1.254 participant DHCP as DHCP Option-set participant Client as proxy-netbird Clients Manifest-\u003e\u003eRouterOS: Install Scripts and Schedulers RouterOS-\u003e\u003eWRT: Every 10m Read NetBird Route Table WRT--\u003e\u003eRouterOS: Private Site Routes RouterOS-\u003e\u003eRouterOS: Filter Local LAN and Unchanged Payload RouterOS-\u003e\u003eDHCP: Update Option 121/249 When Changed DHCP--\u003e\u003eClient: Site Routes -\u003e 10.1.1.254 sequenceDiagram participant RouterOS as RouterOS 10.1.1.1 participant Manifest as Repo Manifest participant WRT as WRT 10.1.1.254 participant DHCP as DHCP Option-set participant Client as proxy-netbird Clients Manifest-\u003e\u003eRouterOS: Install Scripts and Schedulers RouterOS-\u003e\u003eWRT: Every 10m Read NetBird Route Table WRT--\u003e\u003eRouterOS: Private Site Routes RouterOS-\u003e\u003eRouterOS: Filter Local LAN and Unchanged Payload RouterOS-\u003e\u003eDHCP: Update Option 121/249 When Changed DHCP--\u003e\u003eClient: Site Routes -\u003e 10.1.1.254 这个 Route Sync 失败时，目标不是立刻改一堆静态路由。更好的排障顺序是看 WRT Route Table、RouterOS Script Log、DHCP Option Payload、客户端实际 Route。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-automation-recoverability/:0:8","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚","uri":"/2026/05/29/homelab-automation-recoverability/#routeros-manifest-是主网关侧的-truth"},{"categories":null,"collections":null,"content":"回滚不是一个按钮 Homelab 的回滚更像分层恢复，而不是一个万能按钮。 Sing-box 配置部署有上一份配置备份。新配置只有在目标端 Check 通过后才会替换；替换前旧配置会保留一份。出问题时，至少知道上一份 Runtime Config 在哪里。 RouterOS 侧有 Audit / Sync / Install 流程。Install 前后会留下运行证据，Manifest 里也能表达哪些旧脚本和旧文件应该删除。这样排障时可以比较“Repo 期望状态”和“RouterOS 当前状态”，而不是靠终端历史猜。 WRT 侧的 Health 状态写到临时状态文件，关键状态变化进系统日志。VRRP 切换时，看的是 Health 失败、Priority 变化、进入 BACKUP / MASTER 这些明确事件，而不是只看客户端说“好像断了”。 可恢复性的关键是证据链： 生成层知道自己生成了什么 部署层知道目标端有没有接受新配置 运行层知道为什么降级 RouterOS 侧知道 Desired State 和 Live State 是否一致 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-automation-recoverability/:0:9","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚","uri":"/2026/05/29/homelab-automation-recoverability/#回滚不是一个按钮"},{"categories":null,"collections":null,"content":"验证 这类自动化要验证的是链路，不是单个脚本。 我会拆成几组： 生成：默认 Processor 是否能输出 Sing-box / Compatibility / Mihomo / Stash 结果 部署：WRT Preflight 是否通过，目标端 sing-box check 是否通过 服务：新配置是否替换，Sing-box 是否重启成功 健康：L1 失败是否释放 VIP，L2 Degraded 是否只记录不抢 VIP RouterOS：Manifest Audit 是否能发现 Drift，NetBird Route Sync Scheduler 是否存在 客户端：proxy 和 proxy-netbird 拿到的 DHCP Option 是否不同 验证时还要刻意看失败路径： 目标 WRT 不可达时，不应该继续部署 生成配置为空时，不应该重启服务 目标端 sing-box check 失败时，不应该替换旧配置 Route Sync 读取 WRT 失败时，不应该清空已有 DHCP Route L2 海外探测慢时，不应该把 Keepalived Health Script 拖死 这些失败路径比 Happy Path 更能说明自动化有没有边界。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-automation-recoverability/:0:10","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚","uri":"/2026/05/29/homelab-automation-recoverability/#验证"},{"categories":null,"collections":null,"content":"最后的结论 Homelab 网络复杂之后，自动化的价值不是少打几条命令，而是让高频操作有边界、有证据、有回滚入口。 订阅生成负责控制面输出，部署链路负责目标端校验和重启，WRT Health 负责代理 VIP 是否应该继续由 WRT 持有，RouterOS Manifest 负责主网关侧脚本和 Scheduler 的 Desired State。 这些机制合在一起，才让前面几篇的网络设计可维护。否则再好的拓扑，最后都会败给一次漏同步、一次错误重启，或者一次没有证据的手工修复。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-automation-recoverability/:0:11","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚","uri":"/2026/05/29/homelab-automation-recoverability/#最后的结论"},{"categories":null,"collections":null,"content":"解释 ZeroTier P2P 和 Sing-box Inbound 为什么仍然作为 Backup Path 保留，并和 NetBird Admin Overlay、透明代理路径保持故障域隔离。","date":"2026-05-29","objectID":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着","uri":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/"},{"categories":null,"collections":null,"content":"系列导航 Homelab 网络系列：开篇 - 家庭网络为什么会变复杂 Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工 Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络 Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着 Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/:0:1","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着","uri":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/#系列导航"},{"categories":null,"collections":null,"content":"背景 前一篇讲 NetBird 的位置：它是日常 Admin Overlay，负责 Portable Devices (Admin) 访问 Homelab / Hometown / Office / DC-101 的 Peer 和 Route。 但日常路径稳定，不等于可以删掉所有 Backup Path。 我保留 Backup Path 的原因很简单：网络真正坏的时候，最危险的不是某条链路慢，而是所有入口都依赖同一个控制面。 如果 NetBird 的 ACL、Control Plane、客户端状态、WRT 上的 Route Table 其中任何一层出问题，我仍然需要一条可以进去看的路。这个入口不一定舒服，也不一定承担完整路由，但它必须尽量和主路径解耦。 所以这里保留了两类 Backup Path： ZeroTier：保留 P2P Peer 能力，不作为主要 Network Route Sing-box Inbound：Homelab / Office-JT 的备用入口，由 WRT 承载 它们不是为了替代 NetBird，而是为了在 NetBird 不好用的时候，还有办法登录、确认状态、修配置。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/:0:2","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着","uri":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/#背景"},{"categories":null,"collections":null,"content":"先把路径分层 这套网络里容易混淆的地方，是“能连进去”的方案很多，但每条路径解决的问题不一样。 我现在大概这样分： 路径 角色 平时是否主用 失败时看什么 NetBird 日常 Admin Overlay 是 Peer、ACL、Route、回程 ZeroTier P2P Emergency Peer 否 Peer 是否在线、能否 SSH Sing-box Inbound 公网备用入口 否 入口转发、WRT Inbound、下游 LAN Route RouterOS / WRT Fallback Homelab 内部降级 是内部兜底 VIP、VRRP、DNS、普通出口 这里要避免一个误区：Backup Path 不是另一套完整生产网络。 如果把 ZeroTier 也做成完整站点路由，把 Sing-box Inbound 也做成常规默认代理，再把 NetBird 也当主入口，最后不是高可用，而是三套状态互相覆盖。排障时会先问“现在到底走哪条路”，而不是直接定位问题。 所以 Backup Path 的目标要窄： 能确认远端节点是否活着 能进入 WRT 或 RouterOS 看状态 能在必要时修 NetBird / Sing-box / Route / ACL 不承担普通客户端的默认访问 不改变 Homelab 内部主网关职责 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/:0:3","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着","uri":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/#先把路径分层"},{"categories":null,"collections":null,"content":"ZeroTier 为什么只保留 P2P ZeroTier 仍然有效，但我没有把它作为主 Network Route 使用。 原因不是它不能做 Route，而是这里已经有 NetBird 负责 Admin Overlay。如果再让 ZeroTier 也发布站点网段，问题会变成： 同一个站点有多套 Overlay Route Portable Devices (Admin) 的访问边界分散到多个控制面 回程路由和 NAT 排障要同时考虑 NetBird / ZeroTier 某条路径偶然能通，容易掩盖主路径设计问题 这和 Backup Path 的目的相反。 我保留 ZeroTier 的价值主要是 Peer-level Emergency Access。比如远端站点离现场足够远，NetBird 或主入口出了问题时，ZeroTier Peer 只要还能起来，就可以作为第二条 SSH / Ping / Status Path。 它不需要知道所有 LAN Route，也不需要给普通客户端下发 Route。它只要能回答一个问题：主 Overlay 坏了以后，我还能不能进到关键节点上看一眼。 这个定位也让它更容易维护。ZeroTier 出问题时，不会影响 Homelab 的默认访问；ZeroTier 正常时，也不会改变 NetBird 的 ACL 和 Route 语义。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/:0:4","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着","uri":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/#zerotier-为什么只保留-p2p"},{"categories":null,"collections":null,"content":"Sing-box Inbound 为什么放在 WRT 另一条 Backup Path 是 Sing-box Inbound。 它的形态更像传统公网入口： RouterOS 保持公网入口和端口转发边界 入站流量被转到对应站点的 WRT WRT 上的 Sing-box Inbound 接住连接 再访问 Homelab 或 Office-JT 的管理 LAN 我没有把这部分塞进 RouterOS。原因和前面几篇一样：RouterOS 是主网关，要兜住日常国内访问和基础网络；WRT 是额外能力层，适合承载 Sing-box、NetBird、ZeroTier 这类变化快、需要包管理和日志的东西。 Sing-box Inbound 放在 WRT 上，坏了也只是坏掉这条备用入口。它不应该影响普通客户端上网，也不应该改变 RouterOS 的主出口策略。 这里还有一个边界：Sing-box Inbound 是入口，不是 Homelab 内部透明代理 VIP。 透明代理 VIP 解决的是 Homelab 内部某些客户端如何出站；Sing-box Inbound 解决的是人不在现场时如何从外面进来。它们都由 WRT 承载，但故障域不一样。 sequenceDiagram participant Admin as Portable Devices (Admin) participant NetBird as NetBird Admin Overlay participant ZeroTier as ZeroTier P2P participant RouterOS as RouterOS Ingress Edge participant WRT as Homelab / Office-JT WRT participant LAN as Management LAN rect rgb(240, 250, 244) Note over Admin,LAN: 日常路径：NetBird 管 Peer、ACL、Route Admin-\u003e\u003eNetBird: Connect as Portable Devices (Admin) NetBird-\u003e\u003eWRT: Permitted Peer or Site Route WRT-\u003e\u003eLAN: Routed or NATed Admin Access end rect rgb(255, 248, 230) Note over Admin,WRT: Emergency Path：ZeroTier 只保留 P2P 管理能力 Admin-\u003e\u003eZeroTier: Reach Emergency Peer ZeroTier-\u003e\u003eWRT: Ping / SSH / Status Check end rect rgb(245, 248, 255) Note over Admin,LAN: Backup Ingress：Sing-box Inbound 由 WRT 接住 Admin-\u003e\u003eRouterOS: Public Ingress to Backup Port RouterOS-\u003e\u003eWRT: DNAT to Sing-box Inbound WRT-\u003e\u003eLAN: Downstream Management Access end sequenceDiagram participant Admin as Portable Devices (Admin) participant NetBird as NetBird Admin Overlay participant ZeroTier as ZeroTier P2P participant RouterOS as RouterOS Ingress Edge participant WRT as Homelab / Office-JT WRT participant LAN as Management LAN rect rgb(240, 250, 244) Note over Admin,LAN: 日常路径：NetBird 管 Peer、ACL、Route Admin-\u003e\u003eNetBird: Connect as Portable Devices (Admin) NetBird-\u003e\u003eWRT: Permitted Peer or Site Route WRT-\u003e\u003eLAN: Routed or NATed Admin Access end rect rgb(255, 248, 230) Note over Admin,WRT: Emergency Path：ZeroTier 只保留 P2P 管理能力 Admin-\u003e\u003eZeroTier: Reach Emergency Peer ZeroTier-\u003e\u003eWRT: Ping / SSH / Status Check end rect rgb(245, 248, 255) Note over Admin,LAN: Backup Ingress：Sing-box Inbound 由 WRT 接住 Admin-\u003e\u003eRouterOS: Public Ingress to Backup Port RouterOS-\u003e\u003eWRT: DNAT to Sing-box Inbound WRT-\u003e\u003eLAN: Downstream Management Access end sequenceDiagram participant Admin as Portable Devices (Admin) participant NetBird as NetBird Admin Overlay participant ZeroTier as ZeroTier P2P participant RouterOS as RouterOS Ingress Edge participant WRT as Homelab / Office-JT WRT participant LAN as Management LAN rect rgb(240, 250, 244) Note over Admin,LAN: 日常路径：NetBird 管 Peer、ACL、Route Admin-\u003e\u003eNetBird: Connect as Portable Devices (Admin) NetBird-\u003e\u003eWRT: Permitted Peer or Site Route WRT-\u003e\u003eLAN: Routed or NATed Admin Access end rect rgb(255, 248, 230) Note over Admin,WRT: Emergency Path：ZeroTier 只保留 P2P 管理能力 Admin-\u003e\u003eZeroTier: Reach Emergency Peer ZeroTier-\u003e\u003eWRT: Ping / SSH / Status Check end rect rgb(245, 248, 255) Note over Admin,LAN: Backup Ingress：Sing-box Inbound 由 WRT 接住 Admin-\u003e\u003eRouterOS: Public Ingress to Backup Port RouterOS-\u003e\u003eWRT: DNAT to Sing-box Inbound WRT-\u003e\u003eLAN: Downstream Management Access end sequenceDiagram participant Admin as Portable Devices (Admin) participant NetBird as NetBird Admin Overlay participant ZeroTier as ZeroTier P2P participant RouterOS as RouterOS Ingress Edge participant WRT as Homelab / Office-JT WRT participant LAN as Management LAN rect rgb(240, 250, 244) Note over Admin,LAN: 日常路径：NetBird 管 Peer、ACL、Route Admin-\u003e\u003eNetBird: Connect as Portable Devices (Admin) NetBird-\u003e\u003eWRT: Permitted Peer or Site Route WRT-\u003e\u003eLAN: Routed or NATed Admin Access end rect rgb(255, 248, 230) Note over Admin,WRT: Emergency Path：ZeroTier 只保留 P2P 管理能力 Admin-\u003e\u003eZeroTier: Reach Emergency Peer ZeroTier-\u003e\u003eWRT: Ping / SSH / Status Check end rect rgb(245, 248, 255) Note over Admin,LAN: Backup Ingress：Sing-box Inbound 由 WRT 接住 Admin-\u003e\u003eRouterOS: Public Ingress to Backup Port RouterOS-\u003e\u003eWRT: DNAT to Sing-box Inbound WRT-\u003e\u003eLAN: Downstream Management Access end ","date":"2026-05-29","objectID":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/:0:5","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着","uri":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/#sing-box-inbound-为什么放在-wrt"},{"categories":null,"collections":null,"content":"Backup Path 不应该自动接管 我没有让这些 Backup Path 自动接管主路径。 这点很关键。 VRRP 的自动接管适合 Homelab 内部代理 VIP：客户端只认 10.1.1.253，WRT L1 健康失败时 RouterOS 接管，结果是代理能力降级，但普通访问还能走。 但远程管理入口不一样。这里如果做自动接管，很容易把故障隐藏起来： NetBird 不通时，流量悄悄走 ZeroTier Site Route 不通时，临时 Sing-box Inbound 变成常规路径 回程路由错了，但另一个 Backup Path 让测试看起来通过 这种“看起来能用”会让设计慢慢失真。 所以我更倾向于显式切换： 日常先看 NetBird NetBird 不通，再看 ZeroTier Peer 是否能进 需要公网入口时，才走 Sing-box Inbound 修完后，回到 NetBird 和正式 Route 模型 Backup Path 的价值是救援，不是制造第四个日常控制面。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/:0:6","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着","uri":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/#backup-path-不应该自动接管"},{"categories":null,"collections":null,"content":"和 Office 网络的边界 Office-JT / Office-SQ / DC-101 的日常用户流量不是 NetBird，也不是这些 Backup Path。 Office 那边还有 RouterOS、WireGuard、PCC、VLAN、Switch Bonding 等一整套问题。那些路径解决的是办公室的用户流量和站点级路由，不应该混到 Homelab 系列里展开。 在这篇里，Office 只作为远端管理目标出现： NetBird：日常 Admin Overlay ZeroTier：远端 Peer 级别的 Emergency Access Sing-box Inbound：Office-JT 的备用入口 至于 Office 为什么用 WireGuard 承载日常流量，为什么 RouterOS 内部处理策略会不一样，那应该是另一个系列。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/:0:7","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着","uri":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/#和-office-网络的边界"},{"categories":null,"collections":null,"content":"验证 Backup Path 的验证也不能只看“客户端显示在线”。 我会按路径拆： NetBird：Portable Devices (Admin) 是否在线，ACL 和 Site Routes 是否符合预期 ZeroTier：Peer 是否能 P2P，是否能 Ping / SSH 到关键 WRT Peer Sing-box Inbound：公网入口是否到 WRT，WRT Inbound 是否监听，下游 LAN Route 是否能回 RouterOS：入口 DNAT 是否仍由 RouterOS 管，是否没有把 Backup Path 做成普通默认路径 WRT：Sing-box / NetBird / ZeroTier 的日志能否分别定位问题 这里最重要的验证，是故障域不要串。 ZeroTier 不应该因为 NetBird Route 更新失败而改变行为；Sing-box Inbound 不应该因为透明代理 VIP 切换而被误判；RouterOS 主网关不应该因为某个 Backup Path 的服务重启而影响普通客户端。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/:0:8","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着","uri":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/#验证"},{"categories":null,"collections":null,"content":"最后的结论 NetBird 是日常 Admin Overlay，ZeroTier 和 Sing-box Inbound 是 Backup Path。 ZeroTier 只保留 P2P Emergency Access，不作为主要站点 Network Route。 Sing-box Inbound 由 WRT 承载，用来提供 Homelab / Office-JT 的备用入口，不进入普通客户端默认访问路径。 这套设计的重点不是“入口越多越安全”，而是每条入口都有清楚边界。日常路径、救援路径、内部 Fallback 分开之后，故障时才能知道应该查 ACL、Peer、入口转发、WRT 服务，还是下游 LAN 回程。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/:0:9","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着","uri":"/2026/05/29/homelab-backup-path-zerotier-singbox-inbound/#最后的结论"},{"categories":null,"collections":null,"content":"说明 NetBird 在 Homelab 中作为 Admin Overlay 的 ACL 设计，以及 Mobile Devices / MacBook 如何访问 Homelab、Hometown、Office 和 DC-101。","date":"2026-05-29","objectID":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络","uri":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/"},{"categories":null,"collections":null,"content":"系列导航 Homelab 网络系列：开篇 - 家庭网络为什么会变复杂 Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工 Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络 Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着 Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/:0:1","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络","uri":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/#系列导航"},{"categories":null,"collections":null,"content":"背景 前面几篇一直在说 RouterOS、WRT、VIP、Fallback DNS。那些东西解决的是 Homelab 里面的默认网关、透明代理和降级问题。 但还有另一个问题：人不在家里的时候，Mobile Devices 和 MacBook 怎么访问这些网络？ 这里的访问目标不止一个 Homelab： Homelab 的管理入口和内网服务 Hometown 的 WRT Peer Office-JT / Office-SQ 的管理网络 DC-101 这类远端 RouterOS / WRT 管理点 如果只看“能连进去”，方案很多：WireGuard、Tailscale、ZeroTier、NetBird、Sing-box Inbound 都能做一部分。 但我这里真正要解决的不是“从外面连回家”，而是： 哪些 Portable Devices (Admin) 可以访问哪些站点 哪些 WRT Peer 可以作为 Subnet Router Mobile Devices / MacBook 是 Admin Device，不应该变成任意 LAN 的默认出口 Homelab 内部的部分客户端也需要知道 Office / Hometown 路由 出问题时，Admin Overlay 和 Backup Path 要能分清楚 所以 NetBird 在这套网络里的定位，是 Admin Overlay。 它不是普通客户端的默认代理，也不是 Office 日常用户流量的主通道。Office 那部分日常流量和管理职责主要由 RouterOS / WireGuard 解决，属于另一个系列。这里讲的是我作为 Admin，用 Mobile Devices / MacBook 访问 Homelab / Hometown / Office / DC-101 的路径。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/:0:2","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络","uri":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/#背景"},{"categories":null,"collections":null,"content":"为什么不是只开一个 VPN 最朴素的做法，是在 Homelab 开一个 VPN，Mobile Devices 和 MacBook 连进来。 这个方案在单站点时很好理解： 客户端连进 Homelab 拿到一个虚拟网段地址 访问 Homelab LAN 必要时再从 Homelab 转发到其他站点 但多站点之后，它很快会变成另一个问题：所有访问都必须先回 Homelab，再从 Homelab 绕出去。 这带来几个麻烦： Homelab 变成所有管理流量的单点 每个远端站点都要处理从 Homelab 过来的回程 远端 Peer 是否在线、Route 是否发布、ACL 是否允许，很难从一个普通 VPN 配置里看清楚 Mobile Devices / MacBook 的权限边界容易变成“能进 VPN 就都能访问” NetBird 的好处不是“它比某个产品更高级”，而是它的抽象刚好贴近这个问题： Peer Registry 能看到哪些设备和站点在线 ACL 可以按 Peer / Group / Route 控制访问 WRT Peer 可以作为 Subnet Router 暴露受控网段 Portable Devices (Admin) 可以只拿 Admin 访问，不承担站点路由职责 Tailscale 我也对比过，但这篇不是 Tailscale 评测。对我来说，关键不是客户端体验，而是 NetBird 的 ACL、Peer Registry 和 Route Awareness 能比较自然地嵌进现有 RouterOS / WRT 分工里。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/:0:3","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络","uri":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/#为什么不是只开一个-vpn"},{"categories":null,"collections":null,"content":"角色怎么拆 我把 NetBird 里面的角色分成三类。 第一类是 Portable Devices (Admin)： Mobile Devices MacBook 它们是随身管理设备。它们应该能访问被允许的 Homelab / Hometown / Office / DC-101 管理入口，但不应该被当成某个站点的 Subnet Router。 第二类是 WRT Peers： Homelab WRT Hometown WRT Office-JT WRT Office-SQ WRT DC-101 WRT 这些节点更像站点边界上的 Admin Sidecar。它们可以暴露某个站点的受控网段，也可以承载 NetBird Peer、ZeroTier Peer、Sing-box Inbound 这类额外管理路径。 这里还要再分一层：Homelab WRT 10.1.1.254 和 Office-JT WRT 是我常驻 Admin 位置的 Peer，它们拥有完整 Routes。其他 WRT Peers 更多是 Peer-level 管理目标，主要用于互 Ping / SSH 和状态确认，不默认展开背后的 LAN 访问。 第三类是 Homelab 里的 proxy-netbird Clients。 这类客户端仍然把默认网关和 DNS 指向代理 VIP 10.1.1.253，但额外通过 DHCP Option 121/249 拿到 NetBird / Site Routes。这些 Route 的下一跳不是 RouterOS，而是 WRT 10.1.1.254。 也就是说，同一台客户端上会同时存在两类路径： 流量类型 下一跳 默认网关 / DNS 代理 VIP 10.1.1.253 NetBird / Site Route WRT 10.1.1.254 这点很重要。RouterOS 仍然是主网关和 DHCP 控制点，但它不需要理解 NetBird Overlay 的内部状态。它只负责把经过筛选的站点路由下发给需要的客户端。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/:0:4","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络","uri":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/#角色怎么拆"},{"categories":null,"collections":null,"content":"原生 NetBird Peer 路径 第一种路径，是 Mobile Devices / MacBook 自己就是 NetBird Peer。 这时它们和各个 WRT Peers 是 NetBird Overlay 里的 P2P 关系。Portable Devices (Admin) 可以访问被 ACL 允许的 Peer；如果目标是 Homelab WRT 或 Office-JT WRT 这类常驻 Admin Peer，还可以继续访问它们背后的受控 LAN Routes。 其他 WRT Peers 不是“打开一个站点 LAN 给所有 Admin 设备”。它们默认更像 Peer-level 管理点，能互 Ping / SSH / 看状态，但不把背后 LAN 当成默认可访问范围。 sequenceDiagram participant Portable as Portable Devices (Admin)Mobile Devices / MacBook participant NetBird as NetBird ACL / Registry participant HomeWRT as Homelab WRT 10.1.1.254 participant OfficeJT as Office-JT WRTAdmin Full Routes participant OtherPeers as Hometown / Office-SQ / DC-101 WRT Peers participant AdminLAN as Permitted Admin LAN Routes rect rgb(245, 248, 255) Note over Portable,NetBird: 原生 NetBird Peer，先受 ACL 约束 Portable-\u003e\u003eNetBird: Authenticate Peer NetBird--\u003e\u003ePortable: Allowed Peers and Routes end rect rgb(240, 250, 244) Note over Portable,AdminLAN: 常驻 Admin Peers 拥有完整 Routes Portable-\u003e\u003eHomeWRT: P2P Access to Homelab WRT HomeWRT-\u003e\u003eAdminLAN: Routed Homelab Access when Allowed Portable-\u003e\u003eOfficeJT: P2P Access to Office-JT WRT OfficeJT-\u003e\u003eAdminLAN: Routed Office-JT Access when Allowed end rect rgb(255, 248, 230) Note over Portable,OtherPeers: 其他 WRT Peers 默认是 Peer-level Admin Targets Portable-\u003e\u003eOtherPeers: Ping / SSH / Peer Health Checks OtherPeers--\u003e\u003ePortable: Peer-level Response end sequenceDiagram participant Portable as Portable Devices (Admin)Mobile Devices / MacBook participant NetBird as NetBird ACL / Registry participant HomeWRT as Homelab WRT 10.1.1.254 participant OfficeJT as Office-JT WRTAdmin Full Routes participant OtherPeers as Hometown / Office-SQ / DC-101 WRT Peers participant AdminLAN as Permitted Admin LAN Routes rect rgb(245, 248, 255) Note over Portable,NetBird: 原生 NetBird Peer，先受 ACL 约束 Portable-\u003e\u003eNetBird: Authenticate Peer NetBird--\u003e\u003ePortable: Allowed Peers and Routes end rect rgb(240, 250, 244) Note over Portable,AdminLAN: 常驻 Admin Peers 拥有完整 Routes Portable-\u003e\u003eHomeWRT: P2P Access to Homelab WRT HomeWRT-\u003e\u003eAdminLAN: Routed Homelab Access when Allowed Portable-\u003e\u003eOfficeJT: P2P Access to Office-JT WRT OfficeJT-\u003e\u003eAdminLAN: Routed Office-JT Access when Allowed end rect rgb(255, 248, 230) Note over Portable,OtherPeers: 其他 WRT Peers 默认是 Peer-level Admin Targets Portable-\u003e\u003eOtherPeers: Ping / SSH / Peer Health Checks OtherPeers--\u003e\u003ePortable: Peer-level Response end sequenceDiagram participant Portable as Portable Devices (Admin)Mobile Devices / MacBook participant NetBird as NetBird ACL / Registry participant HomeWRT as Homelab WRT 10.1.1.254 participant OfficeJT as Office-JT WRTAdmin Full Routes participant OtherPeers as Hometown / Office-SQ / DC-101 WRT Peers participant AdminLAN as Permitted Admin LAN Routes rect rgb(245, 248, 255) Note over Portable,NetBird: 原生 NetBird Peer，先受 ACL 约束 Portable-\u003e\u003eNetBird: Authenticate Peer NetBird--\u003e\u003ePortable: Allowed Peers and Routes end rect rgb(240, 250, 244) Note over Portable,AdminLAN: 常驻 Admin Peers 拥有完整 Routes Portable-\u003e\u003eHomeWRT: P2P Access to Homelab WRT HomeWRT-\u003e\u003eAdminLAN: Routed Homelab Access when Allowed Portable-\u003e\u003eOfficeJT: P2P Access to Office-JT WRT OfficeJT-\u003e\u003eAdminLAN: Routed Office-JT Access when Allowed end rect rgb(255, 248, 230) Note over Portable,OtherPeers: 其他 WRT Peers 默认是 Peer-level Admin Targets Portable-\u003e\u003eOtherPeers: Ping / SSH / Peer Health Checks OtherPeers--\u003e\u003ePortable: Peer-level Response end sequenceDiagram participant Portable as Portable Devices (Admin)Mobile Devices / MacBook participant NetBird as NetBird ACL / Registry participant HomeWRT as Homelab WRT 10.1.1.254 participant OfficeJT as Office-JT WRTAdmin Full Routes participant OtherPeers as Hometown / Office-SQ / DC-101 WRT Peers participant AdminLAN as Permitted Admin LAN Routes rect rgb(245, 248, 255) Note over Portable,NetBird: 原生 NetBird Peer，先受 ACL 约束 Portable-\u003e\u003eNetBird: Authenticate Peer NetBird--\u003e\u003ePortable: Allowed Peers and Routes end rect rgb(240, 250, 244) Note over Portable,AdminLAN: 常驻 Admin Peers 拥有完整 Routes Portable-\u003e\u003eHomeWRT: P2P Ac","date":"2026-05-29","objectID":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/:0:5","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络","uri":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/#原生-netbird-peer-路径"},{"categories":null,"collections":null,"content":"proxy-netbird DHCP 路径 第二种路径，是 Homelab 内部客户端本身不作为 NetBird Peer，而是被 RouterOS 放进 proxy-netbird DHCP Option-set。 这类客户端仍然使用代理 VIP 10.1.1.253 做默认网关和 DNS；只有 NetBird / Site CIDR 通过 DHCP 121/249 指向 WRT 10.1.1.254。 sequenceDiagram participant RouterOS as Homelab RouterOS 10.1.1.1 participant Client as proxy-netbird LAN Clients participant HomeWRT as Homelab WRT 10.1.1.254 participant NetBird as NetBird Route Table participant SiteWRT as Permitted Site WRT Peer participant SiteLAN as Permitted Site LAN rect rgb(240, 250, 244) Note over RouterOS,Client: Homelab 内部 Route Awareness RouterOS-\u003e\u003eHomeWRT: Read NetBird Route Table RouterOS--\u003e\u003eClient: DHCP 121/249 Site Routes -\u003e 10.1.1.254 Client-\u003e\u003eHomeWRT: Site CIDR Traffic via 10.1.1.254 HomeWRT-\u003e\u003eSiteWRT: NetBird Site Route SiteWRT-\u003e\u003eSiteLAN: Routed or NATed Site Access end rect rgb(255, 248, 230) Note over SiteWRT,Client: ACL 不是唯一问题，回程也要成立 SiteLAN--\u003e\u003eSiteWRT: Return Traffic SiteWRT--\u003e\u003eHomeWRT: Return Path through Overlay or Local SNAT HomeWRT--\u003e\u003eClient: Response end sequenceDiagram participant RouterOS as Homelab RouterOS 10.1.1.1 participant Client as proxy-netbird LAN Clients participant HomeWRT as Homelab WRT 10.1.1.254 participant NetBird as NetBird Route Table participant SiteWRT as Permitted Site WRT Peer participant SiteLAN as Permitted Site LAN rect rgb(240, 250, 244) Note over RouterOS,Client: Homelab 内部 Route Awareness RouterOS-\u003e\u003eHomeWRT: Read NetBird Route Table RouterOS--\u003e\u003eClient: DHCP 121/249 Site Routes -\u003e 10.1.1.254 Client-\u003e\u003eHomeWRT: Site CIDR Traffic via 10.1.1.254 HomeWRT-\u003e\u003eSiteWRT: NetBird Site Route SiteWRT-\u003e\u003eSiteLAN: Routed or NATed Site Access end rect rgb(255, 248, 230) Note over SiteWRT,Client: ACL 不是唯一问题，回程也要成立 SiteLAN--\u003e\u003eSiteWRT: Return Traffic SiteWRT--\u003e\u003eHomeWRT: Return Path through Overlay or Local SNAT HomeWRT--\u003e\u003eClient: Response end sequenceDiagram participant RouterOS as Homelab RouterOS 10.1.1.1 participant Client as proxy-netbird LAN Clients participant HomeWRT as Homelab WRT 10.1.1.254 participant NetBird as NetBird Route Table participant SiteWRT as Permitted Site WRT Peer participant SiteLAN as Permitted Site LAN rect rgb(240, 250, 244) Note over RouterOS,Client: Homelab 内部 Route Awareness RouterOS-\u003e\u003eHomeWRT: Read NetBird Route Table RouterOS--\u003e\u003eClient: DHCP 121/249 Site Routes -\u003e 10.1.1.254 Client-\u003e\u003eHomeWRT: Site CIDR Traffic via 10.1.1.254 HomeWRT-\u003e\u003eSiteWRT: NetBird Site Route SiteWRT-\u003e\u003eSiteLAN: Routed or NATed Site Access end rect rgb(255, 248, 230) Note over SiteWRT,Client: ACL 不是唯一问题，回程也要成立 SiteLAN--\u003e\u003eSiteWRT: Return Traffic SiteWRT--\u003e\u003eHomeWRT: Return Path through Overlay or Local SNAT HomeWRT--\u003e\u003eClient: Response end sequenceDiagram participant RouterOS as Homelab RouterOS 10.1.1.1 participant Client as proxy-netbird LAN Clients participant HomeWRT as Homelab WRT 10.1.1.254 participant NetBird as NetBird Route Table participant SiteWRT as Permitted Site WRT Peer participant SiteLAN as Permitted Site LAN rect rgb(240, 250, 244) Note over RouterOS,Client: Homelab 内部 Route Awareness RouterOS-\u003e\u003eHomeWRT: Read NetBird Route Table RouterOS--\u003e\u003eClient: DHCP 121/249 Site Routes -\u003e 10.1.1.254 Client-\u003e\u003eHomeWRT: Site CIDR Traffic via 10.1.1.254 HomeWRT-\u003e\u003eSiteWRT: NetBird Site Route SiteWRT-\u003e\u003eSiteLAN: Routed or NATed Site Access end rect rgb(255, 248, 230) Note over SiteWRT,Client: ACL 不是唯一问题，回程也要成立 SiteLAN--\u003e\u003eSiteWRT: Return Traffic SiteWRT--\u003e\u003eHomeWRT: Return Path through Overlay or Local SNAT HomeWRT--\u003e\u003eClient: Response end 这里有三个边界。 第一，Portable Devices (Admin) 的权限由 NetBird ACL 控制。Mobile Devices / MacBook 能不能访问某个 Peer、某条 Route，不靠“连上 VPN 以后全放开”，而是由 ACL 明确表达。 第二，Homelab 内部客户端的站点路由由 RouterOS DHCP 下发，但下一跳是 WRT 10.1.1.254。RouterOS 是控制点，不是 Overlay Data Plane。 第三，远端站点不是只要 ACL 允许就一定能通。站点 LAN 的回程路由、SNAT、NetBird Route 发布都要成立，否则就会出现“请求到了，对方回不来”的问题。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/:0:6","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络","uri":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/#proxy-netbird-dhcp-路径"},{"categories":null,"collections":null,"content":"ACL 解决的不是所有路由问题 NetBird ACL 很容易被误解成“只要 ACL 放行，就应该通”。 实际不是这样。 ACL 解决的是访问边界： Mobile Devices 是否可以访问 Homelab WRT MacBook 是否可以访问 Office-JT 的管理入口 Portable Devices (Admin) 是否可以访问某个 Site Route WRT Peers 之间是否允许互通 但 ACL 不负责这些事情： 某个 LAN 主机有没有回程路由 远端 RouterOS 是否知道 NetBird 源地址怎么回 WRT 是否需要对进入 LAN 的 Overlay 流量做 SNAT Homelab 内部静态主机是否自己持有 Site Routes 我遇到过的典型问题就是回程不对称：请求从 Homelab 侧通过 NetBird 到了 Office-JT LAN，但 Office-JT LAN 主机不知道怎么把回包稳定送回 NetBird Peer。 这类问题最后不是靠“再放宽 ACL”解决，而是靠路由和 NAT 边界解决： 首选在 Office-JT WRT 上对 NetBird 进入 LAN 的流量做窄范围 SNAT 避免优先改 Production Gateway RouterOS 侧兜底规则只作为辅助，不作为首选方案 对静态 Homelab 主机，目标模型是它们自己持有 Site Routes，下一跳指向 10.1.1.254 这也是为什么我把 WRT 保留下来。WRT 这层能做 NetBird Peer、Nftables、SNAT、Route Table 观测和脚本修正，而不需要把这些快变化逻辑都塞进主网关。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/:0:7","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络","uri":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/#acl-解决的不是所有路由问题"},{"categories":null,"collections":null,"content":"Homelab 内部为什么还要 Route Sync Mobile Devices / MacBook 作为 Portable Devices (Admin) 时，NetBird 客户端自己知道 Overlay 和允许的 Route。 但 Homelab 内部的 proxy-netbird Clients 不一定跑 NetBird 客户端。它们只是通过 DHCP 被归到一个策略组里。 所以 Homelab 这里有一个 Route Sync： WRT 维护 NetBird Route Table RouterOS 每 10 分钟读取 WRT 上的 NetBird Routes RouterOS 只接受私有网段 Route，并过滤掉 Homelab 自己的 LAN RouterOS 生成 DHCP Option 121/249 proxy-netbird Option-set 组合 proxy-gw、proxy-dns、netbird-route-121、netbird-route-249 这样，Homelab 内部客户端不需要理解 NetBird，它只需要从 DHCP 拿到“这些站点网段走 10.1.1.254”。 这个设计的好处是边界清楚： RouterOS 负责 DHCP 和策略分组 WRT 负责 NetBird Route Table 和 Overlay Data Plane 客户端只根据 DHCP 决定下一跳 Route Sync 失败时，不应该影响普通客户端 这里也故意没有把普通 proxy Option-set 变成带 NetBird Routes 的全集。普通 Proxy 客户端只拿 VIP 网关和 DNS。只有需要跨站路由的设备，才进入 proxy-netbird。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/:0:8","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络","uri":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/#homelab-内部为什么还要-route-sync"},{"categories":null,"collections":null,"content":"NetBird 和 Backup Path 的边界 NetBird 是日常 Admin Overlay，但我没有把其他路径删掉。 原因很简单：Overlay 出问题时，最需要的是第二条入口，而不是现场开始研究 ACL。 现在边界大概是： 路径 定位 NetBird 日常 Admin Overlay，Mobile Devices / MacBook 的主要管理入口 ZeroTier 保留 P2P 能力，不作为主要 Network Route Sing-box Inbound Homelab / Office-JT 的备用入口，由 WRT 承载 这三者不应该混成一个东西。 NetBird 负责平时的 Peer Registry、ACL 和受控站点路由。ZeroTier 和 Sing-box Inbound 更像故障时还能进去的 Backup Path。下一篇会单独讲为什么 Backup Path 仍然值得保留。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/:0:9","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络","uri":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/#netbird-和-backup-path-的边界"},{"categories":null,"collections":null,"content":"验证 这类设计要验证的不是“NetBird 显示在线”。 我会分几层看： Mobile Devices / MacBook 是否作为 Portable Devices (Admin) 在线 ACL 是否只允许预期的 Peer 和 Site Routes Homelab WRT 是否能看到 NetBird Route Table RouterOS 是否能定时刷新 DHCP 121/249 proxy-netbird 客户端是否拿到 Site Routes，下一跳是否是 10.1.1.254 Office / Hometown / DC-101 的站点回程是否成立 静态 Homelab 主机是否没有偷偷依赖临时 ACL Workaround 最后一条尤其重要。临时放行和 Emergency Workaround 很容易变成永久设计。我的目标模型还是：静态主机自己持有必要的 Site Routes，站点 CIDR 指向 10.1.1.254，而不是靠一堆特殊 ACL 去修每一条 TCP 流。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/:0:10","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络","uri":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/#验证"},{"categories":null,"collections":null,"content":"最后的结论 NetBird 在这套 Homelab 网络里，是 Admin Overlay，不是默认网关，也不是普通代理路径。 Mobile Devices / MacBook 是 Portable Devices (Admin)，用 ACL 访问被允许的 Homelab / Hometown / Office / DC-101 Peer 和 Route。 WRT Peers 是站点边界上的 Subnet Router 和管理 Sidecar，负责把 NetBird Overlay 接到受控 LAN。 RouterOS 仍然做主网关和 DHCP 控制点，通过 Route Sync 把需要的 Site Routes 下发给 proxy-netbird 客户端，但不直接承载 Overlay Data Plane。 这套设计真正解决的，不是“能不能连上”，而是把访问权限、站点路由、回程路径和 Backup Path 分开。边界清楚之后，排障时才知道该看 ACL、WRT Route、RouterOS DHCP，还是远端 LAN 的回程。 ","date":"2026-05-29","objectID":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/:0:11","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络","uri":"/2026/05/29/homelab-netbird-acl-mobile-macbook-access/#最后的结论"},{"categories":null,"collections":null,"content":"拆解透明代理 Proxy VIP、VRRP 接管和 Fallback DNS 的实现取舍：WRT 健康时承载策略路径，故障时回到 RouterOS 普通出口。","date":"2026-05-29","objectID":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS","uri":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/"},{"categories":null,"collections":null,"content":"系列导航 Homelab 网络系列：开篇 - 家庭网络为什么会变复杂 Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工 Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络 Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着 Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚 ","date":"2026-05-29","objectID":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/:0:1","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS","uri":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/#系列导航"},{"categories":null,"collections":null,"content":"背景 上一篇讲 RouterOS 和 WRT 为什么要分工：RouterOS 是主网关，负责稳定底座和日常主要访问；WRT 是额外策略层，负责海外访问分流、Sing-box、NetBird Peer 和一些 Backup Path。 这篇继续拆 WRT 这层里最容易出问题的一块：透明代理 VIP、VRRP 和 Fallback DNS。 我想解决的问题不是“所有设备都强制走代理”，而是： 普通设备继续走 RouterOS，不受 WRT 策略层影响 需要海外访问分流的设备，通过 DHCP 进入代理策略组 代理策略组看到的是稳定的网关和 DNS WRT 上的 Sing-box 挂了之后，代理设备至少不要完全断网 Fallback DNS 能兜普通解析，但不要变成公网服务入口 Rewrite 中心 所以最后就变成了一个代理 VIP：客户端只认这个 VIP，背后由 WRT 或 RouterOS 根据健康状态接管。 ","date":"2026-05-29","objectID":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/:0:2","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS","uri":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/#背景"},{"categories":null,"collections":null,"content":"为什么需要一个 VIP 最直接的方案，是让需要代理的设备把默认网关和 DNS 都指向 WRT。 这个方案短期很简单，但问题也很直接：一旦 WRT 或 Sing-box 有问题，客户端拿到的网关和 DNS 就一起失效。对手机、平板、电视这类设备来说，这种故障通常很难现场解释，也很难要求每台设备自己切回普通网络。 所以我没有让客户端直接绑定 WRT 的真实地址，而是让 DHCP 下发一个代理 VIP： 普通客户端：默认网关是 10.1.1.1，DNS 是 10.1.1.100 代理客户端：默认网关和 DNS 都指向代理 VIP 10.1.1.253 WRT 健康时：WRT 10.1.1.254 持有 VIP，后面接 Sing-box DNS / TUN / Route Policy，DNS Backend 是 10.1.1.254:53 WRT 基础健康失败时：RouterOS 10.1.1.1 接管 VIP，提供普通 LAN/WAN Fallback 这样客户端配置是稳定的，故障切换发生在网关侧。 这里的重点不是“无感高可用”，而是把故障结果从“完全不可用”降级成“只失去代理策略”。 ","date":"2026-05-29","objectID":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/:0:3","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS","uri":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/#为什么需要一个-vip"},{"categories":null,"collections":null,"content":"地址和路径先摊开 这套设计如果只讲“VIP”和“Fallback”，很容易听起来像抽象概念。实际地址关系是这样： 场景 客户端网关 客户端 DNS VIP 持有者 DNS 后端 普通客户端 10.1.1.1 10.1.1.100 不经过代理 VIP AdGuardHome 10.1.1.100:53 代理健康 10.1.1.253 10.1.1.253 WRT 10.1.1.254 WRT Sing-box DNS 10.1.1.254:53 代理 Fallback 10.1.1.253 10.1.1.253 RouterOS 10.1.1.1 RouterOS Firewall Redirect 到 AdGuardHome 10.1.1.100:53 sequenceDiagram participant Client as Normal / Proxy Clients participant RouterOS as RouterOS 10.1.1.1 participant WRT as WRT 10.1.1.254 participant SingBox as Sing-box 10.1.1.254:53 participant ADG as AdGuardHome 10.1.1.100:53 participant WAN as WAN / Proxy Nodes rect rgb(245, 248, 255) Note over Client,ADG: 普通客户端路径 Client-\u003e\u003eRouterOS: GW 10.1.1.1 Client-\u003e\u003eADG: DNS 10.1.1.100 RouterOS-\u003e\u003eWAN: Ordinary WAN/NAT end rect rgb(240, 250, 244) Note over Client,WAN: 代理健康路径，VIP 10.1.1.253 在 WRT Client-\u003e\u003eWRT: GW/DNS 10.1.1.253 WRT-\u003e\u003eSingBox: Backend 10.1.1.254 SingBox-\u003e\u003eADG: dns-local SingBox-\u003e\u003eWAN: Direct or Proxy Egress end rect rgb(255, 248, 230) Note over WRT,RouterOS: WRT L1 健康检查失败 WRT--\u003e\u003eRouterOS: RouterOS Becomes VRRP MASTER for 10.1.1.253 Client-\u003e\u003eRouterOS: DNS to 10.1.1.253:53 RouterOS-\u003e\u003eADG: VRRP MASTER Hook Redirects to 10.1.1.100:53 ADG--\u003e\u003eClient: Ordinary/Local/Cache DNS ADG--\u003e\u003eClient: GFWList matched domains return REFUSED Client-\u003e\u003eRouterOS: Default Traffic via 10.1.1.253 RouterOS-\u003e\u003eWAN: Ordinary LAN/WAN Fallback end sequenceDiagram participant Client as Normal / Proxy Clients participant RouterOS as RouterOS 10.1.1.1 participant WRT as WRT 10.1.1.254 participant SingBox as Sing-box 10.1.1.254:53 participant ADG as AdGuardHome 10.1.1.100:53 participant WAN as WAN / Proxy Nodes rect rgb(245, 248, 255) Note over Client,ADG: 普通客户端路径 Client-\u003e\u003eRouterOS: GW 10.1.1.1 Client-\u003e\u003eADG: DNS 10.1.1.100 RouterOS-\u003e\u003eWAN: Ordinary WAN/NAT end rect rgb(240, 250, 244) Note over Client,WAN: 代理健康路径，VIP 10.1.1.253 在 WRT Client-\u003e\u003eWRT: GW/DNS 10.1.1.253 WRT-\u003e\u003eSingBox: Backend 10.1.1.254 SingBox-\u003e\u003eADG: dns-local SingBox-\u003e\u003eWAN: Direct or Proxy Egress end rect rgb(255, 248, 230) Note over WRT,RouterOS: WRT L1 健康检查失败 WRT--\u003e\u003eRouterOS: RouterOS Becomes VRRP MASTER for 10.1.1.253 Client-\u003e\u003eRouterOS: DNS to 10.1.1.253:53 RouterOS-\u003e\u003eADG: VRRP MASTER Hook Redirects to 10.1.1.100:53 ADG--\u003e\u003eClient: Ordinary/Local/Cache DNS ADG--\u003e\u003eClient: GFWList matched domains return REFUSED Client-\u003e\u003eRouterOS: Default Traffic via 10.1.1.253 RouterOS-\u003e\u003eWAN: Ordinary LAN/WAN Fallback end sequenceDiagram participant Client as Normal / Proxy Clients participant RouterOS as RouterOS 10.1.1.1 participant WRT as WRT 10.1.1.254 participant SingBox as Sing-box 10.1.1.254:53 participant ADG as AdGuardHome 10.1.1.100:53 participant WAN as WAN / Proxy Nodes rect rgb(245, 248, 255) Note over Client,ADG: 普通客户端路径 Client-\u003e\u003eRouterOS: GW 10.1.1.1 Client-\u003e\u003eADG: DNS 10.1.1.100 RouterOS-\u003e\u003eWAN: Ordinary WAN/NAT end rect rgb(240, 250, 244) Note over Client,WAN: 代理健康路径，VIP 10.1.1.253 在 WRT Client-\u003e\u003eWRT: GW/DNS 10.1.1.253 WRT-\u003e\u003eSingBox: Backend 10.1.1.254 SingBox-\u003e\u003eADG: dns-local SingBox-\u003e\u003eWAN: Direct or Proxy Egress end rect rgb(255, 248, 230) Note over WRT,RouterOS: WRT L1 健康检查失败 WRT--\u003e\u003eRouterOS: RouterOS Becomes VRRP MASTER for 10.1.1.253 Client-\u003e\u003eRouterOS: DNS to 10.1.1.253:53 RouterOS-\u003e\u003eADG: VRRP MASTER Hook Redirects to 10.1.1.100:53 ADG--\u003e\u003eClient: Ordinary/Local/Cache DNS ADG--\u003e\u003eClient: GFWList matched domains return REFUSED Client-\u003e\u003eRouterOS: Default Traffic via 10.1.1.253 RouterOS-\u003e\u003eWAN: Ordinary LAN/WAN Fallback end sequenceDiagram participant Client as Normal / Proxy Clients participant RouterOS as RouterOS 10.1.1.1 participant WRT as WRT 10.1.1.254 participant SingBox as Sing-box 10.1.1.254:53 participant ADG as AdGuardHome 10.1.1.100:53 participant WAN as WAN / Proxy Nodes rect rgb(245, 248, 255) Note over Client,ADG: 普通客户端路径 Client-\u003e\u003eRouterOS: GW 10.1.1.1 Client-\u003e\u003eADG: DNS 10.1.1.100 RouterOS-\u003e\u003eWAN: Ordinary WAN/NAT end rect rgb(240, 250, 244) Note over Client,WAN: 代理健康路径，VIP 10.1.1.253 在 WRT Client-\u003e\u003eWRT: GW/DNS 10.1.1.253 WRT-\u003e\u003eSingBox: Backend 10.1.1.254 SingB","date":"2026-05-29","objectID":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/:0:4","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS","uri":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/#地址和路径先摊开"},{"categories":null,"collections":null,"content":"VRRP 负责谁持有 VIP VIP 的归属用 VRRP 做。 健康状态正常时，WRT 是 MASTER。代理客户端发到 VIP 的 DNS 和默认路由流量，都会进入 WRT。WRT 上的 Sing-box 再根据规则决定直连、代理、DNS 策略和 TUN 路由。 RouterOS 则保持 BACKUP。它不是日常代理路径，只是在 WRT 基础能力失败时接管 VIP。 这个边界很重要： WRT 负责完整策略能力 RouterOS 负责 Fallback 能力 VRRP 只决定 VIP 属于谁 客户端不需要知道当前是谁在接管 也就是说，VRRP 不是为了让 RouterOS 也实现一份完整代理能力。RouterOS 接管时，它提供的是普通网络兜底，不是 Sing-box 的替代品。 实现上，RouterOS 成为 10.1.1.253 的 MASTER 后，会进入对应的 VRRP 接管逻辑。这里的 Fallback DNS 动作就是 Firewall Redirect：把目的地址仍然写着 10.1.1.253:53 的请求转给 10.1.1.100:53。客户端仍然只知道 VIP，不需要知道背后已经从 WRT 切到了 RouterOS + AdGuardHome。 ","date":"2026-05-29","objectID":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/:0:5","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS","uri":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/#vrrp-负责谁持有-vip"},{"categories":null,"collections":null,"content":"L1 健康检查决定是否切走 WRT 什么时候应该交出 VIP？我的判断标准是 L1 基础能力失败。 这里的 L1 不是“海外网络是否好用”，而是 WRT 作为代理网关还是否具备基本服务能力： Sing-box 进程还在不在 Sing-box 的 DNS 配置是否符合代理路径预期 本地或国内 DNS 探测是否可用 TUN 和转发规则是否存在 必要时再加国内 HTTP 探测 这些检查失败，说明 WRT 已经不适合作为客户端的网关和 DNS。此时让 RouterOS 接管 VIP 是合理的，因为至少能把客户端带回普通网络。 这个设计也避免了一个常见误区：不要因为“海外探测失败”就立刻切 VIP。 ","date":"2026-05-29","objectID":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/:0:6","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS","uri":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/#l1-健康检查决定是否切走"},{"categories":null,"collections":null,"content":"L2 海外退化为什么不切 VIP 海外访问失败和 WRT 基础能力失败不是一回事。 如果只是海外 DNS 或 HTTP 探测失败，但 Sing-box 进程、配置、本地 DNS、TUN、转发规则都还正常，那么 WRT 仍然应该持有 VIP。 原因很简单：切回 RouterOS 并不能修好海外访问。 RouterOS Fallback 提供的是普通 LAN/WAN 出口。它没有完整的 Sing-box 选择器、远端 DNS 策略和海外分流能力。海外路径本身退化时，把 VIP 切走只会让客户端立刻失去策略层，反而扩大影响。 所以我把海外探测放在 L2： L2 失败只记录状态 L2 失败不改变 VRRP 退出码 L2 慢探测不能卡住 VRRP 主循环 L2 恢复后再把状态写回 Healthy 这会带来一个看起来不够“自动化”的结果：海外不可用时，VIP 仍然可能留在 WRT。 但这是有意为之。L2 是观测信号，不是接管信号。 ","date":"2026-05-29","objectID":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/:0:7","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS","uri":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/#l2-海外退化为什么不切-vip"},{"categories":null,"collections":null,"content":"Fallback DNS 能兜什么 RouterOS 接管 VIP 后，需要处理一个现实问题：代理客户端的 DNS 仍然指向 VIP。 如果 RouterOS 只是接管了 VIP，却没有处理 DNS，那么客户端会从“网关不可用”变成“DNS 不可用”，体验还是断的。 所以 RouterOS 上保留一条 Fallback DNS Redirect：当它成为 VIP MASTER 时，通过 Firewall Redirect 把发往 10.1.1.253:53 的 DNS 请求转给本地 DNS 服务。 这个本地 DNS 服务不是 RouterOS 自己跑的递归解析，而是 PVE Host 上 Docker 里的 AdGuardHome。RouterOS 只负责在 Fallback 状态下把 DNS 流量转过去。 更准确地说，这个 AdGuardHome 平时也是 RouterOS 普通客户端的 Upstream DNS。普通客户端没有进代理策略组时，DNS 解析已经会走到这里；Fallback 只是让代理客户端在 WRT 失效后，也回到同一套本地 DNS 语义里。 这个设计有两个好处： 普通客户端和 Fallback 状态下的代理客户端，看到的本地别名和基础解析行为一致 LAN 内已经缓存过的解析结果可以继续复用，不会因为 VIP 接管就换一套 DNS 行为 这里的 Fallback DNS 不是一个“尽量帮你解析所有东西”的宽松 Resolver。它会主动用 Filter 对 GFWList 命中的域名做 Reject。 这个取舍是故意的：当代理路径已经失败时，我不希望 Fallback DNS 继续把明显需要代理策略的域名拿去普通 DNS 路径解析。那样虽然短期看起来更“可用”，但会泄露真实访问意图，也增加 DNS Leak 的可能。 所以 Fallback 状态下，某些本来应该走代理 DNS 的域名被拒绝是预期行为。它的目标是保住普通网络和本地解析，而不是在降级路径里继续假装完整代理策略还存在。 这条 Fallback 能兜的是： 普通域名解析 本地别名 和普通 RouterOS 客户端一致的 LAN 内 DNS Cache 国内访问需要的基础解析 WRT 重启或 Sing-box 挂掉时的临时网络恢复 它不能兜的是： 完整的 Sing-box DNS 分流 海外远端 DNS 策略 GFWList 命中域名的普通 DNS 解析 代理选择器 特定代理规则带来的访问偏好 所以 Fallback DNS 的目标不是“和正常代理路径等价”，而是“别让客户端因为 DNS 完全断掉”。 ","date":"2026-05-29","objectID":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/:0:8","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS","uri":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/#fallback-dns-能兜什么"},{"categories":null,"collections":null,"content":"DNS 不负责公网入口分流 这里还要强调一个边界：Fallback DNS 不是公网服务入口 Rewrite 层。 Homelab 里有些服务既要从外面访问，也要在 LAN 里用同一套公网视角访问。我不希望这些服务在 LAN 内靠 DNS 改写到内网地址。 原因上一篇已经讲过：DNS 只能按名字分流，但入口问题经常和端口、协议、鉴权、后端服务有关。 所以公网服务入口继续由 RouterOS Hairpin NAT 解决： WAN 访问走公网入口 DNAT LAN 访问同一公网入口走 Hairpin 后端回复路径由 RouterOS 保证回流 DNS 视角保持一致 WRT 的透明代理 DNS 和 RouterOS 的公网入口 Hairpin 是两条边界。混在一起，排障会很痛苦。 ","date":"2026-05-29","objectID":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/:0:9","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS","uri":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/#dns-不负责公网入口分流"},{"categories":null,"collections":null,"content":"验证 这类设计不能只看配置，要看故障切换。 我比较关心几种状态： 正常状态下，代理 VIP 在 WRT 上，代理客户端通过 WRT 走 Sing-box 停掉 Sing-box 后，WRT 释放 VIP，RouterOS 接管 RouterOS 接管后，VRRP MASTER Hook/Firewall Redirect 把 VIP DNS 转到 10.1.1.100:53 RouterOS 接管后，代理客户端至少能获得普通 DNS 和普通出口 Sing-box 恢复并通过 L1 检查后，WRT 重新接管 VIP 海外 L2 探测失败时，状态记录退化，但 VIP 不应该因为这个单独切走 这里最容易误判的是“探测慢”和“探测失败”。 VRRP 的健康检查必须短、硬、可预期。慢探测应该异步化，否则会把 Keepalived 的 Track Script 卡住，最后造成不必要的主备抖动。 ","date":"2026-05-29","objectID":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/:0:10","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS","uri":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/#验证"},{"categories":null,"collections":null,"content":"最后的结论 透明代理 VIP 解决的是客户端稳定入口问题。 VRRP 解决的是 WRT 和 RouterOS 谁来持有这个入口。 L1 健康检查决定是否真的需要切走。 L2 海外探测只提供退化状态，不直接触发接管。 Fallback DNS 解决的是降级时的基础可用性，不是完整代理能力，也不是公网服务入口分流。它在 RouterOS 成为 VRRP MASTER 后，通过 Firewall Redirect 把 10.1.1.253:53 转到 PVE Host Docker 上的 AdGuardHome 10.1.1.100:53；这个 AdGuardHome 同时也是普通 RouterOS 客户端的 Upstream DNS，所以 Fallback 后仍然复用同一套本地解析和 LAN Cache。它也会主动 Reject GFWList 命中域名，避免在降级路径里泄露真实访问意图。 这套设计的目标不是把代理路径做成完美 HA，而是让 WRT 这层额外能力失败时，损失范围保持清楚：普通网络还能走，代理策略可以降级，排障时知道问题卡在哪一层。 ","date":"2026-05-29","objectID":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/:0:11","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS","uri":"/2026/05/29/%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86-vipvrrp-%E5%92%8C-Fallback-dns/#最后的结论"},{"categories":null,"collections":null,"content":"解释 RouterOS 主网关和 WRT 旁路由的职责分界：主网关兜底日常访问，WRT 承载透明代理、Admin Overlay 和 Backup Path。","date":"2026-05-29","objectID":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工","uri":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/"},{"categories":null,"collections":null,"content":"系列导航 Homelab 网络系列：开篇 - 家庭网络为什么会变复杂 Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工 Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络 Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着 Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚 ","date":"2026-05-29","objectID":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/:0:1","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工","uri":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/#系列导航"},{"categories":null,"collections":null,"content":"背景 上一篇说到，Homelab 网络最后变复杂，不是因为一开始想把事情做复杂，而是需求慢慢超过了普通家庭路由器能舒服承载的范围。 这一篇只讲其中一个拆分：为什么我最后让 RouterOS 做主网关，让 WRT 做旁路由，而不是把所有东西都塞到其中一边。 现在这套网络里，RouterOS 和 WRT 的分工大概是这样： RouterOS 负责主网关、DHCP、NAT、WAN/LAN 边界、公网入口 Hairpin、主要国内访问兜底 WRT 负责海外访问分流、Sing-box、NetBird Peer、透明代理 VIP、部分跨站路由 普通设备默认只依赖 RouterOS 需要策略能力的设备，才通过 DHCP Option-set 走到 WRT 这层 这个拆分看起来多了一台设备和一堆联动，但核心目标其实很朴素：日常主要网络要稳，工作、管理和个人海外访问偏好可以作为额外层存在。 ","date":"2026-05-29","objectID":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/:0:2","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工","uri":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/#背景"},{"categories":null,"collections":null,"content":"全塞到 WRT 的阶段 最早我用 OpenWrt / ImmortalWrt 承载过几乎所有东西。 它可以拨号，可以 NAT，可以跑 DNS，可以跑代理，也可以跑各种 Overlay Peer。对个人网络来说，这种方案的吸引力很强： 配置入口集中 软件生态足够丰富 调整代理、DNS、VPN 都很方便 机器少，拓扑也短 如果只是一个人用，或者只是做一个很轻量的家庭旁路由，这样完全可以。 但 Homelab 一旦承载了更多基础服务，它的问题就开始明显了。WRT 上的能力太“活”了：代理订阅会更新，Sing-box 会升级，NetBird 会变更 Peer 和 Route，DNS 策略也会经常跟着业务调。 这些东西本身都不是问题。真正的问题是，它们不应该和“全家正常上网”绑在同一个故障域里。 比如： 代理配置生成错了，不应该影响普通设备上网 Overlay Route 调试错了，不应该影响默认出口 DNS 策略变更，不应该把公网服务入口一起改坏 WRT 升级或重启，不应该让主网关也跟着失效 所以全塞到 WRT 的方案，后面最大的问题不是性能，而是职责太混。 ","date":"2026-05-29","objectID":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/:0:3","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工","uri":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/#全塞到-wrt-的阶段"},{"categories":null,"collections":null,"content":"为什么需要 WRT 这层额外能力 另一个方向也很自然：既然 RouterOS 已经是主网关，那能不能把所有东西都放在 RouterOS 上？ RouterOS 做路由、NAT、防火墙、DHCP 都很强，而且稳定。主网关已经掌握了所有流量入口，在它上面做规则，路径最短，排查也直观。 但我现在并不希望 RouterOS 变成一个“全能应用网关”。它在这套网络里的角色，是稳定主网关和主要国内访问兜底，而不是直接承载所有海外分流、Overlay 管理和代理策略。 WRT 这层额外能力解决的是另一类问题： Sing-box Gateway 配置、订阅生成和规则集会频繁变化 NetBird Peer 和站点路由属于 Admin Overlay，不应该污染普通默认出口 VRRP 和健康检查是为了让海外分流失败时可以降级，而不是让主网关一起失败 ZeroTier、Sing-box Inbound 这类 Backup Path 也更适合放在可替换的旁路层 日志、包管理、Nftables、脚本调试都更接近普通 Linux 习惯 这些能力更像应用层或系统层组件。它们需要包管理、文件模板、脚本、日志、版本升级和较快的回滚节奏。WRT 做这些事情明显更顺手。 更重要的是，WRT 这层的失败应该是有边界的。 最坏情况下，NetBird、ZeroTier、Sing-box、WRT 这层全部失效，受影响的应该是额外能力： Mobile Devices / MacBook 在外面的管理入口 跨站点 Overlay 访问 海外访问分流和个人偏好策略 依赖代理 VIP 的策略客户端 而不是所有普通设备的日常主要访问。 RouterOS 更适合做边界和控制面： 谁是默认网关 哪些客户端属于哪个 DHCP 策略组 公网入口的 DNAT / Hairpin 怎么走 Fallback 时要不要让代理 VIP 回到普通 LAN/WAN 出口 哪些 RouterOS 脚本是稳定、可审计、可回滚的 换句话说，RouterOS 适合回答“基础网络还能不能正常工作”，WRT 适合承载“哪些设备需要额外策略能力”。这不是 RouterOS 做不了，而是我不希望快变化的海外分流和 Overlay 管理，变成主网关的核心风险。 ","date":"2026-05-29","objectID":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/:0:4","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工","uri":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/#为什么需要-wrt-这层额外能力"},{"categories":null,"collections":null,"content":"当前分工 现在 Homelab 的分工是把基础网络和策略网络拆开。 普通设备走 RouterOS： DHCP 拿到普通默认网关 10.1.1.1 DNS 使用普通 LAN 策略，Upstream 是 10.1.1.100 上的 AdGuardHome 出口 NAT 和防火墙都在 RouterOS 上完成 日常主要国内访问由 RouterOS 兜底 WRT 故障不会直接影响这类设备 需要透明代理的设备走 WRT： DHCP Option-set 下发代理 VIP 10.1.1.253 作为默认网关和 DNS VIP 正常由 WRT 10.1.1.254 持有 WRT 后面是 Sing-box DNS / TUN / Route Policy，DNS Backend 是 10.1.1.254:53 只有被归入这个策略组的设备才进入这条路径 需要跨站访问的设备再多一层： 默认网关和 DNS 仍然走代理 VIP NetBird / Site Route 通过 DHCP Classless Route 下发 特定远端网段直接指向 WRT，而不是让 RouterOS 假装自己理解 Overlay 内部状态 这里的关键不是“所有设备都走代理”，而是不同设备进入不同策略组。RouterOS 负责分组和下发，WRT 负责执行变化更快的策略。 ","date":"2026-05-29","objectID":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/:0:5","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工","uri":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/#当前分工"},{"categories":null,"collections":null,"content":"VIP 和 Fallback 是这条边界的接口 RouterOS 和 WRT 的交界点，是一个代理 VIP。 正常情况下，WRT 10.1.1.254 持有 10.1.1.253 这个 VIP。代理客户端看到的是一个稳定的网关和 DNS 地址，背后实际由 WRT 上的 Sing-box 接住；也就是客户端目标是 10.1.1.253，健康 Backend 是 10.1.1.254。 当 WRT 的基础健康检查失败时，VIP 可以回到 RouterOS 10.1.1.1。这个 Fallback 并不等价于完整的代理能力，它只是保留一个普通 LAN/WAN 出口，让客户端不至于因为 WRT 故障完全断网。DNS 这部分会被 RouterOS 的 Firewall Redirect 转到 10.1.1.100 上的 AdGuardHome，因此 Fallback 后仍然和普通客户端共用同一套 LAN DNS 语义和 Cache。 这里有一个取舍：Fallback 不是为了让所有能力无感恢复，而是为了让故障影响范围变小。 我更关心的是： Sing-box 挂了，代理客户端至少还能普通出网 WRT 重启时，普通客户端不受影响 NetBird / ZeroTier 出问题时，只影响管理和 Backup Path Fallback DNS 能回到本地解析器，但不承担公网服务入口改写 VIP 的拥有权切换能通过健康检查验证，而不是靠人工记忆 后面会单独写 VIP、VRRP 和 Fallback DNS。这里先把它当成 RouterOS / WRT 分工之间的接口来看。 ","date":"2026-05-29","objectID":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/:0:6","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工","uri":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/#vip-和-fallback-是这条边界的接口"},{"categories":null,"collections":null,"content":"公网入口为什么仍然归 RouterOS 这个拆分里还有一个容易混的点：公网入口不在 WRT 的透明代理层里解决。 Homelab 有一些服务需要从外面访问，也需要在 LAN 内用同一套公网视角访问。这里我没有把它做成“内网 DNS 改写到内网地址”，而是让 RouterOS 继续负责公网入口的 DNAT 和 LAN Hairpin。 原因是 DNS 只认识名字，但入口问题不只看名字。 同一个域名可能有不同端口，不同端口可能落到不同后端，有的走 HTTP(S) 入口，有的不是 HTTP(S)。把这些都交给 DNS Rewrite，会把问题压扁成“名字到地址”的映射，后面很难维护。 RouterOS 在这里更合适： WAN 访问走公网入口 DNAT LAN 内访问同一公网入口时走 Hairpin 后端回复路径由 Hairpin SNAT 保证回到 RouterOS DNS 视角保持一致，不需要为了 LAN 访问维护另一份公网服务 Rewrite 所以 WRT 可以负责透明代理 DNS，但公网服务入口仍然应该留在 RouterOS 的边界 NAT 里。 ","date":"2026-05-29","objectID":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/:0:7","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工","uri":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/#公网入口为什么仍然归-routeros"},{"categories":null,"collections":null,"content":"被刻意留下来的复杂度 这个设计不是无成本的。 它留下了几类复杂度： DHCP Option-set 要维护普通、代理、跨站几类客户端 VIP 健康检查要足够严格，但不能因为慢探测频繁误切 NetBird Route 需要和 DHCP Classless Route 同步 RouterOS 和 WRT 都要保留各自的回滚路径 文档里必须明确哪些能力属于主网关，哪些属于旁路 这些复杂度不适合隐藏。隐藏之后，下一次排障时还是会回来。 我更倾向于把它们变成明确的边界： RouterOS 是稳定边界 WRT 是策略执行层 PVE 是承载层 DNS 不负责公网入口分流 NetBird 是 Admin Overlay，不是普通客户端的默认出口 边界清楚之后，即使组件多，排障时也知道先问哪个问题。 ","date":"2026-05-29","objectID":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/:0:8","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工","uri":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/#被刻意留下来的复杂度"},{"categories":null,"collections":null,"content":"最后的结论 RouterOS 和 WRT 分工的核心，不是“哪个系统更强”，而是把不同变化速度的东西放在不同位置。 RouterOS 负责慢变化的网络底座：主网关、NAT、DHCP、Hairpin、公网入口和可审计脚本。 WRT 负责快变化的策略能力：Sing-box、NetBird、透明代理、健康检查和备用路径。 这样做不会让 Homelab 网络变简单，但它能让故障域更清楚。主网关保持稳定，旁路能力可以升级、重启、替换；当旁路失败时，最多降级成普通网络，而不是把整个家庭网络一起带走。 后面继续拆透明代理 VIP、VRRP 和 Fallback DNS。那一层才是真正把“旁路可以失败，但不要把客户端完全断网”落到实现里的部分。 ","date":"2026-05-29","objectID":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/:0:9","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工","uri":"/2026/05/29/routeros-%E4%B8%BB%E7%BD%91%E5%85%B3%E5%92%8C-wrt-%E6%97%81%E8%B7%AF%E7%94%B1%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%88%86%E5%B7%A5/#最后的结论"},{"categories":null,"collections":null,"content":"从 Homelab 早期 OpenWrt 单点承载开始，拆解为什么家庭网络会逐步分成 RouterOS、WRT、NetBird、Fallback DNS 和 Backup Path 几层。","date":"2026-05-29","objectID":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：开篇 - 家庭网络为什么会变复杂","uri":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/"},{"categories":null,"collections":null,"content":"系列导航 Homelab 网络系列：开篇 - 家庭网络为什么会变复杂 Homelab 网络系列：RouterOS 主网关和 WRT 旁路由为什么要分工 Homelab 网络系列：透明代理 VIP、VRRP 和 Fallback DNS Homelab 网络系列：NetBird ACL：Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络 Homelab 网络系列：Backup Path：ZeroTier P2P 和 Sing-box Inbound 为什么还留着 Homelab 网络系列：自动化和可恢复性：订阅生成、健康检查、配置同步、回滚 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/:0:1","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：开篇 - 家庭网络为什么会变复杂","uri":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/#系列导航"},{"categories":null,"collections":null,"content":"背景 很长一段时间里，我对“家庭网络”的理解都非常朴素： 光猫拨号 主路由 NAT 交换机接内网设备 需要出门访问的时候，开一个 VPN 如果只是手机、电脑、电视、NAS，这个模型其实很好用。问题在于 Homelab 这个东西一旦开始长出来，它就不再只是“家里的网络”。 我现在遇到的问题大概有这么几类： 家里有需要长期运行的服务，有些只给自己用，有些需要从外面访问 Mobile Devices / MacBook 需要在外面访问 Homelab，也需要访问 Hometown / Office-JT / Office-SQ / DC-101 有些设备希望透明代理，有些设备只需要普通直连，有些设备还需要跨站路由 入口访问、DNS、证书、鉴权、转发路径不能互相打架 网络挂了之后，人不一定在现场，所以 Fallback 和回滚路径必须提前设计 所以最后就变成了一个看起来有点夸张的组合： RouterOS CHR 做主网关和边界 NAT ImmortalWrt 做旁路能力承载，比如 Sing-box、NetBird、部分透明代理路径 PVE 承载 RouterOS / WRT / DNS / 入口服务等基础组件 NetBird 作为日常 Admin Overlay，让 Mobile Devices / MacBook 能访问 Homelab / Hometown / Office 侧网络 ZeroTier 和 Sing-box Inbound 作为 Backup Path，而不是主路径 这不是一个“推荐大家都这样搞”的方案，更像是一套不断被现实问题推出来的网络形态。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/:0:2","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：开篇 - 家庭网络为什么会变复杂","uri":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/#背景"},{"categories":null,"collections":null,"content":"旧方案 最早的方案其实更像是“能跑就行”：直接让 OpenWrt / ImmortalWrt 承载所有服务。 它既是路由器，也是 DNS、透明代理、Overlay Peer、入口跳板，甚至还会顺手放一些脚本和小服务。这个阶段的优点很明显： 设备少 路径短 配置集中 出问题的时候基本只需要登录一台机器看 但用久之后，问题也很明显。路由器本来应该是一个稳定的网络底座，一旦上面叠了太多服务，任何一个服务重启、配置失误、依赖升级，都可能把基础网络一起带下去。 后来最容易想到的改法，是把所有东西都塞进主路由： 主路由拨号、NAT、DHCP、DNS 主路由上跑透明代理 主路由上开 VPN 主路由上做公网入口转发 如果网络规模小，这样确实省事。所有流量都经过一个设备，排查路径也短。 但我这里的问题是，主路由同时承担了“家里所有人正常上网”的职责。把实验性能力、代理策略、Overlay 节点、入口转发全部塞进去，风险会变得很集中。 典型的问题有几个： 代理组件挂了，不应该影响普通设备上网 DNS 策略变更，不应该把公网服务入口解析搞乱 Overlay 路由调试，不应该动到家庭网络的默认出口 入口服务调整，不应该依赖内网 DNS Rewrite 来绕过公网路径 人在外面时，管理路径不能只剩一条 也就是说，主路由应该稳定，旁路能力应该可替换、可降级、可重启。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/:0:3","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：开篇 - 家庭网络为什么会变复杂","uri":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/#旧方案"},{"categories":null,"collections":null,"content":"新方案 现在 Homelab 的核心思路是把职责拆开： 组件 职责 RouterOS CHR 主网关、DHCP、NAT、WAN/LAN 边界、公网入口 Hairpin ImmortalWrt Sing-box、NetBird、透明代理 VIP、部分跨站路由 PVE 承载网络 VM/LXC 和基础服务 PVE Host Docker 上的 AdGuardHome 普通客户端 Upstream DNS、Fallback DNS、本地别名和 LAN Cache，不作为公网服务入口 Rewrite 中心 Traefik / Authelia HTTP(S) 服务入口和鉴权 为了后面几篇文章不一直抽象描述，核心 LAN 地址先放在这里： 地址 角色 10.1.1.1 RouterOS 主网关，普通客户端默认网关 10.1.1.100 PVE Host Docker 上的 AdGuardHome，普通客户端 Upstream DNS、Fallback DNS、本地别名和 LAN Cache 10.1.1.253 代理 VIP，需要透明代理的客户端把它当默认网关和 DNS 10.1.1.254 WRT 后端地址，健康时持有代理 VIP；代理路径的网关 Backend 和 Sing-box DNS Backend 都落在这里 flowchart LR normal[\"普通客户端GW 10.1.1.1DNS 10.1.1.100\"] proxy[\"代理客户端GW/DNS 10.1.1.253\"] wan[\"WAN\"] subgraph pve[\"PVE Host 10.1.1.100\"] ros[\"RouterOS CHR VM10.1.1.1Main Gateway\"] wrt[\"WRT LXC10.1.1.254Sing-box / NetBird\"] adg[\"AdGuardHome Docker10.1.1.100:53LAN DNS Cache\"] vip[\"Proxy VIP10.1.1.253VRRP\"] end normal --\u003e|GW| ros normal --\u003e|DNS| adg proxy --\u003e vip vip --\u003e|Healthy Backend| wrt vip -.-\u003e|Fallback Backend| ros wrt --\u003e|dns-local| adg ros --\u003e|Ordinary DNS Upstream| adg ros --\u003e wan wrt --\u003e wan flowchart LR normal[\"普通客户端GW 10.1.1.1DNS 10.1.1.100\"] proxy[\"代理客户端GW/DNS 10.1.1.253\"] wan[\"WAN\"] subgraph pve[\"PVE Host 10.1.1.100\"] ros[\"RouterOS CHR VM10.1.1.1Main Gateway\"] wrt[\"WRT LXC10.1.1.254Sing-box / NetBird\"] adg[\"AdGuardHome Docker10.1.1.100:53LAN DNS Cache\"] vip[\"Proxy VIP10.1.1.253VRRP\"] end normal --\u003e|GW| ros normal --\u003e|DNS| adg proxy --\u003e vip vip --\u003e|Healthy Backend| wrt vip -.-\u003e|Fallback Backend| ros wrt --\u003e|dns-local| adg ros --\u003e|Ordinary DNS Upstream| adg ros --\u003e wan wrt --\u003e wan flowchart LR normal[\"普通客户端GW 10.1.1.1DNS 10.1.1.100\"] proxy[\"代理客户端GW/DNS 10.1.1.253\"] wan[\"WAN\"] subgraph pve[\"PVE Host 10.1.1.100\"] ros[\"RouterOS CHR VM10.1.1.1Main Gateway\"] wrt[\"WRT LXC10.1.1.254Sing-box / NetBird\"] adg[\"AdGuardHome Docker10.1.1.100:53LAN DNS Cache\"] vip[\"Proxy VIP10.1.1.253VRRP\"] end normal --\u003e|GW| ros normal --\u003e|DNS| adg proxy --\u003e vip vip --\u003e|Healthy Backend| wrt vip -.-\u003e|Fallback Backend| ros wrt --\u003e|dns-local| adg ros --\u003e|Ordinary DNS Upstream| adg ros --\u003e wan wrt --\u003e wan flowchart LR normal[\"普通客户端GW 10.1.1.1DNS 10.1.1.100\"] proxy[\"代理客户端GW/DNS 10.1.1.253\"] wan[\"WAN\"] subgraph pve[\"PVE Host 10.1.1.100\"] ros[\"RouterOS CHR VM10.1.1.1Main Gateway\"] wrt[\"WRT LXC10.1.1.254Sing-box / NetBird\"] adg[\"AdGuardHome Docker10.1.1.100:53LAN DNS Cache\"] vip[\"Proxy VIP10.1.1.253VRRP\"] end normal --\u003e|GW| ros normal --\u003e|DNS| adg proxy --\u003e vip vip --\u003e|Healthy Backend| wrt vip -.-\u003e|Fallback Backend| ros wrt --\u003e|dns-local| adg ros --\u003e|Ordinary DNS Upstream| adg ros --\u003e wan wrt --\u003e wan 这里最重要的取舍，是让 RouterOS 保持“边界设备”的角色，让 WRT 承担“弹性能力”的角色。 普通设备仍然走 RouterOS。需要透明代理的设备，通过 DHCP Option-set 拿到一个代理 VIP 作为默认网关和 DNS。这个 VIP 正常情况下由 WRT 持有，WRT 后面是 Sing-box 的 DNS / TUN / Route Policy；如果 WRT 的基础健康检查失败，VIP 会切回 RouterOS，至少还能保留普通 LAN/WAN Fallback。 这样做不是为了优雅，而是为了出问题时损失更可控： WRT 挂了，普通设备不受影响 Sing-box 挂了，代理设备可以 Fallback 到 RouterOS Fallback DNS 可以回到普通客户端也在使用的 AdGuardHome，保持解析和 LAN Cache 一致，但不把它当成公网服务入口的 Split DNS 中心 公网服务入口从 LAN 访问时，仍然保持公网 DNS 视角，通过 RouterOS Hairpin NAT 回来 这也是我后来越来越不喜欢“内网 DNS 劫持公网域名”的原因。DNS 只能按名字做决策，但很多入口服务真正的差异在端口、协议、认证和后端服务上。把这些东西都塞给 DNS，维护到后面很容易变成另一种债。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/:0:4","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：开篇 - 家庭网络为什么会变复杂","uri":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/#新方案"},{"categories":null,"collections":null,"content":"NetBird 的位置 NetBird 在这套网络里不是“另一个给客户端翻出去的代理”，而是 Admin Overlay。 它解决的主要问题是： Mobile Devices / MacBook 在外面可以访问 Homelab 的管理入口 Mobile Devices / MacBook 在外面可以访问 Homelab / Hometown / Office-JT / Office-SQ / DC-101 WRT 节点之间可以作为 Subnet Router，把受控的站点网络暴露给允许的 Portable Devices (Admin) ACL 可以明确限制哪些 Admin 设备能访问哪些 Peer 和哪些站点路由 这里 Tailscale 只是一个顺手对比过的对象，不是这个系列的重点。真正有价值的是 NetBird 的 ACL、Peer Registry、Route Awareness 怎么和现有 RouterOS / WRT 网络配合。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/:0:5","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：开篇 - 家庭网络为什么会变复杂","uri":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/#netbird-的位置"},{"categories":null,"collections":null,"content":"Backup Path 虽然 NetBird 是当前主要的 Admin Overlay，但我没有把 ZeroTier 和 Sing-box Inbound 删掉。 原因很简单：异地网络问题最麻烦的地方，不是平时能不能通，而是出事时你能不能还有第二条路径进去。 现在的定位大概是： NetBird：日常 Admin Overlay ZeroTier：保留 P2P 能力，不再作为主要 Network Route Sing-box Inbound：Homelab / Office-JT 的备用入口手段，由 WRT 承载 这几条路径不是为了“同时在线很酷”，而是为了避免远程故障时只剩一个入口。尤其是跨城市、现场距离比较远的时候，Backup Path 的价值会比平时看起来高很多。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/:0:6","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：开篇 - 家庭网络为什么会变复杂","uri":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/#backup-path"},{"categories":null,"collections":null,"content":"最后的结论 家庭网络变复杂，通常不是因为一开始就想复杂，而是因为需求一点点越过了普通家用路由器的边界。 我的取舍是： 主网关尽量稳定 实验性和策略性能力放到旁路 管理 Overlay 和用户流量分开 DNS 不承担它不擅长的入口分流职责 Backup Path 不追求优雅，只追求出事时还能进去 这套方案肯定不是最简单的，但它的目标也不是简单，而是把复杂性放在相对可控的位置。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/:0:7","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：开篇 - 家庭网络为什么会变复杂","uri":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/#最后的结论"},{"categories":null,"collections":null,"content":"后续准备怎么写 这个系列我大概会按决策拆，而不是按软件拆。后续章节放在开头的系列导航里，已经写完的文章会直接链接，没写到的先保留成题目。 每篇都尽量只讲一个问题。因为这套东西如果一次性全写出来，会变成一大坨拓扑名词和配置片段，读起来也没意义。 ","date":"2026-05-29","objectID":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/:0:8","tags":["运维","网络","Homelab"],"title":"Homelab 网络系列：开篇 - 家庭网络为什么会变复杂","uri":"/2026/05/29/%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%8F%98%E5%A4%8D%E6%9D%82homelab-%E7%BD%91%E7%BB%9C%E7%B3%BB%E5%88%97%E5%BC%80%E7%AF%87/#后续准备怎么写"},{"categories":null,"collections":null,"content":" 利用 ip monitor 工具实现路由观察分析，并利用 OpenWRT 的 hotplug 事件解决 Zerotier 启动时添加自定义路由的难题。 ","date":"2021-11-09","objectID":"/2021/11/09/%E5%88%A9%E7%94%A8-openwrt-%E7%9A%84-hotplug-%E4%BA%8B%E4%BB%B6%E8%A7%A3%E5%86%B3-zerotier-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B7%AF%E7%94%B1%E7%9A%84%E9%9A%BE%E9%A2%98/:0:0","tags":null,"title":"利用 OpenWRT 的 Hotplug 事件解决 Zerotier 启动时添加自定义路由的难题","uri":"/2021/11/09/%E5%88%A9%E7%94%A8-openwrt-%E7%9A%84-hotplug-%E4%BA%8B%E4%BB%B6%E8%A7%A3%E5%86%B3-zerotier-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B7%AF%E7%94%B1%E7%9A%84%E9%9A%BE%E9%A2%98/#"},{"categories":null,"collections":null,"content":"背景 公司有多个办公地点，使用zerotier组网 不是所有办公地点都开放实现互访 每个办公地点都会定期变动公网ip，每日执行 ifup wan 对电信网络执行重新拨号，因此会导致自己手动添加的 ip route 路由被清除 如何获得真正加入 zerotier 网络并可用变成了必须解决的问题，因此本文探讨的问题即为此 Zerotier本身依赖UDP打洞技术，属于P2P V*N，没有明确的中心化概念，所以什么时候明确连接上网络是个不可预知的问题 Zerotier本身有所有节点的自定义路由，可以在控制器添加，但本次仅为了单台节点自身添加自定义路由而不希望网络中其他节点也有此路由，因此只能在节点本身动手脚 ","date":"2021-11-09","objectID":"/2021/11/09/%E5%88%A9%E7%94%A8-openwrt-%E7%9A%84-hotplug-%E4%BA%8B%E4%BB%B6%E8%A7%A3%E5%86%B3-zerotier-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B7%AF%E7%94%B1%E7%9A%84%E9%9A%BE%E9%A2%98/:0:1","tags":null,"title":"利用 OpenWRT 的 Hotplug 事件解决 Zerotier 启动时添加自定义路由的难题","uri":"/2021/11/09/%E5%88%A9%E7%94%A8-openwrt-%E7%9A%84-hotplug-%E4%BA%8B%E4%BB%B6%E8%A7%A3%E5%86%B3-zerotier-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B7%AF%E7%94%B1%E7%9A%84%E9%9A%BE%E9%A2%98/#背景"},{"categories":null,"collections":null,"content":"解决方案 解决方案大体有这么两种 方案1：可以全部通过zerotier custom route实现，全路由转发，再配合iptables ACCEPT来实现访问控制 方案2：仅在需要访问其他子网的路由节点本地添加自定义路由 ","date":"2021-11-09","objectID":"/2021/11/09/%E5%88%A9%E7%94%A8-openwrt-%E7%9A%84-hotplug-%E4%BA%8B%E4%BB%B6%E8%A7%A3%E5%86%B3-zerotier-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B7%AF%E7%94%B1%E7%9A%84%E9%9A%BE%E9%A2%98/:0:2","tags":null,"title":"利用 OpenWRT 的 Hotplug 事件解决 Zerotier 启动时添加自定义路由的难题","uri":"/2021/11/09/%E5%88%A9%E7%94%A8-openwrt-%E7%9A%84-hotplug-%E4%BA%8B%E4%BB%B6%E8%A7%A3%E5%86%B3-zerotier-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B7%AF%E7%94%B1%E7%9A%84%E9%9A%BE%E9%A2%98/#解决方案"},{"categories":null,"collections":null,"content":"分析步骤 打开监控 ip monitor all 之后执行 service zerotier stop 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [NEIGH]172.16.200.1 dev ztjqgyage2 lladdr d2:10:71:16:e9:16 STALE [ROUTE]Deleted 172.16.2.0/24 via 172.16.200.1 dev ztjqgyage2 proto static [NEIGH]172.16.200.1 dev ztjqgyage2 lladdr d2:10:71:16:e9:16 PROBE [LINK]79: ztjqgyage2: \u0026lt;BROADCAST,MULTICAST\u0026gt; mtu 2800 qdisc fq_codel state DOWN group default link/ether d2:73:08:7f:bf:e7 brd ff:ff:ff:ff:ff:ff [NEIGH]Deleted 172.16.200.1 dev ztjqgyage2 lladdr d2:10:71:16:e9:16 PROBE [ROUTE]Deleted fe80::/64 dev ztjqgyage2 proto kernel metric 256 pref medium [ROUTE]Deleted anycast fe80:: dev ztjqgyage2 table local proto kernel metric 0 pref medium [ROUTE]Deleted local fe80::b8ba:12ff:fedd:2fc0 dev ztjqgyage2 table local proto kernel metric 0 pref medium [ROUTE]Deleted multicast ff00::/8 dev ztjqgyage2 table local proto kernel metric 256 pref medium [NEIGH]Deleted ff02::1:ffdd:2fc0 dev ztjqgyage2 lladdr 33:33:ff:dd:2f:c0 NOARP [NEIGH]Deleted ff02::16 dev ztjqgyage2 lladdr 33:33:00:00:00:16 NOARP [ADDR]Deleted 79: ztjqgyage2 inet6 fe80::b8ba:12ff:fedd:2fc0/64 scope link valid_lft forever preferred_lft forever [ADDR]Deleted 79: ztjqgyage2 inet 172.16.200.13/24 brd 172.16.200.255 scope global ztjqgyage2 valid_lft forever preferred_lft forever [ROUTE]Deleted local 172.16.200.13 dev ztjqgyage2 table local proto kernel scope host src 172.16.200.13 [NETCONF]Deleted inet ztjqgyage2 [NETCONF]Deleted inet6 ztjqgyage2 [LINK]Deleted 79: ztjqgyage2: \u0026lt;BROADCAST,MULTICAST\u0026gt; mtu 2800 qdisc noop state DOWN group default link/ether d2:73:08:7f:bf:e7 brd ff:ff:ff:ff:ff:ff 那么再观察下service zerotier start都干了什么？ 先打开监控 ip monitor all，然后执行 service zerotier start [NETCONF]inet ztjqgyage2 forwarding on rp_filter off mc_forwarding off proxy_neigh off ignore_routes_with_linkdown off [NETCONF]inet6 ztjqgyage2 forwarding on mc_forwarding off proxy_neigh off ignore_routes_with_linkdown off [LINK]80: ztjqgyage2: \u0026lt;BROADCAST,MULTICAST\u0026gt; mtu 1500 qdisc noop state DOWN group default link/ether e2:e8:19:70:ce:6a brd ff:ff:ff:ff:ff:ff [LINK]80: ztjqgyage2: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc fq_codel state UNKNOWN group default link/ether e2:e8:19:70:ce:6a brd ff:ff:ff:ff:ff:ff [ROUTE]multicast ff00::/8 dev ztjqgyage2 table local proto kernel metric 256 pref medium [ROUTE]fe80::/64 dev ztjqgyage2 proto kernel metric 256 pref medium [LINK]80: ztjqgyage2: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc fq_codel state UNKNOWN group default link/ether d2:73:08:7f:bf:e7 brd ff:ff:ff:ff:ff:ff [NEIGH]Deleted ff02::16 dev ztjqgyage2 lladdr 33:33:00:00:00:16 NOARP [NEIGH]Deleted ff02::1:ff70:ce6a dev ztjqgyage2 lladdr 33:33:ff:70:ce:6a NOARP [LINK]80: ztjqgyage2: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 2800 qdisc fq_codel state UNKNOWN group default link/ether d2:73:08:7f:bf:e7 brd ff:ff:ff:ff:ff:ff [ADDR]80: ztjqgyage2 inet 172.16.200.13/24 brd 172.16.200.255 scope global ztjqgyage2 valid_lft forever preferred_lft forever [ROUTE]local 172.16.200.13 dev ztjqgyage2 table local proto kernel scope host src 172.16.200.13 [ROUTE]broadcast 172.16.200.255 dev ztjqgyage2 table local proto kernel scope link src 172.16.200.13 [ROUTE]172.16.200.0/24 dev ztjqgyage2 proto kernel scope link src 172.16.200.13 [ROUTE]broadcast 172.16.200.0 dev ztjqgyage2 table local proto kernel scope link src 172.16.200.13 [ROUTE]172.16.2.0/24 via 172.16.200.1 dev ztjqgyage2 proto static [ROUTE]192.168.3.0/24 via 172.16.200.101 dev ztjqgyage2 [ADDR]80: ztjqgyage2 inet6 fe80::e0e8:19ff:fe70:ce6a/64 scope link valid_lft forever preferred_lft forever [ROUTE]local fe80::e0e8:19ff:fe70:ce6a dev ztjqgyage2 table local proto kernel metric 0 pref medium [ROUTE]anycast fe80:: dev ztjqgyage2 table local proto kernel metric 0 pref medium [NEIGH]172.16.200.1 dev ztjqgyage2 lladdr d2:10:71:16:e9:16 REACHABLE [NEIGH]172.16.200.101 dev ztjqgyage2 lladdr d2:23:9e:74:63:f2 REACHABLE 从以上的步骤可以分析得知，在一个zerotier网络存续期间，大概会有这么些[EVENT]产生，那么根据我们的主路","date":"2021-11-09","objectID":"/2021/11/09/%E5%88%A9%E7%94%A8-openwrt-%E7%9A%84-hotplug-%E4%BA%8B%E4%BB%B6%E8%A7%A3%E5%86%B3-zerotier-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B7%AF%E7%94%B1%E7%9A%84%E9%9A%BE%E9%A2%98/:0:3","tags":null,"title":"利用 OpenWRT 的 Hotplug 事件解决 Zerotier 启动时添加自定义路由的难题","uri":"/2021/11/09/%E5%88%A9%E7%94%A8-openwrt-%E7%9A%84-hotplug-%E4%BA%8B%E4%BB%B6%E8%A7%A3%E5%86%B3-zerotier-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B7%AF%E7%94%B1%E7%9A%84%E9%9A%BE%E9%A2%98/#分析步骤"},{"categories":null,"collections":null,"content":"实现方案 首选方案：[NEIGH]172.16.200.1 dev ztjqgyage2 lladdr d2:10:71:16:e9:16 REACHABLE zerotier 虚拟网口 ztjqgyage2 上的网关ip 172.16.200.1变为 REACHABLE 时进行处理 理想很美好，现实很骨感，实际在service zerotier start/stop时并不能触发任何 hotplug neigh事件 备选方案（实际使用方案） 根据测试，在service zerotier start/stop时具有hotplug.d的net/iface变更通知 那么我们根据事件通知来编写最后的代码，vim /etc/hotplug.d/net/99-zerotier 目的是为了在zerotier连接上其他p2p节点之后，在当前节点添加自定义路由ip route add 192.168.3.0/24 via 172.16.200.101（方圆E时光访问建中路大本营的局域网，方便运营访问共享192.168.3.x） 由于Zerotier本身连通过程的不确定性（时间上不明确多久可以打通网络），所以代码添加了循环重试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #!/bin/sh # ref: https://openwrt.org/docs/guide-user/base-system/hotplug # @author: CsHeng # @date: 2021-11-08 # add route to gw-office after zerotier gateway neighbor reachable [ \u0026#34;$ACTION\u0026#34; = \u0026#34;add\u0026#34; -a \u0026#34;$INTERFACE\u0026#34; = \u0026#34;ztjqgyage2\u0026#34; ] \u0026amp;\u0026amp; { echo \u0026#34;`date` net dev ztjqgyage2 add detected...\u0026#34; \u0026gt;\u0026gt; /var/log/hotplug_net.log r=0 # pppoe dial-up will need some more time...zerotier reconnection even~~~ while [ $r -ne 1 ] do echo \u0026#34;`date` sleep 5s, waiting for zt connection\u0026#34; \u0026gt;\u0026gt; /var/log/hotplug_net.log sleep 5 ip route add 192.168.3.0/24 via 172.16.200.101 r=`ip route | grep 192.168.3.0 | wc -l` done echo \u0026#34;`date` ip route add 192.168.3.0/24 via 172.16.200.101\u0026#34; \u0026gt;\u0026gt; /var/log/hotplug_net.log } # custom controller zerotier-cli orbit 1e4735524a 1e4735524a ","date":"2021-11-09","objectID":"/2021/11/09/%E5%88%A9%E7%94%A8-openwrt-%E7%9A%84-hotplug-%E4%BA%8B%E4%BB%B6%E8%A7%A3%E5%86%B3-zerotier-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B7%AF%E7%94%B1%E7%9A%84%E9%9A%BE%E9%A2%98/:0:4","tags":null,"title":"利用 OpenWRT 的 Hotplug 事件解决 Zerotier 启动时添加自定义路由的难题","uri":"/2021/11/09/%E5%88%A9%E7%94%A8-openwrt-%E7%9A%84-hotplug-%E4%BA%8B%E4%BB%B6%E8%A7%A3%E5%86%B3-zerotier-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B7%AF%E7%94%B1%E7%9A%84%E9%9A%BE%E9%A2%98/#实现方案"},{"categories":null,"collections":null,"content":"对结果进行验证 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 \u0026gt; tail -n 100 /var/log/hotplug_net.log Tue Nov 9 00:56:03 CST 2021 net dev ztjqgyage2 add detected... Tue Nov 9 00:56:03 CST 2021 sleep 5s, waiting for zt connection ... # 省略N行 Tue Nov 9 00:59:38 CST 2021 sleep 5s, waiting for zt connection Tue Nov 9 00:59:43 CST 2021 sleep 5s, waiting for zt connection Tue Nov 9 00:59:48 CST 2021 ip route add 192.168.3.0/24 via 172.16.200.101 Tue Nov 9 00:59:49 CST 2021 net dev ztjqgyage2 add detected... Tue Nov 9 00:59:49 CST 2021 sleep 5s, waiting for zt connection Tue Nov 9 00:59:54 CST 2021 ip route add 192.168.3.0/24 via 172.16.200.101 \u0026gt; ip route default via 116.22.200.1 dev pppoe-wan proto static 116.22.200.1 dev pppoe-wan proto kernel scope link src 116.22.200.28 172.16.2.0/24 via 172.16.200.1 dev ztjqgyage2 proto static 172.16.200.0/24 dev ztjqgyage2 proto kernel scope link src 172.16.200.13 192.168.3.0/24 via 172.16.200.101 dev ztjqgyage2 192.168.13.0/24 dev br-lan proto kernel scope link src 192.168.13.1 可以确认到在每天0:56分进行pppoe拨号时，触发了事件通知，我们的代码被执行了，并且最后成功添加了路由 192.168.3.0/24 via 172.16.200.101 dev ztjqgyage2 ","date":"2021-11-09","objectID":"/2021/11/09/%E5%88%A9%E7%94%A8-openwrt-%E7%9A%84-hotplug-%E4%BA%8B%E4%BB%B6%E8%A7%A3%E5%86%B3-zerotier-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B7%AF%E7%94%B1%E7%9A%84%E9%9A%BE%E9%A2%98/:0:5","tags":null,"title":"利用 OpenWRT 的 Hotplug 事件解决 Zerotier 启动时添加自定义路由的难题","uri":"/2021/11/09/%E5%88%A9%E7%94%A8-openwrt-%E7%9A%84-hotplug-%E4%BA%8B%E4%BB%B6%E8%A7%A3%E5%86%B3-zerotier-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B7%AF%E7%94%B1%E7%9A%84%E9%9A%BE%E9%A2%98/#对结果进行验证"},{"categories":null,"collections":null,"content":"Ref Docs IP monitor Manpage OpenWRT hotplug ","date":"2021-11-09","objectID":"/2021/11/09/%E5%88%A9%E7%94%A8-openwrt-%E7%9A%84-hotplug-%E4%BA%8B%E4%BB%B6%E8%A7%A3%E5%86%B3-zerotier-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B7%AF%E7%94%B1%E7%9A%84%E9%9A%BE%E9%A2%98/:0:6","tags":null,"title":"利用 OpenWRT 的 Hotplug 事件解决 Zerotier 启动时添加自定义路由的难题","uri":"/2021/11/09/%E5%88%A9%E7%94%A8-openwrt-%E7%9A%84-hotplug-%E4%BA%8B%E4%BB%B6%E8%A7%A3%E5%86%B3-zerotier-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B7%AF%E7%94%B1%E7%9A%84%E9%9A%BE%E9%A2%98/#ref-docs"},{"categories":null,"collections":null,"content":"背景 我们总共有13台服务器，1个24口交换机（没有路由器），仅购买了两个公网IP，也就是说仅有两台服务器可以直接连通公网（全配置为全转发路由器），而其他机器得通过NAT来访问公网。 ","date":"2021-06-24","objectID":"/2021/06/24/linux-%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2%E8%B7%AF%E7%94%B1%E8%A1%A8/:0:1","tags":null,"title":"Linux 动态切换路由表","uri":"/2021/06/24/linux-%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2%E8%B7%AF%E7%94%B1%E8%A1%A8/#背景"},{"categories":null,"collections":null,"content":"问题 存在的问题：托管在机房的服务器由于是二手硬件，难免会偶尔直接崩溃无法开机。。。而我们没有实际上的路由器，若网关服务器炸了，作为网络内需要通过NAT来上网的机器，该如何自动切换到备用网关呢？ ","date":"2021-06-24","objectID":"/2021/06/24/linux-%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2%E8%B7%AF%E7%94%B1%E8%A1%A8/:0:2","tags":null,"title":"Linux 动态切换路由表","uri":"/2021/06/24/linux-%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2%E8%B7%AF%E7%94%B1%E8%A1%A8/#问题"},{"categories":null,"collections":null,"content":"解决思路 由于我们并不是一台服务器上面多条物理网线，所以没办法使用单台服务器内的网口上下线事件来作为切换通知 所以解决方案是：那部分需要做NAT的机器，通过自身定时检测是否能通过网关访问公网，若不能则切换为备用网关 ","date":"2021-06-24","objectID":"/2021/06/24/linux-%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2%E8%B7%AF%E7%94%B1%E8%A1%A8/:0:3","tags":null,"title":"Linux 动态切换路由表","uri":"/2021/06/24/linux-%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2%E8%B7%AF%E7%94%B1%E8%A1%A8/#解决思路"},{"categories":null,"collections":null,"content":"前提条件 两台能分配到公网的机器开启全路由模式 内核允许转发 iptables允许转发 公司主路由(openwrt 系统)和托管机房服务器通过 Zerotier 组网，并且两台公网服务器分别分配到 zerotier ip 172.16.200.1 和 172.16.200.2 ","date":"2021-06-24","objectID":"/2021/06/24/linux-%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2%E8%B7%AF%E7%94%B1%E8%A1%A8/:0:4","tags":null,"title":"Linux 动态切换路由表","uri":"/2021/06/24/linux-%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2%E8%B7%AF%E7%94%B1%E8%A1%A8/#前提条件"},{"categories":null,"collections":null,"content":"解决步骤 增加ping包的目标路由表、ping指定网络接口，可以在不影响现有网络运行的情况下达到定向检测网络接口可用性 ping -I $NIC -c 2 -W $PING_TIMEOUT $REMOTE_IP \u0026gt; /dev/null # 通过$NIC网络接口发出对$REMOTE_IP的ping包，数量2个，若超过超时时间$PING_TIMEOUT(seconds)则认为是失败，\u0026gt; /dev/null 不输出ping命令的结果到控制台 PING_RESULT=$? # 通过获取上一次命令执行成功的结果，成功为0，失败为1 检测主网关和备用网关可用性，若主网关可用则优先使用主网关 添加crontab任务，每分钟执行一次判断以达到动态切换作用 xxx.sh \u0026gt; /tmp/route_failover.log 实现切换的脚本参考（适用于Linux服务器） 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 #!/bin/bash # # Linux default gateway failover script [route via lan] # @author CsHeng 2020.06.11 # ref: https://blog.rapellys.biz/2014/10/18/linux-default-gateway-failover-script/ # #********************************************************************* # Configuration #********************************************************************* DEF_GATEWAY=\u0026#34;172.16.2.1\u0026#34; # Default Gateway BCK_GATEWAY=\u0026#34;172.16.2.2\u0026#34; # Backup Gateway SUBNET=\u0026#34;default\u0026#34; # ip route destination subnet RMT_IP_1=\u0026#34;119.29.29.29\u0026#34; # first remote ip RMT_IP_2=\u0026#34;223.5.5.5\u0026#34; # second remote ip PING_TIMEOUT=\u0026#34;1\u0026#34; # Ping timeout in seconds #********************************************************************* # fail fast set -e # check user if [ `whoami` != \u0026#34;root\u0026#34; ] then echo \u0026#34;Failover script must be run as root!\u0026#34; exit 1 fi #Check GW CURRENT_GW=`ip route show | grep $SUBNET | head -n 1 | awk \u0026#39;{print $3}\u0026#39;` PING_NIC=`ip route show | grep $SUBNET | head -n 1 | awk \u0026#39;{print $5}\u0026#39;` # ping network interface if [ \u0026#34;$CURRENT_GW\u0026#34; == \u0026#34;$DEF_GATEWAY\u0026#34; ] then ping -4 -I $PING_NIC -c 2 -W $PING_TIMEOUT $RMT_IP_1 \u0026gt; /dev/null PING_1=$? ping -4 -I $PING_NIC -c 2 -W $PING_TIMEOUT $RMT_IP_2 \u0026gt; /dev/null PING_2=$? else # add static routes to remote ip\u0026#39;s ip route add $RMT_IP_1 via $DEF_GATEWAY ip route add $RMT_IP_2 via $DEF_GATEWAY ping -4 -I $PING_NIC -c 2 -W $PING_TIMEOUT $RMT_IP_1 \u0026gt; /dev/null PING_1=$? ping -4 -I $PING_NIC -c 2 -W $PING_TIMEOUT $RMT_IP_2 \u0026gt; /dev/null PING_2=$? # del static route to remote ip\u0026#39;s ip route del $RMT_IP_1 ip route del $RMT_IP_2 fi LOG_TIME=`date +%b\u0026#39; \u0026#39;%d\u0026#39; \u0026#39;%T` # both ping fail if [ \u0026#34;$PING_1\u0026#34; == \u0026#34;1\u0026#34; ] \u0026amp;\u0026amp; [ \u0026#34;$PING_2\u0026#34; == \u0026#34;1\u0026#34; ] then if [ \u0026#34;$CURRENT_GW\u0026#34; == \u0026#34;$DEF_GATEWAY\u0026#34; ] then ip route del $SUBNET ip route add $SUBNET via $BCK_GATEWAY # flushing routing cache ip route flush cache echo \u0026#34;$LOG_TIME: $0 - Switched $SUBNET gateway to default with IP $BCK_GATEWAY\u0026#34; fi elif [ \u0026#34;$CURRENT_GW\u0026#34; != \u0026#34;$DEF_GATEWAY\u0026#34; ] then # switching to default ip route del $SUBNET ip route add $SUBNET via $DEF_GATEWAY ip route flush cache echo \u0026#34;$LOG_TIME: $0 - Switched $SUBNET gateway to default with IP $DEF_GATEWAY\u0026#34; fi ","date":"2021-06-24","objectID":"/2021/06/24/linux-%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2%E8%B7%AF%E7%94%B1%E8%A1%A8/:0:5","tags":null,"title":"Linux 动态切换路由表","uri":"/2021/06/24/linux-%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2%E8%B7%AF%E7%94%B1%E8%A1%A8/#解决步骤"},{"categories":null,"collections":null,"content":"扩展阅读 由于我们使用zerotier将公司网络和托管机房进行组网，因此公司主路由器也应该做动态路由切换 另外一份实现的Shell参考（适用于OpenWRT，除了极个别兼容改动，主体逻辑同Linux Shell） 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 #!/bin/sh # # Linux dynamic route failover script [route via zerotier] # @author CsHeng 2020.06.11 # ref: https://blog.rapellys.biz/2014/10/18/linux-default-gateway-failover-script/ # #********************************************************************* # Configuration #********************************************************************* DEF_GATEWAY=\u0026#34;172.16.200.1\u0026#34; # Default Gateway BCK_GATEWAY=\u0026#34;172.16.200.2\u0026#34; # Backup Gateway SUBNET=\u0026#34;172.16.2.0/24\u0026#34; # ip route destination subnet RMT_IP_1=\u0026#34;172.16.2.3\u0026#34; # first remote ip RMT_IP_2=\u0026#34;172.16.2.4\u0026#34; # second remote ip PING_TIMEOUT=\u0026#34;1\u0026#34; # Ping timeout in seconds #********************************************************************* # fail fast set -e #Check GW CURRENT_GW=`ip route show | grep $SUBNET | head -n 1 | awk \u0026#39;{print $3}\u0026#39;` PING_NIC=`ip route show | grep $SUBNET | head -n 1 | awk \u0026#39;{print $5}\u0026#39;` # ping network interface if [ \u0026#34;$CURRENT_GW\u0026#34; == \u0026#34;$DEF_GATEWAY\u0026#34; ] then ping -4 -I $PING_NIC -c 2 -W $PING_TIMEOUT $RMT_IP_1 \u0026gt; /dev/null PING_1=$? ping -4 -I $PING_NIC -c 2 -W $PING_TIMEOUT $RMT_IP_2 \u0026gt; /dev/null PING_2=$? else # add static routes to remote ip\u0026#39;s ip route add $RMT_IP_1 via $DEF_GATEWAY ip route add $RMT_IP_2 via $DEF_GATEWAY ping -4 -I $PING_NIC -c 2 -W $PING_TIMEOUT $RMT_IP_1 \u0026gt; /dev/null PING_1=$? ping -4 -I $PING_NIC -c 2 -W $PING_TIMEOUT $RMT_IP_2 \u0026gt; /dev/null PING_2=$? # del static route to remote ip\u0026#39;s ip route del $RMT_IP_1 ip route del $RMT_IP_2 fi LOG_TIME=`date +%b\u0026#39; \u0026#39;%d\u0026#39; \u0026#39;%T` # both ping fail if [ \u0026#34;$PING_1\u0026#34; == \u0026#34;1\u0026#34; ] \u0026amp;\u0026amp; [ \u0026#34;$PING_2\u0026#34; == \u0026#34;1\u0026#34; ] then if [ \u0026#34;$CURRENT_GW\u0026#34; == \u0026#34;$DEF_GATEWAY\u0026#34; ] then ip route del $SUBNET ip route add $SUBNET via $BCK_GATEWAY # flushing routing cache ip route flush cache echo \u0026#34;$LOG_TIME: $0 - Switched $SUBNET gateway to default with IP $BCK_GATEWAY\u0026#34; fi elif [ \u0026#34;$CURRENT_GW\u0026#34; != \u0026#34;$DEF_GATEWAY\u0026#34; ] then # switching to default ip route del $SUBNET ip route add $SUBNET via $DEF_GATEWAY ip route flush cache echo \u0026#34;$LOG_TIME: $0 - Switched $SUBNET gateway to default with IP $DEF_GATEWAY\u0026#34; fi PS: 以上思路来源（抄袭）自 linux-default-gateway-failover-script ","date":"2021-06-24","objectID":"/2021/06/24/linux-%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2%E8%B7%AF%E7%94%B1%E8%A1%A8/:0:6","tags":null,"title":"Linux 动态切换路由表","uri":"/2021/06/24/linux-%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2%E8%B7%AF%E7%94%B1%E8%A1%A8/#扩展阅读"},{"categories":null,"collections":null,"content":"前言 为了解决日益增长的计算、存储、测试环境的需求，结合我们办公室小机房优异的散热、电量、网络条件(详情如下)，因此在2021年3月份决定将公司的13台Dell R720服务器搬迁到机房进行托管，以期获得稳定的使用条件。 散热：开了16度然而还能热出汗的空调 供电：物业预期下午5点断电早上11点先进行预演，时不时跳一下闸什么的 机房布线管理：网线乱飞、电源线乱飞、随时踩一脚断电or断网 潘多拉的域名玩法：电信专线并不封堵TCP/443，当年（2017）使用TCP/443并配合DNS-01 challenge验证域名所有权，然后使用Let's Encrypt来签发证书，最终提供给测试环境HTTPS证书，并且在公网环境提供免备案的服务 ","date":"2021-05-13","objectID":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/:1:0","tags":["运维","网络"],"title":"机房托管的血与泪","uri":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/#前言"},{"categories":null,"collections":null,"content":"极其漫长的踩坑之路 从过年后3月初决定要搞事，开始采购新机器到最终上架“萝岗加速器”机房的时间是5月7号，整整跨了两个月。 ","date":"2021-05-13","objectID":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/:2:0","tags":["运维","网络"],"title":"机房托管的血与泪","uri":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/#极其漫长的踩坑之路"},{"categories":null,"collections":null,"content":"硬件玄学 二手硬件不稳定什么的，对于我们这种垃圾佬当然不是什么问题啦！插电，开机~~~ 服务器采购（花费一周） 购买6台新的Dell R720 XD 2U服务器，每台机器配置 CPU： E5 2650V2 * 2 H710P mini 硬盘阵列卡 内存：8GB/16GB * 16 = 144GB/288GB 迁移原有服务器(Dell R420)内硬盘到新的机器 顺利的：基本能够直接开机，只要硬件自检通过，然后重新配置阵列卡，开机完成硬件升级 失败的：硬盘阵列卡故障、硬盘背板失败不通电、内存没装好\u0026hellip;.. ","date":"2021-05-13","objectID":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/:2:1","tags":["运维","网络"],"title":"机房托管的血与泪","uri":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/#硬件玄学"},{"categories":null,"collections":null,"content":"PVE集群之坑 从已有用于测试环境的3台1U服务器，升级成4台2U的服务器（由于IP经过了变更，所以需要重新组件集群而不是使用现有的集群） 旧的集群：2台1U服务器原本已经安装了PVE并且有虚拟机提供测试环境数据，正在服役 新的集群：2台新机器直接安装PVE操作系统，组建集群 集群管理的坑 对pve集群node节点管理不熟悉 官方文档是最好的解决方案 对pve虚拟机磁盘管理不熟悉导致的坑 误删两个虚拟机硬盘，直接导致测试环境需要重建 remove/purge的时候要认真阅读警告信息。。。 ","date":"2021-05-13","objectID":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/:2:2","tags":["运维","网络"],"title":"机房托管的血与泪","uri":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/#pve集群之坑"},{"categories":null,"collections":null,"content":"域名备案问题 这是个迷之问题，只有在神奇的东方才有这种需求，这个过程花了一些时间去了解政策，才算是明确了再次备案不影响原先接入备案的问题。 遵循接入方备案原则：同一个域名，接入阿里云需要做一次备案，接入另外一家服务商需要再做一次备案。 当年绕过电信专线不封堵TCP/443用来提供HTTPS，然后间接提供相对标准（只使用80/443端口）的公网HTTP服务的方案，在经过了几年的发展，积累了一大批域名，还好基本都是属于同一个顶级域名的二级、三级域名，没造成太大的修改难题 ","date":"2021-05-13","objectID":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/:2:3","tags":["运维","网络"],"title":"机房托管的血与泪","uri":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/#域名备案问题"},{"categories":null,"collections":null,"content":"文网文问题 这是一个更迷的问题，同样只存在于大局域网国家，多次申诉、联系客服折腾无果，只能按照某福报厂要求对网站内容进行大幅度修改，去掉游戏相关字眼（只要网站内容有游戏，必须要求文网文证件）的内容。 一个国家有关部门已经不签发的证书，却在审核备案的的初审部分需要审核，投诉无门，喝喝 ","date":"2021-05-13","objectID":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/:2:4","tags":["运维","网络"],"title":"机房托管的血与泪","uri":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/#文网文问题"},{"categories":null,"collections":null,"content":"网络架构调整 原网络拓扑：公司和服务器之间是局域网(192.168.0.0/21），服务器局域网连接是通过连接同一个交换机并uplink到公司主路由来实现访问的，几个提供对外访问的具有公网的服务器则是另外一个专线交换机连接 新网络拓扑：为了方便公司同事在开发的时候，直接使用局域网地址+端口号来访问测试服务，而不是一切访问都经过网关做端口转发 通过 SD-WAN 技术，使用P2P VPN软件Zerotier建立局域网 172.16.200.0/24 托管机房网关 Zerotier 网口 IP 172.16.200.1 配置防火墙允许流量 iptables -t raw -A INPUT -i zt+ -j ACCEPT 配置 NAT iptables -t nat -A POSTROUTING -o zt+ -j MASQUERADE 配置入站数据转发 iptables -A FORWARD -i zt+ -j ACCEPT 配置 Linux 内核开启 ipv4 转发，修改 /etc/sysctl.conf net.ipv4.ip_forward=1 并且使用 sysctl -p 使之生效 公司办公网关 Zerotier 网口 IP 172.16.200.42 配置路由表 ip route add 172.16.200.0/24 via 172.16.200.1 配置 NAT iptables -t nat -A POSTROUTING -o zt+ -j MASQUERADE 配置出站数据转发 iptables -A FORWARD -o zt+ -j ACCEPT 配置 Linux 内核开启 ipv4 转发，修改 /etc/sysctl.conf net.ipv4.ip_forward=1 并且使用 sysctl -p 使之生效 以上配置实现公司办公网络 192.168.0.0/21 对 172.16.2.0/24 的单向访问，反之 172.16.2.0/24 访问 192.168.0.0/21 并不是合理的需求 穷鬼的折腾之路 24口交换机，通过VLAN划分出两个LAN 1-18 共18个交换机1Gbps电口，划分为一个VLAN，用于提供服务器之间的局域网访问 19-24 共6个交换机1Gbps电口，划分为另外一个VLAN，用于提供公网访问（机房仅提供一条Uplink网线过来） ","date":"2021-05-13","objectID":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/:2:5","tags":["运维","网络"],"title":"机房托管的血与泪","uri":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/#网络架构调整"},{"categories":null,"collections":null,"content":"服务器上架 一方折腾之后，5月7号下午搬迁到机房，顺利开机，配置网络，顺利得有点惊人？？？？2小时搞定回家 果然，事出反常必有妖\u0026hellip;.5月8号早上发现其中一台机器硬盘竟然变为只读。。。过去机房开机搞定，回公司 几个小时之后，硬盘再次变为只读\u0026hellip;.带上硬件背板、阵列卡备用件机房拆机更换，似乎有点顺利，开机启动，进入系统引导，然而经过了几次硬盘变为只读，系统文件已损坏，无法进入系统，一番乱敲命令之后，发现并没有解决问题 关键时刻，找出了日常装系统的小U盘，用上了由强大的 ventoy 管理的PVE ISO安装盘，进入rescue boot，哦吼，错误提示跑个硬盘修复命令，一路yyyyyy....reboot，神奇。。。解决了 ","date":"2021-05-13","objectID":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/:2:6","tags":["运维","网络"],"title":"机房托管的血与泪","uri":"/2021/05/13/%E6%9C%BA%E6%88%BF%E6%89%98%E7%AE%A1%E7%9A%84%E8%A1%80%E4%B8%8E%E6%B3%AA/#服务器上架"},{"categories":null,"collections":null,"content":"背景 局域网 Kubernetes 测试服务器的具有公网(1.2.3.4)、局域网(10.0.0.10)双网卡 日常需求较多需要从局域网内/公网环境通过域名访问测试服务器（同时还有部分正式环境的大数据服务） ","date":"2021-01-19","objectID":"/2021/01/19/%E9%80%9A%E8%BF%87-dhcp-options-%E4%B8%8B%E5%8F%91%E8%B7%AF%E7%94%B1%E8%A7%A3%E5%86%B3%E5%90%8C%E5%B1%80%E5%9F%9F%E7%BD%91%E5%86%85%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BA%92%E8%AE%BF%E7%9A%84%E6%95%88%E7%8E%87%E9%97%AE%E9%A2%98/:0:1","tags":["运维","网络"],"title":"通过 DHCP Options 下发路由解决同局域网内服务器互访的效率问题","uri":"/2021/01/19/%E9%80%9A%E8%BF%87-dhcp-options-%E4%B8%8B%E5%8F%91%E8%B7%AF%E7%94%B1%E8%A7%A3%E5%86%B3%E5%90%8C%E5%B1%80%E5%9F%9F%E7%BD%91%E5%86%85%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BA%92%E8%AE%BF%E7%9A%84%E6%95%88%E7%8E%87%E9%97%AE%E9%A2%98/#背景"},{"categories":null,"collections":null,"content":"旧方案 公网环境 DNS 配置gw.sukikaka.com A 1.2.3.4 局域网环境 DNS Server 10.0.0.1 配置劫持成 gw.sukikaka.com A 10.0.0.10 局域网环境通过 DHCP Server 配置 DHCP Options 6,10.0.0.1,223.5.5.5 来达到下发 DNS Server 的目的 而以前用内网DNS服务器添加劫持，将gw.sukikaka.com A 10.0.0.10从而解决解析的问题，但是其他测试环境域名通过CNAME将解析指向gw.sukikaka.com时，并不能将CNAME再次顺利解析到10.0.0.10 存在的问题 需要将DNS Server设置成内网指定的DNS Server 10.0.0.10，否则无法劫持 增减域名需要在公网DNS Server设置解析，也需要在局域网DNS Server设置解析 另外，由于公司不少同事是使用科学上网，而这些科学上网很难要求他们会自己将DNS Server设置成内网的Server，所以最终导致占用 Kubernetes 公网带宽，测试环境体验不好 访问测试环境的数据会经过主路由器 NAT 成 default route 的公网地址，然后再访问Kubernetes的公网地址NAT回来，然后处理完成之后再反向回来局域网内的请求客户端，ip packet 增加了多余的NAT ","date":"2021-01-19","objectID":"/2021/01/19/%E9%80%9A%E8%BF%87-dhcp-options-%E4%B8%8B%E5%8F%91%E8%B7%AF%E7%94%B1%E8%A7%A3%E5%86%B3%E5%90%8C%E5%B1%80%E5%9F%9F%E7%BD%91%E5%86%85%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BA%92%E8%AE%BF%E7%9A%84%E6%95%88%E7%8E%87%E9%97%AE%E9%A2%98/:0:2","tags":["运维","网络"],"title":"通过 DHCP Options 下发路由解决同局域网内服务器互访的效率问题","uri":"/2021/01/19/%E9%80%9A%E8%BF%87-dhcp-options-%E4%B8%8B%E5%8F%91%E8%B7%AF%E7%94%B1%E8%A7%A3%E5%86%B3%E5%90%8C%E5%B1%80%E5%9F%9F%E7%BD%91%E5%86%85%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BA%92%E8%AE%BF%E7%9A%84%E6%95%88%E7%8E%87%E9%97%AE%E9%A2%98/#旧方案"},{"categories":null,"collections":null,"content":"新方案 公网环境 DNS 配置gw.sukikaka.com A 1.2.3.4 局域网环境通过 DHCP Server(网关) 配置 DHCP Options 6,10.0.0.1,223.5.5.5 来达到下发 DNS Server的目的（此时内网DNS Server仅通过使用SmartDNS服务，用于优化DNS查询，不做测试环境解析记录劫持） 利用 DHCP Server 将 DHCP Options 121, 1.2.3.4/32, 10.0.0.10 添加到请求客户端的路由上 新方案的优缺点 优点 直接在请求端发起请求的时候通过路由表路由到最终目的地，ip packet 只经过交换机而不需要经过路由器流转，减少了一次多余的NAT，提升了效率 只需要配置公网 DNS 解析，而不需要再配置局域网 DNS Server 劫持记录，减少了维护成本 缺点 双网卡公网服务器一旦有变更，需要更改主路由器下发 DHCP Options 配置 最后，可以通过ip route(Linux/Unix)或route print(Windows)来查看本机路由来确认： 1 2 3 4 5 6 7 8 9 10 default via 10.0.0.1 dev en0 1.2.3.4/32 via 10.0.0.10 dev en0 \u0026lt;---- 相比旧方案，新增了这一行 127.0.0.0/8 via 127.0.0.1 dev lo0 127.0.0.1/32 via 127.0.0.1 dev lo0 169.254.0.0/16 dev en0 scope link 192.168.0.0/21 dev en0 scope link 10.0.0.1/32 dev en0 scope link 224.0.0.0/4 dev en0 scope link 255.255.255.255/32 dev en0 scope link 现方案可以认为是以前方案的优化版，具体参考一种有趣的测试环境部署方式 ","date":"2021-01-19","objectID":"/2021/01/19/%E9%80%9A%E8%BF%87-dhcp-options-%E4%B8%8B%E5%8F%91%E8%B7%AF%E7%94%B1%E8%A7%A3%E5%86%B3%E5%90%8C%E5%B1%80%E5%9F%9F%E7%BD%91%E5%86%85%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BA%92%E8%AE%BF%E7%9A%84%E6%95%88%E7%8E%87%E9%97%AE%E9%A2%98/:0:3","tags":["运维","网络"],"title":"通过 DHCP Options 下发路由解决同局域网内服务器互访的效率问题","uri":"/2021/01/19/%E9%80%9A%E8%BF%87-dhcp-options-%E4%B8%8B%E5%8F%91%E8%B7%AF%E7%94%B1%E8%A7%A3%E5%86%B3%E5%90%8C%E5%B1%80%E5%9F%9F%E7%BD%91%E5%86%85%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BA%92%E8%AE%BF%E7%9A%84%E6%95%88%E7%8E%87%E9%97%AE%E9%A2%98/#新方案"},{"categories":null,"collections":null,"content":"2017年搭建的hexo博客，因腾讯云学生机即将过期，这几年用下来也觉得：似乎没什么必要续费云服务器 另外，人老了对npm这种一大坨恶心东西没什么好感，因此决定换用hugo，以此记录。 hexo迁移到hugo 腾讯云迁移到github pages 启用disqus评论 ","date":"2020-08-18","objectID":"/2020/08/18/migrate-to-hugo/:0:0","tags":null,"title":"Migrate to Hugo","uri":"/2020/08/18/migrate-to-hugo/#"},{"categories":null,"collections":null,"content":"UPDATE 2020-09-10 由于实在忍受不了github pages速度。。。。 于是： 又迁移到了腾讯云对象存储+CDN+免费HTTPS证书，按访问量收费，估计就。。。几块钱一个月吧，可以忽略不计- -# 使用腾讯云对象存储coscmd工具上传public文件夹，和之前github pages上传到github一样，也问题不大。。 ","date":"2020-08-18","objectID":"/2020/08/18/migrate-to-hugo/:0:1","tags":null,"title":"Migrate to Hugo","uri":"/2020/08/18/migrate-to-hugo/#update-2020-09-10"},{"categories":null,"collections":null,"content":"Vue项目使用Nginx部署并发布到子目录 默认Vue项目是以根目录来发布的，但是我们要有时候希望以子目录来做发布，那么就需要做一些修改，Vue项目本身的配置，包括Nginx也需要做一些配置修改。 ","date":"2019-07-11","objectID":"/2019/07/11/vue%E9%A1%B9%E7%9B%AE%E4%BD%BF%E7%94%A8nginx%E9%83%A8%E7%BD%B2%E5%B9%B6%E5%8F%91%E5%B8%83%E5%88%B0%E5%AD%90%E7%9B%AE%E5%BD%95/:0:0","tags":["Nginx","Vue"],"title":"Vue项目使用Nginx部署并发布到子目录","uri":"/2019/07/11/vue%E9%A1%B9%E7%9B%AE%E4%BD%BF%E7%94%A8nginx%E9%83%A8%E7%BD%B2%E5%B9%B6%E5%8F%91%E5%B8%83%E5%88%B0%E5%AD%90%E7%9B%AE%E5%BD%95/#vue项目使用nginx部署并发布到子目录"},{"categories":null,"collections":null,"content":"对Vue项目源码的修改 以下路径以vue-cli常见项目的文件结构来说明。 修改路由：router/index.js，添加base部分的代码。 1 2 3 4 5 6 7 8 9 10 function getAbsolutePath () { let path = location.pathname return path.substring(0, path.lastIndexOf(\u0026#39;/\u0026#39;) + 1) } export default new Router({ mode: \u0026#39;hash\u0026#39;, base: getAbsolutePath(), routes: [...] }) 修改配置：config/index.js 文件，对于打包路径的定义，只处理build，将assetsPublicPath: '/'修改为assetsPublicPath: './' 1 2 3 4 5 6 7 8 9 10 11 12 module.exports = { build: { // Template for index.html index: path.resolve(__dirname, \u0026#39;../dist/index.html\u0026#39;), // Paths assetsRoot: path.resolve(__dirname, \u0026#39;../dist\u0026#39;), assetsSubDirectory: \u0026#39;static\u0026#39;, assetsPublicPath: \u0026#39;./\u0026#39;, ... } } 修改build/utils.js对静态文件的处理，添加publicPath: '../../' 1 2 3 4 5 6 7 8 9 10 11 12 // Extract CSS when that option is specified // (which is the case during production build) if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, fallback: \u0026#39;vue-style-loader\u0026#39;, publicPath: \u0026#39;../../\u0026#39; }) } else { return [\u0026#39;vue-style-loader\u0026#39;].concat(loaders) } } ","date":"2019-07-11","objectID":"/2019/07/11/vue%E9%A1%B9%E7%9B%AE%E4%BD%BF%E7%94%A8nginx%E9%83%A8%E7%BD%B2%E5%B9%B6%E5%8F%91%E5%B8%83%E5%88%B0%E5%AD%90%E7%9B%AE%E5%BD%95/:1:0","tags":["Nginx","Vue"],"title":"Vue项目使用Nginx部署并发布到子目录","uri":"/2019/07/11/vue%E9%A1%B9%E7%9B%AE%E4%BD%BF%E7%94%A8nginx%E9%83%A8%E7%BD%B2%E5%B9%B6%E5%8F%91%E5%B8%83%E5%88%B0%E5%AD%90%E7%9B%AE%E5%BD%95/#对vue项目源码的修改"},{"categories":null,"collections":null,"content":"对Nginx配置的修改 当前项目结构如下: game ├── bxfr │ ├── index.html │ └── static │ ├── css │ ├── images │ ├── img │ ├── js │ └── mock └── fwjt ├── index.html └── static ├── css ├── images ├── img ├── js └── mock而我们要实现的目的是：使用my.server.name/bxfr/和my.server.name/fwjt/分别访问不同的项目。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 server { server_name my.server.name; access_log /var/log/nginx/game.access.log; error_log /var/log/nginx/game.error.log; # 这里root只能放在game这一层，因为下一层的子目录是不固定的 root /home/ubuntu/workspace/official-website/game/; # json文件使用mock来返回静态资源，这个block对于实现本文的目的并非必要 location ~ \\.json$ { rewrite ^/([^/]+).*/api/(.*) /$1/static/mock/$2 break; } location @vue { # 匹配不含/的首段，目的是拿出bxfr和fwjt rewrite ^/([^/]+).* /$1/index.html last; } # 使用try files来fallback到vue location / { index index.html; try_files $uri $uri/ @vue; } listen 80; ... } ","date":"2019-07-11","objectID":"/2019/07/11/vue%E9%A1%B9%E7%9B%AE%E4%BD%BF%E7%94%A8nginx%E9%83%A8%E7%BD%B2%E5%B9%B6%E5%8F%91%E5%B8%83%E5%88%B0%E5%AD%90%E7%9B%AE%E5%BD%95/:2:0","tags":["Nginx","Vue"],"title":"Vue项目使用Nginx部署并发布到子目录","uri":"/2019/07/11/vue%E9%A1%B9%E7%9B%AE%E4%BD%BF%E7%94%A8nginx%E9%83%A8%E7%BD%B2%E5%B9%B6%E5%8F%91%E5%B8%83%E5%88%B0%E5%AD%90%E7%9B%AE%E5%BD%95/#对nginx配置的修改"},{"categories":null,"collections":null,"content":"记一次celery worker hang debug 【写在前面】： 本文最终并没有debug出为什么卡住，虽然换了种方案解决了问题。 引入celery是为了调用京东api来做发货行为，以便提供给电商业务下快递单，然而在这个过程中，踩了一些坑（此文大概是2018年底的记录） 最初的配置，使用supervisor来管理celery进程，并且在代码更新之后，使用supervisorctl restart {$APP_NAME}来更新代码（celery并不支持gracefully reload，也暂时没有用其他更优雅的方案，待更深入的测试） ","date":"2019-07-09","objectID":"/2019/07/09/%E8%AE%B0%E4%B8%80%E6%AC%A1celery-worker-hang-debug/:0:0","tags":["Python"],"title":"记一次celery worker hang debug","uri":"/2019/07/09/%E8%AE%B0%E4%B8%80%E6%AC%A1celery-worker-hang-debug/#记一次celery-worker-hang-debug"},{"categories":null,"collections":null,"content":"发现问题 线上的celery总是一段时间之后，就没有接受新的请求，celery beat还在发消息，python代码也在发消息存到broker(redis)里面，但消息一直没被消费 ","date":"2019-07-09","objectID":"/2019/07/09/%E8%AE%B0%E4%B8%80%E6%AC%A1celery-worker-hang-debug/:0:1","tags":["Python"],"title":"记一次celery worker hang debug","uri":"/2019/07/09/%E8%AE%B0%E4%B8%80%E6%AC%A1celery-worker-hang-debug/#发现问题"},{"categories":null,"collections":null,"content":"debug过程 找出celery worker的pid， www-data 6329 0.0 0.6 157228 50640 ? S 2018 0:03 /home/ubuntu/.pyenv/versions/3.7.1/envs/ems-admin-api/bin/python /home/ubuntu/.pyenv/versions/ems-admin-api/bin/celery -A settings beat -s /tmp/celerybeat-schedule --pidfile= -l info www-data 10004 0.1 0.6 162456 53804 ? S Jan02 4:12 /home/ubuntu/.pyenv/versions/3.7.1/envs/ems-admin-api/bin/python /home/ubuntu/.pyenv/versions/ems-admin-api/bin/celery -A settings worker --autoscale=8,4 -l info www-data 18317 0.0 0.6 173032 56280 ? S Jan03 0:04 /home/ubuntu/.pyenv/versions/3.7.1/envs/ems-admin-api/bin/python /home/ubuntu/.pyenv/versions/ems-admin-api/bin/celery -A settings worker --autoscale=8,4 -l info www-data 18318 0.0 0.6 166688 50220 ? S Jan03 0:00 /home/ubuntu/.pyenv/versions/3.7.1/envs/ems-admin-api/bin/python /home/ubuntu/.pyenv/versions/ems-admin-api/bin/celery -A settings worker --autoscale=8,4 -l info ... 随便找一个worker的pid=10004，使用sudo strace -p 10004看看进程发生了什么事情，一直在recvfrom状态，等待接收数据 strace: Process 10004 attached recvfrom(23, 那么我们可以使用lsof工具来看23是个什么东西：sudo lsof -p 10004 | grep 23 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME python 10004 www-data 23u IPv4 81508763 0t0 TCP 172.16.0.17:47110-\u0026gt;172.16.0.11:6379 (ESTABLISHED)\u0026gt; 我们是用腾讯云的VPC来部署Redis/MySQL等服务，那么这里的ip`172.16.0.17`是我们的云服务器，而`172.16.0.11`是我们的`celery broker(redis)` 所以从上面的过程可以看出几个问题： 可以看出已经成功连接上redis broker，但并没有接收或者发送数据 celery worker的工作持续时间为4:12，就停止了 而从celery worker output等相关日志也没看出什么问题 那么。。。最后我是换了celery的启动参数而已。 # 在supervisor中的启动参数 # 原本卡死的参数 celery -A config worker --autoscale=8,4 # 后来的参数 celery -A config worker -P gevent -c 4也就是说，实际上我测试出来有变化的部分，就是把--autoscale=8,4去掉了，然后采用-P gevent -c 4来提供并发处理罢了。 至于autoscale为什么会挂，WHO KNOWS. ","date":"2019-07-09","objectID":"/2019/07/09/%E8%AE%B0%E4%B8%80%E6%AC%A1celery-worker-hang-debug/:0:2","tags":["Python"],"title":"记一次celery worker hang debug","uri":"/2019/07/09/%E8%AE%B0%E4%B8%80%E6%AC%A1celery-worker-hang-debug/#debug过程"},{"categories":null,"collections":null,"content":"pipenv使用指南 厌倦了使用virtualenv pyenv的时候，总是先要创建一个虚拟环境，然后激活虚拟环境再写代码 有时候就单纯想要写点scripts，那么pipenv这个开箱即用的虚拟环境显然更适合 确保当期不在任何虚拟环境中，或者说在系统的解释器中 pip install pipenv 然后其他安装命令，以pipenv代替pip 比如pipenv install -r requirements.txt会将pip的依赖文件requirements.txt转换成pipenv的版本管理格式文件Pipfile和Pipfile.lock 如果是空项目，那么直接pipenv install {third-party-lib} 默认将会为你创建当前目录加随机字母组成的虚拟环境，后续直接管理 位于 ~/.local/share/virtualenvs/{pwd_basename}-{random_stuff} 如果需要在vscode中支持pipenv的话，新增支持pipenv的虚拟目录位置 然后就可以愉快地选择pipenv的虚拟环境了 ","date":"2019-05-10","objectID":"/2019/05/10/pipenv%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/:0:0","tags":["Python"],"title":"pipenv使用指南","uri":"/2019/05/10/pipenv%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/#pipenv使用指南"},{"categories":null,"collections":null,"content":"背景 之前使用venv，大部分情况下并没有什么不好，配合virtualenvwrapper，用起来倒也顺手，如果没有Python版本切换需求的话。 日常开发机器使用的python是最新版，logging的时候，使用了f\u0026rsquo;i am a {var}\u0026lsquo;这种format语法，而这个特性是Python 3.6之后才有的，于是上线之后凉凉= = （生产环境的机器是Ubuntu 16.04，仅使用apt管理Python版本，于是装的版本实际上是3.5.2） 既然吃了一回亏，那么就赶紧解决问题。。。 题外话：貌似在Python的benchmark中，3.5、3.6、3.7中性能最差也是3.5，于是，抽空将生产机器改成用pyenv来管理版本 ","date":"2018-12-28","objectID":"/2018/12/28/pyenv%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/:0:1","tags":["Python"],"title":"pyenv使用指南","uri":"/2018/12/28/pyenv%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/#背景"},{"categories":null,"collections":null,"content":"食用步骤 参考pyenv-installer进行安装和配置 直接装需要的Python版本啦，比如pyenv install 3.7.1 如果安装过程中有任何问题，参考common build problems 如果安装也成功了，那么希望更改当前shell环境的Python版本来替换掉系统的版本，可以使用pyenv global 3.7.1 ","date":"2018-12-28","objectID":"/2018/12/28/pyenv%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/:0:2","tags":["Python"],"title":"pyenv使用指南","uri":"/2018/12/28/pyenv%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/#食用步骤"},{"categories":null,"collections":null,"content":"virtualenv使用 使用指定的Python版本创建虚拟环境pyenv virtualenv 3.7.1 myenv 启用虚拟环境 pyenv activate myenv 退出虚拟环境 source deactivate 进入项目目录自动启用虚拟环境，离开项目目录退出虚拟环境，需要在项目目录内 pyenv local myenv，会创建一个.python-version的文件，内容为虚拟环境的名字，则为myenv done, 希望食用快乐~ ","date":"2018-12-28","objectID":"/2018/12/28/pyenv%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/:0:3","tags":["Python"],"title":"pyenv使用指南","uri":"/2018/12/28/pyenv%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/#virtualenv使用"},{"categories":null,"collections":null,"content":"Python的日期实现/Linux发行版一般使用(tz database/Olson database)1 ","date":"2018-11-27","objectID":"/2018/11/27/python%E6%97%A5%E6%9C%9F%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86%E5%8F%8A%E5%A4%84%E7%90%86/:0:0","tags":["Python"],"title":"Python日期相关知识及处理","uri":"/2018/11/27/python%E6%97%A5%E6%9C%9F%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86%E5%8F%8A%E5%A4%84%E7%90%86/#"},{"categories":null,"collections":null,"content":"Python中的日期 一般使用pytz库来操作日期 ","date":"2018-11-27","objectID":"/2018/11/27/python%E6%97%A5%E6%9C%9F%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86%E5%8F%8A%E5%A4%84%E7%90%86/:0:1","tags":["Python"],"title":"Python日期相关知识及处理","uri":"/2018/11/27/python%E6%97%A5%E6%9C%9F%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86%E5%8F%8A%E5%A4%84%E7%90%86/#python中的日期"},{"categories":null,"collections":null,"content":"django中的时区使用问题 https://docs.djangoproject.com/en/2.1/topics/i18n/timezones/ Time zone support is disabled by default. To enable it, set USE_TZ = True in your settings file. Time zone support uses pytz, which is installed when you install Django. When support for time zones is enabled, Django stores datetime information in UTC in the database, uses time-zone-aware datetime objects internally, and translates them to the end user’s time zone in templates and forms. 仅能用于template和form，如果自己写api存和取要转换咯 设置settings.py # 使用时区设置，将tzinfo附加到datetime上面 UES_TZ = True # 设置localtime为上海 TIME_ZONE = \u0026#39;Asia/Chongqing\u0026#39; 以上设置使用的基础处理规则： 所有存入database的时间一律先转换为utc时间再存储，通过auto_now以及auto_now_add自动生成的时间会是utc时间，而且存入model的时间再取出之后的时区并不是naive的而是已经设定时区为utc的，例如从数据库中取出时间显示如下 使用django自带模块django.utils.timezone进行时间处理 比较好的应用实例，在建表时遇到取当前时间默认值时，之前有如下写法—— from django.utils.datetime_safe import datetime class X(models.Model): models.DateTimeField(null=False, default=datetime.utcnow)而现在可以用 from django.utils import timezone class X(models.Model): models.DateTimeField(null=False, default=timezone.now)特别注意设置USE_TZ = True之后，timezone.now()得到的datetime格式时间是aware的并且是UTC时间。以上两种方式都可以使用。 ","date":"2018-11-27","objectID":"/2018/11/27/python%E6%97%A5%E6%9C%9F%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86%E5%8F%8A%E5%A4%84%E7%90%86/:0:2","tags":["Python"],"title":"Python日期相关知识及处理","uri":"/2018/11/27/python%E6%97%A5%E6%9C%9F%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86%E5%8F%8A%E5%A4%84%E7%90%86/#django中的时区使用问题"},{"categories":null,"collections":null,"content":"后端对时间处理的一些原则 以下假设使用Django，且USE_TZ=True和TIME_ZONE='Asia/Shanghai' Django Template/Form，当启用USE_TZ并设置了正确的TIME_ZONE，会自动转成localtime 需要转换成localtime的场景 导出产物：比如excel 调用外部API查询：需要根据对方要求进行转换或者使用unix timestamp 数据库：统一使用UTC保存datetime，由对应的前端再做格式化行为 内部使用API的程序（浏览器、小程序、客户端等）： 提交给django的datetime query parameter，在使用ORM查询的时候，需要使用datetime.strptime将date string转成datetime，并且make_aware附加timezone info，否则查询时会有警告RuntimeWarning: DateTimeField 'xxxxxxx' received a naive datetime (2018-10-05 00:00:00) while time zone support is active. ，而由于启用了时区支持，所以当传入的naive datetime是'2018-10-5\u0026rsquo;到'2018-10-10\u0026rsquo;时，ORM的raw query语句内容会在查询前转换成timezone-aware\u0026lsquo;2018-10-4 16:00:00\u0026rsquo;到'2018-10-9 16:00:00\u0026rsquo;，这点和数据库是一致的 使用utc时间来处理，可以比较无痛处理各时区的数据，但比较麻烦的大概就是“反直觉”吧，毕竟总要算上当前时区 ","date":"2018-11-27","objectID":"/2018/11/27/python%E6%97%A5%E6%9C%9F%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86%E5%8F%8A%E5%A4%84%E7%90%86/:0:3","tags":["Python"],"title":"Python日期相关知识及处理","uri":"/2018/11/27/python%E6%97%A5%E6%9C%9F%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86%E5%8F%8A%E5%A4%84%E7%90%86/#后端对时间处理的一些原则"},{"categories":null,"collections":null,"content":"MySQL timezone的问题 Django 在使用CONVERT_TZ函数时，会使用 tz database 所定义的时区名，比如UTC、Asia/Shanghai来插入SQL，所以如果MySQL没有对应的timezone info database的数据，CONVERT_TZ函数会返回NULL值，这种情况下需要导入timezone database到MySQL里面。 可以到MySQL官网下载sql文件，解压导入，命令 mysql -u root -p mysql \u0026lt; sql_file_name ","date":"2018-11-27","objectID":"/2018/11/27/python%E6%97%A5%E6%9C%9F%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86%E5%8F%8A%E5%A4%84%E7%90%86/:0:4","tags":["Python"],"title":"Python日期相关知识及处理","uri":"/2018/11/27/python%E6%97%A5%E6%9C%9F%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86%E5%8F%8A%E5%A4%84%E7%90%86/#mysql-timezone的问题"},{"categories":null,"collections":null,"content":"为什么需要定时拨号？ 先来看一组数据 从命令sudo cat /var/log/messages | grep local的输出结果来看，IP地址基本上每隔一定时间就发生变化。 从命令show interface pppoe pppoe0 log里面可以找出类似的日志，大意是电信给我们的路由器发了terminate命令，让我们断开连接。 结论也就是： 广州电信，每次拨号维持时间为2875分钟/23小时55分钟，每次拨号维持这么长时间会被强行断网。 时间刚好是9点左右，每隔两天会减少5分钟，也就是。。。如果我周末这个时间点在家玩游戏，然后刚好碰上了，给我来个断网，呵呵 ","date":"2018-06-29","objectID":"/2018/06/29/ubnt-er-x-pppoe%E5%AE%9A%E6%97%B6%E9%87%8D%E6%96%B0%E6%8B%A8%E5%8F%B7/:0:1","tags":["Router","Ubnt"],"title":"Ubnt ER-X pppoe定时重新拨号","uri":"/2018/06/29/ubnt-er-x-pppoe%E5%AE%9A%E6%97%B6%E9%87%8D%E6%96%B0%E6%8B%A8%E5%8F%B7/#为什么需要定时拨号"},{"categories":null,"collections":null,"content":"解决方案 既然知道电信有这么蛋疼的设定，那么我们完全可以在不使用网络的情况下主动断开并重连来避开这个问题。 具体使用命令主要是下面两个： 断开pppoe disconnect interface pppoe0 连接pppoe进行拨号 connect interface pppoe0 那么如何定时去执行呢？ ERX运行的系统基于Linux，那么第一个想到的方案就是使用crontab来跑定时任务，而在相当长的一段时间也是这样干的（路由器固件一般一两个月更新一个版本，除了更新版本，就没重启过路由了。。。） 直到，最近更新了路由器固件，crontab设置被清空了（这是固件设定，需要经过特定的方式做更新才能免于灾难） 所以。。。最后写了个自定义的脚本，再使用系统授权的方式 task-scheduler 来执行这个脚本。 编辑文件: sudo vi /config/scripts/pppoe-redial.sh #!/bin/bash # 由于connect/disconnect命令都是alias，所以需要使用wrapper run=/opt/vyatta/bin/vyatta-op-cmd-wrapper $run disconnect interface pppoe0 sleep 10 $run connect interface pppoe0保存～ 赋予执行权限 sudo chmod +x /config/scripts/pppoe-redial.sh 通过task-scheduler设置定时任务 configure set system task-scheduler task redial crontab-spec \u0026#39;0 3 * * *\u0026#39; //每天凌晨3点执行，设置格式参考crontab set system task-scheduler task redial executable path /config/scripts/pppoe-redial.sh commit save完～ 其实，现在用WEB UI也能配置～ ","date":"2018-06-29","objectID":"/2018/06/29/ubnt-er-x-pppoe%E5%AE%9A%E6%97%B6%E9%87%8D%E6%96%B0%E6%8B%A8%E5%8F%B7/:0:2","tags":["Router","Ubnt"],"title":"Ubnt ER-X pppoe定时重新拨号","uri":"/2018/06/29/ubnt-er-x-pppoe%E5%AE%9A%E6%97%B6%E9%87%8D%E6%96%B0%E6%8B%A8%E5%8F%B7/#解决方案"},{"categories":null,"collections":null,"content":"最后的结论 不作死就不会死，去买那些TPLINK啊，定时重新拨号点几个UI按钮就完了，哪这么麻烦？ ","date":"2018-06-29","objectID":"/2018/06/29/ubnt-er-x-pppoe%E5%AE%9A%E6%97%B6%E9%87%8D%E6%96%B0%E6%8B%A8%E5%8F%B7/:0:3","tags":["Router","Ubnt"],"title":"Ubnt ER-X pppoe定时重新拨号","uri":"/2018/06/29/ubnt-er-x-pppoe%E5%AE%9A%E6%97%B6%E9%87%8D%E6%96%B0%E6%8B%A8%E5%8F%B7/#最后的结论"},{"categories":null,"collections":null,"content":"UPDATE 经过几天的观察，每天3点准时执行命令，18秒后拨号成功，至此定时重新拨号的问题算是解决了～ ","date":"2018-06-29","objectID":"/2018/06/29/ubnt-er-x-pppoe%E5%AE%9A%E6%97%B6%E9%87%8D%E6%96%B0%E6%8B%A8%E5%8F%B7/:0:4","tags":["Router","Ubnt"],"title":"Ubnt ER-X pppoe定时重新拨号","uri":"/2018/06/29/ubnt-er-x-pppoe%E5%AE%9A%E6%97%B6%E9%87%8D%E6%96%B0%E6%8B%A8%E5%8F%B7/#update"},{"categories":null,"collections":null,"content":"拿到一台服务器之后，不管是用一键包还是正常软件包管理安装，一些简单的安全配置还是必要的。 ","date":"2018-01-05","objectID":"/2018/01/05/nginx%E9%85%8D%E7%BD%AE%E7%9A%84%E4%B8%80%E4%BA%9B%E7%AE%80%E5%8D%95%E9%98%B2%E6%8A%A4/:0:0","tags":["Nginx"],"title":"Nginx配置的一些简单防护","uri":"/2018/01/05/nginx%E9%85%8D%E7%BD%AE%E7%9A%84%E4%B8%80%E4%BA%9B%E7%AE%80%E5%8D%95%E9%98%B2%E6%8A%A4/#"},{"categories":null,"collections":null,"content":"验证server_name 首先需要验证server_name，因为IP和域名是一对多的关系，除非针对性攻击，否则一般是用IP+端口来尝试扫描服务器上面运行的网站和服务以找出一些通用的漏洞。（脚本小子最爱） 下面以test.sukikaka.com为域名来说明： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 server { listen 80; server_name test.sukikaka.com; # 假设我的vhost放这个位置 root /data/vhost/test_sukikaka_com; index index.php; gzip on; gzip_types text/plain application/xml; gzip_min_length 1000; gzip_proxied no-cache no-store private expired auth; access_log /var/log/nginx/test.sukikaka.com_access.log; error_log /var/log/nginx/test.sukikaka.com_error.log warn; # 拒绝掉各种不希望被bot访问的 if ($http_user_agent ~* \u0026#34;qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot\u0026#34;) { return 403; } # static files location ~* ^.+.(ico|gif|jpg|jpeg|png|css|js|xml|txt|html|htm)$ { access_log off; expires max; } # 这是一个php程序的配置 location ~* .*.php$ { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # 以sock方式连接或者http fastcgi_pass unix:/var/run/php5-fpm.sock; # or 127.0.0.1:9000 #fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; } } ","date":"2018-01-05","objectID":"/2018/01/05/nginx%E9%85%8D%E7%BD%AE%E7%9A%84%E4%B8%80%E4%BA%9B%E7%AE%80%E5%8D%95%E9%98%B2%E6%8A%A4/:0:1","tags":["Nginx"],"title":"Nginx配置的一些简单防护","uri":"/2018/01/05/nginx%E9%85%8D%E7%BD%AE%E7%9A%84%E4%B8%80%E4%BA%9B%E7%AE%80%E5%8D%95%E9%98%B2%E6%8A%A4/#验证server_name"},{"categories":null,"collections":null,"content":"启用default规则 这点也很重要，deny掉任何不希望开放的路径，默认错误日志会在/var/log/nginx/error.log文件 错误具体会体现为access forbidden by rule 1 2 3 4 5 6 7 8 server { listen 80 default_server; listen [::]:80 default_server; location / { deny all; } } 基本上做完上面两点，你的网站对应的error log就只剩下比较正常的业务访问错误之类的信息了，其余被nginx拒绝掉的可以在error.log文件体现，如果发现某些IP段尝试访问不同的路径以寻求服务器上面的漏洞，那么可以针对性的ban掉这些IP。 ","date":"2018-01-05","objectID":"/2018/01/05/nginx%E9%85%8D%E7%BD%AE%E7%9A%84%E4%B8%80%E4%BA%9B%E7%AE%80%E5%8D%95%E9%98%B2%E6%8A%A4/:0:2","tags":["Nginx"],"title":"Nginx配置的一些简单防护","uri":"/2018/01/05/nginx%E9%85%8D%E7%BD%AE%E7%9A%84%E4%B8%80%E4%BA%9B%E7%AE%80%E5%8D%95%E9%98%B2%E6%8A%A4/#启用default规则"},{"categories":null,"collections":null,"content":"本文围绕端口讲解网络流量流向中可能出现的各种问题，水平有限，仅当入门篇。 ","date":"2017-10-30","objectID":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/:0:0","tags":["网络"],"title":"网络基础-端口连通测试与排查","uri":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/#"},{"categories":null,"collections":null,"content":"访问端：怎么确认目标设备对应端口已经开启 常规方法： tcpping 端口open状态 telnet 端口可连接 其他tcp方案 本地端口没有被运营商or其他工具封锁，比如邮件的25端口 如果以上外部方案都发现并不能连接到目标端口，该那么怎么排查问题 SSH登录目标主机 假设我们想了解为什么80端口没连通，先确认80端口是否正在服务 sudo netstat -anp | grep :80 从结果可以看出主机已经开启了80端口，且服务的程序是Nginx ","date":"2017-10-30","objectID":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/:0:1","tags":["网络"],"title":"网络基础-端口连通测试与排查","uri":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/#访问端怎么确认目标设备对应端口已经开启"},{"categories":null,"collections":null,"content":"被访问端：如何确认有请求访问 以下假设访问端和被访问端使用公网访问。 ifconfig找出公网流量交换的网卡，比如下图我的是eth0 监听网卡eth0上的80端口的流量 sudo tcpdump -i eth0 port 80 开启监听 另外一台机器使用tcpping来访问tcpping 45.34.167.101 80 观察tcpdump结果 结果是连通的，可以清晰看到tcp3次握手的sequence code 接下来使用sudo service nginx stop关停nginx的80端口，然后再次做tcpping 端口已经关闭了，tcpdump依然可以看到类似上面的tcp握手请求 ","date":"2017-10-30","objectID":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/:0:2","tags":["网络"],"title":"网络基础-端口连通测试与排查","uri":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/#被访问端如何确认有请求访问"},{"categories":null,"collections":null,"content":"被访问端：怎么确认端口是可达的（未被封锁） 那么假设防火墙拦截对80端口的请求呢？我们使用iptables对INPUT的流量全部采取DROP处理 sudo iptables -A INPUT -p tcp --dport 80 -j DROP 访问端再次使用tcpping发起请求，可以在被访问端tcpdump看到请求，但无法成功建立tcp连接 访问端看到的请求结果 -\u0026gt; timeout，network packet只进不出，被DROP了 弄完之后我把iptables删掉啦，不然网站都开不动啦- -# sudo iptables -D INPUT -p tcp --dport 80 -j DROP ","date":"2017-10-30","objectID":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/:0:3","tags":["网络"],"title":"网络基础-端口连通测试与排查","uri":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/#被访问端怎么确认端口是可达的未被封锁"},{"categories":null,"collections":null,"content":"排查其他因素 比如在traceroute过程某一跳中断了，可能是路由过程中被某个节点掐断了，参考#不可抗力因素 timeout和closed可是不用的状态噢~ ","date":"2017-10-30","objectID":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/:0:4","tags":["网络"],"title":"网络基础-端口连通测试与排查","uri":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/#排查其他因素"},{"categories":null,"collections":null,"content":"相关软件 ","date":"2017-10-30","objectID":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/:1:0","tags":["网络"],"title":"网络基础-端口连通测试与排查","uri":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/#相关软件"},{"categories":null,"collections":null,"content":"tcpping 安装 wget http://www.vdberg.org/~richard/tcpping sudo mv tcpping /usr/bin/ sudo chmod +x /usr/bin/tcpping 用的比较多的就是用来测试端口是否开启啦~ 其他玩法自己研究下咯 ","date":"2017-10-30","objectID":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/:1:1","tags":["网络"],"title":"网络基础-端口连通测试与排查","uri":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/#tcpping"},{"categories":null,"collections":null,"content":"tcpdump sudo apt-get install tcpdump ","date":"2017-10-30","objectID":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/:1:2","tags":["网络"],"title":"网络基础-端口连通测试与排查","uri":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/#tcpdump"},{"categories":null,"collections":null,"content":"traceroute 假设用来查看路由跳转情况咯，比如192.168.0.10的机器要访问192.168.2.1，若没有在网关配置路由表或192.168.2.1网关防火墙拒绝，则无法访问成功。 ","date":"2017-10-30","objectID":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/:1:3","tags":["网络"],"title":"网络基础-端口连通测试与排查","uri":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/#traceroute"},{"categories":null,"collections":null,"content":"ip(Network Debugging) ","date":"2017-10-30","objectID":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/:1:4","tags":["网络"],"title":"网络基础-端口连通测试与排查","uri":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/#ipnetwork-debugging"},{"categories":null,"collections":null,"content":"iptables 端口限制（为了安全，只开放必要的外部端口） IP请求限制（配合fail2ban食用更佳） 请求频率限制（限制单个IP没秒请求次数） 带宽速度限制 局域网多个服务器共享一个出口带宽（比如购买了多台云服务器，但只有一台有公网出口，可以使用SNAT达到访问公网的目的，节省费用） 局域网堡垒机设置（比如购买了多台云服务器，但只有一台有公网出口，同时又想在外部直接一次SSH登录就进去目标服务器主机，可以使用DNAT及端口转发达到目的） ","date":"2017-10-30","objectID":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/:1:5","tags":["网络"],"title":"网络基础-端口连通测试与排查","uri":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/#iptables"},{"categories":null,"collections":null,"content":"nping 比上面的tcpping更好用，语法如下： sudo nping --tcp -p {port} {host} ","date":"2017-10-30","objectID":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/:1:6","tags":["网络"],"title":"网络基础-端口连通测试与排查","uri":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/#nping"},{"categories":null,"collections":null,"content":"其他抓包分析工具 Charles Fiddler Proxifier Wireshark ","date":"2017-10-30","objectID":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/:1:7","tags":["网络"],"title":"网络基础-端口连通测试与排查","uri":"/2017/10/30/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80-%E7%AB%AF%E5%8F%A3%E8%BF%9E%E9%80%9A%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%8E%92%E6%9F%A5/#其他抓包分析工具"},{"categories":null,"collections":null,"content":"大背景 说需求不讲背景就是耍流氓。 \u0026mdash;\u0026mdash;\u0026mdash;\u0026ndash; by 一个被虐的码农 那么，背景是这样的，公司现有的测试业务情况如实交代： 局域网自建mongo数据库，用于业务的测试环境数据（IP：192.168.2.100，电信公网IP 200.201.202.203，标记为服务器A） 公网阿里云ECS(IP: 100.101.102.103，标记为服务器B），用于外网测试环境代码的运行，通过服务器A的公网IP来连接mongo数据库 阿里云DNS配置A解析记录 dev.xxx.com 100.101.102.103 在脱离公司的公网环境，需要能正常访问dev.xxx.com的服务 ","date":"2017-08-31","objectID":"/2017/08/31/%E4%B8%80%E7%A7%8D%E6%9C%89%E8%B6%A3%E7%9A%84%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F/:0:1","tags":["运维","网络"],"title":"一种有趣的测试环境部署方式","uri":"/2017/08/31/%E4%B8%80%E7%A7%8D%E6%9C%89%E8%B6%A3%E7%9A%84%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F/#大背景"},{"categories":null,"collections":null,"content":"问题来了 运营人员抱怨各种测试服务反应很慢。噢？那么我们来研究下网络数据走向和对应的时间消耗咯 运营人员使用测试服务-\u0026gt;DNS解析dev.xxx.com-\u0026gt;请求服务器B-\u0026gt;通过服务器A的公网IP连接到mongo数据库-\u0026gt;上传数据回服务器B-\u0026gt;返回数据给和服务器A同一个公网出口的App（哇，这链条长的很开心） 通过配置PHP fpm slowlog得知，发现实际上时间消耗都花在了mongo相关的连接上面了，为什么呢？？？ ","date":"2017-08-31","objectID":"/2017/08/31/%E4%B8%80%E7%A7%8D%E6%9C%89%E8%B6%A3%E7%9A%84%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F/:0:2","tags":["运维","网络"],"title":"一种有趣的测试环境部署方式","uri":"/2017/08/31/%E4%B8%80%E7%A7%8D%E6%9C%89%E8%B6%A3%E7%9A%84%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F/#问题来了"},{"categories":null,"collections":null,"content":"分析问题 我们用的电信家用宽带，100M下载带宽，上传也就那么4M，完全不能看啊，稍微查询一个大一点的数据集，传输时间够喝一壶了，而且这么4M带宽，还要服务于公司员工正常的上网需求，那么降低这里的上传带宽使用也是很有必要的。 ","date":"2017-08-31","objectID":"/2017/08/31/%E4%B8%80%E7%A7%8D%E6%9C%89%E8%B6%A3%E7%9A%84%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F/:0:3","tags":["运维","网络"],"title":"一种有趣的测试环境部署方式","uri":"/2017/08/31/%E4%B8%80%E7%A7%8D%E6%9C%89%E8%B6%A3%E7%9A%84%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F/#分析问题"},{"categories":null,"collections":null,"content":"选定方案 so，找到问题了，光说有什么用，得有解决方案啊 把数据库也扔到外网去，那么对整个公司局域网来说，主要消耗只有对公网服务器B的请求下行数据，然而mongo对硬件消耗有点大，作为一个测试环境来讲，升级硬件配置或者再开一台服务器难免有点资源浪费，退而求其次，合理利用局域网服务器做mongo服务才是正路 服务器A硬件配置是强于ECS好多倍的，不要浪费了，那么就在服务器A上面搞事吧 通过分析上面的请求路径，那么我们可以把服务器A的公网上传拦截掉，怎么拦截呢？从DNS上面动手，于是请求路径会变成\u0010：APP-\u0026gt;解析dev.xxx.com-\u0026gt;请求服务器A（192.168.2.100）-\u0026gt;服务器A的程序请求localhost的数据库-\u0026gt;返回数据给程序-\u0026gt;返回给同一个局域网的运营测试人员 这样一来，速度提升的有点可怕，运营人员再也不腰痛了 ","date":"2017-08-31","objectID":"/2017/08/31/%E4%B8%80%E7%A7%8D%E6%9C%89%E8%B6%A3%E7%9A%84%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F/:0:4","tags":["运维","网络"],"title":"一种有趣的测试环境部署方式","uri":"/2017/08/31/%E4%B8%80%E7%A7%8D%E6%9C%89%E8%B6%A3%E7%9A%84%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F/#选定方案"},{"categories":null,"collections":null,"content":"解决问题 既然有初步方案了，那么怎么解决？ 那么需要使用“提速”的运营人员，可以通过配置HOST来实现 dev.xxx.com 解析成 192.168.2.100，如果只有PC平台的产品，倒也不失为一种选择 移动设备怎么办？Android不root，iOS不root没法玩啊，除非这些测试机器允许以某种方式“模拟配置host”，比如Android读取sd卡某个文件，若定义了解析数据，则以解析结果为准，需要预埋代码，改起来也麻烦，一点也不优雅 移动设备实在没办法改呢？那我配置代理咯，代理设备请求到能改HOST的PC设备，也是麻烦 既然这么蛋疼，那我配置一个DNS服务器好了，一番搜索之后，unbound这个软件上场了，配置一个DNS服务器，使用标准端口53，将局域网所有需要”提速“的设备首选DNS改成192.168.2.100即可 本着优化应该对使用者透明的原则，把上面这个配置DNS的步骤也省了，直接用DHCP服务器返回192.168.2.100作为首选DNS 断一下网，重新连接，刷新页面，一切只如初见，那么美好~ ","date":"2017-08-31","objectID":"/2017/08/31/%E4%B8%80%E7%A7%8D%E6%9C%89%E8%B6%A3%E7%9A%84%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F/:0:5","tags":["运维","网络"],"title":"一种有趣的测试环境部署方式","uri":"/2017/08/31/%E4%B8%80%E7%A7%8D%E6%9C%89%E8%B6%A3%E7%9A%84%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F/#解决问题"},{"categories":null,"collections":null,"content":"题外话 有人说，为了性价比，透明解决问题，为何不把所有服务都放在局域网的服务器A上面，连买ECS的钱都省了。。。 骚年，你还是太年轻 电信运营商怎能允许家用宽带用来做服务器提供服务这种行为，那么谁购买他高贵的企业专线带宽呢？于是我们家用宽带的80端口、8080端口默认都是被封了。 就算运营商不搞事，国家要求所有IDC必须只对有域名备案信息的域名才能提供正常的服务，就算配置了解析，在访问到具体的IP的时候，也是一样不能正常访问你的业务，从这个角度来讲，电信运营商封锁这两个端口也算是为了规避备案问题。 改端口也不是不行，然而综合考虑，改端口方案导致各个业务都需要做额外的配置修改，还是买个ECS做外网测试业务简单粗暴 那么其实除了上面的DNS方案，还有没有其他方案？答案是有的，理论上通过配置路由表SNAT，把对服务器B（100.101.102.103）的流量请求转发到服务器A192.168.2.100，然而该方案似乎有点一刀切，不够灵活，还是留着DNS，需要这种访问链路优化的话，配置首选DNS服务器为192.168.2.100，不需要的时候或者想强行访问服务器B的逻辑，那么只需要配置其他公用DNS即可。 ","date":"2017-08-31","objectID":"/2017/08/31/%E4%B8%80%E7%A7%8D%E6%9C%89%E8%B6%A3%E7%9A%84%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F/:0:6","tags":["运维","网络"],"title":"一种有趣的测试环境部署方式","uri":"/2017/08/31/%E4%B8%80%E7%A7%8D%E6%9C%89%E8%B6%A3%E7%9A%84%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F/#题外话"},{"categories":null,"collections":null,"content":"UPDATE 2017-09-05 由于在实际使用过程中（大概1个多月的持续时长），发现对于不甚了解原理的小伙伴来讲，有额外的理解成本，业务也准备上HTTPS访问，那么就又来搞事吧，于是改为下面的方式： 仅保留局域网服务器A，全部使用Let\u0026rsquo;s Encrypt部署HTTPS访问（电信没封443端口），局域网访问可以使用HTTP或者HTTPS，而公网访问就只有HTTPS能通啦- - unbound DNS配置依然保留 路由表在另外一个服务器上面，暂时未变动 ","date":"2017-08-31","objectID":"/2017/08/31/%E4%B8%80%E7%A7%8D%E6%9C%89%E8%B6%A3%E7%9A%84%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F/:0:7","tags":["运维","网络"],"title":"一种有趣的测试环境部署方式","uri":"/2017/08/31/%E4%B8%80%E7%A7%8D%E6%9C%89%E8%B6%A3%E7%9A%84%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F/#update-2017-09-05"},{"categories":null,"collections":null,"content":"工具链 编程语言 Java/Kotlin C/C++(NDK方向，源码阅读) SQL(DB) HTML/JS(Hybrid/Web App) 操作系统 Linux/macOS/Windows IDE: Android Studio为主 Eclipse 网络调试 代理请求劫持与分析、重放：Charles/Wireshark/Fiddler 接口请求：Postman 内存分析 Eclipse MAT Plugin Android Studio Monitors LeakCanary 综合分析（CPU、Network、Memory、GPU)： Android Studio Monitors Android Tools Method Tracer ui hierarchy viewer ui automator viewer draw9patch 代码管理 版本管理 Git SVN Code Review: Gerrit Git托管系统比如(github/gitlab/oschina/coding)的Pull Request Android Studio VCS git log 团队协作 Teambition Tower git issues 编译工具 Gradle 持续集成、分发 Jenkins Travis CI 早期测试分发 fir.im 蒲公英 ","date":"2017-08-29","objectID":"/2017/08/29/android%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91%E6%8A%80%E8%83%BD%E5%9B%BE%E8%B0%B1/:1:0","tags":["Android"],"title":"Android应用开发技能图谱","uri":"/2017/08/29/android%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91%E6%8A%80%E8%83%BD%E5%9B%BE%E8%B0%B1/#工具链"},{"categories":null,"collections":null,"content":"App初级入门 基础组件 Activity (launchmode/category) Service Content Provider Broadcast Receiver Intent \u0026amp; Intent Filter Manifest Permission UI View/ViewGroup Widgets Resources(res/assets) Animations Connectivity WiFi/AP Cellular Network(connectivity changed) Bluetooth MultiMedia Audio Encoding/Decoding Video Encoding/Decoding Camera Recording Gallery LBS GPS AGPS(Cellular Network) Map SDK ","date":"2017-08-29","objectID":"/2017/08/29/android%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91%E6%8A%80%E8%83%BD%E5%9B%BE%E8%B0%B1/:2:0","tags":["Android"],"title":"Android应用开发技能图谱","uri":"/2017/08/29/android%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91%E6%8A%80%E8%83%BD%E5%9B%BE%E8%B0%B1/#app初级入门"},{"categories":null,"collections":null,"content":"App中级进阶 Process/Thread/Runnable Process AIDL Handler/Looper/MessageQueue Loader/AsyncTask UI优化 ANR: Broadcast/Input Events UI Layout 层次优化 Bitmap 分辨率裁剪 内存管理 Soft/Weak References 内存分析、泄露检测 网络优化 网络请求压缩(gzip等) 善用HTTP协议，使用PATCH等 流量使用 根据网络类型选择不同分辨率图片素材 使用缓存 测试 Android Studio使用不同Product Flavor提供测试方案 UI模拟测试 API单元测试 ","date":"2017-08-29","objectID":"/2017/08/29/android%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91%E6%8A%80%E8%83%BD%E5%9B%BE%E8%B0%B1/:3:0","tags":["Android"],"title":"Android应用开发技能图谱","uri":"/2017/08/29/android%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91%E6%8A%80%E8%83%BD%E5%9B%BE%E8%B0%B1/#app中级进阶"},{"categories":null,"collections":null,"content":"App高级提升 知其所以然 Activity ActivityManager 启动流程分析 生命周期回调应用 与View/Window的关系 与Fragment如何结合、两者的关系 View/Window WindowManager View渲染处理流程 View事件分发处理流程 View与Window的关系，PopupWindow? 编译打包 javac/dex/art aapt处理流程 gradle productflavor合并/app与lib工程合并 apktool逆向 热修复/classloader 代码混淆、资源压缩、加密 Hybrid App 与Native App异同 通过JS Bride互相调用 主流跨平台框架：PhoneGap/Cordova/React Native 架构能力 架构设计 MVC/MVP/MVVM Clean Architecture 关注点分离 App框架 逻辑分包 业务分层 设计模式 JVM/DVM ART/AOT GC Bytecode/dex JVM内存模型 自动化编译测试 Jenkins/Travis CI UIAutomator Espresso Monkey Runner ","date":"2017-08-29","objectID":"/2017/08/29/android%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91%E6%8A%80%E8%83%BD%E5%9B%BE%E8%B0%B1/:4:0","tags":["Android"],"title":"Android应用开发技能图谱","uri":"/2017/08/29/android%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91%E6%8A%80%E8%83%BD%E5%9B%BE%E8%B0%B1/#app高级提升"},{"categories":null,"collections":null,"content":"延伸通用基础 响应式编程 RxJava \u0026amp; RxAndroid \u0026amp; RxBinding 网络知识 TCP/IP HTTP Socket 抓包调试 ","date":"2017-08-29","objectID":"/2017/08/29/android%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91%E6%8A%80%E8%83%BD%E5%9B%BE%E8%B0%B1/:5:0","tags":["Android"],"title":"Android应用开发技能图谱","uri":"/2017/08/29/android%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91%E6%8A%80%E8%83%BD%E5%9B%BE%E8%B0%B1/#延伸通用基础"},{"categories":null,"collections":null,"content":"服务器配置 工欲善其事必先利其器，如果都不知道什么时候可能会产生日志，不知道哪里能查到错误日志，那么谈何排查？ 启用PHP错误配置[PHP程序运行错误日志]: /etc/php/*/fpm/php.ini （以FPM为例，cli同理） log_errors = On error_log = /tmp/php_errors.log 启用fpm errors[这个是FPM本身的错误日志，不是服务的PHP程序的错误日志]： /etc/php/*/fpm/php-fpm.ini error_log = /var/log/php-fpm.log 启用FPM workers slowlog/errors: /etc/php//fpm/pool.d/.conf ; 因为PHP程序是以fpm worker的形式运行的，所以要获得输出需要启用worker output catch_workers_output = yes ; PHP 程序代码慢查询日志，比如代码中连接了数据库做查询，当超过一定时间则增加一条slowlog slowlog = /var/log/$pool.log.slow ; 此处定义多长时间为慢查询，一般5s已经很丧心病狂了 request_slowlog_timeout = 5s修改完之后，使用sudo php-fpm -t做测试，一般会有的错误是，错误日志指定的路径不对，或者没权限写入，修改成其他可以写入的路径即可 ","date":"2017-08-24","objectID":"/2017/08/24/php%E9%94%99%E8%AF%AF%E6%8E%92%E6%9F%A5/:0:1","tags":["运维","PHP"],"title":"PHP错误排查","uri":"/2017/08/24/php%E9%94%99%E8%AF%AF%E6%8E%92%E6%9F%A5/#服务器配置"},{"categories":null,"collections":null,"content":"一些错误示例 FPM Slow log，该优化代码啦！！！ PHP Error，该修BUG啦！！！ ","date":"2017-08-24","objectID":"/2017/08/24/php%E9%94%99%E8%AF%AF%E6%8E%92%E6%9F%A5/:0:2","tags":["运维","PHP"],"title":"PHP错误排查","uri":"/2017/08/24/php%E9%94%99%E8%AF%AF%E6%8E%92%E6%9F%A5/#一些错误示例"},{"categories":null,"collections":null,"content":"NOTE 看了还不赶紧配置日志、看日志改代码的同学，你懂的。 ","date":"2017-08-24","objectID":"/2017/08/24/php%E9%94%99%E8%AF%AF%E6%8E%92%E6%9F%A5/:0:3","tags":["运维","PHP"],"title":"PHP错误排查","uri":"/2017/08/24/php%E9%94%99%E8%AF%AF%E6%8E%92%E6%9F%A5/#note"},{"categories":null,"collections":null,"content":"为什么要用Webhooks来更新代码 服务端的代码，不希望直接在服务器上面做更改，需要有中央仓库做托管管理，也利于协作 某些情况下，不希望给开发人员服务器ssh登录权限 开发时，希望得到更快的上线部署速度，享受git commit \u0026amp; git push \u0026amp; refresh的快感 ","date":"2017-05-27","objectID":"/2017/05/27/%E4%BD%BF%E7%94%A8gitlab-webhooks%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2%E4%BB%A3%E7%A0%81/:0:1","tags":["运维"],"title":"使用Gitlab Webhooks自动部署代码","uri":"/2017/05/27/%E4%BD%BF%E7%94%A8gitlab-webhooks%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2%E4%BB%A3%E7%A0%81/#为什么要用webhooks来更新代码"},{"categories":null,"collections":null,"content":"Webhooks部署时需要考虑的一些因素 现有github，gitlab，oschina等一些托管基本都支持Webhooks，原理都是利用git hooks来做的拓展 什么情况下需要更新代码？根据commit message？根据branch? 更新代码时的执行身份？由什么用户来执行git？ ","date":"2017-05-27","objectID":"/2017/05/27/%E4%BD%BF%E7%94%A8gitlab-webhooks%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2%E4%BB%A3%E7%A0%81/:0:2","tags":["运维"],"title":"使用Gitlab Webhooks自动部署代码","uri":"/2017/05/27/%E4%BD%BF%E7%94%A8gitlab-webhooks%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2%E4%BB%A3%E7%A0%81/#webhooks部署时需要考虑的一些因素"},{"categories":null,"collections":null,"content":"设置Linux服务器 前提：当前已经登录root用户或者具有sudo权限的用户 确认即将用于执行git命令的用户，假定我们新增一个用户名git，专门用于跑git命令，那么执行 sudo adduser git，并设置密码 接下来，将git用户添加到sudo组：sudo adduser git sudo[此步骤非必须] 假定项目代码放在/www下面，且Owner是git，那么执行sudo mkdir /www \u0026amp;\u0026amp; sudo chown -R git:git /www 由于我们的Webhooks代码是用Nginx + PHP-FPM部署的，那么确认下PHP脚本的运行用户情况：ps aux | grep php-fpm， 确认www-data为我们的运行用户 将www-data加到git用户组：sudo usermod -aG git www-data 给www-data用户不需要密码就能切换到git用户，并且用git用户的身份执行/usr/bin/git命令，修改sudoers：sudo vim /etc/sudoers，添加一行配置：www-data ALL=(git) NOPASSWD: /usr/bin/git 允许同组用户新增文件时继承原有文件夹权限位：sudo chmod -R g+s /www[此步骤非必须] 由于我们希望无密码自动拉取代码，那么gitlab代码也是使用ssh方式来配置连接方式的，且hooks被触发时是通过www-data切换成git用户来执行/usr/bin/git命令，那么实际上git pull等命令使用的SSH key是git用户的SSH key，确保已经将git用户的/home/git/.ssh/id_rsa.pub文件的内容设置到gitlab项目中 ","date":"2017-05-27","objectID":"/2017/05/27/%E4%BD%BF%E7%94%A8gitlab-webhooks%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2%E4%BB%A3%E7%A0%81/:0:3","tags":["运维"],"title":"使用Gitlab Webhooks自动部署代码","uri":"/2017/05/27/%E4%BD%BF%E7%94%A8gitlab-webhooks%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2%E4%BB%A3%E7%A0%81/#设置linux服务器"},{"categories":null,"collections":null,"content":"实现Webhooks项目的代码 请参考gitlab-php-webhooks，具体逻辑请看代码注释 设置gitlab的Webhooks 项目文件夹权限设置： 项目生成的日志文件权限情况： nginx配置参考 server { listen 80; root /www/push-gitlab; index index.php index.html index.htm; server_name gitlab.server.com; #location ~ \\.php$ { location = /githooks.php { fastcgi_split_path_info ^(.+\\.php)(/.+)$; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass unix:/var/run/php5-fpm.sock; include fastcgi_params; } # rewrite请求参数，不直接暴露服务器文件路径 if (!-e $request_filename) { rewrite /checkout/(.*)$ /githooks.php?name=$1 last; break; } } hooks访问URL会是这样的：http://gitlab.server.com/checkout/gitlab-php-webhooks，将它和上面产生的token一同填入gitlab项目配置，然后尝试一下吧~ 在服务端tailf日志文件，可以观察到有类似的日志输出则是成功拉取代码啦，如果没有日志文件产生，或者git log发现也没有更新代码，那么多半是权限问题了 ","date":"2017-05-27","objectID":"/2017/05/27/%E4%BD%BF%E7%94%A8gitlab-webhooks%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2%E4%BB%A3%E7%A0%81/:0:4","tags":["运维"],"title":"使用Gitlab Webhooks自动部署代码","uri":"/2017/05/27/%E4%BD%BF%E7%94%A8gitlab-webhooks%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2%E4%BB%A3%E7%A0%81/#实现webhooks项目的代码"},{"categories":null,"collections":null,"content":"准备工作 安装docker、docker-compose 更改docker镜像源地址，加速访问 ","date":"2017-05-25","objectID":"/2017/05/25/%E6%89%93%E9%80%A0%E5%9F%BA%E4%BA%8Edocker%E7%9A%84ubuntu-14.04--php-fpm--nginx%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83/:0:1","tags":["运维","docker"],"title":"打造基于Docker的Ubuntu 14.04 + PHP-FPM + Nginx运行环境","uri":"/2017/05/25/%E6%89%93%E9%80%A0%E5%9F%BA%E4%BA%8Edocker%E7%9A%84ubuntu-14.04--php-fpm--nginx%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83/#准备工作"},{"categories":null,"collections":null,"content":"创建Dockerfile 在用户目录下创建docker项目文件夹 $ mkdir -p ~/docker \u0026amp;\u0026amp; cd ~/docker 创建Dockerfile $ vim Dockerfile 由于我们是基于Ubuntu14.04做的镜像，所以定义好官方Ubuntu地址即可，在Dockerfile插入:FROM ubuntu:trusty，保存Dockerfile，然后运行docker build -t ubuntu:14.04-php-nginx .，如果你是第一次运行，需要从上面修改的docker源拉取ubuntu的镜像，会比较久。 我们用docker images来看结果，会有两个镜像，一个是拉下来的ubuntu:trusty，一个是我们定制的镜像: ubuntu:14.04-php-nginx 现在我们已经拥有一个本地image，使用交互模式启动容器准备进行定制 docker run -t -i ubuntu:14.04-php-nginx /bin/bash 把它当成一台装了Ubuntu的虚拟机，该怎么样怎么样，我们准备安装PHP-FPM和Nginx及一些PHP扩展，那么正常命令是这样的：(容器以root用户登录，且默认没有sudo命令，则不需要sudo) apt-get update apt-get install -y nginx nginx php5 php5-fpm php-pear php5-dev php5-redis php5-gd php5-curl php5-mcrypt imagemagick php5-imagick supervisor pecl install mongo echo \u0026#39;extension=mongo.so\u0026#39; \u0026gt; /etc/php5/mods-available/mongo.ini ln -s /etc/php5/mods-available/mongo.ini /etc/php5/fpm/conf.d/20-mongo.ini 漫长的等待时间之后，安装完了 7. 由于默认的系统是UTC时间，我们将它改为CST rm /etc/localtime echo \u0026#34;Asia/Shanghai\u0026#34; \u0026gt; /etc/timezone dpkg-reconfigure -f noninteractive tzdata成功之后会输出当前的local time 接下来我们不需要再安装其他软件了，那么可以删掉没有必要的apt缓存：rm -rf /var/lib/apt/list/* 由于docker是无状态的，且启动时只能保留一条CMD来执行我们要启动的命令，但是我们需要FPM和Nginx都一起启动，怎么办？于是我们通过supervisor来控制，那么我们需要配置supervisor： supervisord配置：/etc/supervisor/conf.d/supervisord.conf [supervisord] nodaemon=true nginx配置：/etc/supervisor/conf.d/nginx.conf [program:nginx] command=/usr/sbin/nginx autostart=true autorestart=true priority=10\u0026#39;fpm配置：/etc/supervisor/conf.d/php-fpm.conf [program:php-fpm] command=/usr/sbin/php5-fpm autostart=true autorestart=true priority=5\u0026#39; 好了，需要的东西都安装配置了，接下来就剩下启动supervisor了，我们把这个命令放在Dockerfile来启动CMD [\u0026quot;/usr/bin/supervisord\u0026quot;, \u0026quot;-n\u0026quot;, \u0026quot;-c\u0026quot;, \u0026quot;/etc/supervisor/supervisord.conf\u0026quot;] ","date":"2017-05-25","objectID":"/2017/05/25/%E6%89%93%E9%80%A0%E5%9F%BA%E4%BA%8Edocker%E7%9A%84ubuntu-14.04--php-fpm--nginx%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83/:0:2","tags":["运维","docker"],"title":"打造基于Docker的Ubuntu 14.04 + PHP-FPM + Nginx运行环境","uri":"/2017/05/25/%E6%89%93%E9%80%A0%E5%9F%BA%E4%BA%8Edocker%E7%9A%84ubuntu-14.04--php-fpm--nginx%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83/#创建dockerfile"},{"categories":null,"collections":null,"content":"完整的文件是这样子的 #FROM ubuntu:14.04.05 FROM ubuntu:trusty # 更换apt源 RUN sed -i \u0026#39;s/http:\\/\\/archive\\.ubuntu\\.com\\/ubuntu\\//http:\\/\\/cn\\.archive\\.ubuntu\\.com\\/ubuntu\\//g\u0026#39; /etc/apt/sources.list \\ \u0026amp;\u0026amp; apt-get update \\ \u0026amp;\u0026amp; apt-get install -y nginx php5 php5-fpm php-pear php5-dev php5-redis php5-gd php5-curl php5-mcrypt imagemagick php5-imagick supervisor \\ \u0026amp;\u0026amp; pecl install mongo \\ \u0026amp;\u0026amp; rm /etc/localtime \\ \u0026amp;\u0026amp; echo \u0026#34;Asia/Shanghai\u0026#34; \u0026gt; /etc/timezone \\ \u0026amp;\u0026amp; dpkg-reconfigure -f noninteractive tzdata \\ # remove caches \u0026amp;\u0026amp; rm -rf /var/lib/apt/lists/* \\ \u0026amp;\u0026amp; echo \u0026#39;extension=mongo.so\u0026#39; \u0026gt; /etc/php5/mods-available/mongo.ini \\ \u0026amp;\u0026amp; ln -s /etc/php5/mods-available/mongo.ini /etc/php5/fpm/conf.d/20-mongo.ini \\ # add supervisord conf before CMD \u0026amp;\u0026amp; mkdir -p /etc/supervisor/conf.d \\ \u0026amp;\u0026amp; echo \u0026#39;[supervisord] \\nnodaemon=true\u0026#39; \u0026gt; /etc/supervisor/conf.d/supervisord.conf \\ \u0026amp;\u0026amp; echo \u0026#39;[program:nginx] \\ncommand=/usr/sbin/nginx \\nautostart=true \\nautorestart=true \\npriority=10\u0026#39; \u0026gt; /etc/supervisor/conf.d/nginx.conf \\ \u0026amp;\u0026amp; echo \u0026#39;[program:php-fpm] \\ncommand=/usr/sbin/php5-fpm \\nautostart=true \\nautorestart=true \\npriority=5\u0026#39; \u0026gt; /etc/supervisor/conf.d/php-fpm.conf CMD [\u0026#34;/usr/bin/supervisord\u0026#34;, \u0026#34;-n\u0026#34;, \u0026#34;-c\u0026#34;, \u0026#34;/etc/supervisor/supervisord.conf\u0026#34;]","date":"2017-05-25","objectID":"/2017/05/25/%E6%89%93%E9%80%A0%E5%9F%BA%E4%BA%8Edocker%E7%9A%84ubuntu-14.04--php-fpm--nginx%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83/:0:3","tags":["运维","docker"],"title":"打造基于Docker的Ubuntu 14.04 + PHP-FPM + Nginx运行环境","uri":"/2017/05/25/%E6%89%93%E9%80%A0%E5%9F%BA%E4%BA%8Edocker%E7%9A%84ubuntu-14.04--php-fpm--nginx%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83/#完整的文件是这样子的"},{"categories":null,"collections":null,"content":"使用方法 git pull 本工程 cd 进入docker-compose.yml文件所在目录（如ubuntu14.04） docker-compose up -d，具体用法命令行输入docker-compose --help查看 ","date":"2017-05-25","objectID":"/2017/05/25/%E6%89%93%E9%80%A0%E5%9F%BA%E4%BA%8Edocker%E7%9A%84ubuntu-14.04--php-fpm--nginx%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83/:0:4","tags":["运维","docker"],"title":"打造基于Docker的Ubuntu 14.04 + PHP-FPM + Nginx运行环境","uri":"/2017/05/25/%E6%89%93%E9%80%A0%E5%9F%BA%E4%BA%8Edocker%E7%9A%84ubuntu-14.04--php-fpm--nginx%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83/#使用方法"},{"categories":null,"collections":null,"content":"docker-compose修改 修改ports端口映射 修改目录映射 修改www目录，将自己本机的目录共享给docker镜像 修改log目录，以便不需要ssh进docker镜像也可以查看log nginx/php-fpm/supervisor master process user为root，因此可以直接写入/var/log目录 php-fpm的worker process user为www-data(默认)，因此将worker的error output设置成(php_errors = /tmp/php_error.log)以写入/tmp 不建议修改系统默认文件夹权限设置，特别是将一些关键目录设置成777或者使用root权限运行程序 修改docker-compose.yml文件完毕之后请运行docker-compose down \u0026amp;\u0026amp; docker-compose up -d重新启动建立映射关系 ","date":"2017-05-25","objectID":"/2017/05/25/%E6%89%93%E9%80%A0%E5%9F%BA%E4%BA%8Edocker%E7%9A%84ubuntu-14.04--php-fpm--nginx%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83/:0:5","tags":["运维","docker"],"title":"打造基于Docker的Ubuntu 14.04 + PHP-FPM + Nginx运行环境","uri":"/2017/05/25/%E6%89%93%E9%80%A0%E5%9F%BA%E4%BA%8Edocker%E7%9A%84ubuntu-14.04--php-fpm--nginx%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83/#docker-compose修改"},{"categories":null,"collections":null,"content":"docker交互模式 通过docker-compose up -d进入后台进程，可以使用docker exec -i -t $containerId bash进入交互模式 通过docker ps查看所有运行的docker情况 通过docker-compose ps -q查看当前镜像运行的containerId 直接使用docker exec -it $(docker-compose ps -q) bash进入交互模式 建议添加function到shell以便快速进入sshdocker() { docker exec -it $(docker-compose ps -q) bash}(alias在shell载入时会计算出结果，所以不能用alias) ","date":"2017-05-25","objectID":"/2017/05/25/%E6%89%93%E9%80%A0%E5%9F%BA%E4%BA%8Edocker%E7%9A%84ubuntu-14.04--php-fpm--nginx%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83/:0:6","tags":["运维","docker"],"title":"打造基于Docker的Ubuntu 14.04 + PHP-FPM + Nginx运行环境","uri":"/2017/05/25/%E6%89%93%E9%80%A0%E5%9F%BA%E4%BA%8Edocker%E7%9A%84ubuntu-14.04--php-fpm--nginx%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83/#docker交互模式"},{"categories":null,"collections":null,"content":"其他参考 为什么只用一条RUN命令? 每一次RUN都会导致镜像被包装一层，从而有不必要的额外信息被记录，更多详细信息参考：https://yeasy.gitbooks.io/docker_practice/content/image/build.html 有什么要注意的？ supervisor启动的进程不要以daemon形式启动，所以在php-fpm.conf和nginx.conf都将daemon关闭了，具体详细参数请参考示例工程 示例工程： 请参考docker-ubuntu-php-nginx，包含ubuntu14.04和ubuntu16.04的示例 更多docker的使用技巧请参考官网和git book ","date":"2017-05-25","objectID":"/2017/05/25/%E6%89%93%E9%80%A0%E5%9F%BA%E4%BA%8Edocker%E7%9A%84ubuntu-14.04--php-fpm--nginx%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83/:0:7","tags":["运维","docker"],"title":"打造基于Docker的Ubuntu 14.04 + PHP-FPM + Nginx运行环境","uri":"/2017/05/25/%E6%89%93%E9%80%A0%E5%9F%BA%E4%BA%8Edocker%E7%9A%84ubuntu-14.04--php-fpm--nginx%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83/#其他参考"}]