MySqlConnector к серверу MySQL на той же системе видит попытку подключения с IP-адреса вместо локального хоста.

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

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

Мы запускаем приложение на dotnet в системе Linux и хотим подключиться к базе данных MySQL на той же системе. Пользователь, которого мы используем, может подключаться только с localhost.

Вот вывод:

2025-01-06 13:41:36.819 +01:00 [INF] OpenConnection => 

Host=localhost;Username=myuser;Password='mypass';Database=; Connection Timeout=360;Allow User Variables=True
2025-01-06 13:41:37.460 +01:00 [ERR] Error connecting to mysql server AccessDenied
MySqlConnector.MySqlException (0x80004005): Access denied for user 'myuser'@'10.15.15.142' (using password: YES)
   at MySqlConnector.Core.ServerSession.ReceiveReplyAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/ServerSession.cs:line 885

IP-адрес, который виден (10.15.15.142), это IP-адрес LAN, назначенный первому интерфейсу системы. Здесь я теряюсь, мы указываем подключение к localhost, но MySQL видит подключение как идущее с этого IP-адреса. Почему?

Открытие оболочки и введение “mysql -u myuser -p” позволит подключиться без проблем.

Исследование предположило принудительное использование Unix-сокета для подключения, указывая “Protocol=unix”, но это не привело к улучшению:

2025-01-06 14:05:53.176 +01:00 [INF] OpenConnection => 
Host=localhost;Username=myuser;Password='mypass';Database=; Connection Timeout=360;Allow User Variables=True;Protocol=unix
2025-01-06 14:05:53.263 +01:00 [ERR] Error connecting to mysql server Failed
MySqlConnector.MySqlException (0x80004005): Cannot find Unix Socket at localhost

Мы также пробовали использовать 127.0.0.1 вместо localhost для строки подключения, но результат тот же. Также проверили, что файл hosts в системе настроен правильно. Мы также подтвердили, что смена пользователя на myuser@% работает как положено, но как только она изменяется на myuser@localhost, проблема возвращается.

Версии:

Microsoft.AspNetCore.App 7.0.20 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.36 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.20 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
mysql  Ver 8.0.35 for Linux on x86_64 (MySQL Community Server - GPL)

Когда пакеты поступают из одного источника, их сопровождающие пытаются сделать так, чтобы все работало без проблем. Но похоже, что .NET клиентская библиотека, вероятно, поступает не из того же источника, что и MySQL серверный пакет. У каждого пакета есть некоторые настройки по умолчанию — пути и так далее, и в данном случае некоторые из этих настроек не совпадают.

Одной из таких настроек, которую мы обнаружили, является путь к Unix-сокету по умолчанию. Должен быть способ его указать, так что в общем случае, когда говорится, что сокет не найден, но другая программа (консольный клиент mysql) может его найти, вы можете просто указать путь, и это должно сработать.

Еще одно различие заключается в том, что “стандартный” libmysqlclient автоматически переключается на Unix-сокеты, когда он видит localhost, но ваша клиентская библиотека этого не делает, поэтому ей нужно указать использовать Unix-сокеты.

Наконец, обратите внимание на нетривиальное поведение предоставления доступа в отношении имен хостов. Ваши таблицы предоставления MySQL, вероятно, содержат предоставления для username@localhost, а не для username@whatever или подстановки username@%. Такие предоставления для localhost определенно работают, когда вы подключаетесь через Unix-сокет. Они также должны работать для TCP от localhost к localhost, но это зависит от разрешения имен, и необычные настройки разрешения имен могут делать его похожим на что-то другое, даже когда вы, кажется, используете адреса localhost. Например, ваше соединение может исходить от 127.0.1.1, который может быть связан с каким-то альтернативным именем в файле hosts, так что когда происходит обратное разрешение на сервере, происходит вывод этого альтернативного имени вместо localhost, и сервер не распознает соединение как исходящее от localhost и не применяет доступы для localhost.

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

Проблема, с которой вы столкнулись, связана с тем, как MySqlConnector обрабатывает подключение к MySQL-серверу на том же самом хосте. Несмотря на указание ‘localhost’ в строке подключения, сервер воспринимает попытку подключения как исходящую с IP-адреса вашей системы в локальной сети. Давайте рассмотрим возможные причины и решения этой проблемы.

Теория:

  1. Протокол подключения: Когда MySQL клиент сталкивается с ‘localhost’, он часто переключается на использование Unix-сокетов по умолчанию. Однако не все клиентские библиотеки выполняют такое переключение автоматически. Это может привести к попытке установить соединение через сетевой интерфейс, что выявляется в виде LAN-адреса.

  2. Разрешение имён: Ваш сервер может выполнять обратное разрешение имён, и если одна из записей hosts связана с другим именем, а не с ‘localhost’, это может влиять на распознавание подключения как исходящего с ‘localhost’.

  3. Путь Unix-сокета: Пакеты и библиотеки могут иметь разные настройки по умолчанию, включая места расположения сокетов. Отсутствие заданного пути может приводить к ошибке подсистемы Unix-сокетов.

Пример:

Возьмем два приложения: одно, использующее стандартный MySQL клиент в командной строке, и другое – dotnet приложение с использованием MySqlConnector. Первое приложение успешно подключается через локальный Unix-сокет, в то время как второе сталкивается с ошибкой из-за использования IP-адреса. В первом случае соединение происходит через сокеты, а во втором через TCP/IP.

Применение:

  1. Настройка Unix-сокетов: Во-первых, попробуйте указать точный путь к Unix-сокету в вашей строке подключения. Обычно MySQL использует путь вроде /var/run/mysqld/mysqld.sock, но это можно уточнить в конфигурации MySQL или через mysqladmin variables|grep socket.

  2. Явное указание протокола подключения: Добавлеите не только Protocol=unix в вашу строку подключения, но и укажите параметр UnixSocket=/путь/к/sock, чтобы принудительно использовать сокеты.

  3. Проверка и настройка файла hosts: Убедитесь, что файл /etc/hosts корректно содержит запись для ‘localhost’. Это должно исключить возможность, что обратное разрешение приводит к получению неверного имени хоста.

  4. Изменение разрешений доступа: Если возможно, создайте пользователя myuser с разрешением на myuser@127.0.0.1, чтобы обойти проблему с некорректным разрешением имен при работе через TCP/IP.

Настройка вышеперечисленных параметров позволит вашему dotnet приложению подключаться к MySQL серверу через Unix-сокеты на том же хосте, используя корректные права доступа и избегая проблем с сетью.

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

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