Block subdomains of blocked hosts
This commit is contained in:
parent
afce8f04ab
commit
d9b7219404
|
@ -0,0 +1,15 @@
|
|||
import { fetchMeta } from '@/misc/fetch-meta.js';
|
||||
import { Instance } from '@/models/entities/instance.js';
|
||||
import { Meta } from '@/models/entities/meta.js';
|
||||
|
||||
/**
|
||||
* Returns whether a specific host (punycoded) should be blocked.
|
||||
*
|
||||
* @param host punycoded instance host
|
||||
* @param meta a resolved Meta table
|
||||
* @returns whether the given host should be blocked
|
||||
*/
|
||||
export async function shouldBlockInstance(host: Instance['host'], meta?: Meta): Promise<boolean> {
|
||||
const { blockedHosts } = meta ?? await fetchMeta();
|
||||
return blockedHosts.some(blockedHost => host === blockedHost || host.endsWith('.' + blockedHost));
|
||||
}
|
|
@ -3,6 +3,7 @@ import { fetchMeta } from '@/misc/fetch-meta.js';
|
|||
import { Instances } from '@/models/index.js';
|
||||
import { Instance } from '@/models/entities/instance.js';
|
||||
import { DAY } from '@/const.js';
|
||||
import { shouldBlockInstance } from './should-block-instance';
|
||||
|
||||
// Threshold from last contact after which an instance will be considered
|
||||
// "dead" and should no longer get activities delivered to it.
|
||||
|
@ -14,11 +15,12 @@ const deadThreshold = 7 * DAY;
|
|||
* @param hosts array of punycoded instance hosts
|
||||
* @returns array of punycoed instance hosts that should be skipped (subset of hosts parameter)
|
||||
*/
|
||||
export async function skippedInstances(hosts: Array<Instace['host']>): Array<Instance['host']> {
|
||||
export async function skippedInstances(hosts: Instance['host'][]): Promise<Instance['host'][]> {
|
||||
// first check for blocked instances since that info may already be in memory
|
||||
const { blockedHosts } = await fetchMeta();
|
||||
|
||||
const skipped = hosts.filter(host => blockedHosts.includes(host));
|
||||
const meta = await fetchMeta();
|
||||
const shouldSkip = await Promise.all(hosts.map(host => shouldBlockInstance(host, meta)));
|
||||
const skipped = hosts.filter((_, i) => shouldSkip[i]);
|
||||
|
||||
// if possible return early and skip accessing the database
|
||||
if (skipped.length === hosts.length) return hosts;
|
||||
|
||||
|
@ -47,7 +49,7 @@ export async function skippedInstances(hosts: Array<Instace['host']>): Array<Ins
|
|||
* @param host punycoded instance host
|
||||
* @returns whether the given host should be skipped
|
||||
*/
|
||||
export async function shouldSkipInstance(host: Instance['host']): boolean {
|
||||
export async function shouldSkipInstance(host: Instance['host']): Promise<boolean> {
|
||||
const skipped = await skippedInstances([host]);
|
||||
return skipped.length > 0;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import { db } from '@/db/postgre.js';
|
|||
import { Instance } from '@/models/entities/instance.js';
|
||||
import { Packed } from '@/misc/schema.js';
|
||||
import { fetchMeta } from '@/misc/fetch-meta.js';
|
||||
import { shouldBlockInstance } from '@/misc/should-block-instance';
|
||||
|
||||
export const InstanceRepository = db.getRepository(Instance).extend({
|
||||
async pack(
|
||||
|
@ -20,7 +21,7 @@ export const InstanceRepository = db.getRepository(Instance).extend({
|
|||
lastCommunicatedAt: instance.lastCommunicatedAt.toISOString(),
|
||||
isNotResponding: instance.isNotResponding,
|
||||
isSuspended: instance.isSuspended,
|
||||
isBlocked: meta.blockedHosts.includes(instance.host),
|
||||
isBlocked: await shouldBlockInstance(instance.host),
|
||||
softwareName: instance.softwareName,
|
||||
softwareVersion: instance.softwareVersion,
|
||||
openRegistrations: instance.openRegistrations,
|
||||
|
|
|
@ -17,6 +17,7 @@ import { LdSignature } from '@/remote/activitypub/misc/ld-signature.js';
|
|||
import { StatusError } from '@/misc/fetch.js';
|
||||
import { CacheableRemoteUser } from '@/models/entities/user.js';
|
||||
import { UserPublickey } from '@/models/entities/user-publickey.js';
|
||||
import { shouldBlockInstance } from '@/misc/should-block-instance.js';
|
||||
|
||||
const logger = new Logger('inbox');
|
||||
|
||||
|
@ -34,7 +35,7 @@ export default async (job: Bull.Job<InboxJobData>): Promise<string> => {
|
|||
|
||||
// interrupt if blocked
|
||||
const meta = await fetchMeta();
|
||||
if (meta.blockedHosts.includes(host)) {
|
||||
if (await shouldBlockInstance(host, meta)) {
|
||||
return `Blocked request: ${host}`;
|
||||
}
|
||||
|
||||
|
@ -123,7 +124,7 @@ export default async (job: Bull.Job<InboxJobData>): Promise<string> => {
|
|||
|
||||
// ブロックしてたら中断
|
||||
const ldHost = extractDbHost(authUser.user.uri);
|
||||
if (meta.blockedHosts.includes(ldHost)) {
|
||||
if (await shouldBlockInstance(ldHost, meta)) {
|
||||
return `Blocked request: ${ldHost}`;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -6,6 +6,7 @@ import { URL } from 'url';
|
|||
import { toPuny } from '@/misc/convert-host.js';
|
||||
import DbResolver from '@/remote/activitypub/db-resolver.js';
|
||||
import { getApId } from '@/remote/activitypub/type.js';
|
||||
import { shouldBlockInstance } from '@/misc/should-block-instance';
|
||||
|
||||
|
||||
export default async function checkFetch(req: IncomingMessage): Promise<number> {
|
||||
|
@ -22,7 +23,7 @@ export default async function checkFetch(req: IncomingMessage): Promise<number>
|
|||
const keyId = new URL(signature.keyId);
|
||||
const host = toPuny(keyId.hostname);
|
||||
|
||||
if (meta.blockedHosts.includes(host)) {
|
||||
if (await shouldBlockInstance(host, meta)) {
|
||||
return 403;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,11 +5,11 @@ import { IAnnounce, getApId } from '../../type.js';
|
|||
import { fetchNote, resolveNote } from '../../models/note.js';
|
||||
import { apLogger } from '../../logger.js';
|
||||
import { extractDbHost } from '@/misc/convert-host.js';
|
||||
import { fetchMeta } from '@/misc/fetch-meta.js';
|
||||
import { getApLock } from '@/misc/app-lock.js';
|
||||
import { parseAudience } from '../../audience.js';
|
||||
import { StatusError } from '@/misc/fetch.js';
|
||||
import { Notes } from '@/models/index.js';
|
||||
import { shouldBlockInstance } from '@/misc/should-block-instance.js';
|
||||
|
||||
const logger = apLogger;
|
||||
|
||||
|
@ -24,8 +24,7 @@ export default async function(resolver: Resolver, actor: CacheableRemoteUser, ac
|
|||
}
|
||||
|
||||
// Interrupt if you block the announcement destination
|
||||
const meta = await fetchMeta();
|
||||
if (meta.blockedHosts.includes(extractDbHost(uri))) return;
|
||||
if (await shouldBlockInstance(extractDbHost(uri))) return;
|
||||
|
||||
const unlock = await getApLock(uri);
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import { parseAudience } from '../audience.js';
|
|||
import { extractApMentions } from './mention.js';
|
||||
import DbResolver from '../db-resolver.js';
|
||||
import { StatusError } from '@/misc/fetch.js';
|
||||
import { shouldBlockInstance } from '@/misc/should-block-instance.js';
|
||||
|
||||
const logger = apLogger;
|
||||
|
||||
|
@ -275,8 +276,7 @@ export async function resolveNote(value: string | IObject, resolver?: Resolver):
|
|||
if (uri == null) throw new Error('missing uri');
|
||||
|
||||
// Abort if origin host is blocked
|
||||
const meta = await fetchMeta();
|
||||
if (meta.blockedHosts.includes(extractDbHost(uri))) throw new StatusError('host blocked', 451, `host ${extractDbHost(uri)} is blocked`);
|
||||
if (await shouldBlockInstance(extractDbHost(uri))) throw new StatusError('host blocked', 451, `host ${extractDbHost(uri)} is blocked`);
|
||||
|
||||
const unlock = await getApLock(uri);
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import renderQuestion from '@/remote/activitypub/renderer/question.js';
|
|||
import renderCreate from '@/remote/activitypub/renderer/create.js';
|
||||
import { renderActivity } from '@/remote/activitypub/renderer/index.js';
|
||||
import renderFollow from '@/remote/activitypub/renderer/follow.js';
|
||||
import { shouldBlockInstance } from '@/misc/should-block-instance.js';
|
||||
|
||||
export default class Resolver {
|
||||
private history: Set<string>;
|
||||
|
@ -72,7 +73,7 @@ export default class Resolver {
|
|||
}
|
||||
|
||||
const meta = await fetchMeta();
|
||||
if (meta.blockedHosts.includes(host)) {
|
||||
if (await shouldBlockInstance(host, meta)) {
|
||||
throw new Error('Instance is blocked');
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import { fetchMeta } from '@/misc/fetch-meta.js';
|
|||
import { isActor, isPost, getApId } from '@/remote/activitypub/type.js';
|
||||
import { SchemaType } from '@/misc/schema.js';
|
||||
import { HOUR } from '@/const.js';
|
||||
import { shouldBlockInstance } from '@/misc/should-block-instance.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['federation'],
|
||||
|
@ -92,8 +93,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
*/
|
||||
async function fetchAny(uri: string, me: CacheableLocalUser | null | undefined): Promise<SchemaType<typeof meta['res']> | null> {
|
||||
// Wait if blocked.
|
||||
const fetchedMeta = await fetchMeta();
|
||||
if (fetchedMeta.blockedHosts.includes(extractDbHost(uri))) return null;
|
||||
if (await shouldBlockInstance(extractDbHost(uri))) return null;
|
||||
|
||||
const dbResolver = new DbResolver();
|
||||
|
||||
|
|
Loading…
Reference in New Issue