
========
parproxy
========

:Parproxy: Paramiko SSH2 ProxyCommand addon
:Copyright: Copyright (c) 2009-2011  Rene Koecher <shirk@bitspin.org>
:License: LGPL
:Homepage: http://pypi.python.org/pypi/paraproxy

history
=======

version       note
============= =========================================
paraproxy 1.0 "Call me God" release, 02 July 2009
paraproxy 1.1 "All my socks" release, 19 Februray 2010
paraproxy 1.2 "Chain reaction" release, 21 May 2011
============= =========================================

What
----

Paraproxy is a supplement to the great "paramiko" SSH2 module.
While paramiko has a really good support for SSH(2) it lacks the
ProxyCommand feature.

ProxyCommands can be used e.g. to connect to VPN tunnels but
they provide manny other nice features.

Paraproxy, once imported will hook into the SSHClient class provided
by paramiko which in turn gains full support for SSH ProxyCommands.

No changes to existing code are needed.

Paraproxy is written entirely in python and is
released under the GNU LGPL (lesser GPL). 

Requirements
------------

  - python 2.4	<http://www.python.org/>
    (python 2.3 is also supported, but not recommended)
  - paramiko 1.7.4	<http://www.lag.net/paramiko>

Portability
-----------

Paraproxy requires unix domain sockets to do it's magic.
As a result support is only available for Linux and MacOS
(this may change depending on demand for Win32 support).

So far I've been testing on different Linux and MacOS flavors
without any problems.

Bugs & Support
--------------

This addon was written for my private needs and has no "real" support.
If you encounter bigger problems dorp me a line.

You can enable verbose debugging by setting the environment variable
*PARAMIKO_SSH_HOOK_VERBOSE* to 1. This will report each step paraproxy 
takes to establish a connection.

Sometimes it seems the thread used to run the proxy command seems
to leave behind a unix socket in /tmp/.
This issue was takled in paraproxy 1.1 release and is hopfully gone now.

Multi-layer proxy chains - since 1.2:
-------------------------------------

Sine version 1.2 paraproxy will detect and connect to multi-layer
proxy chains. This means you can connect to hosts which are not
directly reachable in your network by using an arbitrary number of 
intermediate hosts as "hops".
Hops are required to use ssh or ssh.exe in their respective ProxyCommand
in order to be detected by paraproxy.
In addition to this paramiko needs to know the hostkeys of each hop.
An expamle for a ssh-config using a two-hop chain may look like this:

#------------
# gatekeeper is directly reachable
# yuka is reachable from gatekeeper
# *.kamakura is only reachable from yuka

Host yuka
	ProxyCommand ssh -q -A -x gatekeeper 'nc -w1 %h 22'

Host *.kamakura
	ProxyCommand ssh -q -A -x yuka 'nc -w 1 %h 22'

#------------

An attempt to connect to mayu.kamakura would result in the following chain:

	CONNECT gatekeeper:22
	SSHAUTH gatekeeper
	--> EXEC 'nc -w1 yuka 22'
	    SSHAUTH yuka
	    --> EXEC 'nc -w1 mayu.kamakura 22'
	    SSHAUTH mayu.kamakura

You could have a non-ssh ProxyCommand at the start or end of the chain
like this:

#-------------------
# gatekeeper is reachable via the foo-connector

Host gatekeeper
	ProxyCommand foo-connect %h %p

In this case the proxy command will be executed as usual and if
successful the chain will be established as described above.


Demo
----

The following code is adapted from a paramiko example and
shows the basic usage::

    import paraproxy, paramiko, base64
    # ProxyCommands are enabled and will be used
    key = paramiko.RSAKey(data=base64.decodestring('AAA...'))
    client = paramiko.SSHClient()
    client.get_host_keys().add('ssh.example.com', 'ssh-rsa', key)
    client.connect('ssh.example.com', username='strongbad', password='thecheat')
    stdin, stdout, stderr = client.exec_command('ls')
    for line in stdout:
        print '... ' + line.strip('\n')
    client.close()

...which prints out the results of executing ``ls`` on a remote server.
(the host key 'AAA...' should of course be replaced by the actual base64
encoding of the host key.  if you skip host key verification, the
connection is not secure!)
