ASP.NET的Request.ServerVariables返回本地IP地址而非远程IP地址

3
我有一个在c#中的asp.net网页。我们想要做的一件事是跟踪网站的点击量,包括它们的IP地址。我实现了一些代码(得益于SO),但记录的IP地址似乎总是本地的,即:192.168.x.x。我尝试了多种设备,甚至包括我的手机和Version MiFi,只是为了确保它不是与ISP有关的奇怪问题,但日志始终列出相同的2-3个不同的内部IP地址(似乎会随着时间而略微变化)。
这是我获取IP的函数(再次感谢SO上的帖子):
protected IPAddress GetIp(HttpRequest request)
{
    string ipString;
    if (string.IsNullOrEmpty(request.ServerVariables["HTTP_X_FORWARDED_FOR"]))
        ipString = request.ServerVariables["REMOTE_ADDR"];
    else
        ipString = request.ServerVariables["HTTP_X_FORWARDED_FOR"].Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();

    IPAddress result;
    if (!IPAddress.TryParse(ipString, out result))
        result = IPAddress.None;

    return result;
}

public void logHit()
{
    IPAddress ip = GetIp(Request);
    string sIP = ip.ToString();
}

我也尝试了这个,结果相同。
HttpContext.Current.Request.UserHostAddress;

当我在客户端使用像appspot上的服务进行调用时,它能正常工作。
<script type="application/javascript">
    function getip(json) {
        //txtIP is a input box on the form
        document.getElementById("txtIP").value = json.ip;
    }
</script>

<script type="application/javascript" src="http://jsonip.appspot.com/?callback=getip"></script>

我想我可以通过点击那个appspot链接并解析它来绕过这个问题,但这似乎对于本应该简单的事情来说太麻烦了。
可能是服务器上的IIS出了问题?或者发生了某种重定向?记录的IP地址不是服务器的IP地址。问题在于我没有直接访问它的权限,所以我必须与管理它的人交谈,并希望在他们开始更改任何东西之前给他们一些方向。
谢谢。
Ernie

你可以尝试使用“X-Forwarded-For”头部,而不是(或者除了)“HTTP_X_FORWARDED_FOR”。但是,如果你的应用程序托管在反向代理后面,你可能会遇到问题,因为并非所有的反向代理都正确实现*X_FORWARDED_FOR。 - jbl
Ernie,请看一下这个 Stack Overflow 的帖子,并尝试 @algreat 提供的答案。https://dev59.com/r3RB5IYBdhLWcg3wEDql - MethodMan
@jbl:谢谢回复。我尝试了,但返回null。 - Ernie S
@DJKRAZE:感谢提供链接。我之前已经阅读过并尝试了所有提到的答案,但都返回相同的IP地址。我甚至创建了一个测试页面,循环遍历ServerVariables和DNS AddressList中的所有条目,并将它们转储到客户端HTML中,以查看是否有其他变量可能拥有它,但不幸的是没有。唯一有效的方法是使用JavaScript。Ernie - Ernie S
我只是好奇,所以向我的ISP进行了查询。http://xeondev.weblapportal.hu/Webform1.aspx 支持"HTTP_X_FORWARDED_FOR",也许是一些IIS设置的问题?... - Laszlo Boke
2个回答

2
如果HTTP_X_FORWARDED_FOR标头确实得到支持,那么我认为这不是正向或反向代理服务器导致的问题,而更可能是发生在TCP/IP协议栈应用层下方的动态网络地址转换或动态端口地址转换,因此不会影响HTTP请求标头。
有许多配置NAT的方法,其中大部分不会引起这些症状,但肯定可以以一种可能出现这个问题的方式来配置NAT。动态NAT或动态PAT就是两个这样的例子,我建议您向您的网络管理员询问此问题。
有关动态NAT/PAT的更多信息和良好的示例,请参阅:http://www.cisco.com/en/US/docs/security/asa/asa82/configuration/guide/nat_dynamic.html 在典型的NAT场景中,请求数据包以以下方式到达NAT设备(防火墙或路由器):
FROM - 5.5.5.5(客户端的公共地址) TO - 6.6.6.6(服务器的公共地址)
“典型”的NAT配置只会重写目标,如下所示:
FROM - 5.5.5.5 TO - 192.168.6.6(服务器的私有地址)
在这种典型情况下,服务器仍将看到REMOTE_ADDR为5.5.5.5,因为这是传入请求的源地址。然后,数据包将返回到5.5.5.5,并且响应将成功返回给客户端。
现在,在动态PAT的情况下,例如,请求将以以下方式到达NAT设备:
FROM - 5.5.5.5 TO - 6.6.6.6
然后,NAT设备将重写源和目标数据包,仅维护此“动态”映射的请求寿命: FROM - 192.168.1.1:12345(动态PAT地址) TO - 192.168.6.6(服务器的私有地址)
现在,当服务器看到此请求时,它似乎来自私有地址192.168.1.1。实际上,使用严格的PAT,所有请求都将从此地址中出现。在您的情况下,可能有2或3个这些地址,因为如果只使用单个动态PAT地址,则可能存在足够的流量风险而耗尽端口。
因此,您的REMOTE_ADDR为192.168.1.1,因为实际上这是请求数据包的源地址。没有HTTP_X_FORWARDED_FOR,因为动态PAT发生在较低的TCP/IP层(地址而不是应用程序)。
最终,响应被发送回192.168.1.1:12345,该地址会被路由到NAT设备,而在请求/响应的持续时间内(请参阅上述Cisco文档),该设备将其映射回5.5.5.5,然后删除“动态”映射。所有工作都进行得非常完美,客户端收到了响应,但从服务器的角度来看,你不知道实际的客户端地址。如果使用了动态NAT,则我不认为你可以从服务器中获取此信息。幸运的是,你在客户端的JavaScript中已经采取了正确的步骤来获取信息,因此这很可能解决了你的问题,也是最好的解决方案。

谢谢,你的回答非常有用,尽管最终我认为我的问题是一个普通的防火墙问题。我想给你点赞,但我没有足够的积分:(。 - Ernie S

0

谢谢,你提到防火墙让我找到了正确的答案。我们的Web服务器不仅仅是一个纯粹的Web服务器,还有其他功能,所以它位于我们公司的防火墙内部。 - Ernie S

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