2018-08-29 12:04:23 +00:00
|
|
|
package snmp
|
|
|
|
|
|
|
|
import (
|
2018-08-30 12:56:32 +00:00
|
|
|
"encoding/json"
|
2018-08-29 12:04:23 +00:00
|
|
|
"fmt"
|
2018-08-30 12:56:32 +00:00
|
|
|
"net"
|
|
|
|
"strconv"
|
2018-08-31 02:32:25 +00:00
|
|
|
"sync"
|
|
|
|
"time"
|
2018-08-29 12:04:23 +00:00
|
|
|
|
2018-08-30 12:56:32 +00:00
|
|
|
omcc "git.loafle.net/overflow/model/config/credential"
|
2018-08-29 12:04:23 +00:00
|
|
|
omd "git.loafle.net/overflow/model/discovery"
|
2018-08-30 12:56:32 +00:00
|
|
|
omm "git.loafle.net/overflow/model/meta"
|
|
|
|
omu "git.loafle.net/overflow/model/util"
|
|
|
|
"git.loafle.net/overflow_scanner/probe/discovery/session"
|
2018-08-29 12:04:23 +00:00
|
|
|
"github.com/k-sone/snmpgo"
|
|
|
|
)
|
|
|
|
|
2018-08-30 12:56:32 +00:00
|
|
|
const (
|
|
|
|
defaultPort = 161
|
2018-08-31 02:32:25 +00:00
|
|
|
defaultTimeout = 1
|
2018-08-30 12:56:32 +00:00
|
|
|
defaultCommunity = "public"
|
|
|
|
)
|
2018-08-29 12:04:23 +00:00
|
|
|
|
2018-08-30 12:56:32 +00:00
|
|
|
var (
|
|
|
|
defaultOIDs = []string{
|
|
|
|
"1.3.6.1.2.1.1.5.0", //sysName
|
|
|
|
}
|
|
|
|
|
|
|
|
defaultCredentials = []*omcc.SNMPCredential{
|
|
|
|
&omcc.SNMPCredential{
|
|
|
|
Version: "2c",
|
|
|
|
Community: "public",
|
|
|
|
Port: json.Number(strconv.Itoa(defaultPort)),
|
|
|
|
Timeout: json.Number(strconv.Itoa(defaultTimeout)),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2018-08-31 05:15:46 +00:00
|
|
|
func Scan(discoverySession session.DiscoverySession) error {
|
2018-08-31 02:32:25 +00:00
|
|
|
targetHosts := discoverySession.TargetHosts()
|
|
|
|
if nil == targetHosts || 0 == len(targetHosts) {
|
2018-08-31 05:15:46 +00:00
|
|
|
return nil
|
2018-08-30 12:56:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var cs []*omcc.SNMPCredential
|
|
|
|
|
|
|
|
if _csMap := discoverySession.DiscoveryConfig().Credentials; nil != _csMap {
|
|
|
|
_cs, ok := _csMap["SNMP"]
|
|
|
|
if ok {
|
|
|
|
cs = _cs.([]*omcc.SNMPCredential)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if nil == cs {
|
|
|
|
cs = defaultCredentials
|
|
|
|
}
|
|
|
|
|
|
|
|
credentials := make(map[string][]*omcc.SNMPCredential)
|
|
|
|
for _, _c := range cs {
|
|
|
|
credentials[_c.Version] = append(credentials[_c.Version], _c)
|
|
|
|
}
|
2018-08-29 12:04:23 +00:00
|
|
|
|
2018-08-31 02:32:25 +00:00
|
|
|
var wg sync.WaitGroup
|
|
|
|
|
2018-08-30 12:56:32 +00:00
|
|
|
_2cCS, ok := credentials["2c"]
|
|
|
|
if ok {
|
2018-08-31 02:32:25 +00:00
|
|
|
wg.Add(1)
|
2018-08-30 12:56:32 +00:00
|
|
|
go func() {
|
2018-08-31 02:32:25 +00:00
|
|
|
defer wg.Done()
|
2018-08-31 04:05:59 +00:00
|
|
|
|
2018-08-31 02:32:25 +00:00
|
|
|
for _, target := range targetHosts {
|
2018-08-31 04:05:59 +00:00
|
|
|
wg.Add(1)
|
|
|
|
go func(target net.IP) {
|
|
|
|
defer wg.Done()
|
|
|
|
for _, c := range _2cCS {
|
|
|
|
if scanV2(target, discoverySession, c) {
|
|
|
|
return
|
|
|
|
}
|
2018-08-30 12:56:32 +00:00
|
|
|
}
|
2018-08-31 04:05:59 +00:00
|
|
|
}(target)
|
2018-09-03 10:33:20 +00:00
|
|
|
|
|
|
|
select {
|
|
|
|
case <-discoverySession.StopChan():
|
|
|
|
return
|
|
|
|
default:
|
|
|
|
}
|
2018-08-30 12:56:32 +00:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
2018-08-31 02:32:25 +00:00
|
|
|
|
|
|
|
wg.Wait()
|
2018-08-31 05:15:46 +00:00
|
|
|
|
|
|
|
return nil
|
2018-08-29 12:04:23 +00:00
|
|
|
}
|
|
|
|
|
2018-08-30 12:56:32 +00:00
|
|
|
func scanV2(target net.IP, discoverySession session.DiscoverySession, credential *omcc.SNMPCredential) bool {
|
|
|
|
|
2018-08-31 02:32:25 +00:00
|
|
|
address := fmt.Sprintf("%s:%s", target.String(), credential.Port.String())
|
|
|
|
timeout, _ := credential.Timeout.Int64()
|
2018-08-29 12:04:23 +00:00
|
|
|
snmp, err := snmpgo.NewSNMP(snmpgo.SNMPArguments{
|
|
|
|
Version: snmpgo.V2c,
|
|
|
|
Address: address,
|
2018-08-31 02:32:25 +00:00
|
|
|
Timeout: time.Second * time.Duration(timeout),
|
2018-08-29 12:04:23 +00:00
|
|
|
Retries: 1,
|
2018-08-30 12:56:32 +00:00
|
|
|
Community: credential.Community,
|
2018-08-29 12:04:23 +00:00
|
|
|
})
|
2018-08-31 02:32:25 +00:00
|
|
|
|
2018-08-29 12:04:23 +00:00
|
|
|
if err != nil {
|
2018-08-30 12:56:32 +00:00
|
|
|
// ch <- &SNMPResponse{host, nil, err}
|
|
|
|
return false
|
2018-08-29 12:04:23 +00:00
|
|
|
}
|
|
|
|
defer snmp.Close()
|
|
|
|
|
2018-08-30 12:56:32 +00:00
|
|
|
oids, err := snmpgo.NewOids(defaultOIDs)
|
2018-08-29 12:04:23 +00:00
|
|
|
if err != nil {
|
2018-08-30 12:56:32 +00:00
|
|
|
// ch <- &SNMPResponse{host, nil, err}
|
|
|
|
return false
|
2018-08-29 12:04:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pdu, err := snmp.GetRequest(oids)
|
|
|
|
if err != nil {
|
2018-08-30 12:56:32 +00:00
|
|
|
// ch <- &SNMPResponse{host, nil, err}
|
|
|
|
return false
|
2018-08-29 12:04:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if pdu.ErrorStatus() != snmpgo.NoError {
|
2018-08-30 12:56:32 +00:00
|
|
|
// ch <- &SNMPResponse{host, nil, fmt.Errorf("%s", pdu.ErrorStatus().String())}
|
|
|
|
return false
|
2018-08-29 12:04:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if pdu == nil {
|
2018-08-30 12:56:32 +00:00
|
|
|
// ch <- &SNMPResponse{host, nil, fmt.Errorf("%s", "Empty PDU")}
|
|
|
|
return false
|
2018-08-29 12:04:23 +00:00
|
|
|
}
|
|
|
|
|
2018-08-30 12:56:32 +00:00
|
|
|
meta := make(map[string]string)
|
2018-08-29 12:04:23 +00:00
|
|
|
for _, val := range pdu.VarBinds() {
|
2018-08-30 12:56:32 +00:00
|
|
|
meta[val.Oid.String()] = val.Variable.String()
|
2018-08-29 12:04:23 +00:00
|
|
|
}
|
2018-08-30 12:56:32 +00:00
|
|
|
|
2018-09-11 07:59:21 +00:00
|
|
|
h := discoverySession.AddHost(
|
|
|
|
"SNMP V2c",
|
|
|
|
&omd.Host{
|
|
|
|
MetaIPType: discoverySession.Zone().MetaIPType,
|
|
|
|
Name: "",
|
|
|
|
Address: target.String(),
|
|
|
|
Zone: discoverySession.Zone(),
|
|
|
|
DiscoveredDate: omu.NowPtr(),
|
|
|
|
},
|
|
|
|
meta,
|
|
|
|
)
|
|
|
|
|
|
|
|
p := discoverySession.AddPort("SNMP V2c",
|
|
|
|
&omd.Port{
|
|
|
|
MetaPortType: omm.ToMetaPortType(omm.MetaPortTypeEnumUDP),
|
|
|
|
PortNumber: credential.Port,
|
|
|
|
Host: h,
|
|
|
|
DiscoveredDate: omu.NowPtr(),
|
|
|
|
},
|
|
|
|
meta,
|
|
|
|
)
|
|
|
|
|
|
|
|
discoverySession.AddService("SNMP V2c",
|
|
|
|
&omd.Service{
|
|
|
|
MetaCryptoType: omm.ToMetaCryptoType(omm.MetaCryptoTypeEnumNONE),
|
|
|
|
Key: "SNMP",
|
|
|
|
Name: "SNMP V2c",
|
|
|
|
Port: p,
|
|
|
|
DiscoveredDate: omu.NowPtr(),
|
|
|
|
},
|
|
|
|
meta,
|
|
|
|
)
|
2018-08-30 12:56:32 +00:00
|
|
|
|
2018-09-01 13:09:33 +00:00
|
|
|
// log.Printf("Host: %v, Port: %v, Service: %v", h, p, s)
|
2018-09-01 02:19:03 +00:00
|
|
|
|
2018-08-30 12:56:32 +00:00
|
|
|
return true
|
2018-08-29 12:04:23 +00:00
|
|
|
}
|