Compare commits
2 commits
c504091c61
...
c8f8e4c01d
Author | SHA1 | Date | |
---|---|---|---|
|
c8f8e4c01d | ||
6ee8a369b3 |
5 changed files with 62 additions and 23 deletions
|
@ -52,6 +52,7 @@
|
|||
"got": "12.3.1",
|
||||
"hpagent": "0.1.2",
|
||||
"ioredis": "4.28.5",
|
||||
"ipaddr.js": "2.1.0",
|
||||
"ip-cidr": "3.0.10",
|
||||
"is-svg": "4.3.2",
|
||||
"js-yaml": "4.1.0",
|
||||
|
@ -80,7 +81,6 @@
|
|||
"os-utils": "0.0.14",
|
||||
"parse5": "7.0.0",
|
||||
"pg": "8.7.3",
|
||||
"private-ip": "2.3.3",
|
||||
"probe-image-size": "7.2.3",
|
||||
"promise-limit": "2.7.0",
|
||||
"pug": "3.0.2",
|
||||
|
|
|
@ -3,8 +3,6 @@ import * as stream from 'node:stream';
|
|||
import * as util from 'node:util';
|
||||
import chalk from 'chalk';
|
||||
import got, * as Got from 'got';
|
||||
import IPCIDR from 'ip-cidr';
|
||||
import PrivateIp from 'private-ip';
|
||||
import { SECOND, MINUTE } from '@/const.js';
|
||||
import config from '@/config/index.js';
|
||||
import Logger from '@/services/logger.js';
|
||||
|
@ -42,13 +40,6 @@ export async function downloadUrl(url: string, path: string): Promise<void> {
|
|||
limit: 0,
|
||||
},
|
||||
}).on('response', (res: Got.Response) => {
|
||||
if ((process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test') && !config.proxy && res.ip) {
|
||||
if (isPrivateIp(res.ip)) {
|
||||
logger.warn(`Blocked address: ${res.ip}`);
|
||||
req.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
const contentLength = res.headers['content-length'];
|
||||
if (contentLength != null) {
|
||||
const size = Number(contentLength);
|
||||
|
@ -76,14 +67,3 @@ export async function downloadUrl(url: string, path: string): Promise<void> {
|
|||
|
||||
logger.succ(`Download finished: ${chalk.cyan(url)}`);
|
||||
}
|
||||
|
||||
function isPrivateIp(ip: string): boolean {
|
||||
for (const net of config.allowedPrivateNetworks || []) {
|
||||
const cidr = new IPCIDR(net);
|
||||
if (cidr.contains(ip)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return PrivateIp(ip);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import * as dns from 'node:dns';
|
|||
import CacheableLookup from 'cacheable-lookup';
|
||||
import fetch from 'node-fetch';
|
||||
import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';
|
||||
import ipaddr from 'ipaddr.js';
|
||||
import IPCIDR from 'ip-cidr';
|
||||
import { SECOND } from '@/const.js';
|
||||
import config from '@/config/index.js';
|
||||
|
||||
|
@ -101,7 +103,32 @@ const cacheLookup = (host, _2, _3) => {
|
|||
options.hints = dns.V4MAPPED;
|
||||
}
|
||||
|
||||
return cache.lookup(host, options, callback);
|
||||
// callback wrapper that checks whether an IP is private.
|
||||
// Private IPs will not be returned in the first place.
|
||||
const wrapper = (err, address, family) => {
|
||||
// mimics dns.lookup behaviour as if no result was found
|
||||
const fakeErr = new Error("private IP");
|
||||
fakeErr.code = 'ENOTFOUND';
|
||||
|
||||
if (err != null) {
|
||||
return callback(err, address, family);
|
||||
} else if (options.all) {
|
||||
const results = address.filter(({ address, family }) => isPublicIp(address));
|
||||
if (results.length === 0) {
|
||||
return callback(fakeErr);
|
||||
} else {
|
||||
return callback(err, results);
|
||||
}
|
||||
} else {
|
||||
if (isPublicIp(address)) {
|
||||
return callback(err, address, family);
|
||||
} else {
|
||||
return callback(fakeErr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return cache.lookup(host, options, wrapper);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -178,3 +205,27 @@ export class StatusError extends Error {
|
|||
this.isClientError = typeof this.statusCode === 'number' && this.statusCode >= 400 && this.statusCode < 500;
|
||||
}
|
||||
}
|
||||
|
||||
function isPublicIp(ip: string): boolean {
|
||||
for (const net of config.allowedPrivateNetworks || []) {
|
||||
const cidr = new IPCIDR(net);
|
||||
if (cidr.contains(ip)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround because ipaddr.js in the installed version cannot cope
|
||||
// with v4mapped addresses. a fix has been submitted and merged, but a new
|
||||
// version was not yet released.
|
||||
// FIXME: update ipaddr.js and remove workaround
|
||||
ip = ip.replace(/^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i, '$1');
|
||||
|
||||
try {
|
||||
let range = ipaddr.process(ip).range();
|
||||
// only unicast or multicast addresses are allowed by default
|
||||
// this does not include e.g. loopback addresses
|
||||
return ['unicast', 'multicast'].includes(range);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ function groupingAudience(ids: string[], actor: IRemoteUser) {
|
|||
function isPublic(id: string) {
|
||||
return [
|
||||
'https://www.w3.org/ns/activitystreams#Public',
|
||||
'as#Public',
|
||||
'as:Public',
|
||||
'Public',
|
||||
].includes(id);
|
||||
}
|
||||
|
|
|
@ -3697,6 +3697,7 @@ __metadata:
|
|||
hpagent: 0.1.2
|
||||
ioredis: 4.28.5
|
||||
ip-cidr: 3.0.10
|
||||
ipaddr.js: 2.1.0
|
||||
is-svg: 4.3.2
|
||||
js-yaml: 4.1.0
|
||||
jsdom: 20.0.0
|
||||
|
@ -9087,6 +9088,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ipaddr.js@npm:2.1.0":
|
||||
version: 2.1.0
|
||||
resolution: "ipaddr.js@npm:2.1.0"
|
||||
checksum: 807a054f2bd720c4d97ee479d6c9e865c233bea21f139fb8dabd5a35c4226d2621c42e07b4ad94ff3f82add926a607d8d9d37c625ad0319f0e08f9f2bd1968e2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ipaddr.js@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "ipaddr.js@npm:2.0.1"
|
||||
|
|
Loading…
Add table
Reference in a new issue