Advertisement
fahimmurshed

openvpn-install.sh

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