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:
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
Выполните команду с путями и адресом, который нужно слушать.
0.0.0.0слушает все интерфейсы IPv4,::— все интерфейсы, либо укажите адрес одного интерфейса.bashsudo 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.0powershell& '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, перезапускает службы с ним и сообщает причину.Откройте порт API в брандмауэре для сетей ваших клиентов.
Проверьте с клиентского компьютера. Порт остаётся 8080, пока вы не измените
ARKVORY_PORT:bashcurl 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_VERSION | TLSv1.2 | TLSv1.2 или TLSv1.3 |
ARKVORY_TLS_RELOAD_SECONDS | 300 | Как часто 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
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, поэтому прокси-сервер на хосте подходит ей напрямую.
- Установите прокси-сервер и получите для него сертификат.
- Настройте прокси-сервер, как описано в разделе Что должен делать прокси-сервер.
- Добавьте адрес прокси-сервера в
ARKVORY_TRUSTED_PROXIES. См. Доверенные прокси-серверы. - Убедитесь, что порт API недоступен с других компьютеров.
- Проверьте:
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 собственным ID | API сохраняет ID от доверенного прокси-сервера. Клиент не должен его выбирать |
| Не записывать строку запроса в собственный журнал доступа | Ссылки на скачивание несут секрет в ?token= |
При необходимости самому задавать Strict-Transport-Security | API отправляет его только со встроенного слушателя |
nginx
Поместите это в контекст http существующего nginx. Замените имя и пути к сертификатам. log_format записывает путь без строки запроса.
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
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 и перезапустите службы. См. Применение изменения.
{ "ARKVORY_TRUSTED_PROXIES": "127.0.0.1,::1" }Когда API слушает не loopback-адрес без TLS и без доверенного прокси-сервера, при запуске он записывает http.plaintext_exposed. Правильная настройка прокси-сервера его не вызывает.
Консоль и адрес её API
Консоль, которую отдаёт Arkvory, использует адрес, с которого её открыли. Она общается только со своим сервером: её политика безопасности содержимого не разрешает других адресов. За прокси-сервером она работает без изменений по адресу https://arkvory.example.com/console/.
Чтобы разместить консоль на другом веб-сервере, например рядом с порталом:
Скопируйте файлы консоли из
releases/<версия>/apps/web/public/в корне установки на другой сервер. Отдавайте их по пути/console/через HTTPS с правильными типами MIME для.jsи.css. Копируйте их снова после каждого обновления Arkvory.В скопированном
index.htmlукажите адрес Arkvory:html<meta name="arkvory-api-base-url" content="https://arkvory.example.com/" />Если другой сервер задаёт политику безопасности содержимого, разрешите
connect-srcдля адреса Arkvory и разрешите локальный script worker.Разрешите источник консоли в Arkvory. См. CORS.
CORS
Укажите источники веб-приложений на других адресах в ARKVORY_CORS_ORIGINS и перезапустите API.
{ "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:
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'Проверка настройки
curl https://arkvory.example.com/health/statusвозвращает статус 200 и{"status":"ready"}. Цепочка сертификатов проверяется без исключений.- Откройте консоль, войдите и загрузите большой файл через тот же адрес.
- Выполните
arkvoryctl doctorс профилем, который использует адрес HTTPS. Не отключайте проверку сертификата на клиентах: клиент командной строки этого не умеет, а обычный HTTP принимает только для локального компьютера. См. Клиент командной строки. - После перезапуска 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 и перезапустите службы |
Другие подсказки есть на страницах Устранение неполадок и Безопасность.