配置Nginx反向代理隐藏主服务器IP及多域名正确转发
Nginx反向代理转发到指定站点问题解决
问题背景
- 两台Nginx服务器:
- 服务器1:
192.168.xxx.xxx(LEMP主服务器,托管多个域名) - 服务器2:
128.111.xxx.xxx(作为反向代理使用)
- 服务器1:
- 核心需求:所有流量先经过服务器2,再转发到服务器1的
domain1.com站点;最终将服务器2的IP加入Cloudflare的A记录,隐藏主服务器IP - 当前问题:服务器2的转发请求匹配到了服务器1的默认站点,而非目标
domain1.com站点
当前配置
服务器2配置
upstream backend { server server1_IP; } server { listen 80; server_name domain1.com www.domain1.com; location / { proxy_pass http://backend; } }
服务器1默认站点配置
server { listen 80 default_server; listen [::]:80 default_server; listen 443 ssl http2; ssl_certificate /etc/ssl/master/master.crt; ssl_certificate_key /etc/ssl/master/master.key; root /var/www/html; index index.nginx-debian.html index.html index.htm index.php; server_name _; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/run/php/php7.4-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
服务器1 domain1.com站点配置
server { listen 80; listen 443 ssl http2; ssl_certificate /etc/ssl/domain1.com/domain1.com.crt; ssl_certificate_key /etc/ssl/domain1.com/domain1.com.key; root /var/www/html/domain1.com; index index.php index.html index.htm; error_log /var/log/nginx/domain1.com.error.log; server_name domain1.com www.domain1.com; location / { try_files $uri $uri/ /index.php?$args; } if ($http_user_agent ~* (BLEXBot|GrapeshotCrawler|MJ12bot|SemrushBot|AhrefsBot|DotBot) ) { return 301 http://127.0.0.1/; } location ~* /(?:uploads|files)/.*\.(asp|bat|cgi|htm|html|ico|js|jsp|md|php|pl|py|sh|shtml|swf|twig|txt|yaml|yml|zip|gz|tar|bzip2|7z)$ { deny all; } location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_param PHP_VALUE open_basedir="/tmp/:/usr/share/php/:/dev/urandom:/dev/shm:/var/lib/php/sessions/:$document_root"; fastcgi_pass unix:/run/php/php7.4-domain1.com-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location = /wp-login.php { limit_req zone=limit burst=1 nodelay; limit_req_status 429; fastcgi_pass unix:/run/php/php7.4-domain1.com-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { try_files $uri $uri/ /index.php?$args; allow all; log_not_found off; access_log off; } location ~* \.(js|jpg|jpeg|gif|png|css|tgz|gz|rar|bz2|doc|pdf|ppt|tar|wav|bmp|rtf|swf|ico|flv|txt|woff|woff2|svg)$ { expires 365d; } location ~ /\.ht { deny all; } location ~ /\.us { deny all; } location ~* "(base64_encode)(.*)(\()" { deny all; } location ~* "(eval\()" { deny all; } location = /xmlrpc.php { return 403; } rewrite ^/sitemap_index\.xml$ /index.php?sitemap=1 last; rewrite ^/([^/]+?)-sitemap([0-9]+)?\.xml$ /index.php?sitemap=$1&sitemap_n=$2 last; }
问题原因与解决方案
问题根源
服务器2转发请求时,未将原始请求的Host头传递给服务器1。Nginx默认会把Host头替换为proxy_pass目标的IP/域名,导致服务器1收到的Host是server1_IP,无法匹配domain1.com的站点配置,因此走了默认站点。
修复步骤
修改服务器2的Nginx配置,在location /块中添加传递Host头的参数,同时补充必要的代理参数保证请求正常:
upstream backend { server server1_IP; } server { listen 80; server_name domain1.com www.domain1.com; location / { proxy_pass http://backend; # 传递原始请求的Host头给后端服务器 proxy_set_header Host $host; # 传递真实客户端IP给后端(可选,方便服务器1日志记录真实访客IP) proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 传递协议信息(后续支持HTTPS时必备) proxy_set_header X-Forwarded-Proto $scheme; } }
额外配置建议
- HTTPS支持:若要启用HTTPS,在服务器2上配置对应域名的SSL证书(可使用Let's Encrypt免费证书),监听443端口,同时将
proxy_pass改为https://backend(需确保服务器1的443端口允许服务器2访问)。 - 服务器1安全限制:在服务器1的
domain1.com配置中添加规则,仅允许服务器2的IP访问,避免主服务器被直接访问:# 在server块开头添加 allow 128.111.xxx.xxx; deny all; - Cloudflare配置:将域名的A记录指向服务器2的IP,开启Cloudflare代理模式(橙色云朵图标),确保访客流量先经过Cloudflare再到服务器2。
验证方法
修改配置后,分别重启两台服务器的Nginx服务:
# 服务器2 sudo systemctl restart nginx # 服务器1 sudo systemctl restart nginx
访问domain1.com,检查是否加载目标站点内容;同时查看服务器1的domain1.com.error.log或访问日志,确认请求是否正确匹配到该站点。
内容的提问来源于stack exchange,提问作者Kisama
相关产品推荐
相关产品推荐

