在 AWS ELB 后面使用 NGINX 剥离 www

在 AWS ELB 后面使用 NGINX 剥离 www

我正在尝试从我的请求 URL 中删除 www,但是当我将以下内容添加到我的 nginx 配置时,我的 AWS ELB 运行状况检查失败。

server {
    listen 80;
    server_name www.example.com;
    return 301 $scheme://example.com$request_uri;
}

知道是什么原因导致的吗?这是我的其余配置:

server {

    listen 80;

    server_name .example.com;
    root /var/www/static;
    index index.html;

    try_files $uri.html $uri $uri/ =404;

    charset UTF-8;

    error_log /var/log/error.log;
    access_log /var/log/access.log;

    # ELB test route
    location /test {
        add_header X-Robots-Tag noindex;
        default_type text/plain; 
        return 200 'success';
    }

    # Redirect any request http request that come from AWS ELB to https
    if ($http_x_forwarded_proto = "http") {
        return 301 https://$server_name$request_uri;
    }
}

这是我的健康检查设置:

AWS 目标组健康检查

答案1

来自亚马逊文档

为确保您的负载均衡器可以正确扩展,请验证负载均衡器的每个子网是否都具有至少带有 /27 位掩码的 CIDR 块(例如 10.0.0.0/27)并且至少具有 8 个可用 IP 地址。您的负载均衡器使用这些 IP 地址与实例建立连接。

这听起来好像 ELB 健康检查是通过 AWS 私有 IP 而不是域名进行的。据我对亚马逊的了解,这是他们在可能的情况下更喜欢做的事情(出于明显的性能原因,不需要 DNS 查找,可以由更近的路由器处理,等等)。

如果是这种情况,那么主机标头(除非它是空白的,我不能 100% 确定当您向裸 IP 发出请求时主机标头如何工作)将是运行 Web 服务器的 EC2 实例(我假设它是 EC2)的私有 AWS 地址。这会影响 Nginx 选择哪个虚拟服务器应处理请求的方式。

由于 Nginx 有两个server块,它必须决定哪个块接收任何给定的请求。它选择服务器块的过程(详细信息这里)如下:

  • 首先,它查找监听请求传入端口的服务器。在这种情况下,两个服务器都在监听同一个端口,因此这没有任何帮助。

  • 然后它查看请求的主机标头,并查找与server_name主机标头匹配的服务器。在这种情况下,它们都不会匹配,因为主机标头是分配给实例的私有 AWS IP(或空白,正如我所说,我不确定。)

  • 最后,如果上述两个都不匹配,则直接使用默认服务器。在没有明确声明默认的情况下,将使用定义的服务器第一的在站点配置中被选择为默认配置。

如果您的重定向服务器位于主服务器配置之前(我猜是这样),那么这可能是您的问题。您需要做以下三件事之一:

  • 指定您想要其他default_server通过添加到指令将服务器(主服务器)设置为默认服务器listen,即listen 80 default_server;

  • 将块切换location /test到其他服务器块,或者

  • 反转服务器块定义的顺序。

第一个选项似乎是可行的,因为指令default_server显式而不是隐式是有意义的,并且主服务器作为默认服务器而不是你只有一个作业的重定向服务器是有意义的。

如果我的假设正确,那应该可以解决问题。

答案2

根据我使用 AWS ELB I/F 配置的经验,我可以提供以下建议

  1. 定义位置/{} 块
  2. 你最好使用 location = /test {} 块精确匹配 URL
  3. 您最好使用特殊的 server_name _ 并写入 location = /test {} 块。

參考文獻:
http://nginx.org/en/docs/http/ngx_http_core_module.html#server_name


server {

    listen 80;

    # changed for 1. "anonymous server" (without Host: header) will accept request.
    server_name _ .example.com;
    root /var/www/static;
    index index.html;

    try_files $uri.html $uri $uri/ =404;

    charset UTF-8;

    error_log /var/log/error.log;
    access_log /var/log/access.log;


    # changed for 1. defined location / {} for default behavior
    location / {
        try_files $uri $uri/ =404;
    }
    # ELB test route
    # changed for 2. exactly match only /test request
    location = /test {
        add_header X-Robots-Tag noindex;
        default_type text/plain; 
        return 200 'success';
    }

    # Redirect any request http request that come from AWS ELB to https
    if ($http_x_forwarded_proto = "http") {
        return 301 https://$server_name$request_uri;
    }
}

相关内容