
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
options:
-h, --help show this help message and exit
-U SSH_USERNAME, --username SSH_USERNAME
SSH server account username
-p SSH_PORT, --server_port SSH_PORT
SSH server TCP port (default: 22)
-P SSH_PASSWORD, --password SSH_PASSWORD
SSH server account password
-R IP:PORT [IP:PORT ...], --remote_bind_address IP:PORT [IP:PORT ...]
Remote bind address sequence: ip_1:port_1 ip_2:port_2 ... ip_n:port_n
Equivalent to ssh -Lxxxx:IP_ADDRESS:PORT
If port is omitted, defaults to 22.
Example: -R 10.10.10.10: 10.10.10.10:5900
-L [IP:PORT ...], --local_bind_address [IP:PORT ...]
Local bind address sequence: ip_1:port_1 ip_2:port_2 ... ip_n:port_n
Elements may also be valid UNIX socket domains:
/tmp/foo.sock /tmp/bar.sock ... /tmp/baz.sock
Equivalent to ssh -LPORT:xxxxxxxxx:xxxx, being the local IP address optional.
By default it will listen in all interfaces (0.0.0.0) and choose a random port.
Example: -L :40000
-k SSH_HOST_KEY, --ssh_host_key SSH_HOST_KEY
Gateway's host key
-K KEY_FILE, --private_key_file KEY_FILE
RSA/DSS/ECDSA private key file
-S KEY_PASSWORD, --private_key_password KEY_PASSWORD
RSA/DSS/ECDSA private key password
-t, --threaded Allow concurrent connections to each tunnel
-v, --verbose Increase output verbosity (default: ERROR)
-V, --version Show version number and quit
-x IP:PORT, --proxy IP:PORT
IP and port of SSH proxy to destination
-c SSH_CONFIG_FILE, --config SSH_CONFIG_FILE
SSH configuration file, defaults to ~/.ssh/config
-z, --compress Request server for compression over SSH transport
-n, --noagent Disable looking for keys from an SSH agent
-d [FOLDER ...], --host_pkey_directories [FOLDER ...]
List of directories where SSH pkeys (in the format `id_*`) may be found
.. _Pahaz: https://github.com/pahaz
.. _sshtunnel: https://pypi.python.org/pypi/sshtunnel
.. paramiko: http://www.paramiko.org/
.. |CircleCI| image:: https://circleci.com/gh/pahaz/sshtunnel.svg?style=svg
:target: https://circleci.com/gh/pahaz/sshtunnel
.. |AppVeyor| image:: https://ci.appveyor.com/api/projects/status/oxg1vx2ycmnw3xr9?svg=true&passingText=Windows%20-%20OK&failingText=Windows%20-%20Fail
:target: https://ci.appveyor.com/project/pahaz/sshtunnel
.. |readthedocs| image:: https://readthedocs.org/projects/sshtunnel/badge/?version=latest
:target: http://sshtunnel.readthedocs.io/en/latest/?badge=latest
:alt: Dokumentationsstatus
.. |coveralls| image:: https://coveralls.io/repos/github/pahaz/sshtunnel/badge.svg?branch=master
:target: https://coveralls.io/github/pahaz/sshtunnel?branch=master
.. |pyversions| image:: https://img.shields.io/pypi/pyversions/sshtunnel.svg
.. |version| image:: https://img.shields.io/pypi/v/sshtunnel.svg
:target: sshtunnel
.. |license| image:: https://img.shields.io/pypi/l/sshtunnel.svg
:target: https://github.com/pahaz/sshtunnel/blob/master/LICENSE