SSHの小技集(ログインからポートフォワード、Pythonを利用した自動化まで)
はじめに
MacBook Proとモバイル回線で作業をする様な場合に良く利用するSSHの使い方です。また、サーバー側は、awsの利用を想定しています。
設定編
モバイル回線なので、デフォルトの設定だと頻繁に接続が切れます。
そんな時は、~/.ssh/configに以下の設定を記載します。
これで10秒ごとにパケットを流して接続を維持しようとしてくれます。
(勿論、切られることもあるので、そんな時はscreenなりを活用します。)
ServerAliveInterval 10 TCPKeepAlive yes
基本
ログインしたいサーバが、インターネットに公開されている場合は、以下のように単発のコマンドでログインします。
(証明書での認証を想定しています。)
ssh -i ~/.ssh/<i>foo.pem</i> <i>user</i>@<i>hostname</i>
図にすると以下の様になります。
踏み台の先にあるサーバにログインする
ログインして作業したいサーバが踏み台の先にある場合、一旦、踏み台にログインした後、さらに目的のサーバにログインするのは、面倒なことがあります。そういう場合は、以下の様に
~/.ssh/configファイルに記載しておくことで、自動化されます。
具体的には、ssh target_server とコマンドを打つだけで、自動でJUMP_SERVERを経由してtarget_serverに接続されます。
HOST [target_server] HostName [IP address or host name (1)] User [user name(1)] ProxyCommand ssh -W %h:%p JUMP_SERVER IdentityFile ~/.ssh/foo.pem HOST JUMP_SERVER HostName [IP address or hostname (2)] User [user name(2)] IdentityFile ~/.ssh/bar.pem
※target_serverは、自分の覚えやすい名前に変更してください
※[IP address or host name(1)] は、target_serverのものです。
※[IP address or host name(2)]は、踏み台サーバ(jump server)のものです。
※JUMP_SERVERの所は、字面が一致していれば、なんでも良いです。
踏み台だけをパブリックサブネットに置いて、プライベートサブネット内のワーカーにログインするのは、良く利用するパターンなので、上記の設定で2度ログインする手間を省けます。
ポートフォワード
セキュリティを考慮して、データベース(RDS)やElasticSearchは、外部からは直接接続できない様にすることが普通です。勿論、前述の通り、踏み台を経由して、プライベートサブネット内のマシンにログインして、開発をすることも可能です。しかし、効率面を考慮すると、極力ローカルの慣れたエディタを使いたいケースが多いと思います。
そこでオススメなのが、ポートフォワードです。
例えば、以下の様に、データベースとローカルマシンの間にトンネルを作っておくと、データベースへのアクセスを透過的に扱えます。
これで、踏み台をトンネルして、データベースサーバの5439ポートをローカルの5439ポートへバインドします。
(5439は、Redshiftのデフォルトポートです。適宜バックエンドで動作しているDBのポートに置き換えてください)
ssh -N -i ~/.ssh/[踏み台へ接続するための秘密鍵] -L 5439:[データベースサーバのアドレス]:5439 [ユーザ名]@[踏み台のアドレス]
PythonからSSHで踏み台サーバへログインしてプライベート領域のDBへ接続
上記は、トンネリングはあくまで手動で実施することを想定していました。
ただ、全てをプログラムで制御したい場合も往々にして存在します。
特に、AWS lambdaと組み合わせると、ローカルPCのcronに対するクラウドのcronのごとく、一定間隔で様々な処理が実施できて大変便利です。
では、早速Pythonでのやり方を見ていきたいと思います。
前準備
- 以下のコマンドで、sshtunnelをインストールします。
- pip install sshtunnel
- また、DB接続用のライブラリも好みのものをインストールします(例では、psycopg2)。
コードスニペット
上で出てきた踏み台サーバを経由してバックエンドのDBへアクセスするサンプルは以下の通りです。
必要に応じて、wait(スニペットでwaitのコメントを付けている部分)を入れて接続が整うのを待ってください。
from sshtunnel import SSHTunnelForwarder import psycopg2 as psy2 server = SSHTunnelForwarder( (踏み台サーバのアドレス, 22), ssh_host_key=None, ssh_username=踏み台サーバのユーザ名, ssh_password=None, ssh_pkey=踏み台サーバのSSH秘密鍵, set_keepalive=10.0, remote_bind_address=(データベースのアドレス, 5439) ) server.start() con = psy2.connect( dbname = データベース名, user = データベースのユーザ名, password = パスワード, host = "localhost", port=server.local_bind_port, async_=True(非同期) or False(同期) ) while True : #wait state = con.poll() time.sleep(1) if state == psy2.extensions.POLL_OK: break cur = con.cursor() cur.execute(任意のSQL文) con.close()
その他
- ファイルのやりとりは、上で述べてきたsshコマンドをsftpコマンドに置き換えることで可能です。