reverse-proxy
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseReverse Proxy
反向代理
Configure reverse proxies to route traffic, terminate TLS, enforce rate limits, and serve as the gateway between clients and backend services.
配置反向代理以实现流量路由、TLS终止、速率限制,并作为客户端与后端服务之间的网关。
When to Use
适用场景
- Routing traffic from a public domain to one or more backend services.
- Terminating TLS at the edge and forwarding plain HTTP to backends.
- Adding rate limiting, CORS, security headers, and access control.
- Consolidating multiple services under a single domain with path-based routing.
- Handling WebSocket upgrades, gRPC proxying, or HTTP/2 passthrough.
- 将公网域名的流量路由至一个或多个后端服务。
- 在边缘节点终止TLS连接,向后端转发明文HTTP请求。
- 添加速率限制、CORS、安全标头及访问控制。
- 通过基于路径的路由将多个服务整合到单个域名下。
- 处理WebSocket升级、gRPC代理或HTTP/2透传。
Prerequisites
前置条件
- Backend service(s) running on known host:port.
- TLS certificate (Let's Encrypt, ACM, or self-signed for development).
- nginx 1.25+ or Traefik 3.x installed.
- DNS record pointing the domain to the proxy server.
- 后端服务已在已知的host:port上运行。
- 拥有TLS证书(可使用Let's Encrypt、ACM,或开发环境使用自签名证书)。
- 已安装Nginx 1.25+或Traefik 3.x。
- DNS记录已将域名指向代理服务器。
nginx Reverse Proxy
Nginx反向代理
Basic HTTPS Proxy with Redirect
基础HTTPS代理与重定向
nginx
undefinednginx
undefined/etc/nginx/sites-available/app.example.com
/etc/nginx/sites-available/app.example.com
server {
listen 80;
server_name app.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name app.example.com;
# TLS configuration
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Security headers
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
# Proxy to backend
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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;
# Timeouts
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
# Buffering
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
}}
undefinedserver {
listen 80;
server_name app.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name app.example.com;
# TLS configuration
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Security headers
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
# Proxy to backend
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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;
# Timeouts
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
# Buffering
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
}}
undefinedPath-Based Routing to Multiple Services
基于路径的多服务路由
nginx
server {
listen 443 ssl http2;
server_name app.example.com;
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
# Frontend SPA
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
}
# API backend
location /api/ {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 120s;
}
# WebSocket endpoint
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_set_header Host $host;
proxy_read_timeout 86400s; # 24h for long-lived connections
}
# Static assets with caching
location /static/ {
alias /var/www/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
}nginx
server {
listen 443 ssl http2;
server_name app.example.com;
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
# Frontend SPA
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
}
# API backend
location /api/ {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 120s;
}
# WebSocket endpoint
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_set_header Host $host;
proxy_read_timeout 86400s; # 24h for long-lived connections
}
# Static assets with caching
location /static/ {
alias /var/www/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
}Rate Limiting
速率限制
nginx
undefinednginx
undefinedDefine rate limit zones in http block
Define rate limit zones in http block
http {
# 10 requests/second per IP
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
# 1 request/second for login
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;
# Connection limit per IP
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;}
server {
listen 443 ssl http2;
server_name app.example.com;
# Apply rate limit to API
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
limit_req_status 429;
proxy_pass http://127.0.0.1:8080;
}
# Strict rate limit on auth endpoints
location /api/auth/ {
limit_req zone=login_limit burst=5;
limit_req_status 429;
proxy_pass http://127.0.0.1:8080;
}
# Connection limit
location / {
limit_conn conn_limit 100;
proxy_pass http://127.0.0.1:3000;
}}
undefinedhttp {
# 10 requests/second per IP
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
# 1 request/second for login
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;
# Connection limit per IP
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;}
server {
listen 443 ssl http2;
server_name app.example.com;
# Apply rate limit to API
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
limit_req_status 429;
proxy_pass http://127.0.0.1:8080;
}
# Strict rate limit on auth endpoints
location /api/auth/ {
limit_req zone=login_limit burst=5;
limit_req_status 429;
proxy_pass http://127.0.0.1:8080;
}
# Connection limit
location / {
limit_conn conn_limit 100;
proxy_pass http://127.0.0.1:3000;
}}
undefinedGzip and Brotli Compression
Gzip与Brotli压缩
nginx
http {
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
gzip_min_length 256;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
# Brotli (requires ngx_brotli module)
# brotli on;
# brotli_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
# brotli_comp_level 6;
}nginx
http {
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
gzip_min_length 256;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
# Brotli (requires ngx_brotli module)
# brotli on;
# brotli_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
# brotli_comp_level 6;
}Let's Encrypt with Certbot
使用Certbot配置Let's Encrypt证书
bash
undefinedbash
undefinedInstall certbot with nginx plugin
Install certbot with nginx plugin
sudo apt install certbot python3-certbot-nginx
sudo apt install certbot python3-certbot-nginx
Obtain and install certificate
Obtain and install certificate
sudo certbot --nginx -d app.example.com -d www.example.com
sudo certbot --nginx -d app.example.com -d www.example.com
Auto-renewal is configured via systemd timer
Auto-renewal is configured via systemd timer
sudo systemctl status certbot.timer
sudo systemctl status certbot.timer
Manual renewal test
Manual renewal test
sudo certbot renew --dry-run
undefinedsudo certbot renew --dry-run
undefinedTraefik Reverse Proxy
Traefik反向代理
Static Configuration
静态配置
yaml
undefinedyaml
undefinedtraefik.yml
traefik.yml
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
certificatesResolvers:
letsencrypt:
acme:
email: admin@example.com
storage: /letsencrypt/acme.json
httpChallenge:
entryPoint: web
providers:
docker:
exposedByDefault: false
file:
directory: /etc/traefik/dynamic/
api:
dashboard: true
insecure: false
log:
level: INFO
accessLog:
filePath: /var/log/traefik/access.log
undefinedentryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
certificatesResolvers:
letsencrypt:
acme:
email: admin@example.com
storage: /letsencrypt/acme.json
httpChallenge:
entryPoint: web
providers:
docker:
exposedByDefault: false
file:
directory: /etc/traefik/dynamic/
api:
dashboard: true
insecure: false
log:
level: INFO
accessLog:
filePath: /var/log/traefik/access.log
undefinedDynamic Configuration (File Provider)
动态配置(文件提供者)
yaml
undefinedyaml
undefined/etc/traefik/dynamic/services.yml
/etc/traefik/dynamic/services.yml
http:
routers:
app:
rule: "Host()"
entryPoints:
- websecure
service: app
tls:
certResolver: letsencrypt
middlewares:
- security-headers
- rate-limit
app.example.comapi:
rule: "Host(`app.example.com`) && PathPrefix(`/api`)"
entryPoints:
- websecure
service: api
tls:
certResolver: letsencryptservices:
app:
loadBalancer:
servers:
- url: "http://127.0.0.1:3000"
healthCheck:
path: /health
interval: 10s
timeout: 3s
api:
loadBalancer:
servers:
- url: "http://127.0.0.1:8080"
healthCheck:
path: /api/health
interval: 10s
timeout: 3smiddlewares:
security-headers:
headers:
stsSeconds: 63072000
stsIncludeSubdomains: true
frameDeny: true
contentTypeNosniff: true
browserXssFilter: true
referrerPolicy: strict-origin-when-cross-origin
rate-limit:
rateLimit:
average: 100
burst: 50
period: 1mundefinedhttp:
routers:
app:
rule: "Host()"
entryPoints:
- websecure
service: app
tls:
certResolver: letsencrypt
middlewares:
- security-headers
- rate-limit
app.example.comapi:
rule: "Host(`app.example.com`) && PathPrefix(`/api`)"
entryPoints:
- websecure
service: api
tls:
certResolver: letsencryptservices:
app:
loadBalancer:
servers:
- url: "http://127.0.0.1:3000"
healthCheck:
path: /health
interval: 10s
timeout: 3s
api:
loadBalancer:
servers:
- url: "http://127.0.0.1:8080"
healthCheck:
path: /api/health
interval: 10s
timeout: 3smiddlewares:
security-headers:
headers:
stsSeconds: 63072000
stsIncludeSubdomains: true
frameDeny: true
contentTypeNosniff: true
browserXssFilter: true
referrerPolicy: strict-origin-when-cross-origin
rate-limit:
rateLimit:
average: 100
burst: 50
period: 1mundefinedTraefik with Docker Labels
使用Docker Labels配置Traefik
yaml
undefinedyaml
undefineddocker-compose.yml
docker-compose.yml
version: "3.8"
services:
traefik:
image: traefik:v3.0
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml:ro
- letsencrypt:/letsencrypt
frontend:
image: my-frontend:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host()"
- "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
- "traefik.http.services.frontend.loadbalancer.server.port=3000"
app.example.comapi:
image: my-api:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host() && PathPrefix()"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
- "traefik.http.services.api.loadbalancer.server.port=8080"
- "traefik.http.routers.api.middlewares=api-ratelimit"
- "traefik.http.middlewares.api-ratelimit.ratelimit.average=50"
- "traefik.http.middlewares.api-ratelimit.ratelimit.burst=25"
app.example.com/apivolumes:
letsencrypt:
undefinedversion: "3.8"
services:
traefik:
image: traefik:v3.0
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml:ro
- letsencrypt:/letsencrypt
frontend:
image: my-frontend:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host()"
- "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
- "traefik.http.services.frontend.loadbalancer.server.port=3000"
app.example.comapi:
image: my-api:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host() && PathPrefix()"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
- "traefik.http.services.api.loadbalancer.server.port=8080"
- "traefik.http.routers.api.middlewares=api-ratelimit"
- "traefik.http.middlewares.api-ratelimit.ratelimit.average=50"
- "traefik.http.middlewares.api-ratelimit.ratelimit.burst=25"
app.example.com/apivolumes:
letsencrypt:
undefinednginx Testing and Management
Nginx测试与管理
bash
undefinedbash
undefinedTest configuration syntax
Test configuration syntax
sudo nginx -t
sudo nginx -t
Reload without downtime
Reload without downtime
sudo nginx -s reload
sudo nginx -s reload
View active connections
View active connections
sudo nginx -s status
sudo nginx -s status
Check which config file is active
Check which config file is active
nginx -V 2>&1 | grep -o '--conf-path=[^ ]*'
nginx -V 2>&1 | grep -o '--conf-path=[^ ]*'
Monitor access logs
Monitor access logs
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/access.log
Monitor error logs
Monitor error logs
tail -f /var/log/nginx/error.log
undefinedtail -f /var/log/nginx/error.log
undefinedIP Allowlisting and Geoblocking
IP白名单与地理封锁
nginx
undefinednginx
undefinedAllow only specific IPs (admin panel)
Allow only specific IPs (admin panel)
location /admin/ {
allow 203.0.113.0/24;
allow 198.51.100.5;
deny all;
proxy_pass http://127.0.0.1:3000;
}
location /admin/ {
allow 203.0.113.0/24;
allow 198.51.100.5;
deny all;
proxy_pass http://127.0.0.1:3000;
}
Block by country (requires GeoIP2 module)
Block by country (requires GeoIP2 module)
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
auto_reload 60m;
auto_reload 60m;
$geoip2_data_country_iso_code country iso_code;
$geoip2_data_country_iso_code country iso_code;
}
}
if ($geoip2_data_country_iso_code = "XX") {
if ($geoip2_data_country_iso_code = "XX") {
return 403;
return 403;
}
}
undefinedundefinedTroubleshooting
故障排查
| Symptom | Cause | Fix |
|---|---|---|
| 502 Bad Gateway | Backend not running or unreachable | Verify backend is listening; check |
| 504 Gateway Timeout | Backend too slow | Increase |
| Mixed content warnings | | Add |
| WebSocket disconnects after 60s | Default proxy timeout expires | Set |
| Rate limit hits legitimate users | Zone rate too aggressive | Increase |
| Let's Encrypt renewal fails | Port 80 blocked or wrong server block | Ensure |
| Traefik shows 404 for all routes | Docker labels not detected | Verify Docker socket is mounted; check |
| TLS handshake failure | Certificate chain incomplete | Include intermediate certificates in |
| 症状 | 原因 | 解决方法 |
|---|---|---|
| 502 Bad Gateway | 后端服务未运行或无法访问 | 验证后端服务是否在监听;检查 |
| 504 Gateway Timeout | 后端响应过慢 | 增大 |
| 混合内容警告 | 未设置 | 添加 |
| WebSocket连接60秒后断开 | 默认代理超时到期 | 为WebSocket路径设置 |
| 合法用户触发速率限制 | 速率限制规则过于严格 | 增大 |
| Let's Encrypt证书续期失败 | 80端口被阻塞或服务器块配置错误 | 确保 |
| Traefik所有路由返回404 | Docker标签未被识别 | 验证Docker套接字是否已挂载;检查 |
| TLS握手失败 | 证书链不完整 | 在 |
Related Skills
相关技能
- load-balancing - Multi-backend traffic distribution
- cdn-setup - CDN in front of reverse proxy
- dns-management - DNS records for proxy domains
- service-mesh - Service-level routing in Kubernetes
- 负载均衡 - 多后端流量分发
- CDN配置 - 在反向代理前端部署CDN
- DNS管理 - 代理域名的DNS记录配置
- 服务网格 - Kubernetes中的服务级路由