AWS ELB nginx 启用代理协议

默北 NginxAWS ELB nginx 启用代理协议已关闭评论18,3672字数 3584阅读11分56秒阅读模式

要使用aws elb服务器来做websocket负载均衡时,只能使用tcp模式。

代理协议是一种 Internet 协议,用于将连接信息从请求连接的源传递到请求连接到的目标。Elastic Load Balancing 使用代理协议版本 1,该版本使用用户可读的标头格式。文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/

默认情况下,当对前端和后端连接使用传输控制协议 (TCP) 或安全套接字层 (SSL) 时,您的负载均衡器会将请求转发到后端实例,而不修改请求标头。如果您启用代理协议,则会向请求标头添加一个用户可读的标头,其中包含连接信息(如源 IP 地址、目标 IP 地址和端口号)。该标头随后作为请求的一部分发送到后端实例。文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/

您可以在使用 SSL 和 TCP 协议的端口上启用代理协议。当使用非 HTTP 协议时,或者当使用 HTTPS 并且未在负载均衡器上终止 SSL 连接时,您可以使用代理协议捕获客户端的源 IP。文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/

代理协议头

在您使用为 TCP/SSL 连接配置的负载均衡器时,代理协议标头有助于识别客户端的 IP 地址。因为负载均衡器会拦截客户端与您的后端实例之间的流量,因此您的后端实例的访问日志中将包含负载均衡器的 IP 地址而不是原始客户端的 IP 地址。您可以分析该请求的第一行,以检索该客户端的 IP 地址和端口号。文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/

IPv6 标头中的代理地址是负载均衡器的公有 IPv6 地址。此 IPv6 地址与从该负载均衡器以 ipv6dualstack 开头的 DNS 名称解析而来的 IP 地址相匹配。如果客户端使用 IPv4 进行连接,则代理标头中的地址是该负载均衡器的私有 IPv4 地址,不能在 EC2-Classic 网络外部通过 DNS 查找进行解析。文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/

该代理协议行以回车符和换行符 ("\r\n") 结束,且具有以下形式:文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/

PROXY_STRING + single space + INET_PROTOCOL + single space + CLIENT_IP + single space + PROXY_IP + single space + CLIENT_PORT + single space + PROXY_PORT + "\r\n"文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/

实例:文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/

PROXY TCP4 198.51.100.22 203.0.113.7 35646 80\r\n文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/

安装AWS CLI工具

AWS 管理控制台是不支持启用代理协议的,因此需要通过命令行来启用。文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/

# sudo apt-get install python-pip
# sudo pip install awscli

配置授权连接参数文件。文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/

# sudo vi ~/.aws/config
[default]
aws_access_key_id = YOU_ACCESS_ID
aws_secret_access_key = YOU_SECRET_ID
output = json OR bson OR text
region = PREFERRED_AWS_REGION

类似这样的,aws_access_key_id、aws_secret_access_key、region根据你的aws实例填写。文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/

AWS ELB启用代理协议

  1. 查看ELB支持的策略。响应包含支持的策略类型的名称和描述。
    # aws elb describe-load-balancer-policy-types
    {
        "PolicyTypeDescriptions": [
            ...
            {
                "PolicyAttributeTypeDescriptions": [
                    {
                        "Cardinality": "ONE",
                        "AttributeName": "ProxyProtocol",
                        "AttributeType": "Boolean"
                    }
                ],
                "PolicyTypeName": "ProxyProtocolPolicyType",
                "Description": "Policy that controls whether to include the IP address and port of the originating 
    request for TCP messages. This policy operates on TCP/SSL listeners only"
            },
            ...
        ]
    }
  2. 创建启用代理协议的策略
    # aws elb create-load-balancer-policy --load-balancer-name YOU_ELB_NAME --policy-name EnableProxyProtocol --policy-type-name ProxyProtocolPolicyType --policy-attributes AttributeName=ProxyProtocol,AttributeValue=True

    该命令创建了一个名称为EnableProxyProtocol的策略,并分配下列ELB属性"AttributeName=ProxyProtocol & AttributeValue=True"。

  3. 在指定端口上启用上述的策略
    # aws elb set-load-balancer-policies-for-backend-server --load-balancer-name YOU_ELB_NAME --instance-port 80 --policy-names EnableProxyProtocol
    # aws elb set-load-balancer-policies-for-backend-server --load-balancer-name YOU_ELB_NAME --instance-port 81 --policy-names EnableProxyProtocol
    # aws elb set-load-balancer-policies-for-backend-server --load-balancer-name YOU_ELB_NAME --instance-port 443 --policy-names EnableProxyProtocol

    此命令将替代当前已启用的策略组。因此,--policy-names 选项必须同时指定您正在添加到列表中的策略和任何当前已启用的策略。

  4. 查看是否启用
    # aws elb describe-load-balancers --load-balancer-name YOU_ELB_NAME | jq '.LoadBalancerDescriptions[].BackendServerDescriptions'
    [
      {
        "PolicyNames": [
          "EnableProxyProtocol"
        ],
        "InstancePort": 80
      },
      {
        "PolicyNames": [
          "EnableProxyProtocol"
        ],
        "InstancePort": 81
      },
      {
        "PolicyNames": [
          "EnableProxyProtocol"
        ],
        "InstancePort": 443
      }
    ]
  5. 如果要禁用代理协议可以这么做,同时,可通过第4步查看是否禁用了。
    # aws elb set-load-balancer-policies-for-backend-server --load-balancer-name YOU_ELB_NAME --instance-port 80 --policy-names "[]"

配置nginx接受代理协议头

nginx启用这个主要的目的是为了获取到真实的客户端IP地址。否则,都是ELB的内网IP地址。文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/

set_real_ip_from 127.0.0.1;
set_real_ip_from 10.0.0.0/8;
real_ip_header    proxy_protocol;
real_ip_recursive on;

server {
    listen 80 proxy_protocol;
    listen 443 proxy_protocol ssl;
...
    location / {
      proxy_set_header  Host                $host;
      proxy_set_header  X-Real-IP           $proxy_protocol_addr;
      proxy_set_header  X-Forwarded-For     $proxy_add_x_forwarded_for;
      proxy_set_header  X-Forwarded-Proto   tcp;
      proxy_set_header  X-NginX-Proxy       true;
...
}

当nginx启用了代理协议,$proxy_protocol_addr变量将是真实的客户端IP。文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/

如果没有反代,nginx这么配置即可:文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/

log_format elb_log '$proxy_protocol_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent "$http_referer" ' '"$http_user_agent"';

set_real_ip_from 172.31.0.0/20;
set_real_ip_from 10.0.0.0/8;
real_ip_header proxy_protocol;
文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/文章源自运维生存时间-https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/
weinxin
我的微信
微信公众号
扫一扫关注运维生存时间公众号,获取最新技术文章~
默北
  • 本文由 发表于 23/09/2015 01:00:09
  • 转载请务必保留本文链接:https://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/