• 为F5-LTM上的业务添加x-forward-for


    最近拿到一个旧设备:BIG-IP LTM 6400,玩的人不在,文档又不足;只能自己玩了~

    SNAT模式下,走HTTP代理,往http header中的x-forwarded-for加入源IP,以便让后端设备取得源IP

    万事不懂先问谷歌

    感谢以下:

    1、F5官方解答:可以通过两种方式,一是通过http profile插入;二是通过编写irule插入

    http://support.f5.com/kb/en-us/solutions/public/4000/800/sol4816.html

    2、一位熟悉F5 irule的大神

    http://blog.sina.com.cn/s/blog_444ee46f0100mwzk.html

    3、测试中nginx的accesslog抓不到x-forwarded-for

    http://blog.itpub.net/27043155/viewspace-734234/

    首先要谢谢web开发同事写了一个小页面给我放到服务器上测试,可以打印出服务器端接收到的所有http header信息

       1:  <%@page import="java.util.Set"%>
       2:  <%@page import="java.util.HashMap"%>
       3:  <%@page import="java.util.Map"%>
       4:  <%@page import="java.util.Enumeration"%>
       5:  <%@page import="java.util.ArrayList"%>
       6:  <%@page import="java.util.List"%>
       7:  <%@page import="java.net.UnknownHostException"%>
       8:  <%@page import="java.net.InetAddress"%>
       9:  <%@ page language="java" contentType="text/html; charset=UTF-8"
      10:      pageEncoding="UTF-8"%>
      11:  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
      12:  <html>
      13:  <head>
      14:  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      15:  <title>header参数</title>
      16:  </head>
      17:  <body>
      18:                  <center>
      19:                  <br/>
      20:                  <%
      21:                          Enumeration enumeration =       request.getHeaderNames();
      22:                          Map<String, String> requestHeaders = new HashMap<String, String>();
      23:                          //遍历出获得的请求头信息的名称和值
      24:                          while(enumeration.hasMoreElements()){
      25:                                  String headerName = (String)enumeration.nextElement();
      26:                                  String headerValue = request.getHeader(headerName);
      27:                                  requestHeaders.put(headerName, headerValue);
      28:                          }
      29:                  %>
      30:                          <h2>header参数</h2>
      31:                          <table border="1" width="400px" align="center">
      32:                                  <tr>
      33:                                          <td>
      34:                                                  参数名
      35:                                          </td>
      36:                                          <td>
      37:                                                  参数值
      38:                                          </td>
      39:                                  </tr>
      40:                                  <%
      41:                                                  if (requestHeaders != null && requestHeaders.size() > 0) {
      42:                                                          Set<String> headers = requestHeaders. keySet();
      43:                                                          for(String header : headers) {
      44:                                  %>
      45:                                          <tr>
      46:                                                  <td>
      47:                                                          <%=header%>
      48:                                                  </td>
      49:                                                  <td>
      50:                                                          <%=requestHeaders.get(header)%>
      51:                                                  </td>
      52:                                          </tr>
      53:                                  <%
      54:                                                          }
      55:                                                  }
      56:                                          %>
      57:                          </table>
      58:                  </center>
      59:  </body>
      60:  </html>

    LTM6400要想在http header中插入信息,首先必须得是http代理啦,其次也得是SNAT模式(同LVS的NAT)

    废话了~

    有两种方式可以在http header中插入x-forwarded-for信息

    一、Http Profile

    二、iRule

    两种方式不能共用,在下就吃憋了,没有好好看文档的结果。

    一、使用http profile插入x-forwarded-for非常简单

    只要在Local Traffic中的Profiles里新建一个即可,新的profile会继承自带的http设置;也可以修改原设置的http

    不过不建议修改原有的http配置,没有技术上的问题,管理起来较为麻烦罢了

    QQ图片20140509172657

    新的profile里只需要将insert xforwardedfor 打上钩,改为enable就好了

    $XWGMBS91QQW_UVL]5I}FVF

    二、接下来是使用iRule配置x-forwarded-for

    官方已经给了我们一套简单的模板

       1:  when HTTP_REQUEST {  
       2:  HTTP::header insert X-Forwarded-For [IP::remote_addr] 
       3:  }

    但是不知道如果客户端提前在http header中插入了x-forwarded-for的话,这个动作会不会将原有的x-forwarded-for的值覆盖掉?

    后面大神还提供了两个模板

       1:  when HTTP_REQUEST {
       2:        HTTP::header remove X-Forwarded-For
       3:        HTTP::header insert X-Forwarded-For [IP::client_addr]
       4:  }

    从大神的指导看,最后这个应该最好,但是运算量有些大,在下线上业务压力不小,所以没有使用

    相关xff伪造的文章可以看看这位,非常不错:http://yzs.me/1952.html

       1:  when HTTP_REQUEST {
       2:    if {[HTTP::header exists X-Forwarded-For]}{
       3:        set old_xff   [HTTP::header values X-Forwarded-For]
       4:       HTTP::header remove X-Forwarded-For
       5:        HTTP::header insert X-Forwarded-For_Org  "[IP::client_addr], $old_xff"
       6:    } else { 
       7:        HTTP::header insert X-Forwarded-For [IP::client_addr]
       8:    }
       9:  }

    在Local Traffic – iRules里新建一个即可~

    50R4HD~D3_XMQ0I[4$8]VNT

    填上,直接finish/update~搞定

    Virtual Servers里想要引用iRule配置,要选择转发类型为http

    ](%Q]H]2P%)DRZGC5BQYD5J

    然后在resource里添加已经新建的irules到左边框框,搞定

    无论是使用http profile,还是自己编写irule;最终的效果都是一致的,采取哪种方法并不重要,最好还是根据实际情况和使用习惯决定~

    Nginx放到F5后面,日志记录有问题,先描述一下网络情况

    代理IP:192.168.1.1

    nginx IP:192.168.2.1

    client IP:192.168.3.1

    LTM 6400后有一台nginx的日志中,只能获取到LTM的IP地址,无法获得X-Forwarded-For过来的IP

    nginx.conf中的log配置为

       1:  log_format  '$remote_addr - $remote_user [$time_local] "$request" '
       2:           '$status $body_bytes_sent "$http_referer" '
       3:           '"$http_user_agent" $http_x_forwarded_for';

    打印出来的日志为

       1:  192.168.1.1 - - [09/May/2014:15:04:52 +0800] "GET / HTTP/1.1" 200 798 "-" "Mozilla/5.0 (Windows NT 5.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"

    其中$http_x_forward_for理论上应该获得的是X-Forwarded-For的值

    那我们来查看http header信息

    x-forwarded-for:192.168.3.1

    x-real-ip:192.168.1.1

    这里看完全是无异常的,另一台也是硬件负载均衡到此台nginx的请求日志中$http_x_forward_for显示为x-forwarded-for的IP地址

    但是两台代理的http header中并无差异之处

    万事谷歌

    找到nginx有一个real ip module,随即做了以下测试

    nginx重新编译,configure参数加上选项:--with-http_realip_module

    在原nginx.conf配置中添加:

       1:  server
       2:  {
       3:      ...
       4:      set_real_ip_from 192.168.0.0/16;    #许可此网段过来的访问可以修改real_ip;这里放的比较宽,测试用不要在意细节
       5:      real_ip_header X-Forwarded-For;     #将$x-forward-for的值替换掉real_ip
       6:      ...
       7:      #我的日志格式如下
       8:      log_format  '$remote_addr - $remote_user [$time_local] "$request" '
       9:               '$status $body_bytes_sent "$http_referer" '
      10:               '"$http_user_agent" $http_x_forwarded_for';
      11:      ...
      12:  }

    通过这样的配置,日志的内容变成了

       1:  192.168.3.1 - - [09/May/2014:15:05:35 +0800] "GET / HTTP/1.1" 200 800 "-" "Mozilla/5.0 (Windows NT 5.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"

    可以看得到$remote_addr参数已经变成了x-forwarded-for的值

    同时查看web页面打印出来的http header,其中

    x-forwarded-for:192.168.3.1

    x-real-ip:192.168.3.1

    感觉靠谱吗

    不好说,虽然功能上,nginx的access log里面已经实现了抓取客户端IP的需求,但是$http_x_forwarded_for这个参数的问题仍未解决

    目前求助各大神群未果,谷歌无结果,只能等着看看哪一天可以解决了

    全剧终~

  • 相关阅读:
    基于JFinal中搭建wopi协议支撑办法
    mysql 增加列
    国王分金币
    口算题卡升级版本
    elasticsearch牛人的日志列表
    牛B的大数据库
    golang --rune
    golang ---rune与byte
    golang学习笔记--接口
    golang学习笔记--函数和方法
  • 原文地址:https://www.cnblogs.com/tutuye/p/3719403.html
Copyright © 2020-2023  润新知