外观
阿里云 ECS:从备案到域名能访问
备案通过那天我以为就完事了,结果发现域名还是打不开。中间隔着一层云厂商的 ICP 域名拦截,再加上证书和站点配置两道关。这篇把整条链路按顺序记一遍。
结论先摆出来
备案通过 ≠ 域名可用。完整的顺序是:
ICP 备案通过
↓
DNS 解析到服务器
↓
【关键】云厂商放行该域名 ← 少了这步,80 端口返回 403
↓
签发证书(覆盖域名)
↓
nginx 配域名站点
↓
能用一、先确认 DNS 解析
在阿里云云解析加两条 A 记录,@ 和 www 都指向同一台服务器的公网 IP:
| 主机记录 | 记录类型 | 记录值 | TTL |
|---|---|---|---|
@ | A | 你的公网 IP | 10 分钟 |
www | A | 你的公网 IP | 10 分钟 |
验证:
bash
nslookup example.cn 223.5.5.5
nslookup www.example.cn 8.8.8.8TTL 默认 600 秒,实际几分钟内全网生效。
二、验证云厂商放行(最容易漏的一步)
这一步不做,后面签证书必失败。
大陆的 ECS 会按 HTTP 的 Host 头 / TLS 的 SNI 来拦截未备案域名:80 端口返回一个 403 的 Non-compliance ICP Filing 页面,443 直接重置 TLS 握手。
所以「域名能不能过」和「服务器有没有配好」是两回事,得单独验证:
bash
curl -s -m 20 -o /dev/null -w "%{http_code}\n" \
-H "Host: example.cn" "http://你的公网IP/"| 返回 | 含义 |
|---|---|
301 / 200 / 302,且 Server: 是你的 nginx | 已放行,继续 |
403 且正文含 Non-compliance ICP Filing | 未放行,等或核对接入商 |
别在服务器上测
curl http://127.0.0.1/ 走的是本机回环,绕过了厂商网关,测不出拦截。 必须从外部、带上域名的 Host 头去打 80 端口。
顺带一个副作用:这套机制会让 sslip.io、DuckDNS 之类的免费域名在国内机器上完全不可用——它们过不了 Host 判定,只有按纯 IP 访问才行。
三、签证书
先看清服务器上有几套 certbot:
bash
which -a certbot
systemctl cat certbot.service | grep ExecStart有些机器 apt 装了一套、pip venv 里又装了一套,而 systemd 定时器指向的是后者。手动操作时必须用定时器同款,否则 renewal 配置的版本号会对不上。
签发(webroot 方式):
bash
certbot certonly --webroot -w /var/www/certbot \
-d example.cn -d www.example.cn --cert-name example.cn \
--key-type ecdsa --non-interactive --agree-tos \
--deploy-hook "systemctl reload nginx"--deploy-hook 会写进 renewal 配置,以后每次自动续期完都会 reload nginx。
证书不用买
个人站点用 Let's Encrypt 就够,90 天自动续期。需要买证书的场景只有三种:要通配符(*.example.cn)、要证书上显示主体名(OV/EV)、需要保险赔付。
阿里云/腾讯云的免费 DV 证书现在是 3 个月有效期、到期不支持续费只能重新申请,老老实实用 certbot 反而省事。
四、配 nginx
关键点:别把原有的 default_server 改掉。历史上按 IP 访问的那份配置通常占着 listen 80 default_server; server_name _;,新起一个不写 default_server 的域名配置文件与它并存:
- 域名访问 → 精确匹配
server_name→ 用域名证书 - IP 直连 → 落到
default_server→ 仍用原证书
这样两边互不干扰。
nginx
server {
listen 80;
listen [::]:80;
server_name example.cn www.example.cn;
# ACME 校验走这里;return 必须包在 location 里,
# 写在 server 层会先于 location 匹配执行,把 ACME 路径也跳掉
location /.well-known/acme-challenge/ { root /var/www/certbot; }
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name example.cn www.example.cn;
ssl_certificate /etc/letsencrypt/live/example.cn/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.cn/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
root /var/www/site;
index index.html;
location / { try_files $uri $uri/ /index.html; }
}bash
ln -sf /etc/nginx/sites-available/example-web /etc/nginx/sites-enabled/example-web
nginx -t && systemctl reload nginxSPA 必加的一行
try_files $uri $uri/ /index.html; —— Vue / React / uni-app 打包出来是前端路由,不加这行刷新子页面会 404。
五、验收
浏览器可能挂着代理,结果不可信。用直连 IP + 指定 SNI 的方式验,绕开代理:
python
import socket, ssl
ctx = ssl.create_default_context() # 会真的校验信任链
raw = socket.create_connection(("你的公网IP", 443), timeout=15)
ss = ctx.wrap_socket(raw, server_hostname="example.cn")
cert = ss.getpeercert()
print(cert["subjectAltName"]) # SAN 必须含你的域名
print(cert["notAfter"])
ss.sendall(b"GET / HTTP/1.1\r\nHost: example.cn\r\nConnection: close\r\n\r\n")
print(ss.recv(200))再加一步 HTTP 跳转检查,以及续期演练:
bash
curl -s -o /dev/null -w "%{http_code}\n" -H "Host: example.cn" http://你的公网IP/
certbot renew --dry-run --no-random-sleep-on-renewrenew 会"卡住"是正常的
certbot renew 默认带随机延迟(最长约 5.5 分钟),防雪崩用的。手动测试一定要加 --no-random-sleep-on-renew,否则会以为进程死了。
上线后的合规收尾
| 事项 | 要点 |
|---|---|
| 页脚备案号 | ×ICP备xxxxxxxx号-N,必须链到 https://beian.miit.gov.cn/ |
| 公安联网备案 | 自网络正式联通之日起 30 日内办理,平台 beian.mps.gov.cn |
| 网站名称 | 要和备案信息里的一致,明显不符会被要求整改 |
公安备案别只做主体
公安备案里主体审核通过只是第一步,**还必须提交「新办网站申请」**才会有备案号。
只备主体不备网站就是空壳主体,各省管局会定期公示清理,有的省份公示期只有 3 天,逾期直接注销。