Nginx 实战:利用正则捕获实现子域名动态端口反向代理
在开发测试环境中,我们经常需要为多个本地服务配置外网访问。手动为每个端口编写 server 块不仅低效,而且难以维护。本文将介绍如何利用 Nginx 的正则表达式捕获功能,实现根据子域名自动转发到对应本地端口的“万能”反代配置。
1. 核心需求
实现一个动态规则:访问 [端口号].example.com 时,自动反向代理到本地服务器的 127.0.0.1:[端口号]。
例如:
- 访问
8080.example.com-> 转发至127.0.0.1:8080 - 访问
9000.example.com-> 转发至127.0.0.1:9000
2. Nginx 配置实现
以下是整合了正则捕获与 WebSocket 支持的完整配置模板:
# HTTP 自动跳转 HTTPS (可选)
server {
listen 80;
server_name ~^(?<target_port>\d+)\.example\.com$;
# 引用全局跳转配置
include extend/http_to_https.conf;
}
# HTTPS 核心配置
server {
listen 443 ssl;
# 【关键】使用正则命名分组捕获端口号到变量 $target_port
server_name ~^(?<target_port>\d+)\.example\.com$;
# 证书配置 (需确保证书支持通配符 *.example.com)
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
# 日志路径建议包含变量,方便排查不同服务的访问记录
access_log /data/wwwlogs/dynamic_proxy_$target_port_access.log combined;
error_log /data/wwwlogs/dynamic_proxy_error.log;
charset utf-8;
location / {
# 【关键】动态反代到本地对应的端口
proxy_pass http://127.0.0.1:$target_port;
# 标准头部转发与 WebSocket 支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_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;
}
}3. 关键技术点说明
3.1 正则表达式捕获
在 server_name 指令中,我们使用了 PCRE 命名分组语法:
~^(?<target_port>\d+)\.example\.com$;
~: 告诉 Nginx 这是一个正则表达式匹配。^和$: 匹配域名的开始和结束,确保匹配的精确性。(?<target_port>\d+): 匹配任意长度的数字,并将其赋值给变量$target_port。后续在proxy_pass中可以直接调用该变量。
3.2 动态代理转发
通过 proxy_pass http://127.0.0.1:$target_port;,Nginx 不再将请求发往固定的后端,而是根据当前访问的子域名动态决定目标端口。
4. 安全与部署建议
4.1 限制端口范围
上述配置会尝试转发任何端口,这可能导致未授权访问服务器内部服务。建议限制端口范围。例如,只允许转发 8000 到 8999 之间的端口:
server_name ~^(?<target_port>8\d{3})\.example\.com$;
4.2 证书匹配
请务必使用通配符证书(如 *.example.com)。单域名证书无法匹配动态生成的子域名。
4.3 静态资源与解析器
在某些复杂的 Nginx 版本中,如果在 proxy_pass 中使用了变量,Nginx 启动时可能无法解析地址。虽然转发到 127.0.0.1 通常无须担心,但若转发到域名,请务必在 location 块中添加 resolver 指令:
resolver 8.8.8.8 valid=30s;
4.4 日志管理
使用变量作为日志路径(如 access_log /data/wwwlogs/$target_port.log)虽然便于区分,但在并发量极大或端口极多时,会因打开过多文件句柄而消耗系统资源。生产环境下建议汇总到一个文件或定期清理。
总结:这种配置极大地简化了内部测试环境的部署工作,实现了“一劳永逸”的端口映射管理,是 DevOps 和后端开发者的实用小技巧。