Вопрос или проблема
У нас настроен nginx с аутентификацией клиентских сертификатов, работающий на docker, мы используем только следующие SSL-настройки:
ssl_protocols TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!CAMELLIA;
Когда мы выполняем команду curl, мы получаем следующий вывод:
$ curl -v --cacert ./cacert.pem https://staging-a.b.com/path
* Попытка xx.xx.xx.xx...
* Установлен TCP_NODELAY
* Подключено к staging-a.b.com (xx.xx.xx.xx) порт 443 (#0)
* ALPN, предлагая h2
* ALPN, предлагая http/1.1
* успешно заданы места для проверки сертификатов:
* CAfile: ./cacert.pem
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS рукопожатие, Приветствие клиента (1):
* TLSv1.3 (IN), TLS рукопожатие, Приветствие сервера (2):
* TLSv1.2 (IN), TLS рукопожатие, Сертификат (11):
* TLSv1.2 (IN), TLS рукопожатие, Обмен ключами сервера (12):
* TLSv1.2 (IN), TLS рукопожатие, Сервер закончил (14):
* TLSv1.2 (OUT), TLS рукопожатие, Обмен ключами клиента (16):
* TLSv1.2 (OUT), TLS изменение шифра, Приветствие клиента (1):
* TLSv1.2 (OUT), TLS рукопожатие, Завершено (20):
* TLSv1.2 (IN), TLS рукопожатие, Завершено (20):
* SSL соединение с использованием TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, сервер принял использование http/1.1
* Сертификат сервера:
* субъект: CN=*.b.com
* дата начала: 23 Марта 2022 07:17:12 GMT
* дата истечения: 28 Марта 2023 23:10:15 GMT
* subjectAltName: хост "staging-a.b.com" соответствует сертификату "*.b.com"
* издатель: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2
* Проверка SSL сертификата прошла успешно.
> GET /path HTTP/1.1
> Host: staging-a.b.com
> User-Agent: curl/7.58.0
> Accept: */*
>
* TLSv1.2 (IN), TLS рукопожатие, Запрос приветствия (0):
* TLSv1.2 (OUT), TLS рукопожатие, Приветствие клиента (1):
* TLSv1.2 (IN), TLS рукопожатие, Приветствие сервера (2):
* TLSv1.2 (IN), TLS рукопожатие, Сертификат (11):
* TLSv1.2 (IN), TLS рукопожатие, Обмен ключами сервера (12):
* TLSv1.2 (IN), TLS рукопожатие, Запрос сертификата (13):
* TLSv1.2 (IN), TLS рукопожатие, Сервер закончил (14):
* TLSv1.2 (OUT), TLS рукопожатие, Сертификат (11):
* TLSv1.2 (OUT), TLS рукопожатие, Обмен ключами клиента (16):
* TLSv1.2 (OUT), TLS изменение шифра, Приветствие клиента (1):
* TLSv1.2 (OUT), TLS рукопожатие, Завершено (20):
* TLSv1.2 (IN), TLS предупреждение, Приветствие сервера (2):
* OpenSSL SSL_read: ошибка:14094410:SSL процедуры:ssl3_read_bytes:ошибка рукопожатия sslv3, errno 0
* поток остановлен!
* Закрыто соединение 0
curl: (56) OpenSSL SSL_read: ошибка:14094410:SSL процедуры:ssl3_read_bytes:ошибка рукопожатия sslv3, errno 0
Мы уже запустили nginx в режиме отладки, однако команда curl не вызывает никаких логов. Что может быть не так? Можете помочь? Заранее спасибо!
Обновление
По предложению @yield (в комментарии ниже), я выполнил команду внутри контейнера, и это сработало. Я сделал это, обновив файл hosts в контейнере и добавив
127.0.0.1 staging-a.b.com
, и выполнив команду. Вот вывод:
root@a4cb891fed8a:/# curl -k -v --cacert ./cacert.pem https://staging-a.b.com:2443/obinet/services/itsp/signup/sslc/reqcode?sid=1234billNEWCERT
* Попытка 127.0.0.1...
* Установлен TCP_NODELAY
* Подключено к staging-a.b.com (127.0.0.1) порт 2443 (#0)
* ALPN, предлагая h2
* ALPN, предлагая http/1.1
* успешно заданы места для проверки сертификатов:
* CAfile: ./cacert.pem
CApath: /etc/ssl/certs
* (304) (OUT), TLS рукопожатие, Приветствие клиента (1):
* (304) (IN), TLS рукопожатие, Приветствие сервера (2):
* TLSv1.2 (IN), TLS рукопожатие, Сертификат (11):
* TLSv1.2 (IN), TLS рукопожатие, Обмен ключами сервера (12):
* TLSv1.2 (IN), TLS рукопожатие, Запрос сертификата (13):
* TLSv1.2 (IN), TLS рукопожатие, Сервер закончил (14):
* TLSv1.2 (OUT), TLS рукопожатие, Сертификат (11):
* TLSv1.2 (OUT), TLS рукопожатие, Обмен ключами клиента (16):
* TLSv1.2 (OUT), TLS изменение шифра, Приветствие клиента (1):
* TLSv1.2 (OUT), TLS рукопожатие, Завершено (20):
* TLSv1.2 (IN), TLS рукопожатие, Завершено (20):
* SSL соединение с использованием TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, сервер принял использование http/1.1
* Сертификат сервера:
* субъект: CN=*.b.com
* дата начала: 23 Марта 2022 07:17:12 GMT
* дата истечения: 28 Марта 2023 23:10:15 GMT
* издатель: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2
* Результат проверки SSL сертификата: самоподписанный сертификат в цепочке сертификатов (19), продолжаем в любом случае.
> GET /obinet/services/itsp/signup/sslc/reqcode?sid=1234billNEWCERT HTTP/1.1
> Host: staging-a.b.com:2443
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Сервер: nginx/1.13.6
< Дата: Чт, 10 Авг 2022 14:48:44 GMT
< Content-Type: application/octet-stream
< Content-Length: 0
< Connection: keep-alive
< Content-Type: text/plain
< X-DEBUG-SSLCLIENTVERIFY: NONE
< X-DEBUG-docroot: /usr/local/openresty/nginx/html
<
* Соединение #0 с хостом staging-a.b.com осталось активным
Я бы:
1- Назвал ваш контейнер.
2- Добавил больше информации для OpenSSL с помощью -v
3- На какой дистрибутив Linux основан ваш контейнер. (Это может изменить дальнейшие шаги, так как OpenSSL ведет себя по-разному в зависимости от дистрибутива)
Ответ или решение
Для устранения ошибки OpenSSL SSL_read: error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure, errno 0
, которая возникает при попытке выполнить подключение к вашему Nginx серверу с использованием curl
, необходимо провести детальную диагностику. Ниже приведены шаги для понимания и решения проблемы.
1. Проверка конфигурации Nginx
Убедитесь, что ваш Nginx настроен правильно для поддержки клиентской аутентификации. Вам необходимо добавить следующие директивы в конфигурационный файл вашего Nginx:
ssl_client_certificate /path/to/your/cacert.pem; # Путь к вашему корневому сертификату
ssl_verify_client on; # Включите проверку клиента
Проверьте, что используемые вами сертификаты корректные и соответствуют друг другу.
2. Проверка протоколов и шифров
Ваши настройки ssl_protocols
указывают на использование только TLSv1.2. Это может стать проблемой, если клиент (например, curl) пытается использовать другие протоколы, такие как TLSv1.3. Попробуйте изменить настройки:
ssl_protocols TLSv1.2 TLSv1.3; # Включите поддержку TLSv1.3
3. Дебаггинг Nginx
Запустите Nginx в режиме отладки, чтобы получить больше информации о процессе handshake:
error_log /var/log/nginx/error.log debug;
Это позволит вам увидеть логи, которые могут помочь в понимании проблемы.
4. Диагностика с помощью curl
Если ваш curl
успешно работает внутри контейнера, но не снаружи, это может быть связано с сетевой конфигурацией или брандмауэром. Попробуйте использовать команду curl
с повышенным уровнем подробности:
curl -v --cacert ./cacert.pem https://staging-a.b.com/path
5. Проверка сертификатов
Убедитесь, что сертификаты, которые вы используете для аутентификации клиентов, правильно подписаны и действительны. Команда для проверки действительности сертификата:
openssl verify -CAfile ./cacert.pem ./client-cert.pem
6. Дополнительные проверки
- Имя контейнера: Дайте вашему контейнеру уникальное имя, чтобы было проще с ним работать.
- ОС контейнера: Убедитесь, что вы знаете, на какой системе основан ваш контейнер, так как разные дистрибутивы могут вести себя по-разному с OpenSSL.
- Версия OpenSSL: Убедитесь, что у вас последняя версия OpenSSL, которая может решать известные уязвимости.
Заключение
Если после выполнения всех вышеперечисленных шагов проблема не устраняется, рекомендуется задействовать инструменты диагностики сети, такие как tcpdump
или wireshark
, чтобы понять, что происходит на сетевом уровне во время handshake. Это может дать дополнительную информацию, которая поможет в решении проблемы.
Пожалуйста, помните, что безопасность ваших сертификатов и ключей крайне важна, и они не должны быть раскрыты или неправильно настроены.