• Русский
  • Ошибки 404 при конфигурации нескольких шлюзов с одним и тем же TLS-сертификатом

    Содержание

    Описание проблемы

    Симптомы

    При обращении к сервисам через Istio Ingress Gateway с использованием протокола HTTP/2 возникают ошибки 404. Это известная проблема в сообществе Istio.

    Корневая причина

    Конфигурация нескольких шлюзов с одним и тем же TLS-сертификатом приводит к тому, что браузеры HTTP/2 генерируют ошибки 404 при обращении к вторичным хостам после установления первоначального соединения. Это происходит из-за повторного использования HTTP/2 соединения в браузерах.

    Пример сценария:

    • Домены a.example.com и b.example.com используют один и тот же TLS-сертификат
    • Настроены в отдельных ресурсах Gateway
    • Браузер обращается сначала к a.example.com, затем к b.example.com по одному и тому же соединению

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

    Скрипт для проверки

    Выполните этот скрипт на мастер-узле кластера, в котором развернут Istio Ingress Gateway:

    #!/bin/bash
    nslist=$(kubectl get ns -o jsonpath='{.items[*].metadata.name}')
    declare -A cred_map
    
    echo "begin to check gw"
    for ns in $nslist; do
      gateways=$(kubectl get gw -n $ns -o jsonpath='{.items[*].metadata.name}')
      for gateway in $gateways; do
        gateway_yaml=$(kubectl get gw -n $ns $gateway -o yaml)
        secname=$(echo "$gateway_yaml" | grep 'credentialName:' | awk '{print $2}')
    
        if [[ -n "$secname" ]]; then
          if [[ -n "${cred_map[$secname]}" ]]; then
            echo -e "\033[31m Duplicate TLS detected in gateway: ${cred_map[$secname]} \033[0m"
            hosts=$(kubectl get gw -n $ns $gateway -o json | jq -r '.spec.servers[] | .hosts[]')
            echo -e "\033[31m Conflict gateway: $gateway in $ns \033[0m"
            echo "Affected hosts: $hosts"
          else
            cred_map["$secname"]="$gateway~$ns"
          fi
        fi
      done
    done

    Ожидаемый вывод:

    Duplicate TLS detected in gateway: drawdb-gateway~drawdb
    Conflict gateway: authory-gateway in nm-edu-authory
    Affected hosts: rzzx-test.jiaxiurc.com

    Решение корневой причины 1: Объединение ресурсов Gateway

    Особенности

    • Рекомендуемое сообществом решение
    • Сохраняет преимущества производительности HTTP/2
    • Требует изменения существующих конфигураций Gateway

    Предварительные условия

    1. Установлен jq версии 1.7 и выше на узлах кластера
    2. Доступ к кластеру с правами kubectl

    Шаги

    1. Определить конфликтующие Gateways с помощью скрипта проверки
    2. Объединить конфигурации Host:
      apiVersion: networking.istio.io/v1beta1
      kind: Gateway
      metadata:
        name: unified-gateway
        namespace: istio-system
      spec:
        selector:
          istio: ingressgateway
        servers:
        - hosts:
            - "a.example.com"
            - "b.example.com"
          tls:
            mode: SIMPLE
            credentialName: shared-cert
          port:
            name: https
            number: 443
            protocol: HTTPS
    3. Обновить VirtualServices для ссылки на объединённый Gateway
    4. Удалить избыточные Gateways
    5. Проверить конфигурацию:
      kubectl get gw -A
      istioctl analyze

    Решение корневой причины 2: Код ответа 421

    Особенности

    • Требуется поддержка клиентом кода статуса 421
    • Совместимо с Chrome/Firefox/Safari 15.1 и выше

    Предварительные условия

    1. Версия Istio ≥ 1.12
    2. Права администратора кластера

    Шаги

    1. Применить EnvoyFilter:
      apiVersion: networking.istio.io/v1alpha3
      kind: EnvoyFilter
      metadata:
        name: misdirected-request
        namespace: istio-system
      spec:
        configPatches:
          - applyTo: HTTP_FILTER
            match:
              context: GATEWAY
              listener:
                filterChain:
                  filter:
                    name: envoy.filters.network.http_connection_manager
            patch:
              operation: INSERT_BEFORE
              value:
                name: envoy.lua
                typed_config:
                  "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
                  inlineCode: |
                    function envoy_on_request(request_handle)
                      local authority = request_handle:headers():get(":authority")
                      local sni = request_handle:streamInfo().requestedServerName
      
                      if sni ~= "" and sni ~= authority:match("([^:]+)") then
                        request_handle:respond({[":status"] = "421"}, "Misdirected Request")
                      end
                    end
    2. Проверить реализацию:
      curl -I -H "Host: b.example.com" https://gateway-ip

    Профилактические меры

    1. Управление сертификатами:
      • Использовать wildcard-сертификаты (*.example.com)
      • Избегать повторного использования сертификатов в разных окружениях
    2. Проектирование Gateway:
      • Реализовать один шлюз на шаблон домена
      • Использовать изоляцию сертификатов по namespace
    3. Регулярные аудиты:
      istioctl experimental precheck
      kubectl get secret --all-namespaces -o json | jq '.items[].metadata.name' | sort | uniq -d

    Связанный контент

    Механизм повторного использования HTTP/2 соединений:

    • Одно TLS-соединение обрабатывает несколько запросов
    • Сервер использует SNI для маршрутизации запросов
    • Несовпадение заголовков SNI вызывает сбои маршрутизации

    Ссылка на документацию Istio:
    Istio Common Problems - 404 Errors