
# 在四层独享型ELB转发下获取客户端真实IP
#### 应用场景
在使用弹性负载均衡进行业务转发时，您可能需要获取客户端请求的真实IP地址进行进一步分析，特别是在安全防护、数据分析、用户行为分析和故障排查等典型业务场景。
使用ELB进行四层业务转发时，默认情况下ELB实例与后端服务器之间直接使用客户端的IP地址通信，后端服务器可以直接获取客户端真实IP地址。但是在ELB实例与IP类型后端通信、TCP或UDP监听器开启IPv4/IPv6地址转换、使用TLS监听器进行转发等场景，客户端真实IP经过独享型ELB实例时会发生转换，您可以参考本文获取四层业务转发场景的客户端真实IP地址。
#### 约束与限制
- 如果请求经过NAT网关，则只能获取到NAT转换后的IP地址，无法获取NAT转化前的IP地址。
- 如果请求客户端为容器，则只能获取到容器所在主机的IP地址，无法获取容器的IP地址。
 
- 四层监听器（TCP/UDP）默认开启"获取客户端IP"功能，不支持同一台服务器既作为后端服务器又作为客户端的场景。 如果后端服务器和客户端使用同一台服务器，则后端服务器会根据报文源IP为本地IP判定该报文为本机发出的报文，无法将应答报文返回给ELB，最终导致回程流量不通。
  
#### 四层服务获取客户端真实IP方法介绍
独享型ELB的四层协议监听器（TCP/UDP）默认支持"获取客户端IP"功能，ELB实例与后端服务器之间直接使用客户端真实的IP地址通信。
部分特殊场景，监听器的"获取客户端IP"功能失效，您可以参考[表1]在四层业务转发场景获取客户端真实IP。
 表1四层监听获取客户端真实IP方法总结 
| 监听器    | 监听器的"获取客户端IP"功能                                              | 特殊场景获取客户端真实IP                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
|:---|:---|:---|
| TCP监听器 | [TCP/UDP监听器默认支持"获取客户端IP"] | 以下场景监听器的"获取客户端IP"功能失效，您可以通过[配置TOA插件]或[通过ProxyProtocol协议]获取客户端真实IP： - TCP监听器与IP类型后端通信。  - TCP监听器开启IPv4/IPv6地址转换开关后，客户端IP地址发生转换。   说明： TCP监听器的Proxy Protocol功能陆续上线中，已发布区域请以控制台实际为准。如果您有使用需求，可以提交[工单](https://console.huaweicloud.com/ticket/?agencyId=ed9de0b5e3ac4322a529ac43e44d3872&locale=zh-cn#/ticketindex/serviceTickets)进行申请。 |
| UDP监听器 | [TCP/UDP监听器默认支持"获取客户端IP"] | 以下场景无法获取客户端真实IP： - ELB实例与IP类型后端通信。  - UDP监听器开启IPv4/IPv6地址转换。                                                                                                                                                                                                                                                                                                                                                                                           |
| TLS监听器 | 不支持                                                          | [通过Proxy Protocol协议获取客户端真实IP]。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
   
 #### TCP/UDP监听器默认支持"获取客户端IP"
TCP和UDP监听器的业务转发场景，ELB实例与后端服务器之间直接使用客户端的真实IP地址通信。您无需进行额外设置，通过查看后端服务器的日志记录即可判断是否获取到客户端真实IP。
当Nginx作为后端服务器，您可以参考以下步骤进行验证。
1. 修改http配置块，为Nginx配置访问日志，您可以参考执行以下命令。
   ```
   http {  
         log_format main '$remote_addr- $remote_user [$time_local] "$request" '
                         '$status $body_bytes_sent "http_referer" '
                         '"$http_user_agent" "$http_x_forwarded_for"';     
         }
   ```
   图1配置访问日志   
   ![](https://support.huaweicloud.com/bestpractice-elb/zh-cn_image_0000002369543825.png "点击放大") 
2. 查看Nginx的访问日志，您可以直接获取客户端请求的真实IP。
   ```
   cat /path/server/nginx/logs/access.log
   ```
   日志记录中，第一个IP地址即为客户端的真实IP地址。
   图2查看Nginx的日志   
   ![](https://support.huaweicloud.com/bestpractice-elb/zh-cn_image_0000002335465834.png "点击放大") 
 
#### 特殊场景获取客户端真实IP
**TCP监听器** 在以下场景"获取客户端IP"功能失效：
- TCP监听器与IP类型后端通信。
- TCP监听器开启IPv4/IPv6地址转换开关后进行转发。
 
可以通过以下两种方式获取客户端真实IP。
 #### TCP监听器转发下配置TOA插件获取客户端真实IP
TOA内核模块主要用来获取ELB实例转发过的客户端真实IP地址（**仅支持IPv4** ），该插件安装在ELB后端服务器，详细过程请参考[TOA插件配置](https://support.huaweicloud.com/usermanual-elb/elb_06_0001.html)。
 #### 通过Proxy Protocol协议获取客户端真实IP
您可以通过在监听器上**开启Proxy Protocol功能** 开关，并确保**后端服务器具有解析Proxy Protocol协议的能力**来获取客户端真实IP。
**TLS监听器** ：仅支持通过Proxy Protocol协议获取客户端真实IP。
![](https://support.huaweicloud.com/bestpractice-elb/public_sys-resources/warning_3.0-zh-cn.png)
请确保后端服务器具有解析Proxy Protocol协议的能力，否则会导致业务中断，请谨慎开启。
详细过程请参考以下操作步骤。
#### 步骤一：为监听器开启Proxy Protocol
1. 进入[弹性负载均衡列表页面](https://console.huaweicloud.com/vpc/?locale=zh-cn#/elb/list)。
2. 在弹性负载均衡列表页面，单击目标负载均衡器名称。
3. 在监听器列表页面，单击目标监听器的名称。
4. 在监听器的基本信息页签，单击"编辑监听器"。
5. 在"编辑监听器"页面，开启"Proxy Protocol"开关。
6. 单击"确定"。
 
#### 步骤二：配置后端服务器支持解析Proxy Protocol协议
本文以后端服务器在CentOS 7.5环境下，安装Nginx为例进行介绍，您可以参考执行如下命令进行安装。
1. 运行以下命令安装http_realip_module。
   ```
   yum -y install gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel 
   wget http://nginx.org/download/nginx-1.17.0.tar.gz 
   tar zxvf nginx-1.17.0.tar.gz 
   cd nginx-1.17.0
   ./configure --prefix=/path/server/nginx --with-http_stub_status_module --without-http-cache --with-http_ssl_module --with-http_realip_module 
   make 
   make install
   ```
   
2. 打开Nginx的主配置文件nginx.conf。
   ```
   vi /path/server/nginx/conf/nginx.conf
   ```
   
3. 修改server配置块，修改参考如下。
   1. 启用Proxy Protocol监听。
   
   2. 配置真实IP提取。
   
   
   ```
   server {
      listen 8081 proxy_protocol;
      server_name localhost;
      set_real_ip_from 192.168.0.0/16;
      real_ip_header proxy_protocol;
    }
   ```
   将代理服务器的网段添加到 set_real_ip_from \<IP_address\>，独享型ELB实例需要ELB后端子网网段。
   图3修改Nginx配置文件的server配置块   
   ![](https://support.huaweicloud.com/bestpractice-elb/zh-cn_image_0000002362651569.png) 
4. 修改http配置块，配置访问日志。
   ```
   http {
       log_format main '$remote_addr- $remote_user [$time_local] "$request"' 
                     '$status $body_bytes_sent "$http_referer" '
                     '"$http_user_agent" "$proxy_protocol_addr" ';
     
   }
   ```
   图4修改Nginx配置文件的http配置块   
   ![](https://support.huaweicloud.com/bestpractice-elb/zh-cn_image_0000002363265413.png "点击放大") 
5. 启动Nginx
   ```
   /path/server/nginx/sbin/nginx
   ```
   
 
#### 步骤三：验证后端服务器获得了客户端真实IP
以Nginx作为后端服务器时，客户端访问开启了Proxy Protocol的ELB实例，Nginx日志中的源IP即为真实的客户端IP。
```
cat /path/server/nginx/logs/access.log
```
日志记录中，$proxy_protocol_addr变量对应的IP地址即为客户端的真实IP地址。
图5通过Proxy Protocol协议获取客户端真实IP   
![](https://support.huaweicloud.com/bestpractice-elb/zh-cn_image_0000002363415529.png "点击放大")
