mirror of
https://github.com/oneclickvirt/basics.git
synced 2025-10-08 01:50:28 +08:00
feat: 添加活跃邻居BGP检测
This commit is contained in:
3
go.mod
3
go.mod
@@ -7,8 +7,9 @@ require (
|
||||
github.com/jaypipes/ghw v0.12.0
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/libp2p/go-nat v0.2.0
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||
github.com/oneclickvirt/defaultset v0.0.2-20240624082446
|
||||
github.com/oneclickvirt/gostun v0.0.3-20240702054621
|
||||
github.com/oneclickvirt/gostun v0.0.3-20250329105202
|
||||
github.com/shirou/gopsutil/v4 v4.24.5
|
||||
github.com/yusufpapurcu/wmi v1.2.4
|
||||
golang.org/x/sys v0.21.0
|
||||
|
6
go.sum
6
go.sum
@@ -62,10 +62,12 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OH
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/oneclickvirt/defaultset v0.0.2-20240624082446 h1:5Pg3mK/u/vQvSz7anu0nxzrNdELi/AcDAU1mMsmPzyc=
|
||||
github.com/oneclickvirt/defaultset v0.0.2-20240624082446/go.mod h1:e9Jt4tf2sbemCtc84/XgKcHy9EZ2jkc5x2sW1NiJS+E=
|
||||
github.com/oneclickvirt/gostun v0.0.3-20240702054621 h1:IE89eEYV9TJbF94SakQDAxTLIaqX+Tb6ZhJ/CCIP+90=
|
||||
github.com/oneclickvirt/gostun v0.0.3-20240702054621/go.mod h1:f7DPEXAxbmwXSW33dbxtb0/KzqvOBWhTs2Or5xBerQA=
|
||||
github.com/oneclickvirt/gostun v0.0.3-20250329105202 h1:aJ6E91Lp94lq8iWRcCaxpXTjqOOaWvufr5oras6cFtM=
|
||||
github.com/oneclickvirt/gostun v0.0.3-20250329105202/go.mod h1:f7DPEXAxbmwXSW33dbxtb0/KzqvOBWhTs2Or5xBerQA=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||
|
91
network/baseinfo/bgp.go
Normal file
91
network/baseinfo/bgp.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package baseinfo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"image/color"
|
||||
"image/png"
|
||||
"io"
|
||||
"math"
|
||||
"net"
|
||||
|
||||
"github.com/imroc/req/v3"
|
||||
"github.com/nfnt/resize"
|
||||
)
|
||||
|
||||
// GetCIDRPrefix 获取 IP 地址的实际 CIDR 前缀,获取失败时返回默认值 24
|
||||
func GetCIDRPrefix(ip string) int {
|
||||
interfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return 24
|
||||
}
|
||||
for _, iface := range interfaces {
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
if ipNet, ok := addr.(*net.IPNet); ok && ipNet.IP.To4() != nil {
|
||||
if ipNet.IP.String() == ip {
|
||||
ones, _ := ipNet.Mask.Size()
|
||||
return ones
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 24
|
||||
}
|
||||
|
||||
func GetNeighborCount(ip string, prefixNum int) (int, int, error) {
|
||||
client := req.C()
|
||||
client.ImpersonateChrome()
|
||||
cidrBase := fmt.Sprintf("%s/%d", ip, prefixNum)
|
||||
neighborTotal := int(math.Pow(2, float64(32-prefixNum)))
|
||||
neighborActive, err := countActiveIPs(client, fmt.Sprintf("https://bgp.tools/pfximg/%s", cidrBase))
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
// ipTotal := int(math.Pow(2, float64(32-prefixNum)))
|
||||
// ipActive, err := countActiveIPs(client, fmt.Sprintf("https://bgp.tools/pfximg/%s", ip))
|
||||
// if err != nil {
|
||||
// return 0, 0, err
|
||||
// }
|
||||
// fmt.Printf("Active IPs: %d/%d\n", ipActive, ipTotal)
|
||||
return neighborActive, neighborTotal, nil
|
||||
}
|
||||
|
||||
func countActiveIPs(client *req.Client, url string) (int, error) {
|
||||
resp, err := client.R().Get(url)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if !resp.IsSuccessState() {
|
||||
return 0, fmt.Errorf("HTTP request failed: %s", resp.Status)
|
||||
}
|
||||
// 读取 PNG 数据到内存
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// 确保数据正确
|
||||
if len(data) < 8 || !bytes.HasPrefix(data, []byte("\x89PNG\r\n\x1a\n")) {
|
||||
return 0, fmt.Errorf("invalid PNG format")
|
||||
}
|
||||
// 解码 PNG
|
||||
img, err := png.Decode(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to decode PNG: %w", err)
|
||||
}
|
||||
// 调整图像大小
|
||||
resizedImg := resize.Resize(0, 100, img, resize.Lanczos3)
|
||||
count := 0
|
||||
for y := 0; y < resizedImg.Bounds().Dy(); y++ {
|
||||
for x := 0; x < resizedImg.Bounds().Dx(); x++ {
|
||||
c := color.RGBAModel.Convert(resizedImg.At(x, y)).(color.RGBA)
|
||||
if c.R == 0 && c.G == 3 && c.B == 255 {
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
return count, nil
|
||||
}
|
17
network/baseinfo/bgp_test.go
Normal file
17
network/baseinfo/bgp_test.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package baseinfo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNeighborCount(t *testing.T) {
|
||||
ip := "54.92.128.0" // 示例 IP
|
||||
prefixNum := 24 // 示例前缀
|
||||
neighborActive, neighborTotal, err := GetNeighborCount(ip, prefixNum)
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Neighbor Active: %d/%d\n", neighborActive, neighborTotal)
|
||||
}
|
@@ -2,7 +2,6 @@ package network
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/oneclickvirt/basics/model"
|
||||
"github.com/oneclickvirt/basics/network/baseinfo"
|
||||
@@ -10,35 +9,43 @@ import (
|
||||
)
|
||||
|
||||
// sortAndTranslateText 对原始文本进行排序和翻译
|
||||
func sortAndTranslateText(orginList []string, language string, fields []string) string {
|
||||
var result string
|
||||
for _, key := range fields {
|
||||
var displayKey string
|
||||
if language == "zh" {
|
||||
displayKey = model.TranslationMap[key]
|
||||
if displayKey == "" {
|
||||
displayKey = key
|
||||
}
|
||||
} else {
|
||||
displayKey = key
|
||||
}
|
||||
for _, line := range orginList {
|
||||
if strings.Contains(line, key) {
|
||||
if displayKey == key {
|
||||
result = result + line + "\n"
|
||||
} else {
|
||||
result = result + strings.ReplaceAll(line, key, displayKey) + "\n"
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
// func sortAndTranslateText(orginList []string, language string, fields []string) string {
|
||||
// var result string
|
||||
// for _, key := range fields {
|
||||
// var displayKey string
|
||||
// if language == "zh" {
|
||||
// displayKey = model.TranslationMap[key]
|
||||
// if displayKey == "" {
|
||||
// displayKey = key
|
||||
// }
|
||||
// } else {
|
||||
// displayKey = key
|
||||
// }
|
||||
// for _, line := range orginList {
|
||||
// if strings.Contains(line, key) {
|
||||
// if displayKey == key {
|
||||
// result = result + line + "\n"
|
||||
// } else {
|
||||
// result = result + strings.ReplaceAll(line, key, displayKey) + "\n"
|
||||
// }
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return result
|
||||
// }
|
||||
|
||||
// processPrintIPInfo 处理IP信息
|
||||
func processPrintIPInfo(headASNString string, headLocationString string, ipResult *model.IpInfo) string {
|
||||
func processPrintIPInfo(ipVersion string, ipResult *model.IpInfo) string {
|
||||
var info string
|
||||
var headASNString, headLocationString string
|
||||
if ipVersion == "ipv4" {
|
||||
headASNString = " IPV4 ASN : "
|
||||
headLocationString = " IPV4 Location : "
|
||||
} else if ipVersion == "ipv6" {
|
||||
headASNString = " IPV6 ASN : "
|
||||
headLocationString = " IPV6 Location : "
|
||||
}
|
||||
// 处理ASN信息
|
||||
if ipResult.ASN != "" || ipResult.Org != "" {
|
||||
info += headASNString
|
||||
@@ -64,6 +71,14 @@ func processPrintIPInfo(headASNString string, headLocationString string, ipResul
|
||||
}
|
||||
info += "\n"
|
||||
}
|
||||
// 仅处理 IPv4 的邻居信息
|
||||
if ipVersion == "ipv4" && ipResult.Ip != "" {
|
||||
prefixNum := baseinfo.GetCIDRPrefix(ipResult.Ip)
|
||||
neighborActive, neighborTotal, err := baseinfo.GetNeighborCount(ipResult.Ip, prefixNum)
|
||||
if err == nil {
|
||||
info += fmt.Sprintf(" IPV4 Active IPs : %d/%d (CIDR /%d)\n", neighborActive, neighborTotal, prefixNum)
|
||||
}
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
@@ -82,10 +97,10 @@ func NetworkCheck(checkType string, enableSecurityCheck bool, language string) (
|
||||
Logger.Info(err.Error())
|
||||
}
|
||||
if ipInfoV4Result != nil {
|
||||
ipInfo += processPrintIPInfo(" IPV4 ASN : ", " IPV4 Location : ", ipInfoV4Result)
|
||||
ipInfo += processPrintIPInfo("ipv4", ipInfoV4Result)
|
||||
}
|
||||
if ipInfoV6Result != nil {
|
||||
ipInfo += processPrintIPInfo(" IPV6 ASN : ", " IPV6 Location : ", ipInfoV6Result)
|
||||
ipInfo += processPrintIPInfo("ipv6", ipInfoV6Result)
|
||||
}
|
||||
return ipInfo, "", nil
|
||||
} else if checkType == "ipv4" {
|
||||
@@ -94,7 +109,7 @@ func NetworkCheck(checkType string, enableSecurityCheck bool, language string) (
|
||||
Logger.Info(err.Error())
|
||||
}
|
||||
if ipInfoV4Result != nil {
|
||||
ipInfo += processPrintIPInfo(" IPV4 ASN : ", " IPV4 Location : ", ipInfoV4Result)
|
||||
ipInfo += processPrintIPInfo("ipv4", ipInfoV4Result)
|
||||
}
|
||||
return ipInfo, "", nil
|
||||
} else if checkType == "ipv6" {
|
||||
@@ -103,7 +118,7 @@ func NetworkCheck(checkType string, enableSecurityCheck bool, language string) (
|
||||
Logger.Info(err.Error())
|
||||
}
|
||||
if ipInfoV6Result != nil {
|
||||
ipInfo += processPrintIPInfo(" IPV6 ASN : ", " IPV6 Location : ", ipInfoV6Result)
|
||||
ipInfo += processPrintIPInfo("ipv6", ipInfoV6Result)
|
||||
}
|
||||
return ipInfo, "", nil
|
||||
}
|
||||
|
@@ -115,6 +115,7 @@ func CheckSystemInfo(language string) string {
|
||||
if ret.TcpAccelerationMethod != "" {
|
||||
res += " Tcp Accelerate : " + ret.TcpAccelerationMethod + "\n"
|
||||
}
|
||||
|
||||
} else if language == "zh" {
|
||||
res += " CPU 型号 : " + ret.CpuModel + "\n"
|
||||
res += " CPU 数量 : " + ret.CpuCores + "\n"
|
||||
|
Reference in New Issue
Block a user