用户主机地址提供错误的IP地址

11

我收集用户访问我的网站时的IP地址统计数据,发现只有两个IP地址出现过,分别是172.16.16.1和172.16.16.248。我用来确定IP地址的属性是:

Request.UserHostAddress

IP地址信息丢失的原因可能是什么?所有用户都来自世界各地,因此他们不可能只在两个代理后面。

7个回答

28

你可能想要做这样的事情:

string SourceIP = String.IsNullOrEmpty(Request.ServerVariables["HTTP_X_FORWARDED_FOR"]) ? Request.ServerVariables["REMOTE_ADDR"] : Request.ServerVariables["HTTP_X_FORWARDED_FOR"].Split(",")[0];

HTTP_X_FORWARDED_FOR头部获取代理服务器后面的IP地址。

查看此页面以更详细地了解原因;获取用户真实IP


我知道HTTP_X_FORWARDED_FOR头的存在,但更想了解问题的原因。无论如何感谢! - Alexander Prokofyev
5
请注意,级联代理可能会导致出现多个HTTP_X_FORWARDED_FOR标头。 - Marc Climent
@Marc Climent:你能否添加一个新的答案来解决这个问题?我想看看它是如何工作的。Request.ServerVariables["HTTP_X_FORWARDED_FOR"]会返回一个IP地址的分隔字符串,还是只返回第一个/最后一个头部? - MikeWyatt
@MikeWyatt 请查看这个问题:https://dev59.com/bHRA5IYBdhLWcg3w_DLF - Marc Climent
1
@MarcCliment已经添加了split函数以获取第一个逗号分隔的值。 - Dave Anderson

10

这看起来像是反向代理的工作。

当您使用反向代理时,客户端连接到代理,代理本身会打开一个新连接到您的服务器。由于 ASP.NET 使用传入连接的信息来填充用户地址,因此您会得到反向代理的地址。

如果您确实处于这种配置中,您需要从反向代理获取正确的信息。大多数反向代理都提供在 HTTP 请求中添加标题的可能性,其中包含客户端的真实 IP 地址。请检查您的代理文档。


6

在Dave Anderson的回答基础上,这里有一段代码片段,考虑了反向代理链。

string forwardedFor = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

string ipStr = string.IsNullOrWhiteSpace(forwardedFor) 
                   ? Request.ServerVariables["REMOTE_ADDR"] 
                   : forwardedFor.Split(',').Select(s => s.Trim()).First();

1

Request.ServerVariables("REMOTE_ADDR") 不起作用。 这个问题是因为您的服务器可能在某些代理后面(或通过某些网络连接到互联网),或者您的路由器设置为NAT(网络地址转换),这种技术不会将IP传递给服务器。在这种情况下,您无法使用Asp.net获取IP地址。 然而,Java提供了一个小程序,可以在任何情况下获取IP地址。

(仅适用于Netscape、Mozilla和Firefox,并且必须启用Java)

<script language="javascript" type="text/javascript">   

if (navigator.appName.indexOf("Netscape") != -1){
ip = "" + java.net.InetAddress.getLocalHost().getHostAddress();
document.write("<b>Your IP address is " + ip+'</b>');
}
else {
document.write("<b>IP Address only shown in Netscape with Java enabled!</b>");
}

</script>

1

在Tom Fanning的回答基础上构建...

 public static string ClientIp(this HttpRequestBase @this) {
  var clientIp = string.Empty;
  string forwardedFor = @this.ServerVariables["HTTP_X_FORWARDED_FOR"];

  if (string.IsNullOrWhiteSpace(forwardedFor)) {
    clientIp = @this.ServerVariables["REMOTE_ADDR"];
  } else {

    var array = forwardedFor
      .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
      .Select(s => s.Trim());

    foreach (var element in array) {
      if (element.IsValidIp4() || element.IsValidIp6()) {
        clientIp = element;
        break;
      }
    }
  }
  return clientIp;
}

public static bool IsValidIp4(this string @this) {
  var pattern = new Regex(@"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$");
  return pattern.IsMatch(@this);
}

public static bool IsValidIp6(this string @this) {
  var pattern = new Regex(@"^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/(d|dd|1[0-1]d|12[0-8]))$");
  return pattern.IsMatch(@this);
}

1
将你的代码与问题相关联的解释会有所帮助。 - Prateek

1

我假设你在NAT/反向代理后面,所以我认为你必须使用:

Request.ServerVariables("REMOTE_ADDR") 

很可能172.16.0.0/12是您的私有局域网,其中172.16.16.248是您自己的地址,而172.16.16.1是您的路由器/代理的地址。


不,/12 应该作为默认值是正确的。=)http://zh.wikipedia.org/wiki/私有网络 - Node

0

你列出的这两个地址都属于被定义为私有的地址范围之一。 (详见此处的描述)

听起来更像是你正在获取自己防火墙的内部地址?


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