# -*- coding: utf-8 -*- r'''查服务器为什么访问不了自己的域名(curl 返回 000)。 == 现象 == 从我的电脑 -> https://yk.xxmxxs.top = 200 ✅ 从服务器自己-> https://yk.xxmxxs.top = 000 ❌ 监测单元就跑在服务器上、查的就是这个域名,所以它一直判失败 -> fails 一直涨 -> 会启动紧急预案 -> 瞎折腾。 == 最可能的原因:IPv6 == yk.xxmxxs.top 在 Cloudflare 上有 **AAAA 记录**: 2606:4700:3036::6815:362d 2606:4700:3036::ac43:df96 Lightsail 的实例默认**没有 IPv6 地址**。curl 会先试 IPv6、失败, 如果不自动回退到 IPv4,就直接报连接失败(=000)。 验证办法很简单:`curl -4`(强制 IPv4)通不通。 == 其他可能 == * DNS 在服务器上解析不出来(getent hosts 看看) * Cloudflare 拒绝来自源站自己 IP 的请求(回环防护)——不太可能 * 出站被挡(Lightsail 默认出站全开,概率低) ''' from __future__ import annotations import sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT / "_build")) from lssh import run, HOST as LS_HOST # noqa: E402 DOMAIN = "yk.xxmxxs.top" REMOTE = r''' D=__DOMAIN__ echo "════ 1. 服务器有没有 IPv6 ════" ip -brief addr show 2>/dev/null | sed 's/^/ /' echo " --- IPv6 默认路由 ---" ip -6 route show default 2>/dev/null | sed 's/^/ /' || echo " (没有 IPv6 默认路由)" echo echo "════ 2. 域名解析(IPv4 / IPv6 分开看)════" echo " A 记录:" getent ahostsv4 $D 2>/dev/null | awk '{print " " $1}' | sort -u echo " AAAA 记录:" getent ahostsv6 $D 2>/dev/null | awk '{print " " $1}' | sort -u echo " --- dig 结果 ---" dig +short A $D 2>/dev/null | sed 's/^/ A: /' dig +short AAAA $D 2>/dev/null | sed 's/^/ AAAA: /' echo echo "════ 3. curl 各种姿势 ════" printf ' %-30s %s\n' "默认(可能走 IPv6)" "$(curl -s -o /dev/null -w '%{http_code}' --max-time 15 https://$D/v1/health)" printf ' %-30s %s\n' "强制 IPv4 (-4)" "$(curl -s4 -o /dev/null -w '%{http_code}' --max-time 15 https://$D/v1/health)" printf ' %-30s %s\n' "强制 IPv6 (-6)" "$(curl -s6 -o /dev/null -w '%{http_code}' --max-time 10 https://$D/v1/health)" printf ' %-30s %s\n' "http 强制 IPv4" "$(curl -s4L -o /dev/null -w '%{http_code}' --max-time 15 http://$D/v1/health)" echo echo " --- 详细报错(默认那条)---" curl -s -o /dev/null -w ' %{http_code}\n' --max-time 10 https://$D/v1/health 2>&1 || true curl -v -o /dev/null --max-time 12 https://$D/v1/health 2>&1 | grep -iE 'trying|connected|refused|timed|error|Could not' | head -10 | sed 's/^/ /' echo echo "════ 4. 直连 Cloudflare 边缘 IP(跳过 DNS)════" for ip in 104.21.54.45 172.67.223.150; do printf ' %-20s %s\n' "$ip (HTTPS)" "$(curl -sk -o /dev/null -w '%{http_code}' --max-time 12 --resolve $D:443:$ip https://$D/v1/health)" done echo echo "════ 5. 出站到 Cloudflare 通不通(纯 TCP)════" for ip in 104.21.54.45 172.67.223.150; do if timeout 6 bash -c "/dev/null; then echo " $ip:443 通" else echo " $ip:443 不通" fi done echo echo "════ 6. 对比:直连自己的 nginx ════" printf ' %-30s %s\n' "127.0.0.1:443(带 SNI)" "$(curl -sk -o /dev/null -w '%{http_code}' --max-time 8 --resolve $D:443:127.0.0.1 https://$D/v1/health)" printf ' %-30s %s\n' "公网 IP:443" "$(curl -sk -o /dev/null -w '%{http_code}' --max-time 8 --resolve $D:443:LS_HOST https://$D/v1/health)" ''' def main() -> int: print("=" * 62) print(" 查服务器为什么访问不了自己的域名") print("=" * 62) out = run(REMOTE.replace("__DOMAIN__", DOMAIN), timeout=300, quiet=True) print(out[1] if isinstance(out, tuple) else out) return 0 if __name__ == "__main__": sys.exit(main())