Show More
@@ -213,6 +213,8 blocking execution. The frontend can also know, via a heartbeat mechanism, that | |||||
213 | the kernel has died. This means that the frontend can safely restart the |
|
213 | the kernel has died. This means that the frontend can safely restart the | |
214 | kernel. |
|
214 | kernel. | |
215 |
|
215 | |||
|
216 | .. _multiple_consoles: | |||
|
217 | ||||
216 | Multiple Consoles |
|
218 | Multiple Consoles | |
217 | ***************** |
|
219 | ***************** | |
218 |
|
220 | |||
@@ -225,11 +227,38 like:: | |||||
225 | [IPKernelApp] --existing --shell=60690 --iopub=44045 --stdin=38323 --hb=41797 |
|
227 | [IPKernelApp] --existing --shell=60690 --iopub=44045 --stdin=38323 --hb=41797 | |
226 |
|
228 | |||
227 | Other frontends can connect to your kernel, and share in the execution. This is |
|
229 | Other frontends can connect to your kernel, and share in the execution. This is | |
228 |
great for collaboration. The `-e` flag |
|
230 | great for collaboration. The ``--existing`` flag means connect to a kernel | |
|
231 | that already exists. Starting other | |||
229 | consoles with that flag will not try to start their own, but rather connect to |
|
232 | consoles with that flag will not try to start their own, but rather connect to | |
230 | yours. Ultimately, you will not have to specify each port individually, but for |
|
233 | yours. Ultimately, you will not have to specify each port individually, but for | |
231 | now this copy-paste method is best. |
|
234 | now this copy-paste method is best. | |
232 |
|
235 | |||
|
236 | You can even launch a standalone kernel, and connect and disconnect Qt Consoles | |||
|
237 | from various machines. This lets you keep the same running IPython session | |||
|
238 | on your work machine (with matplotlib plots and everything), logging in from home, | |||
|
239 | cafΓ©s, etc.:: | |||
|
240 | ||||
|
241 | $> ipython kernel | |||
|
242 | [IPKernelApp] To connect another client to this kernel, use: | |||
|
243 | [IPKernelApp] --existing --shell=60690 --iopub=44045 --stdin=38323 --hb=41797 | |||
|
244 | ||||
|
245 | This is actually exactly the same as the subprocess launched by the qtconsole, so | |||
|
246 | all the information about connecting to a standalone kernel is identical to that | |||
|
247 | of connecting to the kernel attached to a running console. | |||
|
248 | ||||
|
249 | .. _kernel_security: | |||
|
250 | ||||
|
251 | Security | |||
|
252 | -------- | |||
|
253 | ||||
|
254 | .. warning:: | |||
|
255 | ||||
|
256 | Since the ZMQ code currently has no security, listening on an | |||
|
257 | external-facing IP is dangerous. You are giving any computer that can see | |||
|
258 | you on the network the ability to issue arbitrary shell commands as you on | |||
|
259 | your machine. Read the rest of this section before listening on external ports | |||
|
260 | or running an IPython kernel on a shared machine. | |||
|
261 | ||||
233 | By default (for security reasons), the kernel only listens on localhost, so you |
|
262 | By default (for security reasons), the kernel only listens on localhost, so you | |
234 | can only connect multiple frontends to the kernel from your local machine. You |
|
263 | can only connect multiple frontends to the kernel from your local machine. You | |
235 | can specify to listen on an external interface by specifying the ``ip`` |
|
264 | can specify to listen on an external interface by specifying the ``ip`` | |
@@ -238,14 +267,134 argument:: | |||||
238 | $> ipython qtconsole --ip=192.168.1.123 |
|
267 | $> ipython qtconsole --ip=192.168.1.123 | |
239 |
|
268 | |||
240 | If you specify the ip as 0.0.0.0, that refers to all interfaces, so any |
|
269 | If you specify the ip as 0.0.0.0, that refers to all interfaces, so any | |
241 | computer that can see yours can connect to the kernel. |
|
270 | computer that can see yours on the network can connect to the kernel. | |
|
271 | ||||
|
272 | Messages are not encrypted, so users with access to the ports your kernel is using will be | |||
|
273 | able to see any output of the kernel. They will also be able to issue shell commands as | |||
|
274 | you, unless you enable HMAC digests, which are **DISABLED** by default. | |||
|
275 | ||||
|
276 | The one security feature IPython does provide is protection from unauthorized | |||
|
277 | execution. IPython's messaging system can sign messages with HMAC digests using | |||
|
278 | a shared-key. The key is never sent over the network, it is only used to generate | |||
|
279 | a unique hash for each message, based on its content. When IPython receives a | |||
|
280 | message, it will check that the digest matches. You can use any file that only you | |||
|
281 | have access to to generate this key. One logical choice would be to use your own | |||
|
282 | SSH private key. Or you can generate a new random private key with:: | |||
|
283 | ||||
|
284 | # generate 1024b of random data, and store in a file only you can read: | |||
|
285 | # (assumes IPYTHON_DIR is defined, otherwise use your IPython directory) | |||
|
286 | $> python -c "import os; print os.urandom(128).encode('base64')" > $IPYTHON_DIR/sessionkey | |||
|
287 | $> chmod 600 $IPYTHON_DIR/sessionkey | |||
|
288 | ||||
|
289 | To enable HMAC digests, simply specify the ``Session.keyfile`` configurable | |||
|
290 | in :file:`ipython_config.py` or at the command-line, as in:: | |||
|
291 | ||||
|
292 | # instruct IPython to sign messages with that key: | |||
|
293 | $> ipython qtconsole --Session.keyfile=$IPYTHON_DIR/sessionkey | |||
|
294 | ||||
|
295 | You must use the same key you used to start the kernel with all frontends, or | |||
|
296 | they will be treated as an unauthorized peer (all messages will be ignored). | |||
|
297 | ||||
|
298 | .. note:: | |||
|
299 | ||||
|
300 | IPython will move to using files to store connection information, as is | |||
|
301 | done in :mod:`IPython.parallel`, at which point HMAC signatures will be | |||
|
302 | enabled *by default*. | |||
|
303 | ||||
|
304 | .. _ssh_tunnels: | |||
|
305 | ||||
|
306 | SSH Tunnels | |||
|
307 | ----------- | |||
|
308 | ||||
|
309 | Sometimes you want to connect to machines across the internet, or just across | |||
|
310 | a LAN that either doesn't permit open ports or you don't trust the other | |||
|
311 | machines on the network. To do this, you can use SSH tunnels. SSH tunnels | |||
|
312 | are a way to securely forward ports on your local machine to ports on another | |||
|
313 | machine, to which you have SSH access. | |||
|
314 | ||||
|
315 | In simple cases, IPython's tools can forward ports over ssh by simply adding the | |||
|
316 | ``--ssh=remote`` argument to the usual ``--existing...`` set of flags for connecting | |||
|
317 | to a running kernel. | |||
242 |
|
318 | |||
243 | .. warning:: |
|
319 | .. warning:: | |
244 |
|
320 | |||
245 | Since the ZMQ code currently has no security, listening on an |
|
321 | Using SSH tunnels does *not* increase localhost security. In fact, when | |
246 | external-facing IP is dangerous. You are giving any computer that can see |
|
322 | tunneling from one machine to another *both* machines have open | |
247 | you on the network the ability to issue arbitrary shell commands as you on |
|
323 | ports on localhost available for connections. | |
248 | your machine. Be very careful with this. |
|
324 | ||
|
325 | There are two primary models for using SSH tunnels with IPython. The first | |||
|
326 | is to have the Kernel listen only on localhost, and connect to it from | |||
|
327 | another machine on the same LAN. | |||
|
328 | ||||
|
329 | First, let's start a kernel on machine **worker**, listening only | |||
|
330 | on loopback:: | |||
|
331 | ||||
|
332 | user@worker $> ipython kernel | |||
|
333 | [IPKernelApp] To connect another client to this kernel, use: | |||
|
334 | [IPKernelApp] --existing --shell=59480 --iopub=62199 --stdin=64898 --hb=56511 | |||
|
335 | ||||
|
336 | In this case, the IP that you would connect | |||
|
337 | to would still be 127.0.0.1, but you want to specify the additional ``--ssh`` argument | |||
|
338 | with the hostname of the kernel (in this example, it's 'worker'):: | |||
|
339 | ||||
|
340 | user@client $> ipython qtconsole --ssh=worker --existing --shell=59480 --iopub=62199 --stdin=64898 --hb=56511 | |||
|
341 | ||||
|
342 | Note again that this opens ports on the *client* machine that point to your kernel. | |||
|
343 | Be sure to use a Session key, as described above, if localhost on *either* the | |||
|
344 | client or kernel machines is untrusted. | |||
|
345 | ||||
|
346 | .. note:: | |||
|
347 | ||||
|
348 | the ssh argument is simply passed to openssh, so it can be fully specified ``user@host:port`` | |||
|
349 | but it will also respect your aliases, etc. in :file:`.ssh/config` if you have any. | |||
|
350 | ||||
|
351 | The second pattern is for connecting to a machine behind a firewall across the internet | |||
|
352 | (or otherwise wide network). This time, we have a machine **login** that you have ssh access | |||
|
353 | to, which can see **kernel**, but **client** is on another network. The important difference | |||
|
354 | now is that **client** can see **login**, but *not* **worker**. So we need to forward ports from | |||
|
355 | client to worker *via* login. This means that the kernel must be started listening | |||
|
356 | on external interfaces, so that its ports are visible to `login`:: | |||
|
357 | ||||
|
358 | user@worker $> ipython kernel --ip=0.0.0.0 | |||
|
359 | [IPKernelApp] To connect another client to this kernel, use: | |||
|
360 | [IPKernelApp] --existing --shell=59480 --iopub=62199 --stdin=64898 --hb=56511 | |||
|
361 | ||||
|
362 | Which we can connect to from the client with:: | |||
|
363 | ||||
|
364 | user@client $> ipython qtconsole --ssh=login --ip=192.168.1.123 --existing --shell=59480 --iopub=62199 --stdin=64898 --hb=56511 | |||
|
365 | ||||
|
366 | Note that now the IP is the address of worker as seen from login. | |||
|
367 | ||||
|
368 | Manual SSH tunnels | |||
|
369 | ------------------ | |||
|
370 | ||||
|
371 | It's possible that IPython's ssh helper functions won't work for you, for various | |||
|
372 | reasons. You can still connect to remote machines, as long as you set up the tunnels | |||
|
373 | yourself. The basic format of forwarding a local port to a remote one is:: | |||
|
374 | ||||
|
375 | [client] $> ssh <server> <localport>:<remoteip>:<remoteport> -f -N | |||
|
376 | ||||
|
377 | This will forward local connections to **localport** on client to **remoteip:remoteport** | |||
|
378 | *via* **server**. Note that remoteip is interpreted relative to *server*, not the client. | |||
|
379 | So if you have direct ssh access to the machine to which you want to forward connections, | |||
|
380 | then the server *is* the remote machine, and remoteip should be server's IP as seen from the | |||
|
381 | server itself, i.e. 127.0.0.1. Thus, to forward local port 12345 to remote port 54321 on | |||
|
382 | a machine you can see, do:: | |||
|
383 | ||||
|
384 | [client] $> ssh machine 12345:127.0.0.1:54321 -f -N | |||
|
385 | ||||
|
386 | But if your target is actually on a LAN at 192.168.1.123, behind another machine called **login**, | |||
|
387 | then you would do:: | |||
|
388 | ||||
|
389 | [client] $> ssh login 12345:192.168.1.16:54321 -f -N | |||
|
390 | ||||
|
391 | The ``-f -N`` on the end are flags that tell ssh to run in the background, | |||
|
392 | and don't actually run any commands beyond creating the tunnel. | |||
|
393 | ||||
|
394 | .. seealso:: | |||
|
395 | ||||
|
396 | A short discussion of ssh tunnels: http://www.revsys.com/writings/quicktips/ssh-tunnel.html | |||
|
397 | ||||
249 |
|
398 | |||
250 |
|
399 | |||
251 | Stopping Kernels and Consoles |
|
400 | Stopping Kernels and Consoles |
General Comments 0
You need to be logged in to leave comments.
Login now