Skip to content

Commit

Permalink
feat(webserver): Allow IPv6 requests from own network (#1342)
Browse files Browse the repository at this point in the history
Co-authored-by: schinken <schinken@bamberg.ccc.de>
  • Loading branch information
schinken and schinken committed Jan 9, 2022
1 parent 77e07ec commit 165deff
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 70 deletions.
40 changes: 18 additions & 22 deletions backend/lib/Tools.js
Expand Up @@ -242,36 +242,32 @@ class Tools {
return `${string[0].toUpperCase()}${string.slice(1)}`;
}

static GET_CURRENT_HOST_IP_ADDRESSES() {
const IPs = new Set();

Object.values(os.networkInterfaces())
static GET_NETWORK_INTERFACES() {
return Object.values(os.networkInterfaces())
.flat()
.filter(i => {
return !i.mac.startsWith("00:00");
})
.forEach(i => {
IPs.add(i.address);
}
);
});
}

static GET_CURRENT_HOST_IP_ADDRESSES() {
const IPs = Tools
.GET_NETWORK_INTERFACES()
.map(i => {
return i.address;
});

return Array.from(IPs.values());
return [...new Set(IPs)]; // dedupe
}

static GET_NETWORK_INTERFACE_MACS_FROM_NODEJS() {
const macAddresses = new Set();

Object.values(os.networkInterfaces())
.flat()
.filter(i => {
return !i.mac.startsWith("00:00");
})
.forEach(i => {
macAddresses.add(i.mac);
}
);
const macs = Tools
.GET_NETWORK_INTERFACES()
.map(i => {
return i.mac;
});

return Array.from(macAddresses.values());
return [...new Set(macs)]; // dedupe
}

static GET_NETWORK_INTERFACE_MACS_FROM_SYSFS() {
Expand Down
26 changes: 24 additions & 2 deletions backend/lib/webserver/middlewares/ExternalAccessCheckMiddleware.js
@@ -1,5 +1,9 @@
const isInSubnet = require("is-in-subnet");
const QuickLRU = require("quick-lru");
const Logger = require("../../Logger");
const Tools = require("../../Tools");

const IPAccessLRU = new QuickLRU({ maxSize: 15 });

/**
*
Expand All @@ -17,20 +21,38 @@ module.exports = function checkExternalAccess(req, res, next) {
}
};

function isLocalIPv6Subnet(ip) {
// Limit requests to GET_NETWORK_INTERFACES by checking for IP-Version first
if (!isInSubnet.isIPv6(ip)) {
return false;
}

// If a IPv6 subnet of the robot matches the origin IP, the request must come from the local network
return !!Tools
.GET_NETWORK_INTERFACES()
.find(i => {
return i.family === "IPv6" && isInSubnet.check(ip, i.cidr);
});
}

function isAllowed(ip) {
let allowed = false;
// IPv6 lookup is expensive, so we've decided to cache all the allow checks here in an LRU
if (IPAccessLRU.has(ip)) {
return IPAccessLRU.get(ip);
}

let allowed = false;
try {
/* See https://github.com/jshttp/on-finished/issues/8 for why req.ip can be undefined
Quote:
req.url and such are strings. req.ip is a getter property that calls req.remoteAddress that is a getter
that does a network socket call, so its value depends on the state of the socket
*/
allowed = ip !== undefined && (isInSubnet.isPrivate(ip) || isInSubnet.isLocalhost(ip));
allowed = ip !== undefined && (isInSubnet.isPrivate(ip) || isInSubnet.isLocalhost(ip) || isLocalIPv6Subnet(ip));
} catch (e) {
Logger.warn("Error during external access check", e);
}

IPAccessLRU.set(ip, allowed);
return allowed;
}
15 changes: 8 additions & 7 deletions backend/package.json
Expand Up @@ -35,9 +35,10 @@
"dependencies": {
"@destinationstransfers/ntp": "2.0.0",
"ajv": "8.8.2",
"axios": "0.24.0",
"async-mqtt": "2.6.1",
"axios": "0.24.0",
"body-parser": "1.19.0",
"bonjour-service": "git+https://npm@github.com/Hypfer/bonjour-service#113d63c3a07f739001198545d2a9c1043e9a5b0b",
"compression": "1.7.4",
"crc": "3.8.0",
"escape-html": "1.0.3",
Expand All @@ -47,27 +48,27 @@
"express-list-endpoints": "6.0.0",
"express-rate-limit": "5.5.1",
"is-in-subnet": "4.0.1",
"jstoxml": "2.2.7",
"mqtt": "4.2.8",
"nested-object-assign": "1.0.4",
"nested-property": "4.0.0",
"node-ssdp": "4.0.1",
"openapi-validator-middleware": "3.2.4",
"quick-lru": "5.1.1",
"semaphore": "1.1.0",
"swagger-ui-express": "4.3.0",
"openapi-validator-middleware": "3.2.4",
"uuid": "8.3.2",
"jstoxml": "2.2.7",
"node-ssdp": "4.0.1",
"bonjour-service": "git+https://npm@github.com/Hypfer/bonjour-service#113d63c3a07f739001198545d2a9c1043e9a5b0b",
"zoo-ids": "2.0.7"
},
"devDependencies": {
"@types/compression": "1.7.2",
"@types/express": "4.17.13",
"@types/express-list-endpoints": "6.0.0",
"@types/jstoxml": "2.0.1",
"@types/mocha": "7.0.2",
"@types/node": "16.11.1",
"@types/semaphore": "1.1.1",
"@types/jstoxml": "2.0.1",
"@types/node-ssdp": "4.0.1",
"@types/semaphore": "1.1.1",
"@types/uuid": "8.3.3",
"cross-env": "7.0.3",
"mocha": "7.1.1",
Expand Down
57 changes: 18 additions & 39 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 165deff

Please sign in to comment.