Git Product home page Git Product logo

gosnmpserver's Introduction

GoSNMPServer

Build Status GoDoc codecov

GoSNMPServer is an SNMP server library fully written in Go. It provides Server Get, GetNext, GetBulk, Walk, BulkWalk, Set and Traps. It supports IPv4 and IPv6, using SNMPv2c or SNMPv3. Builds are tested against linux/amd64 and linux/386.

TL;DR

Build your own SNMP Server, try this:

go install github.com/slayercat/GoSNMPServer/cmd/gosnmpserver
$(go env GOPATH)/bin/gosnmpserver run-server
snmpwalk -v 3 -l authPriv  -n public -u testuser   -a md5 -A testauth -x des -X testpriv 127.0.0.1:1161 1

Quick Start

import "github.com/gosnmp/gosnmp"
import "github.com/slayercat/GoSNMPServer"
import "github.com/slayercat/GoSNMPServer/mibImps"
master := GoSNMPServer.MasterAgent{
    Logger: GoSNMPServer.NewDefaultLogger(),
    SecurityConfig: GoSNMPServer.SecurityConfig{
        AuthoritativeEngineBoots: 1,
        Users: []gosnmp.UsmSecurityParameters{
            {
                UserName:                 c.String("v3Username"),
                AuthenticationProtocol:   gosnmp.MD5,
                PrivacyProtocol:          gosnmp.DES,
                AuthenticationPassphrase: c.String("v3AuthenticationPassphrase"),
                PrivacyPassphrase:        c.String("v3PrivacyPassphrase"),
            },
        },
    },
    SubAgents: []*GoSNMPServer.SubAgent{
        {
            CommunityIDs: []string{c.String("community")},
            OIDs:         mibImps.All(),
        },
    },
}
server := GoSNMPServer.NewSNMPServer(master)
err := server.ListenUDP("udp", "127.0.0.1:1161")
if err != nil {
    logger.Errorf("Error in listen: %+v", err)
}
server.ServeForever()

Serve your own oids

This library provides some common oid for use. See mibImps for code, See GoDoc here.

Append GoSNMPServer.PDUValueControlItem to your SubAgent OIDS:

{
    OID:      fmt.Sprintf("1.3.6.1.2.1.2.2.1.1.%d", ifIndex),
    Type:     gosnmp.Integer,
    OnGet:    func() (value interface{}, err error) { return GoSNMPServer.Asn1IntegerWrap(ifIndex), nil },
    Document: "ifIndex",
},

Supports Types: See RFC-2578 FOR SMI

  • Integer
  • OctetString
  • ObjectIdentifier
  • IPAddress
  • Counter32
  • Gauge32
  • TimeTicks
  • Counter64
  • Uinteger32
  • OpaqueFloat
  • OpaqueDouble

Could use wrap function for detect type error. See GoSNMPServer.Asn1IntegerWrap / GoSNMPServer.Asn1IntegerUnwrap and so on.

Thanks

This library is based on soniah/gosnmp for encoder / decoders.

gosnmpserver's People

Contributors

consoletvs avatar shiwangyi avatar slayercat avatar thorsager avatar upsampled avatar zanexo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

gosnmpserver's Issues

SNMPWalk1 test failure in #21

Summary

Using this issue to track `TestServerTestsSuite/TestGetSetOids/SNMPWalk1 test failure in #21

The issue seems to be with the OpaqueFloat type. It is first used in OID 1.2.3.11. If I make OID 1.2.3.8 an OpaqueFloat the error occurs there instead

Logs from Client

$ snmpwalk -v2c -c public localhost:6161 1
iso.2.3.1 = INTEGER: 0
iso.2.3.2 = NULL
iso.2.3.3 = ""
iso.2.3.4 = OID: iso.2.3.4
iso.2.3.6 = Counter32: 0
iso.2.3.7 = Gauge32: 0
iso.2.3.8 = Timeticks: (0) 0:00:00.00
iso.2.3.9 = Counter64: 0
iso.2.3.10 = 0
Timeout: No Response from localhost:6161

Logs from server

INFO[0004] udp request from 127.0.0.1:52636. size=38    
DEBU[0004] serveGetNextRequest of .1.2.3.9              
DEBU[0004] t.getForPDUValueControl. query_for_oid=.1.2.3.9 item=&{1.2.3.9 Counter64 false <nil> 0x569520 0x569500 <nil> TestTypeCounter64} id=7 
DEBU[0004] i.Variables[id: length]. id=8 length =1. len(t.OIDs)=12 
DEBU[0004] getnext: append oid=1.2.3.10. result={0 1.2.3.10 Uinteger32} err=NoError 
INFO[0004] udp request from 127.0.0.1:52636. size=38    
DEBU[0004] serveGetNextRequest of .1.2.3.10             
DEBU[0004] t.getForPDUValueControl. query_for_oid=.1.2.3.10 item=&{1.2.3.10 Uinteger32 false <nil> 0x5694a0 0x569480 <nil> TestTypeUinteger32} id=8 
DEBU[0004] i.Variables[id: length]. id=9 length =1. len(t.OIDs)=12 
DEBU[0004] getnext: append oid=1.2.3.11. result={0 1.2.3.11 OpaqueFloat} err=NoError 
INFO[0005] udp request from 127.0.0.1:52636. size=38    
DEBU[0005] serveGetNextRequest of .1.2.3.10             
DEBU[0005] t.getForPDUValueControl. query_for_oid=.1.2.3.10 item=&{1.2.3.10 Uinteger32 false <nil> 0x5694a0 0x569480 <nil> TestTypeUinteger32} id=8 
DEBU[0005] i.Variables[id: length]. id=9 length =1. len(t.OIDs)=12 
DEBU[0005] getnext: append oid=1.2.3.11. result={0 1.2.3.11 OpaqueFloat} err=NoError 
INFO[0006] udp request from 127.0.0.1:52636. size=38    
DEBU[0006] serveGetNextRequest of .1.2.3.10             
DEBU[0006] t.getForPDUValueControl. query_for_oid=.1.2.3.10 item=&{1.2.3.10 Uinteger32 false <nil> 0x5694a0 0x569480 <nil> TestTypeUinteger32} id=8 
DEBU[0006] i.Variables[id: length]. id=9 length =1. len(t.OIDs)=12 
DEBU[0006] getnext: append oid=1.2.3.11. result={0 1.2.3.11 OpaqueFloat} err=NoError 
INFO[0007] udp request from 127.0.0.1:52636. size=38    
DEBU[0007] serveGetNextRequest of .1.2.3.10             
DEBU[0007] t.getForPDUValueControl. query_for_oid=.1.2.3.10 item=&{1.2.3.10 Uinteger32 false <nil> 0x5694a0 0x569480 <nil> TestTypeUinteger32} id=8 
DEBU[0007] i.Variables[id: length]. id=9 length =1. len(t.OIDs)=12 
DEBU[0007] getnext: append oid=1.2.3.11. result={0 1.2.3.11 OpaqueFloat} err=NoError 
INFO[0008] udp request from 127.0.0.1:52636. size=38    
DEBU[0008] serveGetNextRequest of .1.2.3.10             
DEBU[0008] t.getForPDUValueControl. query_for_oid=.1.2.3.10 item=&{1.2.3.10 Uinteger32 false <nil> 0x5694a0 0x569480 <nil> TestTypeUinteger32} id=8 
DEBU[0008] i.Variables[id: length]. id=9 length =1. len(t.OIDs)=12 
DEBU[0008] getnext: append oid=1.2.3.11. result={0 1.2.3.11 OpaqueFloat} err=NoError 
INFO[0009] udp request from 127.0.0.1:52636. size=38    
DEBU[0009] serveGetNextRequest of .1.2.3.10             
DEBU[0009] t.getForPDUValueControl. query_for_oid=.1.2.3.10 item=&{1.2.3.10 Uinteger32 false <nil> 0x5694a0 0x569480 <nil> TestTypeUinteger32} id=8 
DEBU[0009] i.Variables[id: length]. id=9 length =1. len(t.OIDs)=12 
DEBU[0009] getnext: append oid=1.2.3.11. result={0 1.2.3.11 OpaqueFloat} err=NoError 

Dynamic OIDs

Once the GoSNMPServer.NewSNMPServer, as far as I know, there is no way to update or change the OIDs list. In some cases, new entries should be added or removed.

Could be possible to add such capability? Can I help adding it?

go mod tidy

Hi,
When i do a go mod tidy on my project using GoSNMPServer I got this error

go: found github.com/soniah/gosnmp in github.com/soniah/gosnmp v1.34.0
go: ./services imports
        github.com/slayercat/gosnmp tested by
        github.com/slayercat/gosnmp.test imports
        github.com/soniah/gosnmp: github.com/soniah/[email protected]: parsing go.mod:
        module declares its path as: github.com/gosnmp/gosnmp
                but was required as: github.com/soniah/gosnmp

I think it comes form the fact that github.com/soniah/gosnmp is now github.com/gosnmp/gosnmp but I don't know how to fix it

Thanks

echo-trap-server?

Sorry, I don't know the snmp protocol very well. There are many parameters to start a trapserver, and I don't understand their meaning. There is no detailed explanation. Can you give an example?
How to quickly start a echo-trapserver to receive all trap messages and print them?
image

[v0.5.2] marshal: crypto/aes: invalid key size 0

I don't know what you did by reverting that commit, but the version v0.5.2 breaks auth with the following issue:

marshal: crypto/aes: invalid key size 0

Tested using gosnmp client to consume a gosnmpserver oid.

version v0.5.1 works fine

SNMPv3 AES192 AES256 not work

I am using SnmpB(windows exe application) and Pysnmp with Python3, I created an usm as following:

master := GoSNMPServer.MasterAgent{
	Logger: GoSNMPServer.NewDefaultLogger(),
	SecurityConfig: GoSNMPServer.SecurityConfig{
		AuthoritativeEngineBoots: 0,
		Users: []gosnmp.UsmSecurityParameters{
			{
				UserName:                 "admin", //c.String("v3Username"),
				AuthenticationProtocol:   gosnmp.MD5,
				PrivacyProtocol:          gosnmp.AES,
				AuthenticationPassphrase: "12345678", //c.String("v3AuthenticationPassphrase"),
				PrivacyPassphrase:        "12345678", //c.String("v3PrivacyPassphrase"),
			},
		},
	},
	SubAgents: []*GoSNMPServer.SubAgent{
		{
			//CommunityIDs: []string{c.String("community")},
			CommunityIDs: []string{"public"},
			OIDs:         mibImps.All(),
		},
	},
}

the snmp agent work well, while if change priv protocol to AES192 or AES256, SnmpB and Pysnmp can not get correct data, wireshark shows malf package. Tried AES192C and AES256C the result is the same.

BUG:oidToByteString has

Why implement oidToByteString like the following, each time a new request is received, such as Get, Get-Next, it will perform multiple oidToByteString operations, there is additional cpu overhead, and this algorithm still has BUG :

func oidToByteString(oid string) string {
	xi := strings.Split(oid, ".")
	out := []rune{}
	for id, each := range xi {
		if each == "" {
			if id == 0 {
				continue
			} else {
				panic(errors.Errorf("oidToByteString not valid id. value=%v", oid))
			}

		}
		i, err := strconv.ParseInt(each, 10, 32)
		if err != nil {
			panic(err)
		}
		out = append(out, rune(i))
	}
	return string(out)
}

Input oids as:

1.3.6.1.4.1.11475.0.2041601.1.632.0
1.3.6.1.4.1.11475.0.2041602.1.632.0

Error Result as:


> Call API as: 
getForPDUValueControl("1.3.6.1.4.1.11475.0.2041601.1.632.0") 

> Output as:
1.3.6.1.4.1.11475.0.2041602.1.632.0 , 1

Why not return the oid string directly, use the oid string to sort and search the slice,like:

func oidToByteString(oid string) string {
    return oid
}

Will doing this cause any problems? If it is to verify the legitimacy of the OID, is it more appropriate to only perform the verification in SyncConfig, not when subsequent new requests flow in?

Disabling privacy triggers authentication errors

Hey!

Applying this patch:

diff --git a/cmd/gosnmpserver/main.go b/cmd/gosnmpserver/main.go
index 1a6c7f4c8faf..3b27dfff29e5 100644
--- a/cmd/gosnmpserver/main.go
+++ b/cmd/gosnmpserver/main.go
@@ -60,9 +62,8 @@ func runServer(c *cli.Context) error {
                                {
                                        UserName:                 c.String("v3Username"),
                                        AuthenticationProtocol:   gosnmp.MD5,
-                                       PrivacyProtocol:          gosnmp.DES,
+                                       PrivacyProtocol:          gosnmp.NoPriv,
                                        AuthenticationPassphrase: c.String("v3AuthenticationPassphrase"),
-                                       PrivacyPassphrase:        c.String("v3PrivacyPassphrase"),
                                },
                        },
                },

We get this:

$ snmpwalk -v 3 -l authNoPriv  -n public -u testuser   -a md5 -A testauth 127.0.0.1:1161 1
Authentication failed for testuser
iso.3.6.1.2.1.1.3.0 = Timeticks: (176926) 0:29:29.26
Authentication failed for testuser
iso.3.6.1.2.1.2.2.1.1.0 = INTEGER: 2

Data race with ServerForever and ServeNextRequest and Shutdown

I have a problem with a data race in the GoSNMPServer during shutdown. This happens pretty reproducible in my test code.
Ideally the Shutdown method would interrupt the ServeNextRequest method before closing the udp connection.
Alternatively adding a context to ServeForever and/or ServeNextRequest to stop them via context close would enable me to work around this issue.

Relevant data race output:

==================
WARNING: DATA RACE
Read at 0x00c000012258 by goroutine 13:
  github.com/slayercat/GoSNMPServer.(*UDPListener).NextSnmp()
      /path/github.com/slayercat/[email protected]/interfaceListener.go:47 +0x6d
  github.com/slayercat/GoSNMPServer.(*SNMPServer).ServeNextRequest()
      /path/github.com/slayercat/[email protected]/snmpserver.go:81 +0xc1
  github.com/slayercat/GoSNMPServer.(*SNMPServer).ServeForever()
      /path/github.com/slayercat/[email protected]/snmpserver.go:54 +0x118
  [REDACTED]

Previous write at 0x00c000012258 by goroutine 9:
  github.com/slayercat/GoSNMPServer.(*UDPListener).Shutdown()
      /path/github.com/slayercat/[email protected]/interfaceListener.go:61 +0x51
  github.com/slayercat/GoSNMPServer.(*SNMPServer).Shutdown()
      /path/github.com/slayercat/[email protected]/snmpserver.go:44 +0x96
  [REDACTED]

Getnext request multiple oids: incorrect behavior

From wireshark analyzer:
get-next-request 1.3.6.1.2.1.33.1.3.3.1.1 1.3.6.1.2.1.33.1.3.3.1.2 1.3.6.1.2.1.33.1.3.3.1.3 1.3.6.1.2.1.33.1.3.3.1.4 1.3.6.1.2.1.33.1.3.3.1.5
get-response 1.3.6.1.2.1.33.1.3.3.1.5.0 1.3.6.1.2.1.33.1.3.3.1.5.1 1.3.6.1.2.1.33.1.3.3.1.5.2 1.3.6.1.2.1.33.1.4.1.0 1.3.6.1.2.1.33.1.4.2.05

After get-next-request with multiple oids: gosnmpserver get LAST oid (1.3.6.1.2.1.33.1.3.3.1.4) from the end of oid list. Then response is .3.6.1.2.1.33.1.3.3.1.5.0 (next after 1.3.6.1.2.1.33.1.3.3.1.4), not after 1.3.6.1.2.1.33.1.3.3.1.1 (1.3.6.1.2.1.33.1.3.3.1.1.1...5).
It's happened after table request. NetSnmp utilities now use get-bulk-request in gettable cli , and all is ok (no error). But some software is continue to use old style (was in SNMP v1) and error occurs.

P.S. "some software" is iReasoning Mib Browser. It's useful and valuable for many users. Table View does not work.

How to import Custom MIBS for Palo Alto Firewall to receive traps

Hi @slayercat

This looks like a great program you have built. Apologies I'm not a developer/coder. I wanted to build an open source Trap receiver and display the trap in a dashaboard. The Palo Alto has custom MIB files.

Could you please let me know how if your program can convert the custom MIB into a readable form for the trap and display it in a log somewhere.. after that I can try to find a way to push that to a dashaboard.

Thanks for any help.

Server snmp v3 auth&priv security mode responds (by oid data) to v3 noauth&nopriv and v2 requests

config code (from .../cmd/gosnmpserver/main.go)

master := GoSNMPServer.MasterAgent{
		Logger: logger,
		SecurityConfig: GoSNMPServer.SecurityConfig{
			AuthoritativeEngineBoots: 1,
			NoSecurity:               false,
			Users: []gosnmp.UsmSecurityParameters{
				{
					UserName:                 c.String("v3Username"),
					AuthenticationProtocol:   gosnmp.MD5,
					PrivacyProtocol:          gosnmp.AES,
					AuthenticationPassphrase: c.String("v3AuthenticationPassphrase"),
					PrivacyPassphrase:        c.String("v3PrivacyPassphrase"),
				},
			},
		},
		SubAgents: []*GoSNMPServer.SubAgent{
			{
				CommunityIDs: []string{c.String("community")},
				OIDs:         mibImps.All(),
			},
		},
	}

(...)
the SNMPv3 gosnmpserver normally continues to respond to snmp v2 requests.
Is it bug or feature? Assume this is a bug: the server should not respond to requests without authentication and privacy passwords in security mode. Or not?

**Edit: Now I try LATEST version and get the same behaviour.

How do I solve the concurrency problem

I found that after receiving the packet from the network, the code in the warehouse seems to execute each event in a single step. Is there a high concurrency problem in the library? After the network packet is unwrapped, can each event independently open a coroutine to complete the logic of data acquisition in its own business and then return to the other party?

SNMPv2c does not work anymore (ErrNoPermission)

$ go run github.com/slayercat/GoSNMPServer/cmd/[email protected] run-server --community public
$ snmpwalk -v2c -c public 127.0.0.1:1161
[...]
INFO[0000] ListenUDP: l3proto=udp, address=127.0.0.1:1161
INFO[0002] udp request from 127.0.0.1:39858. size=40
WARN[0002] ResponseForBuffer Error: ErrNoPermission. without result
INFO[0003] udp request from 127.0.0.1:39858. size=40
WARN[0003] ResponseForBuffer Error: ErrNoPermission. without result
INFO[0004] udp request from 127.0.0.1:39858. size=40
WARN[0004] ResponseForBuffer Error: ErrNoPermission. without result

Dunno if it's related to #27 and #23. It does not work with 0.5 either.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.