Проблемы с подключением к MySQL через SSH

Я использую сайт узла Express на моей машине с OS X локально.

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

Теперь я могу подключиться к нашему удаленному серверу (работающему с базой данных mysql) в облаке, когда я делаю это через мой терминал OS X Yosemite.

Но я не добился успеха, пытаясь сделать это в коде, используя промежуточное программное обеспечение узла node-mysql и tunnel-ssh.

Мой код работает, но на самом деле не выдает ошибку, за исключением моего GET при отладке моего экспресс-приложения в Webstorm.

Некоторые факты:

  • Я могу SSH в MySQL из OS X с помощью этой команды:

    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 ("порт", порт);

    app.listen (app.get ('port'), function () {console.log ('Экспресс-веб-сервер прослушивает порт' + app.get('port')); })

    • Я могу запустить свое экспресс-приложение через localhost:3000 в Chrome

Теперь вот моя первая попытка попробовать использовать оба узла-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;
};

router /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. Соединения показывают 0 в объекте сервера ssh во время отладки

2) MySQL объект подключения показывает отключен, никогда не подключен

3) Я также получаю эту ошибку узла в Webstorm во время работы экспресс-сайта, который не сообщает мне:

введите описание изображения здесь

В каком соединении отказано, я запускаю этот сайт через локальный порт 3000. Это говорит о том, что он не может подключиться к ssh? Я понятия не имею, здесь. Это не всегда проявляется или происходит, это периодически возникающая ошибка, и она может быть просто отладкой веб-шторма, когда мне просто нужно снова запустить отладку и обычно она исчезает... но может быть взаимосвязана, без понятия.

И вот что имеет мой объект конфигурации, когда я проверяю его во время отладки

введите описание изображения здесьвведите описание изображения здесьвведите описание изображения здесь

И в tunnel-ssh / index.js, строка 70, где он возвращает сервер, который пытается создать, я вижу, что ssh-соединения нет:

введите описание изображения здесь

ОБНОВЛЕНИЕ - согласно предложениям от ответов

введите описание изображения здесьвведите описание изображения здесьвведите описание изображения здесьвведите описание изображения здесь

2 ответа

Решение

Это на самом деле может быть упрощено, если все, что вам нужно сделать, это туннелировать соединения MySQL из вашего приложения. mysql2 Модуль (лучше) поддерживает передачу пользовательского потока для использования в качестве соединения с базой данных, это означает, что вам не нужно запускать локальный TCP-сервер и прослушивать соединения для туннелирования.

Вот пример использования mysql2 а также ssh2:

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 остановлены, например). Как правило, вы можете просто добавить error обработчики событий для ssh а также db обрабатывать большинство случаев, хотя вы можете слушать end события, чтобы знать, когда вам нужно восстановить либо ssh а также db соединения.

Кроме того, может быть целесообразно настроить keepalive как на уровне ssh, так и на уровне mysql. ssh2 имеет несколько опций keepalive, которые ведут себя так же, как опцию keepalive клиента OpenSSH. За mysql2 Обычно я просто звоню db.ping() на некотором интервале. Вы можете передать обратный вызов, который будет вызван, когда сервер ответит на эхо-запрос, так что вы можете использовать дополнительный таймер, который очищается при выполнении обратного вызова. Таким образом, если обратный вызов не выполняется, вы можете попытаться восстановить соединение.

Это проблема SELinux, и вашему httpd / webserver не разрешено подключаться по сети, ответьте на вашу проблему следующей командой:

setsebool -P httpd_can_network_connect 1

Это должно работать нормально тогда. Я полагаю, вы используете Apache?

Другие вопросы по тегам