Initial commit: 网络拓扑发现系统
- 支持Cisco、华为、H3C、ASA、Linux、Windows设备 - SSH远程采集设备信息 - 自动发现网络拓扑(LLDP/CDP) - Web可视化界面 - 支持旧版SSH加密算法兼容
这个提交包含在:
@@ -0,0 +1,112 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"network-topology-discovery/pkg/models"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ASAParser ASA防火墙解析器
|
||||
type ASAParser struct {
|
||||
BaseParser
|
||||
}
|
||||
|
||||
// GetCommands 获取ASA设备命令列表
|
||||
func (p *ASAParser) GetCommands() []string {
|
||||
return []string{
|
||||
"show version",
|
||||
"show interface",
|
||||
"show ip",
|
||||
"show inventory",
|
||||
}
|
||||
}
|
||||
|
||||
// Parse 解析ASA设备输出
|
||||
func (p *ASAParser) Parse(device *models.Device, outputs []string) error {
|
||||
if len(outputs) < 4 {
|
||||
return fmt.Errorf("insufficient command outputs")
|
||||
}
|
||||
|
||||
p.parseVersion(device, outputs[0])
|
||||
device.Interfaces = p.parseInterfaces(outputs[1])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *ASAParser) parseVersion(device *models.Device, output string) {
|
||||
hostnameRegex := regexp.MustCompile(`^(\S+)\s*>`)
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
if matches := hostnameRegex.FindStringSubmatch(line); len(matches) > 1 {
|
||||
device.Hostname = matches[1]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Contains(output, "ASA Version") {
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "ASA Version") {
|
||||
device.OSVersion = strings.TrimSpace(line)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uptimeRegex := regexp.MustCompile(`up\s+\d+\s+hours?\s+\d+\s+mins?`)
|
||||
if matches := uptimeRegex.FindString(output); matches != "" {
|
||||
device.Uptime = matches
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ASAParser) parseInterfaces(output string) []models.Interface {
|
||||
var interfaces []models.Interface
|
||||
scanner := bufio.NewScanner(strings.NewReader(output))
|
||||
var currentInterface *models.Interface
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
if nameRegex := regexp.MustCompile(`^Interface\s+(\S+)\s+"(\S+)"`); nameRegex.MatchString(line) {
|
||||
if currentInterface != nil {
|
||||
interfaces = append(interfaces, *currentInterface)
|
||||
}
|
||||
matches := nameRegex.FindStringSubmatch(line)
|
||||
currentInterface = &models.Interface{
|
||||
Name: matches[1],
|
||||
Description: matches[2],
|
||||
}
|
||||
}
|
||||
|
||||
if currentInterface != nil {
|
||||
if statusRegex := regexp.MustCompile(`\S+\s+is\s+(up|down)`); statusRegex.MatchString(line) {
|
||||
matches := statusRegex.FindStringSubmatch(line)
|
||||
currentInterface.Status = matches[1]
|
||||
}
|
||||
|
||||
if macRegex := regexp.MustCompile(`Hardware is\s+\S+,\s+address is\s+(\S+)`); macRegex.MatchString(line) {
|
||||
matches := macRegex.FindStringSubmatch(line)
|
||||
currentInterface.MAC = matches[1]
|
||||
}
|
||||
|
||||
if ipRegex := regexp.MustCompile(`IP address\s+(\d+\.\d+\.\d+\.\d+),\s+subnet mask\s+(\d+\.\d+\.\d+\.\d+)`); ipRegex.MatchString(line) {
|
||||
matches := ipRegex.FindStringSubmatch(line)
|
||||
currentInterface.IP = matches[1]
|
||||
currentInterface.Mask = matches[2]
|
||||
}
|
||||
|
||||
if speedRegex := regexp.MustCompile(`(\d+)\s+(Mbps|Gbps)`); speedRegex.MatchString(line) {
|
||||
matches := speedRegex.FindStringSubmatch(line)
|
||||
currentInterface.Speed = matches[1] + " " + matches[2]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if currentInterface != nil {
|
||||
interfaces = append(interfaces, *currentInterface)
|
||||
}
|
||||
|
||||
return interfaces
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户