Skip to content


Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

This program attaches to a pre-configured TAP interface and establishes
an encrypted UDP tunnel between itself and another copy of the program
running on another host. Each instance must have its own secret key and
the public key of the other side; the server must know where to listen
and the client must know where to connect.


Everything about encryption and security in this document may be untrue.
Read the code and draw your own conclusions.


The public-domain NaCl library is used for cryptography support.
See for details.

Encryption is deterministic, with both sides deriving a shared secret
from their own secret key and the other side's public key and using a
unique nonce to encrypt each packet. There is no renegotiation of keys.
In fact, there is no negotiation at all. Ethernet frames are encrypted
as they are received and immediately forwarded. No attempt is made to
obscure the size and timing of packets being sent over the wire.

The encryption adds a constant 56 bytes of overhead to every ethernet
frame, which are themselves about 18 bytes larger than their payload.
The MTU of both TAP interfaces should therefore be set to at least 74
bytes less than the PMTU between the two ends of the tunnel. If there
are MTU problems, the connection will be very slow or packets
mysteriously disappear. There is often no good way to find the right
MTU other than by experimentation.

» Usage

Suppose you want to establish a tunnel between client X and server Y;
the latter must have a public IP address, say

First, configure TAP interfaces on both hosts. You can create TAP
interfaces as root with a recent version of ip(8) or with tunctl(8):

    # ip tuntap add tappet0 mode tap user someuser

    OR: tunctl -u someuser -t tappet0

Replace "someuser" with the name of an unprivileged user that will be
running tappet. Next, configure the interfaces: at a minimum, assign
IP addresses in the same unique subnet to them and bring them up.

Next, generate keypairs on both hosts with tappet-keygen:

    $ ./tappet-keygen X

This will put the secret key into X.key and the public key into
Run the equivalent command on Y, then copy to Y, and to X.
These .pub files can be transmitted in the clear.

Create a four-byte nonce file containing zeroes on both hosts. This file
must be writable by the user that tappet will run as.

    $ dd if=/dev/zero of=nonce bs=1 count=4

Now start tappet on the server and tell it where to listen:

    $ tappet tappet0 ~/nonce ~/Y.key ~/ 1011 -l

Finally, start tappet on the client and tell it where to connect:

    $ tappet tappet0 ~/nonce ~/X.key ~/ 1011

All of these parameters are mandatory. Once started, the program will
run without producing any output until it encounters an error serious
enough to merit a warning or an unceremonious exit.

You should now be able to reach X over the tunnel from Y and vice versa
by using the IP addresses assigned to the TAP interface earlier.

This code is MIT licensed. Use at your own risk.

Abhijit Menon-Sen <>


No description, website, or topics provided.







No packages published