在Nginx中实现子域名代理的核心原理是基于HTTP请求头中的Host字段进行虚拟主机(Server Block)路由。当请求到达Nginx时,Nginx会根据监听端口和server_name匹配对应的配置块,并将请求通过proxy_pass指令转发到指定的上游服务器。这一机制常用于多子域名指向同一台服务器但由不同后端应用处理的场景,例如api.example.com转发到后端API服务,docs.example.com转发到文档站点。

以下是一个基础的子域名代理配置示例。假设你拥有域名example.com,需要将子域名app.example.com代理到本机端口3000上的Node.js服务:
首先,在Nginx配置目录(通常是/etc/nginx/conf.d/或/etc/nginx/sites-available/)中新建一个配置文件,例如app.example.com.conf。文件内容如下:
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}
上述配置中,listen 80表示监听HTTP默认端口;server_name app.example.com用于精确匹配子域名;proxy_pass http://127.0.0.1:3000将匹配到的请求转发至本机3000端口。通过proxy_set_header设置相关请求头,使后端应用能够获取到原始的Host、客户端IP和协议信息,这对于处理重定向、日志记录和防盗链等需求非常重要。
如果需要代理多个子域名,可以创建多个server块,每个块对应一个子域名。例如,同时代理api.example.com到本机8080端口和admin.example.com到本机8081端口。配置如下:
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 80;
server_name admin.example.com;
location / {
proxy_pass http://127.0.0.1:8081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
当域名解析到服务器后,需要确保DNS记录中存在对应的A记录或CNAME记录,将子域名指向Nginx所在服务器的公网IP。否则外部用户无法通过子域名访问到Nginx。
对于使用HTTPS的情况,需要为每个子域名配置SSL证书。可以使用Let's Encrypt等免费证书颁发机构。Nginx配置中需要添加listen 443 ssl以及ssl_certificate和ssl_certificate_key指令。同时,建议增加HTTP到HTTPS的重定向。示例:
server {
listen 443 ssl;
server_name app.example.com;
ssl_certificate /etc/nginx/ssl/app.example.com.crt;
ssl_certificate_key /etc/nginx/ssl/app.example.com.key;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}
server {
listen 80;
server_name app.example.com;
return 301 https://$host$request_uri;
}
除了基础代理,还需要注意WebSocket代理、请求体大小限制、超时时间设置和负载均衡等高级场景。若后端为WebSocket服务,需要在location中添加以下请求头:
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
因为WebSocket协议需要HTTP/1.1和Upgrade机制,Nginx默认的HTTP/1.0不支持连接升级。此外,若涉及大文件上传,可以设置client_max_body_size;若需要调整后端响应时间,可设置proxy_read_timeout等参数。
在配置完成后,需要验证Nginx配置是否正确。使用命令nginx -t检查语法,若输出syntax is ok和test is successful,则重新加载配置:nginx -s reload。加载后即可生效,无需重启服务。
常见的错误场景包括:server_name拼写错误导致匹配失败;proxy_pass结尾的路径处理问题,例如在location中使用正则或不带URI的proxy_pass会影响转发路径;以及域名未解析到当前服务器。正确理解proxy_pass的URI替换规则也很关键:如果proxy_pass不带URI(即仅包含协议、主机和端口),则请求的原始URI会原样传递;如果带URI且location使用了前缀匹配,则匹配部分会被替换。例如:
location /api/ {
proxy_pass http://127.0.0.1:8080;
}
此时,请求/api/user会转发到http://127.0.0.1:8080/api/user。若改为proxy_pass http://127.0.0.1:8080/,则请求会转发到http://127.0.0.1:8080/user,即/api/被替换为/。这一规则在配置子域名代理时同样适用,需要根据后端接口路径严格设计。
最后,对于泛域名代理,即所有子域名都指向同一后端或不同后端,可以使用server_name *.example.com配合正则捕获或变量动态设置proxy_pass。例如:
server {
listen 80;
server_name *.example.com;
location / {
proxy_pass http://backend_pool;
proxy_set_header Host $host;
}
}
但需要谨慎使用通配符,因为它会匹配所有未精确匹配的子域名,可能造成安全风险。在配置中,还可以使用upstream定义一组后端服务器,实现子域名代理的负载均衡。例如:
upstream backend_app {
server 192.168.1.10:3000;
server 192.168.1.11:3000;
}
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://backend_app;
proxy_set_header Host $host;
}
}
总之,Nginx代理子域名是一种成熟的反向代理方案,核心在于server_name与proxy_pass的配合,同时需要注意请求头传递、SSL配置、WebSocket支持以及路径重写等细节。实际生产环境中应根据后端架构和安全需求灵活调整配置,并定期检查Nginx错误日志(/var/log/nginx/error.log)以排除故障。

查看详情

查看详情