Nginx:具有proxy_protocol和ELB的broken_header

时间:2015-11-09 23:20:05

标签: amazon-web-services nginx amazon-elb

我正在尝试在我的nginx配置中设置proxy_protocol。我的服务器位于AWS负载均衡器(ELB)后面,我为端口80和443启用了代理协议。

然而,这是我点击服务器时得到的结果:

broken header: "��/��
                                                             '���\DW�Vc�A{����
                                                                              �@��kj98���=5���g@32ED�</A
    " while reading PROXY protocol, client: 172.31.12.223, server: 0.0.0.0:443

这是来自nginx错误日志的直接复制粘贴 - 不稳定的字符和所有。

这是我的nginx配置中的剪辑:

server {
  listen  80 proxy_protocol;
  set_real_ip_from 172.31.0.0/20; # Coming from ELB
  real_ip_header proxy_protocol;
  return  301 https://$http_host$request_uri;
}

server {
  listen      443 ssl proxy_protocol;
  server_name *.....com
  ssl_certificate      /etc/ssl/<....>;
  ssl_certificate_key  /etc/ssl/<....?;
  ssl_prefer_server_ciphers On;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4;
  ssl_session_cache shared:SSL:10m;
  add_header X-Frame-Options DENY;
  add_header X-Content-Type-Options nosniff;
  ssl_stapling on;
  ssl_stapling_verify on;


  ...

我无法在线找到有关此问题的任何帮助。其他人已经破坏了标题问题,但标题错误的错误始终是可读的 - 他们看起来并不像他们那样编码。

有什么想法吗?

5 个答案:

答案 0 :(得分:11)

两个建议:

  1. 验证您的ELB侦听器是否配置为使用TCP作为协议,而不是HTTP。我有一个类似于以下的LB配置,它通过配置了proxy_protocol路由到Nginx:

    {
      "LoadBalancerName": "my-lb",
      "Listeners": [
         {
          "Protocol": "TCP",
          "LoadBalancerPort": 80,
          "InstanceProtocol": "TCP",
          "InstancePort": 80
        }
      ],
      "AvailabilityZones": [
        "us-east-1a",
        "us-east-1b",
        "us-east-1d",
        "us-east-1e"
      ],
      "SecurityGroups": [
         "sg-mysg"
      ]
    }
    
  2. 您提到您已在ELB中启用了代理协议,因此我假设您已关注AWS setup steps。如果是这样,那么ELB 应该正确地制作HTTP请求,第一行就像PROXY TCP4 198.51.100.22 203.0.113.7 35646 80\r\n一样。但是,如果HTTP请求没有进入带有PROXY ...行的Nginx,那么它可能会导致您遇到的问题。您可以重现,如果您直接在浏览器中点击EC2 DNS名称,或者您进入EC2实例并尝试curl localhost之类的内容,那么您应该会在Nginx日志中看到类似的断页错误。
  3. 要了解它是否适​​用于正确形成的HTTP请求,您可以使用telnet:

        $ telnet localhost 80
        PROXY TCP4 198.51.100.22 203.0.113.7 35646 80
        GET /index.html HTTP/1.1
        Host: your-nginx-config-server_name
        Connection: Keep-Alive
    

    然后检查Nginx日志,看看是否有相同的断页错误。如果没有,则ELB可能不会发送格式正确的PROXY请求,我建议重新进行ELB代理协议配置,可能使用新的LB,以验证其设置是否正确。

答案 1 :(得分:2)

我也遇到类似的情况,nginx启用了'proxy_protocol',但未启用AWS ELB设置,所以我收到了类似的消息。

编辑设置以将其打开的解决方案:

enter image description here

答案 2 :(得分:0)

Stephen Karger上面的解决方案是正确的,您必须调整以确保配置ELB以支持代理。以下是AWS文档:#{3}}。这些文档起初有点令人生畏,所以如果你想要,你可以跳到location = decodeURIComponent(selectedURL); 部分下的第3步和第4步。这些是启用代理通道的唯一必要步骤。此外,正如Stephen建议的那样,您必须确保您的ELB使用的是Enable Proxy Protocol Using the AWS CLI而不是TCPhttp,因为这两种情况都不能正常使用ELB的代理实现。我建议您将套接字通道从80和443等公共端口移开,这样您仍然可以使用默认行为维护这些标准化连接。当然,进行该调用完全取决于您的应用程序堆栈的外观。

如果有帮助,您可以使用httpsnpm调试您的websocket连接,如下所示:

wscat

如果连接在本地工作,那么肯定是您的负载均衡器。但是,如果它没有,那么套接字主机几乎肯定存在问题。

此外,像$ npm install -g wscat $ wscat --connect 127.0.0.1 这样的工具可以帮助您发现开放端口。一个很好的调试清单:

nmap

您还可以在服务器中使用nmap来发现开放端口。要在ubuntu上安装nmap,只需npm install -g wscat # can you connect to it from within the server? ssh ubuntu@69.69.69.69 wscat -c 127.0.0.1:80 # can you connect to it from outside the server? exit wscat -c 69.69.69.69:80 # if not, is your socket port open for business? nmap 69.69.69.69:80 。在osx上,sudo apt-get install nmap

这是我的工作配置,虽然它目前不提供ssl支持。在这个配置中,我有端口80 为我的rails应用程序提供,端口81 通过我的elb提供套接字连接,并且端口82 为内部打开套接字连接。希望这有助于某人!使用Rails,unicorn和Faye进行部署的人应该会发现这很有用。 :)快乐的黑客!

brew install nmap

答案 3 :(得分:0)

我遇到了这个错误并遇到了这张票:

最终让我发现我的proxy_protocol文件中有一个不需要的nginx.conf声明。我删除了它,一切都恢复了。

奇怪的是,nginx版本1.8.0一切正常,但当我升级到nginx版本1.8.1时,我才开始看到错误。

答案 4 :(得分:0)

我也遇到了这个不可读的标头问题,这是原因以及如何修复它。

就我而言,Nginx已正确配置了use-proxy-protocol=true。它抱怨标头损坏是因为AWS ELB根本没有添加所需的标头(例如PROXY TCP4 198.51.100.22 203.0.113.7 35646 80)。 Nginx直接看到加密的HTTPS有效负载。这就是为什么它会打印出所有不可读字符的原因。

那么,为什么AWS ELB不添加PROXY标头?原来,我在命令中使用了错误的端口来启用代理协议策略。应该使用实例端口,而不是80和443。

ELB具有以下端口映射。

80 -> 30440
443 -> 31772

命令应为

aws elb set-load-balancer-policies-for-backend-server \
  --load-balancer-name a19235ee9945011e9ac720a6c9a49806 \
  --instance-port 30440 \
  --policy-names ars-ProxyProtocol-policy

aws elb set-load-balancer-policies-for-backend-server \
  --load-balancer-name a19235ee9945011e9ac720a6c9a49806 \
  --instance-port 31272 \
  --policy-names ars-ProxyProtocol-policy

但是我误用了80和443。

希望这对某人有帮助。