一、背景:https ELB後端nginx擷取不到真實用戶端IP
使用aws elb伺服器來做websocket負載均衡時,隻能使用tcp模式。
https 協定不在也可以選擇tcp模式,都有後端擷取不到真實用戶端IP問題,擷取都是elb IP位址
代理協定是一種 Internet 協定,用于将連接配接資訊從請求連接配接的源傳遞到請求連接配接到的目标。Elastic Load Balancing 使用代理協定版本 1,該版本使用使用者可讀的标頭格式。
TCP 負載均衡其實是把用戶端的請求截斷,然後自己發送一個請求給後端,拿到後端傳回的資料之後再傳回給 用戶端,這樣後端看到的是 負載均衡器的IP,看不到用戶端的真實IP了 (如果用基于HTTP的Load Balancer,會自動在HTTP頭記錄 X-Forwarded-For , 後端自然很容易擷取到源IP )。其實這和LVS FULLNAT 模式有點像,LVS FULLNAT的解決辦法是把真實IP寫在TCP option裡面,然後後端用toa子產品拿到。
對于這個問題,AWS給了一個解決辦法,叫做 Proxy Protocol ,可以對TCP 負載均衡器開啟Proxy Protocol,它會在請求的第一行寫入 源IP、源端口等資訊,以 \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”
二、安裝 AWS CLI (Command Line Interface)
1、安裝
在安裝 AWS CLI 後,将可執行檔案路徑添加到您的 PATH 變量中:
vim ~/.bash_profile
export PATH=~/.local/bin:$PATH # ~/.local/bin 添加到目前 PATH 變量中
source ~/.bash_profile
aws --version
2、配置通路密鑰
aws configure
# By default, its location is at ~/.aws/credentials:
[default]
aws_access_key_id = YOUR_ACCESS_KEY
aws_secret_access_key = YOUR_SECRET_KEY
三、AWS ELB 啟用代理協定 Proxy Protocol
1、為elb(名稱 YOU_ELB_NAME) 建立一個Proxy Protocol,叫 EnableProxyProtocol
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
# 注意 YOU_ELB_NAME 這裡改為你的elb名稱
2、為 YOU_ELB_NAME 激活 EnableProxyProtocol
aws elb set-load-balancer-policies-for-backend-server --load-balancer-name YOU_ELB_NAME --instance-port --policy-names EnableProxyProtocol
然後确認開啟
aws elb describe-load-balancers --load-balancer-name YOU_ELB_NAME
3、檢視是否啟用
aws elb describe-load-balancers --load-balancer-name YOU_ELB_NAME | jq '.LoadBalancerDescriptions[].BackendServerDescriptions'
[
{
"PolicyNames": [
"EnableProxyProtocol"
],
"InstancePort":
},
{
"PolicyNames": [
"EnableProxyProtocol"
],
"InstancePort":
}
]
4、如果要禁用代理協定可以這麼做,同時,可通過上一步檢視是否禁用了。
四、配置nginx接受代理協定頭
nginx 從1.5.12 版本開始支援Proxy Protocol ,隻需要配置一下就OK了
1、在http 裡面配置如下:
set_real_ip_from ./;
# 表示把來在10.0.0.0/8 段(TCP負載均衡器的IP段)的所有請求的來源位址,都改成 $proxy_protocol_addr,并且記錄在 $remote_addr 變量裡。
real_ip_header proxy_protocol;
這是日志格式:
log_format main '$remote_addr $request_method $http_host $request_uri '
'$status $request_time $body_bytes_sent $upstream_response_time $http_referer '
'$upstream_cache_status $http_x_forwarded_for $http_user_agent';
2、在server裡面linsten的時候開啟 proxy_protocol
listen proxy_protocol;
listen proxy_protocol;
參考位址:
https://docs.aws.amazon.com/zh_cn/elasticloadbalancing/latest/classic/enable-proxy-protocol.html
http://www.ttlsa.com/web/hang-aws-elb-services/
http://www.ttlsa.com/nginx/aws-elb-nginx-enable-proxy-protocol/