Skip to content

Commit

Permalink
Merge pull request #1 from jasonlyc/merge_real
Browse files Browse the repository at this point in the history
merge from firewalla
  • Loading branch information
MelvinTo committed Mar 11, 2021
2 parents 067bfbc + 05864e6 commit 1507bec
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 45 deletions.
6 changes: 3 additions & 3 deletions net2/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@
"NetworkMonitorSensor":{},
"LiveStatsPlugin": {},
"AdblockPlugin": {},
"WireGuardPlugin": {}
"WireGuardPlugin": {},
"InternalScanSensor": {}
},
"intels": [
"DedupAlarm",
Expand Down Expand Up @@ -601,7 +602,6 @@
"SystemDNSSensor": {},
"LocalDomainSensor": {},
"ClashPlugin": {},
"InternalScanSensor": {},
"LogScanSensor": {
"fireResetBluetooth": true,
"bonelogInterval": 900
Expand Down Expand Up @@ -785,7 +785,7 @@
"adblock": false,
"family_protect": false,
"smart_block": false,
"internal_scan": false,
"internal_scan": true,
"acl_audit": false,
"new_device_tag": false,
"dual_wan": true,
Expand Down
10 changes: 7 additions & 3 deletions scripts/flush_iptables.sh
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
#!/bin/bash

: ${FIREWALLA_HOME:=/home/pi/firewalla}

source ${FIREWALLA_HOME}/platform/platform.sh
# if the box is in dhcp mode, we want to keep MASQUERADE rule alive as much as possible
# or user's internet connection will go dead
# DNAT rules are free to flush as they won't block internet
MODE=$(redis-cli get mode)
if [ "$MODE" = "dhcp" ]
then
# reading filtered rules into an array https://www.computerhope.com/unix/bash/mapfile.htm
mapfile -t DHCP_RULES < <( sudo iptables -w -t nat -S | grep MASQUERADE )
mapfile -t DHCP_RULES < <( sudo iptables -w -t nat -S | grep FW_POSTROUTING | grep MASQUERADE )
fi

# Same situation applies to VPN connection
mapfile -t VPN_RULES < <( sudo iptables -w -t nat -S | grep FW_POSTROUTING | grep SNAT )

if [[ $(uname -m) == "x86_64" ]]; then
if [[ "$MANAGED_BY_FIREROUTER" == "yes" ]]; then
sudo iptables -w -t mangle -N FW_PREROUTING &>/dev/null
sudo iptables -w -t mangle -F FW_PREROUTING
sudo iptables -w -t mangle -N FW_FORWARD &> /dev/null
Expand Down Expand Up @@ -64,7 +67,8 @@ do
sudo iptables -w -t nat $RULE
done

if [ "$MODE" = "dhcp" ]
# no need to handle SNAT if it is managed by firerouter
if [ "$MODE" = "dhcp" ] && [ "$MANAGED_BY_FIREROUTER" != "yes" ];
then
for RULE in "${DHCP_RULES[@]}";
do
Expand Down
117 changes: 78 additions & 39 deletions sensor/InternalScanSensor.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,31 +40,61 @@ const am2 = new AM2();
const sem = require('../sensor/SensorEventManager.js').getInstance();
const featureName = "internal_scan";

const extensionManager = require('./ExtensionManager.js')

class InternalScanSensor extends Sensor {
constructor() {
super();
}

async run() {
async apiRun() {

this.running = false;
this.supportPorts = ["tcp_23", "tcp_80", "tcp_21", "tcp_3306", "tcp_6379"]; // default support: telnet http ftp mysql redis
if (platform.getName() === 'gold') {
this.supportPorts.push("tcp_22"); // gold: ssh
}
//this.supportPorts = ["tcp_23"];
sem.once("DeviceServiceScanComplete", async (event) => {
await this.checkAndRunOnce();

extensionManager.onGet("getScanStatus", async (msg, data) => {
return this.scanStatus;
});

extensionManager.onCmd("killScanSession", async (msg, data) => {
this.killCmd = true;
// this.currentPid is the bash command process
if (this.currentPid) {
// cPid is sudo process which fork from currentPid
const cPid = await execAsync(`ps -ef| grep nmap| awk '$3 == '${this.currentPid}' { print $2 }'`).then(result => result.stdout.trim()).catch(() => null);
// ccPid is timeout process which fork from cPid
const ccPid = await execAsync(`ps -ef| grep nmap| awk '$3 == '${cPid}' { print $2 }'`).then(result => result.stdout.trim()).catch(() => null);
// cccPid is nmap process which fork from ccPid
const cccPid = await execAsync(`ps -ef| grep nmap| awk '$3 == '${ccPid}' { print $2 }'`).then(result => result.stdout.trim()).catch(() => null);
if (cccPid) await execAsync(`sudo kill -9 ${cccPid}`).catch((err) => { });
}
});

fc.onFeature(featureName, (feature, status) => {
if (feature != featureName)
return
if (status) {
this.checkAndRunOnce();
extensionManager.onCmd("startScanSession", async (msg, data) => {
if (!this.running) {
this.killCmd = false;
await this.runOnce();
return {"msg":"start scan"}
} else {
return {"msg":"previous scan is running"}
}
})
});

}

// async run() {
// fc.onFeature(featureName, (feature, status) => {
// if (feature != featureName)
// return
// if (status) {
// this.checkAndRunOnce();
// }
// })
// }

async checkAndRunOnce() {
await this.runOnce();

Expand All @@ -84,13 +114,15 @@ class InternalScanSensor extends Sensor {
}

this.running = true;
this.scanStatus = {};
try {
log.info('Scan start...');
await this.checkDictionary();

let results = await hostManager.getHostsAsync();
results = results && results.filter((host) => host && host.o && host.o.mac && host.o.ipv4Addr && host.o.openports);
for (const host of results) {
if (this.killCmd) throw new Error("scan interruptted")
let openPorts = JSON.parse(host.o.openports);
log.info(host.o.ipv4Addr, openPorts);
let mergePorts = [];
Expand All @@ -103,17 +135,21 @@ class InternalScanSensor extends Sensor {
const hostName = host.name();
const waitPorts = this.supportPorts.filter((portid) => mergePorts.includes(portid));
log.info("Scanning device: ", host.o.ipv4Addr, waitPorts);
this.scanStatus[host.o.ipv4Addr] = {}
for (const portid of waitPorts) {
const nmapBrute = bruteConfig[portid];
if (nmapBrute) {
this.scanStatus[host.o.ipv4Addr][portid] = "scanning"
await this.nmapGuessPassword(host.o.ipv4Addr, hostName, nmapBrute);
this.scanStatus[host.o.ipv4Addr][portid] = "scanned"
}
}
};
} catch (err) {
log.error("Failed to scan: " + err);
}
this.running = false;
this.currentPid = undefined;
log.info('Scan end');
}

Expand Down Expand Up @@ -199,38 +235,41 @@ class InternalScanSensor extends Sensor {
log.info("Running command:", cmd);
const startTime = Date.now() / 1000;
try {
const result = await execAsync(cmd);
let output = JSON.parse(result.stdout);
let findings = null;
if (bruteScript.scriptName == "redis-info") {
findings = _.get(output, `nmaprun.host.ports.port.service.version`, null);
if (findings != null) {
weakPasswords.push({username: "", password: ""}); //empty password access
}
} else {
findings = _.get(output, `nmaprun.host.ports.port.script.table.table`, null);
if (findings != null) {
if (findings.constructor === Object) {
findings = [findings]
const result = cp.exec(cmd);
this.currentPid = result.pid;
for await (const r of result.stdout) {
let output = JSON.parse(r);
let findings = null;
if (bruteScript.scriptName == "redis-info") {
findings = _.get(output, `nmaprun.host.ports.port.service.version`, null);
if (findings != null) {
weakPasswords.push({username: "", password: ""}); //empty password access
}

for (const finding of findings) {
let weakPassword = {};
finding.elem.forEach((x) => {
switch (x.key) {
case "username":
weakPassword.username = x["#content"];
break;
case "password":
weakPassword.password = x["#content"];
break;
default:
}
});
weakPasswords.push(weakPassword);
} else {
findings = _.get(output, `nmaprun.host.ports.port.script.table.table`, null);
if (findings != null) {
if (findings.constructor === Object) {
findings = [findings]
}

for (const finding of findings) {
let weakPassword = {};
finding.elem.forEach((x) => {
switch (x.key) {
case "username":
weakPassword.username = x["#content"];
break;
case "password":
weakPassword.password = x["#content"];
break;
default:
}
});
weakPasswords.push(weakPassword);
}
}
}
}
}
} catch (err) {
log.error("Failed to nmap scan:", err);
}
Expand Down

0 comments on commit 1507bec

Please sign in to comment.