Reputation: 438
I can not understand (even after reading few articles dedicated to ssh tunelling) what parameters of CLI ssh command where in this script. Basically I have to connect to some server (I called it 'ssh_tunnel_host:22'), than connect to db_host using this tunnel.
with SSHTunnelForwarder(
('ssh_tunnel_host', 22),
ssh_username="ssh_username",
ssh_pkey="/somepath/id_rsa",
local_bind_address=('0.0.0.0', 1234),
remote_bind_address=('127.0.0.1', 3306)
) as tunnel:
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('127.0.0.1', 1234)
db_connection = pymysql.connect(host=db_host, port=3306, db='mysql', user='user',
password='password', charset='utf8mb4')
Could someone explain to me:
(I did try to read the docs but it is still messing)
Upvotes: 8
Views: 14554
Reputation: 1
Our situation is similar and I got tired of making sure SSH tunnel is up and running before trying to connect to MS Sqlserver db. So we have a remote server (ip1) and on that we installed a docker with MSSqlserver on it. Naturally, when you log into that server, you can forward the docker ip to localhost on that machine. So if you are 'inside' ip1 you can access the server as localhost.
MS Sqlserver for all versions enforce port 1433 as the access port.
So you have ip1->localhost:1433->MSSqlserver
So SSH creates a tunnel for access to ip1 using a simple SSH user@ip1, but you need to forward localhost:1433 on the remoteserver to operate as if it is local.
from sshtunnel import SSHTunnelForwarder
import values
server = SSHTunnelForwarder(
(values.remote_server_ip, values.remote_server_port),
ssh_username=values.remote_server_username,
ssh_pkey=values.rsa_path+values.rsa_file,
ssh_private_key_password=values.rsa_passphrase,
remote_bind_address=(values.private_server_ip, values.private_server_port),
local_bind_address=(values.db_server_ip, values.db_server_port) )
try:
server.start()
except:
print("trouble connecting to the tunnel. we will asume it is already up")
else:
print("server is started and on port ",server.local_bind_port) # show assigned local port
do some work here and then
try:
server.stop()
except:
print("could not stop the server. assume it is already down")
else:
print("stopped the server successfully")
and values.py contains values for
remote_server_ip = "....remote ip...."
remote_server_port = 22
private_server_ip = "localhost"
private_server_port = 1433
db_server_ip = "localhost"
db_server_port = 1433
remote_server_username = "...."
rsa_passphrase = "...."
rsa_path = "˜/.ssh/"
rsa_file = "id_rsa"
Upvotes: -1
Reputation: 5270
Think of it like a proxy connection. You connect to ssh_tunnel_host:22
and you tell it to proxy connections from its <db host>:3306
, meaning port 3306 on db_host
accessed by ssh_tunnel_host
to you, the client.
You can either specify the local (to you) ip:port you want the proxy connection to be available on, or let the client choose a free one. Omitting local_bind_address
does the latter.
You then connect to your local port which is actually a proxy to remote_bind_address:3306
.
local_bind_address
<-> ssh_tunnel_host
<-> remote_bind_address
Code should be:
db_host = '<address reachable only by ssh_tunnel_host>'
with SSHTunnelForwarder(
('ssh_tunnel_host', 22),
ssh_username="ssh_username",
ssh_pkey="/somepath/id_rsa",
remote_bind_address=(db_host, 3306)
) as tunnel:
port = tunnel.local_bind_port
db_connection = pymysql.connect(
host='127.0.0.1', port=port, db='mysql', user='user',
password='password', charset='utf8mb4')
Local to client address. Either set one, or let client choose and find its port from tunnel.local_bind_port
.
The address you want ssh_tunnel_host
to proxy back to you. If it's a local to the server service, the IP will be 127.0.0.1
and port of the service. It could well be any other IP or an IP in ssh_tunnel_host
's network that is not visible outside SSH tunnel host.
Nowhere. The tunnel provides a local ip:port that proxies the remote connection. Once the tunnel is up, no other client is needed. Just connect to the local ip:port.
Upvotes: 16