Node.jsでsshポートフォワーディングを行う方法 tunnel-ssh

プログラミング
スポンサーリンク

挨拶と前書き

ウーバーイーツを始めようと思い準備を勧めているなおこです。

今回はレンタルサーバーなどの外部からデータベースへの接続を制限されてるけどSSH接続は余裕にできまっせといったサービスを利用しているときに役に立ちそうな小技をご紹介したいと思います。

今回の内容に必要な知識は下記ぐらいなのである程度プログラムやサーバーに触れたことのある方であれば大丈夫だと思う。

  • sshポートフォワーディングに関する基礎知識
  • Node.jsの基礎知識
  • mysqlの基礎知識

イメージはこんな感じ

本題

プログラムだけ見たいんじゃって人は

下記のプログラム全文を表示するをクリックやタップしていただくと表示されます。

'use strict';

// パッケージを読み込み
const mysql = require('mysql');
const ssh = require('tunnel-ssh');
const fs = require('fs');

// sshトンネルを開始
ssh({
    username: "sshのユーザー名",//適時変更
    port: "sshのポート番号",//適時変更
    host: "sshのホスト名",//適時変更
    privateKey:fs.readFileSync("ssh鍵のpath"),//適時変更
    passphrase: "鍵のパスフレーズ",//適時変更
    dstPort: "データベースのポート番号",//適時変更
    dstHost: "データベースのホスト名",//適時変更
    localHost: "ホスト名",//適時変更
    localPort: "ポート番号"//適時変更
}, function (errssh) {
    if (errssh) {
        console.log(errssh);
        process.exit();
    }
    console.log('connected');

    // mysqlに接続
    let connection = mysql.createConnection({
        host     : "ホスト名",//適時変更
        user     : "ユーザー名",//適時変更
        password : "パスワード",//適時変更
        port     : "ポート番号",//適時変更
        database : "データベース名"//適時変更
    });


    // SELECT文を実行
    connection.query("SELECT * FROM main;", (err, res) => {
        if (err) {throw err; }
        
        let result = Object.values(JSON.parse(JSON.stringify(res)));
         console.log(result);
    });

    // mysqlから切断
    connection.end();

});

事前準備

nodejsの準備やサーバー側の設定を事前に済ませておいてください。

今回のやり方を用いてsshポートフォワーディング経由でmysqlに接続する場合、使うパッケージは下記の3点になります。

事前に npm install fs mysql tunnel-ssh などで導入しておいてください。

fs

Just a moment...

tunnel-ssh

Just a moment...

mysql

Just a moment...

プログラムを書いていく

パッケージの読み込みを行う

最初の数行でパッケージの読み込みを行うのはnodejsあるあるの書き方ですね。

'use strict';

// パッケージを読み込み
const mysql = require('mysql');
const ssh = require('tunnel-ssh');
const fs = require('fs');

SSHトンネルでポートフォワーディングを行う

ここが大事な部分sshポートフォワーディングを行います。

イメージ的にはmysqlと通信するようのトンネルを作る感じですかね。

localPortの部分にクライアント側で指定する任意のポート番号を設定する感じ。

最初の図で言うところの53306ポートですね



// sshトンネルを開始
ssh({
    username: "sshのユーザー名",//適時変更
    port: "sshのポート番号",//適時変更
    host: "sshのホスト名",//適時変更
    privateKey:fs.readFileSync("ssh鍵のpath"),//適時変更
    passphrase: "鍵のパスフレーズ",//適時変更
    dstPort: "データベースのポート番号",//適時変更
    dstHost: "データベースのホスト名",//適時変更
    localHost: "ホスト名",//適時変更
    localPort: "ポート番号"//適時変更
}, function (errssh) {
    if (errssh) {
        console.log(errssh);
        process.exit();
    }
    console.log('connected');

mysqlに接続する

ポートの部分はsshトンネル時に設定したlocalPortの値を入れる形になります。


    // mysqlに接続
    let connection = mysql.createConnection({
        host     : "ホスト名",//適時変更
        user     : "ユーザー名",//適時変更
        password : "パスワード",//適時変更
        port     : "ポート番号",//適時変更
        database : "データベース名"//適時変更
    });

mysqlでSELECT文を実行する

無事データベースに接続することができたら事前に作成しておいたmainテーブルの内容をSELECT文で表示してみる。




    // SELECT文を実行
    connection.query("SELECT * FROM main;", (err, res) => {
        if (err) {throw err; }
        
        let result = Object.values(JSON.parse(JSON.stringify(res)));
        console.log(result);
    });

mysqlから切断する。

SELECT文の実行、結果を表示し終わったらmysqlの接続を切断しsshの接続も});で終了します。



    // mysqlから切断
    connection.end();
});

完成したプログラム。

'use strict';

// パッケージを読み込み
const mysql = require('mysql');
const ssh = require('tunnel-ssh');
const fs = require('fs');

// sshトンネルを開始
ssh({
    username: "sshのユーザー名",//適時変更
    port: "sshのポート番号",//適時変更
    host: "sshのホスト名",//適時変更
    privateKey:fs.readFileSync("ssh鍵のpath"),//適時変更
    passphrase: "鍵のパスフレーズ",//適時変更
    dstPort: "データベースのポート番号",//適時変更
    dstHost: "データベースのホスト名",//適時変更
    localHost: "ホスト名",//適時変更
    localPort: "ポート番号"//適時変更
}, function (errssh) {
    if (errssh) {
        console.log(errssh);
        process.exit();
    }
    console.log('connected');

    // mysqlに接続
    let connection = mysql.createConnection({
        host     : "ホスト名",//適時変更
        user     : "ユーザー名",//適時変更
        password : "パスワード",//適時変更
        port     : "ポート番号",//適時変更
        database : "データベース名"//適時変更
    });


    // SELECT文を実行
    connection.query("SELECT * FROM main;", (err, res) => {
        if (err) {throw err; }
        
        let result = Object.values(JSON.parse(JSON.stringify(res)));
         console.log(result);
    });

    // mysqlから切断
    connection.end();

});

最後に余談など

これでわざわざシェルスクリプトなどで別途sshを接続する処理を書いたりする必要はなくnodejs内で完結させることができますね。

レンタルサーバーとかじゃないとこのような特殊な状況はまず無いですが、覚えておくと極まれに役に立つかもしれません

今回は設定ファイルを作成しませんでしたが、実際に運用する場合はサーバーなどの接続情報や固定の値は外部に設定ファイルを作成しておくと良いでしょう。


あとそういえば今回もサムネイルを描いて見ました。nodejsをイメージしたキャラクターがsshトンネルに入っていく様子を描きたかったけど背景をうまくかけなかったのでAC素材とボカシでごまかしちゃいました。

キャラクターももうちょいきれいにしたいな〜っと思ったりと絵は楽しいね。

また次のブログでお会いしましょうby

コメント

タイトルとURLをコピーしました