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

Я запускаю веб-сайт node Express на своем компьютере с OS X локально.

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

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

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

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

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

  • Я могу использовать SSH в mySQL из OS X, используя эту команду:

    ssh -L 3306:127.0.0.1:3306 ourCloudServerName.net MyUserNameЗдесь

  • Затем я могу подключиться к mySQL, используя следующую команду:

    mysql -h localhost -p -u имя_пользователяздесь

  • Когда я нахожусь в командной строке mysql и набираю SHOW GLOBAL VARIABLES LIKE 'PORT', я получаю, что сервер (или база данных, я думаю, это означает... не уверен) работает на порту 3306

  • Я отлаживаю через Webstorm 10.0.3. Это означает, что я отлаживаю свое приложение Node Express, которое начинается так:

    вар порт = 3000;

    app.set('порт', порт);

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

    • I can run my express app via localhost:3000 in Chrome

Теперь это моя первая попытка использовать как node-mysql, так и туннель-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. Соединения показывают 0 в объекте сервера ssh во время отладки

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

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

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

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

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

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

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

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

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

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


person PositiveGuy    schedule 05.06.2015    source источник
comment
Можете ли вы попробовать console.log(ошибка, результат) внутри обратного вызова туннеля SSH, чтобы увидеть, что такое ошибка SSH?   -  person Jack Guy    schedule 05.06.2015
comment
куда бы я поместил это сразу после закрытия соединения с БД (строка уничтожения)?   -  person PositiveGuy    schedule 05.06.2015
comment
Прямо в начале вашего обратного вызова (после var sshTunnel...). Если то, что написано в вашем посте, верно, SSH-соединение никогда не устанавливается, поэтому нам нужно выяснить, в чем причина.   -  person Jack Guy    schedule 05.06.2015
comment
Мне также нужно подтвердить, что мои значения конфигурации выглядят правильно. Я думаю, что понял их правильно... но кто знает... Я основываюсь на том, как я подключился через ssh в терминале, но я не уверен, подключаю ли я правильные значения к dstPort, dstHost и т. д. или если Мне даже нужны все переменные, которые я настроил в TBH. У меня нет возможности подтвердить, был ли вызов ssh-соединения вообще получен или не выполнен из-за недопустимых значений конфигурации, которые отклонены Ubuntu / mySQL или что-то еще, поэтому я лечу вслепую.   -  person PositiveGuy    schedule 05.06.2015
comment
Интересно, могли бы вы использовать 127.0.0.1 вместо localhost; Я знаю, что они должны быть одинаковыми, но это устраняет еще одну потенциальную проблему.   -  person Ja͢ck    schedule 05.06.2015
comment
хорошая идея джек, попробую   -  person PositiveGuy    schedule 05.06.2015
comment
не делал различий, жестко закодировал 127   -  person PositiveGuy    schedule 05.06.2015
comment
@ J4G да, когда я записываю ошибку, оба результата не определены.   -  person PositiveGuy    schedule 05.06.2015


Ответы (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.

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

person mscdex    schedule 05.06.2015
comment
спасибо попробую. Интересно, тогда какой смысл в connect-ssh - person PositiveGuy; 05.06.2015
comment
сладкий! появляется у меня есть соединение ssh. Просто получаю ошибки аутентификации mysql сейчас, работаю над этим, надеюсь, скоро все заработает. Я даже не видел mysql2, wtf! должен был использовать это в первую очередь! - person PositiveGuy; 05.06.2015
comment
Я предполагаю, что это был просто вопрос опробования другого промежуточного программного обеспечения mysql. Спасибо - person PositiveGuy; 05.06.2015
comment
Спасибо за помощь. - person PositiveGuy; 05.06.2015
comment
@mscdex Это не работает для SSL-соединений с MySQL. Вы в курсе, в чем может быть проблема? Хост, который я использую, не является локальным. Это выдает ошибку тайм-аута для SSL-соединений, но работает, когда я подключаюсь с помощью замазки. - person Akhoy; 17.05.2019
comment
@Akhoy Если сервер MySQL не совпадает с сервером SSH, вам придется заменить адрес назначения '127.0.0.1' в коде ответа на ip/хост сервера MySQL, который доступен с сервера SSH. - person mscdex; 17.05.2019
comment
@mscdex Извините, должно было быть понятнее. Упомянутое вами изменение уже существует в моем коде, но оно работает для не-SSL-подключений к серверу MySQL. Время просто истекает, когда я добавляю свойство SSL в свой объект конфигурации MySQL. Я пытаюсь подключиться к экземпляру AWS RDS. Не уверен, в чем может быть проблема. - person Akhoy; 17.05.2019

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

setsebool -P httpd_can_network_connect 1

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

person maqsimum    schedule 05.06.2015
comment
Я попытался вставить это в терминал (на моем локальном компьютере с OS X), но он не распознает setsebool - person PositiveGuy; 05.06.2015
comment
Разве эту команду не следует копировать в SSH-терминал, другими словами, на сервер, к которому вы пытаетесь подключиться? - person Peter; 05.06.2015
comment
если это должно быть запущено из Ubuntu, у меня нет доступа к серверу, и я не знаю, зачем мне это нужно запускать, если я могу использовать ssh из своей OS X, но не могу в узле - person PositiveGuy; 05.06.2015
comment
@pbwned, что вы имеете в виду, скопировано в SSH-терминал. - person PositiveGuy; 05.06.2015
comment
Насколько я понимаю, вы скопировали команду, которую дал вам maqsimum, в свой терминал OS X, верно? Но вы используете SSH на другом сервере (называемом ourCloudServerName). Скопируйте код туда.. - person Peter; 05.06.2015
comment
@WeDoTDD вам нужно запустить эту команду на вашем веб-сервере, где запущен ваш httpd или ваше приложение. Где работает ваше приложение node в OS X? - person maqsimum; 05.06.2015
comment
Я не обслуживаю этот сервер. Я не могу просто запустить эту команду на сервере Ubuntu, на котором работает mysql. - person PositiveGuy; 05.06.2015
comment
Мое приложение работает локально на моем Macbook Pro / Yosemite, а не на сервере apache, поскольку это весь новый код только в моей локальной среде разработки, только на моем ПК. Вот почему я запускаю его и отлаживаю в webstorm, все локально, но хочу попасть в эту удаленную БД через ssh. БД работает в Ubuntu/apache - person PositiveGuy; 05.06.2015
comment
@WeDoTDD Снова выполните свой первый шаг, как указано в вашем вопросе здесь, чтобы подключиться к серверу mysql, затем запустите запрос show processlist; и посмотрите, какое имя вашего хоста в результате, а затем убедитесь, что вашему пользователю вашего приложения узла предоставлены привилегии grant all to db.* on 'user'@'host'; Более того, это похоже, что ваш запрос направляется через ваш сервер Ubuntu, нам нужно понимать, что если ваш запрос идет из Ubuntu в MysQL с использованием httpd, то вы все равно должны выполнить команду, которую я предложил в ответе, иначе вы не сможете добиться желаемого. - person maqsimum; 05.06.2015
comment
одна вещь, которую я получаю, когда я связываюсь по ssh: адрес уже используется ... хотя я все еще могу успешно подключиться к Ubuntu ... просто к сведению - person PositiveGuy; 05.06.2015
comment
кто бы мог подумать, что это будет связано только с тем, чтобы заставить узел общаться с mysql. Я точно не ожидал. - person PositiveGuy; 05.06.2015
comment
да не повезло после предоставления привилегий - person PositiveGuy; 05.06.2015
comment
Я запустил setsebool на нашем удаленном сервере, и он говорит, что он даже не установлен. - person PositiveGuy; 05.06.2015