使用AWS的ELB服務時為Nginx啟用代理協(xié)議的步驟講解
投稿:goldensun
在使用aws云服務的時候,90%要使用ELB服務作為負載均衡的解決方案,使用ELB要比自己搭建負載均衡要方便得多。
主要好處有:
1.可以隨時監(jiān)控實例的健康狀態(tài);
2.當服務器不正常時,ELB的報警策略將自動發(fā)送郵件通知運維人員
3.當服務器負載到達閾值時,通過auto scanning將自動加入新的服務器到集群中,同時負載降下去后將自動關閉多余的實例
4.ELB的各項監(jiān)控指標較好地幫助判斷服務器性能
AWS ELB nginx 啟用代理協(xié)議
要使用aws elb服務器來做websocket負載均衡時,只能使用tcp模式。
代理協(xié)議是一種 Internet 協(xié)議,用于將連接信息從請求連接的源傳遞到請求連接到的目標。Elastic Load Balancing 使用代理協(xié)議版本 1,該版本使用用戶可讀的標頭格式。
默認情況下,當對前端和后端連接使用傳輸控制協(xié)議 (TCP) 或安全套接字層 (SSL) 時,您的負載均衡器會將請求轉發(fā)到后端實例,而不修改請求標頭。如果您啟用代理協(xié)議,則會向請求標頭添加一個用戶可讀的標頭,其中包含連接信息(如源 IP 地址、目標 IP 地址和端口號)。該標頭隨后作為請求的一部分發(fā)送到后端實例。
您可以在使用 SSL 和 TCP 協(xié)議的端口上啟用代理協(xié)議。當使用非 HTTP 協(xié)議時,或者當使用 HTTPS 并且未在負載均衡器上終止 SSL 連接時,您可以使用代理協(xié)議捕獲客戶端的源 IP。
代理協(xié)議頭
在您使用為 TCP/SSL 連接配置的負載均衡器時,代理協(xié)議標頭有助于識別客戶端的 IP 地址。因為負載均衡器會攔截客戶端與您的后端實例之間的流量,因此您的后端實例的訪問日志中將包含負載均衡器的 IP 地址而不是原始客戶端的 IP 地址。您可以分析該請求的第一行,以檢索該客戶端的 IP 地址和端口號。
IPv6 標頭中的代理地址是負載均衡器的公有 IPv6 地址。此 IPv6 地址與從該負載均衡器以 ipv6 或 dualstack 開頭的 DNS 名稱解析而來的 IP 地址相匹配。如果客戶端使用 IPv4 進行連接,則代理標頭中的地址是該負載均衡器的私有 IPv4 地址,不能在 EC2-Classic 網(wǎng)絡外部通過 DNS 查找進行解析。
該代理協(xié)議行以回車符和換行符 ("\r\n") 結束,且具有以下形式:
PROXY_STRING + single space + INET_PROTOCOL + single space + CLIENT_IP + single space + PROXY_IP + single space + CLIENT_PORT + single space + PROXY_PORT + "\r\n"
實例:
PROXY TCP4 198.51.100.22 203.0.113.7 35646 80\r\n
安裝AWS CLI工具
AWS 管理控制臺是不支持啟用代理協(xié)議的,因此需要通過命令行來啟用。
# sudo apt-get install python-pip # sudo pip install awscli
配置授權連接參數(shù)文件。
# 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根據(jù)你的aws實例填寫。
AWS ELB啟用代理協(xié)議
查看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"
},
...
]
}
創(chuàng)建啟用代理協(xié)議的策略
# 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
該命令創(chuàng)建了一個名稱為EnableProxyProtocol的策略,并分配下列ELB屬性"AttributeName=ProxyProtocol & AttributeValue=True"。
在指定端口上啟用上述的策略
# 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 選項必須同時指定您正在添加到列表中的策略和任何當前已啟用的策略。
查看是否啟用
# 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
}
]
如果要禁用代理協(xié)議可以這么做,同時,可通過第4步查看是否禁用了。
# aws elb set-load-balancer-policies-for-backend-server --load-balancer-name YOU_ELB_NAME --instance-port 80 --policy-names "[]"
配置nginx接受代理協(xié)議頭
nginx啟用這個主要的目的是為了獲取到真實的客戶端IP地址。否則,都是ELB的內(nèi)網(wǎng)IP地址。
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;
...
}
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啟用了代理協(xié)議,$proxy_protocol_addr變量將是真實的客戶端IP。
如果沒有反代,nginx這么配置即可:
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;