检查 IP 地址是不是在范围/子网内的标准/安全方法
Posted
技术标签:
【中文标题】检查 IP 地址是不是在范围/子网内的标准/安全方法【英文标题】:Standard/safe way to check if IP address is in range/subnet检查 IP 地址是否在范围/子网内的标准/安全方法 【发布时间】:2015-09-11 11:04:29 【问题描述】:我有一小段代码将一个 32 位无符号整数(即:uint32_t
)转换为一组四个 8 位字段,将其视为 IP 地址,然后向客户端报告位于预定的 IP 地址范围内。
我有 already found 一些 different examples 的 C 代码,它们向我展示了如何从包含它的 struct sockaddr_in
以及 with a C# answer 获取客户端的 IP 地址。但是,我想进一步分解地址,将其保留在纯 C 中,并想知道一些快速的事情:
-
系统之间的内部表示是否一致,或者我是否需要对
s_addr
字段进行字节顺序检查/更正?
是否有类似于CLASS_C_NETMASK
、CLASS_B_NETMASK
等的标准宏,它们比使用手动生成的掩码更合适(即:0xFF000000
、0x00FF0000
等)。
套接字库中是否有任何现有函数可以检查 IP 地址是否在 IP 地址范围内或与子网掩码匹配?
谢谢。
【问题讨论】:
s_addr
始终采用“网络字节序”,即大端序。
Beej's Guide to Network Programming 不会出错。将其添加到您的参考/示例列表中以进行检查。 (他的其他导游也不错)
【参考方案1】:
系统之间的内部表示是否一致,或者我是否需要对 s_addr 字段进行字节序检查/更正?
s_addr
在所有平台上始终采用网络(大端)字节顺序。
是否存在 CLASS_C_NETMASK、CLASS_B_NETMASK 等标准宏,它们比使用手动生成的掩码更合适(即:0xFF000000、0x00FF0000 等)。
不,使用这样的宏也没有意义,因为子网掩码不是从一个网络固定到另一个网络。您需要为您的代码提供一个实际的网络 IP 及其子网掩码(提示用户、查询操作系统等)。然后,您可以计算子网的起始 IP 和结束 IP,以与您的目标 IP 进行比较:
uint32_t ip = ...; // value to check
uint32_t netip = ...; // network ip to compare with
uint32_t netmask = ...; // network ip subnet mask
uint32_t netstart = (netip & netmask); // first ip in subnet
uint32_t netend = (netstart | ~netmask); // last ip in subnet
if ((ip >= netstart) && (ip <= netend))
// is in subnet range...
else
// not in subnet range...
或者更简单,用子网掩码屏蔽网络 IP 和目标 IP,看看结果值是否相同(即它们是同一个子网):
uint32_t ip = ...; // value to check
uint32_t netip = ...; // network ip to compare with
uint32_t netmask = ...; // network ip subnet mask
if ((netip & netmask) == (ip & netmask))
// is on same subnet...
else
// not on same subnet...
套接字库中是否有任何现有函数可以检查 IP 地址是否在 IP 地址范围内或与子网掩码匹配?
没有。但是手动实现很简单,只需要几行代码,如上图。
【讨论】:
非常有用的解决方案,谢谢!我可能会建议从 netend 中减去 1 以获得子网上的最后一个地址。 子网上的最后一个地址是子网的广播IP。使用子网掩码屏蔽网络 IP 会产生广播 IP,从技术上讲,它仍然是子网的一部分。如果您不想在比较中允许广播 IP,您可以将netend
减 1,或者您可以将 <= netend
更改为 < netend
,或者您可以使用子网掩码的倒数来屏蔽目标 IP并查看结果是否与掩码的值相同(如果是,则目标是广播IP)。
当网络掩码为 32 时它会失败,知道为什么吗?
32 是十六进制 0x20,二进制 00100000。该子网掩码的高位不是连续的 1 位。这在 IPv4 中技术上并不违法(它在 IPv6 上),但不鼓励并且在实践中很少使用。子网掩码的高位应始终为连续的 1 位。以上是关于检查 IP 地址是不是在范围/子网内的标准/安全方法的主要内容,如果未能解决你的问题,请参考以下文章