MySQL через VPN: проверяйте сервер, а не только шифрование
Шифрование к неправильному хосту всё равно неверно. Сравните значения ssl-mode, затем выполните подключение, которое называет нужный сервер и доказывает это.
Вы сохраняете подключение к 10.20.4.15, VPN падает, а клиент всё равно подключается. Это не хорошая новость. Частный адрес — это место внутри любого контекста маршрутизации, в котором вы находитесь, и многие сети используют одни и те же диапазоны. Клиент достиг сервера MySQL, просто, возможно, не вашего.
Исправление состоит из двух половин, и только одна из них о сети. Держите подключение на предназначенном пути и заставьте клиент проверять подлинность сервера, с которым он говорит. Первая половина — там, где помогает VPN; вторая должна быть настроена.
Зашифровано к чему именно?
TLS защищает разговор от любого посредника и ничего не говорит о том, кем заявляет себя конечная точка, если клиент это не проверяет. Сертификат, прошедший проверку у доверенного центра, доказывает, что сертификат выдан этим центром. Он не доказывает, что сертификат выпущен для имени хоста, которого вы хотели достичь, и это разные вопросы.
Это не теоретическая дыра. Захватывающие порталы, ошибки с неверным VRF и пересекающиеся планы адресов — всё это создаёт сервер, полностью готовый вести с вами переговоры TLS. Если клиент требует только шифрование, сеанс приватный, но направлен на не ту базу данных.
Значит, важный вопрос не в том, зашифровано ли соединение, а в том, зашифровано ли оно к той личности, которую вы имели в виду. В клиенте MySQL это различие целиком живёт в параметре ssl-mode.
Пять значений ssl-mode на практике
Существует пять значений, и только одно из них отвечает на вопрос этого руководства. Таблица перечисляет, что каждое из них на самом деле гарантирует, а не то, что подразумевает его название.
| Mode | What it guarantees |
|---|---|
DISABLED | No TLS at all; everything on the wire is readable |
PREFERRED | Tries TLS and falls back to plaintext when the account and server allow it, so it is not a fail-closed requirement |
REQUIRED | Refuses to connect without TLS, and does not validate the certificate |
VERIFY_CA | Validates the server certificate against the configured CA and does not check the hostname |
VERIFY_IDENTITY | Validates the CA and checks that the certificate names the host the client used |
На вопрос этой статьи отвечает только последняя строка. PREFERRED заслуживает отдельного упоминания, потому что клиент, который молча переходит на открытый текст, хуже того, который отказывается: вы думаете, что у вас есть шифрование, а запись пакетов не согласна.
Подключение, которое можно выполнить сегодня
Команда ниже — это форма, которую нужно использовать, с двумя заполнителями: утверждённое имя базы данных и файл CA, полученный по утверждённому каналу. Ни то ни другое не следует брать из того, что сервер предлагает при первом контакте.
mysql --host=db.corp.example --user=app_reader \
--ssl-mode=VERIFY_IDENTITY \
--ssl-ca=/approved/path/ca.pem --password
--password без значения запрашивает ввод, что держит секрет вне списка процессов и вне истории вашей оболочки. Это маленькая привычка с большой отдачей на общих промежуточных хостах, где командная строка видна другим пользователям.
Когда это не удаётся, текст ошибки различает случаи лучше интуиции. Ошибка CA означает, что цепочка не проверяется, и нужно посмотреть, какой CA подписал сертификат сервера. Ошибка имени хоста означает, что цепочка в порядке, а имя не совпадает, что обычно значит, что вы подключились к правильному серверу под неправильным именем, а не к неправильному серверу.
Появление запроса не доказывает, что пароль уже передан, а неудачное подключение не доказывает, что из клиента ничего не ушло. Если вы восстанавливаете прошлое событие, определите клиент, его конфигурацию, плагин аутентификации и этап, который не удался. Оценка экспозиции по последнему сообщению об ошибке — это догадка.
Когда имя приходит из туннеля
Перенаправление локального порта ломает проверку личности так, что это удивляет людей. Если вы перенаправляете локальный порт к базе данных и подключаетесь к localhost, клиент проверяет сертификат относительно localhost, а сертификат на это имя не выдавался. Соединение может быть совершенно безопасным, и проверка всё равно не пройдёт — это проверка, работающая как задумано.
Есть два честных ответа. Дайте перенаправленной конечной точке имя, которое разрешается в адрес обратной петли и присутствует в сертификате сервера, или используйте имя хоста от начала до конца, чтобы клиент проверял настоящую личность. Первое удобно разработчикам и требует работы с сертификатами; второе проще обдумать и часто правильная настройка по умолчанию для автоматизации. Отключение проверки, чтобы перенаправление работало, выбрасывает свойство, которое вы пытались добавить.
Приёмка — это три условия
Напишите приёмочный тест как три отдельных утверждения: соединение использовало предназначенный маршрут, шифрование требовалось, а не было предпочтительным, и личность сервера была проверена по доверенным материалам. Зелёный значок VPN не устанавливает ни одно из них.
Для GUI-клиентов и для MariaDB проверяйте собственную документацию поставщика, а не предполагайте, что написание флага переносится. Документация MySQL о шифрованных соединениях описывает различия режимов и требование распространения CA, и это справочник, который нужно проверить перед изменением производственной строки подключения.