curl: как указать целевое имя хоста для запроса https

У меня есть x.example который обслуживает трафик для обоих a.example а также b.example,x.example имеет сертификаты для обоих a.example а также b.example, DNS для a.example а также b.example еще не настроен.

Если я добавлю /etc/hosts запись для a.example указывая на x.exampleайпи и беги curl -XGET https://a.exampleЯ получаю 200.

Однако, если я бегу curl --header 'Host: a.example' https://x.example, Я получил:

curl: (51) SSL: альтернативное имя субъекта сертификата не соответствует имени целевого хоста x.example

Я думаю, он будет использовать.example в качестве хоста. Может быть, я не понимаю, как работает SNI/TLS.

Так как a.example заголовок HTTP, к которому у TLS-рукопожатия еще нет доступа? Но сам URL, к которому он имеет доступ?

3 ответа

Решение

На самом деле SNI в TLS не работает так. SNI, как и все, что связано с TLS, происходит перед любым видом трафика HTTP, поэтому Host заголовок не учитывается на этом этапе (но позже будет полезно, чтобы веб-сервер знал, к какому хосту вы подключаетесь).

Таким образом, чтобы включить SNI, вам нужен определенный переключатель в вашем HTTP-клиенте, чтобы он отправлял соответствующее расширение TLS во время квитирования с нужным вам значением имени хоста.

В случае curlвам нужна как минимум версия 7.18.1 (на основе https://curl.haxx.se/changes.html), а затем она автоматически использует значение, указанное в Host заголовок. Это зависит от того, с какой версией OpenSSL (или эквивалентной библиотеки на вашей платформе) он связан.

Смотрите пункт 1.10 в https://curl.haxx.se/docs/knownbugs.html котором говорится об ошибке, но объясняется, что происходит:

Получив URL-адрес с конечной точкой для части имени хоста: " https://example.com/", libcurl удалит точку и будет использовать имя без точки внутри и отправит его без точки в HTTP-хосте: Заголовки и в поле TLS SNI.

--connect-to опция также может быть полезна в вашем случае. Или же --resolve в качестве замены /etc/hostsсм. https://curl.haxx.se/mail/archive-2015-01/0042.html для примера или https://makandracards.com/makandra/1613-make-an-http-request-to-a-machine-but-fake-the-hostname Вы можете добавить --verbose во всех случаях, чтобы увидеть более подробно, что происходит. Смотрите этот пример: https://www.claudiokuenzler.com/blog/693/curious-case-of-curl-ssl-tls-sni-http-host-header; вы также увидите там, как тестировать напрямую с openssl,

Если у вас есть a.example в вашем /etc/hosts Вы должны просто запустить curl с https://a.example/ и это должно заботиться о Host заголовок и, следовательно, SNI (или использовать --resolve вместо)

Выбранный ответ помог мне найти ответ, хотя он и не содержит ответа. Ответ в ссылке на почту / архив, предоставленную Патриком Мевзеком, имеет неправильный номер порта. Так что даже следование этому ответу приведет к продолжению сбоя.

Я использовал этот контейнер для запуска сервера отладки для проверки запросов. Я настоятельно рекомендую всем, кто занимается отладкой такого рода проблем, сделать то же самое.

Вот как ответить на вопрос ОП.

# Instead of this:
# curl --header 'Host: a.example'        https://x.example

# Do:
  host=a.example
  target=x.example

  ip=$(dig +short x.example | head -n1)
  curl -sv   --resolve $host:443:$ip https://$host

Примечание. Поскольку вы используете https, вы должны использовать443 в --resolve аргумент вместо 80как было написано на почте / в архиве

У меня была похожая потребность. Не было доступа sudo для обновления файла hosts.

Я использую параметр разрешения , а также добавляю имя хоста DNS в качестве параметра заголовка .

      --resolve <dns name>:<port>:<ip addr>

curl --request POST --resolve dns_name:443:a.b.c.d 'https://dns_name/x/y' --header 'Host: dns_name' ....

Ваше здоровье..

Другие вопросы по тегам