Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 31 additions & 37 deletions extension/dhcpdump/dhcpdump.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright 2016 Firewalla LLC
/* Copyright 2016-2019 Firewalla Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
Expand All @@ -17,16 +17,8 @@
let instance = null;
let log = null;

let fs = require('fs');
let util = require('util');
let jsonfile = require('jsonfile');

let f = require('../../net2/Firewalla.js');
let fHome = f.getFirewallaHome();

let userID = f.getUserID();
let dhcpdumpSpawn = null;
let pid = null;
const util = require('util');
const networkTool = require('../../net2/NetworkTool')();

module.exports = class {
constructor(loglevel) {
Expand Down Expand Up @@ -152,32 +144,34 @@ OPTION: 12 ( 12) Host name Great-Room-3
}
}

rawStart(callback) {
callback = callback || function() {}


let spawn = require('child_process').spawn;
let dhcpdumpSpawn = spawn('sudo', ['dhcpdump', '-i', 'eth0']);
let pid = dhcpdumpSpawn.pid;
let StringDecoder = require('string_decoder').StringDecoder;
let decoder = new StringDecoder('utf8');

log.info("DHCPDump started with PID: ", pid);

dhcpdumpSpawn.stdout.on('data', (data) => {
log.debug("Found a dhcpdiscover request");
let message = decoder.write(data);

this.parseEvents(message).map(e => callback(e))
});

dhcpdumpSpawn.stderr.on('data', (data) => {
log.error("Got error when running dhcp: ", data);
});

dhcpdumpSpawn.on('close', (code) => {
log.info("DHCPDump exited with error code: ", code);
});
async rawStart(callback) {
callback = callback || function () { }
const interfaces = await networkTool.getLocalNetworkInterface();
for (const intf of interfaces) {
if(!intf.name) continue;
let spawn = require('child_process').spawn;
let dhcpdumpSpawn = spawn('sudo', ['dhcpdump', '-i', intf.name]);
let pid = dhcpdumpSpawn.pid;
let StringDecoder = require('string_decoder').StringDecoder;
let decoder = new StringDecoder('utf8');

log.info("DHCPDump started with PID: ", pid);

dhcpdumpSpawn.stdout.on('data', (data) => {
log.debug("Found a dhcpdiscover request");
let message = decoder.write(data);

this.parseEvents(message).map(e => callback(e))
});

dhcpdumpSpawn.stderr.on('data', (data) => {
log.error("Got error when running dhcp: ", data);
});

dhcpdumpSpawn.on('close', (code) => {
log.info("DHCPDump exited with error code: ", code);
});
}
}

rawStop(callback) {
Expand Down
4 changes: 4 additions & 0 deletions net2/NetworkTool.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ class NetworkTool {

// same as listInterfaces() but filters out non-local interfaces
async getLocalNetworkInterface() {
//todo
//get gold networkInterface from firerouter api
//simple mode br0
//router mode enabled wans
let intfs = fConfig.discovery && fConfig.discovery.networkInterfaces;
if (!intfs) {
return null;
Expand Down
33 changes: 20 additions & 13 deletions sensor/BonjourSensor.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright 2016 Firewalla LLC
/* Copyright 2016-2019 Firewalla Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
Expand Down Expand Up @@ -26,6 +26,7 @@ const Promise = require('bluebird');

const SysManager = require('../net2/SysManager.js')
const sysManager = new SysManager('info')
const networkTool = require('../net2/NetworkTool')();
const Nmap = require('../net2/Nmap.js');
const nmap = new Nmap();
const l2 = require('../util/Layer2.js');
Expand All @@ -40,16 +41,16 @@ const ipMacCache = {};
class BonjourSensor extends Sensor {
constructor() {
super();

this.interfaces = null;
this.hostCache = {};

bonjour._server.mdns.on('warning', (err) => log.warn("Warning on mdns server", err))
bonjour._server.mdns.on('error', (err) => log.error("Error on mdns server", err))
}

run() {
async run() {
log.info("Bonjour Watch Starting");

this.interfaces = await networkTool.getLocalNetworkInterface();
if (this.bonjourBrowserTCP == null) {
this.bonjourBrowserTCP = bonjour.find({
protocol: 'tcp'
Expand Down Expand Up @@ -132,13 +133,16 @@ class BonjourSensor extends Sensor {
resolve(null);
} else {
if (!mac) {
if (ipAddr === sysManager.myIp()) {
resolve(sysManager.myMAC());
} else if (ipAddr === sysManager.myWifiIp()) {
resolve(sysManager.myWifiMAC());
} else {
log.error("Not able to find mac address for host:", ipAddr, mac);
resolve(null);
for (const intf of this.interfaces) {
const intfName = intf.name;
if (ipAddr === sysManager.myIp(intfName)) {
resolve(sysManager.myMAC(intfName));
} else if (ipAddr === sysManager.myWifiIp(intfName)) {
resolve(sysManager.myWifiMAC(intfName));
} else {
log.error("Not able to find mac address for host:", ipAddr, mac);
resolve(null);
}
}
} else {
ipMacCache[ipAddr] = { mac: mac, lastSeen: Date.now() / 1000 };
Expand All @@ -153,8 +157,11 @@ class BonjourSensor extends Sensor {
return null;
})
if (!mac) {
if (sysManager.myIp6() && sysManager.myIp6().includes(ipAddr)) {
mac = sysManager.myMAC();
for (const intf of this.interfaces) {
const intfName = intf.name;
if (sysManager.myIp6(intfName) && sysManager.myIp6(intfName).includes(ipAddr)) {
mac = sysManager.myMAC(intfName);
}
}
} else {
ipMacCache[ipAddr] = { mac: mac, lastSeen: Date.now() / 1000 };
Expand Down
52 changes: 20 additions & 32 deletions sensor/ICMP6Sensor.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright 2019 Firewalla LLC
/* Copyright 2019 Firewalla Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
Expand All @@ -25,7 +25,7 @@ const sem = require('../sensor/SensorEventManager.js').getInstance();
const Sensor = require('./Sensor.js').Sensor;
const SysManager = require('../net2/SysManager.js');
const Discovery = require('../net2//Discovery.js');

const networkTool = require('../net2/NetworkTool')();
const cp = require('child_process');
const execAsync = util.promisify(cp.exec);
const spawn = cp.spawn;
Expand All @@ -34,47 +34,35 @@ class ICMP6Sensor extends Sensor {
constructor() {
super();
this.myMac = null;
this.interfaces = null;
}

run() {
(async () => {
try {
const result = await execAsync("cat /sys/class/net/eth0/address");
this.myMac = result.stdout.trim().toUpperCase();
} catch (err) {
log.warn("Failed to get self MAC address from /sys/class/net/eth0/address");
}
if (!this.myMac) {
const d = new Discovery("ICMP6Sensor", fConfig, "info", false);
await d.discoverInterfacesAsync();
const sysManager = new SysManager();
await sysManager.updateAsync();
this.myMac = sysManager.myMAC().toUpperCase();
this.interfaces = await networkTool.getLocalNetworkInterface();
for (const intf of this.interfaces) {
if (!intf.name || !intf.mac_address) continue;
// listen on icmp6 neighbor-advertisement which is not sent from firewalla
const tcpdumpSpawn = spawn('sudo', ['tcpdump', '-i', intf.name, '-en', `!(ether src ${intf.mac_address}) && icmp6 && ip6[40] == 136`]);
const pid = tcpdumpSpawn.pid;
log.info("TCPDump icmp6 started with PID: ", pid);
const reader = readline.createInterface({
input: tcpdumpSpawn.stdout
});
reader.on('line', (line) => {
this.processNeighborAdvertisement(line);
});
tcpdumpSpawn.on('close', (code) => {
log.info("TCPDump icmp6 exited with code: ", code);
})
}

if (!this.myMac) {
if (!this.interfaces) {
setTimeout(() => {
log.info("Failed to get self MAC address from sysManager, retry in 60 seconds.");
this.run();
}, 60000);
return;
}

// listen on icmp6 neighbor-advertisement which is not sent from firewalla
const tcpdumpSpawn = spawn('sudo', ['tcpdump', '-i', 'eth0', '-en', `!(ether src ${this.myMac}) && icmp6 && ip6[40] == 136`]);
const pid = tcpdumpSpawn.pid;
log.info("TCPDump icmp6 started with PID: ", pid);

const reader = readline.createInterface({
input: tcpdumpSpawn.stdout
});
reader.on('line', (line) => {
this.processNeighborAdvertisement(line);
});

tcpdumpSpawn.on('close', (code) => {
log.info("TCPDump icmp6 exited with code: ", code);
})
})().catch((err) => {
log.error("Failed to run ICMP6Sensor", err);
});
Expand Down
8 changes: 3 additions & 5 deletions sensor/IPv6DiscoverySensor.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright 2016 Firewalla LLC
/* Copyright 2016-2019 Firewalla Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
Expand Down Expand Up @@ -34,11 +34,9 @@ const execAsync = require('child-process-promise').exec
class IPv6DiscoverySensor extends Sensor {
constructor() {
super();
this.networkInterface = networkTool.getLocalNetworkInterface();
this.enabled = true; // very basic feature, always enabled
let p = require('../net2/MessageBus.js');
this.publisher = new p('info','Scan:Done', 10);
log.debug("Starting IPv6DiscoverySensor Interfaces [",this.networkInterface,"]");
}

run() {
Expand Down Expand Up @@ -70,9 +68,9 @@ class IPv6DiscoverySensor extends Sensor {
}

async ping6ForDiscovery(intf, obj) {
await execAsync("ping6 -c2 -I eth0 ff02::1")
await execAsync(`ping6 -c2 -I ${intf} ff02::1`)
return asyncNative.eachLimit(obj.ip6_addresses, 5, async (o) => {
let pcmd = "ping6 -B -c 2 -I eth0 -I " + o + " ff02::1";
let pcmd = `ping6 -B -c 2 -I ${intf} -I ${o} ff02::1`;
log.info("Discovery:v6Neighbor:Ping6", pcmd);
return execAsync(pcmd)
})
Expand Down
38 changes: 20 additions & 18 deletions sensor/NmapSensor.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright 2016 Firewalla LLC
/* Copyright 2016-2019 Firewalla Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
Expand Down Expand Up @@ -35,7 +35,7 @@ const sysManager = new SysManager('info')
class NmapSensor extends Sensor {
constructor() {
super();

this.interfaces = null;
this.enabled = true; // very basic feature, always enabled

let p = require('../net2/MessageBus.js');
Expand Down Expand Up @@ -166,13 +166,12 @@ class NmapSensor extends Sensor {
return host;
}

async getNetworkRanges() {
let results = await networkTool.getLocalNetworkInterface()
return results &&
results.map((x) => networkTool.capSubnet(x.subnet))
getNetworkRanges() {
return this.interfaces && this.interfaces.map((x) => networkTool.capSubnet(x.subnet))
}

run() {
async run() {
this.interfaces = await networkTool.getLocalNetworkInterface();
process.nextTick(() => {
this.checkAndRunOnce(false);
});
Expand All @@ -184,9 +183,9 @@ class NmapSensor extends Sensor {
}, 1000 * 60 * 5); // every 5 minutes, fast scan
}

async checkAndRunOnce(fastMode) {
checkAndRunOnce(fastMode) {
if (this.isSensorEnabled()) {
let range = await this.getNetworkRanges()
let range = this.getNetworkRanges()
return this.runOnce(fastMode, range)
}
}
Expand Down Expand Up @@ -246,15 +245,18 @@ class NmapSensor extends Sensor {

_processHost(host) {
if(!host.mac) {
if(host.ipv4Addr && host.ipv4Addr === sysManager.myIp()) {
host.mac = sysManager.myMAC()
} else if (host.ipv4Addr && host.ipv4Addr === sysManager.myWifiIp()) {
host.mac = sysManager.myWifiMAC();
} else if(host.ipv4Addr && host.ipv4Addr === sysManager.myIp2()) {
return // do nothing on secondary ip
} else {
log.error("Invalid MAC Address for host", host);
return
for(const intf of this.interfaces){
const intfName = intf.name;
if(host.ipv4Addr && host.ipv4Addr === sysManager.myIp(intfName)) {
host.mac = sysManager.myMAC(intfName)
} else if (host.ipv4Addr && host.ipv4Addr === sysManager.myWifiIp(intfName)) {
host.mac = sysManager.myWifiMAC(intfName);
} else if(host.ipv4Addr && host.ipv4Addr === sysManager.myIp2(intfName)) {
return // do nothing on secondary ip
} else {
log.error("Invalid MAC Address for host", host);
return
}
}
}

Expand Down
Loading