Skip to content

Commit

Permalink
Add api to run nse scan
Browse files Browse the repository at this point in the history
  • Loading branch information
xinnige committed May 24, 2024
1 parent 99262a8 commit 743dba2
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 42 deletions.
4 changes: 2 additions & 2 deletions extension/dhcp/dhcp.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ async function dhcpDiscover(serverIp, macAddr=null, options=null) {
for (const item of kvs) {
result[item.key.replace(/\s/g, '')] = item['#content'];
}
if (result["DHCPMessageType"] != "DHCPACK") {
log.warn('expect dhcp-discover reply message type DHCPACK but', result["DHCPMessageType"])
if (result.DHCPMessageType && result.DHCPMessageType != "DHCPACK") {
log.warn(`expect dhcp-discover reply message type DHCPACK but '${result.DHCPMessageType}'`)
}
if (result.ServerIdentifier) {
result['ok'] = true;
Expand Down
1 change: 1 addition & 0 deletions net2/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
"ExternalScanSensor": {
"scanCooldown": 300
},
"NseScanPlugin": {},
"InternetSpeedtestPlugin": {
"vendorCandidates": [
"ookla"
Expand Down
94 changes: 55 additions & 39 deletions sensor/NseScanPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ const MAX_RECODE_NUM = 3; // only keeps last N records
class NseScanPlugin extends Sensor {
constructor(config) {
super(config);
this.scanJob;
this.policy;
this.running = false;
}

async run() {
Expand All @@ -51,6 +54,19 @@ class NseScanPlugin extends Sensor {
})
}

async apiRun() {
extensionManager.onCmd("runNseScan", async (msg, data) => {
if ( !data.policy ) {
return {'err': 'no nse_scan policy specified'};
}
const result = await this._runScanJob(data.policy, '', true)
if (result && result.err) {
return result;
}
return {'ok': true, ts: Date.now()/1000};
});
}

async loadPolicyAsync() {
const data = await rclient.hgetAsync(hostManager._getPolicyKey(), policyKeyName);
if (!data) {
Expand Down Expand Up @@ -112,21 +128,44 @@ class NseScanPlugin extends Sensor {
}

this.scanJob = new CronJob(cron, async() => {
log.info(`start cron nse scan job ${policy.cron}: ${JSON.stringify(policy.policy)}`);
const start = Date.now()/1000;
if (!policy.policy) {
return;
}
for (const key in policy.policy) {
await this.runCronJob(key, policy.policy[key]);
}
const delta = parseFloat((Date.now()/1000 - start).toFixed(2));
log.info(`Nse scan cron job finished in ${delta} seconds`);

await this._runScanJob(policy.policy);
}, () => {}, true, tz);
return;
}

async _runScanJob(policy, cron='', async = false) {
if (this.running) {
log.info('cron nse scan job already running, skip')
return;
}
try {
log.info(`start nse scan job ${cron}: ${JSON.stringify(policy)}`);
this.running = true
const start = Date.now()/1000;
if (!policy) {
return;
}
if (async) {
for (const key in policy) {
this.runCronJob(key, policy[key]);
}
log.info(`Nse scan cron job finish to submit`);
return;
}
// wait for results
for (const key in policy) {
await this.runCronJob(key, policy[key]);
}
const delta = parseFloat((Date.now()/1000 - start).toFixed(2));
log.info(`Nse scan cron job finished in ${delta} seconds`);
} catch (err) {
log.warn('fail to running nse scan job', err.message);
return {'err': err.message}
} finally {
this.running = false;
}
}

async runCronJob(key, state) {
if (!state) {
return;
Expand All @@ -148,11 +187,10 @@ class NseScanPlugin extends Sensor {
checkDhcpResult(result) {
let suspects = [];
for (const intf in result) {
// const ip_addr = await this._getIntfIP(intf);
if (Object.keys(result[intf]).length >= 2) {
// send a warning, suspicious of more than one dhcp server in network
if (Object.keys(result[intf]).length >= 1) {
// send a warning, suspicious of local dhcp server in network
const item = Object.entries(result[intf]).map((i)=>{return i[1].filter(i => i.local==false)}).flat();
log.debug('detect suspicious of more than one dhcp server in network', item.map( i => i.target));
log.debug('suspicious of local dhcp server in network', item.map( i => i.target));
suspects = suspects.concat(item);
}
}
Expand Down Expand Up @@ -220,30 +258,9 @@ class NseScanPlugin extends Sensor {
break;
}
case 'dhcp-discover': {
const interfaces = sysManager.getInterfaces(false).filter(i => i.gateway_ip);
log.debug("exec nse on interfaces", interfaces.map(i=>i.gateway_ip));
// scan gateway network
for (const intf of interfaces) {
if (!this._checkNetworkNsePolicy(intf.uuid, Constants.REDIS_HKEY_NSE_DHCP)) {
log.debug('skip network', scriptName, intf.name);
continue;
}
const result = await dhcp.dhcpDiscover(intf.gateway_ip, intf.mac_address, nseConfig[scriptName]);
log.debug("nse result scriptName", result);
if (result && result.ok) {
results.push({
serverIdentifier: result.ServerIdentifier,
domainNameServer: result.DomainNameServer,
router: result.Router,
interface: intf.name,
target: 'gateway:'+intf.mac_address,
ts: startTs,
});
}
}
// scan devices
const hosts = hostManager.getActiveHosts();
log.debug("exec nse on devices", hosts.map(i=>i.o.mac));
log.debug("exec nse on devices", hosts.map((i) => { return {ipv4: i.o.ipv4, mac: i.o.mac} }));
for (const h of hosts) {
if (h.o.ipv4 && h.o.intf && this._checkNsePolicy(h.policy, Constants.REDIS_HKEY_NSE_DHCP)) {
const result = await dhcp.dhcpDiscover(h.o.ipv4, h.o.mac, nseConfig[scriptName]);
Expand All @@ -256,7 +273,7 @@ class NseScanPlugin extends Sensor {
router: result.Router,
interface: devIntf && devIntf.name,
target: 'mac:'+h.o.mac,
local: sysManager.isMyMac(h.o.mac), // only device dhcp scan
local: sysManager.isMyMac(h.o.mac),
ts: startTs,
});
}
Expand Down Expand Up @@ -408,7 +425,6 @@ class NseScanPlugin extends Sensor {
_checkNetworkNsePolicy(uuid, fieldName) {
const networkProfile = networkProfileManager.getNetworkProfile(uuid);
const policy = networkProfile && networkProfile.policy;
log.debug('network policy', uuid, policy)
return this._checkNsePolicy(policy, fieldName);
}

Expand Down
8 changes: 7 additions & 1 deletion tests/test_nse_scan_sensor.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
'use strict'

let chai = require('chai');
const _ = require('lodash');
let expect = chai.expect;

const Constants = require('../net2/Constants.js');
Expand Down Expand Up @@ -70,6 +71,7 @@ describe('Test NseScanPlugin', function() {
hostManager.hostsdb[`host:mac:${host.mac}`] = host
hostManager.hosts.all.push(host);
}
hostManager.hosts.all = _.uniqWith(hostManager.hosts.all, (a,b) => a.o.ipv4 == b.o.ipv4 && a.o.mac == b.o.mac)
await rclient.hdelAsync(Constants.REDIS_KEY_NSE_RESULT, 'key1');
done();
})()
Expand All @@ -92,6 +94,10 @@ describe('Test NseScanPlugin', function() {
});

it('should exec broadcast-dhcp-discover', async() =>{
const interfaces = sysManager.getInterfaces(false).filter( i => i.name == "eth0");
for (const intf of interfaces) {
await _setIntfPolicy(intf.uuid, {state: true, dhcp: true});
}
const results = await this.plugin.execNse('broadcast-dhcp-discover');
log.debug('broadcast-dhcp-discover', JSON.stringify(results));
expect(results.length).to.be.not.equal(0);
Expand All @@ -100,7 +106,7 @@ describe('Test NseScanPlugin', function() {
it('should exec dhcp-discover', async() =>{
const results = await this.plugin.execNse('dhcp-discover');
log.debug('dhcp-discover', JSON.stringify(results));
expect(results.length).to.be.not.equal(0);
expect(results.length).to.be.not.null;
});

it('should run dhcp once', async() => {
Expand Down

0 comments on commit 743dba2

Please sign in to comment.