事情本身不复杂,线索都在日志里。nginx 1.24 的 443 端口配了 ssl,监控里每天有几十条 400 响应,error.log 里是 The plain HTTP request was sent to HTTPS port,来源既有内网扫描也有负载均衡的健康检查。
第一反应是「端口扫描器直接往 443 发明文请求」,验证下来不成立。
把日志和配置对完,能解释这个现象的基本就这几处。负载均衡的健康检查配成 http 协议,却打到了 443 端口。还有一种是客户端把地址写成了 http 但端口仍保留 443。
另外,HSTS 生效之前有人手动输入了 http 加端口的地址。
第一件事是看 400 请求的原文和来源
awk '$9==400 {print $1,$7,$12}' /var/log/nginx/access.log | tail -20
从 error.log 确认错误类型
grep -c 'plain HTTP request was sent to HTTPS port' /var/log/nginx/error.log
单独用 80 端口做跳转
printf '%s
' 'server {' ' listen 80;' ' server_name demo.example.com;' ' return 301 https://$host$request_uri;' '}' > /etc/nginx/conf.d/redirect.conf
剩下的就是把健康检查改成 https 再复测
curl -k -s -o /dev/null -w '%{http_code}\n' https://127.0.0.1/healthz
怎么算真的好了,看的是同一批现象。access.log 里 400 降到个位数,健康检查返回 200,error.log 不再出现 plain HTTP 的报错。
这里还有个坑。400 不一定是故障,扫描流量打过来也会记一条;但健康检查配错协议会让后端一直被摘,先确认来源再决定是封还是改。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。
