使用AWS的ELB服务时为Nginx启用代理协议的步骤讲解
在使用aws云服务的时候,90%要使用ELB服务作为负载均衡的解决方案,使用ELB要比自己搭建负载均衡要方便得多。
主要好处有:
1.可以随时监控实例的健康状态;
2.当服务器不正常时,ELB的报警策略将自动发送邮件通知运维人员
3.当服务器负载到达阈值时,通过autoscanning将自动加入新的服务器到集群中,同时负载降下去后将自动关闭多余的实例
4.ELB的各项监控指标较好地帮助判断服务器性能
AWSELBnginx启用代理协议
要使用awselb服务器来做websocket负载均衡时,只能使用tcp模式。
代理协议是一种Internet协议,用于将连接信息从请求连接的源传递到请求连接到的目标。ElasticLoadBalancing使用代理协议版本1,该版本使用用户可读的标头格式。
默认情况下,当对前端和后端连接使用传输控制协议(TCP)或安全套接字层(SSL)时,您的负载均衡器会将请求转发到后端实例,而不修改请求标头。如果您启用代理协议,则会向请求标头添加一个用户可读的标头,其中包含连接信息(如源IP地址、目标IP地址和端口号)。该标头随后作为请求的一部分发送到后端实例。
您可以在使用SSL和TCP协议的端口上启用代理协议。当使用非HTTP协议时,或者当使用HTTPS并且未在负载均衡器上终止SSL连接时,您可以使用代理协议捕获客户端的源IP。
代理协议头
在您使用为TCP/SSL连接配置的负载均衡器时,代理协议标头有助于识别客户端的IP地址。因为负载均衡器会拦截客户端与您的后端实例之间的流量,因此您的后端实例的访问日志中将包含负载均衡器的IP地址而不是原始客户端的IP地址。您可以分析该请求的第一行,以检索该客户端的IP地址和端口号。
IPv6标头中的代理地址是负载均衡器的公有IPv6地址。此IPv6地址与从该负载均衡器以ipv6或dualstack开头的DNS名称解析而来的IP地址相匹配。如果客户端使用IPv4进行连接,则代理标头中的地址是该负载均衡器的私有IPv4地址,不能在EC2-Classic网络外部通过DNS查找进行解析。
该代理协议行以回车符和换行符("\r\n")结束,且具有以下形式:
PROXY_STRING+singlespace+INET_PROTOCOL+singlespace+CLIENT_IP+singlespace+PROXY_IP+singlespace+CLIENT_PORT+singlespace+PROXY_PORT+"\r\n"
实例:
PROXYTCP4198.51.100.22203.0.113.73564680\r\n
安装AWSCLI工具
AWS管理控制台是不支持启用代理协议的,因此需要通过命令行来启用。
#sudoapt-getinstallpython-pip #sudopipinstallawscli
配置授权连接参数文件。
#sudovi~/.aws/config
[default] aws_access_key_id=YOU_ACCESS_ID aws_secret_access_key=YOU_SECRET_ID output=jsonORbsonORtext region=PREFERRED_AWS_REGION
类似这样的,aws_access_key_id、aws_secret_access_key、region根据你的aws实例填写。
AWSELB启用代理协议
查看ELB支持的策略。响应包含支持的策略类型的名称和描述。
#awselbdescribe-load-balancer-policy-types { "PolicyTypeDescriptions":[ ... { "PolicyAttributeTypeDescriptions":[ { "Cardinality":"ONE", "AttributeName":"ProxyProtocol", "AttributeType":"Boolean" } ], "PolicyTypeName":"ProxyProtocolPolicyType", "Description":"PolicythatcontrolswhethertoincludetheIPaddressandportoftheoriginating requestforTCPmessages.ThispolicyoperatesonTCP/SSLlistenersonly" }, ... ] }
创建启用代理协议的策略
#awselbcreate-load-balancer-policy--load-balancer-nameYOU_ELB_NAME--policy-nameEnableProxyProtocol--policy-type-nameProxyProtocolPolicyType--policy-attributesAttributeName=ProxyProtocol,AttributeValue=True
该命令创建了一个名称为EnableProxyProtocol的策略,并分配下列ELB属性"AttributeName=ProxyProtocol&AttributeValue=True"。
在指定端口上启用上述的策略
#awselbset-load-balancer-policies-for-backend-server--load-balancer-nameYOU_ELB_NAME--instance-port80--policy-namesEnableProxyProtocol #awselbset-load-balancer-policies-for-backend-server--load-balancer-nameYOU_ELB_NAME--instance-port81--policy-namesEnableProxyProtocol #awselbset-load-balancer-policies-for-backend-server--load-balancer-nameYOU_ELB_NAME--instance-port443--policy-namesEnableProxyProtocol
此命令将替代当前已启用的策略组。因此,--policy-names选项必须同时指定您正在添加到列表中的策略和任何当前已启用的策略。
查看是否启用
#awselbdescribe-load-balancers--load-balancer-nameYOU_ELB_NAME|jq'.LoadBalancerDescriptions[].BackendServerDescriptions' [ { "PolicyNames":[ "EnableProxyProtocol" ], "InstancePort":80 }, { "PolicyNames":[ "EnableProxyProtocol" ], "InstancePort":81 }, { "PolicyNames":[ "EnableProxyProtocol" ], "InstancePort":443 } ]
如果要禁用代理协议可以这么做,同时,可通过第4步查看是否禁用了。
#awselbset-load-balancer-policies-for-backend-server--load-balancer-nameYOU_ELB_NAME--instance-port80--policy-names"[]"
配置nginx接受代理协议头
nginx启用这个主要的目的是为了获取到真实的客户端IP地址。否则,都是ELB的内网IP地址。
set_real_ip_from127.0.0.1; set_real_ip_from10.0.0.0/8; real_ip_headerproxy_protocol; real_ip_recursiveon; server{ listen80proxy_protocol; listen443proxy_protocolssl; ... location/{ proxy_set_headerHost$host; proxy_set_headerX-Real-IP$proxy_protocol_addr; proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for; proxy_set_headerX-Forwarded-Prototcp; proxy_set_headerX-NginX-Proxytrue; ... } set_real_ip_from127.0.0.1; set_real_ip_from10.0.0.0/8; real_ip_headerproxy_protocol; real_ip_recursiveon; server{ listen80proxy_protocol; listen443proxy_protocolssl; ... location/{ proxy_set_headerHost$host; proxy_set_headerX-Real-IP$proxy_protocol_addr; proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for; proxy_set_headerX-Forwarded-Prototcp; proxy_set_headerX-NginX-Proxytrue; ... }
当nginx启用了代理协议,$proxy_protocol_addr变量将是真实的客户端IP。
如果没有反代,nginx这么配置即可:
log_formatelb_log'$proxy_protocol_addr-$remote_user[$time_local]''"$request"$status$body_bytes_sent"$http_referer"''"$http_user_agent"'; set_real_ip_from172.31.0.0/20; set_real_ip_from10.0.0.0/8; real_ip_headerproxy_protocol;