IpUtil.ts 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import * as os from "node:os";
  2. import * as net from "node:net";
  3. export class IpUtil {
  4. // 常见虚拟机网络地址范围
  5. private static readonly VM_NETWORKS = [
  6. '192.168.56.0/24', // VirtualBox Host-Only
  7. '192.168.122.0/24', // KVM
  8. '172.16.0.0/12', // VMware NAT
  9. '192.168.99.0/24', // Docker Machine
  10. '192.168.65.0/24', // Docker Desktop
  11. '192.168.250.0/24', // Parallels
  12. '192.168.131.0/24' // Hyper-V
  13. ];
  14. public static async getLocalIp(): Promise<string> {
  15. return new Promise((resolve, reject) => {
  16. const addressArray = IpUtil.getActiveIPv4Addresses()
  17. if (addressArray && addressArray.length > 0) {
  18. resolve(addressArray[0])
  19. }
  20. reject('未找到可用的IP地址')
  21. })
  22. }
  23. private static getActiveIPv4Addresses() {
  24. const interfaces = os.networkInterfaces()
  25. const addresses: Array<string> = []
  26. for (const interfaceName in interfaces) {
  27. const interfaceInfo = interfaces[interfaceName]
  28. // @ts-ignore
  29. for (const info of interfaceInfo) {
  30. // 过滤条件:IPv4、不是内部地址、不是回环地址、不是虚拟机IP
  31. if (info.family === 'IPv4' &&
  32. !info.internal &&
  33. net.isIPv4(info.address) &&
  34. !IpUtil.isVMIP(info.address)) {
  35. addresses.push(info.address)
  36. }
  37. }
  38. }
  39. return addresses
  40. }
  41. private static isVMIP(ip) {
  42. const ipLong = ip.split('.').reduce((acc, octet) => (acc << 8) + parseInt(octet, 10), 0)
  43. return IpUtil.VM_NETWORKS.some(range => {
  44. const [base, maskBits] = range.split('/')
  45. const mask = ~(0xFFFFFFFF >>> parseInt(maskBits, 10));
  46. const baseLong = base.split('.').reduce((acc, octet) => (acc << 8) + parseInt(octet, 10), 0)
  47. return (ipLong & mask) === (baseLong & mask)
  48. });
  49. }
  50. }