nginx反向代理
2026-02-14
运维
00
请注意,本文编写于 49 天前,最后修改于 5 天前,其中某些信息可能已经过时。

目录

一、为什么需要反向代理?
1.1 直接暴露服务的风险
1.2 反向代理的核心价值
二、基础部署:单服务反向代理
2.1 后端服务启动(安全模式)
2.2 Nginx 安装与基础配置
2.3 核心配置文件详解
2.4 启用配置并验证
三、进阶场景:微服务路由分发
3.1 场景一:路径分发(单域名多服务)
3.2 场景二:子域名分发(多域名架构)
3.3 场景三:负载均衡(多实例高可用)
四、安全加固:生产环境必做
4.1 HTTPS 强制升级
4.2 IP 白名单限制
4.3 隐藏版本信息
五、性能优化:从能用到好用
5.1 启用压缩
5.2 静态资源缓存
5.3 连接优化
六、故障排查:常见问题速查
6.1 502 Bad Gateway
6.2 认证不生效
6.3 配置热重载失败
七、完整配置模板(生产可用)
总结

一、为什么需要反向代理?

1.1 直接暴露服务的风险

展开代码
# 危险做法:直接绑定公网IP python3 -m http.server 8000 --bind 0.0.0.0 # 任何IP都能访问
风险点说明
端口扫描攻击公网IP+开放端口易被扫描探测
无访问控制任何人可直接访问,无身份验证
单点故障直接暴露后端,无负载均衡能力
协议裸奔HTTP明文传输,无TLS加密

1.2 反向代理的核心价值

展开代码
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 客户端 │────→│ Nginx代理 │────→│ 真实服务 │ │ (公网用户) │ │ (安全网关) │ │ (内网隔离) │ └─────────────┘ └─────────────┘ └─────────────┘ ↑ ↑ ↑ 访问域名:443 监听0.0.0.0:443 监听127.0.0.1:8000 HTTPS加密 认证/限流/日志 仅本地可访问

反向代理的本质:把"直接访问"变成"间接访问",在中间层插入安全、性能、扩展的控制能力。


二、基础部署:单服务反向代理

2.1 后端服务启动(安全模式)

展开代码
# ✅ 正确做法:仅监听本地回环 python3 -m http.server 8000 --bind 127.0.0.1 & # 或Flask/FastAPI等框架 # app.run(host='127.0.0.1', port=8000) # 验证:只有本地能访问 curl http://127.0.0.1:8000 # ✅ 成功 curl http://192.168.1.100:8000 # ❌ 连接拒绝(安全)

绑定方式对比

绑定地址安全级别适用场景
0.0.0.0⭐⭐ 中内网可信环境,需同网段直接访问
127.0.0.1⭐⭐⭐⭐⭐ 高生产环境标准做法,强制走反向代理
192.168.x.x⭐⭐⭐ 中高多机内网通信,配合防火墙白名单

2.2 Nginx 安装与基础配置

展开代码
# 1. 安装 Nginx 和认证工具 sudo apt update sudo apt install nginx apache2-utils -y # 2. 生成 Basic Auth 密码文件 sudo htpasswd -c /etc/nginx/.htpasswd admin # 输入两次密码 # 添加更多用户(去掉 -c 参数,避免覆盖) sudo htpasswd /etc/nginx/.htpasswd user2

2.3 核心配置文件详解

展开代码
# /etc/nginx/sites-available/pyhttp server { # 监听端口:对外暴露的入口 listen 8001; # 服务器名:_ 表示匹配任何域名/IP server_name _; # 日志配置(建议开启,便于审计) access_log /var/log/nginx/pyhttp.access.log; error_log /var/log/nginx/pyhttp.error.log; location / { # ========== 认证层 ========== auth_basic "Restricted Access"; # 认证提示语 auth_basic_user_file /etc/nginx/.htpasswd; # 密码文件路径 # ========== 代理层 ========== proxy_pass http://127.0.0.1:8000; # 后端真实服务 # ========== 头部转发(关键)========== # 让后端知道原始域名(多域名场景必需) proxy_set_header Host $host; # 让后端知道真实客户端IP(日志/限流必需) 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; # ========== 性能优化 ========== # 启用连接复用(减少后端TCP建立开销) proxy_http_version 1.1; proxy_set_header Connection ""; # 缓冲区设置(根据内存调整) proxy_buffering on; proxy_buffer_size 4k; proxy_buffers 8 4k; # 超时设置(防止慢客户端拖死后端) proxy_connect_timeout 30s; proxy_send_timeout 30s; proxy_read_timeout 30s; } }

2.4 启用配置并验证

展开代码
# 创建软链接启用站点 sudo ln -s /etc/nginx/sites-available/pyhttp /etc/nginx/sites-enabled/ # 语法检查(必须做,避免配置错误导致Nginx崩溃) sudo nginx -t # 平滑重载配置(不断开现有连接) sudo systemctl reload nginx # 验证:8001端口已监听 sudo ss -tlnp | grep 8001 # 测试访问(应提示输入密码) curl -u admin:密码 http://localhost:8001

三、进阶场景:微服务路由分发

3.1 场景一:路径分发(单域名多服务)

展开代码
用户请求 Nginx路由 后端服务 ───────────────────────────────────────────────────────────────────── GET /api/users/ ──→ location /api/users/ ──→ 用户服务:8000 GET /api/orders/ ──→ location /api/orders/ ──→ 订单服务:8001 GET /api/products/ ──→ location /api/products/ ──→ 商品服务:8002
展开代码
# 上游服务池定义(放在http块内,server块外) upstream user_service { server 127.0.0.1:8000; keepalive 32; # 连接池,提升性能 } upstream order_service { server 127.0.0.1:8001; keepalive 32; } upstream product_service { server 127.0.0.1:8002; keepalive 32; } upstream payment_service { server 127.0.0.1:8003; keepalive 32; } server { listen 9000; server_name api.example.com; # 通用认证(所有location继承) auth_basic "Restricted Access"; auth_basic_user_file /etc/nginx/.htpasswd; # 用户服务 location /api/users/ { proxy_pass http://user_service; 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_read_timeout 60s; } # 订单服务 location /api/orders/ { proxy_pass http://order_service; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 订单接口限流(防止刷单) limit_req_zone $binary_remote_addr zone=order_limit:10m rate=10r/s; limit_req zone=order_limit burst=20 nodelay; } # 商品服务(静态资源缓存) location /api/products/ { proxy_pass http://product_service; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 商品列表缓存5分钟 proxy_cache_valid 200 5m; proxy_cache_key "$scheme$request_method$host$request_uri"; } # 支付服务(最高安全级别) location /api/payments/ { proxy_pass http://payment_service; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 仅允许HTTPS(配合外层TLS) if ($scheme != "https") { return 403; } # 支付接口严格限流 limit_req zone=payment_limit burst=5 nodelay; } # 健康检查端点(无需认证,供监控系统使用) location /health { auth_basic off; # 关闭认证 access_log off; # 关闭日志 return 200 "healthy\n"; add_header Content-Type text/plain; } }

3.2 场景二:子域名分发(多域名架构)

展开代码
users.example.com ──→ 127.0.0.1:8000 用户中心 orders.example.com ──→ 127.0.0.1:8001 订单系统 products.example.com ──→ 127.0.0.1:8002 商品服务
展开代码
# 用户服务子域名 server { listen 9000; server_name users.example.com; # 日志分离(按业务拆分,便于分析) access_log /var/log/nginx/users.access.log; error_log /var/log/nginx/users.error.log; location / { auth_basic "User Service"; auth_basic_user_file /etc/nginx/.htpasswd; proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 用户服务特定:大文件上传支持 client_max_body_size 50M; } } # 订单服务子域名 server { listen 9000; server_name orders.example.com; access_log /var/log/nginx/orders.access.log; error_log /var/log/nginx/orders.error.log; location / { auth_basic "Order Service"; auth_basic_user_file /etc/nginx/.htpasswd; proxy_pass http://127.0.0.1:8001; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 订单需要长连接(WebSocket支持) proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } # 商品服务子域名(静态资源加速) server { listen 9000; server_name products.example.com; access_log /var/log/nginx/products.access.log; # 静态资源直接由Nginx处理,不转发后端 location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { root /var/www/products/static; expires 30d; add_header Cache-Control "public, immutable"; } # API请求转发 location /api/ { auth_basic "Product Service"; auth_basic_user_file /etc/nginx/.htpasswd; proxy_pass http://127.0.0.1:8002; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }

3.3 场景三:负载均衡(多实例高可用)

展开代码
upstream user_service { # 加权轮询(weight越大,分配越多) server 127.0.0.1:8000 weight=3; server 127.0.0.1:8010 weight=2; server 127.0.0.1:8020 weight=2; # 备用服务器(主服务器全挂时启用) server 127.0.0.1:8030 backup; # 健康检查(Nginx Plus功能,开源版需第三方模块) # health_check interval=5 fails=3 passes=2; keepalive 64; # 连接池 keepalive_timeout 60s; # 连接保活时间 keepalive_requests 100; # 单连接最大请求数 } upstream order_service { # IP哈希(保证同一用户固定到同一后端,适用于有状态服务) ip_hash; server 127.0.0.1:8001; server 127.0.0.1:8111; # 最大失败次数和冷却时间 server 127.0.0.1:8222 max_fails=3 fail_timeout=30s; } upstream product_service { # 最少连接(适合请求处理时长不均的场景) least_conn; server 127.0.0.1:8002; server 127.0.0.1:8222; } server { listen 9000; # 全局限流配置 limit_req_zone $binary_remote_addr zone=global_limit:10m rate=100r/s; limit_req zone=global_limit burst=200 nodelay; location /users/ { proxy_pass http://user_service; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 连接错误时的处理 proxy_next_upstream error timeout http_502 http_503; proxy_next_upstream_tries 2; } location /orders/ { proxy_pass http://order_service; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location /products/ { proxy_pass http://product_service; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }

四、安全加固:生产环境必做

4.1 HTTPS 强制升级

展开代码
server { listen 80; server_name api.example.com; # 所有HTTP请求重定向到HTTPS return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; # http2提升性能 server_name api.example.com; # SSL证书(Let's Encrypt免费证书) ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem; # SSL安全配置 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers off; # HSTS(强制浏览器HTTPS访问) add_header Strict-Transport-Security "max-age=63072000" always; location / { # 原有代理配置... } }

4.2 IP 白名单限制

展开代码
location /admin/ { # 仅允许特定IP访问管理后台 allow 192.168.1.0/24; # 内网网段 allow 10.0.0.10; # 特定IP deny all; # 其他全部拒绝 proxy_pass http://127.0.0.1:8000; }

4.3 隐藏版本信息

展开代码
# /etc/nginx/nginx.conf 主配置 http { server_tokens off; # 隐藏Nginx版本号 # 自定义错误页面(防止信息泄露) error_page 500 502 503 504 /50x.html; location = /50x.html { root /var/www/html; internal; } }

五、性能优化:从能用到好用

5.1 启用压缩

展开代码
gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

5.2 静态资源缓存

展开代码
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ { expires 6M; # 半年 access_log off; add_header Cache-Control "public, immutable"; }

5.3 连接优化

展开代码
upstream backend { server 127.0.0.1:8000; # 连接池关键参数 keepalive 100; # 保持100个空闲连接 keepalive_requests 1000; # 单连接复用1000次 keepalive_timeout 60s; # 空闲连接保活60秒 }

六、故障排查:常见问题速查

6.1 502 Bad Gateway

展开代码
# 1. 检查后端服务是否运行 curl http://127.0.0.1:8000 # 2. 检查Nginx错误日志 sudo tail -f /var/log/nginx/error.log # 3. 常见原因 # - 后端未启动 # - 防火墙拦截 # - SELinux限制(setenforce 0 测试) # - 后端监听地址错误(应127.0.0.1而非localhost)

6.2 认证不生效

展开代码
# 检查密码文件权限(必须可读) sudo chmod 644 /etc/nginx/.htpasswd sudo chown www-data:www-data /etc/nginx/.htpasswd # 测试密码文件格式 cat /etc/nginx/.htpasswd # 应为:username:$apr1$xxxxx$xxxxx

6.3 配置热重载失败

展开代码
# 先测试语法 sudo nginx -t # 查看详细错误 sudo nginx -t 2>&1 | less # 紧急恢复(配置错误导致Nginx无法启动) sudo cp /etc/nginx/nginx.conf.bak /etc/nginx/nginx.conf sudo systemctl restart nginx

七、完整配置模板(生产可用)

展开代码
# /etc/nginx/sites-available/production upstream app_backend { server 127.0.0.1:8000; keepalive 64; } server { listen 80; server_name _; return 301 https://$host$request_uri; # 强制HTTPS } server { listen 443 ssl http2; server_name api.example.com; # SSL ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; ssl_protocols TLSv1.2 TLSv1.3; # 日志 access_log /var/log/nginx/api.access.log main; error_log /var/log/nginx/api.error.log warn; # 安全头 add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; # 全局限流 limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s; limit_req zone=api burst=200 nodelay; # 认证 auth_basic "Production API"; auth_basic_user_file /etc/nginx/.htpasswd; location / { proxy_pass http://app_backend; 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; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_connect_timeout 30s; proxy_send_timeout 30s; proxy_read_timeout 30s; proxy_next_upstream error timeout http_502 http_503; } location /health { auth_basic off; access_log off; return 200 "OK\n"; add_header Content-Type text/plain; } }

总结

场景推荐方案关键配置
单服务快速上线路径代理location / { proxy_pass }
多服务微服务upstream + location按路径或域名拆分
高可用生产环境负载均衡 + 健康检查weight/ip_hash/least_conn
安全敏感业务HTTPS + 认证 + 限流auth_basic + limit_req + TLS

反向代理是基础设施的守门员,投入时间做好配置,能大幅提升系统的安全性、可维护性和扩展性。

本文作者:zzz

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!