Advertisement
willysec_id

Wireguard Server Auto Install Script

Feb 24th, 2025
199
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 25.67 KB | Software | 0 0
  1. #!/bin/bash
  2. #
  3. # https://github.com/Nyr/wireguard-install
  4. #
  5. # Copyright (c) 2020 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. elif [[ -e /etc/debian_version ]]; then
  23.     os="debian"
  24.     os_version=$(grep -oE '[0-9]+' /etc/debian_version | head -1)
  25. elif [[ -e /etc/almalinux-release || -e /etc/rocky-release || -e /etc/centos-release ]]; then
  26.     os="centos"
  27.     os_version=$(grep -shoE '[0-9]+' /etc/almalinux-release /etc/rocky-release /etc/centos-release | head -1)
  28. elif [[ -e /etc/fedora-release ]]; then
  29.     os="fedora"
  30.     os_version=$(grep -oE '[0-9]+' /etc/fedora-release | head -1)
  31. else
  32.     echo "This installer seems to be running on an unsupported distribution.
  33. Supported distros are Ubuntu, Debian, AlmaLinux, Rocky Linux, CentOS and Fedora."
  34.     exit
  35. fi
  36.  
  37. if [[ "$os" == "ubuntu" && "$os_version" -lt 2204 ]]; then
  38.     echo "Ubuntu 22.04 or higher is required to use this installer.
  39. This version of Ubuntu is too old and unsupported."
  40.     exit
  41. fi
  42.  
  43. if [[ "$os" == "debian" ]]; then
  44.     if grep -q '/sid' /etc/debian_version; then
  45.         echo "Debian Testing and Debian Unstable are unsupported by this installer."
  46.         exit
  47.     fi
  48.     if [[ "$os_version" -lt 11 ]]; then
  49.         echo "Debian 11 or higher is required to use this installer.
  50. This version of Debian is too old and unsupported."
  51.         exit
  52.     fi
  53. fi
  54.  
  55. if [[ "$os" == "centos" && "$os_version" -lt 9 ]]; then
  56.     os_name=$(sed 's/ release.*//' /etc/almalinux-release /etc/rocky-release /etc/centos-release 2>/dev/null | head -1)
  57.     echo "$os_name 9 or higher is required to use this installer.
  58. This version of $os_name is too old and unsupported."
  59.     exit
  60. fi
  61.  
  62. # Detect environments where $PATH does not include the sbin directories
  63. if ! grep -q sbin <<< "$PATH"; then
  64.     echo '$PATH does not include sbin. Try using "su -" instead of "su".'
  65.     exit
  66. fi
  67.  
  68. # Detect if BoringTun (userspace WireGuard) needs to be used
  69. if ! systemd-detect-virt -cq; then
  70.     # Not running inside a container
  71.     use_boringtun="0"
  72. elif grep -q '^wireguard ' /proc/modules; then
  73.     # Running inside a container, but the wireguard kernel module is available
  74.     use_boringtun="0"
  75. else
  76.     # Running inside a container and the wireguard kernel module is not available
  77.     use_boringtun="1"
  78. fi
  79.  
  80. if [[ "$EUID" -ne 0 ]]; then
  81.     echo "This installer needs to be run with superuser privileges."
  82.     exit
  83. fi
  84.  
  85. if [[ "$use_boringtun" -eq 1 ]]; then
  86.     if [ "$(uname -m)" != "x86_64" ]; then
  87.         echo "In containerized systems without the wireguard kernel module, this installer
  88. supports only the x86_64 architecture.
  89. The system runs on $(uname -m) and is unsupported."
  90.         exit
  91.     fi
  92.     # TUN device is required to use BoringTun
  93.     if [[ ! -e /dev/net/tun ]] || ! ( exec 7<>/dev/net/tun ) 2>/dev/null; then
  94.         echo "The system does not have the TUN device available.
  95. TUN needs to be enabled before running this installer."
  96.         exit
  97.     fi
  98. fi
  99.  
  100. new_client_dns () {
  101.     echo "Select a DNS server for the client:"
  102.     echo "   1) Current system resolvers"
  103.     echo "   2) Google"
  104.     echo "   3) 1.1.1.1"
  105.     echo "   4) OpenDNS"
  106.     echo "   5) Quad9"
  107.     echo "   6) AdGuard"
  108.     read -p "DNS server [1]: " dns
  109.     until [[ -z "$dns" || "$dns" =~ ^[1-6]$ ]]; do
  110.         echo "$dns: invalid selection."
  111.         read -p "DNS server [1]: " dns
  112.     done
  113.         # DNS
  114.     case "$dns" in
  115.         1|"")
  116.             # Locate the proper resolv.conf
  117.             # Needed for systems running systemd-resolved
  118.             if grep '^nameserver' "/etc/resolv.conf" | grep -qv '127.0.0.53' ; then
  119.                 resolv_conf="/etc/resolv.conf"
  120.             else
  121.                 resolv_conf="/run/systemd/resolve/resolv.conf"
  122.             fi
  123.             # Extract nameservers and provide them in the required format
  124.             dns=$(grep -v '^#\|^;' "$resolv_conf" | grep '^nameserver' | grep -v '127.0.0.53' | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | xargs | sed -e 's/ /, /g')
  125.         ;;
  126.         2)
  127.             dns="8.8.8.8, 8.8.4.4"
  128.         ;;
  129.         3)
  130.             dns="1.1.1.1, 1.0.0.1"
  131.         ;;
  132.         4)
  133.             dns="208.67.222.222, 208.67.220.220"
  134.         ;;
  135.         5)
  136.             dns="9.9.9.9, 149.112.112.112"
  137.         ;;
  138.         6)
  139.             dns="94.140.14.14, 94.140.15.15"
  140.         ;;
  141.     esac
  142. }
  143.  
  144. new_client_setup () {
  145.     # Given a list of the assigned internal IPv4 addresses, obtain the lowest still
  146.     # available octet. Important to start looking at 2, because 1 is our gateway.
  147.     octet=2
  148.     while grep AllowedIPs /etc/wireguard/wg0.conf | cut -d "." -f 4 | cut -d "/" -f 1 | grep -q "^$octet$"; do
  149.         (( octet++ ))
  150.     done
  151.     # Don't break the WireGuard configuration in case the address space is full
  152.     if [[ "$octet" -eq 255 ]]; then
  153.         echo "253 clients are already configured. The WireGuard internal subnet is full!"
  154.         exit
  155.     fi
  156.     key=$(wg genkey)
  157.     psk=$(wg genpsk)
  158.     # Configure client in the server
  159.     cat << EOF >> /etc/wireguard/wg0.conf
  160. # BEGIN_PEER $client
  161. [Peer]
  162. PublicKey = $(wg pubkey <<< $key)
  163. PresharedKey = $psk
  164. AllowedIPs = 10.7.0.$octet/32$(grep -q 'fddd:2c4:2c4:2c4::1' /etc/wireguard/wg0.conf && echo ", fddd:2c4:2c4:2c4::$octet/128")
  165. # END_PEER $client
  166. EOF
  167.     # Create client configuration
  168.     cat << EOF > ~/"$client".conf
  169. [Interface]
  170. Address = 10.7.0.$octet/24$(grep -q 'fddd:2c4:2c4:2c4::1' /etc/wireguard/wg0.conf && echo ", fddd:2c4:2c4:2c4::$octet/64")
  171. DNS = $dns
  172. PrivateKey = $key
  173.  
  174. [Peer]
  175. PublicKey = $(grep PrivateKey /etc/wireguard/wg0.conf | cut -d " " -f 3 | wg pubkey)
  176. PresharedKey = $psk
  177. AllowedIPs = 0.0.0.0/0, ::/0
  178. Endpoint = $(grep '^# ENDPOINT' /etc/wireguard/wg0.conf | cut -d " " -f 3):$(grep ListenPort /etc/wireguard/wg0.conf | cut -d " " -f 3)
  179. PersistentKeepalive = 25
  180. EOF
  181. }
  182.  
  183. if [[ ! -e /etc/wireguard/wg0.conf ]]; then
  184.     # Detect some Debian minimal setups where neither wget nor curl are installed
  185.     if ! hash wget 2>/dev/null && ! hash curl 2>/dev/null; then
  186.         echo "Wget is required to use this installer."
  187.         read -n1 -r -p "Press any key to install Wget and continue..."
  188.         apt-get update
  189.         apt-get install -y wget
  190.     fi
  191.     clear
  192.     echo 'Welcome to this WireGuard road warrior installer!'
  193.     # If system has a single IPv4, it is selected automatically. Else, ask the user
  194.     if [[ $(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}') -eq 1 ]]; then
  195.         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}')
  196.     else
  197.         number_of_ip=$(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}')
  198.         echo
  199.         echo "Which IPv4 address should be used?"
  200.         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 ') '
  201.         read -p "IPv4 address [1]: " ip_number
  202.         until [[ -z "$ip_number" || "$ip_number" =~ ^[0-9]+$ && "$ip_number" -le "$number_of_ip" ]]; do
  203.             echo "$ip_number: invalid selection."
  204.             read -p "IPv4 address [1]: " ip_number
  205.         done
  206.         [[ -z "$ip_number" ]] && ip_number="1"
  207.         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)
  208.     fi
  209.     # If $ip is a private IP address, the server must be behind NAT
  210.     if echo "$ip" | grep -qE '^(10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|192\.168)'; then
  211.         echo
  212.         echo "This server is behind NAT. What is the public IPv4 address or hostname?"
  213.         # Get public IP and sanitize with grep
  214.         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/")")
  215.         read -p "Public IPv4 address / hostname [$get_public_ip]: " public_ip
  216.         # If the checkip service is unavailable and user didn't provide input, ask again
  217.         until [[ -n "$get_public_ip" || -n "$public_ip" ]]; do
  218.             echo "Invalid input."
  219.             read -p "Public IPv4 address / hostname: " public_ip
  220.         done
  221.         [[ -z "$public_ip" ]] && public_ip="$get_public_ip"
  222.     fi
  223.     # If system has a single IPv6, it is selected automatically
  224.     if [[ $(ip -6 addr | grep -c 'inet6 [23]') -eq 1 ]]; then
  225.         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}')
  226.     fi
  227.     # If system has multiple IPv6, ask the user to select one
  228.     if [[ $(ip -6 addr | grep -c 'inet6 [23]') -gt 1 ]]; then
  229.         number_of_ip6=$(ip -6 addr | grep -c 'inet6 [23]')
  230.         echo
  231.         echo "Which IPv6 address should be used?"
  232.         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 ') '
  233.         read -p "IPv6 address [1]: " ip6_number
  234.         until [[ -z "$ip6_number" || "$ip6_number" =~ ^[0-9]+$ && "$ip6_number" -le "$number_of_ip6" ]]; do
  235.             echo "$ip6_number: invalid selection."
  236.             read -p "IPv6 address [1]: " ip6_number
  237.         done
  238.         [[ -z "$ip6_number" ]] && ip6_number="1"
  239.         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)
  240.     fi
  241.     echo
  242.     echo "What port should WireGuard listen to?"
  243.     read -p "Port [51820]: " port
  244.     until [[ -z "$port" || "$port" =~ ^[0-9]+$ && "$port" -le 65535 ]]; do
  245.         echo "$port: invalid port."
  246.         read -p "Port [51820]: " port
  247.     done
  248.     [[ -z "$port" ]] && port="51820"
  249.     echo
  250.     echo "Enter a name for the first client:"
  251.     read -p "Name [client]: " unsanitized_client
  252.     # Allow a limited lenght and set of characters to avoid conflicts
  253.     client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client" | cut -c-15)
  254.     [[ -z "$client" ]] && client="client"
  255.     echo
  256.     new_client_dns
  257.     # Set up automatic updates for BoringTun if the user is fine with that
  258.     if [[ "$use_boringtun" -eq 1 ]]; then
  259.         echo
  260.         echo "BoringTun will be installed to set up WireGuard in the system."
  261.         read -p "Should automatic updates be enabled for it? [Y/n]: " boringtun_updates
  262.         until [[ "$boringtun_updates" =~ ^[yYnN]*$ ]]; do
  263.             echo "$remove: invalid selection."
  264.             read -p "Should automatic updates be enabled for it? [Y/n]: " boringtun_updates
  265.         done
  266.         [[ -z "$boringtun_updates" ]] && boringtun_updates="y"
  267.         if [[ "$boringtun_updates" =~ ^[yY]$ ]]; then
  268.             if [[ "$os" == "centos" || "$os" == "fedora" ]]; then
  269.                 cron="cronie"
  270.             elif [[ "$os" == "debian" || "$os" == "ubuntu" ]]; then
  271.                 cron="cron"
  272.             fi
  273.         fi
  274.     fi
  275.     echo
  276.     echo "WireGuard installation is ready to begin."
  277.     # Install a firewall if firewalld or iptables are not already available
  278.     if ! systemctl is-active --quiet firewalld.service && ! hash iptables 2>/dev/null; then
  279.         if [[ "$os" == "centos" || "$os" == "fedora" ]]; then
  280.             firewall="firewalld"
  281.             # We don't want to silently enable firewalld, so we give a subtle warning
  282.             # If the user continues, firewalld will be installed and enabled during setup
  283.             echo "firewalld, which is required to manage routing tables, will also be installed."
  284.         elif [[ "$os" == "debian" || "$os" == "ubuntu" ]]; then
  285.             # iptables is way less invasive than firewalld so no warning is given
  286.             firewall="iptables"
  287.         fi
  288.     fi
  289.     read -n1 -r -p "Press any key to continue..."
  290.     # Install WireGuard
  291.     # If BoringTun is not required, set up with the WireGuard kernel module
  292.     if [[ "$use_boringtun" -eq 0 ]]; then
  293.         if [[ "$os" == "ubuntu" ]]; then
  294.             # Ubuntu
  295.             apt-get update
  296.             apt-get install -y wireguard qrencode $firewall
  297.         elif [[ "$os" == "debian" ]]; then
  298.             # Debian
  299.             apt-get update
  300.             apt-get install -y wireguard qrencode $firewall
  301.         elif [[ "$os" == "centos" ]]; then
  302.             # CentOS
  303.             dnf install -y epel-release
  304.             dnf install -y wireguard-tools qrencode $firewall
  305.         elif [[ "$os" == "fedora" ]]; then
  306.             # Fedora
  307.             dnf install -y wireguard-tools qrencode $firewall
  308.             mkdir -p /etc/wireguard/
  309.         fi
  310.     # Else, BoringTun needs to be used
  311.     else
  312.         # Install required packages
  313.         if [[ "$os" == "ubuntu" ]]; then
  314.             # Ubuntu
  315.             apt-get update
  316.             apt-get install -y qrencode ca-certificates $cron $firewall
  317.             apt-get install -y wireguard-tools --no-install-recommends
  318.         elif [[ "$os" == "debian" ]]; then
  319.             # Debian
  320.             apt-get update
  321.             apt-get install -y qrencode ca-certificates $cron $firewall
  322.             apt-get install -y wireguard-tools --no-install-recommends
  323.         elif [[ "$os" == "centos" ]]; then
  324.             # CentOS
  325.             dnf install -y epel-release
  326.             dnf install -y wireguard-tools qrencode ca-certificates tar $cron $firewall
  327.         elif [[ "$os" == "fedora" ]]; then
  328.             # Fedora
  329.             dnf install -y wireguard-tools qrencode ca-certificates tar $cron $firewall
  330.             mkdir -p /etc/wireguard/
  331.         fi
  332.         # Grab the BoringTun binary using wget or curl and extract into the right place.
  333.         # Don't use this service elsewhere without permission! Contact me before you do!
  334.         { wget -qO- https://wg.nyr.be/1/latest/download 2>/dev/null || curl -sL https://wg.nyr.be/1/latest/download ; } | tar xz -C /usr/local/sbin/ --wildcards 'boringtun-*/boringtun' --strip-components 1
  335.         # Configure wg-quick to use BoringTun
  336.         mkdir /etc/systemd/system/wg-quick@wg0.service.d/ 2>/dev/null
  337.         echo "[Service]
  338. Environment=WG_QUICK_USERSPACE_IMPLEMENTATION=boringtun
  339. Environment=WG_SUDO=1" > /etc/systemd/system/wg-quick@wg0.service.d/boringtun.conf
  340.         if [[ -n "$cron" ]] && [[ "$os" == "centos" || "$os" == "fedora" ]]; then
  341.             systemctl enable --now crond.service
  342.         fi
  343.     fi
  344.     # If firewalld was just installed, enable it
  345.     if [[ "$firewall" == "firewalld" ]]; then
  346.         systemctl enable --now firewalld.service
  347.     fi
  348.     # Generate wg0.conf
  349.     cat << EOF > /etc/wireguard/wg0.conf
  350. # Do not alter the commented lines
  351. # They are used by wireguard-install
  352. # ENDPOINT $([[ -n "$public_ip" ]] && echo "$public_ip" || echo "$ip")
  353.  
  354. [Interface]
  355. Address = 10.7.0.1/24$([[ -n "$ip6" ]] && echo ", fddd:2c4:2c4:2c4::1/64")
  356. PrivateKey = $(wg genkey)
  357. ListenPort = $port
  358.  
  359. EOF
  360.     chmod 600 /etc/wireguard/wg0.conf
  361.     # Enable net.ipv4.ip_forward for the system
  362.     echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/99-wireguard-forward.conf
  363.     # Enable without waiting for a reboot or service restart
  364.     echo 1 > /proc/sys/net/ipv4/ip_forward
  365.     if [[ -n "$ip6" ]]; then
  366.         # Enable net.ipv6.conf.all.forwarding for the system
  367.         echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.d/99-wireguard-forward.conf
  368.         # Enable without waiting for a reboot or service restart
  369.         echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
  370.     fi
  371.     if systemctl is-active --quiet firewalld.service; then
  372.         # Using both permanent and not permanent rules to avoid a firewalld
  373.         # reload.
  374.         firewall-cmd --add-port="$port"/udp
  375.         firewall-cmd --zone=trusted --add-source=10.7.0.0/24
  376.         firewall-cmd --permanent --add-port="$port"/udp
  377.         firewall-cmd --permanent --zone=trusted --add-source=10.7.0.0/24
  378.         # Set NAT for the VPN subnet
  379.         firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.7.0.0/24 ! -d 10.7.0.0/24 -j SNAT --to "$ip"
  380.         firewall-cmd --permanent --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.7.0.0/24 ! -d 10.7.0.0/24 -j SNAT --to "$ip"
  381.         if [[ -n "$ip6" ]]; then
  382.             firewall-cmd --zone=trusted --add-source=fddd:2c4:2c4:2c4::/64
  383.             firewall-cmd --permanent --zone=trusted --add-source=fddd:2c4:2c4:2c4::/64
  384.             firewall-cmd --direct --add-rule ipv6 nat POSTROUTING 0 -s fddd:2c4:2c4:2c4::/64 ! -d fddd:2c4:2c4:2c4::/64 -j SNAT --to "$ip6"
  385.             firewall-cmd --permanent --direct --add-rule ipv6 nat POSTROUTING 0 -s fddd:2c4:2c4:2c4::/64 ! -d fddd:2c4:2c4:2c4::/64 -j SNAT --to "$ip6"
  386.         fi
  387.     else
  388.         # Create a service to set up persistent iptables rules
  389.         iptables_path=$(command -v iptables)
  390.         ip6tables_path=$(command -v ip6tables)
  391.         # nf_tables is not available as standard in OVZ kernels. So use iptables-legacy
  392.         # if we are in OVZ, with a nf_tables backend and iptables-legacy is available.
  393.         if [[ $(systemd-detect-virt) == "openvz" ]] && readlink -f "$(command -v iptables)" | grep -q "nft" && hash iptables-legacy 2>/dev/null; then
  394.             iptables_path=$(command -v iptables-legacy)
  395.             ip6tables_path=$(command -v ip6tables-legacy)
  396.         fi
  397.         echo "[Unit]
  398. Before=network.target
  399. [Service]
  400. Type=oneshot
  401. ExecStart=$iptables_path -t nat -A POSTROUTING -s 10.7.0.0/24 ! -d 10.7.0.0/24 -j SNAT --to $ip
  402. ExecStart=$iptables_path -I INPUT -p udp --dport $port -j ACCEPT
  403. ExecStart=$iptables_path -I FORWARD -s 10.7.0.0/24 -j ACCEPT
  404. ExecStart=$iptables_path -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
  405. ExecStop=$iptables_path -t nat -D POSTROUTING -s 10.7.0.0/24 ! -d 10.7.0.0/24 -j SNAT --to $ip
  406. ExecStop=$iptables_path -D INPUT -p udp --dport $port -j ACCEPT
  407. ExecStop=$iptables_path -D FORWARD -s 10.7.0.0/24 -j ACCEPT
  408. ExecStop=$iptables_path -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT" > /etc/systemd/system/wg-iptables.service
  409.         if [[ -n "$ip6" ]]; then
  410.             echo "ExecStart=$ip6tables_path -t nat -A POSTROUTING -s fddd:2c4:2c4:2c4::/64 ! -d fddd:2c4:2c4:2c4::/64 -j SNAT --to $ip6
  411. ExecStart=$ip6tables_path -I FORWARD -s fddd:2c4:2c4:2c4::/64 -j ACCEPT
  412. ExecStart=$ip6tables_path -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
  413. ExecStop=$ip6tables_path -t nat -D POSTROUTING -s fddd:2c4:2c4:2c4::/64 ! -d fddd:2c4:2c4:2c4::/64 -j SNAT --to $ip6
  414. ExecStop=$ip6tables_path -D FORWARD -s fddd:2c4:2c4:2c4::/64 -j ACCEPT
  415. ExecStop=$ip6tables_path -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT" >> /etc/systemd/system/wg-iptables.service
  416.         fi
  417.         echo "RemainAfterExit=yes
  418. [Install]
  419. WantedBy=multi-user.target" >> /etc/systemd/system/wg-iptables.service
  420.         systemctl enable --now wg-iptables.service
  421.     fi
  422.     # Generates the custom client.conf
  423.     new_client_setup
  424.     # Enable and start the wg-quick service
  425.     systemctl enable --now wg-quick@wg0.service
  426.     # Set up automatic updates for BoringTun if the user wanted to
  427.     if [[ "$boringtun_updates" =~ ^[yY]$ ]]; then
  428.         # Deploy upgrade script
  429.         cat << 'EOF' > /usr/local/sbin/boringtun-upgrade
  430. #!/bin/bash
  431. latest=$(wget -qO- https://wg.nyr.be/1/latest 2>/dev/null || curl -sL https://wg.nyr.be/1/latest 2>/dev/null)
  432. # If server did not provide an appropriate response, exit
  433. if ! head -1 <<< "$latest" | grep -qiE "^boringtun.+[0-9]+\.[0-9]+.*$"; then
  434.     echo "Update server unavailable"
  435.     exit
  436. fi
  437. current=$(/usr/local/sbin/boringtun -V)
  438. if [[ "$current" != "$latest" ]]; then
  439.     download="https://wg.nyr.be/1/latest/download"
  440.     xdir=$(mktemp -d)
  441.     # If download and extraction are successful, upgrade the boringtun binary
  442.     if { wget -qO- "$download" 2>/dev/null || curl -sL "$download" ; } | tar xz -C "$xdir" --wildcards "boringtun-*/boringtun" --strip-components 1; then
  443.         systemctl stop wg-quick@wg0.service
  444.         rm -f /usr/local/sbin/boringtun
  445.         mv "$xdir"/boringtun /usr/local/sbin/boringtun
  446.         systemctl start wg-quick@wg0.service
  447.         echo "Succesfully updated to $(/usr/local/sbin/boringtun -V)"
  448.     else
  449.         echo "boringtun update failed"
  450.     fi
  451.     rm -rf "$xdir"
  452. else
  453.     echo "$current is up to date"
  454. fi
  455. EOF
  456.         chmod +x /usr/local/sbin/boringtun-upgrade
  457.         # Add cron job to run the updater daily at a random time between 3:00 and 5:59
  458.         { crontab -l 2>/dev/null; echo "$(( $RANDOM % 60 )) $(( $RANDOM % 3 + 3 )) * * * /usr/local/sbin/boringtun-upgrade &>/dev/null" ; } | crontab -
  459.     fi
  460.     echo
  461.     qrencode -t ANSI256UTF8 < ~/"$client.conf"
  462.     echo -e '\xE2\x86\x91 That is a QR code containing the client configuration.'
  463.     echo
  464.     echo "Finished!"
  465.     echo
  466.     echo "The client configuration is available in:" ~/"$client.conf"
  467.     echo "New clients can be added by running this script again."
  468. else
  469.     clear
  470.     echo "WireGuard is already installed."
  471.     echo
  472.     echo "Select an option:"
  473.     echo "   1) Add a new client"
  474.     echo "   2) Remove an existing client"
  475.     echo "   3) Remove WireGuard"
  476.     echo "   4) Exit"
  477.     read -p "Option: " option
  478.     until [[ "$option" =~ ^[1-4]$ ]]; do
  479.         echo "$option: invalid selection."
  480.         read -p "Option: " option
  481.     done
  482.     case "$option" in
  483.         1)
  484.             echo
  485.             echo "Provide a name for the client:"
  486.             read -p "Name: " unsanitized_client
  487.             # Allow a limited lenght and set of characters to avoid conflicts
  488.             client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client" | cut -c-15)
  489.             while [[ -z "$client" ]] || grep -q "^# BEGIN_PEER $client$" /etc/wireguard/wg0.conf; do
  490.                 echo "$client: invalid name."
  491.                 read -p "Name: " unsanitized_client
  492.                 client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client" | cut -c-15)
  493.             done
  494.             echo
  495.             new_client_dns
  496.             new_client_setup
  497.             # Append new client configuration to the WireGuard interface
  498.             wg addconf wg0 <(sed -n "/^# BEGIN_PEER $client/,/^# END_PEER $client/p" /etc/wireguard/wg0.conf)
  499.             echo
  500.             qrencode -t ANSI256UTF8 < ~/"$client.conf"
  501.             echo -e '\xE2\x86\x91 That is a QR code containing your client configuration.'
  502.             echo
  503.             echo "$client added. Configuration available in:" ~/"$client.conf"
  504.             exit
  505.         ;;
  506.         2)
  507.             # This option could be documented a bit better and maybe even be simplified
  508.             # ...but what can I say, I want some sleep too
  509.             number_of_clients=$(grep -c '^# BEGIN_PEER' /etc/wireguard/wg0.conf)
  510.             if [[ "$number_of_clients" = 0 ]]; then
  511.                 echo
  512.                 echo "There are no existing clients!"
  513.                 exit
  514.             fi
  515.             echo
  516.             echo "Select the client to remove:"
  517.             grep '^# BEGIN_PEER' /etc/wireguard/wg0.conf | cut -d ' ' -f 3 | nl -s ') '
  518.             read -p "Client: " client_number
  519.             until [[ "$client_number" =~ ^[0-9]+$ && "$client_number" -le "$number_of_clients" ]]; do
  520.                 echo "$client_number: invalid selection."
  521.                 read -p "Client: " client_number
  522.             done
  523.             client=$(grep '^# BEGIN_PEER' /etc/wireguard/wg0.conf | cut -d ' ' -f 3 | sed -n "$client_number"p)
  524.             echo
  525.             read -p "Confirm $client removal? [y/N]: " remove
  526.             until [[ "$remove" =~ ^[yYnN]*$ ]]; do
  527.                 echo "$remove: invalid selection."
  528.                 read -p "Confirm $client removal? [y/N]: " remove
  529.             done
  530.             if [[ "$remove" =~ ^[yY]$ ]]; then
  531.                 # The following is the right way to avoid disrupting other active connections:
  532.                 # Remove from the live interface
  533.                 wg set wg0 peer "$(sed -n "/^# BEGIN_PEER $client$/,\$p" /etc/wireguard/wg0.conf | grep -m 1 PublicKey | cut -d " " -f 3)" remove
  534.                 # Remove from the configuration file
  535.                 sed -i "/^# BEGIN_PEER $client$/,/^# END_PEER $client$/d" /etc/wireguard/wg0.conf
  536.                 echo
  537.                 echo "$client removed!"
  538.             else
  539.                 echo
  540.                 echo "$client removal aborted!"
  541.             fi
  542.             exit
  543.         ;;
  544.         3)
  545.             echo
  546.             read -p "Confirm WireGuard removal? [y/N]: " remove
  547.             until [[ "$remove" =~ ^[yYnN]*$ ]]; do
  548.                 echo "$remove: invalid selection."
  549.                 read -p "Confirm WireGuard removal? [y/N]: " remove
  550.             done
  551.             if [[ "$remove" =~ ^[yY]$ ]]; then
  552.                 port=$(grep '^ListenPort' /etc/wireguard/wg0.conf | cut -d " " -f 3)
  553.                 if systemctl is-active --quiet firewalld.service; then
  554.                     ip=$(firewall-cmd --direct --get-rules ipv4 nat POSTROUTING | grep '\-s 10.7.0.0/24 '"'"'!'"'"' -d 10.7.0.0/24' | grep -oE '[^ ]+$')
  555.                     # Using both permanent and not permanent rules to avoid a firewalld reload.
  556.                     firewall-cmd --remove-port="$port"/udp
  557.                     firewall-cmd --zone=trusted --remove-source=10.7.0.0/24
  558.                     firewall-cmd --permanent --remove-port="$port"/udp
  559.                     firewall-cmd --permanent --zone=trusted --remove-source=10.7.0.0/24
  560.                     firewall-cmd --direct --remove-rule ipv4 nat POSTROUTING 0 -s 10.7.0.0/24 ! -d 10.7.0.0/24 -j SNAT --to "$ip"
  561.                     firewall-cmd --permanent --direct --remove-rule ipv4 nat POSTROUTING 0 -s 10.7.0.0/24 ! -d 10.7.0.0/24 -j SNAT --to "$ip"
  562.                     if grep -qs 'fddd:2c4:2c4:2c4::1/64' /etc/wireguard/wg0.conf; then
  563.                         ip6=$(firewall-cmd --direct --get-rules ipv6 nat POSTROUTING | grep '\-s fddd:2c4:2c4:2c4::/64 '"'"'!'"'"' -d fddd:2c4:2c4:2c4::/64' | grep -oE '[^ ]+$')
  564.                         firewall-cmd --zone=trusted --remove-source=fddd:2c4:2c4:2c4::/64
  565.                         firewall-cmd --permanent --zone=trusted --remove-source=fddd:2c4:2c4:2c4::/64
  566.                         firewall-cmd --direct --remove-rule ipv6 nat POSTROUTING 0 -s fddd:2c4:2c4:2c4::/64 ! -d fddd:2c4:2c4:2c4::/64 -j SNAT --to "$ip6"
  567.                         firewall-cmd --permanent --direct --remove-rule ipv6 nat POSTROUTING 0 -s fddd:2c4:2c4:2c4::/64 ! -d fddd:2c4:2c4:2c4::/64 -j SNAT --to "$ip6"
  568.                     fi
  569.                 else
  570.                     systemctl disable --now wg-iptables.service
  571.                     rm -f /etc/systemd/system/wg-iptables.service
  572.                 fi
  573.                 systemctl disable --now wg-quick@wg0.service
  574.                 rm -f /etc/systemd/system/wg-quick@wg0.service.d/boringtun.conf
  575.                 rm -f /etc/sysctl.d/99-wireguard-forward.conf
  576.                 # Different stuff was installed depending on whether BoringTun was used or not
  577.                 if [[ "$use_boringtun" -eq 0 ]]; then
  578.                     if [[ "$os" == "ubuntu" ]]; then
  579.                         # Ubuntu
  580.                         rm -rf /etc/wireguard/
  581.                         apt-get remove --purge -y wireguard wireguard-tools
  582.                     elif [[ "$os" == "debian" ]]; then
  583.                         # Debian
  584.                         rm -rf /etc/wireguard/
  585.                         apt-get remove --purge -y wireguard wireguard-tools
  586.                     elif [[ "$os" == "centos" ]]; then
  587.                         # CentOS
  588.                         dnf remove -y wireguard-tools
  589.                         rm -rf /etc/wireguard/
  590.                     elif [[ "$os" == "fedora" ]]; then
  591.                         # Fedora
  592.                         dnf remove -y wireguard-tools
  593.                         rm -rf /etc/wireguard/
  594.                     fi
  595.                 else
  596.                     { crontab -l 2>/dev/null | grep -v '/usr/local/sbin/boringtun-upgrade' ; } | crontab -
  597.                     if [[ "$os" == "ubuntu" ]]; then
  598.                         # Ubuntu
  599.                         rm -rf /etc/wireguard/
  600.                         apt-get remove --purge -y wireguard-tools
  601.                     elif [[ "$os" == "debian" ]]; then
  602.                         # Debian
  603.                         rm -rf /etc/wireguard/
  604.                         apt-get remove --purge -y wireguard-tools
  605.                     elif [[ "$os" == "centos" ]]; then
  606.                         # CentOS
  607.                         dnf remove -y wireguard-tools
  608.                         rm -rf /etc/wireguard/
  609.                     elif [[ "$os" == "fedora" ]]; then
  610.                         # Fedora
  611.                         dnf remove -y wireguard-tools
  612.                         rm -rf /etc/wireguard/
  613.                     fi
  614.                     rm -f /usr/local/sbin/boringtun /usr/local/sbin/boringtun-upgrade
  615.                 fi
  616.                 echo
  617.                 echo "WireGuard removed!"
  618.             else
  619.                 echo
  620.                 echo "WireGuard removal aborted!"
  621.             fi
  622.             exit
  623.         ;;
  624.         4)
  625.             exit
  626.         ;;
  627.     esac
  628. fi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement