Scan subnets in parallel, update readme, update gitignore

This commit is contained in:
Łukasz Moskała 2024-02-16 17:57:58 +01:00
parent 6642554473
commit 2caf97d535
3 changed files with 80 additions and 62 deletions

1
.gitignore vendored
View file

@ -2,5 +2,6 @@
!.gitignore
!.screenshot.png
minipam
MinIPAM
*.yaml
*.json

View file

@ -11,6 +11,9 @@ there is no authorization mechanism built in.
Scanning is kind of slow, but I prefer to keep it that way, since I don't need it to be fast, and I don't want to waste
my compute resources. It doesn't matter for me if my scan completes within 1 minute or within 30 minutes.
Subnets are scanned in parallel, but addresses in each subnet are still scanned sequentially. So complete scan takes as
much time, as scanning of biggest subnet that you have.
![Screenshot](.screenshot.png)
# Compilation
@ -33,9 +36,13 @@ scan_subnets:
- 192.168.145.0/24
- 10.250.100.64.0/27
delay_between_scans: 15m
#Setting this to absolute path seems like a good idea :)
persistence_location: "data.json"
#Don't scan network and broadcast address, usually you want to leave this set to true
exclude_special_addresses: true
use_tls: false
#IF use_tls is set to false, following two options are ignored.
#key and cert and fullchain can be in one file. In this case, specify the same file in both fields
tls_key_file: "key.pem"
tls_cert_file: "fullchain.pem"
```

View file

@ -12,6 +12,7 @@ import (
"net/netip"
"os"
"os/exec"
"sync"
"time"
)
@ -120,77 +121,86 @@ func ping(addr string) bool {
func scanner() {
for {
var wg sync.WaitGroup
var mutex sync.Mutex
for _, subnet := range conf.ScanSubnets {
for _, v := range conf.ScanSubnets {
persistenceSubnet, ok := p.Subnets[v]
if !ok {
persistenceSubnet = SubnetT{}
persistenceSubnet.Hosts = make(map[string]HostT)
}
log.Printf("Scanning subnet %s", v)
prefix, err := netip.ParsePrefix(v)
if err != nil {
log.Printf("Error: %s", err)
continue
}
prefix = prefix.Masked()
addr := prefix.Addr()
if conf.ExcludeSpecialAddresses {
addr = addr.Next()
}
persistenceSubnet.TotalAddresses = 0
persistenceSubnet.UsedAddresses = 0
persistenceSubnet.HostList = make([]string, 0)
for {
if !prefix.Contains(addr) {
break
go func(v string) {
wg.Add(1)
defer wg.Done()
persistenceSubnet, ok := p.Subnets[v]
if !ok {
persistenceSubnet = SubnetT{}
persistenceSubnet.Hosts = make(map[string]HostT)
}
//skip broadcast address
if conf.ExcludeSpecialAddresses && !prefix.Contains(addr.Next()) {
break
log.Printf("Scanning subnet %s", v)
prefix, err := netip.ParsePrefix(v)
if err != nil {
log.Printf("Error: %s", err)
return
}
persistenceSubnet.TotalAddresses++
//fmt.Println(addr.String())
persistenceSubnet.HostList = append(persistenceSubnet.HostList, addr.String())
pingstate := ping(addr.String())
host, ok := persistenceSubnet.Hosts[addr.String()]
if pingstate {
persistenceSubnet.UsedAddresses++
//log.Printf("%s is up", addr.String())
rdnsString := ""
rdns, err := net.LookupAddr(addr.String())
if err == nil {
if len(rdns) > 0 {
rdnsString = rdns[0]
}
prefix = prefix.Masked()
addr := prefix.Addr()
if conf.ExcludeSpecialAddresses {
addr = addr.Next()
}
persistenceSubnet.TotalAddresses = 0
persistenceSubnet.UsedAddresses = 0
persistenceSubnet.HostList = make([]string, 0)
for {
if !prefix.Contains(addr) {
break
}
if !ok {
persistenceSubnet.Hosts[addr.String()] = HostT{
FirstSeen: time.Now(),
LastSeen: time.Now(),
Online: true,
RevDNS: rdnsString,
//skip broadcast address
if conf.ExcludeSpecialAddresses && !prefix.Contains(addr.Next()) {
break
}
persistenceSubnet.TotalAddresses++
//fmt.Println(addr.String())
persistenceSubnet.HostList = append(persistenceSubnet.HostList, addr.String())
pingstate := ping(addr.String())
host, ok := persistenceSubnet.Hosts[addr.String()]
if pingstate {
persistenceSubnet.UsedAddresses++
//log.Printf("%s is up", addr.String())
rdnsString := ""
rdns, err := net.LookupAddr(addr.String())
if err == nil {
if len(rdns) > 0 {
rdnsString = rdns[0]
}
}
} else {
host.LastSeen = time.Now()
host.Online = true
host.RevDNS = rdnsString
if !ok {
persistenceSubnet.Hosts[addr.String()] = HostT{
FirstSeen: time.Now(),
LastSeen: time.Now(),
Online: true,
RevDNS: rdnsString,
}
} else {
host.LastSeen = time.Now()
host.Online = true
host.RevDNS = rdnsString
persistenceSubnet.Hosts[addr.String()] = host
}
} else if ok {
host.Online = false
persistenceSubnet.Hosts[addr.String()] = host
persistenceSubnet.UsedAddresses++
}
} else if ok {
host.Online = false
persistenceSubnet.Hosts[addr.String()] = host
persistenceSubnet.UsedAddresses++
addr = addr.Next()
}
addr = addr.Next()
}
p.Subnets[v] = persistenceSubnet
mutex.Lock()
p.Subnets[v] = persistenceSubnet
mutex.Unlock()
log.Printf("Scan of %s finished", v)
}(subnet)
}
log.Printf("Scan finished")
wg.Wait()
log.Printf("All scans finished")
f, err := os.Create(conf.PersistenceLocation)
if err != nil {
log.Printf("Failed to save persistence: %s", err)