diff --git a/README.md b/README.md
index eccb708..943d998 100644
--- a/README.md
+++ b/README.md
@@ -1,30 +1,25 @@
-# OpenVPN-install
+# openvpn-install
-OpenVPN installer for Debian, Ubuntu, Fedora, CentOS and Arch Linux.
+OpenVPN installer for Debian, Ubuntu, Fedora and CentOS.
This script will let you setup your own secure VPN server in just a few minutes.
-Here is a preview of the installer :
-
-
-
-
## Usage
-**You have to enable the TUN module otherwise OpenVPN won't work.** Ask your host if you don't know how to do it. If the TUN module is not enabled, the script will warn you and exit.
-
-You can get a cheap VPS to run this script for $3.50/month worldwide at [Vultr](https://goo.gl/Xyd1Sc) or 3€/month for unlimited bandwidth in France at [PulseHeberg](https://goo.gl/76yqW5).
-
First, get the script and make it executable :
```bash
-wget https://raw.githubusercontent.com/Angristan/OpenVPN-install/master/openvpn-install.sh
+wget https://raw.githubusercontent.com/Angristan/openvpn-install/master/openvpn-install.sh
chmod +x openvpn-install.sh
```
Then run it :
-`./openvpn-install.sh`
+```sh
+./openvpn-install.sh
+```
+
+You need to run the script as root and have the TUN module enabled.
The first time you run it, you'll have to follow the assistant and answer a few questions to setup your VPN server.
@@ -34,81 +29,81 @@ When OpenVPN is installed, you can run the script again, and you will get the ch
- Remove a client
- Uninstall OpenVPN
-
-
-## The fork
-
-This script is based on the great work of [Nyr and its contributors](https://github.com/Nyr/openvpn-install).
-
-I made it because I wanted to have a more secured OpenVPN out-of-the-box. It works like the original script, but is more focused on privacy and especially better encryption. Nyr's original script uses mainly default parameters regarding encryption, and some of them are insecure. See [#encryption](#encryption).
-
-Also, Nyr and myself clearly have not the same point of view regarding this script, that's why it's a fork.
-
-The only drawback is that you need to use a recent version of OpenVPN, because some parameters that requires TLS 1.2 are only available since OpenVPN 2.3.3. Therefore I restrain the compatibility of this script to a few but widely used GNU/Linux distributions, to get a recent version of OpenVPN from trusted third-party repositories, if needed. That is not a complete drawback tough, because it means that you can have the latest version with all the new features and security fixes. See [compatibility](#compatibility).
-
-On the client-side, it's less problematic, but if you want to use an OpenVPN server installed with this script with an old client (\<2.3.3), it won't work. However I don't see why you would use an outdated client.
-
-**TL;DR**, this script is relatively secure, and you can just press enter in the setup.
-
-**[A Pull Request](https://github.com/Angristan/OpenVPN-install/pull/96) is currently being worked on to implement the latest OpenVPN 2.4 features.**
-
-## Compatibility
-
-The script is made to work on these OS and architectures :
-
-- **Debian 7** (i386, amd64)
-- **Debian 8** (i386, amd64)
-- **Debian 9** (i386, amd64, armhf, arm64)
-- **Ubuntu 14.04 LTS** (i386, amd64)
-- **Ubuntu 16.04 LTS** (i386, amd64, armhf)
-- **Ubuntu 17.10** (i386, amd64, armhf, arm64)
-- **Ubuntu 18.04 LTS** (i386, amd64, armhf, arm64)
-- **Fedora 25** (amd64)
-- **Fedora 26** (amd64)
-- **Fedora 27** (amd64)
-- **CentOS 6** (i386, amd64)
-- **CentOS 7** (i386, amd64, arm64)
-- **Arch Linux** (i686, amd64, arm64)
-
-(It should also work on Debian unstable/testing and Ubuntu beta).
-
-If your're using an Ubuntu version that is not supported by the script, be aware that it's not supported by Ubuntu either, thus it's insecure.
+In your home directory, you will have `.ovpn` files. These are the client configuration files. Download them from your server and connect using your prefered OpenVPN client.
## Features
-This fork includes the following features :
+- Installs and configures a ready-to-use OpenVPN server
+- Iptables rules and forwarding managed in a seamless way
+- If needed, the script can cleanly remove OpenVPN, including configuration and iptables rules
+- Customizable encryption settings, enhanced default settings
+- Varitey of DNS resolvers to be pushed to the clients
+- Choice to use a self-hosted resolver with Unbound (supports already existing Unboud installations)
+- Choice between TCP and UDP
+- NATed IPv6 support
+- Compression disabled to prevent VORACLE
+- Unprivileged mode: run as `nobody`/`nogroup`
+- Block DNS leaks on Windows 10
+- Randomized server certificate name
+- Choice to protect clients with a password (private key encryption)
+- Many other little things!
-- Every feature of the [original script](https://github.com/Nyr/openvpn-install)
-- Better encryption, see below
-- Better DNS resolvers, see below
-- Choice between TCP and UDP (UDP is still recommended)
-- Run server in [unprivileged mode](https://github.com/Angristan/OpenVPN-install/blob/master/openvpn-install.sh#L426), reducing risks to the system
-- [Block DNS leak on Windows 10](https://community.openvpn.net/openvpn/ticket/605)
-- No comp-lzo, as [compression is a vector for oracle attacks, e.g. CRIME or BREACH](https://github.com/BetterCrypto/Applied-Crypto-Hardening/pull/91#issuecomment-75388575)
-- [Arch Linux support](https://github.com/Angristan/OpenVPN-install/pull/2)
-- Up-to-date OpenVPN thanks to [EPEL](http://fedoraproject.org/wiki/EPEL) for CentOS and [swupdate.openvpn.net](https://community.openvpn.net/openvpn/wiki/OpenvpnSoftwareRepos) for Ubuntu and Debian. These are third-party yet trusted repositories.
-- Randomized certificate name
-- The ability to create passwordless clients and clients protected with a password
-- Other improvements !
+## Compatibility
-## DNS
+The script supports these OS and architectures:
-The script will ask you which DNS resolvers you want to use when connected to the VPN.
+- **Debian 8** (i386, amd64)
+- **Debian 9** (i386, amd64, armhf, arm64)
+- **Ubuntu 16.04 LTS** (i386, amd64, armhf)
+- **Ubuntu 17.10** (i386, amd64, armhf, arm64)
+- **Ubuntu 18.04 LTS** (i386, amd64, armhf, arm64)
+- **Fedora 27** (amd64)
+- **Fedora 28** (amd64)
+- **CentOS 7** (i386, amd64, arm64)
-Here are the possibilities :
+To be noted:
-- Current system resolvers, those that are in `/etc/resolv.conf`
-- [Cloudflare](https://1.1.1.1/), recommended, fastest resolvers available (Anycast servers)
-- [Quad9](https://www.quad9.net), recommended, security and privacy oriented, fast worldwide (Anycast servers)
-- [FDN's DNS Servers](http://www.fdn.fr/actions/dns/), recommended if you're in western europe (France)
-- [DNS.WATCH DNS Servers](https://dns.watch/index), recommended if you're in western europe (Germany)
-- [OpenDNS](https://en.wikipedia.org/wiki/OpenDNS), not recommened but fast wordlwide (Anycast servers)
-- [Google Public DNS](https://en.wikipedia.org/wiki/Google_Public_DNS), not recommended, but fast worldwide (Anycast servers)
-- [Yandex Basic DNS](https://dns.yandex.com/), not recommended, but fast in Russia
-- [AdGuard DNS](https://github.com/AdguardTeam/AdguardDNS), located in Russia, blocks ads and trackers
-- Soon : local resolver :D
+- It should also work on Debian unstable/testing and Ubuntu beta.
+- The script requires `systemd`.
+- The script is regularly tested against `amd64` only.
-Any other fast, trustable and neutral servers proposition is welcome.
+## Fork
+
+This script is based on the great work of [Nyr and its contributors](https://github.com/Nyr/openvpn-install).
+
+Since 2016, the two scripts have diverged and are not alike anymore, especially under the hood. The main goal of the script was enhanced security. But since then, the script has been completely rewritten and a lot a features have been added. The script is only comptaible with recent distributions though, so if you need to use a very old server or client, I advise using Nyr's script.
+
+## FAQ
+
+**Q:** Which provider do you recommend?
+
+**A:** I recommend these:
+
+- [Vultr](https://goo.gl/Xyd1Sc): Worldwide locations, IPv6 support, starting at $3.50/month
+- [PulseHeberg](https://goo.gl/76yqW5): France, unlimited bandwidth, starting at €3/month
+- [Digital Ocean](https://goo.gl/qXrNLK): Worldwide locations, IPv6 support, starting at $5/month
+
+---
+
+**Q:** The script has been udpated since I installed OpenVPN. How do I update?
+
+**A:** You can't. Managing updates and new features from the script would require way too much work. Your only solution is to uninstall OpenVPN and reinstall with the updated script.
+
+You can, of course, it's even recommended, update the `openvpn` package with your package manager.
+
+---
+
+**Q:** How do I check for DNS leaks?
+
+**A:** Go to [dnsleaktest.com](https://dnsleaktest.com/) or [ipleak.net](https://ipleak.net/) with your browser. Only your server's IP should show up.
+
+---
+
+**Q:** IPv6 is not working on my Hetzner VM
+
+**A:** This an issue on their side. See [issue #295](https://github.com/angristan/openvpn-install/issues/295).
+
+---
## Encryption
@@ -187,8 +182,6 @@ The [SWEET32 vulnerability page](https://community.openvpn.net/openvpn/wiki/SWEE
Indeed, AES is today's standard. It's the fastest and more secure cipher available today. [SEED](https://en.wikipedia.org/wiki/SEED) and [Camellia](https://en.wikipedia.org/wiki/Camellia_(cipher)) are not vulnerable to date but are slower than AES and relatively less trusted.
-As they have not any proven vulnerabilities, I decided to give the user the choice to use them, though I don't see any particular reason to this day to use it. Maybe someday if AES happens to be broken. Here is an example about [why Camellia is good, but AES is better and should be used](http://crypto.stackexchange.com/questions/476/why-does-nobody-use-or-break-the-camellia-cipher/477#477).
-
Currently AES is only available in its CBC mode, which is weaker than GCM.
To quote the [OpenVPN documentation](https://community.openvpn.net/openvpn/wiki/SWEET32) :
@@ -202,10 +195,6 @@ For now, these cipher are available in the setup :
- AES-128-CBC
- AES-192-CBC
- AES-256-CBC
-- CAMELLIA-128-CBC
-- CAMELLIA-192-CBC
-- CAMELLIA-256-CBC
-- SEED-CBC
AES-256 is 40% slower than AES-128, and there isn't any real reason to use a 256 bits key over a 128 bits key with AES. (Source : [[1]](http://security.stackexchange.com/questions/14068/why-most-people-use-256-bit-encryption-instead-of-128-bit),[[2]](http://security.stackexchange.com/questions/6141/amount-of-simple-operations-that-is-safely-out-of-reach-for-all-humanity/6149#6149)).
@@ -256,10 +245,6 @@ SHA-1 is not safe anymore, so I use SHA-256 which is safe and widely used.
TLS-Auth is not enabled by default by OpenVPN, but it is in this script.
-## Check for DNS leaks
-
-Go to [dnsleaktest.com](https://dnsleaktest.com/) or [ipleak.net](https://ipleak.net/) with your browser. Only your server's IP should show up.
-
## Say thanks
You can [say thanks](https://saythanks.io/to/Angristan) if you want!
diff --git a/openvpn-install.sh b/openvpn-install.sh
index 248ce34..ba4f620 100644
--- a/openvpn-install.sh
+++ b/openvpn-install.sh
@@ -1,266 +1,185 @@
#!/bin/bash
-# Secure OpenVPN server installer for Debian, Ubuntu, CentOS and Arch Linux
-# https://github.com/Angristan/OpenVPN-install
+# Secure OpenVPN server installer for Debian, Ubuntu, CentOS and Fedora
+# https://github.com/angristan/openvpn-install
-
-# Verify root
-if [[ "$EUID" -ne 0 ]]; then
- echo "Sorry, you need to run this as root"
- exit 1
-fi
-
-# Verify tun
-if [[ ! -e /dev/net/tun ]]; then
- echo "TUN is not available"
- exit 2
-fi
-
-# Check if CentOS 5
-if grep -qs "CentOS release 5" "/etc/redhat-release"; then
- echo "CentOS 5 is too old and not supported"
- exit 3
-fi
-
-if [[ -e /etc/debian_version ]]; then
- OS="debian"
- # Getting the version number, to verify that a recent version of OpenVPN is available
- source /etc/os-release
- IPTABLES='/etc/iptables/iptables.rules'
- SYSCTL='/etc/sysctl.conf'
- case "$VERSION_ID" in
- 7|8|9|14.04|16.04|17.10)
- :
- ;;
- *)
- echo "Your version of Debian/Ubuntu is not supported."
- echo "I can't install a recent version of OpenVPN on your system."
- echo ""
- echo "However, if you're using Debian unstable/testing, or Ubuntu beta,"
- echo "then you can continue, a recent version of OpenVPN is available on these."
- echo "Keep in mind they are not supported, though."
- while [[ $CONTINUE != "y" && $CONTINUE != "n" ]]; do
- read -rp "Continue ? [y/n]: " -e CONTINUE
- done
- if [[ "$CONTINUE" = "n" ]]; then
- echo "Ok, bye !"
- exit 4
- fi
- esac
- # fi
-elif [[ -e /etc/fedora-release ]]; then
- OS=fedora
- IPTABLES='/etc/iptables/iptables.rules'
- SYSCTL='/etc/sysctl.d/openvpn.conf'
-elif [[ -e /etc/centos-release || -e /etc/redhat-release || -e /etc/system-release ]]; then
- OS=centos
- IPTABLES='/etc/iptables/iptables.rules'
- SYSCTL='/etc/sysctl.conf'
-elif [[ -e /etc/arch-release ]]; then
- OS=arch
- IPTABLES='/etc/iptables/iptables.rules'
- SYSCTL='/etc/sysctl.d/openvpn.conf'
-else
- echo "Looks like you aren't running this installer on a Debian, Ubuntu, CentOS or ArchLinux system"
- exit 4
-fi
-
-newclient () {
- # Where to write the custom client.ovpn?
- if [ -e "/home/$1" ]; then # if $1 is a user name
- homeDir="/home/$1"
- elif [ "${SUDO_USER}" ]; then # if not, use SUDO_USER
- homeDir="/home/${SUDO_USER}"
- else # if not SUDO_USER, use /root
- homeDir="/root"
+function isRoot () {
+ if [ "$EUID" -ne 0 ]; then
+ return 1
fi
- # Generates the custom client.ovpn
- cp /etc/openvpn/client-template.txt "$homeDir/$1.ovpn"
- {
- echo ""
- cat "/etc/openvpn/easy-rsa/pki/ca.crt"
- echo ""
-
- echo ""
- cat "/etc/openvpn/easy-rsa/pki/issued/$1.crt"
- echo ""
-
- echo ""
- cat "/etc/openvpn/easy-rsa/pki/private/$1.key"
- echo ""
- echo "key-direction 1"
-
- echo ""
- cat "/etc/openvpn/tls-auth.key"
- echo ""
- } >> "$homeDir/$1.ovpn"
}
-# Get Internet network interface with default route
-NIC=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1)
+function tunAvailable () {
+ if [ ! -e /dev/net/tun ]; then
+ return 1
+ fi
+}
-if [[ -e /etc/openvpn/server.conf ]]; then
- while :
- do
- clear
- echo "OpenVPN-install (github.com/Angristan/OpenVPN-install)"
- echo ""
- echo "Looks like OpenVPN is already installed"
- echo ""
-
- echo "What do you want to do?"
- echo " 1) Add a cert for a new user"
- echo " 2) Revoke existing user cert"
- echo " 3) Remove OpenVPN"
- echo " 4) Exit"
- read -rp "Select an option [1-4]: " option
-
- case $option in
- 1)
+function checkOS () {
+ if [[ -e /etc/debian_version ]]; then
+ OS="debian"
+ # Getting the version number, to verify that a recent version of OpenVPN is available
+ source /etc/os-release
+ if [[ ! $VERSION_ID =~ (8|9|16.04|17.10|18.04) ]]; then
+ echo "⚠️ Your version of Debian/Ubuntu is not supported."
echo ""
- echo "Here are the files that already exist,do not repeat that"
- tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
- echo "Do you want to protect the configuration file with a password?"
- echo "(e.g. encrypt the private key with a password)"
- echo " 1) Add a passwordless client"
- echo " 2) Use a password for the client"
- until [[ "$pass" =~ ^[1-2]$ ]]; do
- read -rp "Select an option [1-2]: " -e -i 1 pass
+ echo "However, if you're using Debian unstable/testing, or Ubuntu beta, then you can continue."
+ echo "Keep in mind they are not supported, though."
+ echo ""
+ while [[ $CONTINUE != "y" && $CONTINUE != "n" ]]; do
+ read -rp "Continue? [y/n]: " -e CONTINUE
done
+ if [[ "$CONTINUE" = "n" ]]; then
+ echo "Ok, bye!"
+ exit 1
+ fi
+ fi
+ elif [[ -e /etc/fedora-release ]]; then
+ OS=fedora
+ elif [[ -e /etc/centos-release ]]; then
+ if ! grep -qs "^CentOS Linux release 7" /etc/centos-release; then
+ echo "Your version of CentOS is not supported."
+ echo "The script only support CentOS 7."
echo ""
- echo "Tell me a name for the client cert"
- echo "Use one word only, no special characters"
- until [[ "$CLIENT" =~ ^[a-zA-Z0-9_]+$ ]]; do
- read -rp "Client name: " -e CLIENT
+ unset CONTINUE
+ while [[ $CONTINUE != "y" && $CONTINUE != "n" ]]; do
+ read -rp "Continue anyway? [y/n]: " -e CONTINUE
done
-
- cd /etc/openvpn/easy-rsa/
- case $pass in
- 1)
- ./easyrsa build-client-full $CLIENT nopass
- ;;
- 2)
- echo "⚠️ You will be asked for the client password below ⚠️"
- ./easyrsa build-client-full $CLIENT
- ;;
- esac
-
- # Generates the custom client.ovpn
- newclient "$CLIENT"
-
- echo ""
- echo "Client $CLIENT added, certs available at $homeDir/$CLIENT.ovpn"
- exit
- ;;
- 2)
- NUMBEROFCLIENTS=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -c "^V")
- if [[ "$NUMBEROFCLIENTS" = '0' ]]; then
- echo ""
- echo "You have no existing clients!"
- exit 5
+ if [[ "$CONTINUE" = "n" ]]; then
+ echo "Ok, bye!"
+ exit 1
fi
+ fi
+ OS=centos
+ else
+ echo "Looks like you aren't running this installer on a Debian, Ubuntu, Fedora or CentOS system"
+ exit 1
+ fi
+}
- echo ""
- echo "Select the existing client certificate you want to revoke"
- tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
- if [[ "$NUMBEROFCLIENTS" = '1' ]]; then
- read -rp "Select one client [1]: " CLIENTNUMBER
- else
- read -rp "Select one client [1-$NUMBEROFCLIENTS]: " CLIENTNUMBER
- fi
+function initialCheck () {
+ if ! isRoot; then
+ echo "Sorry, you need to run this as root"
+ exit 1
+ fi
+ if ! tunAvailable; then
+ echo "TUN is not available"
+ exit 1
+ fi
+ checkOS
+}
- CLIENT=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$CLIENTNUMBER"p)
- cd /etc/openvpn/easy-rsa/
- ./easyrsa --batch revoke $CLIENT
- EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
- rm -f pki/reqs/$CLIENT.req
- rm -f pki/private/$CLIENT.key
- rm -f pki/issued/$CLIENT.crt
- rm -f /etc/openvpn/crl.pem
- cp /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn/crl.pem
- chmod 644 /etc/openvpn/crl.pem
- rm -f $(find /home -maxdepth 2 | grep $CLIENT.ovpn) 2>/dev/null
- rm -f /root/$CLIENT.ovpn 2>/dev/null
+function installUnbound () {
+ if [[ ! -e /etc/unbound/unbound.conf ]]; then
- echo ""
- echo "Certificate for client $CLIENT revoked"
- echo "Exiting..."
- exit
- ;;
- 3)
- echo ""
- read -rp "Do you really want to remove OpenVPN? [y/n]: " -e -i n REMOVE
- if [[ "$REMOVE" = 'y' ]]; then
- PORT=$(grep '^port ' /etc/openvpn/server.conf | cut -d " " -f 2)
- if pgrep firewalld; then
- # Using both permanent and not permanent rules to avoid a firewalld reload.
- firewall-cmd --zone=public --remove-port=$PORT/udp
- firewall-cmd --zone=trusted --remove-source=10.8.0.0/24
- firewall-cmd --permanent --zone=public --remove-port=$PORT/udp
- firewall-cmd --permanent --zone=trusted --remove-source=10.8.0.0/24
- fi
- if iptables -L -n | grep -qE 'REJECT|DROP'; then
- if [[ "$PROTOCOL" = 'udp' ]]; then
- iptables -D INPUT -p udp --dport $PORT -j ACCEPT
- else
- iptables -D INPUT -p tcp --dport $PORT -j ACCEPT
- fi
- iptables -D FORWARD -s 10.8.0.0/24 -j ACCEPT
- iptables-save > $IPTABLES
- fi
- iptables -t nat -D POSTROUTING -o $NIC -s 10.8.0.0/24 -j MASQUERADE
- iptables-save > $IPTABLES
- if hash sestatus 2>/dev/null; then
- if sestatus | grep "Current mode" | grep -qs "enforcing"; then
- if [[ "$PORT" != '1194' ]]; then
- semanage port -d -t openvpn_port_t -p udp $PORT
- fi
- fi
- fi
- if [[ "$OS" = 'debian' ]]; then
- apt-get autoremove --purge -y openvpn
- elif [[ "$OS" = 'arch' ]]; then
- pacman -R openvpn --noconfirm
- else
- yum remove openvpn -y
- fi
- OVPNS=$(ls /etc/openvpn/easy-rsa/pki/issued | awk -F "." {'print $1'})
- for i in $OVPNS
- do
- rm $(find /home -maxdepth 2 | grep $i.ovpn) 2>/dev/null
- rm /root/$i.ovpn 2>/dev/null
- done
- rm -rf /etc/openvpn
- rm -rf /usr/share/doc/openvpn*
- echo ""
- echo "OpenVPN removed!"
- else
- echo ""
- echo "Removal aborted!"
- fi
- exit
- ;;
- 4) exit;;
- esac
- done
-else
- clear
- echo "Welcome to the secure OpenVPN installer (github.com/Angristan/OpenVPN-install)"
+ if [[ "$OS" = "debian" ]]; then
+ apt-get install -y unbound
+
+ # Configuration
+ echo 'interface: 10.8.0.1
+access-control: 10.8.0.1/24 allow
+hide-identity: yes
+hide-version: yes
+use-caps-for-id: yes
+prefetch: yes' >> /etc/unbound/unbound.conf
+
+ elif [[ "$OS" = "centos" ]]; then
+ yum install -y unbound
+
+ # Configuration
+ sed -i 's|# interface: 0.0.0.0$|interface: 10.8.0.1|' /etc/unbound/unbound.conf
+ sed -i 's|# access-control: 127.0.0.0/8 allow|access-control: 10.8.0.1/24 allow|' /etc/unbound/unbound.conf
+ sed -i 's|# hide-identity: no|hide-identity: yes|' /etc/unbound/unbound.conf
+ sed -i 's|# hide-version: no|hide-version: yes|' /etc/unbound/unbound.conf
+ sed -i 's|use-caps-for-id: no|use-caps-for-id: yes|' /etc/unbound/unbound.conf
+
+ elif [[ "$OS" = "fedora" ]]; then
+ dnf install -y unbound
+
+ # Configuration
+ sed -i 's|# interface: 0.0.0.0$|interface: 10.8.0.1|' /etc/unbound/unbound.conf
+ sed -i 's|# access-control: 127.0.0.0/8 allow|access-control: 10.8.0.1/24 allow|' /etc/unbound/unbound.conf
+ sed -i 's|# hide-identity: no|hide-identity: yes|' /etc/unbound/unbound.conf
+ sed -i 's|# hide-version: no|hide-version: yes|' /etc/unbound/unbound.conf
+ sed -i 's|# use-caps-for-id: no|use-caps-for-id: yes|' /etc/unbound/unbound.conf
+ fi
+
+ if [[ ! "$OS" =~ (fedora|centos) ]];then
+ # DNS Rebinding fix
+ echo "private-address: 10.0.0.0/8
+private-address: 172.16.0.0/12
+private-address: 192.168.0.0/16
+private-address: 169.254.0.0/16
+private-address: fd00::/8
+private-address: fe80::/10
+private-address: 127.0.0.0/8
+private-address: ::ffff:0:0/96" >> /etc/unbound/unbound.conf
+ fi
+ else # Unbound is already installed
+ echo 'include: /etc/unbound/openvpn.conf' >> /etc/unbound/unbound.conf
+
+ # Add Unbound 'server' for the OpenVPN subnet
+ echo 'server:
+interface: 10.8.0.1
+access-control: 10.8.0.1/24 allow
+hide-identity: yes
+hide-version: yes
+use-caps-for-id: yes
+prefetch: yes
+private-address: 10.0.0.0/8
+private-address: 172.16.0.0/12
+private-address: 192.168.0.0/16
+private-address: 169.254.0.0/16
+private-address: fd00::/8
+private-address: fe80::/10
+private-address: 127.0.0.0/8
+private-address: ::ffff:0:0/96' > /etc/unbound/openvpn.conf
+ fi
+
+ systemctl enable unbound
+ systemctl restart unbound
+}
+
+function installOpenVPN () {
+ echo "Welcome to the OpenVPN installer!"
+ echo "The git repository is available at: https://github.com/angristan/openvpn-install"
echo ""
- # OpenVPN setup and first user creation
- echo "I need to ask you a few questions before starting the setup"
- echo "You can leave the default options and just press enter if you are ok with them"
+ echo "I need to ask you a few questions before starting the setup."
+ echo "You can leave the default options and just press enter if you are ok with them."
echo ""
echo "I need to know the IPv4 address of the network interface you want OpenVPN listening to."
echo "If your server is running behind a NAT, (e.g. LowEndSpirit, Scaleway) leave the IP address as it is. (local/private IP)"
echo "Otherwise, it should be your public IPv4 address."
- # Autodetect IP address and pre-fill for the user
+ # Detect public IPv4 address and pre-fill for the user
IP=$(ip addr | grep 'inet' | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1)
read -rp "IP address: " -e -i $IP IP
+ # If $IP is a private IP address, the server must be behind NAT
+ if echo "$IP" | grep -qE '^(10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|192\.168)'; then
+ echo ""
+ echo "This server is behind NAT. What is the public IPv4 address or hostname?"
+ read -rp "Public IP address / hostname: " -e PUBLICIP
+ fi
+
echo ""
- echo "What port do you want for OpenVPN?"
+ echo "Checking for IPv6 connectivity..."
+ ping6 -c4 ipv6.google.com > /dev/null 2>&1;
+ echo ""
+ if [[ $? == 0 ]]; then
+ echo "Your host appears to have IPv6 connectivity."
+ SUGGESTION="y"
+ else
+ echo "Your host does not appear to have IPv6 connectivity."
+ SUGGESTION="n"
+ fi
+ echo ""
+ # Ask the user if they want to enable IPv6 regardless its availability.
+ while [[ $IPV6_SUPPORT != "y" && $IPV6_SUPPORT != "n" ]]; do
+ read -rp "Do you want to enable IPv6 support (NAT)? [y/n]: " -e -i $SUGGESTION IPV6_SUPPORT
+ done
+ echo ""
+ echo "What port do you want OpenVPN to listen to?"
echo " 1) Default: 1194"
echo " 2) Custom"
echo " 3) Random [49152-65535]"
@@ -282,73 +201,76 @@ else
echo "Random Port: $PORT"
;;
esac
-
- # If $IP is a private IP address, the server must be behind NAT
- if echo "$IP" | grep -qE '^(10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|192\.168)'; then
- echo ""
- echo "This server is behind NAT. What is the public IPv4 address or hostname?"
- read -rp "Public IP address / hostname: " -e PUBLICIP
- fi
echo ""
- echo "What protocol do you want for OpenVPN?"
- echo "Unless UDP is blocked, you should not use TCP (unnecessarily slower)"
- until [[ "$PROTOCOL" == "UDP" || "$PROTOCOL" == "TCP" ]]; do
- read -rp "Protocol [UDP/TCP]: " -e -i UDP PROTOCOL
+ echo "What protocol do you want OpenVPN to use?"
+ echo "UDP is faster. Unless it is not available, you shoudn't use TCP."
+ echo " 1) UDP"
+ echo " 2) TCP"
+ until [[ "$PROTOCOL_CHOICE" =~ ^[1-2] ]]; do
+ read -rp "Protocol [1-2]: " -e -i 1 PROTOCOL_CHOICE
done
+ case $PROTOCOL_CHOICE in
+ 1)
+ PROTOCOL="udp"
+ ;;
+ 2)
+ PROTOCOL="tcp"
+ ;;
+ esac
echo ""
- echo "What DNS do you want to use with the VPN?"
+ echo "What DNS resolvers do you want to use with the VPN?"
echo " 1) Current system resolvers (from /etc/resolv.conf)"
- echo " 2) Cloudflare (Anycast: worldwide)"
- echo " 3) Quad9 (Anycast: worldwide)"
- echo " 4) FDN (France)"
- echo " 5) DNS.WATCH (Germany)"
- echo " 6) OpenDNS (Anycast: worldwide)"
- echo " 7) Google (Anycast: worldwide)"
- echo " 8) Yandex Basic (Russia)"
- echo " 9) AdGuard DNS (Russia)"
- until [[ "$DNS" =~ ^[0-9]+$ ]] && [ "$DNS" -ge 1 -a "$DNS" -le 9 ]; do
- read -rp "DNS [1-9]: " -e -i 1 DNS
+ echo " 2) Self-hosted DNS Resolver (Unbound)"
+ echo " 3) Cloudflare (Anycast: worldwide)"
+ echo " 4) Quad9 (Anycast: worldwide)"
+ echo " 5) FDN (France)"
+ echo " 6) DNS.WATCH (Germany)"
+ echo " 7) OpenDNS (Anycast: worldwide)"
+ echo " 8) Google (Anycast: worldwide)"
+ echo " 9) Yandex Basic (Russia)"
+ echo " 10) AdGuard DNS (Russia)"
+ until [[ "$DNS" =~ ^[0-9]+$ ]] && [ "$DNS" -ge 1 -a "$DNS" -le 10 ]; do
+ read -rp "DNS [1-10]: " -e -i 3 DNS
+ if [[ $DNS == 2 ]] && [[ -e /etc/unbound/unbound.conf ]]; then
+ echo ""
+ echo "Unbound is already installed."
+ echo "You can allow the script to configure it in order to use it from your OpenVPN clients"
+ echo "We will simply add a second server to /etc/unbound/unbound.conf for the OpenVPN subnet."
+ echo "No changes are made to the current configuration."
+ echo ""
+
+ while [[ $CONTINUE != "y" && $CONTINUE != "n" ]]; do
+ read -rp "Apply configuration changes to Unbound? [y/n]: " -e CONTINUE
+ done
+ if [[ $CONTINUE = "n" ]];then
+ # Break the loop and cleanup
+ unset DNS
+ unset CONTINUE
+ fi
+ fi
done
echo ""
echo "See https://github.com/Angristan/OpenVPN-install#encryption to learn more about "
echo "the encryption in OpenVPN and the choices I made in this script."
echo "Please note that all the choices proposed are secure (to a different degree)"
echo "and are still viable to date, unlike some default OpenVPN options"
- echo ''
+ echo ""
echo "Choose which cipher you want to use for the data channel:"
- echo " 1) AES-128-CBC (fastest and sufficiently secure for everyone, recommended)"
+ echo " 1) AES-128-CBC (recommended)"
echo " 2) AES-192-CBC"
echo " 3) AES-256-CBC"
- echo "Alternatives to AES, use them only if you know what you're doing."
- echo "They are relatively slower but as secure as AES."
- echo " 4) CAMELLIA-128-CBC"
- echo " 5) CAMELLIA-192-CBC"
- echo " 6) CAMELLIA-256-CBC"
- echo " 7) SEED-CBC"
- until [[ "$CIPHER" =~ ^[0-9]+$ ]] && [ "$CIPHER" -ge 1 -a "$CIPHER" -le 7 ]; do
- read -rp "Cipher [1-7]: " -e -i 1 CIPHER
+ until [[ "$CIPHER_CHOICE" =~ ^[0-9]+$ ]] && [ "$CIPHER_CHOICE" -ge 1 -a "$CIPHER_CHOICE" -le 3 ]; do
+ read -rp "CIPHER_CHOICE [1-7]: " -e -i 1 CIPHER_CHOICE
done
- case $CIPHER in
+ case $CIPHER_CHOICE in
1)
- CIPHER="cipher AES-128-CBC"
+ CIPHER="cipher AES-128-CBC"
;;
2)
- CIPHER="cipher AES-192-CBC"
+ CIPHER="cipher AES-192-CBC"
;;
3)
- CIPHER="cipher AES-256-CBC"
- ;;
- 4)
- CIPHER="cipher CAMELLIA-128-CBC"
- ;;
- 5)
- CIPHER="cipher CAMELLIA-192-CBC"
- ;;
- 6)
- CIPHER="cipher CAMELLIA-256-CBC"
- ;;
- 7)
- CIPHER="cipher SEED-CBC"
+ CIPHER="cipher AES-256-CBC"
;;
esac
echo ""
@@ -356,176 +278,64 @@ else
echo " 1) 2048 bits (fastest)"
echo " 2) 3072 bits (recommended, best compromise)"
echo " 3) 4096 bits (most secure)"
- until [[ "$DH_KEY_SIZE" =~ ^[0-9]+$ ]] && [ "$DH_KEY_SIZE" -ge 1 -a "$DH_KEY_SIZE" -le 3 ]; do
- read -rp "DH key size [1-3]: " -e -i 2 DH_KEY_SIZE
+ until [[ "$DH_KEY_SIZE_CHOICE" =~ ^[0-9]+$ ]] && [ "$DH_KEY_SIZE_CHOICE" -ge 1 -a "$DH_KEY_SIZE_CHOICE" -le 3 ]; do
+ read -rp "DH key size [1-3]: " -e -i 2 DH_KEY_SIZE_CHOICE
done
- case $DH_KEY_SIZE in
+ case $DH_KEY_SIZE_CHOICE in
1)
- DH_KEY_SIZE="2048"
+ DH_KEY_SIZE="2048"
;;
2)
- DH_KEY_SIZE="3072"
+ DH_KEY_SIZE="3072"
;;
3)
- DH_KEY_SIZE="4096"
+ DH_KEY_SIZE="4096"
;;
esac
echo ""
- echo "Choose what size of RSA key you want to use:"
+ echo "Choose what size of RSA key you want to use for the certificate:"
echo " 1) 2048 bits (fastest)"
echo " 2) 3072 bits (recommended, best compromise)"
echo " 3) 4096 bits (most secure)"
- until [[ "$RSA_KEY_SIZE" =~ ^[0-9]+$ ]] && [ "$RSA_KEY_SIZE" -ge 1 -a "$RSA_KEY_SIZE" -le 3 ]; do
- read -rp "RSA key size [1-3]: " -e -i 2 RSA_KEY_SIZE
+ until [[ "$RSA_KEY_SIZE_CHOICE" =~ ^[0-9]+$ ]] && [ "$RSA_KEY_SIZE_CHOICE" -ge 1 -a "$RSA_KEY_SIZE_CHOICE" -le 3 ]; do
+ read -rp "RSA key size [1-3]: " -e -i 2 RSA_KEY_SIZE_CHOICE
done
- case $RSA_KEY_SIZE in
+ case $RSA_KEY_SIZE_CHOICE in
1)
- RSA_KEY_SIZE="2048"
+ RSA_KEY_SIZE="2048"
;;
2)
- RSA_KEY_SIZE="3072"
+ RSA_KEY_SIZE="3072"
;;
3)
- RSA_KEY_SIZE="4096"
+ RSA_KEY_SIZE="4096"
;;
esac
echo ""
- echo "Do you want to protect the configuration file with a password?"
- echo "(e.g. encrypt the private key with a password)"
- echo " 1) Add a passwordless client"
- echo " 2) Use a password for the client"
- until [[ "$pass" =~ ^[1-2]$ ]]; do
- read -rp "Select an option [1-2]: " -e -i 1 pass
- done
- echo ""
- echo "Finally, tell me a name for the client certificate and configuration"
- echo "Use one word only, no special characters"
- until [[ "$CLIENT" =~ ^[a-zA-Z0-9_]+$ ]]; do
- read -rp "Client name: " -e -i client CLIENT
- done
- echo ""
echo "Okay, that was all I needed. We are ready to setup your OpenVPN server now"
+ echo "You will be able to generate a client at the end of the installtion."
read -n1 -r -p "Press any key to continue..."
+ # Get the "public" interface from the default route
+ NIC=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1)
+
if [[ "$OS" = 'debian' ]]; then
+ apt-get update
apt-get install ca-certificates gnupg -y
# We add the OpenVPN repo to get the latest version.
- # Debian 7
- if [[ "$VERSION_ID" = 'VERSION_ID="7"' ]]; then
- echo "deb http://build.openvpn.net/debian/openvpn/stable wheezy main" > /etc/apt/sources.list.d/openvpn.list
- wget -O - https://swupdate.openvpn.net/repos/repo-public.gpg | apt-key add -
- apt-get update
- fi
- # Debian 8
if [[ "$VERSION_ID" = 'VERSION_ID="8"' ]]; then
echo "deb http://build.openvpn.net/debian/openvpn/stable jessie main" > /etc/apt/sources.list.d/openvpn.list
wget -O - https://swupdate.openvpn.net/repos/repo-public.gpg | apt-key add -
- apt update
- fi
- # Ubuntu 14.04
- if [[ "$VERSION_ID" = 'VERSION_ID="14.04"' ]]; then
- echo "deb http://build.openvpn.net/debian/openvpn/stable trusty main" > /etc/apt/sources.list.d/openvpn.list
- wget -O - https://swupdate.openvpn.net/repos/repo-public.gpg | apt-key add -
apt-get update
fi
# Ubuntu >= 16.04 and Debian > 8 have OpenVPN > 2.3.3 without the need of a third party repository.
- # The we install OpenVPN
apt-get install openvpn iptables openssl wget ca-certificates curl -y
- # Install iptables service
- if [[ ! -e /etc/systemd/system/iptables.service ]]; then
- mkdir /etc/iptables
- iptables-save > /etc/iptables/iptables.rules
- echo "#!/bin/sh
-iptables -F
-iptables -X
-iptables -t nat -F
-iptables -t nat -X
-iptables -t mangle -F
-iptables -t mangle -X
-iptables -P INPUT ACCEPT
-iptables -P FORWARD ACCEPT
-iptables -P OUTPUT ACCEPT" > /etc/iptables/flush-iptables.sh
- chmod +x /etc/iptables/flush-iptables.sh
- echo "[Unit]
-Description=Packet Filtering Framework
-DefaultDependencies=no
-Before=network-pre.target
-Wants=network-pre.target
-[Service]
-Type=oneshot
-ExecStart=/sbin/iptables-restore /etc/iptables/iptables.rules
-ExecReload=/sbin/iptables-restore /etc/iptables/iptables.rules
-ExecStop=/etc/iptables/flush-iptables.sh
-RemainAfterExit=yes
-[Install]
-WantedBy=multi-user.target" > /etc/systemd/system/iptables.service
- systemctl daemon-reload
- systemctl enable iptables.service
- fi
- elif [[ "$OS" = 'centos' || "$OS" = 'fedora' ]]; then
- if [[ "$OS" = 'centos' ]]; then
- yum install epel-release -y
- fi
- yum install openvpn iptables openssl wget ca-certificates curl -y
- # Install iptables service
- if [[ ! -e /etc/systemd/system/iptables.service ]]; then
- mkdir /etc/iptables
- iptables-save > /etc/iptables/iptables.rules
- echo "#!/bin/sh
-iptables -F
-iptables -X
-iptables -t nat -F
-iptables -t nat -X
-iptables -t mangle -F
-iptables -t mangle -X
-iptables -P INPUT ACCEPT
-iptables -P FORWARD ACCEPT
-iptables -P OUTPUT ACCEPT" > /etc/iptables/flush-iptables.sh
- chmod +x /etc/iptables/flush-iptables.sh
- echo "[Unit]
-Description=Packet Filtering Framework
-DefaultDependencies=no
-Before=network-pre.target
-Wants=network-pre.target
-[Service]
-Type=oneshot
-ExecStart=/sbin/iptables-restore /etc/iptables/iptables.rules
-ExecReload=/sbin/iptables-restore /etc/iptables/iptables.rules
-ExecStop=/etc/iptables/flush-iptables.sh
-RemainAfterExit=yes
-[Install]
-WantedBy=multi-user.target" > /etc/systemd/system/iptables.service
- systemctl daemon-reload
- systemctl enable iptables.service
- # Disable firewalld to allow iptables to start upon reboot
- systemctl disable firewalld
- systemctl mask firewalld
- fi
- else
- # Else, the distro is ArchLinux
- echo ""
- echo ""
- echo "As you're using ArchLinux, I need to update the packages on your system to install those I need."
- echo "Not doing that could cause problems between dependencies, or missing files in repositories."
- echo ""
- echo "Continuing will update your installed packages and install needed ones."
- until [[ $CONTINUE == "y" || $CONTINUE == "n" ]]; do
- read -rp "Continue ? [y/n]: " -e -i y CONTINUE
- done
- if [[ "$CONTINUE" = "n" ]]; then
- echo "Ok, bye !"
- exit 4
- fi
-
- if [[ "$OS" = 'arch' ]]; then
- # Install dependencies
- pacman -Syu openvpn iptables openssl wget ca-certificates curl --needed --noconfirm
- iptables-save > /etc/iptables/iptables.rules # iptables won't start if this file does not exist
- systemctl daemon-reload
- systemctl enable iptables
- systemctl start iptables
- fi
+ elif [[ "$OS" = 'centos' ]]; then
+ yum install epel-release openvpn iptables openssl wget ca-certificates curl -y
+ elif [[ "$OS" = 'fedora' ]]; then
+ dnf install openvpn iptables openssl wget ca-certificates curl -y
fi
+
# Find out if the machine uses nogroup or nobody for the permissionless group
if grep -qs "^nogroup:" /etc/group; then
NOGROUP=nogroup
@@ -537,34 +347,29 @@ WantedBy=multi-user.target" > /etc/systemd/system/iptables.service
if [[ -d /etc/openvpn/easy-rsa/ ]]; then
rm -rf /etc/openvpn/easy-rsa/
fi
- # Get easy-rsa
- wget -O ~/EasyRSA-3.0.4.tgz https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.4/EasyRSA-3.0.4.tgz
- tar xzf ~/EasyRSA-3.0.4.tgz -C ~/
- mv ~/EasyRSA-3.0.4/ /etc/openvpn/easy-rsa/
+
+ # Install the latest version of easy-rsa from source
+ local version="3.0.4"
+ wget -O ~/EasyRSA-${version}.tgz https://github.com/OpenVPN/easy-rsa/releases/download/v${version}/EasyRSA-${version}.tgz
+ tar xzf ~/EasyRSA-${version}.tgz -C ~/
+ mv ~/EasyRSA-${version}/ /etc/openvpn/
+ mv /etc/openvpn/EasyRSA-${version}/ /etc/openvpn/easy-rsa/
chown -R root:root /etc/openvpn/easy-rsa/
- rm -f ~/EasyRSA-3.0.4.tgz
+ rm -f ~/EasyRSA-${version}.tgz
+
cd /etc/openvpn/easy-rsa/
# Generate a random, alphanumeric identifier of 16 characters for CN and one for server name
SERVER_CN="cn_$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)"
SERVER_NAME="server_$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)"
echo "set_var EASYRSA_KEY_SIZE $RSA_KEY_SIZE" > vars
echo "set_var EASYRSA_REQ_CN $SERVER_CN" >> vars
- # Create the PKI, set up the CA, the DH params and the server + client certificates
+ # Create the PKI, set up the CA, the DH params and the server certificate
./easyrsa init-pki
./easyrsa --batch build-ca nopass
openssl dhparam -out dh.pem $DH_KEY_SIZE
./easyrsa build-server-full $SERVER_NAME nopass
- case $pass in
- 1)
- ./easyrsa build-client-full $CLIENT nopass
- ;;
- 2)
- echo "⚠️ You will be asked for the client password below ⚠️"
- ./easyrsa build-client-full $CLIENT
- ;;
- esac
EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
- # generate tls-auth key
+ # Generate tls-auth key
openvpn --genkey --secret /etc/openvpn/tls-auth.key
# Move all the generated files
cp pki/ca.crt pki/private/ca.key dh.pem pki/issued/$SERVER_NAME.crt pki/private/$SERVER_NAME.key /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn
@@ -573,7 +378,12 @@ WantedBy=multi-user.target" > /etc/systemd/system/iptables.service
# Generate server.conf
echo "port $PORT" > /etc/openvpn/server.conf
- echo "proto $(echo $PROTOCOL | tr '[:upper:]' '[:lower:]')" >> /etc/openvpn/server.conf
+ if [[ "$IPV6_SUPPORT" = 'n' ]]; then
+ echo "proto $PROTOCOL" >> /etc/openvpn/server.conf
+ elif [[ "$IPV6_SUPPORT" = 'y' ]]; then
+ echo "proto ${PROTOCOL}6" >> /etc/openvpn/server.conf
+ fi
+
echo "dev tun
user nobody
group $NOGROUP
@@ -583,56 +393,70 @@ keepalive 10 120
topology subnet
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt" >> /etc/openvpn/server.conf
+
# DNS resolvers
case $DNS in
1)
- # Locate the proper resolv.conf
- # Needed for systems running systemd-resolved
- if grep -q "127.0.0.53" "/etc/resolv.conf"; then
- RESOLVCONF='/run/systemd/resolve/resolv.conf'
- else
- RESOLVCONF='/etc/resolv.conf'
- fi
- # Obtain the resolvers from resolv.conf and use them for OpenVPN
- grep -v '#' $RESOLVCONF | grep 'nameserver' | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | while read -r line; do
- echo "push \"dhcp-option DNS $line\"" >> /etc/openvpn/server.conf
- done
+ # Locate the proper resolv.conf
+ # Needed for systems running systemd-resolved
+ if grep -q "127.0.0.53" "/etc/resolv.conf"; then
+ RESOLVCONF='/run/systemd/resolve/resolv.conf'
+ else
+ RESOLVCONF='/etc/resolv.conf'
+ fi
+ # Obtain the resolvers from resolv.conf and use them for OpenVPN
+ grep -v '#' $RESOLVCONF | grep 'nameserver' | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | while read -r line; do
+ echo "push \"dhcp-option DNS $line\"" >> /etc/openvpn/server.conf
+ done
;;
- 2) # Cloudflare
- echo 'push "dhcp-option DNS 1.0.0.1"' >> /etc/openvpn/server.conf
- echo 'push "dhcp-option DNS 1.1.1.1"' >> /etc/openvpn/server.conf
+ 2)
+ echo 'push "dhcp-option DNS 10.8.0.1"' >> /etc/openvpn/server.conf
;;
- 3) # Quad9
- echo 'push "dhcp-option DNS 9.9.9.9"' >> /etc/openvpn/server.conf
- echo 'push "dhcp-option DNS 149.112.112.112"' >> /etc/openvpn/server.conf
+ 3) # Cloudflare
+ echo 'push "dhcp-option DNS 1.0.0.1"' >> /etc/openvpn/server.conf
+ echo 'push "dhcp-option DNS 1.1.1.1"' >> /etc/openvpn/server.conf
;;
- 4) # FDN
- echo 'push "dhcp-option DNS 80.67.169.40"' >> /etc/openvpn/server.conf
- echo 'push "dhcp-option DNS 80.67.169.12"' >> /etc/openvpn/server.conf
+ 4) # Quad9
+ echo 'push "dhcp-option DNS 9.9.9.9"' >> /etc/openvpn/server.conf
+ echo 'push "dhcp-option DNS 149.112.112.112"' >> /etc/openvpn/server.conf
;;
- 5) # DNS.WATCH
- echo 'push "dhcp-option DNS 84.200.69.80"' >> /etc/openvpn/server.conf
- echo 'push "dhcp-option DNS 84.200.70.40"' >> /etc/openvpn/server.conf
+ 5) # FDN
+ echo 'push "dhcp-option DNS 80.67.169.40"' >> /etc/openvpn/server.conf
+ echo 'push "dhcp-option DNS 80.67.169.12"' >> /etc/openvpn/server.conf
;;
- 6) # OpenDNS
- echo 'push "dhcp-option DNS 208.67.222.222"' >> /etc/openvpn/server.conf
- echo 'push "dhcp-option DNS 208.67.220.220"' >> /etc/openvpn/server.conf
+ 6) # DNS.WATCH
+ echo 'push "dhcp-option DNS 84.200.69.80"' >> /etc/openvpn/server.conf
+ echo 'push "dhcp-option DNS 84.200.70.40"' >> /etc/openvpn/server.conf
;;
- 7) # Google
- echo 'push "dhcp-option DNS 8.8.8.8"' >> /etc/openvpn/server.conf
- echo 'push "dhcp-option DNS 8.8.4.4"' >> /etc/openvpn/server.conf
+ 7) # OpenDNS
+ echo 'push "dhcp-option DNS 208.67.222.222"' >> /etc/openvpn/server.conf
+ echo 'push "dhcp-option DNS 208.67.220.220"' >> /etc/openvpn/server.conf
;;
- 8) # Yandex Basic
- echo 'push "dhcp-option DNS 77.88.8.8"' >> /etc/openvpn/server.conf
- echo 'push "dhcp-option DNS 77.88.8.1"' >> /etc/openvpn/server.conf
+ 8) # Google
+ echo 'push "dhcp-option DNS 8.8.8.8"' >> /etc/openvpn/server.conf
+ echo 'push "dhcp-option DNS 8.8.4.4"' >> /etc/openvpn/server.conf
;;
- 9) # AdGuard DNS
- echo 'push "dhcp-option DNS 176.103.130.130"' >> /etc/openvpn/server.conf
- echo 'push "dhcp-option DNS 176.103.130.131"' >> /etc/openvpn/server.conf
+ 9) # Yandex Basic
+ echo 'push "dhcp-option DNS 77.88.8.8"' >> /etc/openvpn/server.conf
+ echo 'push "dhcp-option DNS 77.88.8.1"' >> /etc/openvpn/server.conf
+ ;;
+ 10) # AdGuard DNS
+ echo 'push "dhcp-option DNS 176.103.130.130"' >> /etc/openvpn/server.conf
+ echo 'push "dhcp-option DNS 176.103.130.131"' >> /etc/openvpn/server.conf
;;
esac
-echo 'push "redirect-gateway def1 bypass-dhcp" ' >> /etc/openvpn/server.conf
-echo "crl-verify crl.pem
+ echo 'push "redirect-gateway def1 bypass-dhcp" '>> /etc/openvpn/server.conf
+
+ # IPv6 network settings if needed
+ if [[ "$IPV6_SUPPORT" = 'y' ]]; then
+ echo 'server-ipv6 fd42:42:42:42::/112
+tun-ipv6
+push tun-ipv6
+push "route-ipv6 2000::/3"
+push "redirect-gateway ipv6"' >> /etc/openvpn/server.conf
+ fi
+
+ echo "crl-verify crl.pem
ca ca.crt
cert $SERVER_NAME.crt
key $SERVER_NAME.key
@@ -646,119 +470,115 @@ tls-cipher TLS-DHE-RSA-WITH-AES-128-GCM-SHA256
status /var/log/openvpn/status.log
verb 3" >> /etc/openvpn/server.conf
-# Create log dir
-mkdir -p /var/log/openvpn
+ # Create log dir
+ mkdir -p /var/log/openvpn
- # Create the sysctl configuration file if needed (mainly for Arch Linux)
- if [[ ! -e $SYSCTL ]]; then
- touch $SYSCTL
+ # Enable routing
+ echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.d/20-openvpn.conf
+ if [[ "$IPV6_SUPPORT" = 'y' ]]; then
+ echo 'net.ipv6.conf.all.forwarding=1' >> /etc/sysctl.d/20-openvpn.conf
fi
-
- # Enable net.ipv4.ip_forward for the system
- sed -i '/\/c\net.ipv4.ip_forward=1' $SYSCTL
- if ! grep -q "\" $SYSCTL; then
- echo 'net.ipv4.ip_forward=1' >> $SYSCTL
- fi
-
# Avoid an unneeded reboot
- echo 1 > /proc/sys/net/ipv4/ip_forward
-
- # Set NAT for the VPN subnet
- iptables -t nat -A POSTROUTING -o $NIC -s 10.8.0.0/24 -j MASQUERADE
-
- # Save persitent iptables rules
- iptables-save > $IPTABLES
-
- if pgrep firewalld; then
- # We don't use --add-service=openvpn because that would only work with
- # the default port. Using both permanent and not permanent rules to
- # avoid a firewalld reload.
- if [[ "$PROTOCOL" = 'UDP' ]]; then
- firewall-cmd --zone=public --add-port=$PORT/udp
- firewall-cmd --permanent --zone=public --add-port=$PORT/udp
- elif [[ "$PROTOCOL" = 'TCP' ]]; then
- firewall-cmd --zone=public --add-port=$PORT/tcp
- firewall-cmd --permanent --zone=public --add-port=$PORT/tcp
- fi
- firewall-cmd --zone=trusted --add-source=10.8.0.0/24
- firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24
- fi
-
- if iptables -L -n | grep -qE 'REJECT|DROP'; then
- # If iptables has at least one REJECT rule, we asume this is needed.
- # Not the best approach but I can't think of other and this shouldn't
- # cause problems.
- if [[ "$PROTOCOL" = 'UDP' ]]; then
- iptables -I INPUT -p udp --dport $PORT -j ACCEPT
- elif [[ "$PROTOCOL" = 'TCP' ]]; then
- iptables -I INPUT -p tcp --dport $PORT -j ACCEPT
- fi
- iptables -I FORWARD -s 10.8.0.0/24 -j ACCEPT
- iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
- # Save persitent OpenVPN rules
- iptables-save > $IPTABLES
- fi
+ sysctl --system
# If SELinux is enabled and a custom port was selected, we need this
if hash sestatus 2>/dev/null; then
if sestatus | grep "Current mode" | grep -qs "enforcing"; then
if [[ "$PORT" != '1194' ]]; then
- # semanage isn't available in CentOS 6 by default
- if ! hash semanage 2>/dev/null; then
- yum install policycoreutils-python -y
- fi
- if [[ "$PROTOCOL" = 'UDP' ]]; then
- semanage port -a -t openvpn_port_t -p udp $PORT
- elif [[ "$PROTOCOL" = 'TCP' ]]; then
- semanage port -a -t openvpn_port_t -p tcp $PORT
- fi
+ semanage port -a -t openvpn_port_t -p $PROTOCOL $PORT
fi
fi
fi
- # And finally, restart OpenVPN
- if [[ "$OS" = 'debian' ]]; then
- # Little hack to check for systemd
- if pgrep systemd-journal; then
- #Workaround to fix OpenVPN service on OpenVZ
- sed -i 's|LimitNPROC|#LimitNPROC|' /lib/systemd/system/openvpn\@.service
- sed -i 's|/etc/openvpn/server|/etc/openvpn|' /lib/systemd/system/openvpn\@.service
- sed -i 's|%i.conf|server.conf|' /lib/systemd/system/openvpn\@.service
- systemctl daemon-reload
- systemctl restart openvpn
- systemctl enable openvpn
- else
- /etc/init.d/openvpn restart
- fi
+ # Finally, restart and enable OpenVPN
+ if [[ "$OS" = 'fedora' ]]; then
+ # Workaround to fix OpenVPN service on OpenVZ
+ sed -i 's|LimitNPROC|#LimitNPROC|' /usr/lib/systemd/system/openvpn-server@.service
+ # Another workaround to keep using /etc/openvpn/
+ sed -i 's|/etc/openvpn/server|/etc/openvpn|' /usr/lib/systemd/system/openvpn-server@.service
+ systemctl daemon-reload
+ systemctl restart openvpn-server@server
+ systemctl enable openvpn-server@server
else
- if pgrep systemd-journal; then
- if [[ "$OS" = 'arch' || "$OS" = 'fedora' ]]; then
- #Workaround to avoid rewriting the entire script for Arch & Fedora
- sed -i 's|/etc/openvpn/server|/etc/openvpn|' /usr/lib/systemd/system/openvpn-server@.service
- sed -i 's|%i.conf|server.conf|' /usr/lib/systemd/system/openvpn-server@.service
- systemctl daemon-reload
- systemctl restart openvpn-server@openvpn.service
- systemctl enable openvpn-server@openvpn.service
- else
- systemctl restart openvpn@server.service
- systemctl enable openvpn@server.service
- fi
- else
- service openvpn restart
- chkconfig openvpn on
- fi
+ # Workaround to fix OpenVPN service on OpenVZ
+ sed -i 's|LimitNPROC|#LimitNPROC|' /lib/systemd/system/openvpn\@.service
+ # Another workaround to keep using /etc/openvpn/
+ sed -i 's|/etc/openvpn/server|/etc/openvpn|' /lib/systemd/system/openvpn\@.service
+ systemctl daemon-reload
+ systemctl restart openvpn@server
+ systemctl enable openvpn@server
fi
- # If the server is behind a NAT, use the correct IP address
+ if [[ $DNS == 2 ]];then
+ installUnbound
+ fi
+
+ # Add iptables rules in two scripts
+ mkdir /etc/iptables
+
+ # Script to add rules
+ echo "#!/bin/sh
+iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o $NIC -j MASQUERADE
+iptables -A INPUT -i tun0 -j ACCEPT
+iptables -A FORWARD -i $NIC -o tun0 -j ACCEPT
+iptables -A FORWARD -i tun0 -o $NIC -j ACCEPT
+iptables -A INPUT -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT" > /etc/iptables/add-openvpn-rules.sh
+
+ if [[ "$IPV6_SUPPORT" = 'y' ]]; then
+ echo "ip6tables -t nat -A POSTROUTING -s fd42:42:42:42::/112 -o $NIC -j MASQUERADE
+ip6tables -A INPUT -i tun0 -j ACCEPT
+ip6tables -A FORWARD -i $NIC -o tun0 -j ACCEPT
+ip6tables -A FORWARD -i tun0 -o $NIC -j ACCEPT" >> /etc/iptables/add-openvpn-rules.sh
+ fi
+
+ # Script to remove rules
+ echo "#!/bin/sh
+iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o $NIC -j MASQUERADE
+iptables -D INPUT -i tun0 -j ACCEPT
+iptables -D FORWARD -i $NIC -o tun0 -j ACCEPT
+iptables -D FORWARD -i tun0 -o $NIC -j ACCEPT
+iptables -D INPUT -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT" > /etc/iptables/rm-openvpn-rules.sh
+
+ if [[ "$IPV6_SUPPORT" = 'y' ]]; then
+ echo "ip6tables -t nat -D POSTROUTING -s fd42:42:42:42::/112 -o $NIC -j MASQUERADE
+ip6tables -D INPUT -i tun0 -j ACCEPT
+ip6tables -D FORWARD -i $NIC -o tun0 -j ACCEPT
+ip6tables -D FORWARD -i tun0 -o $NIC -j ACCEPT" >> /etc/iptables/rm-openvpn-rules.sh
+ fi
+
+ chmod +x /etc/iptables/add-openvpn-rules.sh
+ chmod +x /etc/iptables/rm-openvpn-rules.sh
+
+ # Handle the rules via a systemd script
+ echo "[Unit]
+Description=iptables rules for OpenVPN
+Before=network-pre.target
+Wants=network-pre.target
+
+[Service]
+Type=oneshot
+ExecStart=/etc/iptables/add-openvpn-rules.sh
+ExecStop=/etc/iptables/rm-openvpn-rules.sh
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target" > /etc/systemd/system/iptables-openvpn.service
+
+ # Enable service and apply rules
+ systemctl daemon-reload
+ systemctl enable iptables-openvpn
+ systemctl start iptables-openvpn
+
+ # If the server is behind a NAT, use the correct IP address for the clients to connect to
if [[ "$PUBLICIP" != "" ]]; then
IP=$PUBLICIP
fi
# client-template.txt is created so we have a template to add further users later
echo "client" > /etc/openvpn/client-template.txt
- if [[ "$PROTOCOL" = 'UDP' ]]; then
+ if [[ "$PROTOCOL" = 'udp' ]]; then
echo "proto udp" >> /etc/openvpn/client-template.txt
- elif [[ "$PROTOCOL" = 'TCP' ]]; then
+ elif [[ "$PROTOCOL" = 'tcp' ]]; then
echo "proto tcp-client" >> /etc/openvpn/client-template.txt
fi
echo "remote $IP $PORT
@@ -775,15 +595,248 @@ $CIPHER
tls-client
tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-128-GCM-SHA256
-setenv opt block-outside-dns
+setenv opt block-outside-dns # Prevent Windows 10 DNS leak
verb 3" >> /etc/openvpn/client-template.txt
# Generate the custom client.ovpn
- newclient "$CLIENT"
- echo ""
- echo "Finished!"
- echo ""
- echo "Your client config is available at $homeDir/$CLIENT.ovpn"
+ newClient
echo "If you want to add more clients, you simply need to run this script another time!"
+}
+
+function newClient () {
+ echo ""
+ echo "Tell me a name for the client."
+ echo "Use one word only, no special characters."
+
+ until [[ "$CLIENT" =~ ^[a-zA-Z0-9_]+$ ]]; do
+ read -rp "Client name: " -e CLIENT
+ done
+
+ echo ""
+ echo "Do you want to protect the configuration file with a password?"
+ echo "(e.g. encrypt the private key with a password)"
+ echo " 1) Add a passwordless client"
+ echo " 2) Use a password for the client"
+
+ until [[ "$PASS" =~ ^[1-2]$ ]]; do
+ read -rp "Select an option [1-2]: " -e -i 1 PASS
+ done
+
+ cd /etc/openvpn/easy-rsa/ || return
+ case $PASS in
+ 1)
+ ./easyrsa build-client-full $CLIENT nopass
+ ;;
+ 2)
+ echo "⚠️ You will be asked for the client password below ⚠️"
+ ./easyrsa build-client-full $CLIENT
+ ;;
+ esac
+
+ # Home directory of the user, where the client configuration (.ovpn) will be written
+ if [ -e "/home/$CLIENT" ]; then # if $1 is a user name
+ homeDir="/home/$CLIENT"
+ elif [ "${SUDO_USER}" ]; then # if not, use SUDO_USER
+ homeDir="/home/${SUDO_USER}"
+ else # if not SUDO_USER, use /root
+ homeDir="/root"
+ fi
+
+ # Generates the custom client.ovpn
+ cp /etc/openvpn/client-template.txt "$homeDir/$CLIENT.ovpn"
+ {
+ echo ""
+ cat "/etc/openvpn/easy-rsa/pki/ca.crt"
+ echo ""
+
+ echo ""
+ cat "/etc/openvpn/easy-rsa/pki/issued/$CLIENT.crt"
+ echo ""
+
+ echo ""
+ cat "/etc/openvpn/easy-rsa/pki/private/$CLIENT.key"
+ echo ""
+ echo "key-direction 1"
+
+ echo ""
+ cat "/etc/openvpn/tls-auth.key"
+ echo ""
+ } >> "$homeDir/$CLIENT.ovpn"
+
+ echo ""
+ echo "Client $CLIENT added, the configuration file is available at $homeDir/$CLIENT.ovpn."
+ echo "Download the .ovpn file and import it in your OpenVPN client."
+}
+
+function revokeClient () {
+ NUMBEROFCLIENTS=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -c "^V")
+ if [[ "$NUMBEROFCLIENTS" = '0' ]]; then
+ echo ""
+ echo "You have no existing clients!"
+ exit 1
+ fi
+
+ echo ""
+ echo "Select the existing client certificate you want to revoke"
+ tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
+ if [[ "$NUMBEROFCLIENTS" = '1' ]]; then
+ read -rp "Select one client [1]: " CLIENTNUMBER
+ else
+ read -rp "Select one client [1-$NUMBEROFCLIENTS]: " CLIENTNUMBER
+ fi
+
+ CLIENT=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$CLIENTNUMBER"p)
+ cd /etc/openvpn/easy-rsa/
+ ./easyrsa --batch revoke $CLIENT
+ EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
+ # Cleanup
+ rm -f pki/reqs/$CLIENT.req
+ rm -f pki/private/$CLIENT.key
+ rm -f pki/issued/$CLIENT.crt
+ rm -f /etc/openvpn/crl.pem
+ cp /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn/crl.pem
+ chmod 644 /etc/openvpn/crl.pem
+ rm -f $(find /home -maxdepth 2 | grep $CLIENT.ovpn) 2>/dev/null
+ rm -f /root/$CLIENT.ovpn 2>/dev/null
+
+ echo ""
+ echo "Certificate for client $CLIENT revoked."
+}
+
+function removeUnbound () {
+ # Remove OpenVPN-related config
+ sed -i 's|include: \/etc\/unbound\/openvpn.conf||' /etc/unbound/unbound.conf
+ rm /etc/unbound/openvpn.conf
+ systemctl restart unbound
+
+ until [[ $REMOVE_UNBOUND == "y" || $REMOVE_UNBOUND == "n" ]]; do
+ echo ""
+ echo "If you were already using Unbound before installing OpenVPN, I removed the configuration related to OpenVPN."
+ read -rp "Do you want to completely remove Unbound? [y/n]: " -e REMOVE_UNBOUND
+ done
+
+ if [[ "$REMOVE_UNBOUND" = 'y' ]]; then
+ # Stop Unbound
+ systemctl stop unbound
+
+ if [[ "$OS" = 'debian' ]]; then
+ apt-get autoremove --purge -y unbound
+ elif [[ "$OS" = 'centos' ]]; then
+ yum remove unbound -y
+ elif [[ "$OS" = 'fedora' ]]; then
+ dnf remove unbound -y
+ fi
+
+ rm -rf /etc/unbound/
+
+ echo ""
+ echo "Unbound removed!"
+ else
+ echo ""
+ echo "Unbound wasn't removed."
+ fi
+}
+
+function removeOpenVPN () {
+ echo ""
+ read -rp "Do you really want to remove OpenVPN? [y/n]: " -e -i n REMOVE
+ if [[ "$REMOVE" = 'y' ]]; then
+ # Get OpenVPN port from the configuration
+ PORT=$(grep '^port ' /etc/openvpn/server.conf | cut -d " " -f 2)
+
+ # Stop OpenVPN
+ if [[ "$OS" = 'fedora' ]]; then
+ systemctl stop openvpn-server@server
+ else
+ systemctl stop openvpn@server
+ fi
+
+ # Remove the iptables rules related to the script
+ systemctl stop iptables-openvpn
+ # Cleanup
+ systemctl disable iptables-openvpn
+ rm /etc/systemd/system/iptables-openvpn.service
+ systemctl daemon-reload
+ rm /etc/iptables/add-openvpn-rules.sh
+ rm /etc/iptables/rm-openvpn-rules.sh
+
+ # SELinux
+ if hash sestatus 2>/dev/null; then
+ if sestatus | grep "Current mode" | grep -qs "enforcing"; then
+ if [[ "$PORT" != '1194' ]]; then
+ semanage port -d -t openvpn_port_t -p udp $PORT
+ fi
+ fi
+ fi
+
+ if [[ "$OS" = 'debian' ]]; then
+ apt-get autoremove --purge -y openvpn
+ elif [[ "$OS" = 'centos' ]]; then
+ yum remove openvpn -y
+ elif [[ "$OS" = 'fedora' ]]; then
+ dnf remove openvpn -y
+ fi
+
+ # Cleanup
+ OVPNS=$(ls /etc/openvpn/easy-rsa/pki/issued | awk -F "." {'print $1'})
+ for i in $OVPNS;do
+ rm $(find /home -maxdepth 2 | grep $i.ovpn) 2>/dev/null
+ rm /root/$i.ovpn 2>/dev/null
+ done
+ rm -rf /etc/openvpn
+ rm -rf /usr/share/doc/openvpn*
+ rm -f /etc/sysctl.d/20-openvpn.conf
+
+ # Unbound
+ if [[ -e /etc/unbound/openvpn.conf ]]; then
+ removeUnbound
+ fi
+ echo ""
+ echo "OpenVPN removed!"
+ else
+ echo ""
+ echo "Removal aborted!"
+ fi
+}
+
+function manageMenu () {
+ clear
+ echo "Welcome to OpenVPN-install!"
+ echo "The git repository is available at: https://github.com/angristan/openvpn-install"
+ echo ""
+ echo "It looks like OpenVPN is already installed."
+ echo ""
+ echo "What do you want to do?"
+ echo " 1) Add a new user"
+ echo " 2) Revoke existing user"
+ echo " 3) Remove OpenVPN"
+ echo " 4) Exit"
+ until [[ "$MENU_OPTION" =~ ^[1-4]$ ]]; do
+ read -rp "Select an option [1-4]: " MENU_OPTION
+ done
+
+ case $MENU_OPTION in
+ 1)
+ newClient
+ ;;
+ 2)
+ revokeClient
+ ;;
+ 3)
+ removeOpenVPN
+ ;;
+ 4)
+ exit 0
+ ;;
+ esac
+}
+
+# Check for root, TUN, OS...
+initialCheck
+
+# Check if OpenVPN is already installed
+if [[ -e /etc/openvpn/server.conf ]]; then
+ manageMenu
+else
+ installOpenVPN
fi
-exit 0;