@bybrave/ip2

中文文档
3.1.0发布于 2026/10/14MITTypeScriptESM + CJS零依赖近 30 天下载 5472

维护了 ip- IP 地址公用设施,未标注 SSRF 咨询(CVE-2024-29415 / GHSA-2p57-rm9w-gvfp)固定

中文使用文档
文档目录10 节
  1. 脆弱性及其如何固定
  2. 全部修正完毕 [email protected]
  3. 从 ip 移动
  4. 中断更改(v3)
  5. API 密码
  6. 无效的输入抛出
  7. 浏览器和捆绑器
  8. 作为私有范围处理(无法在全球达到)
  9. 支助
  10. 信贷和许可证

@bybrave/ip2 (英语)

CI npm

维护的叉 ip ——Node.js的IP地址公用设施——与 已固定无标SSRF咨询。 。 。 .

原版包有~38M下载量/月,自2024年2月起无发行量,并有高清的咨询(CVE-2024-29415 (中文(简体) ) 编号 : GHSA-2p57-rm9w-gvfp影响 每个已出版的版本 并创造 npm audit 每次安装失败 。 此分叉修正了根因,而不是补丁正格克塞.

npm install @bybrave/ip2
// CommonJS — drop-in
const ip = require('@bybrave/ip2');

// ESM — named imports
import { isPrivate, isPublic, cidrSubnet } from '@bybrave/ip2';

// TypeScript types built in

脆弱性及其如何固定

原画 isPrivate() 编号 : isPublic() 编号 : isLoopback() 跑过雷克塞斯 原始输入字符串. Regexes没有预料到的地址的任何拼写——八分音或六分音,缩写为IPv4,未压缩的IPv6——被默默地归类为: 公开数字 :

// original [email protected] — all of these are loopback/private, all reported PUBLIC:
ip.isPublic('127.1')            // true 💥
ip.isPublic('012.1.2.3')        // true 💥  (octal 10.1.2.3)
ip.isPublic('01200034567')      // true 💥  (integer 10.0.14.119)
ip.isPublic('000:0:0000::01')   // true 💥  (that's ::1)

如果这些解答 守卫发出的请求, 这是一个SSF孔(CVE-2024-29415), 不完整的修复 CVE-2023-42282.

这个叉子:

  1. 先分析,再分类第二. 每个分类函数将地址解为字节并带有严格的解析器(语法相同于 net.isIP,加上IPv6区ID. 分类运行在字节上,从未运行在字符串上.
  2. 拒绝模糊的输入 . 非冠词拼写法(127.1, (中文(简体) ), 0x7f.1, (中文(简体) ), 0177.0.0.1, (中文(简体) ), 2130706433(中文(简体) ) 掷出 而不是被猜测。 失败关闭,没有打开。 如果你需要接受遗留的标记,首先明确正常化: ip.fromLong(ip.normalizeToLong(addr))。 。 。 .
  3. 涵盖IANA全部特殊用途登记册 (单位:千美元)IPv4 请检查url=值 (帮助), (中文(简体) ), IPv6 请检查url=值 (帮助)),不是四个regex. isPrivate() 现在的意思是"无法在全球达到"——与Python的同一种公约 ipaddress。增加了CGNAT(100.64/10,TEST-NET,基准,多播,保留,ULA,文件范围等——见下表.
  4. 通过嵌入式IPv4对过渡地址进行分类. ::ffff:a.b.c.d (v4-被标记), 64:ff9b::a.b.c.d (NAT64)和 (中文(简体) ) 2002:xxxx:xxxx:: 根据其中的IPv4地址,(6to4)是私有/公有的.
// @bybrave/ip2
ip.isPublic('127.1')             // throws Error: Invalid ip address: 127.1
ip.isPrivate('000:0:0000::01')   // true (parsed as ::1)
ip.isLoopback('::fFFf:127.0.0.1')// true
ip.isPublic('64:ff9b::8.8.8.8')  // true  (NAT64 of a public address)
ip.isPrivate('100.64.0.1')       // true  (CGNAT — original said public)

全部修正完毕 [email protected]

固定原刊
CVE-2024-29415 / GHSA-2p57-rm9w-gvfp – SSRF通过非卡通地址136号, (中文(简体) ), 150号, (中文(简体) ), 153号, (中文(简体) ), 158号
isPrivate() 错过 CGNAT、TEST-NET、基准、多播、保留、文件范围—— 说
cidrSubnet(...).contains() 返回时 false 用于 IPv4- mapped IPv6 地址104号
isV6Format() 返回时 true 为 IPv4 地址67号
isV4Format() 接受octets 256 键105号
address('public') 已返回 私营 地址与反之 (过滤被倒转)—— 说
loopback('ipv6') 已返回 fe80::1,这是链接 - 本地,而不是回转 ~ 现在 ::1—— 说
cidr()编号 :cidrSubnet() 静态生产垃圾,用于无效的前缀长度(/33, (中文(简体) ), /x) 现在抛出—— 说
address(name) 坠入 TypeError 未知接口名称 − 现在返回 undefined—— 说
cidrSubnet()编号 :subnet() 给 IPv6 错误的答案 (/48 内有相邻者 /48^ 真实的IPv6子网数学89号, (中文(简体) ), 110号
浏览器失败 os (网页包装5) ∗∗ browser 字段映射它离开#127号, (中文(简体) ), 132号
构造的脚本类型( 无) @types/ip (需要)—— 说

从 ip 移动

- const ip = require('ip');
+ const ip = require('@bybrave/ip2');

API表面是相同的;行为差异是安全和正确性的修补——在升级前参见下面的断裂变化.

中断更改(v3)

第3.0.0版 因为严格性是固定的——如果你输入了这个库 非卡通字符串,v2会给你错误的答案,而不是兼容的答案:

  • isPrivate 编号 : isPublic 编号 : isLoopback 编号 : toBuffer 编号 : toLong 掷出 (octal/hex octets, 127.1,整数字符串). 使用 normalizeToLong() 首先,如果你必须接受 遗产标记.
  • isLoopback('fe80::1') 现在 false (链接- 本地 qq; 仍然) isPrivate) (中文(简体) ). isLoopback('::') 现在 false (未指定 qq 循环; 仍然) isPrivate) (中文(简体) ).
  • loopback('ipv6') 返回时 '::1' 改为 'fe80::1'。 。 。 .
  • isPrivate() 返回时 true 对于更多的范围(CGNAT,TEST-NETs,多播,.)——现在意思是"无法在全球达到".
  • address('public') 现在返回公共地址。 如果依靠倒向行为获得局域网地址,请使用 address('private') 这就是它给你的.
  • 节点.js 18.

API 密码

所有原始出口,还有 isValid()数字 :

ip.address('public', 'ipv6')          // address of a network interface
ip.isPrivate('10.0.0.1')              // true — not globally reachable
ip.isPublic('8.8.8.8')                // true
ip.isLoopback('127.8.8.8')            // true
ip.isValid('300.1.2.3')               // false (never throws)
ip.isV4Format('192.168.0.1')          // true
ip.isV6Format('2001:db8::1')          // true
ip.isEqual('::ffff:7f00:1', '127.0.0.1') // true

ip.toBuffer('127.0.0.1')              // Buffer([127, 0, 0, 1])
ip.toString(buf, offset, length)      // '127.0.0.1'
ip.toLong('127.0.0.1')                // 2130706433
ip.fromLong(2130706433)               // '127.0.0.1'
ip.normalizeToLong('127.1')           // 2130706433 (lenient, -1 on error)

ip.fromPrefixLen(24)                  // '255.255.255.0'
ip.mask('192.168.1.134', '255.255.255.0') // '192.168.1.0'
ip.cidr('192.168.1.134/26')           // '192.168.1.128'
ip.not('255.255.255.0')               // '0.0.0.255'
ip.or('0.0.0.255', '192.168.1.10')    // '192.168.1.255'

const s = ip.cidrSubnet('192.168.1.134/26')
s.networkAddress                      // '192.168.1.128'
s.firstAddress                        // '192.168.1.129'
s.lastAddress                         // '192.168.1.190'
s.broadcastAddress                    // '192.168.1.191'
s.subnetMaskLength                    // 26
s.numHosts                            // 62
s.contains('::ffff:192.168.1.180')    // true (v4-mapped handled)

const s6 = ip.cidrSubnet('2001:db8:f53b::/48')
s6.lastAddress                        // '2001:db8:f53b:ffff:ffff:ffff:ffff:ffff'
s6.contains('2001:db8:f53a::1')       // false
s6.length                             // 2 ** 80 (approximate above 2 ** 53)

IPv6子网没有广播或保留主机地址: firstAddress 是网络地址和 broadcastAddress 等于 lastAddress。 。 。 . ip.subnet(addr, mask) 当地址和口罩都是IPv6时使用IPv6数学. 普通IPv4地址由IPv6子网通过IPv4-mapped范围相匹配(::ffff:0:0/96) (中文(简体) ).

无效的输入抛出

isPrivate, (中文(简体) ), isPublic, (中文(简体) ), isLoopback, (中文(简体) ), toBuffer 财务报告和审定财务报表 toLong 丢弃错误的输入而不是返回一个猜想( e)146号) (中文(简体) ). 当输入不可信时, 请先检查或抓取 :

const isInternal = ip.isValid(host) && ip.isPrivate(host)

浏览器和捆绑器

图书馆为节点第一. 在一个捆绑中, os 被映射通过 browser 字段,所以 address() 没空,其他的都用过一次 Buffer 已提供。 加上多填充(#127号, (中文(简体) ), 132号:

// webpack.config.js, after `npm i buffer`
resolve: { fallback: { buffer: require.resolve('buffer/') } }

作为私有范围处理(无法在全球达到)

IPv4: (英语) 0.0.0.0/8, (中文(简体) ), 10.0.0.0/8, (中文(简体) ), 100.64.0.0/10 (导航卫星系统), 127.0.0.0/8, (中文(简体) ), 169.254.0.0/16, (中文(简体) ), 172.16.0.0/12, (中文(简体) ), 192.0.0.0/24, (中文(简体) ), 192.0.2.0/24, (中文(简体) ), 192.88.99.0/24, (中文(简体) ), 192.168.0.0/16, (中文(简体) ), 198.18.0.0/15, (中文(简体) ), 198.51.100.0/24, (中文(简体) ), 203.0.113.0/24, (中文(简体) ), 224.0.0.0/4, (中文(简体) ), 240.0.0.0/4 (包括广播).

IPv6: (英语) ::/96 (未说明,回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回, 64:ff9b:1::/48, (中文(简体) ), 100::/64, (中文(简体) ), 2001::/23, (中文(简体) ), 2001:db8::/32, (中文(简体) ), 3fff::/20, (中文(简体) ), 5f00::/16, (中文(简体) ), fc00::/7, (中文(简体) ), fe80::/10, (中文(简体) ), fec0::/10, (中文(简体) ), ff00::/8。过渡范围 ::ffff:0:0/96, (中文(简体) ), 64:ff9b::/96 财务报告和审定财务报表 2002::/16 跟踪他们的IPv4地址.

支助

如果此软件包节省了您的时间, 您可以支持维护 :

Ko-fi Bitcoin

比特币( BTC): bc1q37557q5jpeaxqydzwvf3jgj7zhnfpn2td3q40q

信贷和许可证

麻省理工学院. 依据 节点-ip 费多尔·印地安尼.

版本与发布记录

@bybrave/ip2 共发布 2 个版本,首次发布于 2026/07/05;过去 12 个月发布了 2 个版本。

版本发布日期距今
3.1.0latest2026/10/1425 天前
3.0.02026/07/054 个月前

关于 @bybrave/ip2 的常见问题

@bybrave/ip2 是什么?

维护了 ip- IP 地址公用设施,未标注 SSRF 咨询(CVE-2024-29415 / GHSA-2p57-rm9w-gvfp)固定

如何安装 @bybrave/ip2?

在项目目录运行 npm install @bybrave/ip2,或使用 pnpm add / yarn add / bun add。

@bybrave/ip2 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@bybrave/ip2 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@bybrave/ip2 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@bybrave/ip2 可以商用吗?

@bybrave/ip2 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@bybrave/ip2 的下载量有多少?

根据 npm 官方下载统计,@bybrave/ip2 在 2026/10/09 – 2026/11/07 这 30 天内被下载 5,472 次,日均约 182 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@bybrave/ip2 还在维护吗?

最新版本 3.1.0 发布于 2026/10/14(25 天前);至今共发布 2 个版本,其中过去 12 个月发布了 2 个;首次发布于 2026/07/05。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。