@c -*-texinfo-*-
@c This file is part of Guile-SSH Reference Manual.
@c Copyright (C) 2015 Artyom V. Poptsov
@c See the file guile-ssh.texi for copying conditions.

@node Tunnels
@section Tunnels

@cindex Tunnels

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

@deffn {Scheme Procedure} make-tunnel session [#:bind-address=''127.0.0.1''] #:port #:host [#:host-port=port] [#:reverse?=#f]
Make a new SSH tunnel using @var{session} from @var{bind-address} and
@var{port} to a @var{host} and @var{host-port}.

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

Setting @var{reverse?} to @code{#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 @var{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 @var{host} and @var{host-port} from the
local machine.  @var{host} can be set to @code{#f} to tell the server to
listen on all addresses and known protocol families.  Setting a @var{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.  @code{start-forward} or
@code{call-with-ssh-forward}.

Return a new tunnel object.
@end deffn

@deffn {Scheme Procedure} tunnel? x
Return @code{#t} if @var{x} is an Guile-SSH tunnel, @code{#f} otherwise.
@end deffn

@deffn {Scheme procedure} tunnel-reverse? x
Check if @var{x} is a reverse port forwarding tunnel.
@end deffn

@deffn {Scheme procedure} tunnel-session tunnel
Get a session associated with a @var{tunnel}.
@end deffn

@deffn {Scheme Procedure} tunnel-bind-address tunnel
Get a source host of a @var{tunnel}.
@end deffn

@deffn {Scheme Procedure} tunnel-port tunnel
Get a local port of a @var{tunnel}.
@end deffn

@deffn {Scheme Procedure} tunnel-host tunnel
Get a remote host of a @var{tunnel}.
@end deffn

@deffn {Scheme Procedure} tunnel-host-port tunnel
Get a remote port of a @var{tunnel}.
@end deffn

@deffn {Scheme Procedure} start-forward tunnel
Start port forwarding on @var{tunnel}.  The procedure actually binds tunnel
ports and forwards data.
@end deffn

@deffn {Scheme Procedure} call-with-ssh-forward tunnel proc
Open a new @var{tunnel} and start port forwarding.  @var{proc} is called with
a socket as an argument.  All I/O on the socket will be forwarded to the
remote host and port of a @var{tunnel}.  Return the result the @var{proc}
call.

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

@lisp
(let ((t (make-tunnel session
                      #:port      12345
                      ;; Suppose a Guile-RPC server listens on
                      ;; 127.0.0.1:23456 on the remote host:
                      #:host      "127.0.0.1"
                      #:host-port 23456)))
  (call-with-ssh-forward t
    (lambda (socket)
      (RPC-PROGRAM-proc some-data #x123 socket))))
@end lisp

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

@subsection 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:

@lisp
#!/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))))
@end lisp

@c Local Variables:
@c TeX-master: "guile-ssh.texi"
@c End:
