# -*- coding: utf-8 -*- r'''查 Cloudflare 是不是按 User-Agent 拦请求(403 + error 1010)。 == 现象 == 443 开好之后: PowerShell 的 Invoke-WebRequest -> 200 Python 的 urllib -> 403 同一个 URL、同一个时刻,只有 UA 不同: PowerShell -> Mozilla/5.0 (Windows NT; Windows NT 10.0; ...) PowerShell/5.1 Python -> Python-urllib/3.11 **这正是仓库里早记过的坑**: windows/lanremote/relay.py 文件头写着 "(Python-urllib/3.11)判为可疑客户端,返回 403 + error code 1010。 实测 LanRemote/1.4.0 能过,用自家标识比伪装浏览器合适。" == 为什么这次特别要紧 == 服务器上的**监测单元用的是 curl**。如果 Cloudflare 也拦 curl, 那监测会**永远判定网站挂了** -> 一直启动紧急预案 -> 死循环折腾。 所以必须实测清楚:哪些 UA 能过、哪些被拦。 ''' from __future__ import annotations import ssl import sys import urllib.error import urllib.request from pathlib import Path ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT / "_build")) from lssh import run # noqa: E402 URL = "https://yk.xxmxxs.top/v1/health" UAS = [ ("Python-urllib/3.11", "Python urllib 默认"), ("curl/8.5.0", "curl 默认(监测单元用的就是这个!)"), ("LanRemote/1.4.0", "本项目自己的标识(旧机器上实测能过)"), ("Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "浏览器"), ("", "空 UA"), ] def probe(ua: str) -> tuple: req = urllib.request.Request(URL) if ua: req.add_header("User-Agent", ua) else: req.add_header("User-Agent", "") try: with urllib.request.urlopen(req, timeout=30) as r: body = r.read(300).decode("utf-8", "replace") return str(r.status), body[:90].replace("\n", " ") except urllib.error.HTTPError as exc: body = "" try: body = exc.read(300).decode("utf-8", "replace") except Exception: # noqa: BLE001 pass return str(exc.code), body[:90].replace("\n", " ") except Exception as exc: # noqa: BLE001 return "失败", str(exc)[:70] def main() -> int: print("=" * 62) print(" Cloudflare 是不是按 UA 拦请求?") print("=" * 62) print() print(" 目标: %s" % URL) print() for ua, note in UAS: code, body = probe(ua) mark = "✓" if code == "200" else "✗" print(" %s %-34s %s" % (mark, ("(空)" if not ua else ua)[:34], note)) print(" -> HTTP %s %s" % (code, body)) print() print(" ── 服务器上 curl 实测(监测单元就是这么查的)──") out = run( "echo ' curl 默认 UA:'; " "curl -s -o /dev/null -w ' HTTP %{http_code}\\n' --max-time 15 " "https://yk.xxmxxs.top/v1/health; " "echo ' curl 带 LanRemote UA:'; " "curl -s -o /dev/null -w ' HTTP %{http_code}\\n' --max-time 15 " "-A 'LanRemote/1.4.0' https://yk.xxmxxs.top/v1/health; " "echo ' curl 带浏览器 UA:'; " "curl -s -o /dev/null -w ' HTTP %{http_code}\\n' --max-time 15 " "-A 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)' " "https://yk.xxmxxs.top/v1/health", timeout=180, quiet=True) for ln in out[1].strip().splitlines(): print(ln) print() print(" 结论提示:如果 curl 默认 UA 被拦、带上标识就通,") print(" 那就得给监测单元的 curl 加 -A。") return 0 if __name__ == "__main__": sys.exit(main())