Nginx 代理多个 IP 地址用于 CMS 网站预览

Nginx 代理多个 IP 地址用于 CMS 网站预览

第一次发帖,所以请多包涵。

我对 Nginx 还比较陌生,但已经设法弄清楚我需要什么......直到现在。

Nginx v1.0.15 代理 PHP-FPM v.5.3.10,后者正在监听http://127.0.0.1:9000。[敲木头] 就托管我们的 CMS 和许多网站而言,一切都运行顺利。

现在,我们已经开发了我们的 CMS 并配置了 Nginx,以便每个支持的网站都有一个预览 URL(例如http://[网站ID].ourcms.com/),您猜对了,在 DNS 还不能解析到我们的服务器的情况下,可以预览网站,等等。

具体来说,我们使用 Nginx 的 Map 模块(http://wiki.nginx.org/HttpMapModule) 和 CMSserver{ }块的 server_name 中的正则表达式,以 1) 从网站的预览 URL 中查找网站的主域名,然后 2) 将请求转发到“匹配的”主域。

对应的Nginx配置:

map $host $h {
    123.ourcms.com  www.example1.com;
    456.ourcms.com  www.example2.com;
    789.ourcms.com  www.example3.com;
}

server {
    listen              [OurCMSIPAddress]:80;
    listen              [OurCMSIPAddress]:443 ssl;
    root                /var/www/ourcms.com;
    server_name         ~^(.*)\.ourcms\.com$;
    ssl_certificate     /etc/nginx/conf.d/ourcms.com.chained.crt;
    ssl_certificate_key /etc/nginx/conf.d/ourcms.com.key;

    location / {
        proxy_pass http://127.0.0.1/;
        proxy_set_header Host $h;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

(注意:我确实意识到出于安全原因,server_name 中的正则表达式应该“更严格”,并且仅匹配网站 ID 的格式(即我们例子中的 UUID)。)

此配置适用于我们 99% 的站点……除了那些已安装 SSL 证书的专用 IP 地址的站点。这些站点会返回“502 Bad Gateway”,我不确定原因。

这就是我思考当前配置适用于任何与正则表达式匹配的请求(例如http://123.ourcms.com/):

  1. Nginx 从映射中查找网站的主域名,然后
  2. 作为该指令的结果proxy_pass http://127.0.0.1,将请求传递回 Nginx 本身,
  3. 由于代理请求具有与网站主域名相对应的主机名,因此通过proxy_set_header Host $h指令,Nginx 会将该请求视为该主机名的直接请求。

如果我的理解有误,请纠正我。

我应该代理这些网站的专用 IP 地址吗?我试过了,但似乎不起作用?代理模块中是否有我遗漏的设置?

谢谢您的帮助。

MB

答案1

除非那些拥有已安装 SSL 证书的专用 IP 地址的用户。

在我看来,您只监听一个 IP 地址。您还需要为 SSL 域的其他 IP 设置“监听”指令。除非您有通配符 SSL 证书,否则我认为您需要为每个主机设置一个 server{} 定义。

以下是我使用的相关模式,如果您尝试避免完全手动维护 SSL Nginx 域的配置,它可能会有所帮助:

我的 Nginx 配置的一部分作为模板存储在源代码管理下。Nginx 的“init”脚本已被修改,因此每次重新加载或重新启动 Nginx 时,都会调用一个 Perl 脚本,根据环境(alpha、beta、生产等)填充模板变量。写出一个新的纯文本文件,Nginx 将“渲染”模板作为包含文件包含。

这为自动化和 DRY 提供了新的可能性。也许这对您的情况有帮助。

答案2

对于任何可能偶然遇到此问题的人,解决方案是以下 Nginx 配置:

# Map preview URLs to shared or dedicated IP addresses
map $host $i {
        default         [IP for Shared VHosts];

        123.ourcms.com  [Dedicated IP Address 1];   # www.example1.com;
        456.ourcms.com  [Dedicated IP Address 2];   # www.example2.com;
        789.ourcms.com  [Dedicated IP Address 3];   # www.example3.com;
}

# Map preview URLS to appropriate hostname
map $host $h {

        123.ourcms.com   www.example1.com;
        456.ourcms.com   www.example2.com;
        789.ourcms.com   www.example3.com;
}

...

# Configuration for "preview" server 
server {
    listen                  [OurCMSIPAddress]:80;
    listen                  [OurCMSIPAddress]:443 ssl;
    error_log               /var/log/nginx/error-ourcms.com.log debug;
    root                    /var/www/ourcms.com;
    server_name             ~^(.*)\.ourcms\.com$;
    ssl_certificate         /etc/nginx/conf.d/ourcms.com.chained.crt;
    ssl_certificate_key     /etc/nginx/conf.d/ourcms.com.key;

    location / {
        proxy_pass http://$i;
        proxy_set_header Host $h;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

这个诀窍是查找主机名,我认为@MarkStosberg 暗示了这一点,但我不明白预览网站的 IP 地址。此外,每个虚拟主机的服务器块必须包含listen [SharedIPForVhosts]:80,而不仅仅是listen *:80

相关内容