# Intro to OpenVPN --- ## VPNs what are they good for VPNs allow you to connect to a system --- ## Assumptions + OpenWRT is running on the server + You have SSH access to the machine running OpenWRT + The OpenWRT server is set to give out ips on its lan (i.e. on the 192.168../16 private address block). --- ## Creating Certificates First, let's create the certificates which the server and the clients will uses to authenticate one another. This step will **not** be done on the server so as to not have to load extra software on the server, to keep private keys off the server, and to speed up the proccess of generating the Diffie-Hellman key. --- ### Install Certificate software ```bash= sudo dnf update # Use `apt` or 'opkg' update your box as nessesary sudo dnf install easy-rsa openvpn ``` ---- > I built this on Fedora so you will see the `dnf` command allot if you have `apt` installed or another package manager, use that. --- ### Create CA Certificate We will now setup the directory where easy-rsa will place its files when building the certificates and keys. ```bash= mkdir vpn-keys-certs cd vpn-keys-certs ./easyrsa clean-all ./easyrsa build-ca nopass ``` ---- > **Security** if you need an extra layer of security on top of the *Diffie-Hellman key* and *control list* then ommit `nopass` from the `build-ca` line and the `gen-req` lines to follow. --- #### Generate Diffie-Hellman Key This key will be our fist line of defense. ```bash= ./easyrsa gen-dh # creates file dh.pem ./easyrsa gen-crl # creates file crl.pem ``` --- #### Generate Server Certificates Next we create keys and certificats for the server and a few clients, Luke and Leia. Neither will have passwords assocciated with their keys. ```bash= ./easyrsa gen-req <NAMEOFCert> nopass # Creates the .key file ./easyrsa sign-req server <NAMEOFCert> # Creates the .crt file ``` --- #### Gernerating Client Certificates ```bash= # Create the certs and keys for leia ./easyrsa gen-req <NameOfClientA> nopass ./easyrsa sign-req client <NameOfClientA> # Create the Certs and keys for luke ./easyrsa gen-req <NameOfClientB> nopass ./easyrsa sign-req client <NameOfClientB> ``` --- #### Verifing Certificats Certificates can be verified using: ```bash= openssl verify -CAfile /path/to/ca.crt path/to/certificate.crt` ``` ---- #### Revoking a Certificate If a client certificate has been compermised and needs revoked so that the server will reject all attemps to it conneting we will update the `crl.pem` file. ```bash= ./easyrsa revoke <NameOfClientToBeRevoked> ./easyrsa gen-crl ``` Thats it!!! Now just copy the new `crl.pem` file to the server and restart the system. Luke will nolonger be able to connect with the `luke.key` ---- #### TODO: + [ ] Create and revoke a certificate with duplicate names + [ ] Place the `vpn-keys-certs` in a git repository. See the [Going Futher](https://blog.assortedsolutions.com/2020/01/12/Become-A-Certificate-Authority-with-Easy-RSA/index.html) section at the bottom of the "Assorted Solutions" blog page. --- ### The TLS authority This key will be a shared secret used to verify the integrity of any UDP packet sent to the server. If a packet does not contain the HMAC signiture of the shared key the packet will be dropped emidiatly. Thus protecting againset DoS attacks, Port scanning, Buffer overflow and thus requires a machine to have both a valid `.crt`, and two `.key`s. The [Hardening OpenVPN Security](https://openvpn.net/community-resources/hardening-openvpn-security/) goes into a little more detail but here is the basics. --- #### Generate the TLS key ```bash= openvpn --genkey --secret ta.key ``` --- ## Get the Server going --- `ssh` into the router as root then: ```bash= opkg update opkg install openvpn ``` Make sure that there is a place to store the keys ```bash= mkdir /etc/openvpn/keys ``` --- Move the following keys to the server: + pki/ca.crt + pki/ta.key + pki/issued/republic.crt + pki/private/republic.key + pki/dh.pem + pki/crl.pem --- Exit the `ssh` session and distribute the keys located in the `pki/` folder ```bash= scp ca.crt ta.key issued/republic.crt private/republic.key dh.pem crl.pem root@openwrt.server.lan:/etc/openvpn/keys ``` --- ## Moving Keys to Client Each client will get a set of certs. and keys + pki/ca.crt + pki/ta.key + pki/issued/personal.crt + pki/private/personal.key Send these keys to their respective client's. NOTE: all four keys can live in the same folder. ---- Leia get's: + pki/ca.crt + pki/ta.key + pki/issued/leia.crt + pki/private/leia.key And Luke get's: + pki/ca.crt + pki/ta.key + pki/issued/luke.crt + pki/private/luke.key --- ## Server configuration file Now that we have the keys, certificates and control list files on the server lets setup the configuration file. ```bash= ssh root@openwrt.server.lan touch /etc/config/openvpn.conf nano /etc/config/openvpn.conf ``` --- Paste in the following code taken from the OpenVPN sample config. :::info ```bash= port 1194 proto udp dev tun ca /etc/openvpn/keys/ca.crt cert /etc/openvpn/keys/republic.crt key /etc/openvpn/keys/republic.key dh /etc/openvpn/keys/dh.pem tls-auth /etc/openvpn/keys/ta.key 0 server 10.8.0.0 255.255.255.0 # The 10.8.0.0 my be chaned to any 10... domain such as 10.88.0.0 route 192.168.20.0 255.255.255.0 # The 192.168.20.0 should match the ip domain of your server push "route 192.168.20.0 255.255.255.0" # Should also match the above line. push "dhcp-option DNS 192.168.20.1" topology subnet ifconfig-pool-persist ipp.txt keepalive 10 120 user nobody persist-key persist-tun status openvpn-status.log verb 3 explicit-exit-notify 1 ::: ``` ---- > NOTE: you will need to change the following lines to point to your certificates and keys > ```bash= > ca /etc/openvpn/keys/ca.crt > cert /etc/openvpn/keys/republic.crt > key /etc/openvpn/keys/republic.key > dh /etc/openvpn/keys/dh.pem > tls-auth /etc/openvpn/keys/ta.key 0 >``` --- ## Client Configuration File Lets get back to the Client computer and get them set up to connect. The client configuration looks pretty similar to the server. --- Create a file named `client.conf` on your system and paste the following code. :::info ```bash= # Client Configuration file client auth-nocache dev tun proto udp remote 192.168.124.201 1194 resolv-retry infinite nobind user nobody group nobody persist-key persist-tun mute-replay-warnings ca /home/cde/.vpn/erghos/ca.crt cert /home/cde/.vpn/erghos/erghos.crt key /home/cde/.vpn/erghos/erghos.key remote-cert-tls server tls-auth /home/cde/.vpn/erghos/ta.key 1 cipher BF-CBC verb 3 mute 20 ::: ``` ---- You will again need to change the following lines ```bash= ca /home/cde/.vpn/erghos/ca.crt cert /home/cde/.vpn/erghos/erghos.crt key /home/cde/.vpn/erghos/erghos.key ... tls-auth /home/cde/.vpn/erghos/ta.key 1 ``` To point to the location on your system. --- ## OpenWRT setup Let's get back to the OpenWRT server and finish up the confirmation by `ssh`ing into the server. --- Earlier we created the `openvpn.conf` in the `/etc/config/` directory now we will link to it in the `/etc/config/openvpn` file. ```bash= nano /etc/config/openvpn ``` --- Now we will add the lines so that `openvpn` knows to use our custom configuration file. :::info ```bash= config openvpn myvpn option enabled 1 option config /etc/config/openvpn.conf ``` ::: --- Now lets restart the service ```bash= service openvpn restart ``` --- ### The Interface We will handle the rest of the setup through the LuCI web GUI on OpenWRT. ---- #### TODO: Add screen shots to this section. --- 1. Goto `Networking` 2. -> `Interfaces` 3. Click `Add new interface...` :::info Name: VPN Protocol: Unmanaged Interface Ethernet Adapter: "tun0" (VPN) ::: **Save & Apply** --- ### The Firewall settings #### The Zone 1. Goto `Networking` 2. -> `Firewall` 4. Click `Add` --- :::info Name: vpn Input: accept Output: accept Forward: reject Coverd networks: VPN ::: **Save & Apply** --- #### The Traffic Rules 1. Goto `Network` 2. -> `Firewall` 3. -> `Traffic Rules` --- **Add** :::info Name: Allow-OpenVPN Protocol: UDP Source zone: WAN Source port: 1194 Destination zone: Device (input) Destination port: 1194 ::: **Save** ---- If you want your server to only accept vpn connections and ignore all other requests to all the other ports remove the `Source port: 1194` from the `Allow-OpenVPN` Firewall Traffic Rules. --- **Add** :::info Name: VPN->LAN Source: VPN Destination: LAN ::: **Save** --- **Add** :::info Name: LAN->VPN Source: LAN Destination: VPN ::: **Save** **Save & Apply** You should now be able to connect to the VPN from a client's machine. --- ## CLI VPN connection On the client machine: ```bash= sudo openvpn /path/to/config.conf ``` --- If successful you should see out put similar to: ```bash= [sudo] password for user: Mon Feb 1 10:55:27 2021 OpenVPN 2.4.10 x86_64-redhat-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Dec 9 2020 Mon Feb 1 10:55:27 2021 library versions: OpenSSL 1.1.1i FIPS 8 Dec 2020, LZO 2.10 ... Mon Feb 1 11:08:57 2021 /sbin/ip route add 192.168.22.0/24 via 10.88.0.1 Mon Feb 1 11:08:57 2021 GID set to nobody Mon Feb 1 11:08:57 2021 UID set to nobody Mon Feb 1 11:08:57 2021 Initialization Sequence Completed ``` --- ### Verifing connection You can now open up a second terminal and try and ping one of the machines or the server through the internal 192.168.. network ```bash= ping 192.168.20.1 PING 192.168.22.1 (192.168.22.1) 56(84) bytes of data. 64 bytes from 192.168.22.1: icmp_seq=1 ttl=64 time=3.04 ms 64 bytes from 192.168.22.1: icmp_seq=2 ttl=64 time=2.71 ms 64 bytes from 192.168.22.1: icmp_seq=3 ttl=64 time=3.17 ms ^C --- 192.168.22.1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2003ms rtt min/avg/max/mdev = 2.705/2.970/3.169/0.195 ms ``` --- ## Troubleshooting --- #### Cannot ioctl TUNSETIFF tun **Problem:** If you get `ERROR: Cannot ioctl TUNSETIFF tun: Operation not permitted (errno=1)` when running `openvpn /dir/to/client.conf` **Solution:** Run as admin i.e. `sudo openvpn /dir/containing/client.conf` --- #### SSH connection/tunnel freezes **Problem:** If after starting the openvpn server.conf your SSH connection is lost you may be able to connect using openvpn. **Solution:** Check to see if you can `ping 192.168.2.1` or the ip of your router. If so use a internet browser to open the OpenWRT LuCI interface and goto the `Firewall` setting --- #### GUI Fails to connect **Problem:** On linux with SELinux I found that the GUI interface was having problems accessing the key files and was giving the error: ` AVC avc: denied { open } for pid=9040 comm="openvpn" path="/home/cde/...` **Solution:** After some searching I found a stackover flow post with the solution. ```bash= sudo chcon -t home_cert_t ~/path/to/keys/* ``` --- #### Can't find a machine using it's name **Problem:** I can open a web browser and type in 192.168.2.1 and get the LuCI interface but typing is't name i.e. http://mindover.lan does not work. **Solution:** NoKnown current soulint to this problem and it seems to be seratic. --- ## Links [OpenVPN Server on an OpenWrt Router](https://blog.assortedsolutions.com/2020/01/13/OpenVPN-Server-on-an-OpenWrt-Router/) [Become A Certificate Authority with Easy-RSA 3](https://blog.assortedsolutions.com/2020/01/12/Become-A-Certificate-Authority-with-Easy-RSA/index.html) [2x HOW TO](https://openvpn.net/community-resources/how-to/#creating-configuration-files-for-server-and-clients) [Hardening OpenVPN Security](https://openvpn.net/community-resources/hardening-openvpn-security/) [OpenVPN Community Wiki and Tracker](https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage) [OpenVPN Client Configuration file](https://github.com/OpenVPN/openvpn/blob/master/sample/sample-config-files/client.conf) [OpenVPN Server Configuration File](https://github.com/OpenVPN/openvpn/blob/master/sample/sample-config-files/server.conf)