21 KiB
EdgeOne 回源端口 iptables 白名单自动维护指南
交付物:
scripts/edgeone-origin-whitelist.sh(Linux / iptables + ipset) 适用:TamaBox 源站对公网开放了 EO 回源端口(免备案双线架构的 EO 分支),想把「开放 IP + 端口」收敛为「仅 EdgeOne 可访问」。 更新日期:2026-09-03
0. 先泼一盆冷水:官方清单是付费功能
你要的「定期获取 EdgeOne IP 列表」——免费套餐下官方不提供可程序化获取的渠道:
| 事实 | 说明 |
|---|---|
| 官方唯一清单来源 = 「源站防护 / Origin ACL」 | EO 控制台 → 安全防护 → 源站防护,启用后展示回源 IPv4/IPv6 网段,变更前 14/7/3/1 天通知 |
| 仅付费套餐支持 | 官方文档明确「origin protection 仅支持绑定付费套餐的站点,free edition 不支持」(腾讯文档 1552/76086)——这就是你在控制台找不到入口的原因 |
| 自动化 API 存在但同样付费 | DescribeOriginACL(teo.intl.tencentcloudapi.com,国际站),每 3 天低频轮询,NextOriginACL 非空即同步并调确认接口(文档 71118) |
所以本脚本的现实定位:不依赖官方 API,以「本地/远程 CIDR 清单」为骨架,免费档立刻可用;日后升级付费套餐,只需把 API 拉取结果落到清单文件,脚本零改动继续工作(见 §7)。
🔴 0.1 2026-09-03 实测定稿:免费档请直接用「段级放行」,IP 级采种已证明不可行
曾设计 learn/auto 从连接表逐个收集 EO 出口 IP 作白名单,服务器实测(tcpdump 取证)否决了该路线:
- EO 回源出口是节点池,规模数百上千,且同一时刻在多段轮换——一次 23 秒采样就看到 13 个不同出口(分布在
43.146/43.152/43.168/43.174/43.175五段),其中 9 个因不在白名单被 REJECT → 表现为境内间歇性 521(EO 边缘回源失败)。- 结论:IP 级清单 = 打地鼠,永远追不上。免费档唯一现实可行方案是按腾讯云大段放行(脚本原生支持 CIDR,无需任何改动):
# /etc/edgeone-origin/cidr.txt(2026-09-03 实测生效配置,521 消失) 43.146.0.0/16 43.152.0.0/16 43.168.0.0/16 43.174.0.0/16 43.175.0.0/16
- learn/auto 在段级模式下降级为「新段预警」辅助:auto 采到清单外的 IP →
whois反查归属 → 若属腾讯云 EO 新段,把整段/16补进清单。首次采种不再需要 learn(§3.1 的逐 IP 采种流程整体退役)。- 代价说明:
/16段内任意腾讯云主机可直连该回源端口(比全开安全、比精确 ACL 松),对 TamaBox 这类自身带鉴权的应用风险中等、可接受(§8)。
1. 脚本做什么
把回源端口从「全网开放」收敛为白名单:
INPUT 链(默认仅 2 条规则,其余不动)
├─ -p tcp --dport 18080 -i lo -> ACCEPT ← cloudflared Tunnel 本机回连(回环放行)
└─ -p tcp --dport 18080 -i eth0 -> EO_IN ← 仅公网网卡 eth0 入站才判定
EO_IN 自建链(一次性建立,内容恒定)
├─ EO_ORIGIN 集合命中 -> ACCEPT ← EdgeOne 回源(白名单)
└─ 其余 -> REJECT tcp-reset ← 直连者秒断
(网卡名不是 eth0 请改脚本头 EO_IFACE;留空=不限网卡,回环由 EO_IN 内 127.0.0.0/8 兜底)
两个关键设计,保证不会把自己锁死、不会误伤 CF 分支:
- 更新零窗口:白名单存于 ipset 集合
EO_ORIGIN,更新走「临时集合填充 →ipset swap原子替换 → 销毁临时集」;iptables 规则永远引用同名集合、从不重建。同步过程中不存在「规则被清空」的瞬间。 - cloudflared 不受影响:Tunnel 是 cloudflared 从本机
127.0.0.1连回源端口,INPUT 里有独立的-i loACCEPT 放行回环(与 eth0 网卡限定解耦),所以即使防火墙收紧,CF 分支依然正常工作——这正是裸 iptables 白名单最容易踩的坑(有人把 18080 一刀切 REJECT,Tunnel 分支跟着全挂)。
其余保障:清单为空/拉取失败/全非法 → 拒绝更新、保留现网规则(fail-safe);支持 --dry-run 演练;全程日志 /var/log/eo-origin-whitelist.log。
2. 部署前确认两件事
-
确认你的实际回源端口(脚本默认
18080,务必改成实际值):ss -tlnp | grep -iE 'tamabox|LISTEN' # 找 TamaBox 监听的端口或看
conf/app.ini的[server] port。改脚本文件头EO_PORT=18080那一行,或运行时sudo EO_PORT=xxxx ./edgeone-origin-whitelist.sh sync。 -
确认系统有 ipset(白名单原子替换依赖它):
command -v ipset || sudo apt-get install -y ipset # Debian/Ubuntu command -v ipset || sudo dnf install -y ipset # RHEL/CentOS/Fedora -
确认公网网卡名(脚本默认只对
eth0生效):ip route get 1.1.1.1 | awk '{print $5; exit}' # 输出如 eth0 / ens3 / enp1s0输出不是
eth0时,改脚本头EO_IFACE=或运行时覆盖:sudo EO_IFACE=ens3 ./edgeone-origin-whitelist.sh sync。⚠️ 网卡名不对 → 跳转规则永不命中 → 端口等于裸奔。
3. 初始化:生成种子清单(免费档必经步骤)
🔴 先读 §0.1(实测定稿):免费档不要再做逐 IP 采种(EO 出口是海量轮换节点池,IP 级白名单实测导致间歇 521)。直接按 §0.1 的五个
/16段建清单即可;learn/auto 只留作「新段预警」,见 §3.1 末注。
3.1 首选:腾讯云大段放行(实测定稿)
按 §0.1 直接放行 EO 所属的腾讯云大段(免费档没有官方回源段 API,而逐 IP 采种已被实测否决)。清单内容(2026-09-03 服务器实测生效):
sudo mkdir -p /etc/edgeone-origin
# 每行一个 CIDR,# 开头为注释。以下为实测生效配置:
sudo tee /etc/edgeone-origin/cidr.txt >/dev/null <<'EOF'
# EdgeOne 回源段(腾讯云,2026-09-03 实测;境内 EO 分支访问验证正常)
43.146.0.0/16
43.152.0.0/16
43.168.0.0/16
43.174.0.0/16
43.175.0.0/16
EOF
段怎么来的:用
auto(或 tcpdump 抓 SYN)持续观察回源出口,把出现过的 IP 归并到所属腾讯云段(whois 查 ASN/归属确认),整段放行。上面五个/16来自多次实测采样(新加坡/腾讯云 EO 出口遍布这些段)。🔴 段不是永恒不变的:EO 可能启用清单外的新段(罕见、以月计)。每月跑一次
auto看采样里有没有清单外的 IP,whois <IP>确认属腾讯云 EO 后把整段补进 cidr.txt 再 sync(详见 §4.4)。
3.2 备选:向 EO 索取回源段
免费档控制台无源站防护页面,但可尝试提交工单索取当前回源 IP 段(客服可能以"尽力提供"形式给出);拿到后把 CIDR 逐行放进清单文件即可,效果等同。日后升级付费套餐启用源站防护,官方段可直接用(§7)。
3.3 首次启用(务必先 dry-run)
# 1. 建清单文件
sudo mkdir -p /etc/edgeone-origin
sudo cp 你整理好的清单 /etc/edgeone-origin/cidr.txt # 每行一个 IP/CIDR,# 注释
# 2. 演练:只看将要执行的动作,不触碰系统
sudo ./edgeone-origin-whitelist.sh sync --dry-run
# 3. 正式启用
sudo ./edgeone-origin-whitelist.sh sync
启用后立刻验证(另开一个 SSH 或终端,别把自己关外面):
# 服务器本机验证(必须能通:Tunnel 回环放行)
curl -sI --max-time 5 http://127.0.0.1:18080/ | head -3
# 从一台"与 EO 无关"的外网机器验证(必须被拒)
nc -zv <你的服务器IP> 18080 # 期望 refused 或超时
# 经 EO 访问验证(必须能通)
# ⚠️ 必须用【境内网络】访问——境外访问会被 DNSPod 解析到 CF 分支(走 Tunnel 回环),
# 验证到的是 CF 而不是 EO!境内手机 4G 访问最方便
curl -sI --max-time 10 https://box.tama.guru/ | head -3
3.4 撤掉原来的全局放行
若你之前是用 ufw 放行的(ufw allow 18080),现在它已冗余(脚本的 REJECT 会先于它拦截非白名单),建议删掉避免困惑:
sudo ufw delete allow 18080 # 脚本 sync 时也会检测并提示
⚠️ 云厂商安全组若也是「全放行 18080」:本机 iptables 白名单已是最终防线,直连者到本机 INPUT 即被拒,不强制改安全组;但建议安全组层面至少把 18080 的源收敛为 EO 大段(升级付费拿到官方段后可做),纵深更稳。
4. 定时维护(核心诉求)
4.1 清单会变吗?
EO 官方口径:回源网段平均 3–6 个月更新一次,变更前 14/7/3/1 天通知。付费档启用源站防护后段变更有 API 兜底(§7);免费档请按 §7 的「工单/客服」或定期(建议每月一次)核对。
4.2 用 cron(最简单)
段级模式(§0.1)下清单是 5 个 /16 段、几乎不变 → 定时只需周期 sync 兜底 + 月度人工归段核对,auto 不再作日常主线(改为按需「新段预警」观测,见 4.4):
sudo crontab -e
# ★ 推荐:每 3 天一次 sync(全量重建:清单里没有的旧条目自动剔除)
17 4 */3 * * /usr/local/bin/edgeone-origin-whitelist.sh sync >> /var/log/eo-origin-whitelist.log 2>&1
# 想更保险可改每天:把 */3 改成 *(即 17 4 * * * …)——sync 开销秒级,零负担
# 新段预警观测(不设定时,需要时手动跑):
# sudo /usr/local/bin/edgeone-origin-whitelist.sh auto
# 输出「新增」→ whois 确认属腾讯云新段 → 整段写进 cidr.txt → 再 sync
把脚本放到固定路径:sudo cp scripts/edgeone-origin-whitelist.sh /usr/local/bin/ && sudo chmod +x /usr/local/bin/edgeone-origin-whitelist.sh
4.3 用 systemd timer(更规范,推荐)
/etc/systemd/system/eo-origin-whitelist.service:
[Unit]
Description=Sync EdgeOne origin whitelist
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/edgeone-origin-whitelist.sh sync
推荐每 3 天一次(段级清单近乎静态,sync 纯兜底):
# A. 日历式(推荐):每月 1/4/7/10/13/16/19/22/25/28/31 号 04:17
# /etc/systemd/system/eo-origin-whitelist.timer
[Unit]
Description=EdgeOne origin whitelist sync (3-day)
[Timer]
OnCalendar=*-*-1/3 04:17:00
Persistent=true
[Install]
WantedBy=timers.target
想每天跑:
OnCalendar=*-*-* 04:17:00;想严格 72h 间隔:OnBootSec=5min+OnUnitActiveSec=3d。
4.4 失效的条目会自动剔除吗?(段级模式)
会——且已内建,不需要任何额外参数。 关键是理解 sync 的语义:
| 你可能以为 | 实际机制 |
|---|---|
| sync 是把清单「增量添加」,旧条目越积越多 | ❌ 错。sync 是全量重建:每次按当前清单文件从零填充临时集合 → ipset swap 原子替换 → 旧的 EO_ORIGIN 整个被新集合顶掉 |
所以只要某段/某 IP 不在「当前清单文件」里,下一次 sync 它就自动消失——剔除是 sync 的默认行为,零残留。反证见 §5:「临时 ipset add 放行的 IP,下次 sync 就没了」正是同一机制。
段级模式下清单近乎静态(5 个 /16),日常维护极简,只剩一件事:防 EO 启用清单外新段。
# ① 月度新段预警:跑一次 auto(或 tcpdump 抓 SYN),看采样里有没有清单外的 IP
sudo ./edgeone-origin-whitelist.sh auto
# auto 会把「清单外的新 IP」增量合并进 cidr.txt(只增不删),并提示新增了哪些
# ② 归段:whois <新IP>(/ ipinfo.io/<IP>),确认属腾讯云 EO(Tencent/EdgeOne 字样)
# ③ 把新 IP 归并成所属整段后写入清单(若 auto 已把裸 IP 加进 cidr.txt,可顺手整理成段):
sudo nano /etc/edgeone-origin/cidr.txt # 示例:43.175.x.x → 加一行 43.175.0.0/16
sudo ./edgeone-origin-whitelist.sh sync # 立即生效;不手动跑则下次定时 sync 也会生效
三个要点:
- 别删到清单为空:fail-safe 会让 sync 拒绝执行(宁可保留旧白名单,不可裸奔)。
- 旧段留在清单里没有安全风险:那些地址属于腾讯云,不会"变成攻击者",顶多白名单略宽(/16 级本就宽);真正要紧的只是新段漏加 → 偶发 521(见 §8 免费档清单质量)。
- 想彻底全自动(连月度核对都不想做):升级付费套餐启用「源站防护」,把
DescribeOriginACL输出定时写入 cidr.txt(§7)——清单每次都是官方最新全集,sync 自动带上新段、自动剔除已退出的段,脚本零改动。
5. 常用操作速查
sudo ./edgeone-origin-whitelist.sh sync # 周期入口(定时任务用这个,段级清单全量重建)
sudo ./edgeone-origin-whitelist.sh auto # 新段预警:采集当前回源 IP → 合并进清单 → 有新增即 sync
sudo ./edgeone-origin-whitelist.sh learn # 看当前谁在回源(即时观测,不必用于日常维护)
sudo ./edgeone-origin-whitelist.sh show # 当前白名单条目 + iptables 规则
sudo ./edgeone-origin-whitelist.sh sync --dry-run # 演练
sudo ./edgeone-origin-whitelist.sh flush # 回滚:移除本脚本全部规则/集合
tail -20 /var/log/eo-origin-whitelist.log # 看更新历史
临时放行某个 IP(不用改清单,立即生效;下次 sync 会随清单重建而消失——想持久就写进清单文件):
sudo ipset add EO_ORIGIN x.x.x.x
手动移除某个 IP:
sudo ipset del EO_ORIGIN x.x.x.x
修改回源端口(低概率操作):改 EO_PORT 后先 flush 再 sync(避免 INPUT 残留旧端口跳转)。
修改生效网卡:改 EO_IFACE(或 sudo EO_IFACE=ens3 ./edgeone-origin-whitelist.sh sync)后直接 sync 即可——从「不限网卡」升级为「限定网卡」时会自动删除旧的无限定跳转;改完用 show 确认 INPUT 规则带 -i <网卡>。
6. 排错
| 现象 | 原因与处理 |
|---|---|
| sync 报「清单为空…保持现网白名单不变(fail-safe)」 | 正常保护:空清单绝不上线。成因=清单文件不存在 / 内容全非法 / 无有效条目。先用 learn 采种并人工审阅后写入 /etc/edgeone-origin/cidr.txt(裸 IP 每行即可,已支持直接入清单);脚本报错会自带下一步指引。若真配了 EO_CIDR_URL 且拉取失败 + 本地无条目,会单独报「来源全部失败」 |
| 收紧后 CF 分支(海外)访问挂 | 几乎肯定是 cloudflared 连的不是 127.0.0.1。确认 Tunnel 配置里 service 指向 http://127.0.0.1:PORT(脚本对 127.0.0.0/8 放行;若 cloudflared 在另一台机器则需把那台机器出口 IP 加进白名单——但那属于另一架构,需单独设计) |
| 经 EO 访问 502/回源失败(境内间歇性 521) | ① 端口填错(脚本拦的不是 EO 回源那个端口);② 🔴 清单太细——EO 回源出口是海量轮换节点池(实测 23 秒 13 个出口、分布多个 /16),逐 IP 白名单必然间歇漏放 → EO 报 521。解法=按 §0.1 放行腾讯云大段(43.146/43.152/43.168/43.174/43.175 的 /16,2026-09-03 实测 521 消失);③ 服务器重启后 ipset/iptables 规则丢失 → 见下 |
sync 报 Set EO_ORIGIN doesn't exist |
🔴 iptables-nft 要求「被引用的 ipset 集合必须先于规则存在」。旧版脚本先建链(内含引用集合的规则)后建集合,首次运行必失败。已修复(集合创建挪到建链之前);旧版升级后重跑 sync 即可自愈 |
sync 报 RULE_APPEND failed (Invalid argument) 且 EO_IN 链缺 REJECT 兜底行(只剩 127/集合两条 ACCEPT) |
🔴 iptables-nft 下 --reject-with tcp-reset 必须带 -p tcp(nft 的 reject 语句需确认匹配 TCP 才能构造 RST,无 -p 直接 EINVAL)。旧版 REJECT 行无 -p tcp 必然失败 → 链尾无兜底 → 非白名单直连仍通,白名单形同虚设(集合/127 两条 ACCEPT 无此限制,能正常加入)。已修复(REJECT 加 -p tcp);部署新版后重跑 sync,验证 iptables -S EO_IN 三条齐全:-s 127.0.0.0/8 ACCEPT / -m set --match-set EO_ORIGIN src ACCEPT / -p tcp ... REJECT --reject-with tcp-reset |
| 服务器重启后白名单没了 | ipset 与 iptables 规则是内存态。用 iptables-persistent + ipset-persistent(Debian/Ubuntu),或把 sync 加进开机自启(systemd timer Persistent=true 只补跑错过的任务,不保证开机即跑——建议加一条 @reboot cron 或 oneshot service 开机执行一次 sync) |
| 直连还是能通 | 先 iptables -S INPUT 看是否还有更靠前的全局 ACCEPT 匹配 18080;ufw status 若显示 allow 18080 先删;云安全组全放行但本机已 REJECT 的情况下直连应被拒——若仍通说明规则没插在 INPUT 最前或被其它链绕过(如 nftables 后端混用,iptables -S 与实际生效不一致时改用 nft list ruleset 排查) |
auto 立即结束、没等 EO_SAMPLE_SECONDS 窗口(日志同秒出现「采样到 0 个」) |
🔴 旧版 tcpdump filter 误写为 "... and 'tcp[tcpflags] & tcp-syn != 0'"——双引号内的单引号是字面字符,会原样传给 tcpdump,pcap 编译器不认识引号 → syntax error 秒退(手动执行时单引号由 shell 吃掉,脚本里没这一步);且旧版 awk '{print $2}' 取到的是协议名 IP 而非源地址(源在 > 前一字段)。两个缺陷叠加 = 抓了也白抓、还秒退。已修复(filter 去引号 + 按 > 前字段取源 IP,窗口会真实阻塞)。部署新版后:sudo edgeone-origin-whitelist.sh auto 应看到「tcpdump 采样 Ns … 请稍候」并等待 N 秒;EO_SAMPLE_SECONDS 非数字会打印提示并跳过 |
| learn 输出为空 | ① 没有活跃回源连接——EO 回源是短连接、错过即无,且必须境内网络访问才走 EO 路径(境外访问走 CF Tunnel,对端 127.0.0.1 会被脚本过滤,永远为空);② 端口核对:ss -tlnp | grep LISTEN 确认 TamaBox 监听端口 = 脚本 EO_PORT;③ 访问后 60 秒内 ss -Htan | grep :<端口> 看 TIME-WAIT 痕迹;④ 最稳:tcpdump -ni <网卡> tcp port <端口> and 'tcp[tcpflags] & tcp-syn != 0' 抓 SYN——触发一次境内访问,出现的源 IP 即 EO 回源 IP。新版脚本空结果时会自带以上提示;auto 的采样含 conntrack(窗口比 learn 宽),仍采不到时排查思路同上 |
7. 升级付费套餐后:接官方 API 全自动(零脚本改动)
启用「源站防护」拿到 ZoneId 后,可用腾讯云 Python SDK / tccli 周期调用 DescribeOriginACL,把返回的 CurrentOriginACL.EntireAddresses.IPv4[] 写入 /etc/edgeone-origin/cidr.txt,本脚本照常 sync 即可——脚本无需任何改动(它只认"每行一个 CIDR 的文件")。
也可让脚本直接拉取:把 API 结果发布到一个私有 HTTP URL,配置
EO_CIDR_URL=...(文件 + URL 会取并集)。注意变更时先核对NextOriginACL计划生效时间,建议同步时机放在PlannedActiveTime前完成,避免 EO 强制切换后回源失败。
8. 边界与已知限制
- 默认仅公网网卡 eth0:白名单只判定
EO_IFACE指定网卡的入站流量(默认eth0);回环由独立的-i loACCEPT 放行(供 Tunnel 本机回连),与网卡限定解耦。网卡名不是 eth0 时务必配置,否则跳转永不命中、端口裸奔。 - IPv6 天然无风险、无需任何 ip6tables 规则:脚本只管理 IPv4;TamaBox 监听
0.0.0.0(仅 IPv4、无 AAAA),IPv6 上不存在该回源端口,v6 用户访问由 CDN 边缘走 IPv4 回源,一切正常。只有日后改为监听[::]:PORT并向 EO 开放 v6 回源,才需扩展 inet6 集合 + ip6tables 镜像(脚本头注释 5 有说明)。 - 免费档清单质量(段级视角):清单是 5 个腾讯云
/16段(§0.1),EO 出口怎么轮换都在段内 → 正常无感。唯一风险是 EO 启用清单外的新段(罕见、以月计)→ 表现为个别请求偶发 521;对策=月度跑一次auto看有无清单外新 IP,whois确认归段后补段(§4.4)。这是免费档没有官方清单的固有代价,可接受则用,不可接受就升级付费档走 §7。 - 脚本不触碰 ufw/云安全组,只管理自己创建的链与集合;
flush也只删自己的东西,可放心回滚。 - 本机为 1C1G 低配:脚本每次运行仅秒级、无常驻进程,ipset 查表为 O(1) 哈希,不影响转发性能。