Tunnels
=======

The following procedures from (ssh tunnel) module are a high-level API built upon the basic port forwarding facilities for managing port forwards.

 -- Scheme Procedure: make-tunnel session [#:bind-address=''127.0.0.1''] #:port #:host [#:host-port=port] [#:reverse?=#f]
     Make a new SSH tunnel using SESSION from BIND-ADDRESS and PORT to a HOST and HOST-PORT.

     The procedure is capable of creating both direct and reverse port forwarding tunnels; the type of a tunnel is determined by REVERSE? argument.  If REVERSE? is set to #f then a reverse port forwarding tunnel will be created.

     Setting REVERSE? to #t changes the direction of the tunnel and a reverse port forwarding tunnel will be created.  In this case a server allocates a socket to listen to PORT on the remote side, and whenever a connection is made to this port, the connection is forwarded over the secure channel, and a connection is made to HOST and HOST-PORT from the local machine.  HOST can be set to #f to tell the server to listen on all addresses and known protocol families.  Setting a PORT to 0 tells the server to bind the first unprivileged port.

     The procedure does not binds ports nor transfers data to the port (in case of reverse port forwarding), you should start port forwarding by means of the procedures that operate on a <tunnel> object -- e.g.  start-forward or call-with-ssh-forward.

     Return a new tunnel object.

 -- Scheme Procedure: tunnel? x
     Return #t if X is an Guile-SSH tunnel, #f otherwise.

 -- Scheme procedure: tunnel-reverse? x
     Check if X is a reverse port forwarding tunnel.

 -- Scheme procedure: tunnel-session tunnel
     Get a session associated with a TUNNEL.

 -- Scheme Procedure: tunnel-bind-address tunnel
     Get a source host of a TUNNEL.

 -- Scheme Procedure: tunnel-port tunnel
     Get a local port of a TUNNEL.

 -- Scheme Procedure: tunnel-host tunnel
     Get a remote host of a TUNNEL.

 -- Scheme Procedure: tunnel-host-port tunnel
     Get a remote port of a TUNNEL.

 -- Scheme Procedure: start-forward tunnel
     Start port forwarding on TUNNEL.  The procedure actually binds tunnel ports and forwards data.

 -- Scheme Procedure: call-with-ssh-forward tunnel proc
     Open a new TUNNEL and start port forwarding. PROC is called with an open channel as an argument. All I/O on the channel will be forwarded to the remote host and port of a TUNNEL. Return the result the PROC call.

     As a practical example, let's say you want to use Guile-RPC (https://www.gnu.org/software/guile-rpc/) over SSH. Here's how you can implement a using call-with-ssh-forward:

          (let ((pid (primitive-fork)))
            (if (zero? pid)
                ;; Make a new SSH session, connect it and authenticate the user.
                (let* ((host    "example.org")
                       (user    "alice")
                       (session (make-session #:user user
                                              #:host host
                                              #:port 22
                                              #:log-verbosity 'nolog)))
                  (connect! session)
                  (userauth-agent! session)
                  ;; Make a new SSH tunnel.
                  (let ((tunnel (make-tunnel session
                                             #:port 12345
                                             ;; Guile-RPC server listens on 127.0.0.1
                                             ;; on the remote host.
                                             #:host "127.0.0.1"
                                             ;; Guile-RPC server port.
                                             #:host-port 6666)))
                    ;; Start the forwarder loop.
                    (start-forward tunnel)))
                ;; Parent process.
                (let ((sock (socket PF_INET SOCK_STREAM 0)))
                (dynamic-wind
                  (const #t)
                  (lambda ()
                    (sleep 1)
                    ;; Connect to the port that is listened to by the spawned process.
                    (connect sock AF_INET
                      (inet-pton AF_INET "127.0.0.1")
                      12345)

                    ;; Make an RPC call using the SSH tunnel.
                    (display (invoke-split-number 3.14 #x7777 sock))
                    (newline))
                  (lambda ()
                    (close sock)
                    (kill pid SIGTERM)
                    (waitpid pid))))))

     The full example of an RPC client that uses a SSH tunnel is in $prefix/share/guile-ssh/examples/rpc directory.

Example
-------

Here is a simple Guile program that connects to ``www.example.org'' and starts port forwading from the local port 8080 to the port 80 on the remote host:

     #!/usr/bin/guile \
     -e main
     !#

     (use-modules (ssh session)
                  (ssh auth)
                  (ssh key)
                  (ssh tunnel))

     (define (main args)
       (let ((s (make-session #:user          "alice"
                              #:host          "localhost"
                              #:port          22
                              #:log-verbosity 'nolog))
             (k (private-key-from-file "/home/alice/.ssh/id_rsa")))
         (connect! s)
         (userauth-public-key! s k)
         (let ((t (make-tunnel s
                               #:port      8080
                               #:host      "www.example.org"
                               #:host-port 80)))
           (start-forward t))))