From f057e0aa5f0cb9d9eacade8224c0a6d53af09ebe Mon Sep 17 00:00:00 2001 From: randomshell <43271778+randomshell@users.noreply.github.com> Date: Sun, 16 Sep 2018 00:53:33 +0200 Subject: [PATCH 01/18] Add self-hosted DNS resolver (Unbound) --- README.md | 2 +- openvpn-install.sh | 192 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 175 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index eccb708..785fb39 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,7 @@ The script will ask you which DNS resolvers you want to use when connected to th Here are the possibilities : - Current system resolvers, those that are in `/etc/resolv.conf` +- Self-hosted resolver thanks to Unbound - [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) @@ -106,7 +107,6 @@ Here are the possibilities : - [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 Any other fast, trustable and neutral servers proposition is welcome. diff --git a/openvpn-install.sh b/openvpn-install.sh index df14a6f..2ccd307 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -91,6 +91,109 @@ newclient () { } >> "$homeDir/$1.ovpn" } +function installLocalDNS () { + if [[ ! -e /etc/unbound/unbound.conf ]]; then + + if [[ "$OS" = "debian" ]]; then + apt-get install -y unbound + + 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 + + elif [[ "$OS" = "arch" ]]; then + # Install Unbound + pacman -Syu unbound expat + + #Permissions for the DNSSEC keys + chown root:unbound /etc/unbound + chmod 775 /etc/unbound + + # Get root servers list + wget https://www.internic.net/domain/named.root -O /etc/unbound/root.hints + + # Configuration + mv /etc/unbound/unbound.conf /etc/unbound/unbound.conf.old + echo 'server: +root-hints: root.hints +auto-trust-anchor-file: trusted-key.key +interface: 10.8.0.1 +access-control: 10.8.0.1/24 allow +port: 53 +do-daemonize: yes +num-threads: 2 +use-caps-for-id: yes +harden-glue: yes +hide-identity: yes +hide-version: yes +qname-minimisation: yes +prefetch: 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 OpenVPN integration + 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 + + if pgrep systemd-journal; then + systemctl enable unbound + systemctl start unbound + else + service unbound restart + fi +} + # Get Internet network interface with default route NIC=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1) @@ -225,6 +328,37 @@ if [[ -e /etc/openvpn/server.conf ]]; then done rm -rf /etc/openvpn rm -rf /usr/share/doc/openvpn* + + if [[ -e /etc/unbound/openvpn.conf ]]; then + + # Remove OpenVPN-related config + sed -i 's|include: \/etc\/unbound\/openvpn.conf||' /etc/unbound/unbound.conf + rm /etc/unbound/openvpn.conf + service unbound restart + + 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." + echo "You can keep using Unbound as before." + read -rp "Do you want to completely remove Unbound? [y/n]: " -e REMOVE_UNBOUND + done + + if [[ "$REMOVE_UNBOUND" = 'y' ]]; then + if [[ "$OS" = 'debian' ]]; then + apt-get autoremove --purge -y unbound + elif [[ "$OS" = 'arch' ]]; then + pacman -R unbound --noconfirm + else + yum remove unbound -y + fi + + echo "" + echo "Unbound removed!" + else + echo "" + echo "Unbound not removed!" + fi + fi echo "" echo "OpenVPN removed!" else @@ -291,16 +425,33 @@ else echo "" echo "What DNS 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 1 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 + DNS="" + CONTINUE="" + fi + fi done echo "" echo "See https://github.com/Angristan/OpenVPN-install#encryption to learn more about " @@ -591,35 +742,40 @@ ifconfig-pool-persist ipp.txt" >> /etc/openvpn/server.conf echo "push \"dhcp-option DNS $line\"" >> /etc/openvpn/server.conf done ;; - 2) # Cloudflare + 2) + # Install Unbound + installLocalDNS + echo 'push "dhcp-option DNS 10.8.0.1"' >> /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 ;; - 3) # Quad9 + 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 ;; - 4) # FDN + 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 ;; - 5) # DNS.WATCH + 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 ;; - 6) # OpenDNS + 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 ;; - 7) # Google + 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 ;; - 8) # Yandex Basic + 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 ;; - 9) # AdGuard DNS + 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 ;; From 62380c512b2185f5459816d0d3b26eade5078b61 Mon Sep 17 00:00:00 2001 From: angristan Date: Sun, 16 Sep 2018 01:26:30 +0200 Subject: [PATCH 02/18] Drop CentOS 6 support --- README.md | 1 - openvpn-install.sh | 25 ++++++++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 785fb39..10fc377 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,6 @@ The script is made to work on these OS and architectures : - **Fedora 25** (amd64) - **Fedora 26** (amd64) - **Fedora 27** (amd64) -- **CentOS 6** (i386, amd64) - **CentOS 7** (i386, amd64, arm64) - **Arch Linux** (i686, amd64, arm64) diff --git a/openvpn-install.sh b/openvpn-install.sh index 2ccd307..fe614bf 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -16,12 +16,6 @@ if [[ ! -e /dev/net/tun ]]; then 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 @@ -36,10 +30,10 @@ if [[ -e /etc/debian_version ]]; then 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 + read -rp "Continue? [y/n]: " -e CONTINUE done if [[ "$CONTINUE" = "n" ]]; then - echo "Ok, bye !" + echo "Ok, bye!" exit 4 fi fi @@ -47,7 +41,20 @@ 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 +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 "" + unset CONTINUE + while [[ $CONTINUE != "y" && $CONTINUE != "n" ]]; do + read -rp "Continue anyway? [y/n]: " -e CONTINUE + done + if [[ "$CONTINUE" = "n" ]]; then + echo "Ok, bye!" + exit 5 + fi + fi OS=centos IPTABLES='/etc/iptables/iptables.rules' SYSCTL='/etc/sysctl.conf' From 320944177593087201baf9176077a054f56fe2bb Mon Sep 17 00:00:00 2001 From: angristan Date: Sun, 16 Sep 2018 01:26:37 +0200 Subject: [PATCH 03/18] Better bash --- openvpn-install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openvpn-install.sh b/openvpn-install.sh index fe614bf..dd5a273 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -455,8 +455,8 @@ else read -rp "Apply configuration changes to Unbound? [y/n]: " -e CONTINUE done if [[ $CONTINUE = "n" ]];then - DNS="" - CONTINUE="" + unset DNS + unset CONTINUE fi fi done From 8a5de575b7b177f51b2c37d3f473a77ab4f8d29a Mon Sep 17 00:00:00 2001 From: angristan Date: Sun, 16 Sep 2018 01:29:04 +0200 Subject: [PATCH 04/18] Drop Debian 7 support Debian 7 is EOL and I can't test it on cloud providers anymore --- README.md | 1 - openvpn-install.sh | 8 +------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/README.md b/README.md index 10fc377..323d897 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,6 @@ On the client-side, it's less problematic, but if you want to use an OpenVPN ser 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) diff --git a/openvpn-install.sh b/openvpn-install.sh index dd5a273..9605b83 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -22,7 +22,7 @@ if [[ -e /etc/debian_version ]]; then VERSION_ID=$(grep "VERSION_ID" /etc/os-release) IPTABLES='/etc/iptables/iptables.rules' 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"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="18.04"' ]]; then + if [[ "$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"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="18.04"' ]]; then echo "Your version of Debian/Ubuntu is not supported." echo "I can't install a recent version of OpenVPN on your system." echo "" @@ -561,12 +561,6 @@ else if [[ "$OS" = 'debian' ]]; then 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 From f6c9a63e384a5f66d419796e50ce1fe487c3b04d Mon Sep 17 00:00:00 2001 From: angristan Date: Sun, 16 Sep 2018 01:34:01 +0200 Subject: [PATCH 05/18] Drop support for Arch Linux Arch Linux isn't very used and is not available on cloud providers. I cannot test it easily so it is a burden to maintain for me --- README.md | 1 - openvpn-install.sh | 70 ++++------------------------------------------ 2 files changed, 5 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index 323d897..e089b09 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,6 @@ The script is made to work on these OS and architectures : - **Fedora 26** (amd64) - **Fedora 27** (amd64) - **CentOS 7** (i386, amd64, arm64) -- **Arch Linux** (i686, amd64, arm64) (It should also work on Debian unstable/testing and Ubuntu beta). diff --git a/openvpn-install.sh b/openvpn-install.sh index 9605b83..aeb20ea 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Secure OpenVPN server installer for Debian, Ubuntu, CentOS and Arch Linux +# Secure OpenVPN server installer for Debian, Ubuntu, CentOS and Fedora # https://github.com/Angristan/OpenVPN-install @@ -58,12 +58,8 @@ elif [[ -e /etc/centos-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" + echo "Looks like you aren't running this installer on a Debian, Ubuntu, Fedora or CentOS system" exit 4 fi @@ -130,34 +126,6 @@ prefetch: yes' >> /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" = "arch" ]]; then - # Install Unbound - pacman -Syu unbound expat - - #Permissions for the DNSSEC keys - chown root:unbound /etc/unbound - chmod 775 /etc/unbound - - # Get root servers list - wget https://www.internic.net/domain/named.root -O /etc/unbound/root.hints - - # Configuration - mv /etc/unbound/unbound.conf /etc/unbound/unbound.conf.old - echo 'server: -root-hints: root.hints -auto-trust-anchor-file: trusted-key.key -interface: 10.8.0.1 -access-control: 10.8.0.1/24 allow -port: 53 -do-daemonize: yes -num-threads: 2 -use-caps-for-id: yes -harden-glue: yes -hide-identity: yes -hide-version: yes -qname-minimisation: yes -prefetch: yes' > /etc/unbound/unbound.conf fi if [[ ! "$OS" =~ (fedora|centos) ]];then @@ -322,8 +290,6 @@ if [[ -e /etc/openvpn/server.conf ]]; then 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 @@ -353,8 +319,6 @@ if [[ -e /etc/openvpn/server.conf ]]; then if [[ "$REMOVE_UNBOUND" = 'y' ]]; then if [[ "$OS" = 'debian' ]]; then apt-get autoremove --purge -y unbound - elif [[ "$OS" = 'arch' ]]; then - pacman -R unbound --noconfirm else yum remove unbound -y fi @@ -646,30 +610,6 @@ WantedBy=multi-user.target" > /etc/systemd/system/iptables.service 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 fi # Find out if the machine uses nogroup or nobody for the permissionless group if grep -qs "^nogroup:" /etc/group; then @@ -799,7 +739,7 @@ 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 if [[ ! -e $SYSCTL ]]; then touch $SYSCTL fi @@ -882,8 +822,8 @@ mkdir -p /var/log/openvpn fi else if pgrep systemd-journal; then - if [[ "$OS" = 'arch' || "$OS" = 'fedora' ]]; then - #Workaround to avoid rewriting the entire script for Arch & Fedora + if [[ "$OS" = 'fedora' ]]; then + # Workaround to avoid rewriting the entire script for 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 From 019da89be993b99fb99a7811e913b97d0840f319 Mon Sep 17 00:00:00 2001 From: angristan Date: Sun, 16 Sep 2018 01:49:39 +0200 Subject: [PATCH 06/18] Update Fedora compatibility Remove EOL --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index e089b09..6edd1c2 100644 --- a/README.md +++ b/README.md @@ -62,9 +62,8 @@ The script is made to work on these OS and architectures : - **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) +- **Fedora 28** (amd64) - **CentOS 7** (i386, amd64, arm64) (It should also work on Debian unstable/testing and Ubuntu beta). From bfed14544ecc23273171ef0adf3b0811b077196c Mon Sep 17 00:00:00 2001 From: Stanislas Date: Sun, 16 Sep 2018 17:55:50 +0200 Subject: [PATCH 07/18] Add IPv6 NAT support (#238) --- README.md | 1 + openvpn-install.sh | 88 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 70 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 6edd1c2..03ee9ed 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,7 @@ This fork includes the following features : - Better encryption, see below - Better DNS resolvers, see below - Choice between TCP and UDP (UDP is still recommended) +- IPv6 (NATed) support - 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) diff --git a/openvpn-install.sh b/openvpn-install.sh index aeb20ea..11839de 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -280,6 +280,9 @@ if [[ -e /etc/openvpn/server.conf ]]; then iptables-save > $IPTABLES fi iptables -t nat -D POSTROUTING -o $NIC -s 10.8.0.0/24 -j MASQUERADE + if [[ "$IPV6" = 'y' ]]; then + ip6tables -t nat -D POSTROUTING -o $NIC -s fd42:42:42:42::/112 -j MASQUERADE + fi iptables-save > $IPTABLES if hash sestatus 2>/dev/null; then if sestatus | grep "Current mode" | grep -qs "enforcing"; then @@ -357,6 +360,25 @@ else # 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 + # 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 "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." + else + echo "Your host does not appear to have IPv6 connectivity." + fi + echo "" + while [[ $IPV6 != "y" && $IPV6 != "n" ]]; do + read -rp "Do you want to enable IPv6 support? [y/n]: " -e IPV6 + done echo "" echo "What port do you want for OpenVPN?" echo " 1) Default: 1194" @@ -380,13 +402,6 @@ 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)" @@ -523,13 +538,14 @@ else read -n1 -r -p "Press any key to continue..." 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 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 + apt-get update fi # Ubuntu 14.04 if [[ "$VERSION_ID" = 'VERSION_ID="14.04"' ]]; then @@ -658,7 +674,19 @@ 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" = 'n' ]]; then + if [[ "$PROTOCOL" = 'UDP' ]]; then + echo "proto udp" >> /etc/openvpn/server.conf + elif [[ "$PROTOCOL" = 'TCP' ]]; then + echo "proto tcp" >> /etc/openvpn/server.conf + fi + elif [[ "$IPV6" = 'y' ]]; then + if [[ "$PROTOCOL" = 'UDP' ]]; then + echo "proto udp6" >> /etc/openvpn/server.conf + elif [[ "$PROTOCOL" = 'TCP' ]]; then + echo "proto tcp6" >> /etc/openvpn/server.conf + fi + fi echo "dev tun user nobody group $NOGROUP @@ -721,8 +749,17 @@ ifconfig-pool-persist ipp.txt" >> /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 + + if [[ "$IPV6" = '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 @@ -744,18 +781,19 @@ mkdir -p /var/log/openvpn touch $SYSCTL 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 + # Enable routing + echo 'net.ipv4.ip_forward=1' >> $SYSCTL + if [[ "$IPV6" = 'y' ]]; then + echo 'net.ipv6.conf.all.forwarding=1' >> $SYSCTL fi # Avoid an unneeded reboot - echo 1 > /proc/sys/net/ipv4/ip_forward - + sysctl --system # Set NAT for the VPN subnet iptables -t nat -A POSTROUTING -o $NIC -s 10.8.0.0/24 -j MASQUERADE - + if [[ "$IPV6" = 'y' ]]; then + ip6tables -t nat -A POSTROUTING -o $NIC -s fd42:42:42:42::/112 -j MASQUERADE + fi # Save persitent iptables rules iptables-save > $IPTABLES @@ -788,7 +826,19 @@ mkdir -p /var/log/openvpn # Save persitent OpenVPN rules iptables-save > $IPTABLES fi - + if [[ "$IPV6" = 'y' ]]; then + if ip6tables -L -n | grep -qE 'REJECT|DROP'; then + if [[ "$PROTOCOL" = 'UDP' ]]; then + ip6tables -I INPUT -p udp --dport $PORT -j ACCEPT + elif [[ "$PROTOCOL" = 'TCP' ]]; then + ip6tables -I INPUT -p tcp --dport $PORT -j ACCEPT + fi + ip6tables -I FORWARD -s fd42:42:42:42::/112 -j ACCEPT + ip6tables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT + # Save persitent OpenVPN rules + iptables-save > $IPTABLES + fi + fi # 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 From d6d209ef8c2a1ad83c7409ec09c5cad4679020c3 Mon Sep 17 00:00:00 2001 From: angristan Date: Sun, 16 Sep 2018 18:07:05 +0200 Subject: [PATCH 08/18] Add FAQ: How to manage script updates --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 03ee9ed..bd08a1f 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,16 @@ Here are the possibilities : Any other fast, trustable and neutral servers proposition is welcome. +## FAQ + +**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. + +--- + ## Encryption The main reason why I made this fork is to improve the encryption. Indeed, OpenVPN's default parameters are weak (and that's what [Nyr's script](https://github.com/Nyr/openvpn-install) uses). From 18b025e83144700f6fb34d20fdb8fa1a769ed3fa Mon Sep 17 00:00:00 2001 From: angristan Date: Sun, 16 Sep 2018 22:45:04 +0200 Subject: [PATCH 09/18] Improve sysctl config --- openvpn-install.sh | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/openvpn-install.sh b/openvpn-install.sh index 11839de..4df46f3 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -21,7 +21,6 @@ if [[ -e /etc/debian_version ]]; then # Getting the version number, to verify that a recent version of OpenVPN is available VERSION_ID=$(grep "VERSION_ID" /etc/os-release) IPTABLES='/etc/iptables/iptables.rules' - SYSCTL='/etc/sysctl.conf' if [[ "$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"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="18.04"' ]]; then echo "Your version of Debian/Ubuntu is not supported." echo "I can't install a recent version of OpenVPN on your system." @@ -40,7 +39,6 @@ if [[ -e /etc/debian_version ]]; then elif [[ -e /etc/fedora-release ]]; then OS=fedora IPTABLES='/etc/iptables/iptables.rules' - SYSCTL='/etc/sysctl.d/openvpn.conf' 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." @@ -57,7 +55,6 @@ elif [[ -e /etc/centos-release ]]; then fi OS=centos IPTABLES='/etc/iptables/iptables.rules' - SYSCTL='/etc/sysctl.conf' else echo "Looks like you aren't running this installer on a Debian, Ubuntu, Fedora or CentOS system" exit 4 @@ -297,13 +294,13 @@ if [[ -e /etc/openvpn/server.conf ]]; then 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 + 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 if [[ -e /etc/unbound/openvpn.conf ]]; then @@ -773,18 +770,13 @@ 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 the sysctl configuration file if needed - if [[ ! -e $SYSCTL ]]; then - touch $SYSCTL - fi + # Create log dir + mkdir -p /var/log/openvpn # Enable routing - echo 'net.ipv4.ip_forward=1' >> $SYSCTL + echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.d/20-openvpn.conf if [[ "$IPV6" = 'y' ]]; then - echo 'net.ipv6.conf.all.forwarding=1' >> $SYSCTL + echo 'net.ipv6.conf.all.forwarding=1' >> /etc/sysctl.d/20-openvpn.conf fi # Avoid an unneeded reboot From 594486c1772f84c3a4461000dcf6583d32eac68f Mon Sep 17 00:00:00 2001 From: Stanislas Date: Mon, 17 Sep 2018 01:11:30 +0200 Subject: [PATCH 10/18] Rework iptables handling (#291) --- README.md | 1 - openvpn-install.sh | 210 ++++++++++++++++----------------------------- 2 files changed, 73 insertions(+), 138 deletions(-) diff --git a/README.md b/README.md index bd08a1f..8261de0 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,6 @@ The script is made to work on these OS and architectures : - **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) diff --git a/openvpn-install.sh b/openvpn-install.sh index 4df46f3..dca1d3f 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -21,7 +21,7 @@ if [[ -e /etc/debian_version ]]; then # Getting the version number, to verify that a recent version of OpenVPN is available VERSION_ID=$(grep "VERSION_ID" /etc/os-release) IPTABLES='/etc/iptables/iptables.rules' - if [[ "$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"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="18.04"' ]]; then + if [[ "$VERSION_ID" != 'VERSION_ID="8"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="9"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="16.04"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="17.10"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="18.04"' ]]; then echo "Your version of Debian/Ubuntu is not supported." echo "I can't install a recent version of OpenVPN on your system." echo "" @@ -260,27 +260,16 @@ if [[ -e /etc/openvpn/server.conf ]]; then 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 - if [[ "$IPV6" = 'y' ]]; then - ip6tables -t nat -D POSTROUTING -o $NIC -s fd42:42:42:42::/112 -j MASQUERADE - fi - iptables-save > $IPTABLES + + # Remove ipatbles 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 + if hash sestatus 2>/dev/null; then if sestatus | grep "Current mode" | grep -qs "enforcing"; then if [[ "$PORT" != '1194' ]]; then @@ -544,86 +533,82 @@ else wget -O - https://swupdate.openvpn.net/repos/repo-public.gpg | apt-key add - apt-get 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 + fi + + # Install iptables service + mkdir /etc/iptables + + # Script to add rules + echo "#!/bin/sh +iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE +iptables -A INPUT -i tun0 -j ACCEPT +iptables -A FORWARD -i eth0 -o tun0 -j ACCEPT +iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT" > /etc/iptables/add-openvpn-rules.sh + + if [[ "$PROTOCOL" = 'UDP' ]]; then + echo "iptables -A INPUT -i eth0 -p udp --dport $PORT -j ACCEPT" >> /etc/iptables/add-openvpn-rules.sh + elif [[ "$PROTOCOL" = 'TCP' ]]; then + echo "iptables -A INPUT -i eth0 -p tcp --dport $PORT -j ACCEPT" >> /etc/iptables/add-openvpn-rules.sh + fi + + if [[ "$IPV6" = 'y' ]]; then + echo "ip6tables -t nat -A POSTROUTING -s fd42:42:42:42::/112 -o eth0 -j MASQUERADE +ip6tables -A INPUT -i tun0 -j ACCEPT +ip6tables -A FORWARD -i eth0 -o tun0 -j ACCEPT +ip6tables -A FORWARD -i tun0 -o eth0 -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 eth0 -j MASQUERADE +iptables -D INPUT -i tun0 -j ACCEPT +iptables -D FORWARD -i eth0 -o tun0 -j ACCEPT +iptables -D FORWARD -i tun0 -o eth0 -j ACCEPT" > /etc/iptables/rm-openvpn-rules.sh + + if [[ "$PROTOCOL" = 'UDP' ]]; then + echo "iptables -D INPUT -i eth0 -p udp --dport $PORT -j ACCEPT" >> /etc/iptables/rm-openvpn-rules.sh + elif [[ "$PROTOCOL" = 'TCP' ]]; then + echo "iptables -D INPUT -i eth0 -p tcp --dport $PORT -j ACCEPT" >> /etc/iptables/rm-openvpn-rules.sh + fi + + if [[ "$IPV6" = 'y' ]]; then + echo "ip6tables -t nat -D POSTROUTING -s fd42:42:42:42::/112 -o eth0 -j MASQUERADE +ip6tables -D INPUT -i tun0 -j ACCEPT +ip6tables -D FORWARD -i eth0 -o tun0 -j ACCEPT +ip6tables -D FORWARD -i tun0 -o eth0 -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=/sbin/iptables-restore /etc/iptables/iptables.rules -ExecReload=/sbin/iptables-restore /etc/iptables/iptables.rules -ExecStop=/etc/iptables/flush-iptables.sh +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.service - systemctl daemon-reload - systemctl enable iptables.service - # Disable firewalld to allow iptables to start upon reboot - systemctl disable firewalld - systemctl mask firewalld - fi - fi +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 + # Find out if the machine uses nogroup or nobody for the permissionless group if grep -qs "^nogroup:" /etc/group; then NOGROUP=nogroup @@ -781,56 +766,7 @@ verb 3" >> /etc/openvpn/server.conf # Avoid an unneeded reboot sysctl --system - # Set NAT for the VPN subnet - iptables -t nat -A POSTROUTING -o $NIC -s 10.8.0.0/24 -j MASQUERADE - if [[ "$IPV6" = 'y' ]]; then - ip6tables -t nat -A POSTROUTING -o $NIC -s fd42:42:42:42::/112 -j MASQUERADE - fi - # 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 - if [[ "$IPV6" = 'y' ]]; then - if ip6tables -L -n | grep -qE 'REJECT|DROP'; then - if [[ "$PROTOCOL" = 'UDP' ]]; then - ip6tables -I INPUT -p udp --dport $PORT -j ACCEPT - elif [[ "$PROTOCOL" = 'TCP' ]]; then - ip6tables -I INPUT -p tcp --dport $PORT -j ACCEPT - fi - ip6tables -I FORWARD -s fd42:42:42:42::/112 -j ACCEPT - ip6tables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT - # Save persitent OpenVPN rules - iptables-save > $IPTABLES - fi - fi # 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 From da909ce13db1e65b14fa3b42a15098400de77475 Mon Sep 17 00:00:00 2001 From: angristan Date: Mon, 17 Sep 2018 01:23:39 +0200 Subject: [PATCH 11/18] Add some notes about .ovpn files --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8261de0..8698c26 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,8 @@ When OpenVPN is installed, you can run the script again, and you will get the ch ![](https://i.imgur.com/AlW9g7t.png) +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. + ## The fork This script is based on the great work of [Nyr and its contributors](https://github.com/Nyr/openvpn-install). From 6210c64d10b589e906b4c1e42c8d50b103028557 Mon Sep 17 00:00:00 2001 From: angristan Date: Mon, 17 Sep 2018 01:24:23 +0200 Subject: [PATCH 12/18] Fix broken link in the README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8698c26..c4a3f32 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ This fork includes the following features : - Better DNS resolvers, see below - Choice between TCP and UDP (UDP is still recommended) - IPv6 (NATed) support -- Run server in [unprivileged mode](https://github.com/Angristan/OpenVPN-install/blob/master/openvpn-install.sh#L426), reducing risks to the system +- Run server in unprivileged mode, 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) From 974b80dbc1bb03e18f0b7f9deabeb3c664befb4e Mon Sep 17 00:00:00 2001 From: angristan Date: Mon, 17 Sep 2018 18:05:51 +0200 Subject: [PATCH 13/18] Remove unused variables --- openvpn-install.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/openvpn-install.sh b/openvpn-install.sh index dca1d3f..f4e7acf 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -20,7 +20,6 @@ if [[ -e /etc/debian_version ]]; then OS="debian" # Getting the version number, to verify that a recent version of OpenVPN is available VERSION_ID=$(grep "VERSION_ID" /etc/os-release) - IPTABLES='/etc/iptables/iptables.rules' if [[ "$VERSION_ID" != 'VERSION_ID="8"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="9"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="16.04"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="17.10"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="18.04"' ]]; then echo "Your version of Debian/Ubuntu is not supported." echo "I can't install a recent version of OpenVPN on your system." @@ -38,7 +37,6 @@ if [[ -e /etc/debian_version ]]; then fi elif [[ -e /etc/fedora-release ]]; then OS=fedora - IPTABLES='/etc/iptables/iptables.rules' 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." @@ -54,7 +52,6 @@ elif [[ -e /etc/centos-release ]]; then fi fi OS=centos - IPTABLES='/etc/iptables/iptables.rules' else echo "Looks like you aren't running this installer on a Debian, Ubuntu, Fedora or CentOS system" exit 4 From d3974220ef1cdac141bfcaa67c8c4e31581a892a Mon Sep 17 00:00:00 2001 From: angristan Date: Tue, 18 Sep 2018 12:37:07 +0200 Subject: [PATCH 14/18] Fix public interface in iptables rules --- openvpn-install.sh | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/openvpn-install.sh b/openvpn-install.sh index f4e7acf..f4c8ac1 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -545,42 +545,42 @@ else # Script to add rules echo "#!/bin/sh -iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE +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 eth0 -o tun0 -j ACCEPT -iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT" > /etc/iptables/add-openvpn-rules.sh +iptables -A FORWARD -i $NIC -o tun0 -j ACCEPT +iptables -A FORWARD -i tun0 -o $NIC -j ACCEPT" > /etc/iptables/add-openvpn-rules.sh if [[ "$PROTOCOL" = 'UDP' ]]; then - echo "iptables -A INPUT -i eth0 -p udp --dport $PORT -j ACCEPT" >> /etc/iptables/add-openvpn-rules.sh + echo "iptables -A INPUT -i $NIC -p udp --dport $PORT -j ACCEPT" >> /etc/iptables/add-openvpn-rules.sh elif [[ "$PROTOCOL" = 'TCP' ]]; then - echo "iptables -A INPUT -i eth0 -p tcp --dport $PORT -j ACCEPT" >> /etc/iptables/add-openvpn-rules.sh + echo "iptables -A INPUT -i $NIC -p tcp --dport $PORT -j ACCEPT" >> /etc/iptables/add-openvpn-rules.sh fi if [[ "$IPV6" = 'y' ]]; then - echo "ip6tables -t nat -A POSTROUTING -s fd42:42:42:42::/112 -o eth0 -j MASQUERADE + 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 eth0 -o tun0 -j ACCEPT -ip6tables -A FORWARD -i tun0 -o eth0 -j ACCEPT" >> /etc/iptables/add-openvpn-rules.sh +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 eth0 -j MASQUERADE +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 eth0 -o tun0 -j ACCEPT -iptables -D FORWARD -i tun0 -o eth0 -j ACCEPT" > /etc/iptables/rm-openvpn-rules.sh +iptables -D FORWARD -i $NIC -o tun0 -j ACCEPT +iptables -D FORWARD -i tun0 -o $NIC -j ACCEPT" > /etc/iptables/rm-openvpn-rules.sh if [[ "$PROTOCOL" = 'UDP' ]]; then - echo "iptables -D INPUT -i eth0 -p udp --dport $PORT -j ACCEPT" >> /etc/iptables/rm-openvpn-rules.sh + echo "iptables -D INPUT -i $NIC -p udp --dport $PORT -j ACCEPT" >> /etc/iptables/rm-openvpn-rules.sh elif [[ "$PROTOCOL" = 'TCP' ]]; then - echo "iptables -D INPUT -i eth0 -p tcp --dport $PORT -j ACCEPT" >> /etc/iptables/rm-openvpn-rules.sh + echo "iptables -D INPUT -i $NIC -p tcp --dport $PORT -j ACCEPT" >> /etc/iptables/rm-openvpn-rules.sh fi if [[ "$IPV6" = 'y' ]]; then - echo "ip6tables -t nat -D POSTROUTING -s fd42:42:42:42::/112 -o eth0 -j MASQUERADE + 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 eth0 -o tun0 -j ACCEPT -ip6tables -D FORWARD -i tun0 -o eth0 -j ACCEPT" >> /etc/iptables/rm-openvpn-rules.sh +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 From 1cd80a5cc743651e12e295c3d6d44f834f310dbf Mon Sep 17 00:00:00 2001 From: angristan Date: Tue, 18 Sep 2018 14:26:00 +0200 Subject: [PATCH 15/18] Add Hetzner/IPv6 to FAQ --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index c4a3f32..ffa1fb6 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,12 @@ You can, of course, it's even recommended, update the `openvpn` package with you --- +**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 The main reason why I made this fork is to improve the encryption. Indeed, OpenVPN's default parameters are weak (and that's what [Nyr's script](https://github.com/Nyr/openvpn-install) uses). From 136a46874e6575fe6da373cc2b4591b94bcf79ad Mon Sep 17 00:00:00 2001 From: Stanislas Date: Tue, 18 Sep 2018 14:55:00 +0200 Subject: [PATCH 16/18] Rework and cleanup systemd service handling (#294) * Don't hardcode server.conf in systemd service * Rework and cleanup service handling --- openvpn-install.sh | 46 ++++++++++++++++------------------------------ 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/openvpn-install.sh b/openvpn-install.sh index f4c8ac1..a2ca315 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -781,37 +781,23 @@ verb 3" >> /etc/openvpn/server.conf 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" = 'fedora' ]]; then - # Workaround to avoid rewriting the entire script for 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 From e920f7fbc2f924cd0a4ab13e1b953ca985f69065 Mon Sep 17 00:00:00 2001 From: Stanislas Date: Thu, 20 Sep 2018 00:05:02 +0200 Subject: [PATCH 17/18] Refactoring, cleanup and fixes (#293) --- README.md | 18 +- openvpn-install.sh | 1120 ++++++++++++++++++++++---------------------- 2 files changed, 569 insertions(+), 569 deletions(-) diff --git a/README.md b/README.md index ffa1fb6..1914ba5 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ This script will let you setup your own secure VPN server in just a few minutes. Here is a preview of the installer : -![](https://lut.im/IzjFrfhM18/DY8KD91W0uMhEgLp.png) -![](https://lut.im/eODTn8Sa9y/euCqh0wzXwlz3UNs.png) +![previw_1](https://lut.im/IzjFrfhM18/DY8KD91W0uMhEgLp.png) +![preview_2](https://lut.im/eODTn8Sa9y/euCqh0wzXwlz3UNs.png) ## Usage @@ -34,7 +34,7 @@ When OpenVPN is installed, you can run the script again, and you will get the ch - Remove a client - Uninstall OpenVPN -![](https://i.imgur.com/AlW9g7t.png) +![preview_3](https://i.imgur.com/AlW9g7t.png) 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. @@ -56,7 +56,7 @@ On the client-side, it's less problematic, but if you want to use an OpenVPN ser ## Compatibility -The script is made to work on these OS and architectures : +The script supports these OS and architectures: - **Debian 8** (i386, amd64) - **Debian 9** (i386, amd64, armhf, arm64) @@ -69,7 +69,7 @@ The script is made to work on these OS and architectures : (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. +The script requires `systemd`. ## Features @@ -82,7 +82,7 @@ This fork includes the following features : - IPv6 (NATed) support - Run server in unprivileged mode, 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) +- No compression, 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 @@ -201,8 +201,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) : @@ -216,10 +214,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)). diff --git a/openvpn-install.sh b/openvpn-install.sh index a2ca315..183b0b5 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -3,97 +3,81 @@ # Secure OpenVPN server installer for Debian, Ubuntu, CentOS and Fedora # https://github.com/Angristan/OpenVPN-install +# Functions -# 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 - -if [[ -e /etc/debian_version ]]; then - OS="debian" - # Getting the version number, to verify that a recent version of OpenVPN is available - VERSION_ID=$(grep "VERSION_ID" /etc/os-release) - if [[ "$VERSION_ID" != 'VERSION_ID="8"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="9"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="16.04"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="17.10"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="18.04"' ]]; then - 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 +function isRoot () { + if [ "$EUID" -ne 0 ]; then + return 1 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 "" - unset CONTINUE - while [[ $CONTINUE != "y" && $CONTINUE != "n" ]]; do - read -rp "Continue anyway? [y/n]: " -e CONTINUE - done - if [[ "$CONTINUE" = "n" ]]; then - echo "Ok, bye!" - exit 5 - fi - fi - OS=centos -else - echo "Looks like you aren't running this installer on a Debian, Ubuntu, Fedora or CentOS 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" - 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" } -function installLocalDNS () { +function tunAvailable () { + if [ ! -e /dev/net/tun ]; then + return 1 + fi +} + +function checkOS () { + if [[ -e /etc/debian_version ]]; then + OS="debian" + # Getting the version number, to verify that a recent version of OpenVPN is available + VERSION_ID=$(grep "VERSION_ID" /etc/os-release) + if [[ "$VERSION_ID" != 'VERSION_ID="8"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="9"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="16.04"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="17.10"' ]] && [[ "$VERSION_ID" != 'VERSION_ID="18.04"' ]]; then + echo "Your version of Debian/Ubuntu is not supported." + echo "" + echo "However, if you're using Debian unstable/testing, or Ubuntu beta," + echo "then you can continue." + 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 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 "" + unset CONTINUE + while [[ $CONTINUE != "y" && $CONTINUE != "n" ]]; do + read -rp "Continue anyway? [y/n]: " -e CONTINUE + done + 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 +} + +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 +} + +function installUnbound () { if [[ ! -e /etc/unbound/unbound.conf ]]; then 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 @@ -125,19 +109,18 @@ prefetch: yes' >> /etc/unbound/unbound.conf 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 +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 + else # Unbound is already installed echo 'include: /etc/unbound/openvpn.conf' >> /etc/unbound/unbound.conf - # Add OpenVPN integration + # Add Unbound 'server' for the OpenVPN subnet echo 'server: interface: 10.8.0.1 access-control: 10.8.0.1/24 allow @@ -155,192 +138,23 @@ private-address: 127.0.0.0/8 private-address: ::ffff:0:0/96' > /etc/unbound/openvpn.conf fi - if pgrep systemd-journal; then systemctl enable unbound - systemctl start unbound - else - service unbound restart - fi + systemctl restart unbound } -# Get Internet network interface with default route -NIC=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1) - -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) - 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 "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 - 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 - 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 - 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" - 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) - - # Remove ipatbles 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 - - 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 - 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* - rm -f /etc/sysctl.d/20-openvpn.conf - - if [[ -e /etc/unbound/openvpn.conf ]]; then - - # Remove OpenVPN-related config - sed -i 's|include: \/etc\/unbound\/openvpn.conf||' /etc/unbound/unbound.conf - rm /etc/unbound/openvpn.conf - service unbound restart - - 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." - echo "You can keep using Unbound as before." - read -rp "Do you want to completely remove Unbound? [y/n]: " -e REMOVE_UNBOUND - done - - if [[ "$REMOVE_UNBOUND" = 'y' ]]; then - if [[ "$OS" = 'debian' ]]; then - apt-get autoremove --purge -y unbound - else - yum remove unbound -y - fi - - echo "" - echo "Unbound removed!" - else - echo "" - echo "Unbound not removed!" - fi - fi - 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)" +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 @@ -349,21 +163,25 @@ else 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 "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 "" - while [[ $IPV6 != "y" && $IPV6 != "n" ]]; do - read -rp "Do you want to enable IPv6 support? [y/n]: " -e IPV6 + # 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 for OpenVPN?" + echo "What port do you want OpenVPN to listen to?" echo " 1) Default: 1194" echo " 2) Custom" echo " 3) Random [49152-65535]" @@ -386,13 +204,23 @@ else ;; esac 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) Self-hosted DNS Resolver (Unbound)" echo " 3) Cloudflare (Anycast: worldwide)" @@ -404,7 +232,7 @@ else 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 1 DNS + read -rp "DNS [1-10]: " -e -i 3 DNS if [[ $DNS == 2 ]] && [[ -e /etc/unbound/unbound.conf ]]; then echo "" echo "Unbound is already installed." @@ -417,6 +245,7 @@ else 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 @@ -427,41 +256,23 @@ else 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 "" @@ -469,78 +280,242 @@ 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 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-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 - 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 + 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 - # Install iptables service + # Find out if the machine uses nogroup or nobody for the permissionless group + if grep -qs "^nogroup:" /etc/group; then + NOGROUP=nogroup + else + NOGROUP=nobody + fi + + # An old version of easy-rsa was available by default in some openvpn packages + if [[ -d /etc/openvpn/easy-rsa/ ]]; then + rm -rf /etc/openvpn/easy-rsa/ + fi + + # 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-${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 certificate + ./easyrsa init-pki + ./easyrsa --batch build-ca nopass + openssl dhparam -out dh.pem $DH_KEY_SIZE + ./easyrsa build-server-full $SERVER_NAME nopass + EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl + # 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 + # Make cert revocation list readable for non-root + chmod 644 /etc/openvpn/crl.pem + + # Generate server.conf + echo "port $PORT" > /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 +persist-key +persist-tun +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 + ;; + 2) + echo 'push "dhcp-option DNS 10.8.0.1"' >> /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) # 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) # 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) # 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) # 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) # 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) # 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 + + # 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 +tls-auth tls-auth.key 0 +dh dh.pem +auth SHA256 +$CIPHER +tls-server +tls-version-min 1.2 +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 + + # 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 + # Avoid an unneeded reboot + 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 port -a -t openvpn_port_t -p $PROTOCOL $PORT + fi + fi + 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 + # 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 [[ $DNS == 2 ]];then + installUnbound + fi + + # Add iptables rules in two scripts mkdir /etc/iptables # Script to add rules @@ -548,15 +523,10 @@ else 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" > /etc/iptables/add-openvpn-rules.sh +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 [[ "$PROTOCOL" = 'UDP' ]]; then - echo "iptables -A INPUT -i $NIC -p udp --dport $PORT -j ACCEPT" >> /etc/iptables/add-openvpn-rules.sh - elif [[ "$PROTOCOL" = 'TCP' ]]; then - echo "iptables -A INPUT -i $NIC -p tcp --dport $PORT -j ACCEPT" >> /etc/iptables/add-openvpn-rules.sh - fi - - if [[ "$IPV6" = 'y' ]]; then + 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 @@ -568,15 +538,10 @@ ip6tables -A FORWARD -i tun0 -o $NIC -j ACCEPT" >> /etc/iptables/add-openvpn-rul 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" > /etc/iptables/rm-openvpn-rules.sh +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 [[ "$PROTOCOL" = 'UDP' ]]; then - echo "iptables -D INPUT -i $NIC -p udp --dport $PORT -j ACCEPT" >> /etc/iptables/rm-openvpn-rules.sh - elif [[ "$PROTOCOL" = 'TCP' ]]; then - echo "iptables -D INPUT -i $NIC -p tcp --dport $PORT -j ACCEPT" >> /etc/iptables/rm-openvpn-rules.sh - fi - - if [[ "$IPV6" = 'y' ]]; then + 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 @@ -606,210 +571,16 @@ WantedBy=multi-user.target" > /etc/systemd/system/iptables-openvpn.service systemctl enable iptables-openvpn systemctl start iptables-openvpn - # Find out if the machine uses nogroup or nobody for the permissionless group - if grep -qs "^nogroup:" /etc/group; then - NOGROUP=nogroup - else - NOGROUP=nobody - fi - - # An old version of easy-rsa was available by default in some openvpn packages - 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/ - chown -R root:root /etc/openvpn/easy-rsa/ - rm -f ~/EasyRSA-3.0.4.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 - ./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 - 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 - # Make cert revocation list readable for non-root - chmod 644 /etc/openvpn/crl.pem - - # Generate server.conf - echo "port $PORT" > /etc/openvpn/server.conf - if [[ "$IPV6" = 'n' ]]; then - if [[ "$PROTOCOL" = 'UDP' ]]; then - echo "proto udp" >> /etc/openvpn/server.conf - elif [[ "$PROTOCOL" = 'TCP' ]]; then - echo "proto tcp" >> /etc/openvpn/server.conf - fi - elif [[ "$IPV6" = 'y' ]]; then - if [[ "$PROTOCOL" = 'UDP' ]]; then - echo "proto udp6" >> /etc/openvpn/server.conf - elif [[ "$PROTOCOL" = 'TCP' ]]; then - echo "proto tcp6" >> /etc/openvpn/server.conf - fi - fi - echo "dev tun -user nobody -group $NOGROUP -persist-key -persist-tun -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 - ;; - 2) - # Install Unbound - installLocalDNS - echo 'push "dhcp-option DNS 10.8.0.1"' >> /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) # 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) # 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) # 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) # 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) # 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) # 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 - - if [[ "$IPV6" = '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 -tls-auth tls-auth.key 0 -dh dh.pem -auth SHA256 -$CIPHER -tls-server -tls-version-min 1.2 -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 - - # Enable routing - echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.d/20-openvpn.conf - if [[ "$IPV6" = 'y' ]]; then - echo 'net.ipv6.conf.all.forwarding=1' >> /etc/sysctl.d/20-openvpn.conf - fi - - # Avoid an unneeded reboot - 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 - fi - fi - 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 - # 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 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 @@ -830,11 +601,246 @@ setenv opt block-outside-dns 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 +} + +# Main + +# 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; From 0a5c3c1401ade216a95d30887c7144f14cae56b0 Mon Sep 17 00:00:00 2001 From: angristan Date: Thu, 20 Sep 2018 17:16:04 +0200 Subject: [PATCH 18/18] Rewrite README --- README.md | 115 ++++++++++++++++++--------------------------- openvpn-install.sh | 8 +--- 2 files changed, 48 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index 1914ba5..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 : - -![previw_1](https://lut.im/IzjFrfhM18/DY8KD91W0uMhEgLp.png) -![preview_2](https://lut.im/eODTn8Sa9y/euCqh0wzXwlz3UNs.png) - ## 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,25 +29,24 @@ When OpenVPN is installed, you can run the script again, and you will get the ch - Remove a client - Uninstall OpenVPN -![preview_3](https://i.imgur.com/AlW9g7t.png) - 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. -## The fork +## Features -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.** +- 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! ## Compatibility @@ -67,49 +61,30 @@ The script supports these OS and architectures: - **Fedora 28** (amd64) - **CentOS 7** (i386, amd64, arm64) -(It should also work on Debian unstable/testing and Ubuntu beta). +To be noted: -The script requires `systemd`. +- It should also work on Debian unstable/testing and Ubuntu beta. +- The script requires `systemd`. +- The script is regularly tested against `amd64` only. -## Features +## Fork -This fork includes the following features : +This script is based on the great work of [Nyr and its contributors](https://github.com/Nyr/openvpn-install). -- 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) -- IPv6 (NATed) support -- Run server in unprivileged mode, reducing risks to the system -- [Block DNS leak on Windows 10](https://community.openvpn.net/openvpn/ticket/605) -- No compression, 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 ! - -## DNS - -The script will ask you which DNS resolvers you want to use when connected to the VPN. - -Here are the possibilities : - -- Current system resolvers, those that are in `/etc/resolv.conf` -- Self-hosted resolver thanks to Unbound -- [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 - -Any other fast, trustable and neutral servers proposition is welcome. +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. @@ -118,6 +93,12 @@ You can, of course, it's even recommended, update the `openvpn` package with you --- +**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). @@ -264,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 183b0b5..064d301 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -1,9 +1,7 @@ #!/bin/bash # Secure OpenVPN server installer for Debian, Ubuntu, CentOS and Fedora -# https://github.com/Angristan/OpenVPN-install - -# Functions +# https://github.com/angristan/openvpn-install function isRoot () { if [ "$EUID" -ne 0 ]; then @@ -597,7 +595,7 @@ $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 @@ -833,8 +831,6 @@ function manageMenu () { esac } -# Main - # Check for root, TUN, OS... initialCheck