Nginx:broken_header with proxy_protocol和ELB

0wi1tuuw  于 2023-08-03  发布在  Nginx
关注(0)|答案(5)|浏览(285)

我正在尝试在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错误日志- wonky字符和所有。
下面是我的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;

  ...


我在网上找不到关于这个问题的任何帮助。其他人也有过坏头的问题,但是坏头的错误总是可读的--它们看起来不像是编码的,就像我一样。
有什么想法吗

ej83mcc0

ej83mcc01#

两点建议:
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"
  ]
}

字符串
1.您提到在ELB中启用了代理协议,因此我假设您遵循了AWS setup steps。如果是这样,那么ELB * 应该 * 正确地制作HTTP请求,第一行类似于PROXY TCP4 198.51.100.22 203.0.113.7 35646 80\r\n。但是,如果HTTP请求没有进入Nginx,并带有PROXY ...行,那么它可能会导致您看到的问题。你可以复制,如果你直接在浏览器中点击EC2 DNS名称,或者你ssh到EC2示例并尝试类似curl localhost的东西,那么你应该在Nginx日志中看到类似的破碎头错误。
要确定它是否能处理正确格式的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,以验证它是否正确设置。

7eumitmz

7eumitmz2#

我有类似的情况,nginx有'proxy_protocol',但AWS ELB设置没有打开,所以我得到了类似的消息。
编辑设置以将其打开的解决方案:


的数据

ff29svar

ff29svar3#

我也得到了这个不可读的标题问题,这里是原因和我如何修复它。
在我的例子中,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具有以下端口Map。

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
希望这对某人有帮助。

5ssjco0h

5ssjco0h4#

我遇到了这个错误,遇到了这个票:

这最终导致我发现我的nginx.conf文件中有一个不需要的proxy_protocol声明。我把它移走了,一切都恢复了正常。
奇怪的是,nginx版本1.8.0一切正常,但当我升级到nginx版本1.8.1时,我开始看到错误。

3htmauhk

3htmauhk5#

Stephen的solution above是正确的,您必须调整并确保配置ELB以支持代理。以下是AWS文档,用于执行此操作:http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/enable-proxy-protocol.html。文档一开始有点令人生畏,所以如果你愿意,你可以跳到Enable Proxy Protocol Using the AWS CLI部分下的步骤3和4。这些是启用代理通道的唯一必要步骤。此外,正如Stephen所建议的,您必须确保ELB使用的是TCP,而不是httphttps,因为这两种方式在ELB的代理实现中都不能正常工作。我建议将套接字通道从80和443等常见端口移开,这样您仍然可以使用它们的默认行为来维护这些标准化连接。当然,进行该调用完全取决于应用堆栈的外观。
如果有帮助的话,你可以使用npmwscat来调试你的WebSocket连接,如下所示:

$ npm install -g wscat
$ wscat --connect 127.0.0.1

字符串
如果连接在本地工作,那么它肯定是您的负载均衡器。但是,如果没有,几乎可以肯定您的套接字主机有问题。
此外,像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


您还可以在服务器中使用nmap来发现打开的端口。要在ubuntu上安装nmap,只需sudo apt-get install nmap。在osx上,brew install nmap
这是我的一个工作配置,虽然它目前不提供SSL支持。在这个配置中,我有 * 端口80* 为我的rails应用程序提供服务,* 端口81* 通过我的elb提供socket连接,* 端口82* 为内部socket连接打开。希望这对某人有帮助!!任何使用Rails、unicorn和Faye进行部署的人都应该会发现这很有帮助。:)happy hacking!

# sets up deployed ruby on rails server
upstream unicorn {
  server unix:/path/to/unicorn/unicorn.sock fail_timeout=0;
}

# sets up Faye socket
upstream rack_upstream {
  server 127.0.0.1:9292;
}

# sets port 80 to proxy to rails app
server {
  listen 80 default_server;
  keepalive_timeout 300;
  client_max_body_size 4G;
  root /path/to/rails/public;
  try_files $uri/index.html $uri.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded_Proto $scheme;
    proxy_redirect off;
    proxy_pass http://unicorn;
    proxy_read_timeout 300s;
    proxy_send_timeout 300s;
  }

  error_page 500 502 503 504 /500.html;
  location = /500.html {
    root /path/to/rails/public;
  }
}

# open 81 to load balancers (external socket connection)
server {
  listen 81 proxy_protocol;
  server_name _;
  charset UTF-8;
  location / {
    proxy_pass http://rack_upstream;
    proxy_redirect off;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }
}

# open 82 to internal network (internal socket connections)
server {
  listen 82;
  server_name _;
  charset UTF-8;
  location / {
    proxy_pass http://rack_upstream;
    proxy_redirect off;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }
}

相关问题