
本文介绍如何使用 php 判断两个 ipv4 或 ipv6 地址/cidr 是否位于同一子网,提供轻量级自定义函数(ipv4)和推荐的成熟方案(ipv6),并附带可直接运行的示例与关键注意事项。
本文介绍如何使用 php 判断两个 ipv4 或 ipv6 地址/cidr 是否位于同一子网,提供轻量级自定义函数(ipv4)和推荐的成熟方案(ipv6),并附带可直接运行的示例与关键注意事项。
在实际网络服务开发中(如访问控制、多租户隔离、安全审计),常需验证两个 IP 地址(或其所属 CIDR 表示的子网)是否处于同一逻辑网络内。例如:192.168.1.10/24 与 192.168.1.50/24 属于同一子网,而 192.168.1.10/24 和 192.168.10.130/24 则不属于——尽管掩码相同,但网络地址不同(前者为 192.168.1.0,后者为 192.168.10.0)。
✅ IPv4:使用位运算精准比对(无依赖)
核心思路是:将 CIDR 解析为网络地址(subnet)和前缀长度(mask),再将待测 IP 与该子网掩码做按位与运算,结果等于网络地址即表示命中子网。
function cidr_match($ip, $cidr) {
list($subnet, $mask) = explode('/', $cidr);
// 验证输入合法性(增强健壮性)
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ||
!filter_var($subnet, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ||
!is_numeric($mask) || $mask 32) {
return false;
}
$ipLong = ip2long($ip);
$subnetLong = ip2long($subnet);
$maskBits = (1 <blockquote>
<p>⚠️ 注意事项: </p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5233" title="btpanel phpsite 宝塔面板PHP网站"><img
src="https://img.php.cn/upload/skill/000/000/081/179040786932301.jpg" alt="btpanel phpsite 宝塔面板PHP网站" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill5233" title="btpanel phpsite 宝塔面板PHP网站" class="overflowclass">btpanel phpsite 宝塔面板PHP网站</a>
<p class="overflowclass">宝塔面板 PHP 网站管理:站点创建、删除、启停、PHP 版本切换、域名管理、SSL证书管理、伪静态管理、数据库管理</p>
</div>
<a rel="nofollow" href="/xiazai/skill5233" title="btpanel phpsite 宝塔面板PHP网站" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<ul>
<li>
<code>ip2long()</code> 在 Windows 上对 <code>255.255.255.255</code> 可能返回负数,建议统一用 <code>sprintf('%u', ip2long($ip))</code> 转为无符号整型(本例已通过 <code>===</code> 严格比较规避溢出风险); </li>
<li>此函数仅校验 <em>单个 IP 是否属于某 CIDR</em>,若需判断「两个 CIDR 是否重叠或同属一更大网络」,需额外实现网络地址归一化与包含关系分析(见下文延伸说明)。</li>
</ul>
</blockquote><h3>✅ IPv6:推荐使用 Symfony HttpFoundation(稳定可靠)</h3><p>原生 PHP 对 IPv6 子网计算支持有限,手动实现易出错。<code>Symfony\Component\HttpFoundation\IpUtils::checkIp()</code> 经过广泛测试,同时支持 IPv4/IPv6 和 CIDR、范围、通配符等多种格式:</p><pre class="brush:php;toolbar:false;">composer require symfony/http-foundationuse Symfony\Component\HttpFoundation\IpUtils;
// 检查单个 IP 是否在指定 CIDR 内
var_dump(IpUtils::checkIp('2001:db8::1', '2001:db8::/32')); // true
var_dump(IpUtils::checkIp('192.168.5.10', '192.168.0.0/16')); // true
// 批量检查(支持数组 CIDR)
$cidrs = ['192.168.1.0/24', '10.0.0.0/8'];
var_dump(IpUtils::checkIp('10.5.2.7', $cidrs)); // true? 进阶场景:判断两个 CIDR 是否“属于同一网络”?
题干中“same network subnet”若指 两个 CIDR 的网络地址完全一致(如 192.168.1.0/24 和 192.168.1.0/24),可复用上述函数分别提取网络地址后字符串比较;
若指 存在一个更大的公共父网段(如 192.168.1.0/24 和 192.168.2.0/24 共同属于 192.168.0.0/22),则需实现 CIDR 合并算法,超出本文基础范围,建议借助 spatie/cidr 等专用库处理。
✅ 总结
- 对纯 IPv4 且环境受限场景,使用自定义
cidr_match()函数高效可靠; - 涉及 IPv6、生产环境或需长期维护,强烈推荐
symfony/http-foundation—— 它经过大规模验证,API 清晰,扩展性强; - 始终对输入做合法性过滤(
filter_var+ 边界检查),避免因恶意输入导致逻辑错误或潜在漏洞。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










