Как реализовать безопасные заголовки с помощью Cloudflare Workers?

Как реализовать безопасные заголовки с помощью Cloudflare Workers?

Пошаговое руководство по реализации безопасных HTTP-заголовков на веб-сайтах на базе Cloudflare с использованием Cloudflare Workers.

Существует множество способов реализации заголовков ответов HTTP для защиты сайтов от распространенных уязвимостей, таких как CSS, Clickjacking, MIMI sniffing, межсайтовые инъекции и т. д. Это широко распространенная практика, рекомендованная OVASP.

Ранее я уже писал о реализации заголовков на таких веб-серверах, как Apache, Ngink и IIS. Однако, если вы используете Cloudflare для защиты и резервного копирования своих веб-сайтов, вы можете использовать Cloudflare Workers для управления заголовками ответов HTTP.

Cloudflare Workers — это бессерверная платформа, на которой вы можете запускать код JavaScript, C, C++, Rust. Он развернут в каждом дата-центре Cloudflare, которых в мире более 200.

Реализация очень проста и гибка. Это дает вам возможность применять заголовки ко всему сайту, включая поддомен или определенный URI с соответствующим шаблоном, используя Regex.

Для этой демонстрации я буду использовать код Скотта Хелма.

Давайте начнем… ?‍?

  • Скопируйте код worker.js с GitHub и вставьте в редактор скриптов.
const securityHeaders = {
        "Content-Security-Policy": "upgrade-insecure-requests",
        "Strict-Transport-Security": "max-age=1000",
        "X-Xss-Protection": "1; mode=block",
        "X-Frame-Options": "DENY",
        "X-Content-Type-Options": "nosniff",
        "Referrer-Policy": "strict-origin-when-cross-origin"
    },
    sanitiseHeaders = {
        Server: ""
    },
    removeHeaders = [
        "Public-Key-Pins",
        "X-Powered-By",
        "X-AspNet-Version"
    ];

async function addHeaders(req) {
    const response = await fetch(req),
        newHeaders = new Headers(response.headers),
        setHeaders = Object.assign({}, securityHeaders, sanitiseHeaders);

    if (newHeaders.has("Content-Type") && !newHeaders.get("Content-Type").includes("text/html")) {
        return new Response(response.body, {
            status: response.status,
            statusText: response.statusText,
            headers: newHeaders
        });
    }

    Object.keys(setHeaders).forEach(name => newHeaders.set(name, setHeaders[name]));

    removeHeaders.forEach(name => newHeaders.delete(name));

    return new Response(response.body, {
        status: response.status,
        statusText: response.statusText,
        headers: newHeaders
    });
}

addEventListener("fetch", event => event.respondWith(addHeaders(event.request)));

Пока не сохраняйте; вы можете настроить следующие заголовки в соответствии с требованиями.

Content-Security-Policies — если вам нужно применить собственную политику приложений, вы можете сделать это здесь.

Например, если вам нужно получить контент через iFrame на несколько URL-адресов, вы можете воспользоваться преимуществами родительского фрейма, как показано ниже.

"Content-Security-Policy" : "frame-ancestors 'self' gf.dev techblog.co.rs.com",

Это позволит загружать контент с gf.dev, vdzvdz.com и собственного сайта.

X-Frame-Options — вы можете изменить на SAMEORIGIN, если вы собираетесь отображать содержимое вашего сайта на странице того же сайта с помощью iframe.

"X-Frame-Options": "SAMEORIGIN",

Сервер — здесь вы можете очистить заголовок сервера. Ставь что хочешь.

"Server" : "techblog.co.rs Server",

RemoveHeaders — вам нужно удалить некоторые заголовки, чтобы скрыть версии, чтобы уменьшить уязвимость к утечке информации?

Вы можете сделать это здесь.

let removeHeaders = [
	"Public-Key-Pins",
	"X-Powered-By",
	"X-AspNet-Version",
]

Добавление новых заголовков. Если вам нужно передать некоторые пользовательские заголовки в ваши приложения, вы можете добавить их в раздел securitiHeaders, как показано ниже.

let securityHeaders = {
	"Content-Security-Policy" : "frame-ancestors 'self' gf.dev techblog.co.rs.com",
	"Strict-Transport-Security" : "max-age=1000",
	"X-Xss-Protection" : "1; mode=block",
	"X-Frame-Options" : "SAMEORIGIN",
	"X-Content-Type-Options" : "nosniff",
	"Referrer-Policy" : "strict-origin-when-cross-origin",
        "Custom-Header"  : "Success",
}

Когда вы закончите настройку всех необходимых заголовков, назовите работника и нажмите «Сохранить и применить».

Большой! рабочий готов, то нам нужно добавить это на сайт, где вы хотите применить заголовки. Я применю это к своей лаборатории.

  • Перейдите на главную страницу/панель инструментов Cloudflare и выберите местоположение.
  • Перейдите на вкладку Рабочие >> Добавить маршрут.
  • Введите URL-адрес в Маршрут; вы можете применить Regex здесь.
  • Выберите только что созданных воркеров и сохраните

Вот и все; уже через секунду вы заметите, что все заголовки реализованы на сайте.

Вот как это выглядит в Chrome Dev Tools. Вы также можете протестировать заголовок с помощью инструмента HTTP-заголовков.

Я не знаю, почему заголовок сервера не отображается. Думаю, Cloudflare преодолевает это.

Видите ли, вся реализация занимает ~15 минут и не требует простоев или перезапусков, как Apache или Ngink. Если вы планируете развернуть это в рабочей среде, я предлагаю вам сначала протестировать в среде низкого уровня или с помощью маршрута вы можете развернуть его на тестовых страницах, чтобы проверить результаты. Когда вы будете удовлетворены, нажмите куда хотите.

Отлично!

Спасибо Скотту за код.

Поделиться в соцсетях