6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

paramiko使って多段接続でSFTP

Posted at

paramiko

paramikoは、Pythonのライブラリで、SSH接続やSFTPなどができるもののようです。
http://www.paramiko.org/

インストールは、pipで簡単にできました。

多段ではない普通のSFTP接続

「paramiko SFTP」で検索すると、ほとんどの先人たちは、以下のように接続を行っています。

import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy)
key = paramiko.RSAKey.from_private_key_file("id_rsa", password="passphrase")
client.connect(
    "hostname",
    port=22,
    username="hoge",
    pkey=key
)
sftp = client.open_sftp()

参考:
https://qiita.com/NAKA_G/items/eb6061884416209047e8
http://trelab.info/python/python%E3%81%A7ssh%E6%8E%A5%E7%B6%9A%E3%82%92%E5%85%AC%E9%96%8B%E9%8D%B5%E8%AA%8D%E8%A8%BC%E3%80%81%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E8%AA%8D%E8%A8%BC%E3%81%A7%E8%A1%8C%E3%81%86%E6%96%B9%E6%B3%95/

あとは、sftpputgetメソッドを使って、ファイルのやり取りができます。

多段接続その1:ProxyCommandを使う方法

多段SSH接続するときに良く使われるProxyCommandをparamikoでも使えるようです。

import paramiko
proxy = paramiko.ProxyCommand("ssh -i id_rsa.fumidai hoge@fumidai -p 22 nc hostname 22")
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy)
key = paramiko.RSAKey.from_private_key_file("id_rsa", password="passphrase")
client.connect(
    "hostname",
    port=22,
    username="hoge",
    pkey=key,
    sock=proxy
)
sftp = client.open_sftp()

二行目で、ncコマンドを使って、通信を踏み台サーバー経由で目的のサーバーにプロキシさせています。
ncコマンドは使ったことなかったですが、多段SSH接続でsshコマンドの-Wオプションが使われるようになる前は、ProxyCommandはこのように指定していたようです。知りませんでした。

このやり方は分かりやすくて良いのですが、id_rsa.fumidaiにパスフレーズが設定されていると、対話式でなければ実行できないという欠点があります。

ちなみに、同じことをparamiko.SSHClientを使わずに実現することもできるようです。

import paramiko
proxy = paramiko.ProxyCommand("ssh -i id_rsa.fumidai hoge@fumidai -p 22 nc hostname 22")
t = paramiko.Transport(proxy)
key = paramiko.RSAKey.from_private_key_file("id_rsa", password="passphrase")
t.connect(username="hoge", pkey=key)
sftp = paramiko.SFPTClient.from_transport(t)

こっちの方が、一行だけ短いですね。(どうでもいいか。)
なお、paramiko.Transportは、何かエラーを起こすと、そこでパイプが切れるようで、例えば、t.connectを呼び出すとProken Pipeとなりました。対話型であれこれ試すときは、ご注意ください。

多段接続その2:ProxyCommandを使わない方法

Pythonコード上には、コマンドを書かなくても同じようなことができます。

gateway = paramiko.SSHClient()
gateway.set_missing_host_key_policy(paramiko.AutoAddPolicy)
key_fumidai = paramiko.RSAKey.from_private_key_file("id_rsa.fumidai", password="passphrase")
gateway.connect(hostname="fumidai", username="hoge", port=22, pkey=key_fumidai)
sock = gateway.get_transport().open_channel(
    "direct-tcpip", ("hostname", 22), ("", 22)
)
t = paramiko.Transport(sock)
key = paramiko.RSAKey.from_private_key_file("id_rsa", password="passphrase")
t.connect(username="hoge", pkey=key)
sftp = paramiko.SFPTClient.from_transport(t)

無事、パスワード付きの秘密鍵でも対話無しに実行できるコードになりました。

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?