Setup a VPN with cjdns
In this tutorial I will outline a simple setup for a VPN using
cjdns
. Cjdns will allow you to setup a secure mesh vpn which uses
IPv6 internally.
Requirements
For this tutorial, I have used two client machines, both running Funtoo. A FreeBSD 11 server is used as a global connection point.
You are ofcourse able to use any other OS or distro supported by cjdns, but you may have to update some steps to work on your environment in that case.
Installation of the server
Dependencies
Before you can begin, we need some dependencies. There’s only two of those, and
they are available via pkg
to make it even easier. Install them as follows:
pkg install gmake node
Compiling
Next up is getting the cjdns sources and compile these, as cjdns is not available as a prebuilt package:
mkdir -p ~/.local/src
cd $_
git clone https://github.com/cjdelisle/cjdns.git cjdns
cd $_
./do
To make the compiled binary available system-wide so we can use it with a
system service, copy it to /usr/local/bin
and rehash to make it available as
a direct command:
cp cjdroute /usr/local/bin/.
hash -r
Configuring
Cjdns provides a flag to generate the initial configuration. This will provide
you with some sane defaults where only a couple of small changes are needed to
make it work properly. Generate these defaults with --genconf
:
(umask 177 && cjdroute --genconf > /usr/local/etc/cjdroute.conf)
The umask will make all following commands write files using 600
permissions.
This makes sure the config file is not readable by people who shouldn’t be able
to read it. Be sure to check wether the owner of the file is root
!
Now you can start actually configuring the node to allow incoming connections.
You have to find the authorizedPasswords
array in the cjdroute.conf
file
and remove the contents of it. Then you can add your own machines in it. This
guide follows the assumption of two clients, so the config for two clients will
be shown here. You can add more clients if you wish, ofcourse.
"authorizedPasswords":
[
{"password": "aeQu6pa4Vuecai3iebah7ogeiShaeDaepha6Mae1yooThoF0oa0Eetha9oox", "user": "client_1"},
{"password": "aiweequuthohkahx4tahLohPiezee9OhweiShoNeephe0iekai2jo9Toorah", "user": "client_2"},
]
If you need to generate a password, you can make use of the tool pwgen
,
available at your local package manager. You can then generate new passwords by
running pwgen 60 -1
. Change the 60
around if you want passwords of a
different size.
Adding a startup service
rcinit has deceptively easy scripts to make applications available as services.
This in turn allows you to enable a service at startup. This way you can make
sure cjdns starts whenever the server boots. You can copy the following
contents directly into /usr/local/etc/rc.d/cjdroute
:
#!/bin/sh
# PROVIDE: cjdroute
# KEYWORD: shutdown
#
# Add the following lines to /etc/rc.conf to enable cjdroute:
#
#cjdroute_enable="YES"
. /etc/rc.subr
name="cjdroute"
rcvar="cjdroute_enable"
load_rc_config $name
: ${cjdroute_config:=/usr/local/etc/cjdroute.conf}
command="/usr/local/bin/cjdroute"
command_args=" < ${cjdroute_config}"
run_rc_command "$1"
Afterwards, you must enable the service in /etc/rc.conf.local
like follows:
echo 'cjdroute_enable="YES"' >> /etc/rc.conf.local
Installation of the clients
Dependencies
The dependencies are still on gmake
and node
, so simply install those on
your clients. This guide assumes using Funtoo for the clients, so installation
would go as follows:
emerge gmake nodejs
Compiling
Compilation is the same as for the server, so check back there for more information if you have already forgotten.
Configuring
Generating the base configuration is again done using cjdroute --genconf
,
just like on the server. On Funtoo, config files generally reside in /etc
instead of /usr/local/etc
, so you should set the filepath you write the
configuration to accordingly:
cjdroute --genconf > /etc/cjdroute.conf
Setting up the connections differs as well, as the clients are going to make an outbound connection to the server, which is configured to accept inbound connections.
You should still clean the authorizedPasswords
array, as it comes with a
default entry that is uncommented.
Now you can setup outbound connections on the clients. You set these up in the
connectTo
block of cjdroute.conf
. For this example, the IP 192.168.1.1 is
used to denote the server IP. Unsurprisingly, you should change this to your
server’s actual IP. You can find the publicKey
value at the top of your
server’s cjdroute.conf
file.
On client 1, put the following in your cjdroute.conf
:
"connectTo":
{
"192.168.1.1:9416":
{
"login": "client_1",
"password": "aeQu6pa4Vuecai3iebah7ogeiShaeDaepha6Mae1yooThoF0oa0Eetha9oox",
"publicKey": "thisIsJustForAnExampleDoNotUseThisInYourConfFile_1.k"
}
}
On client 2:
"connectTo":
{
"192.168.1.1:9416":
{
"login": "client_2",
"password": "aiweequuthohkahx4tahLohPiezee9OhweiShoNeephe0iekai2jo9Toorah",
"publicKey": "thisIsJustForAnExampleDoNotUseThisInYourConfFile_1.k"
}
}
That is all for configuring the nodes.
Adding a startup service
You probably want cjdroute to run at system startup so you can immediatly use your VPN. For openrc based systems, such as Funtoo, cjdns comes with a ready to use service script. To make this available to your system, copy it over to the right directory:
cp ~/.local/src/cjdns/contrib/openrc/cjdns /etc/init.d/cjdroute
Now add the service to system startup and start the service:
rc-update add cjdroute default
rc-service cjdroute start
That should be sufficient to get cjdns up and running for an encrypted VPN. You
can find the IPs of each of your systems at the top of your cjdroute.conf
files, in the ipv6
attribute.