南京网站制作域名,做营销型网站需要注意哪些点,下载四川天府健康二维码,互联网推广的好处出于安全考虑#xff0c;近期在处理一个记录用户真实IP的需求。本来以为很简单#xff0c;后来发现没有本来以为的简单。这里主要备忘下#xff0c;如果服务器处于端口回流#xff08;hairpin NAT#xff09;,keepalived#xff0c;nginx之后#xff0c;如何取得客户端的… 出于安全考虑近期在处理一个记录用户真实IP的需求。本来以为很简单后来发现没有本来以为的简单。这里主要备忘下如果服务器处于端口回流hairpin NAT,keepalivednginx之后如何取得客户端的外网IP。 来自客户端PC的流量路径如上在这样的拓扑中在应用服务中取得客户端PC的外网ip可能会遇到哪些问题呢ip 编的随意为便于说明不考虑合理。
编程实现 Java 为例这个我会。 public static String getClientIP(HttpServletRequest request) {String remoteAddr request.getRemoteAddr();return remoteAddr;} 运行一下输出呢是 3.3.3.3 。 这是因为这个API所取得的是IP数据包的源地址。Nginx的反向代理时工作在应用层的当他收到一个http请求时会对应生成一个新的请求发送给应用服务这个请求的IP包的源地址是Nginx服务器的IP即3.3.3.3。
Nginx头部注入 因为是应用层那这个请求ip包的源地址肯定就是3.3.3.3了但是在应用层我们可以附加一点信息以便后面的应用服务可以通过这个附加信息了解这个请求对应的原始源地址。这个我也会。 在Nginx 中配置。
server {...proxy_set_header X-Real-IP $remote_addr; 在应用层http协议中加一个http header。X-Real-IP:$remote_addr. $remote_addr 是一个预设变量代表所代理转发请求的原始源ip地址。 在Java 程序中读取对应的附加信息 public String getRealIp(HttpServletRequest request) {String realIp request.getHeader(X-Real-IP);if (realIp ! null !realIp.isEmpty()) {return Clients Real IP: realIp;} return ;} 运行一下此时输出2.2.2.2。 显然我们向前推进了一步。
Keepalived负载均衡模式 印象里这里keepalived的主要作用应该是解决nginx 代理服务器的单点问题的似乎也被配置为负载均衡了翻了下配置文件实际的情况如下。 运维大壮说他配置keepalived 时候多考虑了一步如果机器活着nginx 挂了怎么办于是又做了一层负载均衡这种情况虚拟IP不会漂移到右边的备机。他说的也确实不是没有道理。keepalived 的负载均衡貌似是工作在第三层的那肯定在负载均衡的时候又对ip包的源地址进行了修改。这是网络层向nginx 这样附加信息肯定是不行了。于是翻了翻手册发现keepalived 的负载均衡支持三种路由模式NATDirect Routing 和 Tunneling。 NAT 模式会修改源IP出入流量都会经过负载均衡器。而DR模式会直接修改MAC地址那回程流量就不再经过负载均衡器了也就意味这种模式源地址不会被修改回程流量会直接发送给源ip地址。 DR模式有个要求就是负载均衡器需要能知道后端服务的MAC地址这是依赖于ARP实现的也就是要求负载均衡器和后端服务器在同一广播域。恰好我门可以满足。于是。
virtual_server 192.168.11.242 80 {
……
lb_kind DR
…… 将负载均衡路由模式切换为DR模式。重新看一下这次取得客户端地址变成了 1.1.1.1, 这一步一坑。为什么到达keepalived的ip包的源地址会变成出口路由器的外网地址呢
路由器端口回流Hairpin NAT 离胜利是不远了此时见多识广的大壮说这应该是跟端口回流有关之前有个系统也是类似问题 你的web端口配置了端口回流如果关掉端口回流就可以取得外网地址了。什么是端口回流 首先路由器做了端口映射1.1.1.1:80-192.168.0.2:80 服务器A由于某些原因不方便使用内网地址192.168.0.2访问B而要通过外网IP或者域名访问服务器B即访问1.1.1.1:80 按端口转发规则路由器会将这个来自于内网接口的流量再次转发回内网服务器B形成了一个180度的急弯——发卡弯这也就是Haripin NAT的名字由来十分形象。 如果不做设置服务器A通过访问1.1.1.1:80 是无法正常访问服务器B的。原因是hairpin会影响Tcp连接建立的握手过程。 1. A发送握手请求给入口路由器路由器修改目的ip为192.68.0.2 发送到服务器B。 2.B收到握手请求后回复握手确认应答给这个握手请求的源IP地址此处是A的地址192.168.0.1 3.因为AB同一网络握手确认会直接到达A。 4.A发现这个握手确认回复的源ip192.168.0.2并不是我期望与之建立连接的握手请求目的地址1.1.1.1A并不认识B只认识路由器导致TCP连接无法建立。 解决以上问题的关键就是让握手确认应当同样经过路由器发送给A。因此需要在之前将握手请求转发给B时同时修改源ip地址为1.1.1.1如此B服务器作出确认回复时自然也会发送给1.1.1.1。 但是这个源地址转化SNAT的过程实际上只对于来自内网的流量是有必要的。对于外网流量其源IP本身就处于网络外部必然会经过再次经过路由器返回。 于是联系管路由器的小明请他不要偷懒规则配置的细致一点不要做无差别的源地址转换。即 1.对内网接口流量进行源地址和目标地址转换2.对外网流量只进行目标地址转化。 重新测试。 终于输出实际了客户PC实际ip地址0.0.0.0 OK一波三折跌宕起伏写到这里