无法通过 SSH 连接到 MySQL
Trouble Connecting to MySQL via SSH
我 运行 在我的本地 OS X 机器上创建一个 node Express 网站。
我需要通过 ssh 连接到远程 mysql 数据库,这样我才能开始针对它编写查询。
现在我可以通过 OS X [=147= SSH 连接到云中的远程服务器(运行连接 mysql 数据库) ] 终端机。
但是我尝试使用 node-mysql 和 tunnel-ssh 节点中间件在代码中尝试这样做并没有成功。
我的代码 运行s 但在 Webstorm 中调试我的 express 应用程序时除了 GET 之外并没有真正出错。
一些事实:
我可以使用以下命令从 OS X 通过 SSH 连接到 mySQL:
ssh -L 3306:127.0.0.1:3306 ourCloudServerName.net MyUserNameHere
然后我可以使用以下命令连接到 mySQL:
mysql -h localhost -p -u myUserNameHere
当我在 mysql 命令提示符下输入 SHOW GLOBAL VARIABLES LIKE 'PORT' 时,我得到服务器(或数据库,我想这意味着......不确定)是 运行ning 在端口 3306
我正在通过 Webstorm 10.0.3 进行调试
这意味着我正在调试像这样启动的 Node Express 应用程序:
var 端口 = 3000;
app.set('port', 端口);
app.listen(app.get('port'), 函数(){
console.log('Express web server is listening on port ' + app.get('port'));
})
- 我可以在 Chrome
中通过 localhost:3000 运行 我的快捷应用
现在这是我第一次尝试同时使用 node-mysql 和 tunnel-ssh
mysqlConfig.js
var databaseConfig = module.exports = function(){};
module.exports = {
mySQLConfig: {
host: '127.0.0.1',
username: 'root',
password: 'rootPassword',
database: 'SomeDatabaseName',
port: 3306,
timeout: 100000
},
sshTunnelConfig: {
username: 'myusername',
password: 'mypassword',
host: 'ourCloudServerName\.net',
port: 22,
//localPort: 3306, //4370
//port: 3333,
//localPort: 4370,
dstPort: 3306,
srcHost: 'localhost',
dstHost: 'localhost',
localHost: 'localhost'
}
};
connection.js
var mysql = require('mysql'),
config = require('./mysqlConfig'),
tunnel = require('tunnel-ssh');
var connection = module.exports = function(){};
createDBConnection = function(){
var mysqlConnection = mysql.createConnection({
host: config.mySQLConfig.host,
user: config.mySQLConfig.username,
password: config.mySQLConfig.password,
database: config.mySQLConfig.database,
connectTimeout: config.mySQLConfig.timeout
});
return mysqlConnection;
};
connection.invokeQuery = function(sqlQuery){
var data = undefined;
var sshTunnel = tunnel(config.sshTunnelConfig, function(error, result) {
var sqlConnection = createDBConnection();
sqlConnection.connect(function (err) {
console.log(err.code);
});
sqlConnection.on('error', function (err) {
console.log(err.code);
});
data = sqlConnection.query({
sql: sqlQuery,
timeout: config.mySQLConfig.timeout
}, function (err, rows) {
if (err && err.code) {
console.log("error code: " + err.code)
}
if (err) {
console.error("error stack: " + err.stack)
}
;
if (rows) {
console.log("We have Rows!!!!!!")
}
});
sqlConnection.destroy();
});
return data;
};
路由器/index.js
var connection = require('../config/database/connection');
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
var sqlStatement = "Select top 10 from someTable";
var rows = connection.invokeQuery(sqlStatement);
});
module.exports = router;
所以我尝试在 Webstorm 中进行调试,但我要么从未真正在控制台上打印出正确的错误,要么即使我打印了,也是一个通用的节点错误。我可能有一个基本的代码问题 and/or 只是没有正确设置值或正确使用中间件,我只是不知道,在调试期间它没有告诉我太多。我只知道:
1) 我没有通过 ssh 连接到服务器。调试期间 ssh 服务器对象中的连接显示为 0
2) mysql 连接对象显示断开,从未连接
3) 我在 Webstorm 中也遇到了这个节点错误,而 运行 在没有告诉我 jack:
的快递网站上
什么连接被拒绝了,我运行正在通过本地主机端口 3000 连接这个网站。这是说它无法连接到 ssh 吗?我不知道这里。这并不总是出现或发生,它是一个间歇性错误,可能只是一个 webstorm 调试问题,我只需要再次 运行 调试并且通常会消失......但可能是相互关联的,没有线索。
这是我在调试期间检查配置对象时的内容
并且在 tunnel-ssh/index.js 的第 70 行 returns 它试图创建的服务器,我看到没有 ssh 连接:
更新 - 根据答案中的建议
这是 SELinux 问题,您的 httpd / web 服务器不允许通过网络连接,您的问题的答案是以下命令:
setsebool -P httpd_can_network_connect 1
那么它应该可以正常工作。我相信您正在使用 apache?
如果您需要做的只是从应用程序内部建立 MySQL 连接,这实际上可以简化。 mysql2
模块(更好地)支持传递自定义流以用作数据库连接,这意味着您不必启动本地 TCP 服务器并侦听隧道连接。
var mysql2 = require('mysql2');
var SSH2Client = require('ssh2').Client;
var sshConf = {
host: 'ourCloudServerName.net',
port: 22,
username: 'myusername',
password: 'mypassword',
};
var sqlConf = {
user: 'root',
password: 'rootPassword',
database: 'SomeDatabaseName',
timeout: 100000
};
var ssh = new SSH2Client();
ssh.on('ready', function() {
ssh.forwardOut(
// source IP the connection would have came from. this can be anything since we
// are connecting in-process
'127.0.0.1',
// source port. again this can be randomized and technically should be unique
24000,
// destination IP on the remote server
'127.0.0.1',
// destination port at the destination IP
3306,
function(err, stream) {
// you will probably want to handle this better,
// in case the tunnel couldn't be created due to server restrictions
if (err) throw err;
// if you use `sqlConf` elsewhere, be aware that the following will
// mutate that object by adding the stream object for simplification purposes
sqlConf.stream = stream;
var db = mysql2.createConnection(sqlConf);
// now use `db` to make your queries
}
);
});
ssh.connect(sshConf);
当然,您会希望扩展此示例,在 ssh 和 mysql 级别添加错误处理,以防因某种原因(TCP 连接被切断或 ssh/mysql例如服务停止)。通常,您只需为 ssh
和 db
添加 error
事件处理程序即可处理大多数情况,尽管您可能还想监听 end
事件以了解何时需要重新-建立 either/both ssh
和 db
连接。
此外,在 ssh 和 mysql 级别配置 keepalive 可能是明智的。 ssh2
有几个 keepalive options 的行为就像 OpenSSH 客户端的 keepalive 选项。
对于 mysql2
,通常我所做的只是在某个时间间隔调用 db.ping()
。您可以传入一个回调,该回调将在服务器响应 ping 时调用,因此您可以使用一个额外的计时器,该计时器会在回调执行时被清除。这样如果回调没有执行,你可以尝试重新连接。
我 运行 在我的本地 OS X 机器上创建一个 node Express 网站。
我需要通过 ssh 连接到远程 mysql 数据库,这样我才能开始针对它编写查询。
现在我可以通过 OS X [=147= SSH 连接到云中的远程服务器(运行连接 mysql 数据库) ] 终端机。
但是我尝试使用 node-mysql 和 tunnel-ssh 节点中间件在代码中尝试这样做并没有成功。
我的代码 运行s 但在 Webstorm 中调试我的 express 应用程序时除了 GET 之外并没有真正出错。
一些事实:
我可以使用以下命令从 OS X 通过 SSH 连接到 mySQL:
ssh -L 3306:127.0.0.1:3306 ourCloudServerName.net MyUserNameHere
然后我可以使用以下命令连接到 mySQL:
mysql -h localhost -p -u myUserNameHere
当我在 mysql 命令提示符下输入 SHOW GLOBAL VARIABLES LIKE 'PORT' 时,我得到服务器(或数据库,我想这意味着......不确定)是 运行ning 在端口 3306
我正在通过 Webstorm 10.0.3 进行调试 这意味着我正在调试像这样启动的 Node Express 应用程序:
var 端口 = 3000;
app.set('port', 端口);
app.listen(app.get('port'), 函数(){ console.log('Express web server is listening on port ' + app.get('port')); })
- 我可以在 Chrome 中通过 localhost:3000 运行 我的快捷应用
现在这是我第一次尝试同时使用 node-mysql 和 tunnel-ssh
mysqlConfig.js
var databaseConfig = module.exports = function(){};
module.exports = {
mySQLConfig: {
host: '127.0.0.1',
username: 'root',
password: 'rootPassword',
database: 'SomeDatabaseName',
port: 3306,
timeout: 100000
},
sshTunnelConfig: {
username: 'myusername',
password: 'mypassword',
host: 'ourCloudServerName\.net',
port: 22,
//localPort: 3306, //4370
//port: 3333,
//localPort: 4370,
dstPort: 3306,
srcHost: 'localhost',
dstHost: 'localhost',
localHost: 'localhost'
}
};
connection.js
var mysql = require('mysql'),
config = require('./mysqlConfig'),
tunnel = require('tunnel-ssh');
var connection = module.exports = function(){};
createDBConnection = function(){
var mysqlConnection = mysql.createConnection({
host: config.mySQLConfig.host,
user: config.mySQLConfig.username,
password: config.mySQLConfig.password,
database: config.mySQLConfig.database,
connectTimeout: config.mySQLConfig.timeout
});
return mysqlConnection;
};
connection.invokeQuery = function(sqlQuery){
var data = undefined;
var sshTunnel = tunnel(config.sshTunnelConfig, function(error, result) {
var sqlConnection = createDBConnection();
sqlConnection.connect(function (err) {
console.log(err.code);
});
sqlConnection.on('error', function (err) {
console.log(err.code);
});
data = sqlConnection.query({
sql: sqlQuery,
timeout: config.mySQLConfig.timeout
}, function (err, rows) {
if (err && err.code) {
console.log("error code: " + err.code)
}
if (err) {
console.error("error stack: " + err.stack)
}
;
if (rows) {
console.log("We have Rows!!!!!!")
}
});
sqlConnection.destroy();
});
return data;
};
路由器/index.js
var connection = require('../config/database/connection');
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
var sqlStatement = "Select top 10 from someTable";
var rows = connection.invokeQuery(sqlStatement);
});
module.exports = router;
所以我尝试在 Webstorm 中进行调试,但我要么从未真正在控制台上打印出正确的错误,要么即使我打印了,也是一个通用的节点错误。我可能有一个基本的代码问题 and/or 只是没有正确设置值或正确使用中间件,我只是不知道,在调试期间它没有告诉我太多。我只知道:
1) 我没有通过 ssh 连接到服务器。调试期间 ssh 服务器对象中的连接显示为 0
2) mysql 连接对象显示断开,从未连接
3) 我在 Webstorm 中也遇到了这个节点错误,而 运行 在没有告诉我 jack:
的快递网站上什么连接被拒绝了,我运行正在通过本地主机端口 3000 连接这个网站。这是说它无法连接到 ssh 吗?我不知道这里。这并不总是出现或发生,它是一个间歇性错误,可能只是一个 webstorm 调试问题,我只需要再次 运行 调试并且通常会消失......但可能是相互关联的,没有线索。
这是我在调试期间检查配置对象时的内容
并且在 tunnel-ssh/index.js 的第 70 行 returns 它试图创建的服务器,我看到没有 ssh 连接:
更新 - 根据答案中的建议
这是 SELinux 问题,您的 httpd / web 服务器不允许通过网络连接,您的问题的答案是以下命令:
setsebool -P httpd_can_network_connect 1
那么它应该可以正常工作。我相信您正在使用 apache?
如果您需要做的只是从应用程序内部建立 MySQL 连接,这实际上可以简化。 mysql2
模块(更好地)支持传递自定义流以用作数据库连接,这意味着您不必启动本地 TCP 服务器并侦听隧道连接。
var mysql2 = require('mysql2');
var SSH2Client = require('ssh2').Client;
var sshConf = {
host: 'ourCloudServerName.net',
port: 22,
username: 'myusername',
password: 'mypassword',
};
var sqlConf = {
user: 'root',
password: 'rootPassword',
database: 'SomeDatabaseName',
timeout: 100000
};
var ssh = new SSH2Client();
ssh.on('ready', function() {
ssh.forwardOut(
// source IP the connection would have came from. this can be anything since we
// are connecting in-process
'127.0.0.1',
// source port. again this can be randomized and technically should be unique
24000,
// destination IP on the remote server
'127.0.0.1',
// destination port at the destination IP
3306,
function(err, stream) {
// you will probably want to handle this better,
// in case the tunnel couldn't be created due to server restrictions
if (err) throw err;
// if you use `sqlConf` elsewhere, be aware that the following will
// mutate that object by adding the stream object for simplification purposes
sqlConf.stream = stream;
var db = mysql2.createConnection(sqlConf);
// now use `db` to make your queries
}
);
});
ssh.connect(sshConf);
当然,您会希望扩展此示例,在 ssh 和 mysql 级别添加错误处理,以防因某种原因(TCP 连接被切断或 ssh/mysql例如服务停止)。通常,您只需为 ssh
和 db
添加 error
事件处理程序即可处理大多数情况,尽管您可能还想监听 end
事件以了解何时需要重新-建立 either/both ssh
和 db
连接。
此外,在 ssh 和 mysql 级别配置 keepalive 可能是明智的。 ssh2
有几个 keepalive options 的行为就像 OpenSSH 客户端的 keepalive 选项。
对于 mysql2
,通常我所做的只是在某个时间间隔调用 db.ping()
。您可以传入一个回调,该回调将在服务器响应 ping 时调用,因此您可以使用一个额外的计时器,该计时器会在回调执行时被清除。这样如果回调没有执行,你可以尝试重新连接。