
SSH-Tunnel zu einem entfernten Server.
|CircleCI| |AppVeyor| |readthedocs| |coveralls| |version|
|pyversions| |license|
Autor: Pahaz_
Repo: https://github.com/pahaz/sshtunnel/
Inspiriert von https://github.com/jmagnusson/bgtunnel, das unter Windows nicht funktioniert.
Siehe auch: https://github.com/paramiko/paramiko/blob/master/demos/forward.py
paramiko_sshtunnel_ ist auf PyPI, also einfach ausführen:
::
pip install sshtunnel
oder ::
easy_install sshtunnel
oder ::
conda install -c conda-forge sshtunnel
um es in Ihrer Umgebung zu installieren.
Für die Installation aus dem Quellcode klonen Sie das
Repo <https://github.com/pahaz/sshtunnel>_ und führen Sie aus::
python setup.py install
Um die Tests auszuführen, benötigen Sie zunächst
tox <https://testrun.org/tox/latest/>_ und führen Sie aus::
python setup.py test
Eines der typischen Szenarien, in denen sshtunnel hilfreich ist, ist in der
folgenden Abbildung dargestellt. Der Benutzer muss möglicherweise einen Port eines entfernten Servers (z. B. 8080) erreichen, wo nur der SSH-Port (normalerweise Port 22) erreichbar ist. ::
----------------------------------------------------------------------
|
-------------+ | +----------+
LOKAL | | | ENTFERN | :22 SSH
CLIENT | <== SSH ========> | SERVER | :8080 Webservice
-------------+ | +----------+
|
FIREWALL (nur Port 22 ist offen)
----------------------------------------------------------------------
Abb1: Verbindung zu einem durch eine Firewall blockierten Dienst über SSH-Tunnel.
Falls vom SSH-Server erlaubt, ist es auch möglich, einen privaten Server zu erreichen (aus Sicht des ENTFERNTEN SERVERS), der von außen (aus Sicht des LOKALEN CLIENTS) nicht direkt sichtbar ist. ::
----------------------------------------------------------------------
|
-------------+ | +----------+ +---------
LOKAL | | | ENTFERN | | PRIVATER
CLIENT | <== SSH ========> | SERVER | <== lokal ==> | SERVER
-------------+ | +----------+ +---------
|
FIREWALL (nur Port 443 ist offen)
----------------------------------------------------------------------
Abb2: Verbindung zum PRIVATEN SERVER über SSH-Tunnel.
Die API ermöglicht entweder das Initialisieren des Tunnels und dessen Start oder die Verwendung eines with-Kontexts, der sich um das Starten und Stoppen des Tunnels kümmert:
Der Code entsprechend Abb1 oben folgt, vorausgesetzt die Adresse des entfernten Servers ist
pahaz.urfuclub.ru, Passwort-Authentifizierung und ein zufällig zugewiesener lokaler Bindungsport.
.. 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) # zeigt den zugewiesenen lokalen Port an
# Arbeiten mit `SECRET SERVICE` über `server.local_bind_port`.
server.stop()
Beispiel einer Portweiterleitung zu einem nicht direkt erreichbaren privaten Server, angenommen passwortgeschützte Pkey-Authentifizierung, der SSH-Dienst des entfernten Servers hört auf Port 443 und dieser Port ist in der Firewall offen (Abb2):
.. 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)
# einige Operationen mit der Client-Sitzung durchführen
client.close()
print('FERTIG!')
Beispiel einer Portweiterleitung für den Vagrant MySQL lokalen Port:
.. 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:
# Drücken Sie Ctrl-C zum Beenden
sleep(1)
print('FERTIG!')
Oder einfach über die CLI:
.. code-block:: console
(bash)$ python -m sshtunnel -U vagrant -P vagrant -L :3306 -R 127.0.0.1:3306 -p 2222 localhost
Öffnen einer SSH-Sitzung über zwei Tunnel. SSH-Transport und Tunnel werden als Daemon ausgeführt, sodass sie beim Schließen nicht auf das Ende der Verbindungen warten.
.. 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('Verbindung zu 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('Verbindung zu 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