
Tunnel SSH verso server remoto.
|CircleCI| |AppVeyor| |readthedocs| |coveralls| |version|
|pyversions| |license|
Autore: Pahaz_
Repository: https://github.com/pahaz/sshtunnel/
Ispirato da https://github.com/jmagnusson/bgtunnel, che non funziona su Windows.
Vedi anche: https://github.com/paramiko/paramiko/blob/master/demos/forward.py
paramiko_sshtunnel_ è su PyPI, quindi esegui semplicemente:
::
pip install sshtunnel
oppure ::
easy_install sshtunnel
oppure ::
conda install -c conda-forge sshtunnel
per installarlo nel tuo ambiente.
Per installare dal sorgente, clona il
repository <https://github.com/pahaz/sshtunnel>_ ed esegui::
python setup.py install
Per eseguire i test devi prima installare
tox <https://testrun.org/tox/latest/>_ e poi eseguire::
python setup.py test
Uno degli scenari tipici in cui sshtunnel è utile è rappresentato nella
figura sottostante. L'utente potrebbe dover connettere una porta di un server remoto (es. 8080)
dove solo la porta SSH (di solito porta 22) è raggiungibile. ::
----------------------------------------------------------------------
|
-------------+ | +----------+
LOCALE | | | REMOTO | :22 SSH
CLIENT | <== SSH ========> | SERVER | :8080 servizio web
-------------+ | +----------+
|
FIREWALL (solo porta 22 aperta)
----------------------------------------------------------------------
Fig1: Come connettersi a un servizio bloccato da un firewall tramite tunnel SSH.
Se consentito dal server SSH, è anche possibile raggiungere un server privato
(dalla prospettiva del SERVER REMOTO) non direttamente visibile dall'esterno
(prospettiva del CLIENT LOCALE). ::
----------------------------------------------------------------------
|
-------------+ | +----------+ +---------
LOCALE | | | REMOTO | | PRIVATO
CLIENT | <== SSH ========> | SERVER | <== locale ==>| SERVER
-------------+ | +----------+ +---------
|
FIREWALL (solo porta 443 aperta)
----------------------------------------------------------------------
Fig2: Come connettersi al SERVER PRIVATO tramite tunnel SSH.
L'API consente sia di inizializzare il tunnel e avviarlo, sia di usare un contesto with,
che si occuperà di avviare e fermare il tunnel:
Codice corrispondente alla Fig1 sopra, dato l'indirizzo del server remoto
pahaz.urfuclub.ru, autenticazione tramite password e porta locale di bind assegnata casualmente.
.. code-block:: python
from sshtunnel import SSHTunnelForwarder
server = SSHTunnelForwarder(
'alfa.8iq.dev',
ssh_username="pahaz",
ssh_password="secret",
remote_bind_address=('127.0.0.1', 8080)
)
server.start()
print(server.local_bind_port) # show assigned local port
# work with `SECRET SERVICE` through `server.local_bind_port`.
server.stop()
Esempio di port forwarding verso un server privato non direttamente raggiungibile, supponendo autenticazione tramite pkey protetta da password, il servizio SSH del server remoto ascolta sulla porta 443 e tale porta è aperta nel firewall (Fig2):
.. code-block:: python
import paramiko
import sshtunnel
with sshtunnel.open_tunnel(
(REMOTE_SERVER_IP, 443),
ssh_username="",
ssh_pkey="/var/ssh/rsa_key",
ssh_private_key_password="secret",
remote_bind_address=(PRIVATE_SERVER_IP, 22),
local_bind_address=('0.0.0.0', 10022)
) as tunnel:
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('127.0.0.1', 10022)
# do some operations with client session
client.close()
print('FINISH!')
Esempio di port forwarding per la porta MySQL locale di Vagrant:
.. code-block:: python
from sshtunnel import open_tunnel
from time import sleep
with open_tunnel(
('localhost', 2222),
ssh_username="vagrant",
ssh_password="vagrant",
remote_bind_address=('127.0.0.1', 3306)
) as server:
print(server.local_bind_port)
while True:
# press Ctrl-C for stopping
sleep(1)
print('FINISH!')
O semplicemente tramite CLI:
.. code-block:: console
(bash)$ python -m sshtunnel -U vagrant -P vagrant -L :3306 -R 127.0.0.1:3306 -p 2222 localhost
Aprire una sessione SSH saltando due tunnel. Il trasporto SSH e i tunnel saranno demoneizzati, quindi non aspetteranno la chiusura delle connessioni al momento della terminazione.
.. code-block:: python
import sshtunnel
from paramiko import SSHClient
with sshtunnel.open_tunnel(
ssh_address_or_host=('GW1_ip', 20022),
remote_bind_address=('GW2_ip', 22),
) as tunnel1:
print('Connection to tunnel1 (GW1_ip:GW1_port) OK...')
with sshtunnel.open_tunnel(
ssh_address_or_host=('localhost', tunnel1.local_bind_port),
remote_bind_address=('target_ip', 22),
ssh_username='GW2_user',
ssh_password='GW2_pwd',
) as tunnel2:
print('Connection to tunnel2 (GW2_ip:GW2_port) OK...')
with SSHClient() as ssh:
ssh.connect('localhost',
port=tunnel2.local_bind_port,
username='target_user',
password='target_pwd',
)
ssh.exec_command(...)
::
$ sshtunnel --help
usage: sshtunnel [-h] [-U SSH_USERNAME] [-p SSH_PORT] [-P SSH_PASSWORD] -R
IP:PORT [IP:PORT ...] [-L [IP:PORT ...]] [-k SSH_HOST_KEY]
[-K KEY_FILE] [-S KEY_PASSWORD] [-t] [-v] [-V] [-x IP:PORT]
[-c SSH_CONFIG_FILE] [-z] [-n] [-d [FOLDER ...]]
ssh_address
Pure python ssh tunnel utils
Version 0.4.0
positional arguments:
ssh_address SSH server IP address (GW for SSH tunnels)
set with "-- ssh_address" if immediately after -R or -L