IPv6 地址规范化实战:把多种写法归一成一种
同一个 IPv6 地址常有压缩、展开、大小写、前导零等多种写法,导致比对和去重出错。本文讲清规范化规则,并演示在浏览器本地把杂乱列表统一成标准形式的做法。
IPv6 地址规范化实战:把多种写法归一成一种
我第一次被 IPv6 地址坑到,是在合并两份防火墙白名单的时候。一份里写着 2001:db8::1,另一份写着 2001:0db8:0000:0000:0000:0000:0000:0001,文本比对工具认为这是两条不同的记录,于是同一台主机被放进白名单两次,审计时还以为多了一个未知节点。问题不在数据,在写法:这两串字符指向的是同一个地址。
为什么同一个 IPv6 会有多种写法
IPv6 地址是 128 位,按惯例写成 8 组、每组 4 位十六进制,用冒号隔开。规范允许两种省略:
- 每组里的前导零可以去掉,
0db8写成db8,0000写成0。 - 一段连续的全零组可以用
::整个折叠掉,但整个地址里只能出现一次::。
这两条省略规则一叠加,同一个地址就有了大量合法写法。再加上十六进制字母大小写都被接受(DB8 和 db8 等价),写法数量进一步膨胀。人手敲、不同设备导出、从网页复制,各写各的,文本上就对不齐了。
规范化到底在统一什么
规范化的目标,是让同一个地址永远只产出一种字符串。业界遵循的是 RFC 5952,核心几条:
- 所有十六进制字母转小写。
- 每组去掉前导零,但保留至少一位,
0000变成0。 - 用
::折叠最长的一段连续零组;如果有两段一样长,折叠靠前的那一段。 ::只用一次,不能拆零段去凑。
这里最容易被忽略的是"压缩最长零段"这一条。比如 2001:0db8:0000:0000:0001:0000:0000:0001,前面有两段连续零,后面也有两段,但前一段更靠前且长度相同,规范要求压前面那段,得到 2001:db8::1:0:0:1,而不是随便压一段。只有规则唯一,结果才唯一。
一个完整的输入输出例子
把展开到底的写法丢进规范化:
输入: 2001:0db8:0000:0000:0000:0000:0000:0001
输出: 2001:db8::1
去前导零:0db8 变 db8,后面六组 0000 是最长的连续零段,整段压成 ::,末组 0001 去零变 1。一行 39 个字符的地址,规范化后只剩 11 个字符,而且和别人手写的 2001:db8::1 完全一致,再比对就不会误判成两条。
比对和去重之前,先规范化
我现在的习惯是:任何要做去重、求交集、对白名单的 IPv6 列表,先过一遍规范化,再做后续动作。顺序反了,去重会漏。fe80::1 和 FE80:0000:0000:0000:0000:0000:0000:0001 在没规范化时是两条,规范化后才会被识别成同一条收掉。
实际清洗时我会用 IPv6 地址规范化工具 直接把粘贴进来的杂乱文本统一成标准压缩形式,大小写、前导零、零段折叠一次处理完,输出还能切成逐行、CSV、JSON 或 SQL IN,交接给脚本时不用再手工补引号逗号。如果列表里本来就有重复项,可以再接 IPv6 地址去重工具,在规范化之后去重才是干净的。需要换成开发可直接用的片段格式,就转给 IPv6 列表转换工具。
本地处理,数据不出浏览器
IP 列表往往牵涉内网拓扑、客户资产、访问来源,这类东西不该随手发到第三方服务器。上面这些工具的解析、规范化、去重、导出全在浏览器本地完成,上传的文本文件通过 File API 在当前标签页读取,不发到任何服务器。处理完直接复制或下载结果即可。
顺带提醒一句:规范化只管格式,不验证地址背后的主机是否真实存在,格式正确不等于这台机器在线。如果你的日志里 IPv4 和 IPv6 混在一起,可以先用 IPv4 地址提取工具 把两类地址分开,再各自规范化处理,排查起来更清楚。
把规范化放在流程最前面,后面的比对、去重、白名单维护都会稳很多,也不会再出现同一台主机算成两台的尴尬。
Made by Toolora · Updated 2026-06-13