使用SSH隧道连接MySQL主机失败问题求助
错误信息
Connection.Open() Error: MySqlConnector.MySqlException: 'Unable to connect to any of the specified MySQL hosts.'
问题描述
尝试多种代码方案仍触发上述错误,需通过跳板机连接EC2上的生产MySQL数据库。将连接字符串改为localhost时仅能连接本地数据库,端口转发操作未解决问题。
问题排查与修复方案
你的代码存在核心逻辑错误:构建了正确的隧道连接字符串connStr,但实际使用的却是配置文件中的mySQLConnectionString,直接导致端口隧道未被利用,自然无法连接生产库。同时还有几个细节需要调整:
- 区分跳板机与数据库地址:当前代码把同一个
_host同时用作SSH跳板机地址和数据库地址,若跳板机和EC2数据库不是同一台服务器,必须分开配置。 - 端口转发目标地址:如果MySQL部署在EC2本地(相对于跳板机),目标地址应写
127.0.0.1而非MyDbHost,跳板机访问本地数据库用localhost即可。 - 延长连接超时时间:当前3秒超时过短,网络波动时极易失败,建议调整为15秒以上。
修正后的完整代码
static bool isFirstTimeSSH() { Console.WriteLine("Verificando se é a primeira vez"); // 跳板机配置 string jumpboxHost = "你的跳板机IP或域名"; int jumpboxPort = 22; string jumpboxUser = "MyUserSSH"; string privateKeyPath = @"MyKeyPath"; string privateKeyPassPhrase = ""; // 生产MySQL配置(相对于跳板机的访问地址) string dbHost = "127.0.0.1"; // 若MySQL在EC2本地,跳板机访问用127.0.0.1;其他情况填实际地址 int dbPort = 3306; string dbName = "database"; string dbUser = "MyDbUser"; string dbPass = "MyDbPass"; var privateKeyStream = new PrivateKeyFile(privateKeyPath, privateKeyPassPhrase); var ci = new PrivateKeyConnectionInfo(jumpboxHost, jumpboxPort, jumpboxUser, privateKeyStream); using (var client = new SshClient(ci)) { client.Connect(); if (client.IsConnected) { // 建立端口转发:本地随机端口 转发到 跳板机可访问的数据库地址 var portForwarded = new ForwardedPortLocal("127.0.0.1", 0, dbHost, dbPort); client.AddForwardedPort(portForwarded); portForwarded.Start(); Console.WriteLine($"隧道已建立,本地绑定端口:{portForwarded.BoundPort}"); // 使用隧道连接字符串 string connStr = string.Format( "Server={0};Port={1};Database={2};Uid={3};Pwd={4};SslMode=none;default command timeout=30;Connection Timeout=15;MinimumPoolSize=20;maximumpoolsize=500", portForwarded.BoundHost, portForwarded.BoundPort, dbName, dbUser, dbPass); var connection = new MySqlConnection(connStr); var command = connection.CreateCommand(); int numberOfTransactions = 0; try { connection.Open(); command.CommandText = "SELECT count(*) FROM transactions;"; using (MySqlDataReader reader = command.ExecuteReader()) { if (reader.Read()) { numberOfTransactions = Convert.ToInt32(reader[0]); } } return numberOfTransactions < 20; } finally { if (connection.State == ConnectionState.Open) connection.Close(); portForwarded.Stop(); client.Disconnect(); } } else { Console.WriteLine("无法连接到跳板机..."); return false; } } }
额外排查步骤
- 验证跳板机连通性:在跳板机上执行
mysql -h 数据库地址 -u 用户名 -p,确认能正常连接生产库。 - 检查本地防火墙:确保本地未阻止隧道绑定的端口。
- 确认私钥权限:Linux跳板机上的私钥文件权限需设置为600,避免权限过高导致SSH连接失败。
内容的提问来源于stack exchange,提问作者Gabriel Barros
相关产品推荐
相关产品推荐

