GoSNMP是一个用Go编写的SNMP库

GoSNMP


GoSNMP 是一个完全用 Go 编写的 SNMP 客户端库。它提供 Get、GetNext、GetBulk、Walk、BulkWalk、Set 和 Traps 等功能。它支持 IPv4 和 IPv6,使用 SNMPv1SNMPv2cSNMPv3。构建版本已针对linux/amd64 和 linux/386 进行测试。

关于

gosnmpAndreas Louca 发起,后由 Sonia Hamilton 完全重写(2012-2020),现在所有权已转移至 gosnmp/gosnmp 社区。

概述

GoSNMP 具有以下 SNMP 函数:

  • Get(单个或多个 OID)
  • GetNext
  • GetBulk(仅限 SNMPv2c 和 SNMPv3)
  • Walk - 使用 GETNEXT 检索值的子树。
  • BulkWalk - 使用 GETBULK 检索值的子树(仅限 SNMPv2c 和 SNMPv3)。
  • BulkWalkAll - 与 BulkWalk 类似,但返回包含所有值的填充数组,而不是使用回调函数来流式传输结果。
  • Set - 支持整数和八进制字符串。
  • SendTrap - 发送 SNMP TRAP。
  • Listen - 充当接收 TRAP 的 NMS。

GoSNMP 具有以下 辅助 函数:

  • ToBigInt - 将返回值视为 *big.Int
  • Partition - 方便分割大块的 OID

gosnmp/gosnmpalouca/gosnmp 完全不同,您的代码需要在以下(以及其他)位置进行修改:

  • Get 函数的方法签名不同
  • NewGoSNMP 函数已被移除,请使用 Connect 代替(请参阅下文的用法)。Connect 使用 GoSNMP 结构体;gosnmp.Default 可供您在此基础上构建。
  • GoSNMP 不再依赖 alouca/gologger - 您可以使用符合 gosnmp.LoggerInterface 接口的记录器;否则调试将被禁用。
go 复制代码
type LoggerInterface interface {
    Print(v ...interface{})
    Printf(format string, v ...interface{})
}

要启用日志记录,您必须调用 gosnmp.NewLogger() 函数,并将指针传递给您的日志记录接口,例如使用标准 *log.Logger:

go 复制代码
gosnmp.Default.Logger = gosnmp.NewLogger(log.New(os.Stdout, "", 0))

或者

go 复制代码
g := &gosnmp.GoSNMP{
    ...
    Logger:    gosnmp.NewLogger(log.New(os.Stdout, "", 0)),
}

您可以使用 golang 构建标签“gosnmp_nodebug”从应用程序中完全删除日志代码,例如:

复制代码
go build -tags gosnmp_nodebug

即使在代码中指定了日志记录器接口,此操作也会完全禁用 gosnmp 库的日志记录功能。这会带来一些性能提升。

安装

shell 复制代码
go get github.com/gosnmp/gosnmp

文档

https://pkg.go.dev/github.com/gosnmp/gosnmp

使用方法

以下是 examples/example/main.go,演示了如何使用 GoSNMP:

go 复制代码
// Default is a pointer to a GoSNMP struct that contains sensible defaults
// eg port 161, community public, etc
g.Default.Target = "192.168.1.10"
err := g.Default.Connect()
if err != nil {
    log.Fatalf("Connect() err: %v", err)
}
defer g.Default.Conn.Close()

oids := []string{"1.3.6.1.2.1.1.4.0", "1.3.6.1.2.1.1.7.0"}
result, err2 := g.Default.Get(oids) // Get() accepts up to g.MAX_OIDS
if err2 != nil {
    log.Fatalf("Get() err: %v", err2)
}

for i, variable := range result.Variables {
    fmt.Printf("%d: oid: %s ", i, variable.Name)

    // the Value of each variable returned by Get() implements
    // interface{}. You could do a type switch...
    switch variable.Type {
    case g.OctetString:
        bytes := variable.Value.([]byte)
        fmt.Printf("string: %s\n", string(bytes))
    default:
        // ... or often you're just interested in numeric values.
        // ToBigInt() will return the Value as a BigInt, for plugging
        // into your calculations.
        fmt.Printf("number: %d\n", g.ToBigInt(variable.Value))
    }
}

运行此示例将产生以下输出(来自我的打印机):

shell 复制代码
% go run example.go
0: oid: 1.3.6.1.2.1.1.4.0 string: Administrator
1: oid: 1.3.6.1.2.1.1.7.0 number: 104
  • examples/example2.goexample.go 类似,但它使用了自定义的 &GoSNMP 而不是 g.Default
  • examples/walkexample.go 演示了如何使用 BulkWalk
  • examples/example3.go 演示了如何使用 SNMPv3
  • examples/trapserver.go 演示了如何编写 SNMP v2c 陷阱服务器

MIB 解析器

我目前没有编写 MIB 解析器的计划。其他人建议
https://github.com/sleepinggenius2/gosmi

贡献

欢迎贡献,尤其是包含数据包捕获功能的贡献(见下文)。

如果您之前从未为 Go 项目贡献过代码,这里有一个示例工作流程。

  1. 在 GitHub 网页上 fork 此仓库
  2. go get github.com/gosnmp/gosnmp
  3. cd $GOPATH/src/github.com/gosnmp/gosnmp
  4. git remote rename origin upstream
  5. git remote add origin git@github.com:<your-github-username>/gosnmp.git
  6. git checkout -b development
  7. git push -u origin development(设置推送目标,检查是否正常工作)

数据包捕获

按以下方式创建数据包捕获:

预期输出,通过 snmp 命令获取。例如:

shell 复制代码
% snmpget -On -v2c -c public 203.50.251.17 1.3.6.1.2.1.1.7.0 \
  1.3.6.1.2.1.2.2.1.2.6 1.3.6.1.2.1.2.2.1.5.3
.1.3.6.1.2.1.1.7.0 = INTEGER: 78
.1.3.6.1.2.1.2.2.1.2.6 = STRING: GigabitEthernet0
.1.3.6.1.2.1.2.2.1.5.3 = Gauge32: 4294967295

运行 snmpget 时获取的数据包捕获。例如:

shell 复制代码
sudo tcpdump -s 0 -i eth0 -w foo.pcap host 203.50.251.17 and port 161

bugs

Rane 的文档 SNMP:简单?网络管理协议 在学习 SNMP 协议时非常有用。

请在 Github 上创建一个 issue,其中包含数据包捕获(上传到 Google Drive、Dropbox 或类似平台),其中包含缺失 BER 类型的示例,或您发现的任何其他错误。如果可能,请包含 2 到 3 个缺失/错误的 BER 类型的示例。

已实现以下 BER 类型:

  • 0x00 UnknownType
  • 0x01 Boolean
  • 0x02 Integer
  • 0x03 BitString
  • 0x04 OctetString
  • 0x05 Null
  • 0x06 ObjectIdentifier
  • 0x07 ObjectDescription
  • 0x40 IPAddress (IPv4 & IPv6)
  • 0x41 Counter32
  • 0x42 Gauge32
  • 0x43 TimeTicks
  • 0x44 Opaque (Float & Double)
  • 0x45 NsapAddress
  • 0x46 Counter64
  • 0x47 Uinteger32
  • 0x78 OpaqueFloat
  • 0x79 OpaqueDouble
  • 0x80 NoSuchObject
  • 0x81 NoSuchInstance
  • 0x82 EndOfMibView

运行测试

Docker 中的本地测试

shell 复制代码
docker build -t gosnmp/gosnmp:latest .
docker run -it gosnmp/gosnmp:latest

或者

shell 复制代码
export GOSNMP_TARGET=1.2.3.4
export GOSNMP_PORT=161
export GOSNMP_TARGET_IPV4=1.2.3.4
export GOSNMP_PORT_IPV4=161
export GOSNMP_TARGET_IPV6='0:0:0:0:0:ffff:102:304'
export GOSNMP_PORT_IPV6=161
go test -v -tags all        # for example
go test -v -tags helper     # for example

测试分组如下:

  • 单元测试(验证数据打包和编组):
    • marshal_test.go
    • misc_test.go
  • 公共 API 一致性测试:
    • gosnmp_api_test.go
  • 端到端集成测试:
    • generic_e2e_test.go

通用端到端集成测试 generic_e2e_test.go 应该可以在任何兼容 SNMP MIB-2 的主机(例如路由器、NAS 盒、打印机)上运行。

模拟测试使用以下方法生成:

mockgen -source=interface.go -destination=mocks/gosnmp_mock.go -package=mocks

但是,由于它们会破坏 linting 功能,因此目前已被移除。

要分析 CPU 使用情况:

shell 复制代码
go test -cpuprofile cpu.out
go test -c
go tool pprof gosnmp.test cpu.out

要分析内存使用情况:

shell 复制代码
go test -memprofile mem.out
go test -c
go tool pprof gosnmp.test mem.out

检查测试覆盖率:

shell 复制代码
go get github.com/axw/gocov/gocov
go get github.com/matm/gocov-html
gocov test github.com/gosnmp/gosnmp | gocov-html > gosnmp.html && firefox gosnmp.html &

测量密码哈希缓存性能的方法:

在基准测试期间,可以使用 golang 构建标签“gosnmp_nopwdcache”禁用密码哈希缓存,因此:

复制代码
go build -tags gosnmp_nopwdcache -bench=Benchmark.*Hash

将在不使用密码哈希缓存的情况下对代码进行基准测试。删除该标签将在启用缓存的情况下运行基准测试(这是软件包的默认行为)。

许可证

部分代码取自 Golang 项目(特别是一些用于解组 BER 响应的函数),这些函数的条款和条件与 Go 语言相同。其余代码遵循 BSD 许可证。

更多详情请参阅许可证文件。

其余代码版权所有 2012 GoSNMP 作者 - 作者列表请参阅AUTHORS.md

关于项目

GoSNMP 是一个完全用 Go 编写的 SNMP 客户端库。它提供 Get、GetNext、GetBulk、Walk、BulkWalk、Set 和 Traps 等功能。它支持 IPv4 和 IPv6,使用 SNMPv1、SNMPv2c 或 SNMPv3。其构建版本已针对 linux/amd64 和 linux/386 进行测试。
BSD-3-Clause
Golang
1,226
373
46
2012-08-27
2025-11-02

增长趋势 - stars