很多朋友第一次给网站上加密访问时都会卡在同一个问题上:后端服务本身只支持普通http,证书也不知道往哪装,难道要把业务代码全部改一遍?其实完全不用。用nginx做反向代理,加密的活儿全部在代理层完成,后端一行代码都不用动。这篇文章就按照原理 → 实操 → 避坑的顺序,把整条链路一次性讲透。
一、先讲原理:nginx凭什么能代理https
先说清楚角色分工。用户访问你的网站时,浏览器和服务器之间的数据是加密传输的,这就是https。而你的后端应用——比如一个Java、Python或Node服务——可能只监听了一个普通的http端口。这时候nginx就站在最前面充当"门卫":
用户发起加密请求 → nginx负责完成加密握手并解密 → nginx把解密后的请求以普通http转交给后端 → 后端返回结果 → nginx再加密传回给用户。
这个过程在行业里叫TLS终止(也叫SSL卸载)。简单记一句话:加密的活儿全交给nginx,后端专心处理业务。这样做有三个明显好处:证书只需要维护一份;后端服务完全不用改造;加解密的性能开销由nginx统一承担,不占用业务资源。
二、动手前的准备:环境与证书
实操之前把两样东西备齐就够了。
第一,装好nginx。以最常见的两套系统为例:
# CentOS / RHEL
yum install -y nginx
systemctl start nginx
# Ubuntu / Debian
apt update && apt install -y nginx
systemctl start nginx
第二,搞一张SSL证书。个人和小项目可以直接用Let's Encrypt的免费证书,配合certbot工具自动申请和续期;企业项目建议在云厂商申请免费或付费证书。审核通过后下载nginx格式的证书包,里面一般有两个文件:.pem(证书)和 .key(私钥)。把它们上传到服务器,比如统一放在 /etc/nginx/ssl/ 目录下。
提醒一句:私钥文件权限建议设为600,别图省事开放读取权限,否则任何能登录服务器的人都能拿走你的证书。
三、核心实操:一段能直接用的nginx配置
下面就是nginx代理https最核心的配置,改掉域名和路径就能上线:
# HTTPS 站点
server {
listen 443 ssl;
server_name example.com; # 换成你的域名
ssl_certificate /etc/nginx/ssl/example.com.pem; # 证书文件
ssl_certificate_key /etc/nginx/ssl/example.com.key; # 私钥文件
ssl_protocols TLSv1.2 TLSv1.3; # 只保留安全协议
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://127.0.0.1:8080; # 后端服务的地址和端口
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# 所有 http 请求自动跳转到 https
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
几个关键点解释一下:
listen 443 ssl:监听https默认端口;ssl_certificate 和 ssl_certificate_key:证书与私钥的路径;proxy_pass:流量最终转发到哪,这里指向本机8080端口的后端;proxy_set_header 那一排:把访客的真实IP、原始协议等信息透传给后端,后面避坑环节会重点讲它。
改完配置先检测再重载,避免手一抖把线上服务打挂:
nginx -t # 检测语法是否正确
systemctl reload nginx # 平滑重载,不断开已有连接
重载完成后用浏览器访问 https://你的域名,地址栏出现小锁图标,就说明代理已经生效了。
四、进阶配置:WebSocket、超时和大文件
基础链路跑通后,实际业务里还有三个高频需求要补上。
如果你的站点用到WebSocket(在线客服、实时消息这类),需要单独加一段协议升级配置:
location /ws/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 300s;
}
如果后端接口响应慢(比如要跑复杂计算或调用第三方接口),默认超时可能不够,按需调大:
proxy_connect_timeout 60s;
proxy_send_timeout 120s;
proxy_read_timeout 300s;
上传大文件报413错误,是nginx默认限制请求体在10MB以内,加一行即可放开:
client_max_body_size 100m;
五、避坑指南:这些错误90%的人都踩过
配置本身不难,难的是各种奇奇怪怪的线上问题。下面这张表是高频坑位汇总,出了问题先对号入座:
| 现象 / 报错 | 常见原因 | 解决办法 |
|---|---|---|
| 浏览器提示证书不受信任 | 证书链不完整,缺中间证书 | 改用证书商提供的fullchain合并文件 |
| 页面能开但样式错乱、控制台一堆警告 | 混合内容:加密页面里加载了http资源 | 资源链接改成https或协议相对路径 |
| 502 Bad Gateway | 后端没启动或proxy_pass端口写错 | 先用curl测本机后端端口排查 |
| 504 Gateway Timeout | 后端响应太慢 | 调大proxy_read_timeout |
| 后端拿到的全是127.0.0.1 | 没有透传真实IP头 | 配置X-Real-IP和X-Forwarded-For |
| 访问陷入无限重定向 | 后端误判请求协议,不停发起跳转 | 透传X-Forwarded-Proto,后端按它判断 |
其中"真实IP"和"重定向循环"这两个坑最隐蔽。很多后端框架会根据请求协议生成跳转链接,经过nginx代理之后,如果不告诉它原始协议是https,它就以为是http,于是不停发起跳转,形成死循环。解决办法就是配置里那行 X-Forwarded-Proto $scheme,后端读这个头判断协议即可。
还有一个进阶坑:如果proxy_pass写的是https地址(全链路加密场景),nginx默认不会把域名通过SNI发出去,遇到按域名路由的网关就会握手失败,需要加两行:
proxy_ssl_server_name on;
proxy_ssl_name example.com;
六、nginx之外:出口IP的问题别忽略
最后聊一个容易被忽略的分工问题。nginx解决的是"入口"——让用户安全地访问你的服务。但有些业务的痛点其实在"出口"。
举个例子:你做数据采集,需要用大量不同的IP去请求目标网站;或者做批量任务执行,同一个IP高频访问很容易被对方限制。这种场景下,光有nginx是不够的,你需要一个稳定的代理IP资源池,让每个请求走不同的出口IP。
国内业务场景下,可以了解天启HTTP。它是国内的IP代理服务商,提供HTTP/HTTPS代理,支持高匿名与API批量提取,适合数据采集、批量任务执行等需要大量国内出口IP的业务。要注意的是,它只覆盖国内IP资源,如果你的业务需要访问海外站点,就不适用了。
一句话总结分工:nginx管入口的加密和转发,代理IP服务管出口的IP轮换,两者方向相反、各司其职,互不冲突。
常见问题
Q: nginx代理https后,后端服务还需要再配https吗?
不需要。默认方案是TLS终止在nginx层,nginx到后端走内网http即可,省证书也省性能。如果公司安全等级要求全链路加密,再把proxy_pass改成https地址,并按上文加上proxy_ssl_server_name配置。
Q: 一台服务器能挂多个https站点吗?
可以。为每个域名各写一个server块,都监听443 ssl,各自配各自的证书。现代浏览器都支持SNI扩展,同一台服务器、同一个IP上跑多个加密域名互不影响。
Q: 免费证书多久要续一次?
Let's Encrypt证书有效期90天,用certbot申请时会自动配置定时续期任务,基本不用操心;云厂商的免费证书一般有效期一年,到期前记得手动更换,避免临期忘换导致站点打不开。
Q: 配置完访问报握手失败或连接被重置怎么办?
按顺序排查三件事:一是云服务器安全组和防火墙是否放行了443端口;二是证书路径和权限是否正确,nginx -t能否通过;三是域名解析是否指向了这台服务器。绝大多数"握手失败"都出在这三步。
Q: 数据采集业务里,nginx和代理IP是什么关系?
两者方向相反。nginx是"入口"代理,负责接收外部访问你的服务;代理IP是"出口"代理,让你的请求以不同IP身份去访问别人。做采集时,目标网站看的是你的出口IP,所以需要天启HTTP这类国内代理IP服务来轮换出口,nginx在这条链路里帮不上忙。





