0
# SSH Tunnel
1
2
Pure python SSH tunnels for creating secure connections through intermediate servers. This library enables both local and remote port forwarding via SSH, supporting applications that need reliable SSH tunnel functionality without external dependencies beyond paramiko.
3
4
## Package Information
5
6
- **Package Name**: sshtunnel
7
- **Language**: Python
8
- **Installation**: `pip install sshtunnel`
9
10
## Core Imports
11
12
```python
13
import sshtunnel
14
```
15
16
Common patterns:
17
18
```python
19
from sshtunnel import SSHTunnelForwarder, open_tunnel
20
```
21
22
## Basic Usage
23
24
```python
25
from sshtunnel import SSHTunnelForwarder
26
27
# Create and start SSH tunnel
28
server = SSHTunnelForwarder(
29
ssh_address_or_host='ssh.example.com',
30
ssh_username='user',
31
ssh_password='secret',
32
remote_bind_address=('127.0.0.1', 3306),
33
local_bind_address=('127.0.0.1', 3307)
34
)
35
36
server.start()
37
print(f"Server connected via local port: {server.local_bind_port}")
38
39
# Use your tunnel connection here
40
# Connect to localhost:3307 to reach 127.0.0.1:3306 on remote server
41
42
server.stop()
43
```
44
45
Context manager usage:
46
47
```python
48
from sshtunnel import open_tunnel
49
50
with open_tunnel(
51
('ssh.example.com', 22),
52
ssh_username='user',
53
ssh_password='secret',
54
remote_bind_address=('127.0.0.1', 3306),
55
local_bind_address=('127.0.0.1', 3307)
56
) as tunnel:
57
print(f"Tunnel opened on local port: {tunnel.local_bind_port}")
58
# Use tunnel connection here
59
# Tunnel automatically closed when exiting context
60
```
61
62
## Architecture
63
64
The sshtunnel package is built around a few key components:
65
66
- **SSHTunnelForwarder**: Main class managing SSH connections and tunnel forwarding
67
- **Forward servers**: Background TCP/UNIX socket servers handling tunnel connections
68
- **Handler threads**: Individual connection handlers for concurrent tunnel usage
69
- **Transport layer**: Paramiko-based SSH transport with keepalive and authentication
70
71
## Capabilities
72
73
### SSH Tunnel Management
74
75
Main functionality for creating and managing SSH tunnels with full lifecycle control.
76
77
```python { .api }
78
class SSHTunnelForwarder:
79
def __init__(
80
self,
81
ssh_address_or_host=None,
82
ssh_config_file=SSH_CONFIG_FILE,
83
ssh_host_key=None,
84
ssh_password=None,
85
ssh_pkey=None,
86
ssh_private_key_password=None,
87
ssh_proxy=None,
88
ssh_proxy_enabled=True,
89
ssh_username=None,
90
local_bind_address=None,
91
local_bind_addresses=None,
92
logger=None,
93
mute_exceptions=False,
94
remote_bind_address=None,
95
remote_bind_addresses=None,
96
set_keepalive=5.0,
97
threaded=True,
98
compression=None,
99
allow_agent=True,
100
host_pkey_directories=None
101
): ...
102
103
def start(self): ...
104
def stop(self, force=False): ...
105
def close(self): ...
106
def restart(self): ...
107
```
108
109
### Tunnel Status and Properties
110
111
Access tunnel connection information and status.
112
113
```python { .api }
114
class SSHTunnelForwarder:
115
@property
116
def local_bind_port(self) -> int: ...
117
118
@property
119
def local_bind_ports(self) -> list[int]: ...
120
121
@property
122
def local_bind_host(self) -> str: ...
123
124
@property
125
def local_bind_hosts(self) -> list[str]: ...
126
127
@property
128
def local_bind_address(self) -> tuple: ...
129
130
@property
131
def local_bind_addresses(self) -> list[tuple]: ...
132
133
@property
134
def tunnel_bindings(self) -> dict: ...
135
136
tunnel_is_up: dict # Instance attribute - tunnel status mapping
137
138
@property
139
def is_active(self) -> bool: ...
140
141
is_alive: bool # Instance attribute - whether tunnels are alive
142
143
def check_tunnels(self): ...
144
def local_is_up(self, target: tuple) -> bool: ... # deprecated
145
```
146
147
### Simplified Tunnel Interface
148
149
Convenience function for common tunnel use cases with context manager support.
150
151
```python { .api }
152
def open_tunnel(*args, **kwargs) -> SSHTunnelForwarder:
153
"""
154
Open an SSH Tunnel, wrapper for SSHTunnelForwarder.
155
156
Parameters:
157
- ssh_address_or_host: SSH server address/hostname
158
- ssh_username: SSH username
159
- ssh_password: SSH password
160
- ssh_pkey: Private key file path or paramiko.PKey object
161
- ssh_port: SSH port (default: 22)
162
- remote_bind_address: Remote (host, port) tuple
163
- remote_bind_addresses: List of remote bind addresses
164
- local_bind_address: Local (host, port) tuple
165
- local_bind_addresses: List of local bind addresses
166
- debug_level: Log level for debugging
167
- skip_tunnel_checkup: Disable tunnel status checking
168
- Additional SSHTunnelForwarder parameters supported
169
170
Returns:
171
SSHTunnelForwarder instance configured as context manager
172
"""
173
```
174
175
### SSH Key Management
176
177
Utilities for loading SSH keys from various sources.
178
179
```python { .api }
180
class SSHTunnelForwarder:
181
@staticmethod
182
def get_agent_keys(logger=None) -> list:
183
"""Load public keys from SSH agent."""
184
185
@staticmethod
186
def get_keys(
187
logger=None,
188
host_pkey_directories=None,
189
allow_agent=False
190
) -> list:
191
"""Load keys from SSH agent or local directories."""
192
193
@staticmethod
194
def read_private_key_file(
195
pkey_file: str,
196
pkey_password=None,
197
key_type=None,
198
logger=None
199
):
200
"""Read private key file and return paramiko.PKey object."""
201
```
202
203
### Validation and Logging
204
205
Utility functions for address validation and logger configuration.
206
207
```python { .api }
208
def check_host(host: str): ...
209
def check_port(port: int): ...
210
def check_address(address): ...
211
def check_addresses(address_list: list, is_remote=False): ...
212
213
def create_logger(
214
logger=None,
215
loglevel=None,
216
capture_warnings=True,
217
add_paramiko_handler=True
218
) -> logging.Logger:
219
"""Create or configure logger with console handler."""
220
221
def address_to_str(address) -> str:
222
"""Convert address to string representation."""
223
224
def get_connection_id() -> int:
225
"""Generate unique connection ID for tunnel connections."""
226
```
227
228
## Exception Classes
229
230
```python { .api }
231
class BaseSSHTunnelForwarderError(Exception):
232
"""Base exception for SSHTunnelForwarder errors."""
233
234
class HandlerSSHTunnelForwarderError(BaseSSHTunnelForwarderError):
235
"""Exception for tunnel forwarder errors."""
236
```
237
238
## Constants
239
240
```python { .api }
241
__version__: str = '0.4.0'
242
__author__: str = 'pahaz'
243
244
SSH_TIMEOUT: float = 0.1 # Transport socket timeout
245
TUNNEL_TIMEOUT: float = 10.0 # Tunnel connection timeout
246
DEFAULT_LOGLEVEL: int = logging.ERROR # Default log level
247
TRACE_LEVEL: int = 1 # Trace log level
248
DEFAULT_SSH_DIRECTORY: str = '~/.ssh' # Default SSH directory
249
SSH_CONFIG_FILE: str # Path to SSH config file
250
```
251
252
## Usage Examples
253
254
### Multiple Tunnels
255
256
```python
257
from sshtunnel import SSHTunnelForwarder
258
259
# Create multiple tunnels at once
260
server = SSHTunnelForwarder(
261
ssh_address_or_host='ssh.example.com',
262
ssh_username='user',
263
ssh_password='secret',
264
remote_bind_addresses=[('127.0.0.1', 3306), ('127.0.0.1', 5432)],
265
local_bind_addresses=[('127.0.0.1', 3307), ('127.0.0.1', 5433)]
266
)
267
268
server.start()
269
print(f"MySQL tunnel: localhost:{server.local_bind_ports[0]}")
270
print(f"PostgreSQL tunnel: localhost:{server.local_bind_ports[1]}")
271
server.stop()
272
```
273
274
### SSH Key Authentication
275
276
```python
277
from sshtunnel import SSHTunnelForwarder
278
279
# Using SSH key file
280
server = SSHTunnelForwarder(
281
ssh_address_or_host='example.com',
282
ssh_username='user',
283
ssh_pkey='/home/user/.ssh/id_rsa',
284
ssh_private_key_password='key_password', # if key is encrypted
285
remote_bind_address=('192.168.1.100', 22),
286
local_bind_address=('127.0.0.1', 2222)
287
)
288
289
# Using SSH agent keys
290
server = SSHTunnelForwarder(
291
ssh_address_or_host='example.com',
292
ssh_username='user',
293
allow_agent=True,
294
remote_bind_address=('192.168.1.100', 22)
295
)
296
```
297
298
### Custom Logger Configuration
299
300
```python
301
import logging
302
from sshtunnel import SSHTunnelForwarder, create_logger
303
304
# Create custom logger
305
logger = create_logger(loglevel=logging.DEBUG)
306
307
server = SSHTunnelForwarder(
308
ssh_address_or_host='example.com',
309
ssh_username='user',
310
ssh_password='secret',
311
remote_bind_address=('127.0.0.1', 3306),
312
logger=logger
313
)
314
```
315
316
### Error Handling
317
318
```python
319
from sshtunnel import (
320
SSHTunnelForwarder,
321
BaseSSHTunnelForwarderError,
322
HandlerSSHTunnelForwarderError
323
)
324
325
try:
326
server = SSHTunnelForwarder(
327
ssh_address_or_host='example.com',
328
ssh_username='user',
329
ssh_password='wrong_password',
330
remote_bind_address=('127.0.0.1', 3306),
331
mute_exceptions=False # Enable exception raising
332
)
333
server.start()
334
except BaseSSHTunnelForwarderError as e:
335
print(f"SSH tunnel error: {e}")
336
except HandlerSSHTunnelForwarderError as e:
337
print(f"Tunnel handler error: {e}")
338
```
339
340
### Proxy Support
341
342
```python
343
from sshtunnel import SSHTunnelForwarder
344
345
# Using HTTP proxy
346
server = SSHTunnelForwarder(
347
ssh_address_or_host='target.example.com',
348
ssh_username='user',
349
ssh_password='secret',
350
ssh_proxy=('proxy.example.com', 8080),
351
remote_bind_address=('127.0.0.1', 3306)
352
)
353
354
# Using ProxyCommand from SSH config
355
server = SSHTunnelForwarder(
356
ssh_address_or_host='target.example.com',
357
ssh_username='user',
358
ssh_config_file='~/.ssh/config', # Contains ProxyCommand
359
ssh_proxy_enabled=True,
360
remote_bind_address=('127.0.0.1', 3306)
361
)
362
```