fix(backend): Serve valid headers for HSTS and HSTS preload
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
This commit is contained in:
parent
ec060b7a14
commit
acba0bb54c
9 changed files with 75 additions and 5 deletions
|
@ -174,6 +174,12 @@ id: 'aidx'
|
||||||
# Whether disable HSTS
|
# Whether disable HSTS
|
||||||
#disableHsts: true
|
#disableHsts: true
|
||||||
|
|
||||||
|
# Whether to enable HSTS preload
|
||||||
|
# Read these before enabling:
|
||||||
|
# - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security#preloading_strict_transport_security
|
||||||
|
# - https://hstspreload.org/
|
||||||
|
#hstsPreload: false
|
||||||
|
|
||||||
# Number of worker processes
|
# Number of worker processes
|
||||||
#clusterLimit: 1
|
#clusterLimit: 1
|
||||||
|
|
||||||
|
|
|
@ -168,6 +168,12 @@ id: 'aidx'
|
||||||
# Whether disable HSTS
|
# Whether disable HSTS
|
||||||
#disableHsts: true
|
#disableHsts: true
|
||||||
|
|
||||||
|
# Whether to enable HSTS preload
|
||||||
|
# Read these before enabling:
|
||||||
|
# - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security#preloading_strict_transport_security
|
||||||
|
# - https://hstspreload.org/
|
||||||
|
#hstsPreload: false
|
||||||
|
|
||||||
# Number of worker processes
|
# Number of worker processes
|
||||||
#clusterLimit: 1
|
#clusterLimit: 1
|
||||||
|
|
||||||
|
|
|
@ -250,6 +250,12 @@ id: 'aidx'
|
||||||
# Whether disable HSTS
|
# Whether disable HSTS
|
||||||
#disableHsts: true
|
#disableHsts: true
|
||||||
|
|
||||||
|
# Whether to enable HSTS preload
|
||||||
|
# Read these before enabling:
|
||||||
|
# - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security#preloading_strict_transport_security
|
||||||
|
# - https://hstspreload.org/
|
||||||
|
#hstsPreload: false
|
||||||
|
|
||||||
# Number of worker processes
|
# Number of worker processes
|
||||||
#clusterLimit: 1
|
#clusterLimit: 1
|
||||||
|
|
||||||
|
|
|
@ -161,6 +161,12 @@ id: 'aidx'
|
||||||
# Whether disable HSTS
|
# Whether disable HSTS
|
||||||
#disableHsts: true
|
#disableHsts: true
|
||||||
|
|
||||||
|
# Whether to enable HSTS preload
|
||||||
|
# Read these before enabling:
|
||||||
|
# - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security#preloading_strict_transport_security
|
||||||
|
# - https://hstspreload.org/
|
||||||
|
#hstsPreload: false
|
||||||
|
|
||||||
# Number of worker processes
|
# Number of worker processes
|
||||||
#clusterLimit: 1
|
#clusterLimit: 1
|
||||||
|
|
||||||
|
|
|
@ -182,6 +182,12 @@ id: "aidx"
|
||||||
# Whether disable HSTS
|
# Whether disable HSTS
|
||||||
#disableHsts: true
|
#disableHsts: true
|
||||||
|
|
||||||
|
# Whether to enable HSTS preload
|
||||||
|
# Read these before enabling:
|
||||||
|
# - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security#preloading_strict_transport_security
|
||||||
|
# - https://hstspreload.org/
|
||||||
|
#hstsPreload: false
|
||||||
|
|
||||||
# Number of worker processes
|
# Number of worker processes
|
||||||
#clusterLimit: 1
|
#clusterLimit: 1
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ type Source = {
|
||||||
socket?: string;
|
socket?: string;
|
||||||
chmodSocket?: string;
|
chmodSocket?: string;
|
||||||
disableHsts?: boolean;
|
disableHsts?: boolean;
|
||||||
|
hstsPreload?: boolean;
|
||||||
db: {
|
db: {
|
||||||
host: string;
|
host: string;
|
||||||
port: number;
|
port: number;
|
||||||
|
@ -107,6 +108,7 @@ export type Config = {
|
||||||
socket: string | undefined;
|
socket: string | undefined;
|
||||||
chmodSocket: string | undefined;
|
chmodSocket: string | undefined;
|
||||||
disableHsts: boolean | undefined;
|
disableHsts: boolean | undefined;
|
||||||
|
hstsPreload: boolean | undefined;
|
||||||
db: {
|
db: {
|
||||||
host: string;
|
host: string;
|
||||||
port: number;
|
port: number;
|
||||||
|
@ -241,6 +243,7 @@ export function loadConfig(): Config {
|
||||||
socket: config.socket,
|
socket: config.socket,
|
||||||
chmodSocket: config.chmodSocket,
|
chmodSocket: config.chmodSocket,
|
||||||
disableHsts: config.disableHsts,
|
disableHsts: config.disableHsts,
|
||||||
|
hstsPreload: config.hstsPreload ?? false,
|
||||||
host,
|
host,
|
||||||
hostname,
|
hostname,
|
||||||
scheme,
|
scheme,
|
||||||
|
|
|
@ -31,6 +31,7 @@ import { HealthServerService } from './HealthServerService.js';
|
||||||
import { ClientServerService } from './web/ClientServerService.js';
|
import { ClientServerService } from './web/ClientServerService.js';
|
||||||
import { OpenApiServerService } from './api/openapi/OpenApiServerService.js';
|
import { OpenApiServerService } from './api/openapi/OpenApiServerService.js';
|
||||||
import { OAuth2ProviderService } from './oauth/OAuth2ProviderService.js';
|
import { OAuth2ProviderService } from './oauth/OAuth2ProviderService.js';
|
||||||
|
import { makeHstsHook } from './hsts.js';
|
||||||
|
|
||||||
const _dirname = fileURLToPath(new URL('.', import.meta.url));
|
const _dirname = fileURLToPath(new URL('.', import.meta.url));
|
||||||
|
|
||||||
|
@ -81,12 +82,10 @@ export class ServerService implements OnApplicationShutdown {
|
||||||
this.#fastify = fastify;
|
this.#fastify = fastify;
|
||||||
|
|
||||||
// HSTS
|
// HSTS
|
||||||
// 6months (15552000sec)
|
|
||||||
if (this.config.url.startsWith('https') && !this.config.disableHsts) {
|
if (this.config.url.startsWith('https') && !this.config.disableHsts) {
|
||||||
fastify.addHook('onRequest', (request, reply, done) => {
|
const preload = this.config.hstsPreload;
|
||||||
reply.header('strict-transport-security', 'max-age=15552000; preload');
|
const host = new URL(this.config.url).host;
|
||||||
done();
|
fastify.addHook('onRequest', makeHstsHook(host, preload));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register raw-body parser for ActivityPub HTTP signature validation.
|
// Register raw-body parser for ActivityPub HTTP signature validation.
|
||||||
|
|
30
packages/backend/src/server/hsts.ts
Normal file
30
packages/backend/src/server/hsts.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { onRequestHookHandler } from "fastify";
|
||||||
|
|
||||||
|
// 6months (15552000sec) by default, 1year (31536000sec) if preload is enabled
|
||||||
|
export function makeHstsHook(host: string, preload: boolean = false): onRequestHookHandler {
|
||||||
|
if (preload) {
|
||||||
|
return (request, reply, done) => {
|
||||||
|
// we must permanent redirect http to https for preload to be eligible
|
||||||
|
// however we do not want to do this if a reverse proxy is detected
|
||||||
|
if (
|
||||||
|
(request.host === host || request.hostname === host) &&
|
||||||
|
(request.headers['x-forwarded-proto'] ?? request.protocol) === 'http') {
|
||||||
|
reply.redirect(`https://${request.hostname}${request.url}`, 301);
|
||||||
|
} else {
|
||||||
|
// 1 year is mandatory for preload
|
||||||
|
reply.header('strict-transport-security', 'max-age=31536000; includeSubDomains; preload');
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return (request, reply, done) => {
|
||||||
|
reply.header('strict-transport-security', 'max-age=15552000');
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,6 +52,7 @@ import { FeedService } from './FeedService.js';
|
||||||
import { UrlPreviewService } from './UrlPreviewService.js';
|
import { UrlPreviewService } from './UrlPreviewService.js';
|
||||||
import { ClientLoggerService } from './ClientLoggerService.js';
|
import { ClientLoggerService } from './ClientLoggerService.js';
|
||||||
import type { FastifyInstance, FastifyPluginOptions, FastifyReply } from 'fastify';
|
import type { FastifyInstance, FastifyPluginOptions, FastifyReply } from 'fastify';
|
||||||
|
import { makeHstsHook } from '../hsts.js';
|
||||||
|
|
||||||
const _filename = fileURLToPath(import.meta.url);
|
const _filename = fileURLToPath(import.meta.url);
|
||||||
const _dirname = dirname(_filename);
|
const _dirname = dirname(_filename);
|
||||||
|
@ -207,6 +208,13 @@ export class ClientServerService {
|
||||||
//#region Bull Dashboard
|
//#region Bull Dashboard
|
||||||
const bullBoardPath = '/queue';
|
const bullBoardPath = '/queue';
|
||||||
|
|
||||||
|
// HSTS
|
||||||
|
if (this.config.url.startsWith('https') && !this.config.disableHsts) {
|
||||||
|
const preload = this.config.hstsPreload;
|
||||||
|
const host = new URL(this.config.url).host;
|
||||||
|
fastify.addHook('onRequest', makeHstsHook(host, preload));
|
||||||
|
}
|
||||||
|
|
||||||
// Authenticate
|
// Authenticate
|
||||||
fastify.addHook('onRequest', async (request, reply) => {
|
fastify.addHook('onRequest', async (request, reply) => {
|
||||||
if (request.routeOptions.url == null) {
|
if (request.routeOptions.url == null) {
|
||||||
|
|
Loading…
Reference in a new issue