2016-11-16 10 views
1

Amazon RDS( "D")でホストされているリモートMySQLデータベースがあります。セキュリティ上の理由から、リモートサーバー(「C」)を介してのみアクセスできます。 Cは、ジャンプホスト "B"を介してssh経由でアクセスできます。私は、リモートSQLホストにアクセスするために二重SSHトンネルが必要です。ジャンプホストとリモートデータベースを使用したSSHトンネル転送

[A: local host] -> [B: jump host] -> [C: target host] => [D: RDS MySQL host] 

paramikoおよび/またはsshtunnelを使用してDからPythonにアクセスしたいと思います。私は見つけることができるすべての情報が含まれます。

これまでのところ、私はCにから取得するには、プロキシコマンドでparamikoを使用している私は、コマンドを実行することにより、Dにアクセスすることができますmysqldbまたはsqlalchemy(私の究極の目標)に接続することによってではなく、Cで。

私の現在のコード:

import paramiko 

ssh = paramiko.SSHClient() 
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
proxy = paramiko.ProxyCommand("ssh -A [email protected]_host -W C_host:12345") 
ssh.connect("C_host", username="C_username", sock=proxy) 

stdin, stdout, stderr = ssh.exec_command("mysql -u D_username -p D_password -h D_host_rds") 
print("STDOUT:\n{}\n\nSTDERR:\n{}\n".format(stdout.read(), stderr.read())) 
# successfully prints out MySQL welcome screen 

私はこのような何かを探しています(sshtunnel docs例2から変更):

import paramiko 
from sshtunnel import SSHTunnelForwarder 

with SSHTunnelForwarder(
    intermediate = { 
     ("B_host", 22), 
     ssh_username = "B_username", 
     ssh_password = "B_password")}, 
    remote = { 
     ("C_host", 12345), 
     ssh_username = "C_username", 
     ssh_password = "C_password")}, 
    remote_bind_address=("D_host_rds", 3306), 
    local_bind_address=("0.0.0.0", 3307)) as server: 

    conn = MySQLdb.connect(
     user = "D_username", 
     passwd = "D_password", 
     db = "my_database", 
     host = "127.0.0.1", 
     port = 3307) 

TL; DR:どのように前方Iを行いますPythonで2つのsshジャンプを通るポート?

答えて

2

私はそれを考え出しました。これは、ssh設定の組み合わせと、sshtunnelライブラリのSSHTunnelForwarderコンテキストマネージャの組み合わせで動作します。

Using the following model and naming conventions

[A: local host] -> [B: jump host] -> [C: target host] => [D: RDS MySQL host]

私はB経由からCに到達するために私の〜/ .ssh/configにを設定します。

Host C_ssh_shortcut 
    HostName C_host 
    User C_user 
    Port 22 
    ForwardAgent yes 
    ProxyCommand ssh [email protected]_host -W %h:%p 

私は私が使用するキー/キーを追加しましたBとCに私のssh-agentにログインしてください:

ssh-add 

最後に私はp SSHTunnelForwarder:

import sqlalchemy 
from sshtunnel import SSHTunnelForwarder 

with SSHTunnelForwarder(
    "C_ssh_shortcut",      # The SSHTunnelForwarder "ssh_address_or_host" argument, which takes care of bypassing B through the ProxyCommand set up in ~/.ssh/config 
    remote_bind_address=(D_host, 3306), # Points to your desired destination, ie. database host on 3306, which is the MySQL port 
    local_bind_address=('', 1111)   # Gives a local way to access this host and port on your machine. '' is localhost/127.0.0.1, 1111 is an unused port 
) as server: 
    connection_string = "mysql+pymysql://D_user:[email protected]:1111/D_dbname" # note that D_host and D_port were replaced by the host and port defined in "local_bind_address" 
    engine = sqlalchemy.create_engine(connection_string) 
    # do your thing 

ここから、いつものように自分のエンジンを使用してデータベースとやり取りできます。

0

ソリューションを見つけましたか?もしそうなら、それを投稿できますか?

私は現在、このようなことに取り組んでおり、ポート転送に関するいくつかのアイデアを持っています。たとえば、私の〜/ .ssh/configファイルには、次のようなものがあります。これにより、ポート転送を使用して中間から最初に中間に最初にsshすることなく、自分のローカルからリモートに直接sshできるようになります。

これで端末のssh経由でローカルからリモートに接続できます。今、ローカルからリモートにプログラムで直接トンネリングする作業をしています。私はPythonと私のsshの設定ファイルがうまく再生し、私がポート転送のトリックを使用できるようにしたいと考えています。私はこれを動作させると私のコードをフォローアップします。

(私はWindowsがそのSSHキーと設定ファイルをどのように処理するかわからない。あなたは、LinuxやMacOSにしていると仮定します。)

Host remote 
    HostName <remote_host.org> 
    User <username> 
    Port 22 
    ForwardAgent yes 
    ProxyCommand ssh <intermediate> nc %h %p 

Host intermediate 
    HostName <intermediate_host.org> 
    User <username> 
# IdentityFile ~/.ssh/id_rsa 
    ControlMaster auto 
    ControlPath ~/.ssh/master-%[email protected]%h:%p 
    ControlPersist 30m 
+1

[回答](https://stackoverflow.com/a/44739471/6412017)を見つけました。 – blep

関連する問題