diff --git a/kernel/util/net.go b/kernel/util/net.go index 9e79b6295..1f39ca627 100644 --- a/kernel/util/net.go +++ b/kernel/util/net.go @@ -33,6 +33,64 @@ import ( "github.com/siyuan-note/logging" ) +// GetPrivateIPv4s 获取本地所有的私有 IPv4 地址(排除虚拟网卡) +func GetPrivateIPv4s() (ret []string) { + ret = []string{} + + interfaces, err := net.Interfaces() + if err != nil { + return + } + + // 常见的虚拟网卡名称关键字黑名单 + virtualKeywords := []string{"docker", "veth", "br-", "vmnet", "vbox", "utun", "tun", "tap", "bridge", "cloud", "hyper-"} + + for _, itf := range interfaces { + // 1. 基础状态过滤:必须是启动状态且不能是回环网卡 + if itf.Flags&net.FlagUp == 0 || itf.Flags&net.FlagLoopback != 0 { + continue + } + + // 2. 硬件地址过滤:物理网卡通常必须有 MAC 地址 + if len(itf.HardwareAddr) == 0 { + continue + } + + // 3. 名称过滤:排除已知虚拟网卡前缀 + name := strings.ToLower(itf.Name) + isVirtual := false + for _, kw := range virtualKeywords { + if strings.Contains(name, kw) { + isVirtual = true + break + } + } + if isVirtual { + continue + } + + // 4. 提取并校验 IP + addrs, err := itf.Addrs() + if err != nil { + continue + } + + for _, addr := range addrs { + ipNet, ok := addr.(*net.IPNet) + if !ok { + continue + } + + ip := ipNet.IP + // 仅保留 IPv4 且必须是私有局域网地址 (10.x, 172.16.x, 192.168.x) + if ip.To4() != nil && ip.IsPrivate() { + ret = append(ret, ip.String()) + } + } + } + return +} + func IsLocalHostname(hostname string) bool { if "localhost" == hostname || strings.HasSuffix(hostname, ".localhost") { return true diff --git a/kernel/util/path.go b/kernel/util/path.go index ff3e56026..ed89fed8d 100644 --- a/kernel/util/path.go +++ b/kernel/util/path.go @@ -19,7 +19,6 @@ package util import ( "bytes" "io/fs" - "net" "os" "path" "path/filepath" @@ -74,74 +73,7 @@ func GetLocalIPs() (ret []string) { } ret = []string{} - addrs, err := net.InterfaceAddrs() - if err != nil { - logging.LogWarnf("get interface addresses failed: %s", err) - return - } - - IPv4Nets := []*net.IPNet{} - IPv6Nets := []*net.IPNet{} - for _, addr := range addrs { - if networkIp, ok := addr.(*net.IPNet); ok && networkIp.IP.String() != "" { - if networkIp.IP.To4() != nil { - IPv4Nets = append(IPv4Nets, networkIp) - } else if networkIp.IP.To16() != nil { - IPv6Nets = append(IPv6Nets, networkIp) - } - } - } - - // loopback address - for _, net := range IPv4Nets { - if net.IP.IsLoopback() { - ret = append(ret, net.IP.String()) - } - } - // private address - for _, net := range IPv4Nets { - if net.IP.IsPrivate() { - ret = append(ret, net.IP.String()) - } - } - // IPv4 private address - for _, net := range IPv4Nets { - if net.IP.IsGlobalUnicast() { - ret = append(ret, net.IP.String()) - } - } - // link-local unicast address - for _, net := range IPv4Nets { - if net.IP.IsLinkLocalUnicast() { - ret = append(ret, net.IP.String()) - } - } - - // loopback address - for _, net := range IPv6Nets { - if net.IP.IsLoopback() { - ret = append(ret, "["+net.IP.String()+"]") - } - } - // private address - for _, net := range IPv6Nets { - if net.IP.IsPrivate() { - ret = append(ret, "["+net.IP.String()+"]") - } - } - // IPv6 private address - for _, net := range IPv6Nets { - if net.IP.IsGlobalUnicast() { - ret = append(ret, "["+net.IP.String()+"]") - } - } - // link-local unicast address - for _, net := range IPv6Nets { - if net.IP.IsLinkLocalUnicast() { - ret = append(ret, "["+net.IP.String()+"]") - } - } - + ret = append(ret, GetPrivateIPv4s()...) ret = append(ret, LocalHost) ret = gulu.Str.RemoveDuplicatedElem(ret) return