别再放任用户乱填 IP 了!一套前端 IP 与 CIDR 校验的高效方案

953 阅读5分钟

在实际开发中,网络地址输入错误往往是隐藏的“定时炸弹”:

  • 用户在表单里输个 192.168.300.1,结果后端直接报错;
  • 运维想加个网段 10.0.0.0/40,系统却崩了;
  • 防火墙、白名单、批量导入……一个错误输入可能拖垮整个配置流程。

👉 这些问题,完全可以在前端就拦截掉!
如果你还没在项目里做 IP / CIDR 校验,这篇文章就是提醒你“该补上这一环了”。

IPv4 与 CIDR 到底是什么?

IPv4(本文聚焦 IPv4)

IPv4(Internet Protocol version 4)是目前最常用的 IP 地址格式,由 4 段十进制数 组成(范围 0–255),用点隔开:

  • 192.168.0.1
  • 10.0.0.5
  • 00.1.2.3(前导零是允许的,严格模式不合法)
  • 192.168.1.1.(末尾多点)
  • 256.0.0.1(超出 255)

常见分类:

  • 公网 IP:可在互联网上直接路由
  • 私网 IP10.0.0.0/8172.16.0.0/12192.168.0.0/16
  • 特殊 IP127.0.0.1(回环)、0.0.0.0(任意地址)

CIDR(网段表示法)

CIDR(Classless Inter-Domain Routing,无类域间路由)用来表示 一个 IP 段,格式为:
IP/前缀长度

  • 192.168.0.0/24 → 覆盖 192.168.0.0192.168.0.255 共 256 个地址
  • 10.0.0.0/8 → 覆盖 10.0.0.010.255.255.255 共 1600 万个地址
  • 00.1.2.3/24 → 前导零同样支持,严格模式不合法)
  • 192.168.1.0/35 → 掩码不可能大于 32

前缀长度范围必须是 0–32,其中:

  • /24 表示前 24 位是网络号,后 8 位是主机号
  • /0 表示全网(0.0.0.0/0

前导零处理策略

在IPv4验证中,有两种策略:

严格模式(如Node.js net.isIP()

  • 拒绝前导零:00.1.2.3
  • 避免八进制解释混淆
  • 适合对格式要求严格的场景

宽松模式(如系统ping、网络设备)

  • 接受前导零:00.1.2.3 ✅ (很神奇吧!你试试)
  • 符合实际网络应用需求
  • 适合用户输入和配置场景

本文采用宽松模式,因为:

  • 系统 ping 00.1.2.3 能正常工作
  • 网络设备配置普遍支持前导零
  • 用户输入习惯更加灵活

可直接复用的校验正则与函数

IPv4 校验

const validateIPv4 = (input: string) => {
    // 宽松模式
    const regex = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
    // 严格模式
    // const regexStrict = /^((\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.){3}(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))$/;
    return regex.test(input);

}

精准限制 0–255,不允许末尾多点。正则解析

  • 25[0-5]:匹配 250-255
  • 2[0-4][0-9]:匹配 200-249
  • [01]?[0-9][0-9]?:匹配 0-199(支持前导零)

CIDR 校验

const validateCIDR = (input: string) => {
  // 宽松模式
  const regex = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(3[0-2]|[12]?[0-9])$/;
  // 严格模式
  // const regex = /^((\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.){3}(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\/(3[0-2]|[12]?[0-9])$/
  return regex.test(input);
};

保证前缀长度在 0–32,非法掩码直接判错。掩码部分解析

  • 3[0-2]:匹配 30-32
  • [12]?[0-9]:匹配 0-29

单行判定策略

用户输入可能是 单个 IP一个 CIDR,两者之一合法即可。

/**
 * 校验IP和CIDR
 * @param s 字符串
 * @returns 是否是IP或CIDR
 */
const isValidIpOrCidr = (s: string) => {
  const v = s.trim();
  return validateIPv4(v) || validateCIDR(v);
};

批量输入的高可用校验方案

在实际场景里(批量导入、防火墙规则、白名单),往往是多行输入。
我们需要支持:换行、注释、去重、逐行定位错误

/**
 * 批量校验IP和CIDR
 * @param lines 
 * @param allowComments 是否允许注释
 * @param dedupe 是否去重
 * @returns {ok: boolean, errors: string[], items: string[]} 是否校验通过,错误信息,校验通过的IP和CIDR
 */
const validateBatch = (lines: string[], { allowComments = true, dedupe = true } = {}) => {
  const itemsWithLineNumbers = lines
    .map((s, originalIndex) => {
      let content = s.trim()
      // 如果包含 # 且不是行首注释,则截断到 # 前
      const commentIndex = content.indexOf('#')
      if (commentIndex > 0) {
        content = content.slice(0, commentIndex).trim()
      }
      return { content, originalLine: originalIndex + 1 }
    })
    .filter(item => item.content.length > 0 && (!allowComments || !item.content.startsWith('#')));

  let items = itemsWithLineNumbers;
  
  if (dedupe) {
    const seen = new Set();
    items = items.filter(item => (seen.has(item.content) ? false : (seen.add(item.content), true)));
  }

  const errors: any = [];
  items.forEach((item) => {
    if (!isValidIpOrCidr(item.content)) {
      errors.push(`第 ${item.originalLine} 行格式不正确: ${item.content}`);
    }
  });

  return {
    ok: errors.length === 0,
    errors,
    items: items.map(item => item.content)
  };
};

使用示例

const input = `
# 服务器IP配置
192.168.1.100
00.1.2.3
10.0.0.0/8

# 错误示例
256.1.1.1
192.168.1.0/35
`.trim().split('\n');

const result = validateBatch(input);
console.log(result);
// {
//   ok: false,
//   errors: ['第 7 行格式不正确: 256.1.1.1', '第 8 行格式不正确: 192.168.1.0/35'],
//   items: ['192.168.1.100', '00.1.2.3', '10.0.0.0/8', '256.1.1.1', '192.168.1.0/35'],
// }

一分钟自测清单

  • ✅ 合法 IP

    • 1.2.3.4
    • 192.168.0.1
    • 255.255.255.255
    • 00.1.2.3(IPv4标准允许前导零,严格模式不合法)
    • 000.1.2.3(三位前导零,严格模式不合法)
    • 0.0.0.0
  • ❌ 不合法 IP

    • 192.168.1.1.(末尾点)
    • 256.0.0.1(超出范围)
    • 192.168.1(缺少段)
    • 192.168.1.1.1(多余段)
  • ✅ 合法 CIDR

    • 10.0.0.0/8
    • 172.16.0.0/12
    • 192.168.1.0/24
    • 0.0.0.0/0(默认路由)
    • 00.1.2.3/24(前导零IP,严格模式不合法)
    • 192.168.1.1/32(单主机)
  • ❌ 不合法 CIDR

    • 192.168.1.0/35(掩码超出 32)
    • 192.168.1.0/-1(负数掩码)
    • 192.168.1.0/033(前导零掩码,避免八进制混淆)
    • 256.1.1.1/24(无效IP)

总结

无论你在做:

  • API 网关
  • 防火墙规则配置
  • 监控平台
  • 管理系统

只要涉及 IP 或 CIDR 配置前端校验就是必不可少的一环

通过这套正则与函数,你可以:迅速拦截错误、提升安全性、改善用户体验。

🚀 更简单的选择:Regex Center

如果你觉得手写这些正则表达式还是太麻烦,不妨试试 Regex Center —— 一个专业的正则表达式管理库,内置了 100+ 精选正则,包括本文提到的所有 IP 和 CIDR 验证:

npm install regex-center
import { rx } from 'regex-center';

// 🎯 语义化API,一看就懂
rx.test('ip:v4', '00.1.2.3');           // ✅ true - IPv4验证
rx.test('ip:cidr_v4', '192.168.1.0/24'); // ✅ true - CIDR验证
rx.test('ip:cidr_v6', '2001:db8::/32');  // ✅ true - IPv6 CIDR

// 🔥 文本处理,开箱即用
const text = '服务器:192.168.1.100,网段:10.0.0.0/8,测试:00.1.2.3';
rx.extractAll('ip:v4', text);           // ['192.168.1.100', '10.0.0.0', '00.1.2.3']
rx.replaceAll('ip:v4', text, '[IP]');   // '服务器:[IP],网段:[IP]/8,测试:[IP]'

// 💪 批量验证,企业级功能
const ips = ['192.168.1.1', '00.1.2.3', '10.0.0.0/8'];
ips.every(ip => rx.test('ip:v4', ip) || rx.test('ip:cidr_v4', ip)); // 批量检查

为什么选择 Regex Center?

  • 零配置启动import { rx } 即可使用,无需复制粘贴正则
  • 语义化APIrx.test('ip:cidr_v4', input) 比一长串正则更易读
  • 完整覆盖:IPv4、IPv6、CIDR、私有IP... 网络相关验证一应俱全
  • 前导零支持:与实际网络应用保持一致,避免格式冲突
  • TypeScript友好:完整类型提示,IDE智能补全
  • 团队标准化:告别每个人写不同正则的混乱局面

记住:好的工具能让你专注于业务逻辑,而不是纠结于正则表达式的细节。Regex Center 就是这样一个让 IP/CIDR 验证变得简单的工具!

本文提供的所有代码都经过实际测试,可以直接在项目中使用。如果你想要更强大的正则管理能力,不妨试试 Regex Center