无法通过SSH连接到MySQL

时间:2015-06-05 05:25:21

标签: javascript node.js ubuntu ssh node-mysql

我在本地OS X机器上运行节点Express网站。

我需要ssh到一个远程mysql数据库,所以我可以开始编写查询。

现在我可以通过我的OS X Yosemite终端在云端ssh到我们的远程服务器(运行mysql数据库)。

但是我没有成功尝试使用node-mysql和tunnel-ssh节点中间件在代码中进行此操作。

我的代码运行但除了在Webstorm中调试我的快速应用程序时的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'时,我得到服务器(或数据库,我猜这意味着......不确定)在端口3306上运行

  • 我正在通过Webstorm 10.0.3进行调试 这意味着我正在调试我的Node Express应用程序,它的启动方式如下:

    var port = 3000;

    app.set('port',port);

    app.listen(app.get('port'),function(){     console.log('Express Web服务器正在侦听端口'+ 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中调试,我或者从来没有真正得到一个很好的错误打印到控制台或如果我这样做,这是一个通用的节点错误,如。我可能有一个基本的代码问题和/或只是没有正确设置值或正确使用中间件,我只是不知道,它在调试期间没有告诉我太多。我只知道:

1)我没有通过ssh与服务器建立连接。在调试期间,连接在ssh服务器对象中显示0

2) mysql连接对象显示断开连接,从未连接

3)我在运行快递网站时也在Webstorm中收到此节点错误,但没有告诉我杰克:

enter image description here

什么连接被拒绝,我通过localhost端口3000运行这个网站。这是说它无法连接到ssh吗?我不知道在这里。这并不总是显示或发生,这是一个间歇性的错误,可能只是一个webstorm调试的东西,我只需要再次运行调试,通常会消失...但可能是相互关联的,没有任何线索。

这是我在调试期间检查出来时配置对象的内容

enter image description here enter image description here enter image description here

在tunnel-ssh / index.js第70行,它返回它尝试创建的服务器,我看到没有ssh连接:

enter image description here

更新 - 根据答案提出的建议

enter image description here enter image description here enter image description here enter image description here

2 个答案:

答案 0 :(得分:4)

如果您需要做的只是从应用程序内部隧道MySQL连接,这实际上可以简化。 mysql2模块(更好)支持传递自定义流以用作数据库连接,这意味着您不必启动本地TCP服务器并侦听通过隧道的连接。

以下是使用mysql2ssh2的示例:

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服务停止)而消失。通常,您只需为errorssh添加db个事件处理程序来处理大多数情况,但您可能也想要监听end事件,以了解何时需要重新启动 - 建立sshdb连接中的一个/两个。

此外,在ssh和mysql级别配置keepalive可能是明智之举。 ssh2有几个keepalive options,其行为与OpenSSH客户端的keepalive选项一样。 对于mysql2,通常我所做的只是在某个时间间隔内调用db.ping()。您可以传入将在服务器响应ping时调用的回调,因此可以使用在回调执行时清除的其他计时器。这样,如果回调没有执行,你可以尝试重新连接。

答案 1 :(得分:0)

这是SELinux问题,你的httpd / webserver不允许通过网络连接,你的问题答案如下:

setsebool -P httpd_can_network_connect 1

它应该工作正常。我相信你正在使用apache?