import * as os from 'os'; import * as fs from 'fs'; import * as path from 'path'; import * as crypto from 'crypto'; import type { HardwareFingerprint } from './types'; // 实例 ID 存储路径 const INSTANCE_ID_FILE = path.join(process.cwd(), 'data', '.instance-id'); /** * 获取 machine-id * Linux: /etc/machine-id 或 /var/lib/dbus/machine-id * Windows: 使用 hostname + 网卡信息生成 * Docker: 使用容器 ID 或挂载的 machine-id */ async function getMachineId(): Promise { // 尝试读取 Linux machine-id const machineIdPaths = [ '/etc/machine-id', '/var/lib/dbus/machine-id', ]; for (const filePath of machineIdPaths) { try { const machineId = fs.readFileSync(filePath, 'utf8').trim(); if (machineId) { return machineId; } } catch { // 文件不存在,继续尝试下一个 } } // 尝试读取 Docker 容器 ID try { const cgroupContent = fs.readFileSync('/proc/self/cgroup', 'utf8'); const match = cgroupContent.match(/docker[/-]([a-f0-9]{64})/); if (match) { return match[1].substring(0, 32); } } catch { // 不在 Docker 容器中 } // Windows 或其他系统:使用 hostname + 网卡信息生成 const hostname = os.hostname(); const networkInterfaces = os.networkInterfaces(); const macs: string[] = []; for (const interfaces of Object.values(networkInterfaces)) { if (interfaces) { for (const iface of interfaces) { if (!iface.internal && iface.mac !== '00:00:00:00:00:00') { macs.push(iface.mac); } } } } const data = `${hostname}-${macs.sort().join('-')}`; return crypto.createHash('md5').update(data).digest('hex'); } /** * 获取主网卡 MAC 地址 */ function getPrimaryMacAddress(): string { const networkInterfaces = os.networkInterfaces(); // 优先查找常见的网卡名称 const preferredNames = ['eth0', 'en0', 'ens33', 'enp0s3', 'Ethernet', 'Wi-Fi']; for (const name of preferredNames) { const interfaces = networkInterfaces[name]; if (interfaces) { for (const iface of interfaces) { if (!iface.internal && iface.mac !== '00:00:00:00:00:00') { return iface.mac; } } } } // 如果没有找到,返回第一个非内部网卡的 MAC for (const interfaces of Object.values(networkInterfaces)) { if (interfaces) { for (const iface of interfaces) { if (!iface.internal && iface.mac !== '00:00:00:00:00:00') { return iface.mac; } } } } return '00:00:00:00:00:00'; } /** * 获取或创建实例 ID * 实例 ID 在首次激活时生成,并持久化存储 */ async function getOrCreateInstanceId(): Promise { // 确保目录存在 const dir = path.dirname(INSTANCE_ID_FILE); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } // 尝试读取现有的实例 ID try { const instanceId = fs.readFileSync(INSTANCE_ID_FILE, 'utf8').trim(); if (instanceId) { return instanceId; } } catch { // 文件不存在 } // 生成新的实例 ID const instanceId = crypto.randomBytes(16).toString('hex'); fs.writeFileSync(INSTANCE_ID_FILE, instanceId); return instanceId; } /** * 生成硬件指纹 */ export async function generateFingerprint(): Promise { const [machineId, instanceId] = await Promise.all([ getMachineId(), getOrCreateInstanceId(), ]); return { machineId, hostname: os.hostname(), macAddress: getPrimaryMacAddress(), instanceId, }; } /** * 获取实例 ID */ export async function getInstanceId(): Promise { return getOrCreateInstanceId(); } /** * 计算两个指纹的匹配分数 * 返回 0-100 的分数 */ export function calculateFingerprintMatchScore( stored: HardwareFingerprint, current: HardwareFingerprint ): number { let score = 0; // machineId 权重 40% if (stored.machineId === current.machineId) { score += 40; } // hostname 权重 20% if (stored.hostname === current.hostname) { score += 20; } // macAddress 权重 30% if (stored.macAddress === current.macAddress) { score += 30; } // instanceId 权重 10% if (stored.instanceId === current.instanceId) { score += 10; } return score; } /** * 检查指纹是否匹配(60% 阈值) */ export function isFingerprintMatch( stored: HardwareFingerprint, current: HardwareFingerprint ): boolean { return calculateFingerprintMatchScore(stored, current) >= 60; }