refactor: 重构随机中国ip

This commit is contained in:
MoeFurina
2026-02-14 23:50:59 +08:00
parent b04b9d51fb
commit f08f192328
3 changed files with 4201 additions and 77 deletions
+54 -51
View File
@@ -1,36 +1,8 @@
const logger = require('./logger')
// 预先定义常量和函数引用
// 中国 IP 段(来源:data/ChineseIPGenerate.csv)
const chinaIPRangesRaw = [
// 开始IP, 结束IP, IP个数, 位置
['1.0.1.0', '1.0.3.255', 768, '福州'],
['1.0.8.0', '1.0.15.255', 2048, '广州'],
['1.0.32.0', '1.0.63.255', 8192, '广州'],
['1.1.0.0', '1.1.0.255', 256, '福州'],
['1.1.2.0', '1.1.63.255', 15872, '广州'],
['1.2.0.0', '1.2.2.255', 768, '北京'],
['1.2.4.0', '1.2.127.255', 31744, '广州'],
['1.3.0.0', '1.3.255.255', 65536, '广州'],
['1.4.1.0', '1.4.127.255', 32512, '广州'],
['1.8.0.0', '1.8.255.255', 65536, '北京'],
['1.10.0.0', '1.10.9.255', 2560, '福州'],
['1.10.11.0', '1.10.127.255', 29952, '广州'],
['1.12.0.0', '1.15.255.255', 262144, '上海'],
['1.18.128.0', '1.18.128.255', 256, '北京'],
['1.24.0.0', '1.31.255.255', 524288, '赤峰'],
['1.45.0.0', '1.45.255.255', 65536, '北京'],
['1.48.0.0', '1.51.255.255', 262144, '济南'],
['1.56.0.0', '1.63.255.255', 524288, '伊春'],
['1.68.0.0', '1.71.255.255', 262144, '忻州'],
['1.80.0.0', '1.95.255.255', 1048576, '北京'],
['1.116.0.0', '1.117.255.255', 131072, '上海'],
['1.119.0.0', '1.119.255.255', 65536, '北京'],
['1.180.0.0', '1.185.255.255', 393216, '桂林'],
['1.188.0.0', '1.199.255.255', 786432, '洛阳'],
['1.202.0.0', '1.207.255.255', 393216, '铜仁'],
]
const fs = require('fs')
const path = require('path')
// 将原始字符串段转换为数值段并计算总数(在模块初始化时完成一次)
// IP地址转换函数
function ipToInt(ip) {
const parts = ip.split('.').map(Number)
const a = (parts[0] << 24) >>> 0
@@ -49,20 +21,56 @@ function intToIp(int) {
].join('.')
}
const chinaIPRanges = (function buildRanges() {
const arr = []
let total = 0
for (let i = 0; i < chinaIPRangesRaw.length; i++) {
const r = chinaIPRangesRaw[i]
const start = ipToInt(r[0])
const end = ipToInt(r[1])
const count = r[2] || end - start + 1
arr.push({ start, end, count, location: r[3] || '' })
total += count
// 解析CIDR格式的IP段
function parseCIDR(cidr) {
const [ipStr, prefixLengthStr] = cidr.split('/')
const prefixLength = parseInt(prefixLengthStr, 10)
const ipInt = ipToInt(ipStr)
const mask = (0xffffffff << (32 - prefixLength)) >>> 0
const start = (ipInt & mask) >>> 0
const end = (start | (~mask >>> 0)) >>> 0
const count = end - start + 1
return { start, end, count, cidr }
}
// 从china_ip_ranges.txt加载中国IP段(CIDR格式)
const chinaIPRanges = (function loadChinaIPRanges() {
try {
const filePath = path.join(__dirname, '../data/china_ip_ranges.txt')
const content = fs.readFileSync(filePath, 'utf-8')
const lines = content
.split('\n')
.filter((line) => line.trim() && !line.startsWith('#'))
const arr = []
let total = 0
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim()
if (!line) continue
const range = parseCIDR(line)
arr.push(range)
total += range.count
}
// 按IP段大小排序,提高随机选择效率
arr.sort((a, b) => b.count - a.count)
// attach total for convenience
arr.totalCount = total
logger.info(
`Loaded ${arr.length} Chinese IP ranges from china_ip_ranges.txt, total ${total} IPs`,
)
return arr
} catch (error) {
logger.error('Failed to load china_ip_ranges.txt:', error.message)
// 返回空数组,generateRandomChineseIP会使用兜底逻辑
return { totalCount: 0 }
}
// attach total for convenience
arr.totalCount = total
return arr
})()
const floor = Math.floor
const random = Math.random
@@ -144,16 +152,11 @@ module.exports = {
// 如果没有选中(理论上不应该发生),回退到最后一个段
if (!chosen) chosen = chinaIPRanges[chinaIPRanges.length - 1]
// 在段内随机生成一个 IP(使用段真实的数值范围,而非 csv 中的 count)
// 在段内随机生成一个 IP(使用段真实的数值范围)
const segSize = chosen.end - chosen.start + 1
const ipInt = chosen.start + Math.floor(random() * segSize)
const ip = intToIp(ipInt)
logger.info(
'Generated Random Chinese IP:',
ip,
'location:',
chosen.location,
)
logger.info('Generated Random Chinese IP:', ip, 'from CIDR:', chosen.cidr)
return ip
},
// 生成chainId的函数