Перейти к содержимому

HTTPS и обратный прокси-сервер ​

Новая установка слушает 127.0.0.1:8080 по обычному HTTP. Достучаться до неё могут только программы на самом сервере. Прежде чем клиенты начнут подключаться с других компьютеров, поставьте перед ней HTTPS. Ключи, пароли и ссылки на скачивание передаются в запросах: никогда не отправляйте их по обычному HTTP между компьютерами.

Выбор способа ​

Встроенный TLSОбратный прокси-сервер
УстановкиСлужбы Windows и Linux (нативные). Не ComposeВсе; для Compose — единственный способ
НастройкаОдна команда arkvory configure с откатомНастройка прокси-сервера плюс ARKVORY_TRUSTED_PROXIES в Arkvory
ПортПорт API, по умолчанию 8080Любой, например 443
Обновление сертификатаAPI сам читает обновлённые файлыВыполняет прокси-сервер
Клиентские сертификаты (mTLS)Не поддерживаютсяВозможны в прокси-сервере

Перед началом ​

  • Получите сертификат для имени, которое используют клиенты, у удостоверяющего центра, которому клиенты доверяют, например с помощью certbot, win-acme или корпоративного центра. Вам нужны сертификат с цепочкой и закрытый ключ, оба в виде файлов PEM. У ключа не должно быть пароля.
  • Создайте DNS-имя, которое указывает на сервер.
  • Откройте в брандмауэре только порт HTTPS и только для сетей ваших клиентов. Порт базы данных (54329 или 45329-45348) не открывайте никогда.

Встроенный TLS ​

Подготовка файлов ​

Файлы должны соответствовать этим правилам. Команда проверяет все их, прежде чем что-либо изменить.

  • Пути абсолютные.
  • Каждый файл — файл PEM размером не более 1 МиБ. В файле сертификата лежит сертификат, а за ним — цепочка.
  • Ключ — незашифрованный закрытый ключ PEM, соответствующий сертификату.
  • Срок действия сертификата не истёк.
  • Учётная запись службы может читать оба файла: arkvory в Linux, LocalService в Windows.

Arkvory ссылается на файлы и не копирует их. Разместите их там, где они останутся при обновлении. В Linux — не в /home: юниты его не видят. Каталоги некоторых средств работы с сертификатами читает только root; копируйте обновлённые файлы в каталог, который может читать группа службы, например с помощью хука обновления. Пример для Linux:

bash
sudo install -d -m 0750 -o root -g arkvory /etc/arkvory/tls
sudo install -m 0644 -o root -g arkvory fullchain.pem /etc/arkvory/tls/fullchain.pem
sudo install -m 0640 -o root -g arkvory privkey.pem /etc/arkvory/tls/privkey.pem

В Windows поместите файлы в папку, которую может читать LocalService, и разрешите читать ключ только SYSTEM, группе «Администраторы» и LocalService.

Включение встроенного TLS ​

  1. Выполните команду с путями и адресом, который нужно слушать. 0.0.0.0 слушает все интерфейсы IPv4, :: — все интерфейсы, либо укажите адрес одного интерфейса.

    bash
    sudo arkvory configure --root /opt/proanima-arkvory \
      --tls-cert /etc/arkvory/tls/fullchain.pem \
      --tls-key /etc/arkvory/tls/privkey.pem \
      --listen-host 0.0.0.0
    powershell
    & 'C:\Program Files\ProAnima\Arkvory\arkvory.ps1' configure --root C:\ProgramData\ProAnima\Arkvory `
      --tls-cert C:\ProgramData\ProAnima\Arkvory\tls\fullchain.pem `
      --tls-key C:\ProgramData\ProAnima\Arkvory\tls\privkey.pem `
      --listen-host 0.0.0.0

    Команда записывает ARKVORY_TLS_CERT_FILE, ARKVORY_TLS_KEY_FILE и ARKVORY_HOST в config/runtime.json, перезапускает службы и ждёт, пока API ответит на проверку готовности по HTTPS. Проверка принимает только настроенный сертификат. В случае успеха команда печатает день окончания срока действия сертификата. Если что-то не получается, она восстанавливает прежний runtime.json, перезапускает службы с ним и сообщает причину.

  2. Откройте порт API в брандмауэре для сетей ваших клиентов.

  3. Проверьте с клиентского компьютера. Порт остаётся 8080, пока вы не измените ARKVORY_PORT:

    bash
    curl https://arkvory.example.com:8080/health/status

    Ответ — статус 200 и {"status":"ready"}. Консоль находится по адресу https://arkvory.example.com:8080/console/.

В Linux учётная запись службы обычно не может слушать порт ниже 1024. Чтобы отдавать HTTPS на порту 443, используйте обратный прокси-сервер.

Если при запуске сертификат недействителен, API останавливается с ошибкой. Он никогда не переключается на обычный HTTP.

Параметры ​

configure задаёт файлы и адрес. Ещё два параметра добавляются в runtime.json вручную. После их изменения перезапустите службы: см. Применение изменения.

ПеременнаяПо умолчаниюЗначение
ARKVORY_TLS_MIN_VERSIONTLSv1.2TLSv1.2 или TLSv1.3
ARKVORY_TLS_RELOAD_SECONDS300Как часто API заново читает файлы сертификата: от 30 до 86400 секунд или 0, чтобы читать их только при запуске

Каждый ответ содержит Strict-Transport-Security: max-age=31536000.

Обновление сертификата ​

Запишите обновлённые сертификат и ключ по тем же путям. Команда и перезапуск не нужны.

  • API сравнивает файлы каждые ARKVORY_TLS_RELOAD_SECONDS. Новые соединения используют новый сертификат. Открытые соединения сохраняют старый, пока не закончатся.
  • Неудачное обновление (нечитаемые файлы, несовпадающий ключ, просроченный сертификат) никогда не заменяет работающий сертификат. API записывает в журнал tls.reload_failed и пробует снова через следующий интервал.
  • В последние 14 дней перед окончанием срока API раз в сутки записывает в журнал tls.expiring. Метрика arkvory_tls_certificate_expiry_timestamp_seconds подходит для оповещения. См. Мониторинг.

Выключение встроенного TLS ​

bash
sudo arkvory configure --root /opt/proanima-arkvory --tls-off --listen-host 127.0.0.1

Один --tls-off оставляет адрес прослушивания как есть. Без --listen-host 127.0.0.1 API продолжил бы отдавать обычный HTTP на каждом открытом вами интерфейсе.

Обратный прокси-сервер ​

Прокси-сервер принимает HTTPS от клиентов и пересылает обычный HTTP в API. Оставьте API на 127.0.0.1:8080 и установите прокси-сервер на том же хосте. Установка Compose всегда публикует только 127.0.0.1:8080, поэтому прокси-сервер на хосте подходит ей напрямую.

  1. Установите прокси-сервер и получите для него сертификат.
  2. Настройте прокси-сервер, как описано в разделе Что должен делать прокси-сервер.
  3. Добавьте адрес прокси-сервера в ARKVORY_TRUSTED_PROXIES. См. Доверенные прокси-серверы.
  4. Убедитесь, что порт API недоступен с других компьютеров.
  5. Проверьте: curl https://arkvory.example.com/health/status возвращает {"status":"ready"}.

Что должен делать прокси-сервер ​

ТребованиеЗачем
Принимать тела запросов любого размера (client_max_body_size 0 в nginx)Файлы весят десятки гигабайт и больше. Часть может достигать 1 ГиБ
Не буферизовать тела запросов и ответов (proxy_request_buffering off, proxy_buffering off)Байты идут потоком. Буферизация заполняет диск прокси-сервера и задерживает передачу
Допускать запросы длительностью не менее 1900 секунд (proxy_read_timeout, proxy_send_timeout)Один запрос загрузки может идти до 30 минут (ARKVORY_UPLOAD_DEADLINE_MS, по умолчанию 1 800 000 мс)
Говорить с API по HTTP/1.1 и сохранять соединениеНужно для потоковой передачи
Пересылать публичное имя в HostСервер строит из него абсолютные ссылки, например ссылки в ответах Git LFS и npm
Отправлять X-Forwarded-For и X-Forwarded-Proto: httpsАдрес клиента для журналов и ограничения входа и схема абсолютных ссылок
Перезаписывать X-Request-Id собственным IDAPI сохраняет ID от доверенного прокси-сервера. Клиент не должен его выбирать
Не записывать строку запроса в собственный журнал доступаСсылки на скачивание несут секрет в ?token=
При необходимости самому задавать Strict-Transport-SecurityAPI отправляет его только со встроенного слушателя

nginx ​

Поместите это в контекст http существующего nginx. Замените имя и пути к сертификатам. log_format записывает путь без строки запроса.

nginx
log_format arkvory_path '$remote_addr [$time_local] "$request_method $uri $server_protocol" '
                        '$status $body_bytes_sent $request_time $request_id';
server {
    listen 443 ssl;
    server_name arkvory.example.com;
    ssl_certificate /etc/arkvory/tls/fullchain.pem;
    ssl_certificate_key /etc/arkvory/tls/privkey.pem;
    access_log /var/log/nginx/arkvory.access.log arkvory_path;
    client_max_body_size 0;
    client_body_timeout 60s;
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Request-Id $request_id;
        proxy_set_header Connection "";
        proxy_request_buffering off;
        proxy_buffering off;
        proxy_read_timeout 1900s;
        proxy_send_timeout 1900s;
    }
}

С такой конфигурацией укажите прокси-сервер в ARKVORY_TRUSTED_PROXIES, например 127.0.0.1. Директива proxy_set_header X-Request-Id $request_id должна остаться: она перезаписывает ID, который может отправить клиент.

Caddy ​

caddyfile
arkvory.example.com {
    reverse_proxy 127.0.0.1:8080 {
        header_up X-Request-Id {http.request.uuid}
        flush_interval -1
    }
}

Caddy сам получает сертификат, передаёт тела запросов потоком, по умолчанию не ограничивает размер тела и не задаёт тайм-аут для upstream, а также задаёт X-Forwarded-For, X-Forwarded-Proto и X-Forwarded-Host. Caddy не пишет журнал доступа, пока вы не включите log. Если вы его включите, удаляйте строку запроса из записываемого адреса.

IIS и другие прокси-серверы ​

Эталонная конфигурация проекта — приведённый выше файл nginx. Ниже даны эквивалентные настройки для IIS с Application Request Routing и URL Rewrite. Проект их не проверяет. Сверьте названия с вашей версией IIS.

  • Увеличьте тайм-аут прокси-сервера до не менее 1900 секунд и задайте порог буфера ответа 0.
  • Увеличьте maxAllowedContentLength в фильтрации запросов до максимума — 4 294 967 295 байт. IIS не может принять тело запроса в 4 ГиБ и больше, поэтому единичная загрузка такого файла через curl -T не удастся. arkvoryctl отправляет большие файлы частями.
  • Отправляйте исходный хост, X-Forwarded-Proto: https и адрес клиента в X-Forwarded-For. Задавайте новый X-Request-Id правилом URL Rewrite.
  • Не записывайте строку запроса в журнал IIS.

Доверенные прокси-серверы ​

ARKVORY_TRUSTED_PROXIES принимает до 32 адресов или диапазонов CIDR через запятую. Имена хостов и подстановочные знаки отклоняются. Только запрос, пришедший с одного из этих адресов, может задавать:

  • адрес клиента через X-Forwarded-For. API берёт ближайший адрес, который не входит в список доверенных,
  • ID запроса через X-Request-Id,
  • хост абсолютных ссылок через X-Forwarded-Host.

Без списка каждый клиент выглядит пришедшим с адреса прокси-сервера. Тогда ограничение входа считает всех людей одним клиентом, а журнал доступа показывает адрес прокси-сервера в clientIp. Указывайте только прокси-серверы, которые вы контролируете.

На хосте Compose API может видеть прокси-сервер под адресом шлюза сети Compose, а не под 127.0.0.1. Отправьте один запрос через прокси-сервер, найдите clientIp в записи http.access в журнале API и укажите этот адрес.

Отредактируйте config/runtime.json и перезапустите службы. См. Применение изменения.

json
{ "ARKVORY_TRUSTED_PROXIES": "127.0.0.1,::1" }

Когда API слушает не loopback-адрес без TLS и без доверенного прокси-сервера, при запуске он записывает http.plaintext_exposed. Правильная настройка прокси-сервера его не вызывает.

Консоль и адрес её API ​

Консоль, которую отдаёт Arkvory, использует адрес, с которого её открыли. Она общается только со своим сервером: её политика безопасности содержимого не разрешает других адресов. За прокси-сервером она работает без изменений по адресу https://arkvory.example.com/console/.

Чтобы разместить консоль на другом веб-сервере, например рядом с порталом:

  1. Скопируйте файлы консоли из releases/<версия>/apps/web/public/ в корне установки на другой сервер. Отдавайте их по пути /console/ через HTTPS с правильными типами MIME для .js и .css. Копируйте их снова после каждого обновления Arkvory.

  2. В скопированном index.html укажите адрес Arkvory:

    html
    <meta name="arkvory-api-base-url" content="https://arkvory.example.com/" />
  3. Если другой сервер задаёт политику безопасности содержимого, разрешите connect-src для адреса Arkvory и разрешите локальный script worker.

  4. Разрешите источник консоли в Arkvory. См. CORS.

CORS ​

Укажите источники веб-приложений на других адресах в ARKVORY_CORS_ORIGINS и перезапустите API.

json
{ "ARKVORY_CORS_ORIGINS": "https://portal.example.com,https://tools.example.com" }
  • В списке до 16 источников, каждый со схемой, хостом и необязательным портом, без пути. Нужен HTTPS. Обычный HTTP принимается только для localhost, 127.0.0.1 и [::1].
  • CORS действует для /api/v1/* и /health/ready. Запрос с источника, которого нет в списке, получает статус 403 с причиной origin_not_allowed. Запросу с собственного адреса сервера запись не нужна.
  • Источник из списка не получает никаких прав. Каждый запрос по-прежнему требует ключа или сессии и проходит проверки доступа сервера. Веб-приложение отправляет ключ в заголовке Authorization, а не в cookie.
  • Разрешённые методы: GET, HEAD, POST, PUT, PATCH и DELETE. Браузеры могут кэшировать ответ на предварительный запрос (preflight) на 10 минут.

Проверьте предварительный запрос. Ответ должен иметь статус 204 и ваш источник в Access-Control-Allow-Origin:

bash
curl -i -X OPTIONS https://arkvory.example.com/api/v1/auth/me \
  -H 'Origin: https://portal.example.com' \
  -H 'Access-Control-Request-Method: GET' \
  -H 'Access-Control-Request-Headers: authorization'

Проверка настройки ​

  1. curl https://arkvory.example.com/health/status возвращает статус 200 и {"status":"ready"}. Цепочка сертификатов проверяется без исключений.
  2. Откройте консоль, войдите и загрузите большой файл через тот же адрес.
  3. Выполните arkvoryctl doctor с профилем, который использует адрес HTTPS. Не отключайте проверку сертификата на клиентах: клиент командной строки этого не умеет, а обычный HTTP принимает только для локального компьютера. См. Клиент командной строки.
  4. После перезапуска API в журнале нет записи http.plaintext_exposed.

Устранение неполадок ​

ПроблемаПричина и решение
HTTPS was not enabled; the previous configuration is restoredДальше в сообщении указана причина: файлы не в формате PEM, у ключа есть пароль, ключ не подходит, срок сертификата истёк или учётная запись службы не может прочитать файл. Исправьте это и выполните команду снова
TLS files must be given as absolute pathsУкажите полные пути
Built-in TLS is for native installations; use a reverse proxy with ComposeВ Compose нет встроенного TLS. Используйте обратный прокси-сервер
Статус 413 от прокси-сервераСлишком низкий предел размера тела. Используйте client_max_body_size 0 в nginx
Статус 502 или 504, либо загрузка, оборвавшаяся через несколько минутПрокси-сервер буферизует тело, или его тайм-ауты короче 1900 секунд
Всех ограничивают при входе, либо clientIp всегда равен адресу прокси-сервераПрокси-сервера нет в ARKVORY_TRUSTED_PROXIES
Ссылки в ответах Git LFS или npm показывают http или внутреннее имяПрокси-сервер не пересылает Host или X-Forwarded-Proto: https
Браузерное приложение получает 403 origin_not_allowedДобавьте его источник в ARKVORY_CORS_ORIGINS и перезапустите службы

Другие подсказки есть на страницах Устранение неполадок и Безопасность.

Arkvory · ProAnimaStudio