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/
あとは、sftp
のput
やget
メソッドを使って、ファイルのやり取りができます。
多段接続その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)
無事、パスワード付きの秘密鍵でも対話無しに実行できるコードになりました。