Open
Description
Below is a sample code:
package main
import (
"encoding/binary"
"fmt"
"net"
"strconv"
"strings"
"github.com/gosnmp/gosnmp"
)
const (
// SNMP 版本号
SNMPVersion = 1
// 固定的 OID 和值
OID = ".1.3.6.1.4.1.5105.100.1.9.4.15.0" // sysDescr
Value = "My SNMP Server"
)
// sendSNMPRequest 发送 SNMP 请求并接收响应
func sendSNMPRequest(target string, community string, oid string) ([]byte, error) {
// 创建 SNMP 客户端
gosnmp.Default.Target = target
gosnmp.Default.Port = 161
gosnmp.Default.Community = community
gosnmp.Default.Version = gosnmp.Version2c
// 创建 PDU
pdu := gosnmp.SnmpPDU{
Name: oid,
Type: gosnmp.OctetString,
Value: Value,
}
// 创建请求
request := &gosnmp.SnmpPacket{
Version: gosnmp.Version2c,
Community: community,
Error: gosnmp.NoError,
ErrorIndex: 0,
PDUType: gosnmp.GetRequest,
Variables: []gosnmp.SnmpPDU{pdu},
}
// 编码请求
req, err := request.MarshalMsg()
if err != nil {
return nil, fmt.Errorf("failed to marshal SNMP request: %v", err)
}
// 发送请求并接收响应
conn, err := net.Dial("udp", fmt.Sprintf("%s:%d", target, 161))
if err != nil {
return nil, fmt.Errorf("failed to dial UDP: %v", err)
}
defer conn.Close()
_, err = conn.Write(req)
if err != nil {
return nil, fmt.Errorf("failed to send SNMP request: %v", err)
}
buffer := make([]byte, 4096) // Increased buffer size
n, err := conn.Read(buffer)
if err != nil {
return nil, fmt.Errorf("failed to read SNMP response: %v", err)
}
return buffer[:n], nil
}
func main() {
pc, err := net.ListenPacket("udp", ":161")
if err != nil {
fmt.Println("Failed to listen on UDP port 161:", err)
return
}
defer pc.Close()
fmt.Println("SNMP server listening on UDP port 161...")
buffer := make([]byte, 4096) // Increased buffer size
for {
// 读取客户端请求
n, addr, err := pc.ReadFrom(buffer)
if err != nil {
fmt.Println("Failed to read UDP packet:", err)
continue
}
// 解析 SNMP 请求
req := buffer[:n]
fmt.Printf("Received SNMP request from %s: %X\n", addr, req)
// 生成 SNMP 响应
resp := generateSNMPResponse(req)
if resp == nil {
fmt.Println("Failed to generate SNMP response")
continue
}
// 发送响应
_, err = pc.WriteTo(resp, addr)
if err != nil {
fmt.Println("Failed to send SNMP response:", err)
continue
} else {
fmt.Printf("Sent SNMP response to %s: %X\n", addr, resp)
}
}
// 测试发送 SNMP 请求
//resp, err := sendSNMPRequest("192.168.12.109", "public", ".1.3.6.1.4.1.5105.100.1.9.4.15.0")
//if err != nil {
// fmt.Println("Failed to send SNMP request:", err)
//} else {
// fmt.Printf("Received SNMP response: %X\n", resp)
//}
}
// generateSNMPResponse 生成 SNMP 响应数据
func generateSNMPResponse(req []byte) []byte {
// 解析请求
// 这里仅处理简单的 GET 请求
if len(req) < 4 {
fmt.Println("Invalid SNMP request length")
return nil
}
// 提取社区字符串
communityLen := req[6]
community := string(req[7 : 7+communityLen]) // 提取社区字符串
fmt.Printf("Received SNMP request with community: %s\n", community)
// 提取请求 ID
requestId := binary.BigEndian.Uint32(req[7+communityLen+2+2 : 7+communityLen+2+2+4])
fmt.Printf("Received SNMP request with ID %d\n", requestId)
// 使用 gosnmp 库构建响应
gosnmp.Default.Target = "192.168.123.58"
gosnmp.Default.Port = 161
gosnmp.Default.Community = community
gosnmp.Default.Version = gosnmp.Version2c
// 创建 PDU
pdu := gosnmp.SnmpPDU{
Name: OID,
Type: gosnmp.OctetString,
Value: Value,
}
// 创建响应
response := &gosnmp.SnmpPacket{
Version: gosnmp.Version2c,
Community: community,
//ErrorStatus: gosnmp.NoError,
Error: gosnmp.NoError,
ErrorIndex: 0,
RequestID: requestId,
PDUType: gosnmp.GetResponse,
Variables: []gosnmp.SnmpPDU{pdu},
}
// 编码响应
resp, err := response.MarshalMsg()
if err != nil {
fmt.Println("Failed to marshal SNMP response:", err)
return nil
}
fmt.Printf("Generated SNMP response: %X\n", resp)
return resp
}
// encodeOID 编码 OID
func encodeOID(oid string) []byte {
// 使用 BER 编码来编码 OID
parts := splitOID(oid)
encoded := make([]byte, 0)
first := parts[0]*40 + parts[1]
encoded = append(encoded, byte(first))
for _, part := range parts[2:] {
encoded = append(encoded, encodeVarInt(part)...)
}
return encoded
}
// encodeVarInt 使用 BER 编码来编码一个整数
func encodeVarInt(value int) []byte {
if value < 128 {
return []byte{byte(value)}
}
encoded := make([]byte, 0)
for value > 0 {
encoded = append([]byte{byte(value%128 | 0x80)}, encoded...)
value /= 128
}
encoded[len(encoded)-1] &= 0x7F
return encoded
}
// encodeValue 编码值
func encodeValue(value string) []byte {
// 使用 BER 编码来编码值
encoded := make([]byte, 0)
encoded = append(encoded, byte(0x04)) // 字符串类型
encoded = append(encoded, byte(len(value))) // 字符串长度
encoded = append(encoded, []byte(value)...) // 字符串值
return encoded
}
// splitOID 分割 OID 字符串为整数数组
func splitOID(oid string) []int {
parts := make([]int, 0)
for _, part := range strings.Split(oid, ".") {
num, _ := strconv.Atoi(part)
parts = append(parts, num)
}
return parts
}
Metadata
Metadata
Assignees
Labels
No labels