Improvements, fixes
This commit is contained in:
parent
6c391e8c0a
commit
c17cace17c
3 changed files with 95 additions and 27 deletions
56
README.md
Normal file
56
README.md
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
# MinIPAM
|
||||||
|
A simple tool that scans specified subnet(s) and has WEB UI to easily see which IPs are available
|
||||||
|
|
||||||
|
I wanted something like space map from PHPIPAM but with less clicking to get to see what I want to see.
|
||||||
|
Web UI is just a bunch of buttons (one for subnet) and table, representing hosts in said subnet. Hosts that were online
|
||||||
|
during last scan are marked as green, hosts which were online at least once but were offline during last scan are marked
|
||||||
|
red, and hosts that were never seen online are marked gray. Also for every online host during a scan RevDNS lookup
|
||||||
|
is made to attempt to get its hostname. Web UI does not allow editing presented data in any way, which is also why
|
||||||
|
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.
|
||||||
|
|
||||||
|
TODO: screenshot
|
||||||
|
|
||||||
|
# Configuration reference
|
||||||
|
```yaml
|
||||||
|
bind_address: "0.0.0.0:8443"
|
||||||
|
scan_subnets:
|
||||||
|
- 192.168.145.0/24
|
||||||
|
- 10.250.100.64.0/27
|
||||||
|
delay_between_scans: 15m
|
||||||
|
persistence_location: "data.json"
|
||||||
|
exclude_special_addresses: true
|
||||||
|
use_tls: false
|
||||||
|
tls_key_file: "key.pem"
|
||||||
|
tls_cert_file: "fullchain.pem"
|
||||||
|
```
|
||||||
|
`delay_between_scans` specifies time to wait between scans. For example 15m means that
|
||||||
|
scan starts at 17:43, takes 2 minutes, finishes at 17:45, next scan will start at 18:00
|
||||||
|
|
||||||
|
`exclude_special_addresses` excludes network and broadcast addresses from scanning and results.
|
||||||
|
With subnets in example above, those would be `192.168.145.0`,`192.168.145.255`,`10.250.100.64`,`10.250.100.95`.
|
||||||
|
|
||||||
|
`persistence_location` indicates where data should be stored. It needs to be writable.
|
||||||
|
|
||||||
|
# Requirements
|
||||||
|
|
||||||
|
Scanning is done by running:
|
||||||
|
```go
|
||||||
|
exec.Command("ping", "-n", "-W", "0.2", "-c", "1", addr)
|
||||||
|
```
|
||||||
|
So you need OS that has `ping` command with those options.
|
||||||
|
Tested with GNU coreutils on archlinux. Also works on FreeBSD, however, FreeBSD's ping will wait 1 second instead of
|
||||||
|
0.2 seconds, making scanning networks with a lot of free IPs slower.
|
||||||
|
|
||||||
|
While we're at it, hosts are expected to reply within 0.2 seconds (except on FreeBSD, where ping is not accepting
|
||||||
|
fractional timeout values). This is currently hard-coded.
|
||||||
|
|
||||||
|
# Authentication
|
||||||
|
Since I don't think that any data presented by this tool would be considered sensitive, I didn't implement any
|
||||||
|
authentication mechanism. If for some reason you decided that you NEED one, consider following options:
|
||||||
|
- Use firewall to only allow trusted networks to access this tool
|
||||||
|
- If this tool happens to be running on your workstation, bind it to localhost only
|
||||||
|
- Bind this tool to localhost only and use SSH port forwarding
|
||||||
|
- Set up reverse proxy with authorization, then bind this tool to localhost only.
|
24
index.html
24
index.html
|
@ -5,12 +5,19 @@
|
||||||
<style>
|
<style>
|
||||||
.status_online {
|
.status_online {
|
||||||
background-color: lawngreen;
|
background-color: lawngreen;
|
||||||
|
color: black;
|
||||||
}
|
}
|
||||||
.status_offline {
|
.status_offline {
|
||||||
background-color: orangered;
|
background-color: orangered;
|
||||||
|
color: black;
|
||||||
}
|
}
|
||||||
.status_free {
|
.status_free {
|
||||||
background-color: dimgray;
|
background-color: dimgray;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
|
@ -53,16 +60,20 @@
|
||||||
alert(`Error ${xhr.status}: ${xhr.statusText}`); // e.g. 404: Not Found
|
alert(`Error ${xhr.status}: ${xhr.statusText}`); // e.g. 404: Not Found
|
||||||
} else { // show the result
|
} else { // show the result
|
||||||
data = JSON.parse(xhr.responseText)
|
data = JSON.parse(xhr.responseText)
|
||||||
|
let last=""
|
||||||
for (const subnet in data.Subnets) {
|
for (const subnet in data.Subnets) {
|
||||||
document.getElementById("subnetscontainer").innerHTML+="<button onClick=viewSubnet(this)>"+subnet+"</button>"
|
document.getElementById("subnetscontainer").innerHTML+="<button onClick=viewSubnet(this.innerText)>"+subnet+"</button>"
|
||||||
|
last=subnet
|
||||||
|
}
|
||||||
|
if(last != "") {
|
||||||
|
viewSubnet(last)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
xhr.send();
|
xhr.send();
|
||||||
}
|
}
|
||||||
function viewSubnet(elem) {
|
function viewSubnet(subnet) {
|
||||||
subnet = elem.innerText
|
|
||||||
|
|
||||||
usedAddresses = data.Subnets[subnet].used_addresses
|
usedAddresses = data.Subnets[subnet].used_addresses
|
||||||
totalAddresses = data.Subnets[subnet].total_addresses
|
totalAddresses = data.Subnets[subnet].total_addresses
|
||||||
|
@ -75,7 +86,7 @@
|
||||||
|
|
||||||
let tableHTML = '<table border="1"><thead><tr><th>IP Address</th><th>RevDNS</th><th>First seen</th><th>Last seen</th></tr></thead><tbody>';
|
let tableHTML = '<table border="1"><thead><tr><th>IP Address</th><th>RevDNS</th><th>First seen</th><th>Last seen</th></tr></thead><tbody>';
|
||||||
|
|
||||||
for (const subnet in data.Subnets) {
|
|
||||||
const hosts = data.Subnets[subnet].hosts;
|
const hosts = data.Subnets[subnet].hosts;
|
||||||
|
|
||||||
// Iterate over IPs in the subnet
|
// Iterate over IPs in the subnet
|
||||||
|
@ -99,9 +110,9 @@
|
||||||
// Add a row to the HTML table
|
// Add a row to the HTML table
|
||||||
tableHTML += `<tr class="status_${status}"><td>${ip}</td><td>${revdns}</td><td>${fs}</td><td>${ls}</td></tr>`;
|
tableHTML += `<tr class="status_${status}"><td>${ip}</td><td>${revdns}</td><td>${fs}</td><td>${ls}</td></tr>`;
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
tableHTML += '</tbody></table>';
|
tableHTML += '</tbody></table>';
|
||||||
|
document.getElementById("subnetview").innerHTML=""
|
||||||
document.getElementById("subnetview").innerHTML=tableHTML
|
document.getElementById("subnetview").innerHTML=tableHTML
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -112,7 +123,8 @@
|
||||||
<div id="subnetscontainer"></div>
|
<div id="subnetscontainer"></div>
|
||||||
<hr>
|
<hr>
|
||||||
<p>Subnet <span id="subnetCidrField"></span></p>
|
<p>Subnet <span id="subnetCidrField"></span></p>
|
||||||
<p>Space usage <span id="subnetUsedField"></span><progress id="subnetUsageBar"></progress></p>
|
<p>Space usage <span id="subnetUsedField"></span></p>
|
||||||
|
<progress id="subnetUsageBar"></progress><br>
|
||||||
<div id="subnetview"></div>
|
<div id="subnetview"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -37,7 +37,7 @@ type SubnetT struct {
|
||||||
Hosts map[string]HostT `json:"hosts"`
|
Hosts map[string]HostT `json:"hosts"`
|
||||||
TotalAddresses int `json:"total_addresses"`
|
TotalAddresses int `json:"total_addresses"`
|
||||||
UsedAddresses int `json:"used_addresses"`
|
UsedAddresses int `json:"used_addresses"`
|
||||||
HostList []string `json:"host_list"`
|
HostList []string `json:"host_list"` //I _REALLY_ didn't want to calculate this in javascript
|
||||||
}
|
}
|
||||||
|
|
||||||
type PersistenceT struct {
|
type PersistenceT struct {
|
||||||
|
|
Loading…
Reference in a new issue