rrqnet(8)
=========
:doctype: manpage
:revdate: {sys:date "+%Y-%m-%d %H:%M:%S"}
:COLON: :
:EQUALS: =

NAME
----
rrqnet - Packet tunneling over UDP, multiple channels

SYNOPSIS
--------
*rrqnet* [ OPTIONS ] _port_ ( _remote_ [*-i* _mac_]* )*

DESCRIPTION
-----------
*rrqnet* is a bi-directional networking plug that channels Ethernet
packets between a UDP port and either a tap interface or standard
input/output. It is configured on the command line by declarations of
the remotes it may communicate with.

OPTIONS
-------

Note that any options must be given or omitted in the fixed order:

  [-v] [-tpg] [-4] [-B n] [-T n] [-H r] [-m mcast] [-t tap] [-S source]

*-v*::

This tells *rrqnet* to log its operation on +stderr+. Use *-vv* to
also see logs about connections and messaging, or *-vvv* for *rrqnet*
to be insanely verbose on +stderr+ about virtually everything.

*-tpg*::

This enables a special UDP transport quirk where *rrqnet* expands any
packet in the range [1461,1477] bytes to be of 1478 bytes instead. It
is a work-around for an observed problem in a NAT traversal case for
certain packet sizes in that range.

*-4*::

This directs *rrqnet* to use an ipv4-only socket for its UDP. By
default it opens a dual ipv4/ipv6 socket and internally it then uses
address mapping for ipv4 (i.e. the ::ffff/96 prefix).

*-B* _n_::

This sets the number of receive buffers *rrqnet* should use. The
default is computed to be twice the number of dispatch threads (see
*-T* below). Receive buffers are pre-allocated and recycled.

*-T* _n_::

This sets the number of dispatch threads *rrqnet* should use. The
default is 5. The (additional) main thread handles packet reception,
where it immediately puts received packets into the buffer queue which
is serviced by the dispatch threads for optional decryption, dispatch
decision, optional encryption and delivery.

*-H* _r_::

This sets the number of seconds *rrqnet* should wait between "heart
beat" messages to uplinks. The default is 30. This is used to hold the
uplink open for return traffic through NAT routers. Set to 0 to
disable the heartbeat messages.

*-m* _mcast_::

This tells *rrqnet* to open an ipv4 UDP multicast channel as an
additional remote channel.

*-t* _tap_::

This tells *rrqnet* to open the nominated tap (the _tap_ interface
name) as local channel.

* When a tap is used, stdin and stdout are closed, but stderr remains
open.

* With "*-*" as tap name, *rrqnet* will use stdin/stdout as local
networking channel in a format compatible with VDE plugs.

* Without a *-t* argument, *rrqnet* will operate merely as a virtual
cable switch among its channels.

*-S* _source_::

This tells which source address to use for outgoing UDP messages.

port::

This non-optional argument tells which UDP port to use.

_address-block[:port][=cryptfile]_ [ *-i* _mac_[,_mac_]* ]::

Remotes are declared as +ipv4+ or +ipv6+ network address blocks
optionally with port and transport encryption key file pathname, and
optionally with specific MAC addresses (in a comma separated list) to
ignore. Note that an ipv6 address block might need surrounding square
brackets, to avoid confusion with the port number.

DETAILED DESCRIPTION
--------------------

The intended use of *rrqnet* is to provide VPN (virtual private
network) connectivity between hosts. Each VPN host runs its own
*rrqnet* daemon to channel the traffic to/from tap interfaces on the
hosts via UDP messaging between the hosts.

*rrqnet* is prepared for almost any network layout, even including a
collection of fully connected hosts, although the more common is a
"star' formation. See the EXAMPLES section for inspiration.

*rrqnet* includes logic to protect against broadcast cycles. Whilst
acting as a switch for all its remotes it does not have spanning tree
logic as is offered by bridge interfaces. Generally it's probably best
to avoid cabling cycles, but *rrqnet* also handles full mesh linking
between multiple hosts without additional configuration. Such a setup
is also dynamically adapting to prefer the fastest link between hosts.

By default *rrqnet* opens an +ipv6+ socket on the given port. This
mode handles both +ipv6+ and +ipv4+ remotes with +ipv4+ remotes
handled by means of standard ipv6-mapped address translations. If *-4*
is given, *rrqnet* opens a plain +ipv4+ socket instead, and it cannot
then have +ipv6+ remotes.

An *rrqnet* daemon delivers the packets received from the local end,
i.e., the _tap_ or _stdio_, to known remote ends according the
targeted MAC addresses through its established remote channels.
Likewise, packets from remotes are delivered to the local end or to
other remotes according to the targeted MAC addresses. If a packet is
an Ethernet broadcast, it is delivered to all (known) channels except
the one it came from.

If *rrqnet* is started without *-t* option it will operate like an
Ethernet switch that provides connectivity among its +UDP+ channels
without involving the host network other than for the tunneling.


REMOTE DECLARATIONS
~~~~~~~~~~~~~~~~~~~

.ipv4 address block

This format declares remotes by +ipv4+ address, with optional network
prefix length (0-32), optional port (1-65535) and/or optional key file
pathname. *rrqnet* will accept packets from sources that match by
prefix. If the network prefix length, +n+, is omitted or given as 32,
and a port is given, then it declares an _uplink_.

.matching ipv4 uplink and downlink
====
----
[1.2.3.4]# rrqnet -t vpn0 2300 5.6.7.1:2300=/sec/vpn0.key
[5.6.7.1]# rrqnet -t vpn0 2300 1.2.3.0/24:2300=/sec/vpn0.key
----
====

.plain ipv6 address block

This format declares remotes by ipv6 address, with optional network
prefix length (0-128) and/or optional key file pathname. *rrqnet* will
accept packets from sources that match by prefix. This format (without
square brackets) is without port number part, and it thus only
declares a prefix mask for allowed remote hosts.

.ipv6 address block within square brackets

This format declares remotes by ipv6 address, with optional network
prefix length (0-128) within square brackets, then optionally a port
number and/or an optional key file pathname. *rrqnet* will accept
packets from sources that match by prefix. If the network prefix
length, +n+, is omitted, or given as 128, and a port number is given,
then it declares an _uplink_.

.matching ipv6 uplink and downlink
====
----
[fd::4]# rrqnet -t vpn0 2300 '[fe::1:4]:2300=/sec/vpn0.key'
[fe::1:4]# rrqnet -t vpn0 2300 '[fd::/120]:2300=/sec/vpn0.key'
----
====

The remote declarations define by prefix match the allowed source IP
addresses for incoming UDP traffic. A full network address and port
(e.g +[fe::1:4]:2300+ of example 2) declares an _uplink_ that the
*rrqnet* daemon will establish and maintain by means of regular
"heartbeat" messaging. Other declarations define the mask for allowed
incoming connections, aka _downlinks_, that the dameon expects the
remote end to maintain as uplinks by the remote *rrqnet* daemons.

Two (or more) +rrqnet+ plugs may be set up with uplink connections to
each other in which case both (all) of them maintain the link.

.example of multiple pair-wise uplinks
====
----
[1.0.0.1]# rrqnet -t vpn0 2300 2.0.0.1:2300 3.0.0.1:2300 4.0.0.1:2300
[2.0.0.1]# rrqnet -t vpn0 2300 1.0.0.1:2300 3.0.0.1:2300 4.0.0.1:2300
[3.0.0.1]# rrqnet -t vpn0 2300 2.0.0.1:2300 1.0.0.1:2300 4.0.0.1:2300
[4.0.0.1]# rrqnet -t vpn0 2300 2.0.0.1:2300 3.0.0.1:2300 1.0.0.1:2300
----
====

The *-i* option, if used for a remote declaration, is followed by a
comma separated list of the MAC addresses to ignore on the associated
channel. The *rrqnet* daemon will then just drop any packet with those
MAC addresses (whether source or destination) on the remotes of the
channel.

MULTICAST CHANNEL
-----------------

With the *-m* option, the *rrqnet* daemon also listens for packets on
the declared ipv4 multicast address. It is then treated as a separate,
persistent remote channel.

A multicast channel is declared using the format:
*ipv4:port{=keyfile}*. I.e. it includes the multicast ipv4 address,
the port number (1-65535), and optionally a key file pathname. The
multicast channel is an additional communication channel, but anything
received on it will be treated as being from the multicast IP rather
than the actual source IP.

.multicast example without other remotes
====
----
# rrqnet -m 244.0.2.1:2000 -t vpn0
----
====

The multicast channel is compatible with QEMU multicast socket.

TRANSPORT ENCRYPTION
--------------------

Transport encryption is added to a channel by means of using a shared
key. This is a sizable file, say 1 Mb, of binary data that is used for
scrambling the network packets. For example, 1 Mb random data is fine.

.preparing 1 Mb key file with random content
====
----
dd if=/dev/random of=/sec/keyfile bs=1M count=1
----
====

The key file needs to be copied to all hosts.

A channel that has a key file is declared by appending it to the
channel declaration, as in the following example.

.another example of a downlink with encryption
====
----
[10.0.0.1]# rrqnet -v -t tap0 1400 10.2.0.0/16:1400=/sec/keyfile
----
====

That declaration says that all channels with hosts of ipv4 address
+10.2.0.0/16+, port 1400, use the file +/sec/keyfile+ for transport
encryption. This may also be used as way of restricting remote
connections to those that use the right key.

FURTHER EXAMPLES
----------------

Simple rrqnet set up (ipv6)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
This is an example of connecting two hosts with *rrqnet* without
transport encryption. We pretend these hosts are mutually reachable
with ipv6 addresses +fe::2+ and +fe::1:3+ respectively, and we want to
use the ipv6 network +fd::1000:0/120+ over *rrqnet*. A nominal set up
might then be as follows:

.simple rrqnet set up (ipv6)
====
----
[fe::2]# ip tuntap add tap0 mode tap
[fe::2]# ifconfig tap0 fd::1000:10/120 up
[fe::2]# rrqnet -v -t tap0 1400 '[fe::1:3]:1400' &
--
[fe::1:3]# ip tuntap add tap0 mode tap
[fe::1:3]# ifconfig tap0 fd::1000:20/120 up
[fe::1:3]# rrqnet -v -t tap0 1400 '[fe::2]:1400' &
----
====

Thus, the host +fe::2+ is set up with a tap +tap0+ having ipv6 address
+fd::1000:10/120+, and an *rrqnet* daemon for the tap using UDP port
+1400+ and an uplink +fe::1:3+ port +1400+. Similarly, the host
+fe::1:3+ is set up with a tap +tap0+ having ipv6 address
+fd::1000:20/120+, and an *rrqnet* daemon for the tap using UDP port
+1400+ and an uplink (back) to +fe::2+ port +1400+.

This example also needs ipv6 address resolution set up, which uses the
MAC addresses of the two taps. Let's say it's +02:00:00:00:00:02+ for
+tap0+ on +fe::2+ and +04:00:00:00:00:04+ for +tap0+ on +fe::1:3+.
Then address resolution is established with the following:

.example of ipv6 address resolution set up
====
----
[fe::2]# ip neigh add fd::1000:20 dev tap0 lladdr 04:00:00:00:00:04
--
[fe::1:3]# ip neigh add fd::1000:10 dev tap0 lladdr 02:00:00:00:00:02
----
====

Simple rrqnet set up (ipv4)
~~~~~~~~~~~~~~~~~~~~~~~~~~~

This is an example of connecting two hosts with *rrqnet* without
transport encryption. We pretend these hosts are mutually reachable
with ipv4 addresses +10.0.0.1+ and +192.168.0.1+ respectively, and we
want to use the ipv4 network +10.100.100.0/24+ over *rrqnet*. A
nominal set up might be as follows:

.Simple rrqnet set up (ipv4)
====
----
[10.0.0.1]# ip tuntap add tap0 mode tap
[10.0.0.1]# ifconfig tap0 10.100.100.1/24 up
[10.0.0.1]# rrqnet -v -t tap0 1400 192.168.0.1:1400 &
--
[192.168.0.1]# ip tuntap add tap0 mode tap
[192.168.0.1]# ifconfig tap0 10.100.100.2/24 up
[192.168.0.1]# rrqnet -v -t tap0 1400 10.0.0.1:1400 &
----
====

Thus, the host +10.0.0.1+ is set up with a tap +tap0+ having ipv4
address +10.100.100.1/24+, and an *rrqnet* daemon for the tap and UDP
port +1400+ uplink +192.168.0.1+ port +1400+. Similarly, the host
+192.168.0.1+ is set up with a tap +tap0+ having ipv4 address
+10.100.100.2/24+, and an *rrqnet* daemon for the tap and UDP port
+1400+ and uplink (back) to +10.0.0.1+ port 1400.

The kernel automagically performs ipv4 address resolution to learn the
MAC addresses associated with the remote ipv4 addresses through the
taps.

rrqnet set up through NAT
~~~~~~~~~~~~~~~~~~~~~~~~~

If one of the hosts, say +192.168.0.1+, is behind a NAT router with
different IP, say a dynamic IP on the net +10.2.0.0/16+, we need a
different set up. In this scenario, the first host would be set up as
a "server" and the second a client that would utilize the router's NAT
function for return traffic. The set up would be as follows:

.rrqnet set up through NAT
====
----
[10.0.0.1]# ip tuntap add tap0 mode tap
[10.0.0.1]# ifconfig tap0 10.100.100.1 up
[10.0.0.1]# rrqnet -v -t tap0 1400 10.2.0.0/16:1400 &
--
[192.168.0.1]# ip tuntap add tap0 mode tap
[192.168.0.1]# ifconfig tap0 10.100.100.2 up
[192.168.0.1]# rrqnet -v -t tap0 1400 10.0.0.1:1400 &
----
====

Thus, the "server" is set up to allow connections from any host on the
network +10.2.0.0/16+ port 1400 while the "client" is set up the same
way as in the simple example above. The client will establish and
uphold the connection by virtue of its 30 second "heart beat", and
return traffic will be channeled via the router's NAT function.

Note that the server sees the _external_ IP of the client and not its
_internal_ IP. The server's *rrqnet* therefore has a remote
declaration to allow messages from that external IP. In the example
case it allows the address block of the 16 bit common prefix (the
choice of a 16 bit prefix is merely for the sake of this example).

Multiple client hosts
~~~~~~~~~~~~~~~~~~~~~

In a "client-server" set up there can be any number of "client" hosts.
However, the "clients" behind a common NAT router must then use
distinct ports as otherwise the router will be confused about the
return traffic.

With multiple remote channels, an *rrqnet* daemon serves as a network
switch that forwards traffic in between the channels as well as to and
from the "server" tap. The daemon also forwards Ethernet broadcasts
out on all established channels in support of ARP messaging.

Further, an *rrqnet* daemon may be both a "server" with down-link
channels, and a "client" with one or more up-link channels, all at the
same time. Such a daemon forwards traffic between all established
channels by means of the Ethernet addresses, as well as broadcasts
onto all channels.

Stdio network
~~~~~~~~~~~~~
The *rrqnet* daemon may be configured to use standard input/output
rather than a tap for local network traffic. This operation mode has
more rare use cases, such as linking two *rrqnet* daemons or
connecting to a VDE network. For example:

.stdio network between two rrqnet plugs
====
----
# dpipe rrqnet 1400 0.0.0.0/0=keyfile0 = rrqnet 1401 0.0.0.0/0=keyfile1 &
----
====

The example above connects the two "server" +rrqnet+ daemons operating
at different UDP ports, each accepting messages from any ipv4 host.
Port +1400+ has +keyfile0+ for transport encryption, and +1401+ has
+keyfile1+ for transport encryption.

The follwoing, different, example connects the *rrqnet* traffic to a
VDE network via a +vde_plug+:

.stdio network to a vde_plug
====
----
# dpipe rrqnet 1400 0.0.0.0/0 = vde_plug /tmp/vde1.ctl &
----
====

Note that *rrqnet* and +vde_plug+ use compatible stdio packet
representation.

NOTES
-----

The UDP receiver in *rrqnet* accepts packets from the specified remote
ends only, but it doesn't perform any payload verification. Messages
smaller than 12 bytes are taken as "heartbeats", and larger messages
are first decrypted as applicable, then treated as Ethernet messages
and delivered according to their destination MAC addresses.

*rrqnet* bridges its connections, and forwards Ethernet broadcasts to
all known end-points except the incoming one. The input logic takes
care of avoiding broadcast cycles.

*rrqnet* does not have Spanning Tree Logic (STL), but some simple
timing logic based on binding MAC addresses to remotes. That binding
is sticky for a short time: 6s for broadcast and 20s for unicast. Any
packet received during that time from the same MAC address via another
remote is dropped. Also, downlinks without incoming traffic for 3
minutes are considered stale.

*rrqnet* sends a "heartbeat" of an empty UDP message on its uplinks
every 30 seconds. This is done in order to maintain the channel with
the remote end without actually binding any MAC address.

When the local input is a tap, *rrqnet* closes standard input and
standard output, but not standard error, before entering the packet
handling loop.

Using +-t -+ for stdin/stdout packet traffic is compatible with
+vde_plug+.

SEE ALSO
--------
*rrqnet-cron(8)* - Management script to uphold a *rrqnet* plug.
*rrqnet-ifupdown(8)* - Management script to uphold a *rrqnet* plug.

*vde_plug(1)* - Virtual Distributed Ethernet plug.

AUTHOR
------
Ralph Rönnquist <ralph.ronnquist@gmail.com>
