Ошибка рукопожатия шифровального набора TLS 1.2 при подключении к SQL Server с помощью sqlcmd

Вопрос или проблема

Ошибка рукопожатия шифровального набора TLS 1.2 при подключении к SQL Server с помощью sqlcmd

Я пытаюсь создать контейнер Docker для манипуляции данными из SQL Server.

Описание проблемы и вовлеченных устройств

Вот список соответствующих устройств:

  • Контейнер Docker: ОС – Debian 12.
  • Хост-машина: Ubuntu 22.04.
  • SQL Server: версия 2016 13.0.2026. Работает на виртуальной машине Windows Server 2012R2. И нет, я не могу обновить ни одно из них (я спрашивал…).

Я использую точно те же учетные данные (взятые из того же .env файла, чтобы избежать ошибок).

Я могу подключиться через sqlcmd с хоста (используя sqlcmd v1.5.0, ODBC 17 и openssl 3.0.2-0ubuntu1.18).

Я использую эту команду для подключения с хоста:

        sqlcmd \
        --server "$UTT_SQLDB_SERVERNAME" \
        --database-name "$UTT_SQLDB_DATABASE" \
        --user-name "$UTT_SQLDB_USERNAME" \
        --password "$UTT_SQLDB_PASSWORD"

Но из контейнера я не могу (используя sqlcmd 17.10.0001.1 Linux, ODBC 17 и openssl 3.0.14-1~deb12u2):

Я использую эту команду для подключения из контейнера:

sqlcmd \
    -S "$UTT_SQLDB_SERVERNAME" \
    -U "$UTT_SQLDB_USERNAME" \
    -P "$UTT_SQLDB_PASSWORD" \
    -d "$UTT_SQLDB_DATABASE"

Проблема с брандмауэром отсутствует, так как я могу telnet и ping SQL Server из контейнера.

Сообщения об ошибках

В контейнере я получаю следующее сообщение об ошибке:

root@50f7a7519b2b:/var/www/html# sqlcmd -S $UTT_SQLDB_SERVERNAME -U $UTT_SQLDB_USERNAME -P $UTT_SQLDB_PASSWORD -d $UTT_SQLDB_DATABASE
Sqlcmd: Ошибка: Microsoft ODBC Driver 17 для SQL Server : TCP Provider: код ошибки 0x2746.
Sqlcmd: Ошибка: Microsoft ODBC Driver 17 для SQL Server : клиент не может установить соединение.

А в журналах SQL Server я получаю следующие два сообщения об ошибках (я перевел их с французского):

Код ошибки TLS 40: Это указывает на сбой при установлении соединения во время обмена TLS. Это происходит, когда клиент и сервер не могут согласовать протоколы шифрования или шифры.
Ошибка SChannel 1205: Это ошибка Windows, связанная с SChannel (Безопасный канал), который является компонентом, ответственным за обработку шифрования SSL/TLS. Ошибка 1205, как правило, означает, что имел место несоответствие в конфигурации TLS между клиентом и сервером.

Что я пробовал

Так как это, похоже, проблема с набором шифров, я пытался подключиться напрямую через openssl вот так (из контейнера):

root@50f7a7519b2b:/var/www/html# openssl s_client -connect $UTT_SQLDB_SERVERNAME:1433 -tls1_2
CONNECTED(00000003)
root@50f7a7519b2b:/var/www/html# openssl s_client -connect $UTT_SQLDB_SERVERNAME:1433 -tls1_1
CONNECTED(00000003)
root@50f7a7519b2b:/var/www/html# openssl s_client -connect $UTT_SQLDB_SERVERNAME:1433 -tls1  
CONNECTED(00000003)

И это работает. Что меня сбивает с толку.

Я также не понимаю, почему я могу подключаться с хоста, но не из контейнера, используя эквивалентные команды и схожие ОС?

Я также пытался запустить контейнер в режиме сети хоста. Без успеха.

Ответ или решение

Проблема, с которой вы столкнулись, связана с ошибкой рукопожатия TLS при попытке подключения к SQL Server из Docker-контейнера. Хотя вы можете успешно подключиться к серверу из хостовой системы, но не можете сделать это из контейнера — это довольно распространенная проблема, учитывая, что в окружениях Docker могут быть разные конфигурации.

Анализ проблемы

  1. Сертификаты и протоколы: Хотя вы можете установить соединение с SQL Server с помощью OpenSSL, это не обязательно означает, что ваш клиент sqlcmd может использовать те же шифры, что и OpenSSL. Версия ODBC драйвера и его совместимость с TLS могут вызывать проблемы с шифрованием.

  2. Разные версии библиотек: На хост-системе используется openssl 3.0.2, в то время как в контейнере openssl 3.0.14. Версии библиотек могут иметь разные настройки по умолчанию, что может влиять на совместимость шифров.

  3. Конфигурация Docker: Контейнер может иметь разные сетевые настройки и зависимости от конфигурации Docker. Возможно, что в контейнере что-то мешает правильному использованию ODBC драйвера.

Рекомендации по решению проблемы

  1. Проверка шифров: Убедитесь, что ODBC драйвер, используемый в контейнере, поддерживает те же шифры, что и сервер. Вы можете выполнить команду для отображения доступных шифров:

    openssl ciphers -v

    Убедитесь, что необходимые для работы шифры и протоколы включены.

  2. Обновление ODBC драйвера: Убедитесь, что вы используете последнюю версию ODBC драйвера 17 для SQL Server. Иногда обновления могут содержать исправления, которые улучшают совместимость.

  3. Проверка настроек TLS на сервере: Убедитесь, что сервер SQL настроен для поддержки необходимых протоколов и шифров. Возможно, потребуется изменить настройки на стороне сервера.

  4. Запуск контейнера с использованием --network host: Если вы еще не попробовали это, попробуйте запустить контейнер с флагом --network host. Это обеспечит использование сетевых настроек вашего хоста и может помочь с проблемами совместимости.

    docker run --network host your-docker-image
  5. Анализ логов SQL Server: Обратите внимание на дополнительные ошибки в журналах SQL Server. Они могут дать дополнительную информацию о причинах при отказе в подключении.

  6. Протестируйте на другой версии контейнера: Возможно, у вас изменится поведение при использовании другого базового образа Docker. Попробуйте начать с базового образа, отличного от Debian 12, например, с Ubuntu.

Пример команды для тестирования

Попробуйте следующее, чтобы увидеть, может ли sqlcmd подключиться:

sqlcmd -S "$UTT_SQLDB_SERVERNAME" -U "$UTT_SQLDB_USERNAME" -P "$UTT_SQLDB_PASSWORD" -d "$UTT_SQLDB_DATABASE" -N

Флаг -N требует, чтобы соединение было защищенным.

Заключение

Если ни одно из решений не поможет, возможно, стоит рассмотреть возможность использования другого клиента, например, sql-cli или другого инструмента, который может использовать другие механизмы подключения. Кроме того, не забудьте проверить справочную документацию Microsoft и Bugzilla для известного поведения, связанного с их ODBC драйверами и соответствующими библиотеками.

Оцените материал
Добавить комментарий

Капча загружается...