16 KiB
rrqnet(8) Manual Page
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 in the fixed order:
[-v] [-4] [-B n] [-T n] [-m mcast] [-t tap]
- -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 onstderr
about virtually everything. - -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.
- -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.
-
- address-block[:port][=cryptfile] [ -i mac[,mac]* ]
-
Remotes are declared as
ipv4
oripv6
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
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.
[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
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.
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.
[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.
[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.
# 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.
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.
[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:
[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:
[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:
[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:
[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:
# 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
:
# 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>