检查 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_NETMASKCLASS_B_NETMASK 等的标准宏,它们比使用手动生成的掩码更合适(即:0xFF0000000x00FF0000 等)。 套接字库中是否有任何现有函数可以检查 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,或者您可以将 &lt;= netend 更改为 &lt; netend,或者您可以使用子网掩码的倒数来屏蔽目标 IP并查看结果是否与掩码的值相同(如果是,则目标是广播IP)。 当网络掩码为 32 时它会失败,知道为什么吗? 32 是十六进制 0x20,二进制 00100000。该子网掩码的高位不是连续的 1 位。这在 IPv4 中技术上并不违法(它在 IPv6 上),但不鼓励并且在实践中很少使用。子网掩码的高位应始终为连续的 1 位。

以上是关于检查 IP 地址是不是在范围/子网内的标准/安全方法的主要内容,如果未能解决你的问题,请参考以下文章

第1章·子网划分的意义及案例

我应该在 Azure *** 中使用网关子网中的 IP 地址吗?

如何从 IP 范围/子网中获取随机 IP?

Centos网络管理-IP与子网掩码计算

Pandas检查哪个子网IP地址属于

只知道一个ip地址如何算出他的子网掩码和网络ID以及主机ID的范围呢?