ActiveScaleинженерная практика

S3-домен, сертификат и DNS

Эксплуатация s3tlsdnshaproxyiamsigv4

Коротко. S3-фронт слушает 443 и терминирует TLS на узле. Клиент «не подключается» по трём независимым причинам: сертификат без subjectAltName (handshake отбивается на имени хоста), выбран virtual-hosted стиль без wildcard-DNS, либо запрос уходит не в S3, а в IAM из-за карты доменов. Лечится не отключением проверки, а сертификатом с SAN на apex и wildcard, wildcard-записью в DNS и корректной картой доменов.


1. Что где стоит

клиент → DNS → внешний адрес (DNAT/балансировщик) → узел :443 (haproxy) → scalerd (S3)
  • 443 — единственная точка входа S3. Порты 11000–11003 — внутренние порты DSS, не S3.
  • TLS терминируется на узле; дальше трафик идёт во внутренний S3-шлюз.
  • Сертификат фронта — не файл «на память»: продукт рендерит его из ConfigRule haproxy_ssl (ресурсный тип scalerd) в файл вида scalerd.pem. Поэтому правка файла руками бессмысленна — при следующем применении конфигурации он будет перезаписан.
  • Сертификат GUI — отдельное правило (samurai_ssl); его браузерные предупреждения лечатся независимо от S3.

Внешний доступ — это DNS + проброс порта. Продукт не знает, какой внешний адрес и порт вы используете; он видит только запрос, пришедший на узел. Поэтому «изнутри работает, снаружи нет» — почти всегда история про DNAT, DNS или сертификат, выданный на другое имя.


2. Два стиля адресации

Стиль Формат Что нужно
Path-style https://s3.<DOMAIN>/<BUCKET>/<KEY> apex-имя в DNS, SAN на apex
Virtual-hosted https://<BUCKET>.s3.<DOMAIN>/<KEY> wildcard *.s3.<DOMAIN> в DNS, SAN на wildcard

Path-style работает всегда и является безопасным выбором для проверки. Virtual-hosted требует, чтобы каждый бакет резолвился как имя хоста: без wildcard-записи клиент падает ещё на DNS, до TLS.

Список доменов, которые шлюз понимает как суффиксы, задаётся в конфигурации шлюза (domain_suffix_set). Это отдельная настройка от сертификата: сертификат может быть wildcard, а DNS — без wildcard, и наоборот.


3. Симптомы и что они значат

Симптом клиента Причина
hostname '...' doesn't match 'scalerd' сертификат по умолчанию: CN=scalerd, без SAN
Handshake не проходит, HTTP 000 при --cacert та же причина: доверие не спасает, если имя не совпадает
Не резолвится <BUCKET>.s3.<DOMAIN> нет wildcard-DNS, а клиент настаивает на virtual-hosted
400 InvalidAction ... NO_VERSION_SPECIFIED запрос ушёл в службу IAM: S3-хост попал в карту IAM-доменов
307 без ошибки штатный ответ S3-фронта; признак, что фронт жив
403 SignatureDoesNotMatch подпись/время/кодирование ключа, не сертификат

Важно: «добавить сертификат в доверенные» не лечит S3, если в сертификате нет SAN. Браузер предлагает «принять исключение», а библиотеки (aws-cli, boto3, s3cmd, rclone) сравнивают имя хоста и отказывают. Импорт в доверенные оправдан для браузеров и внутренних служб — но не как решение для S3-клиентов.


4. Сертификат с SAN: штатный путь

Нужны оба имени в SAN: apex (для path-style и вызовов API) и wildcard (для virtual-hosted). Wildcard-сертификат сам по себе apex не покрывает.

Выпуск (у себя или на узле; приватный ключ — вне каталогов продукта, права не шире 600):

cat > san.cnf <<'EOF'
[req]
distinguished_name = dn
req_extensions     = v3
prompt             = no
[dn]
CN = s3.<DOMAIN>
[v3]
subjectAltName = @alt
basicConstraints = critical, CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[alt]
DNS.1 = s3.<DOMAIN>
DNS.2 = *.s3.<DOMAIN>
EOF
openssl req -new -newkey rsa:2048 -nodes -keyout s3.key -out s3.csr -config san.cnf
openssl x509 -req -in s3.csr -signkey s3.key -days 3650 \
  -extfile san.cnf -extensions v3 -out s3.crt
cat s3.crt s3.key > s3-fullchain.pem

Установка — только через модель или GUI, не копированием файла:

  1. GUI: Configuration → SSL-сертификаты → раздел S3 SSL; загрузить s3-fullchain.pem (сертификат + ключ одним файлом) и подтвердить операцию. Право на это действие — UPDATE_SYSTEMCONFIG_S3SSL.
  2. Model API (эквивалент): изменить содержимое настройки ssl_pem_content в ConfigRule haproxy_ssl (ресурсный тип scalerd), затем применить конфигурацию приложения scalerd штатным configure. Формат settings — массив по узлам/локациям: смотреть живой документ, а не угадывать. Как читать и менять модель — Model API.

Альтернатива для парка сервисов — свой CA: клиентам ставится один корневой сертификат, продление идёт без правок на клиентах. Публичный ACME-сертификат возможен, но требует DNS-01 для wildcard (обновление TXT-записи каждые 90 дней) или HTTP-01 с открытым 80 на терминаторе; для закрытого контура это лишняя зависимость.


5. DNS и внешний доступ

  1. Apex: s3.<DOMAIN> → внешний адрес (или CNAME на балансировщик).
  2. Wildcard: *.s3.<DOMAIN> → тот же адрес, если нужен virtual-hosted. Без него — только path-style.
  3. Проброс порта: наружу публикуется ровно один порт S3; он обслуживает любой хост, поэтому при смене сертификата DNAT менять не нужно.
  4. IAM-домен: для IAM-вызовов нужен отдельный FQDN (см. IAM и resource policy); по IP IAM не работает.

Проверка снаружи — тем же инструментом, что видит клиент: curl, openssl s_client, клиентский SDK. Локальные проверки на узле доказывают только, что служба жива, но не что клиент дойдёт.


6. Проверка после установки сертификата

# 1) какой сертификат реально отдаётся и есть ли SAN
echo | openssl s_client -connect s3.<DOMAIN>:443 -servername s3.<DOMAIN> 2>/dev/null \
  | openssl x509 -noout -subject -ext subjectAltName

# 2) фронт отвечает без отключения проверки
curl -sS -o /dev/null -w '%{http_code}\n' https://s3.<DOMAIN>/

# 3) клиент без --no-verify-ssl
aws --endpoint-url https://s3.<DOMAIN> s3 ls

Ожидается: в SAN — s3.<DOMAIN> и *.s3.<DOMAIN>; curl → 307; aws s3 ls → список бакетов или AccessDenied при валидных ключах (это уже права, не TLS).

Для virtual-hosted дополнительно:

getent hosts <BUCKET>.s3.<DOMAIN>

Ожидается адрес, а не пустой ответ. Если пусто — wildcard-записи нет.


7. Продление и откат

  • Перед заменой сохранить текущий PEM вне каталога продукта и зафиксировать содержимое ssl_pem_content (guid правила haproxy_ssl).
  • Продление = новая пара «сертификат + ключ» в модель тем же путём, в окно обслуживания. Для самоподписанного/своего CA — по календарю; срок можно ставить длинный, но правило «продление = новая пара через модель» остаётся.
  • Откат = вернуть прежний PEM в то же правило и применить configure приложения scalerd.
  • Не забыть GUI-сертификат (samurai_ssl): браузерные предупреждения на порту GUI лечатся им же.
  • Каталог ssl.<hash> ротируется продуктом; путь брать через симлинк ssl.

8. Границы

  • Конкретные имена DNS-зон, внешние адреса и порты проброса — инфраструктура заказчика, не продукта: в статье они не приводятся.
  • Поведение клиента при не-ASCII ключах и неизвестных query-параметрах — отдельная тема совместимости, см. S3-совместимость.
  • «Сертификат без SAN — штатное поведение по умолчанию» подтверждено на нашей практике; в других сборках проверять фактический вывод openssl s_client, а не предполагать.

9. Источники

  • Quantum Software Documentation Center (7.3) (2026-11-07)
  • Release Notes 7.3 — загрузка цепочки SSL через GUI по документированному порядку PEM, предупреждение об истечении сертификата за 6 месяцев
  • Наша практика (обезличенно): сертификат без SAN, path-style, wildcard-DNS и проверка 307 на кластере из трёх нод, ActiveScale 7.3.1.2; замена через ConfigRule haproxy_ssl.
  • Обновлено: 2026-11-07.

Нужен инженер? Разберу вашу ситуацию и скажу, что делать — по шагам, с проверками.

Обсудить задачу