aboutsummaryrefslogtreecommitdiff
path: root/content/weblog/2018-11-02_your-own-vpn/index.md
blob: e1140c6d3d820cdbbd2978758db2d39222747e96 (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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
+++
title = "Setting up your own VPN"
date = 2018-11-02T05:43:00Z
+++

There are many reasons why you would want to use a VPN, especially in this day
and age. The major one would be to securely and more privately surf the web, but
that is far from the only reason. I for one use it as well to be able to set up
a remote network with my desktop PC while I'm away from home, so that I can
access all of my files through SSH. There are a ton of other reasons as to why a
VPN could be useful, but that is not the topic of this post, rather I will be
writing here about to set up your own VPN (yes your own!) on a VPS, or any other
kind of linux server for that matter, using OpenVPN.

<!-- more -->

I am in fact running my own VPN in the same server that I use to host this site
and other projects of mine. However due to certain circumstances I need to
migrate to another VPS, and so I decided to write this little guide to refresh
my memory on how to set up OpenVPN.

Before we begin to set up our VPN, we need to install OpenVPN. I am using Debian
Stretch, so your install process may differ depending on your distro.

```sh
# apt-get install openvpn easy-rsa
```

## Configuring OpenVPN

After installing the necessary packages, we proceed to configure OpenVPN. First
we need to extract the sample OpenVPN server configuration file to /etc/openvpn

```sh
# gunzip -c /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz > /etc/openvpn/server.conf
```

Next we proceed to edit it.

```sh
# vim /etc/openvpn/server.conf
```

Inside we will make changes to basically use higher-level encryption, forward
web traffic to destination, prevent DNS leaking, and set up permissions.

First we make sure that we are using 2048 bit-length keys instead of 1024. In my
case it was already set to 2048 bit by default, however, the first time that I
set up OpenVPN the default was 1024, so find this line

```
dh dh2048.pem
```

If instead you see "dh1024.pem" change it so that it is like in this example.

Next we make sure to redirect all traffic to its proper destination. Find this
line

```
push "redirect-gateway def1 bypass-dhcp"
```

If it has a semicolon (;) at the beginning, remove it so that it is uncommented.

Now we will tell OpenVPN to use OpenDNS for DNS resolution. This will help
prevent DNS requests from leaking outside of the VPN connection.

Immediately after the previous setting, you will see a block of comments
followed by two commented lines

```
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
```

As previously, just remove the semicolon character from the beginning of the
line.

Next we should comment the next line with a # or ; character. It is supposed to
be used as an extra security measure especially against DoS attacks, however, we
don't really need it

```
tls-auth ta.key 0 # This file is secret
```

If you really want to leave that on, you will need to generate it

```sh
openvpn --genkey --secret ta.key
```

And last but not least in our server.conf file, we need to adjust permissions.
Find and uncomment these lines

```
user nobody
group nogroup
```

This way OpenVPN doesn't run as the root user. And we don't want any random
program wildly running as root, especially ones that are exposed to the
interwebz, no sir we don't ( ͡° ͜ʖ ͡°).

After having made all the needed changes, just write them and close the editor.

## Configuring network and firewall

We need to enable packet forwarding, otherwise our traffic will not leave the
server.

So that we don't have to reboot our server (let's leave all that rebooting to
windows systems), we can enable it on runtime by running the following command

```sh
# sysctl net.ipv4.ip_forward=1
```

However, we need to make this change permanent as well, so we open the following
file

```sh
# vim /etc/sysctl.conf
```

And uncomment the following line by removing the hash character (#) at the
beginning of the line

```sh
net.ipv4.ip_forward=1
```

Save your changes and close the editor.

Now we need to properly set up our firewall. Personally I use ufw as front-end
to iptables, since it is pretty easy to set up and use (as its name suggests,
uncomplicated firewall). If you don't have it installed yet, you can go ahead
and run

```sh
# apt-get install ufw
```

By default ufw denies all incoming connections and allow all outgoing. Those
defaults are fine for my case, some might prefer to deny all outgoing
connections by default, some riskier guys (or gals) might prefer to allow all by
default (however, you wouldn't have unprotected fun time with just any partner,
now would you?( ͡° ͜ʖ ͡°)), however explaining all the details about ufw is out of
the scope of this tutorial, but I invite you use your duckduckgo-fu if you're
interested in learning more about ufw.

Now, as ufw denies all incoming connections by default, we need to configure it
so that we don't get locked out of our server. If you use the standard ssh port,
just run the following command

```sh
# ufw allow ssh
```

ufw comes with some presets for the most common services, so that in fact allows
connections from port 22 over tcp. If you, like me, prefer to use another port
for SSH, you need to specify the port and protocol manually, so, if say, you
connect to SSH over port 3333, you would run

```sh
# ufw allow 3333/tcp
```

(Of course that is not the actual port I myself use for ssh, so don't even try
(That is however not an open invitation to try and guess my SSH port and hack
yourself into my server (seriously, please don't hack me ´༎ຶ ͜ʖ ༎ຶ ))).

In this tutorial we will be using OpenVPN on port 1194 over UDP, so we must
allow it

```sh
# ufw allow 1194/udp
```

Next we need to set ufw's forwarding policy, so we open the primary
configuration file

```sh
# vim /etc/default/ufw
```

Modify the following line

```
DEFAULT_FORWARD_POLICY="DROP"
```

So that it looks like this

```
DEFAULT_FORWARD_POLICY="ACCEPT"
```

Save and exit.

Open this file

```sh
# vim /etc/ufw/before.rules
```

And add the rules for OpenVPN somewhere after the first block of comments

```
# START OPENVPN RULES
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
# Allow traffic from OpenVPN client to eth0
-A POSTROUTING -s 10.8.0.0/8 -o eth0 -j MASQUERADE
COMMIT
# END OPENVPN RULES
```

Once more, save and exit.

Now we can safely enable ufw

```sh
# ufw enable
```

It will say something about disrupting current SSH connections, however, since
we just added the needed rules for SSH we can go ahead and answer y.

## Configuring the Certificate Authority

Now we are going to setup our own CA. This is crucial since OpenVPN encrypts
traffic (what use is a VPN that doesn't encrypt traffic?)

First we need to copy the RSA generation scripts

```sh
# cp -r /usr/share/easy-rsa/ /etc/openvpn
```

Next, we create a directory to house our keys

```sh
# mkdir /etc/openvpn/easy-rsa/keys
```

Now we open the variables files

```sh
# vim /etc/openvpn/easy-rsa/vars
```

And modify these lines according to our needs/preferences (they are not that
really important)

```sh
# These are the default values for fields
# which will be placed in the certificate.
# Don't leave any of these fields blank.
export KEY_COUNTRY="US"
export KEY_PROVINCE="CA"
export KEY_CITY="SanFrancisco"
export KEY_ORG="Fort-Funston"
export KEY_EMAIL="me@myhost.mydomain"
export KEY_OU="MyOrganizationalUnit"
```

Then, in the same file, we need to change the name of the key. For simplicity's
sake we will use the name "server", since that's the name that OpenVPN uses to
reference the .key and .crt files by default. If you decide to use a different
name, you will need to modify the OpenVPN configuration files that reference the
aformentioned files.

So change this

```sh
# X509 Subject Field
export KEY_NAME="EasyRSA"
```

Into this

```sh
# X509 Subject Field
export KEY_NAME="server"
```

Save and exit.

Next we will use OpenSSL to generate the Diffie-Helman parameters. Grab a cup of
tea, take a seat, it might take some minutes

```sh
# openssl dhparam -out /etc/openvpn/dh2048.pem 2048
```

Now that our certificate is ready, it's time to generate a key. For that, we
first switch into the easy-rsa folder

```sh
# cd /etc/openvpn/easy-rsa
```

Now we start setting up the CA. We first, need to initialize the Public Key
Infrastructure (PKI). For that we need to source the vars file

```sh
# . ./var
```

If you get something like this in your output

```
  No /etc/openvpn/easy-rsa/openssl.cnf file could be found
  Further invocations will fail
```

Your .cnf might have a different name (due to differing versions of OpenSSL).
Just copy it like this

```sh
# cp openssl-*.cnf openssl.cnf
```

And source the vars file one more time.

After sourcing the vars file, it will give us a warning about removing some
files. Don't sweat it, it's fine, since right now that folder is empty. So we go
ahead and clear any and all keys that might interfere with out setup

```sh
# ./clean-all
```

Finally, we can go ahead and build our CA using the following command

```sh
# ./build-ca
```

We can skip through each prompt since we set up that info previously inside the
vars file. The CA is now ready to go.

## Generating a certificate and key for our server

Now we can proceed to actually setting up and launching OpenVPN.

While still on the easy-rsa folder, we input this command

```sh
# ./build-key-server server
```

server is the name of the key that we set up earlier in the vars file. We can go
ahead, and as earlier leave the defaults which we configured in the vars file.

Upon reaching these prompts

```
A challenge password []:
An optional company name []:
```

Just press enter for both. We won't be needing them for this setup.

The last two entries require a y answer

```
Sign the certificate? [y/n]
1 out of 1 certificate requests certified, commit? [y/n]
```

Now that our server certificate and key are ready, we need to copy them over to
/etc/openvpn, since that the directory in which OpenVPN will be looking for them

```sh
# cp /etc/openvpn/easy-rsa/keys/{server.crt,server.key,ca.crt} /etc/openvpn
```

Now we can start OpenVPN

```sh
# systemctl start openvpn
```

You can check if it launched correctly by running

```sh
# systemctl status openvpn
```

It should say something like "Active: active (exited) since..." then,
congratulations! OpenVPN is now running in your server. If it says otherwise,
maybe something like "inactive (dead)...", you might to check the log file
"/var/log/syslog" for errors.

If all is fine and dandy, you can enable the OpenVPN service so that it
automatically starts on each reboot

```sh
# systemctl enable openvpn
```

## Generating certificates keys for clients

Ideally each client that needs to connect to the VPN should have their own
unique certificate and key. Actually, by default, OpenVPN doesn't allow
simultaneous connections using the same certificate.

Because of that you will need to repeat the steps in this section for each
device that you wish to allow to connect to your VPN, just changing the name
"desktop" below, to something different like "laptop" or "phone". This way you
can also later deactivate a specific device/client from accessing if needed be.

I will start by building the key and certificate for my desktop computer, so I
will be using the "desktop" name as an example. We still should be in our
easy-rsa directory

```sh
# ./build-key desktop
```

Once more, as with the server's cert and key, we will asked about some info
which we set on the vars, so we should skip all that by pressing enter
(including setting the passwords). Just press y both times at the end to
confirm.

Now we need the sample profile to the keys folder. We need to change its
extension to ovpn, since that will be the file that OpenVPN will use on each
device to automatically set the profile to connect to our VPN server

```sh
# cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/easy-rsa/keys/client.ovpn
```

The name of this file doesn't need to be related to our client's cert and key
filenames, we can actually name to something that will describe our VPN, since
that will be the name that OpenVPN will be pick up by default in our client
device for our profile. So you can name it "work.ovpn" or maybe something more
rich like "muhfreedumbs.ovpn"

```sh
# mv keys/client.ovpn keys/muhfreedumbs.ovpn
```

After that we need to make some modifications to our ovpn file, so open it up

```sh
# vim keys/muhfreedumbs.ovpn
```

And edit the line starting with remote with your server's ip address

```
remote your.ip.address.here 1194
```

And if you chose to leave out the "ta.key" file protection option, don't forget
to comment this line

```
tls-auth ta.key 0
```

Next we find these two lines and uncomment them (remove the ; character at the
beginning of each line)

```
user nobody
group nogroup
```

That's it. All that's left is to copy the client key and certificate, and the
ovpn file over to our device. First we need to copy them to another folder that
is available to our standard (non-root) user on the server for reading, since it
is not a good idea to have root login enabled on SSH. For example, we could
create a "vpnkeys" folder in our user's home directory

```sh
$ mkdir /home/yaroslav/vpnkeys
```

And then copy the need files over to that folder

```sh
# cp /etc/openvpn/easy-rsa/keys/{desktop.key,desktop.crt,muhfreedumbs.ovpn} /home/yaroslav/vpnkeys/
```

There is one more file that we need to copy, the server's certificate

```sh
# cp /etc/openvpn/ca.crt /home/yaroslav/vpnkeys/
```

If you previously also left the secret "ta.key" file enabled and generated it,
you should copy that too.

Note that the "ca.crt" and the ovpn files will be the same for all devices. If
you wish to create a new key/cert pair for another device/client, you DO NOT
need to create a new ovpn file, just run the "./build-key clientkeyname" command
as before and copy the same old ovpn and ca.crt file along with client key and
cert to your other device.

Now we need to actually copy the keys to our device. You can use rsync or scp
for that. For example, I will be using scp to copy them to my Keys folder

```sh
$ scp -P portno -r yaroslav@ipaddressorurl:/home/yaroslav/vpnkeys ~/Keys/
```

If you need to use your VPN on your mobile device, just copy them first to your
computer through SSH, and then transfer them over to your mobile device.

After transferring them to the device, you should delete the keys from the home
directory.

## Conclusion

Now that all is setup on the server side of things, you can go ahead and add
your VPN profile on your device. This process will vary greatly from device to
device.

On most Linux distros/DEs, for example, you would go to your network manager,
and select "Configure VPN..." or something like that. Then, a window with a list
of (VPN) connections will appear, and you should be able to add your profile by
clicking on the plus (+) button. After another window like this should pop up

![VPN dialog](vpndialog.png)

You should select the option that says "Import a saved VPN configuration..."

Note that the "openvpn" and "networkmanager-openvpn" packages should be
installed in your (client) system.

Once you have connected to your VPN, you can head over to
[https://dnsleaktest.com/](https://dnsleaktest.com/) to check your connectivity.

Now you can more safely and securely browse the interwebz, and be sure that no
third-party VPN company is logging your activity.