BETA

【Node.js】SSH経由でRedisへ接続する

投稿日:2019-04-14
最終更新:2019-04-14
※この記事は外部サイト(https://qiita.com/uki00a/items/4dcc13ce571...)からのクロス投稿です

概要

ioredisssh2モジュールを使用して、SSH経由でRedisへ接続します。

環境

  • Node.js v8.15.0
  • ioredis v4.2.0
  • ssh2 v0.8.2

方法

依存モジュールを読み込みます。

const Redis = require('ioredis');  
const { Client: SSHClient } = require('ssh2');  
const net = require('net');  
const fs = require('fs');  

SSHサーバへ接続する関数を用意します。

function connectToSSH(options) {  
  return new Promise((resolve, reject) => {  
    const connection = new SSHClient();  

    connection.once('ready', () => resolve(connection));  
    connection.once('error', reject);  

    connection.connect(options);  
  });  
}  

Redisへ接続するためのヘルパー関数を用意します。

function connectToRedis(options) {  
  const redis = new Redis(options);  
  return new Promise((resolve, reject) => {  
    redis.once('error', reject);  
    redis.once('ready', () => resolve(redis));  
  });  
}  

ポートフォワーディング用の中間サーバを作成します。

server.listenの第1引数に0を渡すと、システムの空きポートが割り当てられます。

function createIntermediateServer(connectionListener) {  
  return new Promise((resolve, reject) => {  
    const server = net.createServer(connectionListener);  
    server.once('error', reject);   
    server.listen(0, () => resolve(server));  
  });  
}  

一連のヘルパー関数をまとめて、SSH経由でRedisへ接続する関数を用意します。

async function connectToRedisViaSSH(options = {  
  ssh: {  
    host: 'localhost',  
    port: 22  
  },  
  redis: {  
    host: 'localhost',  
    port: 6379  
  }  
}) {  
  const sshConnection = await connectToSSH({  
    host: options.ssh.host,  
    port: options.ssh.port,  
    username: options.ssh.username,  
    privateKey: options.ssh.privateKey,  
    passphrase: options.ssh.passphrase  
  });  

  const server = await createIntermediateServer(socket => {  
    sshConnection.forwardOut(  
      socket.remoteAddress,  
      socket.remotePort,   
      options.redis.host,  
      options.redis.port,  
      (error, stream) => {  
        if (error) {  
          socket.end();  
        } else {  
          socket.pipe(stream).pipe(socket);  
        }  
      }  
    );  
  });  

  // Redisサーバのアドレスではなく、中間サーバのアドレスを指定します。  
  const redis = await connectToRedis({  
    host: server.address().address,  
    port: server.address().port  
  });  

  return redis;  
}  

作成した関数を利用してRedisへ接続します。

const redis = await connectToRedisViaSSH({  
  ssh: {  
    host: '<ssh-server-address>',  
    port: 22,  
    username: '<username>',  
    privateKey: fs.readFileSync('/path/to/private-key'),  
    passphrase: '<passphrase>'  
  },  
  redis: {  
    host: '<redis-server-address>',  
    port: 6379  
  }  
});  
const keys = await redis.keys('*');  
console.log(keys);  

参考

https://gist.github.com/luoyjx/b2ea3cfaa20fee43258573b90c2e01a9

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@uki00aの技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!