DistributionsThis guide is tested for Debian 9 Stretch Linux, but it may work with other recent Debian versions.
- This guide assumes that you're running Debian on a VPS or a remote server, since that's the most likely scenario for a VPN.
- A working install of Debian Stretch with root access
- # - requires given command to be executed with root privileges either directly as a root user or by use of
- $ - given command to be executed as a regular non-privileged user
Configuring IptablesSetting up your own VPN is no small task, but there are plenty of reasons that you'd want to do it. For one, when you run your own VPN, you have complete control of it and know exactly what it's doing.
Security is an important factor for VPNs. It's possible to set up a simple one in a few minutes, but it won't be secure at all. You need to take the appropriate steps to ensure that both the server and your connections remain private and encrypted.
Before embarking down this road, you may want to consider encrypting your disks, beefing up kernel security with SELinux or PAX, and making sure everything else is locked down.
Iptables is a big part of server security. You need iptables to ensure that information doesn't leak out of your VPN. Iptables also works to prevent unauthorized connections. So, the first step in setting up a VPN on Debian is setting up iptables.
Find Your WAN InterfaceBefore you can start writing your iptables rules, you need to know which interface you're writing them for.
ip ato search for the interface that your server is connected to the Internet with.
The rest of this guide will refer to that interface as
eth0, but that probably won't be yours. Make sure to swap in the name of your server's network interface instead.
Creating The Iptables RulesEvery Linux user and admin loves writing iptables rules, right? It's not going to be that bad. You'll compose a file with all of the commands and just restore it into iptables.
Create your file. You can make it somewhere that you want to save or just dump it in
/tmp. Iptables will save your rules anyway, so
$ vim /tmp/v4rulesStart the file off by adding
*filterto let iptables know that these are filter rules.
Yes, there will be an IPv6 one too, but it'll be much shorter.
Loopback RulesStart off with the simplest set of rules, the loopback interface ones. These just tell iptables to only accept looback traffic originating from localhost.
-A INPUT -i lo -j ACCEPT -A INPUT ! -i lo -s 127.0.0.0/8 -j REJECT -A OUTPUT -o lo -j ACCEPT
Allowing PingNext, you probably want to be able to ping your server. This group of rules allows ping through.
-A INPUT -p icmp -m state --state NEW --icmp-type 8 -j ACCEPT -A INPUT -p icmp -m state --state ESTABLISHED,RELATED -j ACCEPT -A OUTPUT -p icmp -j ACCEPT
SSH SetupYou should probably change SSH off of port 22, so let your rules reflect that.
-A INPUT -i eth0 -p tcp -m state --state NEW,ESTABLISHED --dport 22 -j ACCEPT -A OUTPUT -o eth0 -p tcp -m state --state ESTABLISHED --sport 22 -j ACCEPT
Allow OpenVPN ThroughObviously, you're going to want to allow OpenVPN traffic through. This guide is going to use UDP for OpenVPN. If you choose to go with TCP, let the rules reflect that.
-A INPUT -i eth0 -p udp -m state --state NEW,ESTABLISHED --dport 1194 -j ACCEPT -A OUTPUT -o eth0 -p udp -m state --state ESTABLISHED --sport 1194 -j ACCEPT
DNSYou're also going to want to allow DNS traffic through your VPN server. This will be through both UDP and TCP.
-A INPUT -i eth0 -p udp -m state --state ESTABLISHED --sport 53 -j ACCEPT -A OUTPUT -o eth0 -p udp -m state --state NEW,ESTABLISHED --dport 53 -j ACCEPT -A INPUT -i eth0 -p tcp -m state --state ESTABLISHED --sport 53 -j ACCEPT -A OUTPUT -o eth0 -p tcp -m state --state NEW,ESTABLISHED --dport 53 -j ACCEPT
HTTP/S For UpdatesIt might seem odd to allow HTTP/S traffic, but you do want Debian to be able to update itself, right? These rules allow Debian to initiate HTTP requests, but not receive them from the outside.
-A INPUT -i eth0 -p tcp -m state --state ESTABLISHED --sport 80 -j ACCEPT -A INPUT -i eth0 -p tcp -m state --state ESTABLISHED --sport 443 -j ACCEPT -A OUTPUT -o eth0 -p tcp -m state --state NEW,ESTABLISHED --dport 80 -j ACCEPT -A OUTPUT -o eth0 -p tcp -m state --state NEW,ESTABLISHED --dport 443 -j ACCEPT
NTP To Sync Your ClockAssuming that you're not going to manually synchronize your server clock and the client clocks, you're going to need NTP. Allow it too.
-A INPUT -i eth0 -p udp -m state --state ESTABLISHED --sport 123 -j ACCEPT -A OUTPUT -o eth0 -p udp -m state --state NEW,ESTABLISHED --dport 123 -j ACCEPT
TUN To Tunnel Through The VPNThis guide uses TUN to tunnel through the VPN, if you're using TAP, adjust accordingly.
-A INPUT -i tun0 -j ACCEPT -A FORWARD -i tun0 -j ACCEPT -A OUTPUT -o tun0 -j ACCEPTFor the VPN to forward your traffic to the Internet, you need to enable forwarding from TUN to your physical network interface.
-A FORWARD -i tun0 -o eth0 -s 10.8.0.0/24 -j ACCEPT -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
Log Blocked TrafficYou should probably have iptables log the traffic that it blocks. This way, you are aware of any potential threats.
-A INPUT -m limit --limit 3/min -j LOG --log-prefix "iptables_INPUT_denied: " --log-level 4 -A FORWARD -m limit --limit 3/min -j LOG --log-prefix "iptables_FORWARD_denied: " --log-level 4 -A OUTPUT -m limit --limit 3/min -j LOG --log-prefix "iptables_OUTPUT_denied: " --log-level 4
Reject All Other TrafficNow that you're logging everything that doesn't fit into the existing rules, reject it.
-A INPUT -j REJECT -A FORWARD -j REJECT -A OUTPUT -j REJECTDon't forget to close out your file with
NATThis next part requires a different table. You can't add it to the same file, so you'll just have to run the command manually.
Make traffic from the VPN masquerade as traffic from the physical network interface.
# iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
Block All IPv6 TrafficTraffic can leak out over IPv6, and there really isn't any need to use IPv6 right now. The easiest thing to do is to shut it down entirely. Create another file and throw in the rules to reject all IPv6 traffic.
*filter -A INPUT -j REJECT -A FORWARD -j REJECT -A OUTPUT -j REJECT COMMIT
Commit EverythingStart off by flushing out all existing iptables rules.
# iptables -F && iptables -XImport each of the rules files that you created.
# iptables-restore < /tmp/v4rules # ip6tables-restore < /tmp/v6rules
Making It StickDebian has a package that will handle automatically loading your iptable rules, so you don't have to create a cron job or anything like that.
# apt install iptables-persistentThe installation process will ask you if you want to save your configurations. Answer, "Yes."
In the future, you can update your rules by running the following command.
# service netfilter-persistent save
Additional ConfigurationThere are a couple more things that you need to do in order to get all of your network interfaces working as needed.
First, open up
/etc/hostsand comment out all of the IPv6 lines.
/etc/sysctl.d/99-sysctl.conf. Find and uncomment the following line.
net.ipv4.ip_forward=1Add these next lines to disable IPv6 completely.
net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 net.ipv6.conf.lo.disable_ipv6 = 1 net.ipv6.conf.eth0.disable_ipv6 = 1Finally, apply your changes.
# sysctl -p
What's NextThat's the first part down. Your server's firewall is now ready to run OpenVPN, and your networking is all aligned properly too. The next step is to create a certificate authority to handle all of your encryption keys. It's not lengthy a process as this was, but it's just as important.
Certification AuthorityUse Easy-RSA to establish the certificate authority that you'll use to create and the encryption keys for your OpenVPN server. This is the second part in configuring an OpenVPN server on Debian Stretch.
VPNs rely on encryption. It's absolutely vital that they encrypt their connections with clients as well as the connection process itself.
In order to generate the keys necessary for encrypted communication, you need to establish a certificate authority. It's really not that difficult, and there are tools that simplify the process further.
Installing the PackagesBefore you get started, install OpenVPN and Easy-RSA.
# apt install openvpn easy-rsa
Set Up The DirectoryThe OpenVPN package created a directory for itself at
/etc/openvpn. That's where you can set up the certificate authority. Easy-RSA includes a script that automatically creates a directory with everything that you need. Use it to create your certificate authority directory.
# make-cadir /etc/openvpn/certsEnter that directory and create a soft link between the latest OpenSSL config with
# ln -s openssl-1.0.0.cnf openssl.cnf
Set The VariablesInside the folder is a file called,
vars. That file contains the variables that Easy-RSA will use to generate your keys. Open it up. There are a few values that you need to change. Start by finding the
KEY_SIZEvariable and change it's value to
export KEY_SIZE=4096Next, find a block of information concerning the location and identity of your certificate authority.
export KEY_NAME="VPNServer"Name it something identifiable.
Create The Authority KeysEasy-RSA includes scripts to generate the certificate authority. Load the variables first.
# source ./varsA warning message will pop up in the terminal telling you that
clean-allwill erase your keys. You don't have any yet, so it's alright.
# ./clean-allYou can now run the script to actually generate your certificate authority. The script will ask you questions about the keys that you're generating. The default answers will be the variables that you already entered. You can safely smash "Enter." Just remember to enter a password if you want to and answer "Yes" to the last two questions.
Create A Server KeyThose keys that you made were for the certificate authority itself. You need a key for the server too. Yet again, there's a script for that.
# ./build-key-server server
Generate a Diffie-Hellman PEMYou need to generate a Diffie-Hellman PEM which OpenVPN will use to create secure client sessions keys. Easy-RSA provides a script for this too, but it's just easier to use plain OpenSSL. Since the goal here is security, it's best to generate a 4096bit key. It's going to take some time to generate, and it might slow down the connection process a bit, but the encryption will be reasonably strong.
# openssl dhparam 4096 > /etc/openvpn/dh4096.pem
Generate An HMAC KeyYeah, you need another encryption key. OpenVPN uses HMAC keys to sign the packets it uses in the TLS authentication process. By signing those packets, OpenVPN can guarantee that only packets originating from a machine with the key are accepted. It just adds another layer of security. The utility for generating your HMAC key is actually built into OpenVPN itself. Run it.
# openvpn --genkey --secret /etc/openvpn/certs/keys/ta.key
What's NextCreating strong encryption is easily one of the most important aspects of setting up an OpenVPN server. Without good encryption, the whole process is basically meaningless. By this point, you're finally ready to configure the server itself. The server configuration is actually less complicated than what you've done so far, so congratulations.
OpenVPN SeverConfigure the OpenVPN server using the encryption keys that you generated in the previous section of the guide. This is the third part in configuring an OpenVPN server on Debian Stretch.
Now, you've arrived at the main event. This is the actual OpenVPN server configuration. Everything that you've done so far was absolutely necessary, but none of it has touched OpenVPN itself, until now.
This section is entirely concerned with configuring and running the OpenVPN server, and it's actually less complicated than you're probably thinking.
Get The Base ConfigOpenVPN has made this process very easy. The package that you installed came with sample configuration files for both clients and the server. You just need to unzip the server one into you
# gunzip -c /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz > /etc/openvpn/server.confOpen it in your favorite text editor and get ready to start changing things.
Use Your KeysOnce you're inside the file, you'll see that everything is filled out with reasonable defaults, and there are loads of comments that provide excellent documentation of what everything does. The first thing that you need to find is the section to add your certificate authority and server keys. The variables are
key. Set them equal to the full path of each of those files. It should look like the example below.
ca /etc/openvpn/cert-auth/keys/ca.crt cert /etc/openvpn/cert-auth/keys/server.crt key /etc/openvpn/cert-auth/keys/server.key # This file should be kept secretThe next part that you need to find is the Diffie-Hellman
.pemWhen you're done, it should look like this:
dh dh4096.pemFinally, find
tls-authfor your HMAC key.
tls-auth /etc/openvpn/cert-auth/keys/ta.key 0 # This file is secretYes, leave the
Beef Up SecurityThe encryption settings in the configuration file are alright, but they could be much better. It's time to enable better encryption settings.
Find the section that begins with,
# Select a cryptographic cipher.That's where you need to add the following line below he existing commented options.
cipher AES-256-CBCIt's not one of the listed options there, but it is supported by OpenVPN. That 256bit AES encryption is probably the best one offered by OpenVPN.
Scroll to the end of the file. The next two options aren't already in the configuration, so you need to add them.
First, you need to specify a strong authentication digest. This is the encryption that OpenVPN will use for user authentication. Choose SHA512.
# Auth Digest auth SHA512Next, limit the ciphers that OpenVPN will use to stronger ones. It's best to limit it as far as reasonably possible.
# Limit Ciphers tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA:TLS-DHE-RSA-WITH-AES-128-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA
Direct TrafficAll of the encryption stuff is out of the way. It's time to do some routing. You need to tell OpenVPN to handle redirecting traffic and DNS.
Start by redirecting traffic. Find the line below and uncomment it.
push "redirect-gateway def1 bypass-dhcp"In order to route DNS through OpenVPN, you need to give it DNS options. These lines are already there and commented too. Uncomment them. If you want to use a different DNS server, you can change the IP to that DNS too.
push "dhcp-option DNS 22.214.171.124" push "dhcp-option DNS 126.96.36.199"
Set Up An OpenVPN UserOpenVPN runs as root by default. That's a pretty terrible idea. If OpenVPN is compromised, the whole system's screwed. There are a couple of commented lines to run OpenVPN as "nobody," but "nobody" is usually running other services too. If you don't want OpenVPN to have access to anything but OpenVPN, you need to run it as its own unprivileged user.
Create a system user for OpenVPN to run as.
# adduser --system --shell /usr/sbin/nologin --no-create-home openvpnThen, you can edit the configuration file by uncommenting the lines that run OpenVPN as "nobody," and replace it with the user name that you just made.
user openvpn group nogroup
Send Logs To NullThere are two options when it comes to logs, and they both have their merits. You can log everything as normal and have the logs to loop back on at a later date, or you can be paranoid and log to
By logging to
/dev/null, you're erasing any record of the clients that connect to the VPN and where they go. Even though you control your VPN, you may want to go this route if you're trying to be more privacy-minded.
If you want to destroy your logs, find the
log-appendvariables and point them all at
/dev/null. It should look similar to the example below.
status /dev/null … log /dev/null log-append /dev/nullThat's the last part of the configuration. Save it, and get ready to run your server.
Run Your ServerThere are actually two services that you need to start to spin up OpenVPN on Debian Stretch. Start them both up with systemd.
# systemctl start openvpn # systemctl start openvpn@serverVerify that they're running properly.
# systemctl status openvpn*.serviceEnable them both to run at startup.
# systemctl enable openvpn # systemctl enable openvpn@serverYou now have a running VPN server on Debian Stretch!
What's nextYou're here. You've done it! Debian is now running OpenVPN behind a secure firewall, and it's ready for clients to connect. In the next section, you'll set up your first client and connect it to your server.
OpenVPN ClientConfigure and OpenVPN client to connect to the newly configured OpenVPN server. This is the fourth and final part in configuring an OpenVPN server on Debian Stretch.
Now that your server is running, you can set up a client to connect to it. That client can be any device that supports OpenVPN, which is nearly anything. There are somethings that you need to do on the server first to hand off to the client, but after that, it's all about setting up that connection.
Create Client KeysStart off by making a set of client keys. The process is almost identical to the one you used to make the server keys.
cdinto the certificate authority directory, set the source from the variables file and build the keys.
# cd /etc/openvpn/certs # source ./vars # ./build-key firstclientYou can name the client key whatever you choose. Again, the script will ask you a series of questions. The defaults should be good for everything.
Client Configuration FileOpenVPN provides example client configurations in addition to the server ones. Crate a new directory for your client configuration and copy the example in.
# mkdir /etc/openvpn/clients # cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/clients/client.ovpnOpen the file in your text editor of choice.
Remote HostFind the line with the
remotevariable. Set it equal to your server's IP.
remote 192.168.1.5 1194
Become NobodyThere's no training with the Faceless Men required. Just find an uncomment the lines below.
user nobody group nogroup
Set Up Your KeysYou have to tell the client configuration where to find the keys that it needs too. Find the following lines and edit them to match what you've set up.
ca ca.crt cert firstclient.crt key firstclient.keyMake sure to use the actual names of the client cert and key. The path is fine. You'll be putting it all in the same directory. Find and uncomment the line for HMAC.
tls-auth ta.key 1
Specify EncryptionThe client needs to know what encryption the server is using. Just like the server, a couple of these lines need to be added in. Find the
ciphervariable. It's commented. Uncomment it and add in the cipher that you used on the server.
cipher AES-256-CBCAdd in the authentication digest and the cipher restrictions at the end of the client configuration.
# Authentication Digest auth SHA512 # Cipher Restrictions tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA:TLS-DHE-RSA-WITH-AES-128-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHASave your configuration and exit.
Send The Client A TarballYou have to pack up your client configuration and keys in a tarball and send them to the client. Load everything into one tarball to simplify things on the client end.
# tar cJf /etc/openvpn/clients/firstclient.tar.xz -C /etc/openvpn/certs/keys ca.crt firstclient.crt firstclient.key ta.key -C /etc/openvpn/clients/client.ovpnNow, you can transfer that tarball to your client however you choose.
ConnectAssuming that your client is a Debian distribution, the connection process is very simple. Install OpenVPN like you did on the server.
# apt install openvpnExtract your tarball into the
/etc/openvpndirectory that the installation created.
# cd /etc/openvpn # tar xJf /path/to/firstclient.tar.xzYou may need to rename
openvpn.conf. You'll get an error on startup if you do. Start and enable OpenVPN with systemd.
# systemctl start openvpn # systemctl enable openvpn
ConclusionYou have a working VPN server and a connected client! You can follow the same procedure detailed in this guide for your other clients too. Make sure to create separate keys for each one. You can use the same config file, though.
You also might want to make sure that everything is working properly. Head over to DNS Leak Test to make sure that your IP patches the server, and you're not using your IPS's DNS.