import * as os from "node:os"; import * as net from "node:net"; export class IpUtil { // 常见虚拟机网络地址范围 private static readonly VM_NETWORKS = [ '192.168.56.0/24', // VirtualBox Host-Only '192.168.122.0/24', // KVM '172.16.0.0/12', // VMware NAT '192.168.99.0/24', // Docker Machine '192.168.65.0/24', // Docker Desktop '192.168.250.0/24', // Parallels '192.168.131.0/24' // Hyper-V ]; public static async getLocalIp(): Promise { return new Promise((resolve, reject) => { const addressArray = IpUtil.getActiveIPv4Addresses() if (addressArray && addressArray.length > 0) { resolve(addressArray[0]) } reject('未找到可用的IP地址') }) } private static getActiveIPv4Addresses() { const interfaces = os.networkInterfaces() const addresses: Array = [] for (const interfaceName in interfaces) { const interfaceInfo = interfaces[interfaceName] // @ts-ignore for (const info of interfaceInfo) { // 过滤条件:IPv4、不是内部地址、不是回环地址、不是虚拟机IP if (info.family === 'IPv4' && !info.internal && net.isIPv4(info.address) && !IpUtil.isVMIP(info.address)) { addresses.push(info.address) } } } return addresses } private static isVMIP(ip) { const ipLong = ip.split('.').reduce((acc, octet) => (acc << 8) + parseInt(octet, 10), 0) return IpUtil.VM_NETWORKS.some(range => { const [base, maskBits] = range.split('/') const mask = ~(0xFFFFFFFF >>> parseInt(maskBits, 10)); const baseLong = base.split('.').reduce((acc, octet) => (acc << 8) + parseInt(octet, 10), 0) return (ipLong & mask) === (baseLong & mask) }); } }