Show More
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 |
@@ -29,21 +29,11 b' connection to a destination reachable from the SSH server machine.' | |||||
29 |
|
29 | |||
30 | from __future__ import print_function |
|
30 | from __future__ import print_function | |
31 |
|
31 | |||
32 | import getpass |
|
32 | import logging | |
33 | import os |
|
|||
34 | import socket |
|
|||
35 | import select |
|
33 | import select | |
36 | import SocketServer |
|
34 | import SocketServer | |
37 | import sys |
|
|||
38 | from optparse import OptionParser |
|
|||
39 |
|
||||
40 | import paramiko |
|
|||
41 |
|
||||
42 | SSH_PORT = 22 |
|
|||
43 | DEFAULT_PORT = 4000 |
|
|||
44 |
|
||||
45 | g_verbose = False |
|
|||
46 |
|
35 | |||
|
36 | logger = logging.getLogger('ssh') | |||
47 |
|
37 | |||
48 | class ForwardServer (SocketServer.ThreadingTCPServer): |
|
38 | class ForwardServer (SocketServer.ThreadingTCPServer): | |
49 | daemon_threads = True |
|
39 | daemon_threads = True | |
@@ -58,16 +48,16 b' class Handler (SocketServer.BaseRequestHandler):' | |||||
58 | (self.chain_host, self.chain_port), |
|
48 | (self.chain_host, self.chain_port), | |
59 | self.request.getpeername()) |
|
49 | self.request.getpeername()) | |
60 | except Exception, e: |
|
50 | except Exception, e: | |
61 |
|
|
51 | logger.debug('Incoming request to %s:%d failed: %s' % (self.chain_host, | |
62 | self.chain_port, |
|
52 | self.chain_port, | |
63 | repr(e))) |
|
53 | repr(e))) | |
64 | return |
|
54 | return | |
65 | if chan is None: |
|
55 | if chan is None: | |
66 |
|
|
56 | logger.debug('Incoming request to %s:%d was rejected by the SSH server.' % | |
67 | (self.chain_host, self.chain_port)) |
|
57 | (self.chain_host, self.chain_port)) | |
68 | return |
|
58 | return | |
69 |
|
59 | |||
70 |
|
|
60 | logger.debug('Connected! Tunnel open %r -> %r -> %r' % (self.request.getpeername(), | |
71 | chan.getpeername(), (self.chain_host, self.chain_port))) |
|
61 | chan.getpeername(), (self.chain_host, self.chain_port))) | |
72 | while True: |
|
62 | while True: | |
73 | r, w, x = select.select([self.request, chan], [], []) |
|
63 | r, w, x = select.select([self.request, chan], [], []) | |
@@ -83,7 +73,7 b' class Handler (SocketServer.BaseRequestHandler):' | |||||
83 | self.request.send(data) |
|
73 | self.request.send(data) | |
84 | chan.close() |
|
74 | chan.close() | |
85 | self.request.close() |
|
75 | self.request.close() | |
86 |
|
|
76 | logger.debug('Tunnel closed ') | |
87 |
|
77 | |||
88 |
|
78 | |||
89 | def forward_tunnel(local_port, remote_host, remote_port, transport): |
|
79 | def forward_tunnel(local_port, remote_host, remote_port, transport): | |
@@ -97,87 +87,4 b' def forward_tunnel(local_port, remote_host, remote_port, transport):' | |||||
97 | ForwardServer(('127.0.0.1', local_port), SubHander).serve_forever() |
|
87 | ForwardServer(('127.0.0.1', local_port), SubHander).serve_forever() | |
98 |
|
88 | |||
99 |
|
89 | |||
100 | def verbose(s): |
|
90 | __all__ = ['forward_tunnel'] No newline at end of file | |
101 | if g_verbose: |
|
|||
102 | print (s) |
|
|||
103 |
|
||||
104 |
|
||||
105 | HELP = """\ |
|
|||
106 | Set up a forward tunnel across an SSH server, using paramiko. A local port |
|
|||
107 | (given with -p) is forwarded across an SSH session to an address:port from |
|
|||
108 | the SSH server. This is similar to the openssh -L option. |
|
|||
109 | """ |
|
|||
110 |
|
||||
111 |
|
||||
112 | def get_host_port(spec, default_port): |
|
|||
113 | "parse 'hostname:22' into a host and port, with the port optional" |
|
|||
114 | args = (spec.split(':', 1) + [default_port])[:2] |
|
|||
115 | args[1] = int(args[1]) |
|
|||
116 | return args[0], args[1] |
|
|||
117 |
|
||||
118 |
|
||||
119 | def parse_options(): |
|
|||
120 | global g_verbose |
|
|||
121 |
|
||||
122 | parser = OptionParser(usage='usage: %prog [options] <ssh-server>[:<server-port>]', |
|
|||
123 | version='%prog 1.0', description=HELP) |
|
|||
124 | parser.add_option('-q', '--quiet', action='store_false', dest='verbose', default=True, |
|
|||
125 | help='squelch all informational output') |
|
|||
126 | parser.add_option('-p', '--local-port', action='store', type='int', dest='port', |
|
|||
127 | default=DEFAULT_PORT, |
|
|||
128 | help='local port to forward (default: %d)' % DEFAULT_PORT) |
|
|||
129 | parser.add_option('-u', '--user', action='store', type='string', dest='user', |
|
|||
130 | default=getpass.getuser(), |
|
|||
131 | help='username for SSH authentication (default: %s)' % getpass.getuser()) |
|
|||
132 | parser.add_option('-K', '--key', action='store', type='string', dest='keyfile', |
|
|||
133 | default=None, |
|
|||
134 | help='private key file to use for SSH authentication') |
|
|||
135 | parser.add_option('', '--no-key', action='store_false', dest='look_for_keys', default=True, |
|
|||
136 | help='don\'t look for or use a private key file') |
|
|||
137 | parser.add_option('-P', '--password', action='store_true', dest='readpass', default=False, |
|
|||
138 | help='read password (for key or password auth) from stdin') |
|
|||
139 | parser.add_option('-r', '--remote', action='store', type='string', dest='remote', default=None, metavar='host:port', |
|
|||
140 | help='remote host and port to forward to') |
|
|||
141 | options, args = parser.parse_args() |
|
|||
142 |
|
||||
143 | if len(args) != 1: |
|
|||
144 | parser.error('Incorrect number of arguments.') |
|
|||
145 | if options.remote is None: |
|
|||
146 | parser.error('Remote address required (-r).') |
|
|||
147 |
|
||||
148 | g_verbose = options.verbose |
|
|||
149 | server_host, server_port = get_host_port(args[0], SSH_PORT) |
|
|||
150 | remote_host, remote_port = get_host_port(options.remote, SSH_PORT) |
|
|||
151 | return options, (server_host, server_port), (remote_host, remote_port) |
|
|||
152 |
|
||||
153 |
|
||||
154 | def main(): |
|
|||
155 | options, server, remote = parse_options() |
|
|||
156 |
|
||||
157 | password = None |
|
|||
158 | if options.readpass: |
|
|||
159 | password = getpass.getpass('Enter SSH password: ') |
|
|||
160 |
|
||||
161 | client = paramiko.SSHClient() |
|
|||
162 | client.load_system_host_keys() |
|
|||
163 | client.set_missing_host_key_policy(paramiko.WarningPolicy()) |
|
|||
164 |
|
||||
165 | verbose('Connecting to ssh host %s:%d ...' % (server[0], server[1])) |
|
|||
166 | try: |
|
|||
167 | client.connect(server[0], server[1], username=options.user, key_filename=options.keyfile, |
|
|||
168 | look_for_keys=options.look_for_keys, password=password) |
|
|||
169 | except Exception as e: |
|
|||
170 | print ('*** Failed to connect to %s:%d: %r' % (server[0], server[1], e)) |
|
|||
171 | sys.exit(1) |
|
|||
172 |
|
||||
173 | verbose('Now forwarding port %d to %s:%d ...' % (options.port, remote[0], remote[1])) |
|
|||
174 |
|
||||
175 | try: |
|
|||
176 | forward_tunnel(options.port, remote[0], remote[1], client.get_transport()) |
|
|||
177 | except KeyboardInterrupt: |
|
|||
178 | print ('C-c: Port forwarding stopped.') |
|
|||
179 | sys.exit(0) |
|
|||
180 |
|
||||
181 |
|
||||
182 | if __name__ == '__main__': |
|
|||
183 | main() |
|
1 | NO CONTENT: file renamed from IPython/zmq/tunnel.py to IPython/external/ssh/tunnel.py |
|
NO CONTENT: file renamed from IPython/zmq/tunnel.py to IPython/external/ssh/tunnel.py |
@@ -23,7 +23,7 b' from zmq.eventloop import ioloop, zmqstream' | |||||
23 |
|
23 | |||
24 | from IPython.utils.path import get_ipython_dir |
|
24 | from IPython.utils.path import get_ipython_dir | |
25 | from IPython.external.decorator import decorator |
|
25 | from IPython.external.decorator import decorator | |
26 |
from IPython. |
|
26 | from IPython.external.ssh import tunnel | |
27 |
|
27 | |||
28 | import streamsession as ss |
|
28 | import streamsession as ss | |
29 | from clusterdir import ClusterDir, ClusterDirError |
|
29 | from clusterdir import ClusterDir, ClusterDirError | |
@@ -152,9 +152,10 b' class Client(object):' | |||||
152 | Parameters |
|
152 | Parameters | |
153 | ---------- |
|
153 | ---------- | |
154 |
|
154 | |||
155 | addr : bytes; zmq url, e.g. 'tcp://127.0.0.1:10101' |
|
155 | url_or_file : bytes; zmq url or path to ipcontroller-client.json | |
156 | The address of the controller's registration socket. |
|
156 | Connection information for the Hub's registration. If a json connector | |
157 | [Default: 'tcp://127.0.0.1:10101'] |
|
157 | file is given, then likely no further configuration is necessary. | |
|
158 | [Default: None] | |||
158 | context : zmq.Context |
|
159 | context : zmq.Context | |
159 | Pass an existing zmq.Context instance, otherwise the client will create its own |
|
160 | Pass an existing zmq.Context instance, otherwise the client will create its own | |
160 | username : bytes |
|
161 | username : bytes | |
@@ -178,15 +179,18 b' class Client(object):' | |||||
178 | sshkey : str; path to public ssh key file |
|
179 | sshkey : str; path to public ssh key file | |
179 | This specifies a key to be used in ssh login, default None. |
|
180 | This specifies a key to be used in ssh login, default None. | |
180 | Regular default ssh keys will be used without specifying this argument. |
|
181 | Regular default ssh keys will be used without specifying this argument. | |
181 |
password : str |
|
182 | password : str | |
182 | Your ssh password to sshserver. Note that if this is left None, |
|
183 | Your ssh password to sshserver. Note that if this is left None, | |
183 | you will be prompted for it if passwordless key based login is unavailable. |
|
184 | you will be prompted for it if passwordless key based login is unavailable. | |
|
185 | paramiko : bool | |||
|
186 | flag for whether to use paramiko instead of shell ssh for tunneling. | |||
|
187 | [default: True on win32, False else] | |||
184 |
|
188 | |||
185 | #------- exec authentication args ------- |
|
189 | #------- exec authentication args ------- | |
186 | # If even localhost is untrusted, you can have some protection against |
|
190 | # If even localhost is untrusted, you can have some protection against | |
187 | # unauthorized execution by using a key. Messages are still sent |
|
191 | # unauthorized execution by using a key. Messages are still sent | |
188 | # as cleartext, so if someone can snoop your loopback traffic this will |
|
192 | # as cleartext, so if someone can snoop your loopback traffic this will | |
189 | # not help anything. |
|
193 | # not help against malicious attacks. | |
190 |
|
194 | |||
191 | exec_key : str |
|
195 | exec_key : str | |
192 | an authentication key or file containing a key |
|
196 | an authentication key or file containing a key |
General Comments 0
You need to be logged in to leave comments.
Login now