【问题标题】:What is Request.UserHostName actually returning and is it possible to convert it to something that I can get a host entry for?Request.UserHostName 实际返回的是什么,是否可以将其转换为我可以获得主机条目的内容?
【发布时间】:2012-11-16 02:05:12
【问题描述】:

我想我可能处于答案是this is not possible 但万一不是这里...

我已经编写了一个ASP .NET MVC 3 应用程序,我正在使用Request.UserHostName 属性,然后将返回的值传递给Dns.GetHostEntry,以找出当前连接的客户端的所有可能IP 和主机名,例如示例:

var clientAddress = Request.UserHostName;
var entry = Dns.GetHostEntry(clientAddress);

一般来说这很好,除非我从Dns.GetHostEntry 调用中得到一个“找不到主机”SocketException。

真正奇怪的是,从Request.UserHostName 属性返回的地址不是公共地址或任何私有地址。为了证明这一点,我在有问题的客户端机器上运行了这段代码......

var host = Dns.GetHostEntry(Dns.GetHostName());

foreach (var a in host.Aliases)
{
    Console.WriteLine("alias '{0}'", a);
}

foreach (var a in host.AddressList)
{
    Console.WriteLine("ip address '{0}'", a);
}

// ...from http://stackoverflow.com/a/2353177/1039947...
String direction = "";
WebRequest request = WebRequest.Create("http://checkip.dyndns.org/");
using (WebResponse response = request.GetResponse())
{
    using (var stream = new StreamReader(response.GetResponseStream()))
    {
        direction = stream.ReadToEnd();
    }
}

int first = direction.IndexOf("Address: ") + 9;
int last = direction.LastIndexOf("</body>");
direction = direction.Substring(first, last - first);

Console.WriteLine("Public IP: '{0}'", direction);

它打印三个 IP 地址(::1,一个私有和一个公共),但它们都不是从 Request.UserHostName 返回的地址。

如果我将从上述测试应用程序打印的任何地址传递到 Dns.GetHostEntry 方法中,我会得到一个合理的值。

那么,有什么方法可以让我从这个既不是公共也不是任何私人的奇怪 IP 地址中获得一个我可以毫无例外地获取它的主机条目的地址(以及这个地址是什么) ?

顺便说一句,据我所知,在 HTTP 消息中没有 X_FORWARD_FOR 标头或其他任何我可以用来识别客户端的东西?

问题的背景

因此有人指出(感谢 Damien),如果我解释了为什么要问这个问题,也许有人可以提供一种替代方法,所以这里有一些背景......

我有一个要求,应该允许应用程序的管理员在配置中指定允许查看页面的单个机器 - IP 地址或机器名称 - 我可能可以删除机器名称要求,但即使他们在配置中指定了 IP 地址,但它仍然与从 UserHostName 属性返回的 IP 地址不匹配,因为他们将使用在 ping 机器名称时返回的 IP 地址。

因此,我的想法是,如果我获取 HTTP 标头中发送的任何内容并将其传递给 GetHostEntry,然后从中获取所有可能的结果(所有 IP 和主机名)并查看它们中是否有任何匹配配置值我可以说“允许”,否则“不允许”(我也将删除第一个点之前的主机名部分,以涵盖这种可能性)。这种方案已经被我所遇到的这种情况彻底摧毁了,因为我的 IP 地址根本不是我所期望的。

【问题讨论】:

  • 所有你通常可以告诉(在 HTTP 中)是 an 请求声称来自的 IP 地址(这实际上可能是防火墙或代理地址,X_FORWARD_FOR 是很好,但实际上并不需要)。我有一种感觉,如果我们知道这里要解决的整体问题,我们会做得更好(例如,我确信您的最终目标不是“为客户端获取主机条目” - 这听起来像是“解决方案” - 一个行不通的)
  • @Damien_The_Unbeliever 谢谢 - 我添加了一些背景
  • 除非您处于一个受严格限制的网络中,否则无法实现所要求的要求。这是一个 Intranet 站点还是一个面向 Internet 的站点?
  • @Damien_The_Unbeliever 一个 Intranet 应用程序 - 不是面向 Internet 的

标签: c# .net asp.net-mvc


【解决方案1】:

客户端的主机名通常是未知的,因为它不是在 HTTP 级别传输的。服务器无法知道它。用 Fiddler 看一下 HTTP 请求,自己看看服务器可用的信息并不多(当然客户端可以伪造所有请求内容)。

使用UserHostAddress 属性获取IP 地址。这是您可以可靠地找到的最多信息。一旦你有了它,你可以尝试将 IP 反转为主机名,但这并不总是可行的。

【讨论】:

  • 没错。仅依靠 .NET 将 IP 转换为主机,然后再将该主机转换回 IP 很容易失败并且没有用处。
  • 对于任何给定的 IP,可能有零个或多个主机名!任何给定的主机都可能有很多 IP。它是 m:n。 IP 和主机名之间的映射没有明确定义。
  • 谢谢 - 这也是我在提出问题之前得出的结论 - 只是想知道是否有其他方法(可能在堆栈中较低)可以获取我能够获得的 IP 地址可靠地匹配,但我猜不是
  • 当然不是因为HTTP请求不包含主机名,低层也不包含。
【解决方案2】:

我对你的问题有一个更具体的答案。通过检查 HttpRequest.UserHostName here 的源代码,我发现它映射到一个名为 REMOTE_HOST 的 IIS 服务器变量,该变量描述为 here。该属性将返回客户端的 IP 地址,除非您已按照描述的方式配置 IIS,在这种情况下,IIS 将执行反向 DNS 查找以尝试返回与 IP 关联的名称。

【讨论】:

  • 上面描述REMOTE_HOST用户变量的链接已经烂了。网络搜索“配置 iis 反向查找 remote_host”会产生一些有用的结果,但可能是 IIS 不再支持反向查找选项。
【解决方案3】:

请务必阅读Dns.GetHostEntry 的备注部分,了解 许多 可能(部分)失败的情况:

备注

GetHostEntry 方法向 DNS 服务器查询 IP 与主机名或 IP 地址关联的地址。

如果将空字符串作为 hostNameOrAddress 参数传递,则此方法 返回本地主机的 IPv4 和 IPv6 地址。

如果找不到主机名,则返回 SocketException 异常 值为 11001(Windows 套接字错误 WSAHOST_NOT_FOUND)。这 如果 DNS 服务器没有响应,则可以返回异常。这 如果名称不是官方主机,也可以返回异常 名称或别名,或者在被查询的数据库中找不到。

ArgumentException 异常也会返回,如果 hostNameOrAddress 参数包含 Any 或 IPv6Any。

GetHostEntry 方法假定如果 IP 文字字符串在 应用程序需要 IPHostEntry 的 hostNameOrAddress 参数 实例返回所有属性集。这些属性 包括地址列表、别名和主机名。结果, GetHostEntry 方法的实现展示了以下内容 传递 IP 字符串文字时的行为:

  1. 该方法尝试解析地址。如果 hostNameOrAddress 参数包含合法的 IP 字符串文字,则第一阶段成功。
  2. 尝试使用 IP 字符串文字的 IP 地址进行反向查找以获取主机名。此结果设置为 HostName 属性。
  3. 再次使用此反向查找的主机名来获取所有可能的 与名称关联并设置为 AddressList 的 IP 地址 财产。

对于 IPv4 字符串文字,上述所有三个步骤都可以 成功。但是 IPv4 地址的 DNS 记录过时是可能的 实际上属于要返回的不同主机。这可能 导致步骤 #3 失败并引发异常(存在 DNS PTR IPv4 地址的记录,但没有 IPv4 的 DNS A 记录 地址)。

对于 IPv6,上面的第 2 步可能会失败,因为大多数 IPv6 部署不注册 IPv6 的反向 (PTR) 记录 地址。所以这个方法可能会返回字符串 IPv6 文字作为 HostName 属性中的完全限定域 (FQDN) 主机名。

GetHostAddresses 方法在 IP 方面具有不同的行为 文字。如果上面的步骤 #1 成功(它成功解析为 IP 地址),该地址立即作为结果返回。有 没有尝试反向查找。

如果本地计算机没有安装 IPv6,则从 GetHostEntry 方法的结果中过滤 IPv6 地址。结果,有可能取回一个空的 如果只有 IPv6 结果可用于 IPHostEntry 实例 主机名或地址。参数。

返回的 IPHostEntry 实例的 Aliases 属性未由该方法填充,始终为空。

【讨论】:

    猜你喜欢
    • 2020-11-24
    • 1970-01-01
    • 2021-10-01
    • 2020-02-05
    • 1970-01-01
    • 2016-05-01
    • 1970-01-01
    • 2010-12-22
    • 1970-01-01
    相关资源
    最近更新 更多