merg from upstream

This commit is contained in:
xiagw 2018-09-11 16:59:25 +08:00
commit fd35392977
3 changed files with 209 additions and 109 deletions

View file

@ -1,6 +1,7 @@
The MIT License (MIT) MIT License
Copyright (c) 2016 Nyr, Angristan Copyright (c) 2013 Nyr
Copyright (c) 2016 Angristan (Stanislas Lange)
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in

View file

@ -13,7 +13,7 @@ Here is a preview of the installer :
**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 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 $2.50/month worldwide at [Vultr](https://goo.gl/Xyd1Sc) or 3€/month for unlimited bandwidth in France at [PulseHeberg](https://goo.gl/76yqW5). 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 : First, get the script and make it executable :
@ -40,11 +40,11 @@ When OpenVPN is installed, you can run the script again, and you will get the ch
This script is based on the great work of [Nyr and its contributors](https://github.com/Nyr/openvpn-install). 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 espicially better encryption. Nyr's original script uses mainly default parameters regarding encryption, and some of them are unsecure. See [#encryption](#encryption). 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. 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 availble 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 [compatibilty](#compatibility). 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. 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.
@ -60,8 +60,9 @@ The script is made to work on these OS and architectures :
- **Debian 8** (i386, amd64) - **Debian 8** (i386, amd64)
- **Debian 9** (i386, amd64, armhf, arm64) - **Debian 9** (i386, amd64, armhf, arm64)
- **Ubuntu 14.04 LTS** (i386, amd64) - **Ubuntu 14.04 LTS** (i386, amd64)
- **Ubuntu 16.04 LTS** (i386, amd64) - **Ubuntu 16.04 LTS** (i386, amd64, armhf)
- **Ubuntu 17.10** (i386, amd64, armhf, arm64) - **Ubuntu 17.10** (i386, amd64, armhf, arm64)
- **Ubuntu 18.04 LTS** (i386, amd64, armhf, arm64)
- **Fedora 25** (amd64) - **Fedora 25** (amd64)
- **Fedora 26** (amd64) - **Fedora 26** (amd64)
- **Fedora 27** (amd64) - **Fedora 27** (amd64)
@ -87,6 +88,7 @@ This fork includes the following features :
- [Arch Linux support](https://github.com/Angristan/OpenVPN-install/pull/2) - [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. - 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 - Randomized certificate name
- The ability to create passwordless clients and clients protected with a password
- Other improvements ! - Other improvements !
## DNS ## DNS
@ -96,6 +98,7 @@ The script will ask you which DNS resolvers you want to use when connected to th
Here are the possibilities : Here are the possibilities :
- Current system resolvers, those that are in `/etc/resolv.conf` - 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) - [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) - [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) - [DNS.WATCH DNS Servers](https://dns.watch/index), recommended if you're in western europe (Germany)
@ -184,7 +187,7 @@ 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. 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 exemple 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). 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. Currently AES is only available in its CBC mode, which is weaker than GCM.
@ -212,7 +215,7 @@ Thus, the best data channel cipher currently available in OpenVPN is `AES-128-CB
### Control channel's cipher ### Control channel's cipher
According to the [Hardening](https://community.openvpn.net/openvpn/wiki/Hardening#Useof--tls-cipher) page of the OpenVPN wiki, TLS 1.2 is not supported by OpenVPN <2.3.3, so it uses a TLS 1.0 cipher by default, which is unsecure. According to the [Hardening](https://community.openvpn.net/openvpn/wiki/Hardening#Useof--tls-cipher) page of the OpenVPN wiki, TLS 1.2 is not supported by OpenVPN <2.3.3, so it uses a TLS 1.0 cipher by default, which is insecure.
> The following are TLSv1.2 DHE + RSA choices, requiring a compatible peer running at least OpenVPN 2.3.3: > The following are TLSv1.2 DHE + RSA choices, requiring a compatible peer running at least OpenVPN 2.3.3:
- TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 - TLS-DHE-RSA-WITH-AES-256-GCM-SHA384
@ -228,7 +231,7 @@ Thus, I have chosen `TLS-DHE-RSA-WITH-AES-128-GCM-SHA256` as the control channel
OpenVPN uses a 2048 bits DH key [by default](https://github.com/OpenVPN/easy-rsa/blob/master/easyrsa3/vars.example#L97). OpenVPN uses a 2048 bits DH key [by default](https://github.com/OpenVPN/easy-rsa/blob/master/easyrsa3/vars.example#L97).
2048 bits is OK, but both [NSA](https://cryptome.org/2016/01/CNSA-Suite-and-Quantum-Computing-FAQ.pdf) and [ANSSI](https://www.ssi.gouv.fr/uploads/2015/01/RGS_v-2-0_B1.pdf) recommend at least a 3072 bits for a future-proof key. Like RSA, the size of the key will have an impact on speed, I leave the choice to use a 2048, 3072 or 4096 bits key. 4096 bits is what's most used and recommened today, but 3072 bits is still good. 2048 bits is OK, but both [NSA](https://cryptome.org/2016/01/CNSA-Suite-and-Quantum-Computing-FAQ.pdf) and [ANSSI](https://www.ssi.gouv.fr/uploads/2015/01/RGS_v-2-0_B1.pdf) recommend at least a 3072 bits for a future-proof key. Like RSA, the size of the key will have an impact on speed, I leave the choice to use a 2048, 3072 or 4096 bits key. 4096 bits is what's most used and recommended today, but 3072 bits is still good.
In OpenVPN 2.4, we will be able to use ECDH key. It uses elliptic curves instead of prime numbers' factorization for a reduced key size and calculation time, thus it's faster and more secure. In OpenVPN 2.4, we will be able to use ECDH key. It uses elliptic curves instead of prime numbers' factorization for a reduced key size and calculation time, thus it's faster and more secure.
@ -253,10 +256,16 @@ 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. 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!
## Credits & Licence ## Credits & Licence
Thanks to the [contributors](https://github.com/Angristan/OpenVPN-install/graphs/contributors) and of course Nyr's orginal work. Thanks to the [contributors](https://github.com/Angristan/OpenVPN-install/graphs/contributors) and of course Nyr's orginal work.
[Old repo](https://github.com/Angristan/OpenVPN-install-fork-old)
[MIT Licence](https://raw.githubusercontent.com/Angristan/openvpn-install/master/LICENSE) [MIT Licence](https://raw.githubusercontent.com/Angristan/openvpn-install/master/LICENSE)

View file

@ -4,16 +4,19 @@
# https://github.com/Angristan/OpenVPN-install # https://github.com/Angristan/OpenVPN-install
# Verify root
if [[ "$EUID" -ne 0 ]]; then if [[ "$EUID" -ne 0 ]]; then
echo "Sorry, you need to run this as root" echo "Sorry, you need to run this as root"
exit 1 exit 1
fi fi
# Verify tun
if [[ ! -e /dev/net/tun ]]; then if [[ ! -e /dev/net/tun ]]; then
echo "TUN is not available" echo "TUN is not available"
exit 2 exit 2
fi fi
# Check if CentOS 5
if grep -qs "CentOS release 5" "/etc/redhat-release"; then if grep -qs "CentOS release 5" "/etc/redhat-release"; then
echo "CentOS 5 is too old and not supported" echo "CentOS 5 is too old and not supported"
exit 3 exit 3
@ -22,11 +25,9 @@ fi
if [[ -e /etc/debian_version ]]; then if [[ -e /etc/debian_version ]]; then
OS="debian" OS="debian"
# Getting the version number, to verify that a recent version of OpenVPN is available # Getting the version number, to verify that a recent version of OpenVPN is available
# VERSION_ID=$(cat /etc/os-release | grep "VERSION_ID")
source /etc/os-release source /etc/os-release
IPTABLES='/etc/iptables/iptables.rules' IPTABLES='/etc/iptables/iptables.rules'
SYSCTL='/etc/sysctl.conf' SYSCTL='/etc/sysctl.conf'
# if [[ "$VERSION_ID" != 'VERSION_ID="7"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="8"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="9"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="14.04"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="16.04"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="17.10"' ]]; then
case "$VERSION_ID" in case "$VERSION_ID" in
7|8|9|14.04|16.04|17.10) 7|8|9|14.04|16.04|17.10)
: :
@ -39,7 +40,7 @@ if [[ -e /etc/debian_version ]]; then
echo "then you can continue, a recent version of OpenVPN is available on these." echo "then you can continue, a recent version of OpenVPN is available on these."
echo "Keep in mind they are not supported, though." echo "Keep in mind they are not supported, though."
while [[ $CONTINUE != "y" && $CONTINUE != "n" ]]; do while [[ $CONTINUE != "y" && $CONTINUE != "n" ]]; do
read -p "Continue ? [y/n]: " -e CONTINUE read -rp "Continue ? [y/n]: " -e CONTINUE
done done
if [[ "$CONTINUE" = "n" ]]; then if [[ "$CONTINUE" = "n" ]]; then
echo "Ok, bye !" echo "Ok, bye !"
@ -66,37 +67,35 @@ fi
newclient () { newclient () {
# Where to write the custom client.ovpn? # Where to write the custom client.ovpn?
if [ -e /home/$1 ]; then # if $1 is a user name if [ -e "/home/$1" ]; then # if $1 is a user name
homeDir="/home/$1" homeDir="/home/$1"
elif [ ${SUDO_USER} ]; then # if not, use SUDO_USER elif [ "${SUDO_USER}" ]; then # if not, use SUDO_USER
homeDir="/home/${SUDO_USER}" homeDir="/home/${SUDO_USER}"
else # if not SUDO_USER, use /root else # if not SUDO_USER, use /root
homeDir="/root" homeDir="/root"
fi fi
# Generates the custom client.ovpn # Generates the custom client.ovpn
cp /etc/openvpn/client-template.txt $homeDir/$1.ovpn cp /etc/openvpn/client-template.txt "$homeDir/$1.ovpn"
echo "<ca>" >> $homeDir/$1.ovpn {
cat /etc/openvpn/easy-rsa/pki/ca.crt >> $homeDir/$1.ovpn echo "<ca>"
echo "</ca>" >> $homeDir/$1.ovpn cat "/etc/openvpn/easy-rsa/pki/ca.crt"
echo "<cert>" >> $homeDir/$1.ovpn echo "</ca>"
cat /etc/openvpn/easy-rsa/pki/issued/$1.crt >> $homeDir/$1.ovpn
echo "</cert>" >> $homeDir/$1.ovpn echo "<cert>"
echo "<key>" >> $homeDir/$1.ovpn cat "/etc/openvpn/easy-rsa/pki/issued/$1.crt"
cat /etc/openvpn/easy-rsa/pki/private/$1.key >> $homeDir/$1.ovpn echo "</cert>"
echo "</key>" >> $homeDir/$1.ovpn
echo "key-direction 1" >> $homeDir/$1.ovpn echo "<key>"
echo "<tls-auth>" >> $homeDir/$1.ovpn cat "/etc/openvpn/easy-rsa/pki/private/$1.key"
cat /etc/openvpn/tls-auth.key >> $homeDir/$1.ovpn echo "</key>"
echo "</tls-auth>" >> $homeDir/$1.ovpn echo "key-direction 1"
echo "<tls-auth>"
cat "/etc/openvpn/tls-auth.key"
echo "</tls-auth>"
} >> "$homeDir/$1.ovpn"
} }
# Try to get our IP from the system and fallback to the Internet.
# I do this to make the script compatible with NATed servers (LowEndSpirit/Scaleway)
# and to avoid getting an IPv6.
IP=$(ip addr | grep 'inet' | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -o -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1)
if [[ "$IP" = "" ]]; then
IP=$(wget -qO- ipv4.icanhazip.com)
fi
# Get Internet network interface with default route # Get Internet network interface with default route
NIC=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1) NIC=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1)
@ -108,24 +107,47 @@ if [[ -e /etc/openvpn/server.conf ]]; then
echo "" echo ""
echo "Looks like OpenVPN is already installed" echo "Looks like OpenVPN is already installed"
echo "" echo ""
echo "What do you want to do?" echo "What do you want to do?"
echo " 1) Add a cert for a new user" echo " 1) Add a cert for a new user"
echo " 2) Revoke existing user cert" echo " 2) Revoke existing user cert"
echo " 3) Remove OpenVPN" echo " 3) Remove OpenVPN"
echo " 4) Exit" echo " 4) Exit"
read -p "Select an option [1-4]: " option read -rp "Select an option [1-4]: " option
case $option in case $option in
1) 1)
echo "" echo ""
echo "Here are the files that already exist,do not repeat that" 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 ') ' 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
done
echo ""
echo "Tell me a name for the client cert" echo "Tell me a name for the client cert"
echo "Please, use one word only, no special characters" echo "Use one word only, no special characters"
read -p "Client name: " -e -i newclient CLIENT until [[ "$CLIENT" =~ ^[a-zA-Z0-9_]+$ ]]; do
read -rp "Client name: " -e CLIENT
done
cd /etc/openvpn/easy-rsa/ cd /etc/openvpn/easy-rsa/
case $pass in
1)
./easyrsa build-client-full $CLIENT nopass ./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 # Generates the custom client.ovpn
newclient "$CLIENT" newclient "$CLIENT"
echo "" echo ""
echo "Client $CLIENT added, certs available at $homeDir/$CLIENT.ovpn" echo "Client $CLIENT added, certs available at $homeDir/$CLIENT.ovpn"
exit exit
@ -137,24 +159,29 @@ if [[ -e /etc/openvpn/server.conf ]]; then
echo "You have no existing clients!" echo "You have no existing clients!"
exit 5 exit 5
fi fi
echo "" echo ""
echo "Select the existing client certificate you want to revoke" 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 ') ' tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
if [[ "$NUMBEROFCLIENTS" = '1' ]]; then if [[ "$NUMBEROFCLIENTS" = '1' ]]; then
read -p "Select one client [1]: " CLIENTNUMBER read -rp "Select one client [1]: " CLIENTNUMBER
else else
read -p "Select one client [1-$NUMBEROFCLIENTS]: " CLIENTNUMBER read -rp "Select one client [1-$NUMBEROFCLIENTS]: " CLIENTNUMBER
fi fi
CLIENT=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$CLIENTNUMBER"p) 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/ cd /etc/openvpn/easy-rsa/
./easyrsa --batch revoke $CLIENT ./easyrsa --batch revoke $CLIENT
EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
rm -rf pki/reqs/$CLIENT.req rm -f pki/reqs/$CLIENT.req
rm -rf pki/private/$CLIENT.key rm -f pki/private/$CLIENT.key
rm -rf pki/issued/$CLIENT.crt rm -f pki/issued/$CLIENT.crt
rm -rf /etc/openvpn/crl.pem rm -f /etc/openvpn/crl.pem
cp /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn/crl.pem cp /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn/crl.pem
chmod 644 /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 ""
echo "Certificate for client $CLIENT revoked" echo "Certificate for client $CLIENT revoked"
echo "Exiting..." echo "Exiting..."
@ -162,7 +189,7 @@ if [[ -e /etc/openvpn/server.conf ]]; then
;; ;;
3) 3)
echo "" echo ""
read -p "Do you really want to remove OpenVPN? [y/n]: " -e -i n REMOVE read -rp "Do you really want to remove OpenVPN? [y/n]: " -e -i n REMOVE
if [[ "$REMOVE" = 'y' ]]; then if [[ "$REMOVE" = 'y' ]]; then
PORT=$(grep '^port ' /etc/openvpn/server.conf | cut -d " " -f 2) PORT=$(grep '^port ' /etc/openvpn/server.conf | cut -d " " -f 2)
if pgrep firewalld; then if pgrep firewalld; then
@ -197,6 +224,12 @@ if [[ -e /etc/openvpn/server.conf ]]; then
else else
yum remove openvpn -y yum remove openvpn -y
fi 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 /etc/openvpn
rm -rf /usr/share/doc/openvpn* rm -rf /usr/share/doc/openvpn*
echo "" echo ""
@ -214,6 +247,7 @@ else
clear clear
echo "Welcome to the secure OpenVPN installer (github.com/Angristan/OpenVPN-install)" echo "Welcome to the secure OpenVPN installer (github.com/Angristan/OpenVPN-install)"
echo "" echo ""
# OpenVPN setup and first user creation # OpenVPN setup and first user creation
echo "I need to ask you a few questions before starting the setup" 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 "You can leave the default options and just press enter if you are ok with them"
@ -221,28 +255,59 @@ else
echo "I need to know the IPv4 address of the network interface you want OpenVPN listening to." 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 "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." echo "Otherwise, it should be your public IPv4 address."
read -p "IP address: " -e -i $IP IP
# Autodetect IP 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
echo "" echo ""
echo "What port do you want for OpenVPN?" echo "What port do you want for OpenVPN?"
read -p "Port: " -e -i 1194 PORT echo " 1) Default: 1194"
echo " 2) Custom"
echo " 3) Random [49152-65535]"
until [[ "$PORT_CHOICE" =~ ^[1-3]$ ]]; do
read -p "Port choice [1-3]: " -e -i 1 PORT_CHOICE
done
case $PORT_CHOICE in
1)
PORT="1194"
;;
2)
until [[ "$PORT" =~ ^[0-9]+$ ]] && [ "$PORT" -ge 1 -a "$PORT" -le 65535 ]; do
read -p "Custom port [1-65535]: " -e -i 1194 PORT
done
;;
3)
# Generate random number within private ports range
PORT=$(shuf -i49152-65535 -n1)
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 ""
echo "What protocol do you want for OpenVPN?" echo "What protocol do you want for OpenVPN?"
echo "Unless UDP is blocked, you should not use TCP (unnecessarily slower)" echo "Unless UDP is blocked, you should not use TCP (unnecessarily slower)"
while [[ $PROTOCOL != "UDP" && $PROTOCOL != "TCP" ]]; do until [[ "$PROTOCOL" == "UDP" || "$PROTOCOL" == "TCP" ]]; do
read -p "Protocol [UDP/TCP]: " -e -i UDP PROTOCOL read -rp "Protocol [UDP/TCP]: " -e -i UDP PROTOCOL
done done
echo "" echo ""
echo "What DNS do you want to use with the VPN?" echo "What DNS do you want to use with the VPN?"
echo " 1) Current system resolvers (from /etc/resolv.conf)" echo " 1) Current system resolvers (from /etc/resolv.conf)"
echo " 2) Quad9 (Anycast: worldwide)" echo " 2) Cloudflare (Anycast: worldwide)"
echo " 3) FDN (France)" echo " 3) Quad9 (Anycast: worldwide)"
echo " 4) DNS.WATCH (Germany)" echo " 4) FDN (France)"
echo " 5) OpenDNS (Anycast: worldwide)" echo " 5) DNS.WATCH (Germany)"
echo " 6) Google (Anycast: worldwide)" echo " 6) OpenDNS (Anycast: worldwide)"
echo " 7) Yandex Basic (Russia)" echo " 7) Google (Anycast: worldwide)"
echo " 8) AdGuard DNS (Russia)" echo " 8) Yandex Basic (Russia)"
while [[ $DNS != "1" && $DNS != "2" && $DNS != "3" && $DNS != "4" && $DNS != "5" && $DNS != "6" && $DNS != "7" && $DNS != "8" ]]; do echo " 9) AdGuard DNS (Russia)"
read -p "DNS [1-8]: " -e -i 1 DNS until [[ "$DNS" =~ ^[0-9]+$ ]] && [ "$DNS" -ge 1 -a "$DNS" -le 9 ]; do
read -rp "DNS [1-9]: " -e -i 1 DNS
done done
echo "" echo ""
echo "See https://github.com/Angristan/OpenVPN-install#encryption to learn more about " echo "See https://github.com/Angristan/OpenVPN-install#encryption to learn more about "
@ -260,8 +325,8 @@ else
echo " 5) CAMELLIA-192-CBC" echo " 5) CAMELLIA-192-CBC"
echo " 6) CAMELLIA-256-CBC" echo " 6) CAMELLIA-256-CBC"
echo " 7) SEED-CBC" echo " 7) SEED-CBC"
while [[ $CIPHER != "1" && $CIPHER != "2" && $CIPHER != "3" && $CIPHER != "4" && $CIPHER != "5" && $CIPHER != "6" && $CIPHER != "7" ]]; do until [[ "$CIPHER" =~ ^[0-9]+$ ]] && [ "$CIPHER" -ge 1 -a "$CIPHER" -le 7 ]; do
read -p "Cipher [1-7]: " -e -i 1 CIPHER read -rp "Cipher [1-7]: " -e -i 1 CIPHER
done done
case $CIPHER in case $CIPHER in
1) 1)
@ -291,8 +356,8 @@ else
echo " 1) 2048 bits (fastest)" echo " 1) 2048 bits (fastest)"
echo " 2) 3072 bits (recommended, best compromise)" echo " 2) 3072 bits (recommended, best compromise)"
echo " 3) 4096 bits (most secure)" echo " 3) 4096 bits (most secure)"
while [[ $DH_KEY_SIZE != "1" && $DH_KEY_SIZE != "2" && $DH_KEY_SIZE != "3" ]]; do until [[ "$DH_KEY_SIZE" =~ ^[0-9]+$ ]] && [ "$DH_KEY_SIZE" -ge 1 -a "$DH_KEY_SIZE" -le 3 ]; do
read -p "DH key size [1-3]: " -e -i 2 DH_KEY_SIZE read -rp "DH key size [1-3]: " -e -i 2 DH_KEY_SIZE
done done
case $DH_KEY_SIZE in case $DH_KEY_SIZE in
1) 1)
@ -310,8 +375,8 @@ else
echo " 1) 2048 bits (fastest)" echo " 1) 2048 bits (fastest)"
echo " 2) 3072 bits (recommended, best compromise)" echo " 2) 3072 bits (recommended, best compromise)"
echo " 3) 4096 bits (most secure)" echo " 3) 4096 bits (most secure)"
while [[ $RSA_KEY_SIZE != "1" && $RSA_KEY_SIZE != "2" && $RSA_KEY_SIZE != "3" ]]; do until [[ "$RSA_KEY_SIZE" =~ ^[0-9]+$ ]] && [ "$RSA_KEY_SIZE" -ge 1 -a "$RSA_KEY_SIZE" -le 3 ]; do
read -p "RSA key size [1-3]: " -e -i 2 RSA_KEY_SIZE read -rp "RSA key size [1-3]: " -e -i 2 RSA_KEY_SIZE
done done
case $RSA_KEY_SIZE in case $RSA_KEY_SIZE in
1) 1)
@ -325,17 +390,25 @@ else
;; ;;
esac esac
echo "" 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 "Finally, tell me a name for the client certificate and configuration"
while [[ $CLIENT = "" ]]; do echo "Use one word only, no special characters"
echo "Please, use one word only, no special characters" until [[ "$CLIENT" =~ ^[a-zA-Z0-9_]+$ ]]; do
read -p "Client name: " -e -i client CLIENT read -rp "Client name: " -e -i client CLIENT
done done
echo "" echo ""
echo "Okay, that was all I needed. We are ready to setup your OpenVPN server now" echo "Okay, that was all I needed. We are ready to setup your OpenVPN server now"
read -n1 -r -p "Press any key to continue..." read -n1 -r -p "Press any key to continue..."
if [[ "$OS" = 'debian' ]]; then if [[ "$OS" = 'debian' ]]; then
apt-get install ca-certificates gpg -y apt-get install ca-certificates gnupg -y
# We add the OpenVPN repo to get the latest version. # We add the OpenVPN repo to get the latest version.
# Debian 7 # Debian 7
if [[ "$VERSION_ID" = 'VERSION_ID="7"' ]]; then if [[ "$VERSION_ID" = 'VERSION_ID="7"' ]]; then
@ -436,8 +509,8 @@ WantedBy=multi-user.target" > /etc/systemd/system/iptables.service
echo "Not doing that could cause problems between dependencies, or missing files in repositories." echo "Not doing that could cause problems between dependencies, or missing files in repositories."
echo "" echo ""
echo "Continuing will update your installed packages and install needed ones." echo "Continuing will update your installed packages and install needed ones."
while [[ $CONTINUE != "y" && $CONTINUE != "n" ]]; do until [[ $CONTINUE == "y" || $CONTINUE == "n" ]]; do
read -p "Continue ? [y/n]: " -e -i y CONTINUE read -rp "Continue ? [y/n]: " -e -i y CONTINUE
done done
if [[ "$CONTINUE" = "n" ]]; then if [[ "$CONTINUE" = "n" ]]; then
echo "Ok, bye !" echo "Ok, bye !"
@ -467,14 +540,13 @@ WantedBy=multi-user.target" > /etc/systemd/system/iptables.service
# Get easy-rsa # 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 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 ~/ tar xzf ~/EasyRSA-3.0.4.tgz -C ~/
mv ~/EasyRSA-3.0.4/ /etc/openvpn/ mv ~/EasyRSA-3.0.4/ /etc/openvpn/easy-rsa/
mv /etc/openvpn/EasyRSA-3.0.4/ /etc/openvpn/easy-rsa/
chown -R root:root /etc/openvpn/easy-rsa/ chown -R root:root /etc/openvpn/easy-rsa/
rm -rf ~/EasyRSA-3.0.4.tgz rm -f ~/EasyRSA-3.0.4.tgz
cd /etc/openvpn/easy-rsa/ cd /etc/openvpn/easy-rsa/
# Generate a random, alphanumeric identifier of 16 characters for CN and one for server name # Generate a random, alphanumeric identifier of 16 characters for CN and one for server name
SERVER_CN="cn_$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)" SERVER_CN="cn_$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)"
SERVER_NAME="server_$(cat /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_KEY_SIZE $RSA_KEY_SIZE" > vars
echo "set_var EASYRSA_REQ_CN $SERVER_CN" >> 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 + client certificates
@ -482,7 +554,15 @@ WantedBy=multi-user.target" > /etc/systemd/system/iptables.service
./easyrsa --batch build-ca nopass ./easyrsa --batch build-ca nopass
openssl dhparam -out dh.pem $DH_KEY_SIZE openssl dhparam -out dh.pem $DH_KEY_SIZE
./easyrsa build-server-full $SERVER_NAME nopass ./easyrsa build-server-full $SERVER_NAME nopass
case $pass in
1)
./easyrsa build-client-full $CLIENT nopass ./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 EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
# generate tls-auth key # generate tls-auth key
openvpn --genkey --secret /etc/openvpn/tls-auth.key openvpn --genkey --secret /etc/openvpn/tls-auth.key
@ -493,11 +573,7 @@ WantedBy=multi-user.target" > /etc/systemd/system/iptables.service
# Generate server.conf # Generate server.conf
echo "port $PORT" > /etc/openvpn/server.conf echo "port $PORT" > /etc/openvpn/server.conf
if [[ "$PROTOCOL" = 'UDP' ]]; then echo "proto $(echo $PROTOCOL | tr '[:upper:]' '[:lower:]')" >> /etc/openvpn/server.conf
echo "proto udp" >> /etc/openvpn/server.conf
elif [[ "$PROTOCOL" = 'TCP' ]]; then
echo "proto tcp" >> /etc/openvpn/server.conf
fi
echo "dev tun echo "dev tun
user nobody user nobody
group $NOGROUP group $NOGROUP
@ -510,40 +586,52 @@ ifconfig-pool-persist ipp.txt" >> /etc/openvpn/server.conf
# DNS resolvers # DNS resolvers
case $DNS in case $DNS in
1) 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 # Obtain the resolvers from resolv.conf and use them for OpenVPN
grep -v '#' /etc/resolv.conf | grep 'nameserver' | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | while read line; do 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 echo "push \"dhcp-option DNS $line\"" >> /etc/openvpn/server.conf
done done
;; ;;
2) #Quad9 2) # Cloudflare
echo 'push "dhcp-option DNS 9.9.9.9"' >> /etc/openvpn/server.conf 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
;; ;;
3) #FDN 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
;;
4) # FDN
echo 'push "dhcp-option DNS 80.67.169.40"' >> /etc/openvpn/server.conf 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 echo 'push "dhcp-option DNS 80.67.169.12"' >> /etc/openvpn/server.conf
;; ;;
4) #DNS.WATCH 5) # DNS.WATCH
echo 'push "dhcp-option DNS 84.200.69.80"' >> /etc/openvpn/server.conf 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 echo 'push "dhcp-option DNS 84.200.70.40"' >> /etc/openvpn/server.conf
;; ;;
5) #OpenDNS 6) # OpenDNS
echo 'push "dhcp-option DNS 208.67.222.222"' >> /etc/openvpn/server.conf 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 echo 'push "dhcp-option DNS 208.67.220.220"' >> /etc/openvpn/server.conf
;; ;;
6) #Google 7) # Google
echo 'push "dhcp-option DNS 8.8.8.8"' >> /etc/openvpn/server.conf 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 echo 'push "dhcp-option DNS 8.8.4.4"' >> /etc/openvpn/server.conf
;; ;;
7) #Yandex Basic 8) # Yandex Basic
echo 'push "dhcp-option DNS 77.88.8.8"' >> /etc/openvpn/server.conf 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 echo 'push "dhcp-option DNS 77.88.8.1"' >> /etc/openvpn/server.conf
;; ;;
8) #AdGuard DNS 9) # AdGuard DNS
echo 'push "dhcp-option DNS 176.103.130.130"' >> /etc/openvpn/server.conf 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 echo 'push "dhcp-option DNS 176.103.130.131"' >> /etc/openvpn/server.conf
;; ;;
esac esac
echo 'push "redirect-gateway def1 bypass-dhcp" '>> /etc/openvpn/server.conf echo 'push "redirect-gateway def1 bypass-dhcp" ' >> /etc/openvpn/server.conf
echo "crl-verify crl.pem echo "crl-verify crl.pem
ca ca.crt ca ca.crt
cert $SERVER_NAME.crt cert $SERVER_NAME.crt
@ -555,9 +643,12 @@ $CIPHER
tls-server tls-server
tls-version-min 1.2 tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 tls-cipher TLS-DHE-RSA-WITH-AES-128-GCM-SHA256
status openvpn.log status /var/log/openvpn/status.log
verb 3" >> /etc/openvpn/server.conf verb 3" >> /etc/openvpn/server.conf
# Create log dir
mkdir -p /var/log/openvpn
# Create the sysctl configuration file if needed (mainly for Arch Linux) # Create the sysctl configuration file if needed (mainly for Arch Linux)
if [[ ! -e $SYSCTL ]]; then if [[ ! -e $SYSCTL ]]; then
touch $SYSCTL touch $SYSCTL
@ -568,12 +659,16 @@ verb 3" >> /etc/openvpn/server.conf
if ! grep -q "\<net.ipv4.ip_forward\>" $SYSCTL; then if ! grep -q "\<net.ipv4.ip_forward\>" $SYSCTL; then
echo 'net.ipv4.ip_forward=1' >> $SYSCTL echo 'net.ipv4.ip_forward=1' >> $SYSCTL
fi fi
# Avoid an unneeded reboot # Avoid an unneeded reboot
echo 1 > /proc/sys/net/ipv4/ip_forward echo 1 > /proc/sys/net/ipv4/ip_forward
# Set NAT for the VPN subnet # Set NAT for the VPN subnet
iptables -t nat -A POSTROUTING -o $NIC -s 10.8.0.0/24 -j MASQUERADE iptables -t nat -A POSTROUTING -o $NIC -s 10.8.0.0/24 -j MASQUERADE
# Save persitent iptables rules # Save persitent iptables rules
iptables-save > $IPTABLES iptables-save > $IPTABLES
if pgrep firewalld; then if pgrep firewalld; then
# We don't use --add-service=openvpn because that would only work with # We don't use --add-service=openvpn because that would only work with
# the default port. Using both permanent and not permanent rules to # the default port. Using both permanent and not permanent rules to
@ -588,6 +683,7 @@ verb 3" >> /etc/openvpn/server.conf
firewall-cmd --zone=trusted --add-source=10.8.0.0/24 firewall-cmd --zone=trusted --add-source=10.8.0.0/24
firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24 firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24
fi fi
if iptables -L -n | grep -qE 'REJECT|DROP'; then if iptables -L -n | grep -qE 'REJECT|DROP'; then
# If iptables has at least one REJECT rule, we asume this is needed. # 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 # Not the best approach but I can't think of other and this shouldn't
@ -602,6 +698,7 @@ verb 3" >> /etc/openvpn/server.conf
# Save persitent OpenVPN rules # Save persitent OpenVPN rules
iptables-save > $IPTABLES iptables-save > $IPTABLES
fi fi
# If SELinux is enabled and a custom port was selected, we need this # If SELinux is enabled and a custom port was selected, we need this
if hash sestatus 2>/dev/null; then if hash sestatus 2>/dev/null; then
if sestatus | grep "Current mode" | grep -qs "enforcing"; then if sestatus | grep "Current mode" | grep -qs "enforcing"; then
@ -618,6 +715,7 @@ verb 3" >> /etc/openvpn/server.conf
fi fi
fi fi
fi fi
# And finally, restart OpenVPN # And finally, restart OpenVPN
if [[ "$OS" = 'debian' ]]; then if [[ "$OS" = 'debian' ]]; then
# Little hack to check for systemd # Little hack to check for systemd
@ -650,20 +748,12 @@ verb 3" >> /etc/openvpn/server.conf
chkconfig openvpn on chkconfig openvpn on
fi fi
fi fi
# Try to detect a NATed connection and ask about it to potential LowEndSpirit/Scaleway users
EXTERNALIP=$(wget -qO- ipv4.icanhazip.com) # If the server is behind a NAT, use the correct IP address
if [[ "$IP" != "$EXTERNALIP" ]]; then if [[ "$PUBLICIP" != "" ]]; then
echo "" IP=$PUBLICIP
echo "Looks like your server is behind a NAT!"
echo ""
echo "If your server is NATed (e.g. LowEndSpirit, Scaleway, or behind a router),"
echo "then I need to know the address that can be used to access it from outside."
echo "If that's not the case, just ignore this and leave the next field blank"
read -p "External IP or domain name: " -e USEREXTERNALIP
if [[ "$USEREXTERNALIP" != "" ]]; then
IP=$USEREXTERNALIP
fi
fi fi
# client-template.txt is created so we have a template to add further users later # client-template.txt is created so we have a template to add further users later
echo "client" > /etc/openvpn/client-template.txt echo "client" > /etc/openvpn/client-template.txt
if [[ "$PROTOCOL" = 'UDP' ]]; then if [[ "$PROTOCOL" = 'UDP' ]]; then