summaryrefslogtreecommitdiff
path: root/_posts/2016-10-25-setup-a-vpn-with-cjdns.md
blob: 74446b048b2dad389078bb7c499176d40fc6d221 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
---
title: Setup a VPN with cjdns
date: 2016-10-25 08:00:34
tags: Tutorial VPN cjdns GNU+Linux FreeBSD
layout: post
authors:
  - ["Patrick Spek", "http://tyil.work"]
---

In this tutorial I will outline a simple setup for a [VPN][vpn] using
[`cjdns`][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:

{% highlight sh %}
pkg install gmake node
{% endhighlight %}

### Compiling
Next up is getting the cjdns sources and compile these, as cjdns is not
available as a prebuilt package:

{% highlight sh %}
mkdir -p ~/.local/src
cd $_
git clone https://github.com/cjdelisle/cjdns.git cjdns
cd $_
./do
{% endhighlight %}

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:

{% highlight sh %}
cp cjdroute /usr/local/bin/.
hash -r
{% endhighlight %}

### 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`:

{% highlight sh %}
(umask 177 && cjdroute --genconf > /usr/local/etc/cjdroute.conf)
{% endhighlight %}

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.

{% highlight json %}
"authorizedPasswords":
[
    {"password": "aeQu6pa4Vuecai3iebah7ogeiShaeDaepha6Mae1yooThoF0oa0Eetha9oox", "user": "client_1"},
    {"password": "aiweequuthohkahx4tahLohPiezee9OhweiShoNeephe0iekai2jo9Toorah", "user": "client_2"},
]
{% endhighlight %}

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`:

{% highlight sh %}
#! /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"
{% endhighlight %}

Afterwards, you must enable the service in `/etc/rc.conf.local` like follows:

{% highlight sh %}
echo 'cjdroute_enable="YES"' >> /etc/rc.conf.local
{% endhighlight %}

## 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:

{% highlight sh %}
emerge gmake nodejs
{% endhighlight %}

### 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:

{% highlight sh %}
cjdroute --genconf > /etc/cjdroute.conf
{% endhighlight %}

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`:

{% highlight json %}
"connectTo":
{
	"192.168.1.1:9416":
	{
		"login": "client_1",
		"password": "aeQu6pa4Vuecai3iebah7ogeiShaeDaepha6Mae1yooThoF0oa0Eetha9oox",
		"publicKey": "thisIsJustForAnExampleDoNotUseThisInYourConfFile_1.k"
	}
}
{% endhighlight %}

On client 2:

{% highlight json %}
"connectTo":
{
	"192.168.1.1:9416":
	{
		"login": "client_2",
		"password": "aiweequuthohkahx4tahLohPiezee9OhweiShoNeephe0iekai2jo9Toorah",
		"publicKey": "thisIsJustForAnExampleDoNotUseThisInYourConfFile_1.k"
	}
}
{% endhighlight %}

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:

{% highlight sh %}
cp ~/.local/src/cjdns/contrib/openrc/cjdns /etc/init.d/cjdroute
{% endhighlight %}

Now add the service to system startup and start the service:

{% highlight sh %}
rc-update add cjdroute default
rc-service cjdroute start
{% endhighlight %}

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.

[cjdns]: https://github.com/cjdelisle/cjdns
[vpn]: https://en.wikipedia.org/wiki/Virtual_private_network