如果HTTP_X_FORWARDED_FOR包含多个IP地址,我该如何获取正确的IP地址?

36
如果Request.ServerVariables["HTTP_X_FORWARDED_FOR"]返回多个IP地址,我应该选择哪个IP地址?在C#中如何实现呢?我的理解是,如果它为空或null,则客户端计算机没有通过代理,我可以从Request.ServerVariables["REMOTE_ADDR"]获取他们的IP地址。这个说法正确吗?
"which one do I take"指的是我应该选择列表中的第一个IP还是最后一个IP,我只需要将其拆分成数组,然后选择我想要的那个IP地址。我不太确定HTTP_X_FORWARDED_FOR是如何工作的。
4个回答

44
根据这里的说明,X-Forwarded-For HTTP头的格式为:
X-Forwarded-For: client1, proxy1, proxy2, ...

所以你想要的客户端IP地址应该是列表中的第一个


7
关于可靠性问题的进一步说明:
任何人都可以通过使用像Firefox插件“Tamper Data”或他们自己的本地代理(例如Privoxy)这样的工具伪造HTTP_X_FORWARDED_FOR。这意味着整个字符串可能是虚假的,而REMOTE_ADDR则是实际原始主机。它也可能意味着第一个“client1”地址是伪造的,然后客户端通过代理连接,导致proxy1成为客户端的IP地址,而REMOTE_ADDR成为单个代理所使用的IP地址。
如果您想基于IP拒绝访问,建议检查XFF头中的每个IP地址以及REMOTE_ADDR。
如果您想基于IP区域授权访问,我建议仅允许访问当XFF为空且IP来自正确的区域时。
但正如Mastermind已经指出的,有些代理会隐藏代理链。例如,Tor网络将使请求看起来像来自最终代理机器,而不是原始IP。匿名代理通常声称它们正在转发与REMOTE_ADDR报告的相同IP。
基于IP的过滤通常是一种粗略、最后手段的访问控制机制。

那么,为什么像AWS和Azure这样的公司要依赖IP地址来配置安全组规则呢? - It's a trap

3

3
实际客户端IP应该是头部值中最左边的IP地址。您可以使用正则表达式将其提取到环境变量中:
SetEnvIf X-Forwarded-For "^(\d{1,3}+\.\d{1,3}+\.\d{1,3}+\.\d{1,3}+).*" XFFCLIENTIP=$1

请注意使用$1来设置XFFCLIENTIP环境变量,以保存正则表达式中第一个组的内容(括号内的内容)。
例如,您可以定义一个使用该变量的日志格式:以下示例是我们在nearmap.com内部使用的一个示例,因此记录了额外的信息,但您需要的是开头的%{XFFCLIENTIP}e。请注意行末的env=XFFCLIENTIP,这意味着仅在设置了环境变量时才使用此格式。
CustomLog /var/log/apache2/access.log "%{XFFCLIENTIP}e \"%{session}C\" \"%{nearmapuid}C\" %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" env=XFFCLIENTIP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接