From 2695401bc90a4024bbfed5e402c3c10a71c30108 Mon Sep 17 00:00:00 2001 From: Teddysun Date: Mon, 23 Sep 2019 21:32:27 +0900 Subject: [PATCH] Added wireguard.sh This is a Shell script for configure and start WireGuard VPN server Signed-off-by: Teddysun --- wireguard.sh | 651 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 651 insertions(+) create mode 100644 wireguard.sh diff --git a/wireguard.sh b/wireguard.sh new file mode 100644 index 0000000..a68eb54 --- /dev/null +++ b/wireguard.sh @@ -0,0 +1,651 @@ +#!/usr/bin/env bash +# +# This is a Shell script for configure and start WireGuard VPN server. +# +# Copyright (C) 2019 Teddysun +# +# Reference URL: +# https://www.wireguard.com +# https://git.zx2c4.com/WireGuard + +trap _exit INT QUIT TERM + +_red() { + printf '\033[1;31;31m%b\033[0m' "$1" +} + +_green() { + printf '\033[1;31;32m%b\033[0m' "$1" +} + +_yellow() { + printf '\033[1;31;33m%b\033[0m' "$1" +} + +_printargs() { + printf -- "%s" "[$(date)] " + printf -- "%s" "$1" + printf "\n" +} + +_info() { + _printargs "$@" +} + +_warn() { + printf -- "%s" "[$(date)] " + _yellow "$1" + printf "\n" +} + +_error() { + printf -- "%s" "[$(date)] " + _red "$1" + printf "\n" + exit 2 +} + +_exit() { + printf "\n" + _red "$0 has been terminated." + printf "\n" + exit 1 +} + +_exists() { + local cmd="$1" + if eval type type > /dev/null 2>&1; then + eval type "$cmd" > /dev/null 2>&1 + elif command > /dev/null 2>&1; then + command -v "$cmd" > /dev/null 2>&1 + else + which "$cmd" > /dev/null 2>&1 + fi + rt="$?" + return ${rt} +} + +_ipv4() { + local ipv4="$( ip addr | egrep -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | \ + egrep -v "^192\.168|^172\.1[6-9]\.|^172\.2[0-9]\.|^172\.3[0-2]\.|^10\.|^127\.|^255\.|^0\." | head -n 1 )" + [ -z "${ipv4}" ] && ipv4="$( wget -qO- -t1 -T2 ipv4.icanhazip.com )" + [ -z "${ipv4}" ] && ipv4="$( wget -qO- -t1 -T2 ipinfo.io/ip )" + printf -- "%s" "${ipv4}" +} + +_ipv6() { + local ipv6="" + ipv6="$(wget -qO- -t1 -T2 ipv6.icanhazip.com)" + printf -- "%s" "${ipv6}" +} + +_nic() { + local nic="" + nic="$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1)" + printf -- "%s" "${nic}" +} + +_port() { + local port="$(shuf -i 1024-20480 -n 1)" + while true + do + if _exists "netstat" && netstat -tunlp | grep -w "${port}" > /dev/null 2>&1; then + port="$(shuf -i 1024-20480 -n 1)" + else + break + fi + done + printf -- "%s" "${port}" +} + +_os() { + local os="" + [ -f "/etc/debian_version" ] && source /etc/os-release && os="${ID}" && printf -- "%s" "${os}" && return + [ -f "/etc/fedora-release" ] && os="fedora" && printf -- "%s" "${os}" && return + [ -f "/etc/redhat-release" ] && os="centos" && printf -- "%s" "${os}" && return +} + +_os_full() { + [ -f /etc/redhat-release ] && awk '{print ($1,$3~/^[0-9]/?$3:$4)}' /etc/redhat-release && return + [ -f /etc/os-release ] && awk -F'[= "]' '/PRETTY_NAME/{print $3,$4,$5}' /etc/os-release && return + [ -f /etc/lsb-release ] && awk -F'[="]+' '/DESCRIPTION/{print $2}' /etc/lsb-release && return +} + +_os_ver() { + local main_ver="$( echo $(_os_full) | grep -oE "[0-9.]+")" + printf -- "%s" "${main_ver%%.*}" +} + +_error_detect() { + local cmd="$1" + _info "${cmd}" + eval ${cmd} 1> /dev/null + if [ $? -ne 0 ]; then + _error "Execution command (${cmd}) failed, please check it and try again." + fi +} + +# Check OS version +check_os() { + _info "Check OS version" + if _exists "virt-what"; then + virt="$(virt-what)" + elif _exists "systemd-detect-virt"; then + virt="$(systemd-detect-virt)" + fi + if [ -n "${virt}" -a "${virt}" = "lxc" ]; then + _error "Virtualization method is LXC, which is not supported." + fi + if [ -n "${virt}" -a "${virt}" = "openvz" ] || [ -d "/proc/vz" ]; then + _error "Virtualization method is OpenVZ, which is not supported." + fi + [ -z "$(_os)" ] && _error "Not supported OS." + case "$(_os)" in + ubuntu) + [ -n "$(_os_ver)" -a "$(_os_ver)" -lt 16 ] && _error "Not supported OS, please change to Ubuntu 16+ and try again." + ;; + debian) + [ -n "$(_os_ver)" -a "$(_os_ver)" -lt 8 ] && _error "Not supported OS, please change to Debian 8+ and try again." + ;; + fedora) + [ -n "$(_os_ver)" -a "$(_os_ver)" -lt 29 ] && _error "Not supported OS, please change to Fedora 29+ and try again." + ;; + centos) + [ -n "$(_os_ver)" -a "$(_os_ver)" -lt 7 ] && _error "Not supported OS, please change to CentOS 7+ and try again." + ;; + *) + ;; # do nothing + esac +} + +# Install from repository +install_wg_1() { + _info "Install wireguard from repository" + case "$(_os)" in + ubuntu) + _error_detect "add-apt-repository ppa:wireguard/wireguard" + _error_detect "apt-get update" + _error_detect "apt-get -y install linux-headers-$(uname -r)" + _error_detect "apt-get -y install qrencode" + _error_detect "apt-get -y install iptables" + _error_detect "apt-get -y install wireguard" + ;; + debian) + echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable.list + printf 'Package: *\nPin: release a=unstable\nPin-Priority: 90\n' > /etc/apt/preferences.d/limit-unstable + _error_detect "apt-get update" + _error_detect "apt-get -y install linux-headers-$(uname -r)" + _error_detect "apt-get -y install qrencode" + _error_detect "apt-get -y install iptables" + _error_detect "apt-get -y install wireguard" + ;; + fedora) + _error_detect "dnf -y copr enable jdoss/wireguard" + _error_detect "dnf -y install kernel-devel" + _error_detect "dnf -y install kernel-headers" + _error_detect "dnf -y install qrencode" + _error_detect "dnf -y install wireguard-dkms wireguard-tools" + ;; + centos) + _error_detect "curl -Lso /etc/yum.repos.d/wireguard.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-7/jdoss-wireguard-epel-7.repo" + _error_detect "yum -y install epel-release" + _error_detect "yum -y install kernel-devel" + _error_detect "yum -y install kernel-headers" + _error_detect "yum -y install qrencode" + _error_detect "yum -y install wireguard-dkms wireguard-tools" + ;; + *) + ;; # do nothing + esac +} + +# Install from source +install_wg_2() { + _info "Install wireguard from source" + wireguard_ver="$(wget --no-check-certificate -qO- https://api.github.com/repos/WireGuard/WireGuard/tags | grep 'name' | head -1 | cut -d\" -f4)" + if [ -z "${wireguard_ver}" ]; then + wireguard_ver="$(curl -Lso- https://api.github.com/repos/WireGuard/WireGuard/tags | grep 'name' | head -1 | cut -d\" -f4)" + fi + [ -z "${wireguard_ver}" ] && _error "Failed to get wireguard latest version from github." + wireguard_name="WireGuard-${wireguard_ver}" + wireguard_url="https://github.com/WireGuard/WireGuard/archive/${wireguard_ver}.tar.gz" + case "$(_os)" in + ubuntu|debian) + _error_detect "apt-get update" + [ ! -d "/usr/src/linux-headers-$(uname -r)" ] && _error_detect "apt-get -y install linux-headers-$(uname -r)" + _error_detect "apt-get -y install qrencode" + _error_detect "apt-get -y install iptables" + _error_detect "apt-get -y install bc" + _error_detect "apt-get -y install gcc" + _error_detect "apt-get -y install make" + _error_detect "apt-get -y install libmnl-dev" + ;; + fedora) + [ ! -d "/usr/src/kernels/$(uname -r)" ] && _error_detect "dnf -y install kernel-headers" && _error_detect "dnf -y install kernel-devel" + _error_detect "dnf -y install qrencode" + _error_detect "dnf -y install bc" + _error_detect "dnf -y install gcc" + _error_detect "dnf -y install make" + _error_detect "dnf -y install libmnl-devel" + ;; + centos) + _error_detect "yum -y install epel-release" + [ ! -d "/usr/src/kernels/$(uname -r)" ] && _error_detect "yum -y install kernel-headers" && _error_detect "yum -y install kernel-devel" + _error_detect "yum -y install qrencode" + _error_detect "yum -y install bc" + _error_detect "yum -y install gcc" + _error_detect "yum -y install make" + _error_detect "yum -y install libmnl-devel" + ;; + *) + ;; # do nothing + esac + _error_detect "wget --no-check-certificate -qO ${wireguard_name}.tar.gz ${wireguard_url}" + _error_detect "tar zxf ${wireguard_name}.tar.gz" + _error_detect "cd ${wireguard_name}/src" + _error_detect "make tools" + _error_detect "make module" + _error_detect "make install" + _error_detect "cd ${cur_dir} && rm -fr ${wireguard_name}.tar.gz ${wireguard_name}" +} + +# Create server interface +create_server_if() { + SERVER_PRIVATE_KEY="$(wg genkey)" + SERVER_PUBLIC_KEY="$(echo ${SERVER_PRIVATE_KEY} | wg pubkey)" + CLIENT_PRIVATE_KEY="$(wg genkey)" + CLIENT_PUBLIC_KEY="$(echo ${CLIENT_PRIVATE_KEY} | wg pubkey)" + CLIENT_PRE_SHARED_KEY="$( wg genpsk )" + _info "Create server interface: /etc/wireguard/${SERVER_WG_NIC}.conf" + [ ! -d "/etc/wireguard" ] && mkdir -p "/etc/wireguard" + if [ -n "${SERVER_PUB_IPV6}" ]; then + cat > /etc/wireguard/${SERVER_WG_NIC}.conf < /etc/wireguard/${SERVER_WG_NIC}.conf < /etc/wireguard/${SERVER_WG_NIC}_client < /etc/wireguard/${SERVER_WG_NIC}_client <> /etc/sysctl.conf + [ -n "${SERVER_PUB_IPV6}" ] && echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.conf + sysctl -p >/dev/null 2>&1 +} + +# Set firewall rules +set_firewall() { + _info "Setting firewall rules" + if _exists "firewall-cmd"; then + if [ "$(firewall-cmd --state)" = "running" ]; then + default_zone="$(firewall-cmd --get-default-zone)" + if [ "$(firewall-cmd --zone=${default_zone} --query-masquerade)" = "no" ]; then + _error_detect "firewall-cmd --zone=${default_zone} --add-masquerade" + fi + if ! firewall-cmd --list-ports | grep -qw "${SERVER_WG_PORT}/udp"; then + _error_detect "firewall-cmd --permanent --zone=${default_zone} --add-port=${SERVER_WG_PORT}/udp" + fi + _error_detect "firewall-cmd --reload" + else + _warn "Firewalld looks like not running, please start it and manually set" + fi + else + if _exists "iptables"; then + iptables -A INPUT -p udp --dport ${SERVER_WG_PORT} -j ACCEPT + iptables -A FORWARD -i ${SERVER_WG_NIC} -j ACCEPT + iptables -t nat -A POSTROUTING -o ${SERVER_PUB_NIC} -j MASQUERADE + iptables-save > /etc/iptables.rules + if [ -d "/etc/network/if-up.d" ]; then + cat > /etc/network/if-up.d/iptables < /etc/ip6tables.rules + if [ -d "/etc/network/if-up.d" ]; then + cat > /etc/network/if-up.d/ip6tables < ${new_client_if} <> ${default_server_if} < ${new_client_if} <> ${default_server_if} <