标签:style blog class code java ext
最近拿到一个旧设备: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的大神
3、测试中nginx的accesslog抓不到x-forwarded-for
首先要谢谢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配置,没有技术上的问题,管理起来较为麻烦罢了
新的profile里只需要将insert xforwardedfor 打上钩,改为enable就好了
二、接下来是使用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里新建一个即可~
填上,直接finish/update~搞定
Virtual Servers里想要引用iRule配置,要选择转发类型为http
然后在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这个参数的问题仍未解决
目前求助各大神群未果,谷歌无结果,只能等着看看哪一天可以解决了
全剧终~
为F5-LTM上的业务添加x-forward-for功能,布布扣,bubuko.com
标签:style blog class code java ext
原文地址:http://www.cnblogs.com/tutuye/p/3719403.html