Перейти до змісту

Про HTTPS

🌐 Переклад ШІ та людьми

Цей переклад виконано ШІ під керівництвом людей. 🤝

Можливі помилки через неправильне розуміння початкового змісту або неприродні формулювання тощо. 🤖

Ви можете покращити цей переклад, допомігши нам краще спрямовувати AI LLM.

Англійська версія

Легко припустити, що HTTPS - це щось, що просто «увімкнено» або ні.

Але все значно складніше.

Порада

Якщо ви поспішаєте або це неважливо для вас, переходьте до наступних розділів для покрокових інструкцій із налаштування всього різними техніками.

Щоб вивчити основи HTTPS з точки зору споживача, перегляньте https://howhttps.works/.

Тепер, з точки зору розробника, ось кілька речей, які варто пам'ятати, розмірковуючи про HTTPS:

  • Для HTTPS сервер має мати «сертифікати», видані третьою стороною.
    • Насправді ці сертифікати «отримуються» у третьої сторони, а не «генеруються».
  • Сертифікати мають строк дії.
    • Їхній строк дії спливає.
    • І тоді їх потрібно поновити, знову отримавши у третьої сторони.
  • Шифрування з'єднання відбувається на рівні TCP.
    • Це один шар нижче від HTTP.
    • Тож обробка сертифіката та шифрування виконується до HTTP.
  • TCP не знає про «домени». Лише про IP-адреси.
    • Інформація про конкретний домен, який запитується, міститься в даних HTTP.
  • Сертифікати HTTPS «засвідчують» певний домен, але протокол і шифрування працюють на рівні TCP, до того як відомо, з яким доменом маємо справу.
  • Типово це означало б, що на одну IP-адресу можна мати лише один сертифікат HTTPS.
    • Неважливо, наскільки великий ваш сервер або наскільки малий кожен застосунок на ньому.
    • Однак для цього є рішення.
  • Є розширення протоколу TLS (який обробляє шифрування на рівні TCP, до HTTP), що називається SNI.
    • Це розширення SNI дозволяє одному серверу (з однією IP-адресою) мати кілька сертифікатів HTTPS і обслуговувати кілька доменів/застосунків по HTTPS.
    • Щоб це працювало, один-єдиний компонент (програма), що працює на сервері та слухає публічну IP-адресу, має мати всі сертифікати HTTPS на сервері.
  • Після отримання захищеного з'єднання протокол обміну все ще HTTP.
    • Вміст зашифровано, хоча він надсилається протоколом HTTP.

Поширена практика мати одну програму/HTTP-сервер, що працює на сервері (машині, хості тощо) і керує всіма частинами HTTPS: приймає зашифровані HTTPS-запити, надсилає розшифровані HTTP-запити до фактичного HTTP-застосунку, що працює на тому ж сервері (у нашому випадку застосунок FastAPI), отримує HTTP-відповідь від застосунку, шифрує її за допомогою відповідного сертифіката HTTPS і надсилає її назад клієнту через HTTPS. Такий сервер часто називають TLS Termination Proxy.

Деякі варіанти, які ви можете використати як TLS Termination Proxy:

  • Traefik (також може виконувати поновлення сертифікатів)
  • Caddy (також може виконувати поновлення сертифікатів)
  • Nginx
  • HAProxy

Let's Encrypt

До Let's Encrypt ці сертифікати HTTPS продавалися довіреними третіми сторонами.

Процес отримання одного з таких сертифікатів був громіздким, вимагав чимало паперової роботи, а самі сертифікати були доволі дорогими.

Але потім з'явився проєкт Let's Encrypt.

Це проєкт Linux Foundation. Він надає сертифікати HTTPS безкоштовно, в автоматизований спосіб. Ці сертифікати використовують усі стандартні криптографічні механізми безпеки і є короткостроковими (близько 3 місяців), тож безпека насправді краща завдяки зменшеній тривалості життя.

Домени безпечно перевіряються, а сертифікати генеруються автоматично. Це також дозволяє автоматизувати поновлення цих сертифікатів.

Ідея полягає в автоматизації отримання та поновлення цих сертифікатів, щоб ви могли мати безпечний HTTPS безкоштовно та назавжди.

HTTPS для розробників

Ось приклад того, як може виглядати HTTPS API, крок за кроком, зосереджуючись переважно на ідеях, важливих для розробників.

Доменне ім'я

Ймовірно, все почнеться з того, що ви придбаєте якесь доменне ім'я. Потім ви налаштуєте його на сервері DNS (можливо, у вашого ж хмарного провайдера).

Ви, скоріш за все, отримаєте хмарний сервер (віртуальну машину) або щось подібне, і він матиме фіксовану публічну IP-адресу.

На сервері(ах) DNS ви налаштуєте запис («A record»), щоб спрямувати ваш домен на публічну IP-адресу вашого сервера.

Ймовірно, ви зробите це лише один раз, уперше, коли все налаштовуватимете.

Порада

Частина про доменне ім'я значно раніше за HTTPS, але оскільки все залежить від домену та IP-адреси, варто згадати це тут.

DNS

Тепер зосередьмося на всіх власне частинах HTTPS.

Спочатку браузер звернеться до серверів DNS, щоб дізнатися, яка IP-адреса для домену, у цьому випадку someapp.example.com.

Сервери DNS повідомлять браузеру використати конкретну IP-адресу. Це буде публічна IP-адреса, яку використовує ваш сервер і яку ви налаштували на серверах DNS.

Початок TLS рукостискання

Потім браузер зв'яжеться з цією IP-адресою на порту 443 (порт HTTPS).

Перша частина комунікації - це просто встановлення з'єднання між клієнтом і сервером та узгодження криптографічних ключів тощо.

Ця взаємодія між клієнтом і сервером для встановлення з'єднання TLS називається TLS рукостисканням.

TLS із розширенням SNI

Лише один процес на сервері може слухати конкретний порт на конкретній IP-адресі. Інші процеси можуть слухати інші порти на тій самій IP-адресі, але лише один для кожної комбінації IP-адреси та порту.

TLS (HTTPS) за замовчуванням використовує конкретний порт 443. Отже, це порт, який нам потрібен.

Оскільки лише один процес може слухати цей порт, процесом, що робитиме це, буде TLS Termination Proxy.

TLS Termination Proxy матиме доступ до одного або кількох сертифікатів TLS (сертифікатів HTTPS).

Використовуючи обговорене вище розширення SNI, TLS Termination Proxy перевірить, який із наявних сертифікатів TLS (HTTPS) слід використати для цього з'єднання, обравши той, що відповідає домену, очікуваному клієнтом.

У цьому випадку він використає сертифікат для someapp.example.com.

Клієнт уже довіряє сутності, яка видала цей сертифікат TLS (у цьому випадку Let's Encrypt, але про це згодом), тож він може перевірити, що сертифікат дійсний.

Потім, використовуючи сертифікат, клієнт і TLS Termination Proxy узгоджують, як шифрувати решту TCP-комунікації. На цьому частина TLS рукостискання завершується.

Після цього клієнт і сервер мають зашифроване TCP-з'єднання - саме це надає TLS. І тоді вони можуть використати це з'єднання, щоб почати власне HTTP-комунікацію.

І це і є HTTPS: це звичайний HTTP усередині захищеного TLS-з'єднання замість чистого (незашифрованого) TCP-з'єднання.

Порада

Зверніть увагу, що шифрування комунікації відбувається на рівні TCP, а не на рівні HTTP.

HTTPS-запит

Тепер, коли клієнт і сервер (конкретно браузер і TLS Termination Proxy) мають зашифроване TCP-з'єднання, вони можуть почати HTTP-комунікацію.

Отже, клієнт надсилає HTTPS-запит. Це просто HTTP-запит через зашифроване TLS-з'єднання.

Розшифрування запиту

TLS Termination Proxy використає узгоджене шифрування, щоб розшифрувати запит, і передасть звичайний (розшифрований) HTTP-запит процесу, що запускає застосунок (наприклад, процесу з Uvicorn, який запускає застосунок FastAPI).

HTTP-відповідь

Застосунок обробить запит і надішле звичайну (незашифровану) HTTP-відповідь TLS Termination Proxy.

HTTPS-відповідь

Потім TLS Termination Proxy зашифрує відповідь, використовуючи попередньо узгоджену криптографію (що почалася із сертифіката для someapp.example.com), і надішле її назад у браузер.

Далі браузер перевірить, що відповідь дійсна й зашифрована правильним криптографічним ключем тощо. Потім він розшифрує відповідь і обробить її.

Клієнт (браузер) знатиме, що відповідь надходить від правильного сервера, тому що використовується узгоджена раніше криптографія з використанням сертифіката HTTPS.

Кілька застосунків

На тому самому сервері (або серверах) може бути кілька застосунків, наприклад інші програми API або база даних.

Лише один процес може обробляти конкретну IP-адресу і порт (TLS Termination Proxy у нашому прикладі), але інші застосунки/процеси також можуть працювати на сервері(ах), доки вони не намагаються використати ту саму комбінацію публічної IP-адреси й порту.

Таким чином, TLS Termination Proxy може обробляти HTTPS і сертифікати для кількох доменів, для кількох застосунків, а потім передавати запити до відповідного застосунку в кожному випадку.

Поновлення сертифіката

У певний момент у майбутньому строк дії кожного сертифіката спливе (приблизно через 3 місяці після його отримання).

Потім інша програма (в деяких випадках це інша програма, а в деяких - той самий TLS Termination Proxy) зв'яжеться з Let's Encrypt і поновить сертифікат(и).

Сертифікати TLS пов'язані з доменним іменем, а не з IP-адресою.

Тому, щоб поновити сертифікати, програма поновлення має довести авторитету (Let's Encrypt), що вона справді «володіє» і контролює цей домен.

Щоб зробити це й задовольнити різні потреби застосунків, є кілька способів. Деякі популярні:

  • Змінити деякі записи DNS.
    • Для цього програма поновлення має підтримувати API провайдера DNS, тож залежно від того, якого провайдера DNS ви використовуєте, це може бути або не бути варіантом.
  • Запуститися як сервер (принаймні під час процесу отримання сертифіката) на публічній IP-адресі, пов'язаній із доменом.
    • Як ми казали вище, лише один процес може слухати конкретну IP-адресу та порт.
    • Це одна з причин, чому дуже зручно, коли той самий TLS Termination Proxy також займається процесом поновлення сертифікатів.
    • Інакше вам, можливо, доведеться на мить зупинити TLS Termination Proxy, запустити програму поновлення, щоб отримати сертифікати, потім налаштувати їх у TLS Termination Proxy і перезапустити TLS Termination Proxy. Це неідеально, оскільки ваші застосунки будуть недоступні під час вимкнення TLS Termination Proxy.

Увесь цей процес поновлення, паралельно з обслуговуванням застосунку, - одна з головних причин, чому ви можете захотіти мати окрему систему для обробки HTTPS за допомогою TLS Termination Proxy замість того, щоб просто використовувати сертифікати TLS безпосередньо з сервером застосунку (наприклад, Uvicorn).

Направлені заголовки проксі

Коли ви використовуєте проксі для обробки HTTPS, ваш сервер застосунку (наприклад, Uvicorn через FastAPI CLI) нічого не знає про процес HTTPS, він спілкується звичайним HTTP із TLS Termination Proxy.

Цей проксі зазвичай динамічно встановлює деякі HTTP-заголовки перед передачею запиту серверу застосунку, щоб дати йому знати, що запит направляється проксі.

Технічні деталі

Заголовки проксі:

Втім, оскільки сервер застосунку не знає, що він стоїть за довіреним проксі, за замовчуванням він не довірятиме цим заголовкам.

Але ви можете налаштувати сервер застосунку, щоб довіряти направленим заголовкам, надісланим проксі. Якщо ви використовуєте FastAPI CLI, ви можете скористатися курсивною опцією CLI --forwarded-allow-ips, щоб повідомити, з яких IP-адрес слід довіряти цим направленим заголовкам.

Наприклад, якщо сервер застосунку отримує комунікацію лише від довіреного проксі, ви можете встановити --forwarded-allow-ips="*", щоб довіряти всім вхідним IP-адресам, оскільки він отримуватиме запити лише з тієї IP-адреси, яку використовує проксі.

Так застосунок зможе знати свою публічну URL-адресу, чи використовує він HTTPS, домен тощо.

Це буде корисно, наприклад, для коректної обробки перенаправлень.

Порада

Ви можете дізнатися більше про це в документації За проксі - Увімкнути направлені заголовки проксі

Підсумок

Наявність HTTPS дуже важлива і в більшості випадків критична. Більшість зусиль, які вам як розробнику доведеться докласти навколо HTTPS, полягають лише в розумінні цих концепцій і того, як вони працюють.

Але як тільки ви знаєте базову інформацію про HTTPS для розробників, ви можете легко комбінувати й налаштовувати різні інструменти, щоб керувати всім просто.

У деяких наступних розділах я покажу кілька конкретних прикладів налаштування HTTPS для застосунків FastAPI. 🔒