sufehmi

OpenVPN Easy Install

Sep 15th, 2020
185
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 23.09 KB | None | 0 0
  1. #!/bin/bash
  2. #
  3. # https://github.com/Nyr/openvpn-install
  4. #
  5. # Copyright (c) 2013 Nyr. Released under the MIT License.
  6.  
  7.  
  8. # Detect Debian users running the script with "sh" instead of bash
  9. if readlink /proc/$$/exe | grep -q "dash"; then
  10.     echo 'This installer needs to be run with "bash", not "sh".'
  11.     exit
  12. fi
  13.  
  14. # Discard stdin. Needed when running from an one-liner which includes a newline
  15. read -N 999999 -t 0.001
  16.  
  17. # Detect OpenVZ 6
  18. if [[ $(uname -r | cut -d "." -f 1) -eq 2 ]]; then
  19.     echo "The system is running an old kernel, which is incompatible with this installer."
  20.     exit
  21. fi
  22.  
  23. # Detect OS
  24. # $os_version variables aren't always in use, but are kept here for convenience
  25. if grep -qs "ubuntu" /etc/os-release; then
  26.     os="ubuntu"
  27.     os_version=$(grep 'VERSION_ID' /etc/os-release | cut -d '"' -f 2 | tr -d '.')
  28.     group_name="nogroup"
  29. elif [[ -e /etc/debian_version ]]; then
  30.     os="debian"
  31.     os_version=$(grep -oE '[0-9]+' /etc/debian_version | head -1)
  32.     group_name="nogroup"
  33. elif [[ -e /etc/centos-release ]]; then
  34.     os="centos"
  35.     os_version=$(grep -oE '[0-9]+' /etc/centos-release | head -1)
  36.     group_name="nobody"
  37. elif [[ -e /etc/fedora-release ]]; then
  38.     os="fedora"
  39.     os_version=$(grep -oE '[0-9]+' /etc/fedora-release | head -1)
  40.     group_name="nobody"
  41. else
  42.     echo "This installer seems to be running on an unsupported distribution.
  43. Supported distributions are Ubuntu, Debian, CentOS, and Fedora."
  44.     exit
  45. fi
  46.  
  47. if [[ "$os" == "ubuntu" && "$os_version" -lt 1804 ]]; then
  48.     echo "Ubuntu 18.04 or higher is required to use this installer.
  49. This version of Ubuntu is too old and unsupported."
  50.     exit
  51. fi
  52.  
  53. if [[ "$os" == "debian" && "$os_version" -lt 9 ]]; then
  54.     echo "Debian 9 or higher is required to use this installer.
  55. This version of Debian is too old and unsupported."
  56.     exit
  57. fi
  58.  
  59. if [[ "$os" == "centos" && "$os_version" -lt 7 ]]; then
  60.     echo "CentOS 7 or higher is required to use this installer.
  61. This version of CentOS is too old and unsupported."
  62.     exit
  63. fi
  64.  
  65. # Detect environments where $PATH does not include the sbin directories
  66. if ! grep -q sbin <<< "$PATH"; then
  67.     echo '$PATH does not include sbin. Try using "su -" instead of "su".'
  68.     exit
  69. fi
  70.  
  71. if [[ "$EUID" -ne 0 ]]; then
  72.     echo "This installer needs to be run with superuser privileges."
  73.     exit
  74. fi
  75.  
  76. if [[ ! -e /dev/net/tun ]] || ! ( exec 7<>/dev/net/tun ) 2>/dev/null; then
  77.     echo "The system does not have the TUN device available.
  78. TUN needs to be enabled before running this installer."
  79.     exit
  80. fi
  81.  
  82. new_client () {
  83.     # Generates the custom client.ovpn
  84.     {
  85.     cat /etc/openvpn/server/client-common.txt
  86.     echo "<ca>"
  87.     cat /etc/openvpn/server/easy-rsa/pki/ca.crt
  88.     echo "</ca>"
  89.     echo "<cert>"
  90.     sed -ne '/BEGIN CERTIFICATE/,$ p' /etc/openvpn/server/easy-rsa/pki/issued/"$client".crt
  91.     echo "</cert>"
  92.     echo "<key>"
  93.     cat /etc/openvpn/server/easy-rsa/pki/private/"$client".key
  94.     echo "</key>"
  95.     echo "<tls-crypt>"
  96.     sed -ne '/BEGIN OpenVPN Static key/,$ p' /etc/openvpn/server/tc.key
  97.     echo "</tls-crypt>"
  98.     } > ~/"$client".ovpn
  99. }
  100.  
  101. if [[ ! -e /etc/openvpn/server/server.conf ]]; then
  102.     clear
  103.     echo 'Welcome to this OpenVPN road warrior installer!'
  104.     # If system has a single IPv4, it is selected automatically. Else, ask the user
  105.     if [[ $(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}') -eq 1 ]]; then
  106.         ip=$(ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}')
  107.     else
  108.         number_of_ip=$(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}')
  109.         echo
  110.         echo "Which IPv4 address should be used?"
  111.         ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | nl -s ') '
  112.         read -p "IPv4 address [1]: " ip_number
  113.         until [[ -z "$ip_number" || "$ip_number" =~ ^[0-9]+$ && "$ip_number" -le "$number_of_ip" ]]; do
  114.             echo "$ip_number: invalid selection."
  115.             read -p "IPv4 address [1]: " ip_number
  116.         done
  117.         [[ -z "$ip_number" ]] && ip_number="1"
  118.         ip=$(ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | sed -n "$ip_number"p)
  119.     fi
  120.     # If $ip is a private IP address, the server must be behind NAT
  121.     if echo "$ip" | grep -qE '^(10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|192\.168)'; then
  122.         echo
  123.         echo "This server is behind NAT. What is the public IPv4 address or hostname?"
  124.         # Get public IP and sanitize with grep
  125.         get_public_ip=$(grep -m 1 -oE '^[0-9]{1,3}(\.[0-9]{1,3}){3}$' <<< "$(wget -T 10 -t 1 -4qO- "http://ip1.dynupdate.no-ip.com/" || curl -m 10 -4Ls "http://ip1.dynupdate.no-ip.com/")")
  126.         read -p "Public IPv4 address / hostname [$get_public_ip]: " public_ip
  127.         # If the checkip service is unavailable and user didn't provide input, ask again
  128.         until [[ -n "$get_public_ip" || -n "$public_ip" ]]; do
  129.             echo "Invalid input."
  130.             read -p "Public IPv4 address / hostname: " public_ip
  131.         done
  132.         [[ -z "$public_ip" ]] && public_ip="$get_public_ip"
  133.     fi
  134.     # If system has a single IPv6, it is selected automatically
  135.     if [[ $(ip -6 addr | grep -c 'inet6 [23]') -eq 1 ]]; then
  136.         ip6=$(ip -6 addr | grep 'inet6 [23]' | cut -d '/' -f 1 | grep -oE '([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}')
  137.     fi
  138.     # If system has multiple IPv6, ask the user to select one
  139.     if [[ $(ip -6 addr | grep -c 'inet6 [23]') -gt 1 ]]; then
  140.         number_of_ip6=$(ip -6 addr | grep -c 'inet6 [23]')
  141.         echo
  142.         echo "Which IPv6 address should be used?"
  143.         ip -6 addr | grep 'inet6 [23]' | cut -d '/' -f 1 | grep -oE '([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}' | nl -s ') '
  144.         read -p "IPv6 address [1]: " ip6_number
  145.         until [[ -z "$ip6_number" || "$ip6_number" =~ ^[0-9]+$ && "$ip6_number" -le "$number_of_ip6" ]]; do
  146.             echo "$ip6_number: invalid selection."
  147.             read -p "IPv6 address [1]: " ip6_number
  148.         done
  149.         [[ -z "$ip6_number" ]] && ip6_number="1"
  150.         ip6=$(ip -6 addr | grep 'inet6 [23]' | cut -d '/' -f 1 | grep -oE '([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}' | sed -n "$ip6_number"p)
  151.     fi
  152.     echo
  153.     echo "Which protocol should OpenVPN use?"
  154.     echo "   1) UDP (recommended)"
  155.     echo "   2) TCP"
  156.     read -p "Protocol [1]: " protocol
  157.     until [[ -z "$protocol" || "$protocol" =~ ^[12]$ ]]; do
  158.         echo "$protocol: invalid selection."
  159.         read -p "Protocol [1]: " protocol
  160.     done
  161.     case "$protocol" in
  162.         1|"")
  163.         protocol=udp
  164.         ;;
  165.         2)
  166.         protocol=tcp
  167.         ;;
  168.     esac
  169.     echo
  170.     echo "What port should OpenVPN listen to?"
  171.     read -p "Port [1194]: " port
  172.     until [[ -z "$port" || "$port" =~ ^[0-9]+$ && "$port" -le 65535 ]]; do
  173.         echo "$port: invalid port."
  174.         read -p "Port [1194]: " port
  175.     done
  176.     [[ -z "$port" ]] && port="1194"
  177.     echo
  178.     echo "Select a DNS server for the clients:"
  179.     echo "   1) Current system resolvers"
  180.     echo "   2) Google"
  181.     echo "   3) 1.1.1.1"
  182.     echo "   4) OpenDNS"
  183.     echo "   5) Quad9"
  184.     echo "   6) AdGuard"
  185.     read -p "DNS server [1]: " dns
  186.     until [[ -z "$dns" || "$dns" =~ ^[1-6]$ ]]; do
  187.         echo "$dns: invalid selection."
  188.         read -p "DNS server [1]: " dns
  189.     done
  190.     echo
  191.     echo "Enter a name for the first client:"
  192.     read -p "Name [client]: " unsanitized_client
  193.     # Allow a limited set of characters to avoid conflicts
  194.     client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")
  195.     [[ -z "$client" ]] && client="client"
  196.     echo
  197.     echo "OpenVPN installation is ready to begin."
  198.     # Install a firewall in the rare case where one is not already available
  199.     if ! systemctl is-active --quiet firewalld.service && ! hash iptables 2>/dev/null; then
  200.         if [[ "$os" == "centos" || "$os" == "fedora" ]]; then
  201.             firewall="firewalld"
  202.             # We don't want to silently enable firewalld, so we give a subtle warning
  203.             # If the user continues, firewalld will be installed and enabled during setup
  204.             echo "firewalld, which is required to manage routing tables, will also be installed."
  205.         elif [[ "$os" == "debian" || "$os" == "ubuntu" ]]; then
  206.             # iptables is way less invasive than firewalld so no warning is given
  207.             firewall="iptables"
  208.         fi
  209.     fi
  210.     read -n1 -r -p "Press any key to continue..."
  211.     # If running inside a container, disable LimitNPROC to prevent conflicts
  212.     if systemd-detect-virt -cq; then
  213.         mkdir /etc/systemd/system/openvpn-server@server.service.d/ 2>/dev/null
  214.         echo "[Service]
  215. LimitNPROC=infinity" > /etc/systemd/system/openvpn-server@server.service.d/disable-limitnproc.conf
  216.     fi
  217.     if [[ "$os" = "debian" || "$os" = "ubuntu" ]]; then
  218.         apt-get update
  219.         apt-get install -y openvpn openssl ca-certificates $firewall
  220.     elif [[ "$os" = "centos" ]]; then
  221.         yum install -y epel-release
  222.         yum install -y openvpn openssl ca-certificates tar $firewall
  223.     else
  224.         # Else, OS must be Fedora
  225.         dnf install -y openvpn openssl ca-certificates tar $firewall
  226.     fi
  227.     # If firewalld was just installed, enable it
  228.     if [[ "$firewall" == "firewalld" ]]; then
  229.         systemctl enable --now firewalld.service
  230.     fi
  231.     # Get easy-rsa
  232.     easy_rsa_url='https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.8/EasyRSA-3.0.8.tgz'
  233.     mkdir -p /etc/openvpn/server/easy-rsa/
  234.     { wget -qO- "$easy_rsa_url" 2>/dev/null || curl -sL "$easy_rsa_url" ; } | tar xz -C /etc/openvpn/server/easy-rsa/ --strip-components 1
  235.     chown -R root:root /etc/openvpn/server/easy-rsa/
  236.     cd /etc/openvpn/server/easy-rsa/
  237.     # Create the PKI, set up the CA and the server and client certificates
  238.     ./easyrsa init-pki
  239.     ./easyrsa --batch build-ca nopass
  240.     EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-server-full server nopass
  241.     EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full "$client" nopass
  242.     EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
  243.     # Move the stuff we need
  244.     cp pki/ca.crt pki/private/ca.key pki/issued/server.crt pki/private/server.key pki/crl.pem /etc/openvpn/server
  245.     # CRL is read with each client connection, while OpenVPN is dropped to nobody
  246.     chown nobody:"$group_name" /etc/openvpn/server/crl.pem
  247.     # Without +x in the directory, OpenVPN can't run a stat() on the CRL file
  248.     chmod o+x /etc/openvpn/server/
  249.     # Generate key for tls-crypt
  250.     openvpn --genkey --secret /etc/openvpn/server/tc.key
  251.     # Create the DH parameters file using the predefined ffdhe2048 group
  252.     echo '-----BEGIN DH PARAMETERS-----
  253. MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
  254. +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
  255. 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
  256. YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
  257. 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
  258. ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
  259. -----END DH PARAMETERS-----' > /etc/openvpn/server/dh.pem
  260.     # Generate server.conf
  261.     echo "local $ip
  262. port $port
  263. proto $protocol
  264. dev tun
  265. ca ca.crt
  266. cert server.crt
  267. key server.key
  268. dh dh.pem
  269. auth SHA512
  270. tls-crypt tc.key
  271. topology subnet
  272. server 10.8.0.0 255.255.255.0" > /etc/openvpn/server/server.conf
  273.     # IPv6
  274.     if [[ -z "$ip6" ]]; then
  275.         echo 'push "redirect-gateway def1 bypass-dhcp"' >> /etc/openvpn/server/server.conf
  276.     else
  277.         echo 'server-ipv6 fddd:1194:1194:1194::/64' >> /etc/openvpn/server/server.conf
  278.         echo 'push "redirect-gateway def1 ipv6 bypass-dhcp"' >> /etc/openvpn/server/server.conf
  279.     fi
  280.     echo 'ifconfig-pool-persist ipp.txt' >> /etc/openvpn/server/server.conf
  281.     # DNS
  282.     case "$dns" in
  283.         1|"")
  284.             # Locate the proper resolv.conf
  285.             # Needed for systems running systemd-resolved
  286.             if grep -q '^nameserver 127.0.0.53' "/etc/resolv.conf"; then
  287.                 resolv_conf="/run/systemd/resolve/resolv.conf"
  288.             else
  289.                 resolv_conf="/etc/resolv.conf"
  290.             fi
  291.             # Obtain the resolvers from resolv.conf and use them for OpenVPN
  292.             grep -v '^#\|^;' "$resolv_conf" | grep '^nameserver' | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | while read line; do
  293.                 echo "push \"dhcp-option DNS $line\"" >> /etc/openvpn/server/server.conf
  294.             done
  295.         ;;
  296.         2)
  297.             echo 'push "dhcp-option DNS 8.8.8.8"' >> /etc/openvpn/server/server.conf
  298.             echo 'push "dhcp-option DNS 8.8.4.4"' >> /etc/openvpn/server/server.conf
  299.         ;;
  300.         3)
  301.             echo 'push "dhcp-option DNS 1.1.1.1"' >> /etc/openvpn/server/server.conf
  302.             echo 'push "dhcp-option DNS 1.0.0.1"' >> /etc/openvpn/server/server.conf
  303.         ;;
  304.         4)
  305.             echo 'push "dhcp-option DNS 208.67.222.222"' >> /etc/openvpn/server/server.conf
  306.             echo 'push "dhcp-option DNS 208.67.220.220"' >> /etc/openvpn/server/server.conf
  307.         ;;
  308.         5)
  309.             echo 'push "dhcp-option DNS 9.9.9.9"' >> /etc/openvpn/server/server.conf
  310.             echo 'push "dhcp-option DNS 149.112.112.112"' >> /etc/openvpn/server/server.conf
  311.         ;;
  312.         6)
  313.             echo 'push "dhcp-option DNS 176.103.130.130"' >> /etc/openvpn/server/server.conf
  314.             echo 'push "dhcp-option DNS 176.103.130.131"' >> /etc/openvpn/server/server.conf
  315.         ;;
  316.     esac
  317.     echo "keepalive 10 120
  318. cipher AES-256-CBC
  319. user nobody
  320. group $group_name
  321. persist-key
  322. persist-tun
  323. status openvpn-status.log
  324. verb 3
  325. crl-verify crl.pem" >> /etc/openvpn/server/server.conf
  326.     if [[ "$protocol" = "udp" ]]; then
  327.         echo "explicit-exit-notify" >> /etc/openvpn/server/server.conf
  328.     fi
  329.     # Enable net.ipv4.ip_forward for the system
  330.     echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/30-openvpn-forward.conf
  331.     # Enable without waiting for a reboot or service restart
  332.     echo 1 > /proc/sys/net/ipv4/ip_forward
  333.     if [[ -n "$ip6" ]]; then
  334.         # Enable net.ipv6.conf.all.forwarding for the system
  335.         echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.d/30-openvpn-forward.conf
  336.         # Enable without waiting for a reboot or service restart
  337.         echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
  338.     fi
  339.     if systemctl is-active --quiet firewalld.service; then
  340.         # Using both permanent and not permanent rules to avoid a firewalld
  341.         # reload.
  342.         # We don't use --add-service=openvpn because that would only work with
  343.         # the default port and protocol.
  344.         firewall-cmd --add-port="$port"/"$protocol"
  345.         firewall-cmd --zone=trusted --add-source=10.8.0.0/24
  346.         firewall-cmd --permanent --add-port="$port"/"$protocol"
  347.         firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24
  348.         # Set NAT for the VPN subnet
  349.         firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip"
  350.         firewall-cmd --permanent --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip"
  351.         if [[ -n "$ip6" ]]; then
  352.             firewall-cmd --zone=trusted --add-source=fddd:1194:1194:1194::/64
  353.             firewall-cmd --permanent --zone=trusted --add-source=fddd:1194:1194:1194::/64
  354.             firewall-cmd --direct --add-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to "$ip6"
  355.             firewall-cmd --permanent --direct --add-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to "$ip6"
  356.         fi
  357.     else
  358.         # Create a service to set up persistent iptables rules
  359.         iptables_path=$(command -v iptables)
  360.         ip6tables_path=$(command -v ip6tables)
  361.         # nf_tables is not available as standard in OVZ kernels. So use iptables-legacy
  362.         # if we are in OVZ, with a nf_tables backend and iptables-legacy is available.
  363.         if [[ $(systemd-detect-virt) == "openvz" ]] && readlink -f "$(command -v iptables)" | grep -q "nft" && hash iptables-legacy 2>/dev/null; then
  364.             iptables_path=$(command -v iptables-legacy)
  365.             ip6tables_path=$(command -v ip6tables-legacy)
  366.         fi
  367.         echo "[Unit]
  368. Before=network.target
  369. [Service]
  370. Type=oneshot
  371. ExecStart=$iptables_path -t nat -A POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $ip
  372. ExecStart=$iptables_path -I INPUT -p $protocol --dport $port -j ACCEPT
  373. ExecStart=$iptables_path -I FORWARD -s 10.8.0.0/24 -j ACCEPT
  374. ExecStart=$iptables_path -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
  375. ExecStop=$iptables_path -t nat -D POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $ip
  376. ExecStop=$iptables_path -D INPUT -p $protocol --dport $port -j ACCEPT
  377. ExecStop=$iptables_path -D FORWARD -s 10.8.0.0/24 -j ACCEPT
  378. ExecStop=$iptables_path -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT" > /etc/systemd/system/openvpn-iptables.service
  379.         if [[ -n "$ip6" ]]; then
  380.             echo "ExecStart=$ip6tables_path -t nat -A POSTROUTING -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to $ip6
  381. ExecStart=$ip6tables_path -I FORWARD -s fddd:1194:1194:1194::/64 -j ACCEPT
  382. ExecStart=$ip6tables_path -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
  383. ExecStop=$ip6tables_path -t nat -D POSTROUTING -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to $ip6
  384. ExecStop=$ip6tables_path -D FORWARD -s fddd:1194:1194:1194::/64 -j ACCEPT
  385. ExecStop=$ip6tables_path -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT" >> /etc/systemd/system/openvpn-iptables.service
  386.         fi
  387.         echo "RemainAfterExit=yes
  388. [Install]
  389. WantedBy=multi-user.target" >> /etc/systemd/system/openvpn-iptables.service
  390.         systemctl enable --now openvpn-iptables.service
  391.     fi
  392.     # If SELinux is enabled and a custom port was selected, we need this
  393.     if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$port" != 1194 ]]; then
  394.         # Install semanage if not already present
  395.         if ! hash semanage 2>/dev/null; then
  396.             if [[ "$os_version" -eq 7 ]]; then
  397.                 # Centos 7
  398.                 yum install -y policycoreutils-python
  399.             else
  400.                 # CentOS 8 or Fedora
  401.                 dnf install -y policycoreutils-python-utils
  402.             fi
  403.         fi
  404.         semanage port -a -t openvpn_port_t -p "$protocol" "$port"
  405.     fi
  406.     # If the server is behind NAT, use the correct IP address
  407.     [[ -n "$public_ip" ]] && ip="$public_ip"
  408.     # client-common.txt is created so we have a template to add further users later
  409.     echo "client
  410. dev tun
  411. proto $protocol
  412. remote $ip $port
  413. resolv-retry infinite
  414. nobind
  415. persist-key
  416. persist-tun
  417. remote-cert-tls server
  418. auth SHA512
  419. cipher AES-256-CBC
  420. ignore-unknown-option block-outside-dns
  421. block-outside-dns
  422. verb 3" > /etc/openvpn/server/client-common.txt
  423.     # Enable and start the OpenVPN service
  424.     systemctl enable --now openvpn-server@server.service
  425.     # Generates the custom client.ovpn
  426.     new_client
  427.     echo
  428.     echo "Finished!"
  429.     echo
  430.     echo "The client configuration is available in:" ~/"$client.ovpn"
  431.     echo "New clients can be added by running this script again."
  432. else
  433.     clear
  434.     echo "OpenVPN is already installed."
  435.     echo
  436.     echo "Select an option:"
  437.     echo "   1) Add a new client"
  438.     echo "   2) Revoke an existing client"
  439.     echo "   3) Remove OpenVPN"
  440.     echo "   4) Exit"
  441.     read -p "Option: " option
  442.     until [[ "$option" =~ ^[1-4]$ ]]; do
  443.         echo "$option: invalid selection."
  444.         read -p "Option: " option
  445.     done
  446.     case "$option" in
  447.         1)
  448.             echo
  449.             echo "Provide a name for the client:"
  450.             read -p "Name: " unsanitized_client
  451.             client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")
  452.             while [[ -z "$client" || -e /etc/openvpn/server/easy-rsa/pki/issued/"$client".crt ]]; do
  453.                 echo "$client: invalid name."
  454.                 read -p "Name: " unsanitized_client
  455.                 client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")
  456.             done
  457.             cd /etc/openvpn/server/easy-rsa/
  458.             EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full "$client" nopass
  459.             # Generates the custom client.ovpn
  460.             new_client
  461.             echo
  462.             echo "$client added. Configuration available in:" ~/"$client.ovpn"
  463.             exit
  464.         ;;
  465.         2)
  466.             # This option could be documented a bit better and maybe even be simplified
  467.             # ...but what can I say, I want some sleep too
  468.             number_of_clients=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -c "^V")
  469.             if [[ "$number_of_clients" = 0 ]]; then
  470.                 echo
  471.                 echo "There are no existing clients!"
  472.                 exit
  473.             fi
  474.             echo
  475.             echo "Select the client to revoke:"
  476.             tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
  477.             read -p "Client: " client_number
  478.             until [[ "$client_number" =~ ^[0-9]+$ && "$client_number" -le "$number_of_clients" ]]; do
  479.                 echo "$client_number: invalid selection."
  480.                 read -p "Client: " client_number
  481.             done
  482.             client=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$client_number"p)
  483.             echo
  484.             read -p "Confirm $client revocation? [y/N]: " revoke
  485.             until [[ "$revoke" =~ ^[yYnN]*$ ]]; do
  486.                 echo "$revoke: invalid selection."
  487.                 read -p "Confirm $client revocation? [y/N]: " revoke
  488.             done
  489.             if [[ "$revoke" =~ ^[yY]$ ]]; then
  490.                 cd /etc/openvpn/server/easy-rsa/
  491.                 ./easyrsa --batch revoke "$client"
  492.                 EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
  493.                 rm -f /etc/openvpn/server/crl.pem
  494.                 cp /etc/openvpn/server/easy-rsa/pki/crl.pem /etc/openvpn/server/crl.pem
  495.                 # CRL is read with each client connection, when OpenVPN is dropped to nobody
  496.                 chown nobody:"$group_name" /etc/openvpn/server/crl.pem
  497.                 echo
  498.                 echo "$client revoked!"
  499.             else
  500.                 echo
  501.                 echo "$client revocation aborted!"
  502.             fi
  503.             exit
  504.         ;;
  505.         3)
  506.             echo
  507.             read -p "Confirm OpenVPN removal? [y/N]: " remove
  508.             until [[ "$remove" =~ ^[yYnN]*$ ]]; do
  509.                 echo "$remove: invalid selection."
  510.                 read -p "Confirm OpenVPN removal? [y/N]: " remove
  511.             done
  512.             if [[ "$remove" =~ ^[yY]$ ]]; then
  513.                 port=$(grep '^port ' /etc/openvpn/server/server.conf | cut -d " " -f 2)
  514.                 protocol=$(grep '^proto ' /etc/openvpn/server/server.conf | cut -d " " -f 2)
  515.                 if systemctl is-active --quiet firewalld.service; then
  516.                     ip=$(firewall-cmd --direct --get-rules ipv4 nat POSTROUTING | grep '\-s 10.8.0.0/24 '"'"'!'"'"' -d 10.8.0.0/24' | grep -oE '[^ ]+$')
  517.                     # Using both permanent and not permanent rules to avoid a firewalld reload.
  518.                     firewall-cmd --remove-port="$port"/"$protocol"
  519.                     firewall-cmd --zone=trusted --remove-source=10.8.0.0/24
  520.                     firewall-cmd --permanent --remove-port="$port"/"$protocol"
  521.                     firewall-cmd --permanent --zone=trusted --remove-source=10.8.0.0/24
  522.                     firewall-cmd --direct --remove-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip"
  523.                     firewall-cmd --permanent --direct --remove-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip"
  524.                     if grep -qs "server-ipv6" /etc/openvpn/server/server.conf; then
  525.                         ip6=$(firewall-cmd --direct --get-rules ipv6 nat POSTROUTING | grep '\-s fddd:1194:1194:1194::/64 '"'"'!'"'"' -d fddd:1194:1194:1194::/64' | grep -oE '[^ ]+$')
  526.                         firewall-cmd --zone=trusted --remove-source=fddd:1194:1194:1194::/64
  527.                         firewall-cmd --permanent --zone=trusted --remove-source=fddd:1194:1194:1194::/64
  528.                         firewall-cmd --direct --remove-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to "$ip6"
  529.                         firewall-cmd --permanent --direct --remove-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to "$ip6"
  530.                     fi
  531.                 else
  532.                     systemctl disable --now openvpn-iptables.service
  533.                     rm -f /etc/systemd/system/openvpn-iptables.service
  534.                 fi
  535.                 if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$port" != 1194 ]]; then
  536.                     semanage port -d -t openvpn_port_t -p "$protocol" "$port"
  537.                 fi
  538.                 systemctl disable --now openvpn-server@server.service
  539.                 rm -rf /etc/openvpn/server
  540.                 rm -f /etc/systemd/system/openvpn-server@server.service.d/disable-limitnproc.conf
  541.                 rm -f /etc/sysctl.d/30-openvpn-forward.conf
  542.                 if [[ "$os" = "debian" || "$os" = "ubuntu" ]]; then
  543.                     apt-get remove --purge -y openvpn
  544.                 else
  545.                     # Else, OS must be CentOS or Fedora
  546.                     yum remove -y openvpn
  547.                 fi
  548.                 echo
  549.                 echo "OpenVPN removed!"
  550.             else
  551.                 echo
  552.                 echo "OpenVPN removal aborted!"
  553.             fi
  554.             exit
  555.         ;;
  556.         4)
  557.             exit
  558.         ;;
  559.     esac
  560. fi
Add Comment
Please, Sign In to add comment