HTTPS 与 443 端口
443 是 HTTPS 的默认端口,即 HTTP 报文承载在 TLS 之上加密传输。浏览器地址栏的锁标、证书校验、密钥协商全部在这一端口完成,TLS 1.3(RFC 8446)把完整握手压缩到一次往返。HTTP/3 把传输层换成基于 UDP 的 QUIC,默认端口仍是 443,只是从 TCP 改成了 UDP。
基本信息
| 服务 | https(HTTP over TLS),Nginx/Apache/IIS/CDN 承载 |
|---|---|
| 协议 | TCP;HTTP/3 走 UDP(QUIC) |
| 规范 | RFC 9110/9112(HTTP)、RFC 8446(TLS 1.3) |
| 权限要求 | 监听 1024 以下端口需 root 或 CAP_NET_BIND_SERVICE |
| 证书位置 | Nginx 常见于 /etc/nginx/ssl 或 /etc/letsencrypt/live/<域名>/ |
典型使用场景
- 对外网站与 API 的唯一入口,全站强制 HTTPS 已是基线要求
- 反向代理终结 TLS:后端服务跑明文,由 Nginx 在 443 卸载证书与加密
- 移动端与小程序后端:平台要求接口证书链可被系统信任校验
- 内网系统也加域名配证书,避免明文与浏览器不安全告警
- 多域名共用入口:靠 SNI 在同一 443 上按 server_name 分流不同证书
证书链与握手检查
证书链与握手检查
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates # -servername 必须带,否则可能收到默认站点证书
curl -sI https://example.com | head -n 3 # 看状态码与 Server 头
curl -s -o /dev/null -w '%{http_code} %{ssl_verify_result}\n' https://example.com/ # 第二列 0 表示证书校验通过
openssl s_client -connect example.com:443 -servername example.com -tls1_2 </dev/null >/dev/null 2>&1 && echo 'TLS1.2 ok' # 老客户端兼容性抽查
openssl s_client -connect example.com:443 -servername example.com -alpn h2 </dev/null 2>/dev/null | grep -i 'ALPN' # 确认协商到 HTTP/2
ss -lntp | grep ':443 ' # 确认监听进程与绑定地址握手失败与定位手段
| 现象 | 原因 | 定位手段 |
|---|---|---|
| 证书过期 | notAfter 时间已过 | openssl x509 -noout -dates 看有效期,续期后 reload |
| 域名不匹配 | SAN 列表不含实际访问的地址 | 带 -servername 对比 SAN 列表,重新签发证书 |
| 链不完整 | 缺中间证书,部分客户端报不受信任 | 部署完整链文件后重载,再用外部 TLS 检测复核 |
| 协议不兼容 | 只允许 TLS1.3 而客户端过旧 | 按业务客户端能力确定最低版本,避免一刀切 |
| SNI 未命中 | 返回了其他站点的证书 | 核对 server_name 与证书绑定,默认站点单独兜底 |
输出逐列读法
| 输出项 | 含义 | 正常/异常 |
|---|---|---|
| Verify return code | 证书链校验结论 | 0 (ok) 正常;20/21 多为链或域名问题 |
| subject / issuer | 证书主体与签发者 | subject 的 CN/SAN 应包含你访问的域名 |
| Protocol / Cipher | 协商出的版本与套件 | 应为 TLSv1.2/1.3,出现 TLSv1 说明配置过旧 |
| ssl_verify_result | curl 的证书校验结果码 | 0 通过,非 0 会有证书错误提示 |
| http_code | HTTP 响应码 | 200/301/302 正常;000 表示 TLS 层就没连上 |
Nginx 443 站点骨架
Nginx 443 站点骨架
server {
listen 443 ssl;
http2 on; # Nginx 1.25.1 起用 http2 指令,旧版本写在 listen 后面
server_name example.com;
ssl_certificate /etc/nginx/ssl/fullchain.pem; # 必须是含中间证书的完整链
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:10m;
add_header Strict-Transport-Security 'max-age=31536000' always; # HSTS,确认全站可 HTTPS 后再开
}证书私钥文件权限应为 600 并归属 root;私钥一旦泄露,任何人都能冒充你的域名,需要走吊销再重签流程。
HTTP/3 走 UDP 443,防火墙只放行 TCP 443 时客户端会静默回退到 HTTP/2,回退本身不是故障;要启用就同时放行 UDP 并发布 Alt-Svc 头引导升级。
混合内容排查:页面走 443 但内部仍引用 http:// 的图片或脚本,浏览器会拦截或告警,先看浏览器控制台的具体 URL 比只看服务端访问日志更快。
排障顺序
- 先确认 TCP 443 可达:本机 ss 看监听进程,外部用 nc 或 curl 确认连接能否建立
- 再看 TLS 层:s_client 带 -servername 确认拿到的证书主体、有效期与协商的协议版本
- 最后看应用层:出现 502/504 说明 TLS 已通,问题在后端服务或上游转发
- 证书类问题优先对比 SAN 与有效期,配置类问题优先对比 server_name 与证书绑定
- 启用 HTTP/3 时单独查 UDP:TCP 正常但部分客户端抖动,先怀疑 QUIC 报文被丢
证书续期后必须重载才生效:Nginx 用 nginx -s reload,Apache 用 graceful;只替换证书文件不重载,进程仍持有旧证书,表现为换了新证书但浏览器依旧提示过期。
自签证书场景:服务端配置全部正确,浏览器依旧拦截,因为客户端信任库不认这个签发者;内部系统用自签证书时,要把根证书通过终端管理或域策略分发到客户端,单独配好服务端是不够的。