mirror of
https://github.com/koush/scrypted.git
synced 2026-02-17 12:12:16 +00:00
107 lines
3.0 KiB
TypeScript
107 lines
3.0 KiB
TypeScript
import os from 'os';
|
|
import net from 'net';
|
|
|
|
export const loopbackList = new net.BlockList();
|
|
loopbackList.addSubnet('127.0.0.0', 8);
|
|
loopbackList.addAddress('::1', 'ipv6');
|
|
|
|
const unusableList = new net.BlockList();
|
|
|
|
// link local
|
|
unusableList.addSubnet('169.254.0.0', 16);
|
|
unusableList.addSubnet('fe80::', 64, 'ipv6');
|
|
|
|
// cg nat
|
|
unusableList.addSubnet('100.64.0.0', 10);
|
|
|
|
// documentation and testing
|
|
unusableList.addSubnet('192.0.2.0', 24);
|
|
unusableList.addSubnet('198.51.100.0', 24);
|
|
unusableList.addSubnet('203.0.113.0', 24);
|
|
|
|
// reserved
|
|
unusableList.addSubnet('0.0.0.0', 8);
|
|
unusableList.addSubnet('240.0.0.0', 4);
|
|
|
|
// benchmarking
|
|
unusableList.addSubnet('198.18.0.0', 15);
|
|
|
|
const privateList = new net.BlockList();
|
|
privateList.addSubnet('10.0.0.0', 8);
|
|
privateList.addSubnet('172.16.0.0', 12);
|
|
privateList.addSubnet('192.168.0.0', 16);
|
|
privateList.addSubnet('fc00::', 7, 'ipv6');
|
|
|
|
|
|
export function isIPv4EmbeddedIPv6(address: string) {
|
|
// this is valid ipv6 address with ipv4 embedded
|
|
// ::ffff:10.0.0.1
|
|
return net.isIPv6(address) && address.startsWith('::ffff:');
|
|
}
|
|
|
|
export function removeIPv4EmbeddedIPv6(address: string) {
|
|
if (isIPv4EmbeddedIPv6(address))
|
|
return address.slice(7);
|
|
return address;
|
|
}
|
|
|
|
function isUsableNetworkAddress(address: string) {
|
|
if (!address)
|
|
return false;
|
|
try {
|
|
address = removeIPv4EmbeddedIPv6(address);
|
|
|
|
const type = net.isIPv6(address) ? 'ipv6' : 'ipv4';
|
|
|
|
// ipv6 addresses are "usable" in the context of scrypted if they are public.
|
|
if (type === 'ipv6' && privateList.check(address, type))
|
|
return false;
|
|
|
|
return !unusableList.check(address, type) && !loopbackList.check(address, type);
|
|
}
|
|
catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export function getUsableNetworkAddresses() {
|
|
const nis = os.networkInterfaces();
|
|
|
|
const getUsable = (family: string | number) => {
|
|
const usable = Object.values(nis)
|
|
.flat()
|
|
.filter((details) => details.family === family)
|
|
.filter(details => isUsableNetworkAddress(details.address));
|
|
return usable;
|
|
}
|
|
|
|
const ipv4 = getUsable('IPv4');
|
|
const ipv6 = getUsable('IPv6');
|
|
|
|
// ipv6 generates temporary per connection ips that we want to filter out.
|
|
|
|
// 2001:abc:def::7b0
|
|
const fixedAddresses = ipv6.filter(details => details.address.includes('::'));
|
|
const fixedRanges = fixedAddresses.map(details => {
|
|
const block = new net.BlockList();
|
|
const cidr = parseInt(details.address.split('/')[1]) || 1;
|
|
block.addSubnet(details.address, cidr, 'ipv6');
|
|
return block;
|
|
});
|
|
|
|
// 2001:abc:def:0:dc:28a7:261b:9324
|
|
const fixedFiltered = ipv6.filter(details => {
|
|
for (const block of fixedRanges) {
|
|
if (block.check(details.address, 'ipv6'))
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
|
|
return [
|
|
...ipv4.map(details => details.address),
|
|
...fixedAddresses.map(details => details.address),
|
|
...fixedFiltered.map(details => details.address),
|
|
];
|
|
}
|