diff --git a/.travis.yml b/.travis.yml index 3eb710a..e4b7961 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ addons: - shellcheck script: - - export SHELLCHECK_OPTS="-e SC1091" + - export SHELLCHECK_OPTS="-e SC1091,SC1117" - shellcheck *.sh extras/*.sh - sudo sed -i "/debian unstable/d" /etc/apt/sources.list - sudo VPN_IPSEC_PSK='vpn_psk' diff --git a/README-zh.md b/README-zh.md index ab4e44f..1bd9c08 100644 --- a/README-zh.md +++ b/README-zh.md @@ -28,7 +28,7 @@ IPsec VPN 可以加密你的网络流量,以防止在通过因特网传送时 ## 快速开始 -首先,在你的 Linux 服务器* 上全新安装一个 Ubuntu LTS, Debian 或者 CentOS 系统。 +首先,在你的 Linux 服务器[*](#quick-start-note) 上全新安装一个 Ubuntu LTS, Debian 或者 CentOS 系统。 使用以下命令快速搭建 IPsec VPN 服务器: @@ -42,6 +42,7 @@ wget https://git.io/vpnsetup -O vpnsetup.sh && sudo sh vpnsetup.sh 如需了解其它安装选项,以及如何配置 VPN 客户端,请继续阅读以下部分。 + \* 一个专用服务器或者虚拟专用服务器 (VPS)。OpenVZ VPS 不受支持。 ## 功能特性 @@ -66,9 +67,9 @@ wget https://git.io/vpnsetup -O vpnsetup.sh && sudo sh vpnsetup.sh **-或者-** -一个专用服务器,或者基于 KVM/Xen 的虚拟专用服务器 (VPS),全新安装以上操作系统之一。OpenVZ VPS 不受支持,用户可以尝试使用比如 Shadowsocks 或者 OpenVPN。 +一个专用服务器,或者基于 KVM/Xen 的虚拟专用服务器 (VPS),全新安装以上操作系统之一。OpenVZ VPS 不受支持,用户可以另外尝试比如 Shadowsocks 或者 OpenVPN。 -这也包括各种公共云服务中的 Linux 虚拟机,比如 DigitalOcean, Vultr, Linode, Google Compute Engine, Amazon Lightsail, Microsoft Azure, IBM SoftLayer, OVHRackspace。 +这也包括各种公共云服务中的 Linux 虚拟机,比如 DigitalOcean, Vultr, Linode, Google Compute Engine, Amazon Lightsail, Microsoft Azure, IBM Bluemix, OVHRackspaceDeploy to Azure Install on DigitalOcean Deploy to Linode @@ -124,10 +125,11 @@ VPN_PASSWORD='你的VPN密码' sh vpnsetup.sh 配置你的计算机或其它设备使用 VPN 。请参见: -配置 IPsec/L2TP VPN 客户端 -配置 IPsec/XAuth ("Cisco IPsec") VPN 客户端 +**配置 IPsec/L2TP VPN 客户端** -如何配置 IKEv2 VPN: Windows 和 Android +**配置 IPsec/XAuth ("Cisco IPsec") VPN 客户端** + +**如何配置 IKEv2 VPN: Windows 和 Android** 如果在连接过程中遇到错误,请参见 故障排除。 @@ -139,7 +141,7 @@ VPN_PASSWORD='你的VPN密码' sh vpnsetup.sh **Windows 用户** 在首次连接之前需要修改一次注册表,以解决 VPN 服务器 和/或 客户端与 NAT (比如家用路由器)的兼容问题。 -同一个 VPN 账户可以在你的多个设备上使用。但是由于 IPsec/L2TP 的局限性,如果需要同时连接在同一个 NAT (比如家用路由器)后面的多个设备到 VPN 服务器,你必须仅使用 IPsec/XAuth 模式。另外,你的服务器必须运行 [Libreswan 3.19 或更新版本](#升级libreswan)。 +同一个 VPN 账户可以在你的多个设备上使用。但是由于 IPsec/L2TP 的局限性,如果需要同时连接在同一个 NAT (比如家用路由器)后面的多个设备到 VPN 服务器,你必须仅使用 IPsec/XAuth 模式。 对于有外部防火墙的服务器(比如 EC2/GCE),请为 VPN 打开 UDP 端口 500 和 4500。 @@ -147,6 +149,8 @@ VPN_PASSWORD='你的VPN密码' sh vpnsetup.sh 在 VPN 已连接时,客户端配置为使用 Google Public DNS。如果偏好其它的域名解析服务,请编辑 `/etc/ppp/options.xl2tpd` 和 `/etc/ipsec.conf` 并替换 `8.8.8.8` 和 `8.8.4.4`。然后重启服务器。 +使用 L2TP 内核支持有助于提高 IPsec/L2TP 性能。它在以下系统上可用: Ubuntu 16.04, Debian 9, CentOS 7 和 6。 Ubuntu 16.04 用户需要安装 `` linux-image-extra-`uname -r` `` 软件包并且重启 `xl2tpd` 服务。 + 如果需要在安装后更改 IPTables 规则,请编辑 `/etc/iptables.rules` 和/或 `/etc/iptables/rules.v4` (Ubuntu/Debian),或者 `/etc/sysconfig/iptables` (CentOS)。然后重启服务器。 在使用 `IPsec/L2TP` 连接时,VPN 服务器在虚拟网络 `192.168.42.0/24` 内具有 IP `192.168.42.1`。 @@ -155,7 +159,7 @@ VPN_PASSWORD='你的VPN密码' sh vpnsetup.sh ## 升级Libreswan -提供两个额外的脚本 vpnupgrade.shvpnupgrade_centos.sh,可用于升级 Libreswan更新日志 | 通知列表)。请在运行前根据需要修改 `swan_ver` 变量。检查已安装版本: `ipsec --version`. +提供两个额外的脚本 vpnupgrade.shvpnupgrade_centos.sh,可用于升级 Libreswan更新日志 | 通知列表)。请在运行前根据需要修改 `SWAN_VER` 变量。查看已安装版本: `ipsec --version`. ```bash # Ubuntu & Debian diff --git a/README.md b/README.md index b3f4319..37eecff 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ We will use Libreswan as th ## Quick start -First, prepare your Linux server* with a fresh install of Ubuntu LTS, Debian or CentOS. +First, prepare your Linux server[*](#quick-start-note) with a fresh install of Ubuntu LTS, Debian or CentOS. Use this one-liner to set up an IPsec VPN server: @@ -42,6 +42,7 @@ Your VPN login details will be randomly generated, and displayed on the screen w For other installation options and how to set up VPN clients, read the sections below. + \* A dedicated server or virtual private server (VPS). OpenVZ VPS is not supported. ## Features @@ -68,7 +69,7 @@ Please see OpenVPN or Shadowsocks. -This also includes Linux VMs in public clouds, such as DigitalOcean, Vultr, Linode, Google Compute Engine, Amazon Lightsail, Microsoft Azure, IBM SoftLayer, OVH and Rackspace. +This also includes Linux VMs in public clouds, such as DigitalOcean, Vultr, Linode, Google Compute Engine, Amazon Lightsail, Microsoft Azure, IBM Bluemix, OVH and Rackspace. Deploy to Azure Install on DigitalOcean Deploy to Linode @@ -105,7 +106,7 @@ sudo sh vpnsetup.sh ```bash # All values MUST be placed inside 'single quotes' -# DO NOT use these characters within values: \ " ' +# DO NOT use these special characters within values: \ " ' wget https://git.io/vpnsetup -O vpnsetup.sh && sudo \ VPN_IPSEC_PSK='your_ipsec_pre_shared_key' \ VPN_USER='your_vpn_username' \ @@ -124,10 +125,11 @@ Follow the same steps as above, but replace `https://git.io/vpnsetup` with `http Get your computer or device to use the VPN. Please refer to: -Configure IPsec/L2TP VPN Clients -Configure IPsec/XAuth ("Cisco IPsec") VPN Clients +**Configure IPsec/L2TP VPN Clients** -How-To: IKEv2 VPN for Windows and Android +**Configure IPsec/XAuth ("Cisco IPsec") VPN Clients** + +**How-To: IKEv2 VPN for Windows and Android** If you get an error when trying to connect, see Troubleshooting. @@ -139,7 +141,7 @@ Enjoy your very own VPN! :sparkles::tada::rocket::sparkles: For **Windows users**, this one-time registry change is required if the VPN server and/or client is behind NAT (e.g. home router). -The same VPN account can be used by your multiple devices. However, due to an IPsec/L2TP limitation, if you wish to connect multiple devices simultaneously from behind the same NAT (e.g. home router), you must use only IPsec/XAuth mode. Also, your server must run [Libreswan 3.19 or newer](#upgrade-libreswan). +The same VPN account can be used by your multiple devices. However, due to an IPsec/L2TP limitation, if you wish to connect multiple devices simultaneously from behind the same NAT (e.g. home router), you must use only IPsec/XAuth mode. For servers with an external firewall (e.g. EC2/GCE), open UDP ports 500 and 4500 for the VPN. @@ -147,6 +149,8 @@ If you wish to add, edit or remove VPN user accounts, see Google Public DNS when the VPN is active. If another DNS provider is preferred, replace `8.8.8.8` and `8.8.4.4` in both `/etc/ppp/options.xl2tpd` and `/etc/ipsec.conf`. Then reboot your server. +Using L2TP kernel support could improve IPsec/L2TP performance. It is available on Ubuntu 16.04, Debian 9, CentOS 7 and 6. Ubuntu 16.04 users should install the `` linux-image-extra-`uname -r` `` package and restart the `xl2tpd` service. + To modify the IPTables rules after install, edit `/etc/iptables.rules` and/or `/etc/iptables/rules.v4` (Ubuntu/Debian), or `/etc/sysconfig/iptables` (CentOS). Then reboot your server. When connecting via `IPsec/L2TP`, the VPN server has IP `192.168.42.1` within the VPN subnet `192.168.42.0/24`. @@ -155,7 +159,7 @@ The scripts will backup existing config files before making changes, with `.old- ## Upgrade Libreswan -The additional scripts vpnupgrade.sh and vpnupgrade_centos.sh can be used to upgrade Libreswan (changelog | announce). Edit the `swan_ver` variable as necessary. Check installed version: `ipsec --version`. +The additional scripts vpnupgrade.sh and vpnupgrade_centos.sh can be used to upgrade Libreswan (changelog | announce). Edit the `SWAN_VER` variable as necessary. Check which version is installed: `ipsec --version`. ```bash # Ubuntu & Debian diff --git a/docs/clients-zh.md b/docs/clients-zh.md index be2d84f..f478aa4 100644 --- a/docs/clients-zh.md +++ b/docs/clients-zh.md @@ -20,7 +20,7 @@ * [故障排除](#故障排除) * [Windows 错误 809](#windows-错误-809) * [Windows 错误 628](#windows-错误-628) - * [Android 6 and 7](#android-6-and-7) + * [Android 6 及以上版本](#android-6-及以上版本) * [Chromebook](#chromebook) * [其它错误](#其它错误) * [额外的步骤](#额外的步骤) @@ -182,10 +182,10 @@ yum -y install strongswan xl2tpd 创建 VPN 变量 (替换为你自己的值): ```bash -VPN_SERVER_IP='your_vpn_server_ip' -VPN_IPSEC_PSK='your_ipsec_pre_shared_key' -VPN_USER='your_vpn_username' -VPN_PASSWORD='your_vpn_password' +VPN_SERVER_IP='你的VPN服务器IP' +VPN_IPSEC_PSK='你的IPsec预共享密钥' +VPN_USER='你的VPN用户名' +VPN_PASSWORD='你的VPN密码' ``` 配置 strongSwan: @@ -316,13 +316,13 @@ ip route 从新的默认路由中排除你的 VPN 服务器 IP (替换为你自己的值): ```bash -route add YOUR_VPN_SERVER_IP gw X.X.X.X +route add 你的VPN服务器IP gw X.X.X.X ``` -如果你的 VPN 客户端是一个远程服务器,则必须从新的默认路由中排除你本地电脑的公有 IP,以避免 SSH 会话被断开 (替换为你自己的公有 IP,可在 这里 查看): +如果你的 VPN 客户端是一个远程服务器,则必须从新的默认路由中排除你的本地电脑的公有 IP,以避免 SSH 会话被断开 (替换为实际值): ```bash -route add YOUR_LOCAL_PC_PUBLIC_IP gw X.X.X.X +route add 你的本地电脑的公有IP gw X.X.X.X ``` 添加一个新的默认路由,并且开始通过 VPN 服务器发送数据: @@ -378,6 +378,12 @@ strongswan down myvpn REG ADD HKLM\SYSTEM\CurrentControlSet\Services\IPSec /v AssumeUDPEncapsulationContextOnSendRule /t REG_DWORD /d 0x2 /f ``` +另外,某些个别的 Windows 系统禁用了 IPsec 加密,此时也会导致连接失败。要重新启用它,可以运行以下命令并重启计算机。 + +```console +REG ADD HKLM\SYSTEM\CurrentControlSet\Services\RasMan\Parameters /v ProhibitIpSec /t REG_DWORD /d 0x0 /f +``` + ### Windows 错误 628 > 在连接完成前,连接被远程计算机终止。 @@ -395,13 +401,12 @@ strongswan down myvpn ![Select CHAP in VPN connection properties](images/vpn-properties-zh.png) -### Android 6 and 7 +### Android 6 及以上版本 -如果你无法使用 Android 6 (Marshmallow) 或者 7 (Nougat) 连接: +如果你无法使用 Android 6 或以上版本连接: 1. 单击 VPN 连接旁边的设置按钮,选择 "Show advanced options" 并且滚动到底部。如果选项 "Backward compatible mode" 存在,请启用它并重试连接。如果不存在,请尝试下一步。 -1. **注:** 最新版本的 VPN 脚本已经包含这个更改。 - (适用于 Android 7.1.2 及以上版本) 编辑 VPN 服务器上的 `/etc/ipsec.conf`。在 `ike=` 和 `phase2alg=` 两行的末尾添加 `,aes256-sha2_512` 字样。保存修改并运行 `service ipsec restart`。(参见) +1. (适用于 Android 7.1.2 及以上版本) 编辑 VPN 服务器上的 `/etc/ipsec.conf`。在 `ike=` 和 `phase2alg=` 两行的末尾添加 `,aes256-sha2_512` 字样。保存修改并运行 `service ipsec restart`。(参见) 注:最新版本的 VPN 脚本已经包含这个更改。 1. 编辑 VPN 服务器上的 `/etc/ipsec.conf`。找到 `sha2-truncbug=yes` 并将它替换为 `sha2-truncbug=no`,开头必须空两格。保存修改并运行 `service ipsec restart`。(参见) ![Android VPN workaround](images/vpn-profile-Android.png) @@ -414,9 +419,9 @@ Chromebook 用户: 如果你无法连接,请尝试 from here): +If your VPN client is a remote server, you must also exclude your Local PC's public IP from the new default route, to prevent your SSH session from being disconnected (replace with actual value): ```bash route add YOUR_LOCAL_PC_PUBLIC_IP gw X.X.X.X @@ -377,6 +377,12 @@ To fix this error, a Ref) +1. (For Android 7.1.2 and newer) Edit `/etc/ipsec.conf` on the VPN server. Append `,aes256-sha2_512` to the end of both `ike=` and `phase2alg=` lines. Save the file and run `service ipsec restart`. (Ref) Note that the latest version of VPN scripts already includes this change. 1. Edit `/etc/ipsec.conf` on the VPN server. Find `sha2-truncbug=yes` and replace it with `sha2-truncbug=no`, indented with two spaces. Save the file and run `service ipsec restart`. (Ref) ![Android VPN workaround](images/vpn-profile-Android.png) @@ -413,9 +418,9 @@ Chromebook users: If you are unable to connect, try &2; exit 1; } -exiterr2() { echo "Error: 'apt-get install' failed." >&2; exit 1; } +exiterr2() { exiterr "'apt-get install' failed."; } + +vpnupgrade() { os_type="$(lsb_release -si 2>/dev/null)" if [ -z "$os_type" ]; then [ -f /etc/os-release ] && os_type="$(. /etc/os-release && echo "$ID")" [ -f /etc/lsb-release ] && os_type="$(. /etc/lsb-release && echo "$DISTRIB_ID")" fi -if ! printf %s "$os_type" | head -n 1 | grep -qiF -e ubuntu -e debian -e raspbian; then - exiterr "This script only supports Ubuntu/Debian." +if ! printf '%s' "$os_type" | head -n 1 | grep -qiF -e ubuntu -e debian -e raspbian; then + exiterr "This script only supports Ubuntu and Debian." fi if [ "$(sed 's/\..*//' /etc/debian_version)" = "7" ]; then - exiterr "This script does not support Debian 7 (Wheezy)." + exiterr "Debian 7 is not supported." fi if [ -f /proc/user_beancounters ]; then - exiterr "This script does not support OpenVZ VPS." + exiterr "OpenVZ VPS is not supported." fi if [ "$(id -u)" != 0 ]; then exiterr "Script must be run as root. Try 'sudo sh $0'" fi -if [ -z "$swan_ver" ]; then - exiterr "Libreswan version 'swan_ver' not specified." +if [ -z "$SWAN_VER" ]; then + exiterr "Libreswan version 'SWAN_VER' not specified." fi if ! /usr/local/sbin/ipsec --version 2>/dev/null | grep -q "Libreswan"; then exiterr "This script requires Libreswan already installed." fi -if /usr/local/sbin/ipsec --version 2>/dev/null | grep -qF "$swan_ver"; then - echo "You already have Libreswan version $swan_ver installed! " +if [ "$SWAN_VER" = "3.22" ]; then + if grep -qs raspbian /etc/os-release; then + echo "Note: For Raspberry Pi systems, this script will install Libreswan" + echo "version 3.21 instead of 3.22, to avoid some recent bugs." + echo + printf "Do you wish to continue? [y/N] " + read -r response + case $response in + [yY][eE][sS]|[yY]) + echo + SWAN_VER=3.21 + ;; + *) + echo "Aborting." + exit 1 + ;; + esac + fi +fi + +if /usr/local/sbin/ipsec --version 2>/dev/null | grep -qF "$SWAN_VER"; then + echo "You already have Libreswan version $SWAN_VER installed! " echo "If you continue, the same version will be re-installed." echo printf "Do you wish to continue anyway? [y/N] " @@ -69,7 +91,7 @@ fi clear cat < Makefile.inc.local <<'EOF' WERROR_CFLAGS = USE_DNSSEC = false @@ -147,19 +169,24 @@ EOF if [ "$(packaging/utils/lswan_detect.sh init)" = "systemd" ]; then apt-get -yq install libsystemd-dev || exiterr2 fi -make -s programs && make -s install +NPROCS="$(grep -c ^processor /proc/cpuinfo)" +[ -z "$NPROCS" ] && NPROCS=1 +make "-j$((NPROCS+1))" -s base && make -s install-base # Verify the install and clean up cd /opt/src || exiterr "Cannot enter /opt/src." -/bin/rm -rf "/opt/src/libreswan-$swan_ver" -if ! /usr/local/sbin/ipsec --version 2>/dev/null | grep -qF "$swan_ver"; then - exiterr "Libreswan $swan_ver failed to build." +/bin/rm -rf "/opt/src/libreswan-$SWAN_VER" +if ! /usr/local/sbin/ipsec --version 2>/dev/null | grep -qF "$SWAN_VER"; then + exiterr "Libreswan $SWAN_VER failed to build." fi # Update ipsec.conf for Libreswan 3.19 and newer IKE_NEW=" ike=3des-sha1,3des-sha2,aes-sha1,aes-sha1;modp1024,aes-sha2,aes-sha2;modp1024,aes256-sha2_512" PHASE2_NEW=" phase2alg=3des-sha1,3des-sha2,aes-sha1,aes-sha2,aes256-sha2_512" -sed -i".old-$(date +%Y-%m-%d-%H:%M:%S)" \ +if grep -qs raspbian /etc/os-release; then + PHASE2_NEW=" phase2alg=3des-sha1,3des-sha2,aes-sha1,aes-sha2" +fi +sed -i".old-$(date +%F-%T)" \ -e "s/^[[:space:]]\+auth=esp\$/ phase2=esp/" \ -e "s/^[[:space:]]\+forceencaps=yes\$/ encapsulation=yes/" \ -e "s/^[[:space:]]\+ike=.\+\$/$IKE_NEW/" \ @@ -169,7 +196,12 @@ sed -i".old-$(date +%Y-%m-%d-%H:%M:%S)" \ service ipsec restart echo -echo "Libreswan $swan_ver was installed successfully! " +echo "Libreswan $SWAN_VER was installed successfully! " echo +} + +## Defer setup until we have the complete script +vpnupgrade "$@" + exit 0 diff --git a/extras/vpnupgrade_centos.sh b/extras/vpnupgrade_centos.sh index e44887f..1e44f5b 100644 --- a/extras/vpnupgrade_centos.sh +++ b/extras/vpnupgrade_centos.sh @@ -11,37 +11,39 @@ # know how you have improved it! # Check https://libreswan.org for the latest version -swan_ver=3.21 +SWAN_VER=3.22 ### DO NOT edit below this line ### export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" exiterr() { echo "Error: $1" >&2; exit 1; } -exiterr2() { echo "Error: 'yum install' failed." >&2; exit 1; } +exiterr2() { exiterr "'yum install' failed."; } + +vpnupgrade() { if ! grep -qs -e "release 6" -e "release 7" /etc/redhat-release; then exiterr "This script only supports CentOS/RHEL 6 and 7." fi if [ -f /proc/user_beancounters ]; then - exiterr "This script does not support OpenVZ VPS." + exiterr "OpenVZ VPS is not supported." fi if [ "$(id -u)" != 0 ]; then exiterr "Script must be run as root. Try 'sudo sh $0'" fi -if [ -z "$swan_ver" ]; then - exiterr "Libreswan version 'swan_ver' not specified." +if [ -z "$SWAN_VER" ]; then + exiterr "Libreswan version 'SWAN_VER' not specified." fi if ! /usr/local/sbin/ipsec --version 2>/dev/null | grep -q "Libreswan"; then exiterr "This script requires Libreswan already installed." fi -if /usr/local/sbin/ipsec --version 2>/dev/null | grep -qF "$swan_ver"; then - echo "You already have Libreswan version $swan_ver installed! " +if /usr/local/sbin/ipsec --version 2>/dev/null | grep -qF "$SWAN_VER"; then + echo "You already have Libreswan version $SWAN_VER installed! " echo "If you continue, the same version will be re-installed." echo printf "Do you wish to continue anyway? [y/N] " @@ -60,7 +62,7 @@ fi clear cat < Makefile.inc.local <<'EOF' WERROR_CFLAGS = USE_DNSSEC = false EOF -make -s programs && make -s install +NPROCS="$(grep -c ^processor /proc/cpuinfo)" +[ -z "$NPROCS" ] && NPROCS=1 +make "-j$((NPROCS+1))" -s base && make -s install-base # Verify the install and clean up cd /opt/src || exiterr "Cannot enter /opt/src." -/bin/rm -rf "/opt/src/libreswan-$swan_ver" -if ! /usr/local/sbin/ipsec --version 2>/dev/null | grep -qF "$swan_ver"; then - exiterr "Libreswan $swan_ver failed to build." +/bin/rm -rf "/opt/src/libreswan-$SWAN_VER" +if ! /usr/local/sbin/ipsec --version 2>/dev/null | grep -qF "$SWAN_VER"; then + exiterr "Libreswan $SWAN_VER failed to build." fi # Restore SELinux contexts @@ -160,7 +167,7 @@ restorecon /usr/local/libexec/ipsec -Rv 2>/dev/null # Update ipsec.conf for Libreswan 3.19 and newer IKE_NEW=" ike=3des-sha1,3des-sha2,aes-sha1,aes-sha1;modp1024,aes-sha2,aes-sha2;modp1024,aes256-sha2_512" PHASE2_NEW=" phase2alg=3des-sha1,3des-sha2,aes-sha1,aes-sha2,aes256-sha2_512" -sed -i".old-$(date +%Y-%m-%d-%H:%M:%S)" \ +sed -i".old-$(date +%F-%T)" \ -e "s/^[[:space:]]\+auth=esp\$/ phase2=esp/" \ -e "s/^[[:space:]]\+forceencaps=yes\$/ encapsulation=yes/" \ -e "s/^[[:space:]]\+ike=.\+\$/$IKE_NEW/" \ @@ -170,7 +177,12 @@ sed -i".old-$(date +%Y-%m-%d-%H:%M:%S)" \ service ipsec restart echo -echo "Libreswan $swan_ver was installed successfully! " +echo "Libreswan $SWAN_VER was installed successfully! " echo +} + +## Defer setup until we have the complete script +vpnupgrade "$@" + exit 0 diff --git a/vpnsetup.sh b/vpnsetup.sh index aebc7ce..a8527e6 100755 --- a/vpnsetup.sh +++ b/vpnsetup.sh @@ -22,7 +22,7 @@ # Define your own values for these variables # - IPsec pre-shared key, VPN username and password # - All values MUST be placed inside 'single quotes' -# - DO NOT use these characters within values: \ " ' +# - DO NOT use these special characters within values: \ " ' YOUR_IPSEC_PSK='' YOUR_USERNAME='' @@ -34,71 +34,64 @@ YOUR_PASSWORD='' # ===================================================== export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" -SYS_DT="$(date +%Y-%m-%d-%H:%M:%S)"; export SYS_DT +SYS_DT="$(date +%F-%T)" exiterr() { echo "Error: $1" >&2; exit 1; } -exiterr2() { echo "Error: 'apt-get install' failed." >&2; exit 1; } +exiterr2() { exiterr "'apt-get install' failed."; } conf_bk() { /bin/cp -f "$1" "$1.old-$SYS_DT" 2>/dev/null; } bigecho() { echo; echo "## $1"; echo; } check_ip() { - IP_REGEX="^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" - printf %s "$1" | tr -d '\n' | grep -Eq "$IP_REGEX" + IP_REGEX='^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' + printf '%s' "$1" | tr -d '\n' | grep -Eq "$IP_REGEX" } +vpnsetup() { + os_type="$(lsb_release -si 2>/dev/null)" if [ -z "$os_type" ]; then [ -f /etc/os-release ] && os_type="$(. /etc/os-release && echo "$ID")" [ -f /etc/lsb-release ] && os_type="$(. /etc/lsb-release && echo "$DISTRIB_ID")" fi -if ! printf %s "$os_type" | head -n 1 | grep -qiF -e ubuntu -e debian -e raspbian; then - exiterr "This script only supports Ubuntu/Debian." +if ! printf '%s' "$os_type" | head -n 1 | grep -qiF -e ubuntu -e debian -e raspbian; then + exiterr "This script only supports Ubuntu and Debian." fi if [ "$(sed 's/\..*//' /etc/debian_version)" = "7" ]; then - exiterr "This script does not support Debian 7 (Wheezy)." + exiterr "Debian 7 is not supported." fi if [ -f /proc/user_beancounters ]; then - echo "Error: This script does not support OpenVZ VPS." >&2 - echo "Try OpenVPN: https://github.com/Nyr/openvpn-install" >&2 - exit 1 + exiterr "OpenVZ VPS is not supported. Try OpenVPN: github.com/Nyr/openvpn-install" fi if [ "$(id -u)" != 0 ]; then exiterr "Script must be run as root. Try 'sudo sh $0'" fi -NET_IFACE=${VPN_NET_IFACE:-'eth0'} -DEF_IFACE="$(route 2>/dev/null | grep '^default' | grep -o '[^ ]*$')" -[ -z "$DEF_IFACE" ] && DEF_IFACE="$(ip -4 route list 0/0 2>/dev/null | grep -Po '(?<=dev )(\S+)')" +net_iface=${VPN_NET_IFACE:-'eth0'} +def_iface="$(route 2>/dev/null | grep '^default' | grep -o '[^ ]*$')" +[ -z "$def_iface" ] && def_iface="$(ip -4 route list 0/0 2>/dev/null | grep -Po '(?<=dev )(\S+)')" -if_state1=$(cat "/sys/class/net/$DEF_IFACE/operstate" 2>/dev/null) -if [ -z "$VPN_NET_IFACE" ] && [ -n "$if_state1" ] && [ "$if_state1" != "down" ]; then +def_iface_state=$(cat "/sys/class/net/$def_iface/operstate" 2>/dev/null) +if [ -n "$def_iface_state" ] && [ "$def_iface_state" != "down" ]; then if ! grep -qs raspbian /etc/os-release; then - case "$DEF_IFACE" in + case "$def_iface" in wl*) -cat 1>&2 <> DO NOT RUN THIS SCRIPT ON YOUR PC OR MAC! << -If you are certain that this script is running on a server, re-run it with: - sudo VPN_NET_IFACE="$DEF_IFACE" sh "$0" -EOF - exit 1 + exiterr "Wireless interface '$def_iface' detected. DO NOT run this script on your PC or Mac!" ;; esac fi - NET_IFACE="$DEF_IFACE" + net_iface="$def_iface" fi -if_state2=$(cat "/sys/class/net/$NET_IFACE/operstate" 2>/dev/null) -if [ -z "$if_state2" ] || [ "$if_state2" = "down" ] || [ "$NET_IFACE" = "lo" ]; then - printf "Error: Network interface '%s' is not available.\n" "$NET_IFACE" >&2 +net_iface_state=$(cat "/sys/class/net/$net_iface/operstate" 2>/dev/null) +if [ -z "$net_iface_state" ] || [ "$net_iface_state" = "down" ] || [ "$net_iface" = "lo" ]; then + printf "Error: Network interface '%s' is not available.\n" "$net_iface" >&2 if [ -z "$VPN_NET_IFACE" ]; then cat 1>&2 </dev/null 2>&1; do + [ "$count" -ge "20" ] && exiterr "Cannot get apt/dpkg lock." + count=$((count+1)) + printf '%s' '.' + sleep 3 +done + export DEBIAN_FRONTEND=noninteractive apt-get -yq update || exiterr "'apt-get update' failed." bigecho "Installing packages required for setup..." -apt-get -yq install wget dnsutils openssl || exiterr2 -apt-get -yq install iproute gawk grep sed net-tools || exiterr2 +apt-get -yq install wget dnsutils openssl \ + iproute gawk grep sed net-tools || exiterr2 bigecho "Trying to auto discover IP of this server..." cat <<'EOF' In case the script hangs here for more than a few minutes, -use Ctrl-C to interrupt. Then edit it and manually enter IP. +press Ctrl-C to abort. Then edit it and manually enter IP. EOF # In case auto IP discovery fails, enter server's public IP here. @@ -160,16 +162,14 @@ PUBLIC_IP=${VPN_PUBLIC_IP:-''} # Check IP for correct format check_ip "$PUBLIC_IP" || PUBLIC_IP=$(wget -t 3 -T 15 -qO- http://ipv4.icanhazip.com) -check_ip "$PUBLIC_IP" || exiterr "Cannot find valid public IP. Edit the script and manually enter it." +check_ip "$PUBLIC_IP" || exiterr "Cannot detect this server's public IP. Edit the script and manually enter it." bigecho "Installing packages required for the VPN..." -apt-get -yq install libnss3-dev libnspr4-dev pkg-config libpam0g-dev \ - libcap-ng-dev libcap-ng-utils libselinux1-dev \ - libcurl4-nss-dev flex bison gcc make \ - libunbound-dev libnss3-tools libevent-dev || exiterr2 -apt-get -yq --no-install-recommends install xmlto || exiterr2 -apt-get -yq install ppp xl2tpd || exiterr2 +apt-get -yq install libnss3-dev libnspr4-dev pkg-config \ + libpam0g-dev libcap-ng-dev libcap-ng-utils libselinux1-dev \ + libcurl4-nss-dev flex bison gcc make libnss3-tools \ + libevent-dev ppp xl2tpd || exiterr2 bigecho "Installing Fail2Ban to protect SSH..." @@ -177,16 +177,21 @@ apt-get -yq install fail2ban || exiterr2 bigecho "Compiling and installing Libreswan..." -swan_ver=3.21 -swan_file="libreswan-$swan_ver.tar.gz" -swan_url1="https://github.com/libreswan/libreswan/archive/v$swan_ver.tar.gz" +if ! grep -qs raspbian /etc/os-release; then + SWAN_VER=3.22 +else + SWAN_VER=3.21 +fi +swan_file="libreswan-$SWAN_VER.tar.gz" +swan_url1="https://github.com/libreswan/libreswan/archive/v$SWAN_VER.tar.gz" swan_url2="https://download.libreswan.org/$swan_file" if ! { wget -t 3 -T 30 -nv -O "$swan_file" "$swan_url1" || wget -t 3 -T 30 -nv -O "$swan_file" "$swan_url2"; }; then exiterr "Cannot download Libreswan source." fi -/bin/rm -rf "/opt/src/libreswan-$swan_ver" +/bin/rm -rf "/opt/src/libreswan-$SWAN_VER" tar xzf "$swan_file" && /bin/rm -f "$swan_file" -cd "libreswan-$swan_ver" || exiterr "Cannot enter Libreswan source dir." +cd "libreswan-$SWAN_VER" || exiterr "Cannot enter Libreswan source dir." +[ "$SWAN_VER" = "3.22" ] && sed -i '/^#define LSWBUF_CANARY/s/-2$/((char) -2)/' include/lswlog.h cat > Makefile.inc.local <<'EOF' WERROR_CFLAGS = USE_DNSSEC = false @@ -194,13 +199,15 @@ EOF if [ "$(packaging/utils/lswan_detect.sh init)" = "systemd" ]; then apt-get -yq install libsystemd-dev || exiterr2 fi -make -s programs && make -s install +NPROCS="$(grep -c ^processor /proc/cpuinfo)" +[ -z "$NPROCS" ] && NPROCS=1 +make "-j$((NPROCS+1))" -s base && make -s install-base # Verify the install and clean up cd /opt/src || exiterr "Cannot enter /opt/src." -/bin/rm -rf "/opt/src/libreswan-$swan_ver" -if ! /usr/local/sbin/ipsec --version 2>/dev/null | grep -qF "$swan_ver"; then - exiterr "Libreswan $swan_ver failed to build." +/bin/rm -rf "/opt/src/libreswan-$SWAN_VER" +if ! /usr/local/sbin/ipsec --version 2>/dev/null | grep -qF "$SWAN_VER"; then + exiterr "Libreswan $SWAN_VER failed to build." fi bigecho "Creating VPN configuration..." @@ -219,9 +226,8 @@ cat > /etc/ipsec.conf < /etc/ipsec.secrets < /etc/ppp/chap-secrets <> /etc/sysctl.conf </dev/null \ - || ! iptables -t nat -C POSTROUTING -s "$XAUTH_NET" -o "$NET_IFACE" -m policy --dir out --pol none -j MASQUERADE 2>/dev/null; then + || ! iptables -t nat -C POSTROUTING -s "$L2TP_NET" -o "$net_iface" -j MASQUERADE 2>/dev/null \ + || ! iptables -t nat -C POSTROUTING -s "$XAUTH_NET" -o "$net_iface" -m policy --dir out --pol none -j MASQUERADE 2>/dev/null; then ipt_flag=1 fi @@ -386,17 +397,17 @@ if [ "$ipt_flag" = "1" ]; then iptables -I INPUT 5 -p udp --dport 1701 -m policy --dir in --pol ipsec -j ACCEPT iptables -I INPUT 6 -p udp --dport 1701 -j DROP iptables -I FORWARD 1 -m conntrack --ctstate INVALID -j DROP - iptables -I FORWARD 2 -i "$NET_IFACE" -o ppp+ -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT - iptables -I FORWARD 3 -i ppp+ -o "$NET_IFACE" -j ACCEPT + iptables -I FORWARD 2 -i "$net_iface" -o ppp+ -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT + iptables -I FORWARD 3 -i ppp+ -o "$net_iface" -j ACCEPT iptables -I FORWARD 4 -i ppp+ -o ppp+ -s "$L2TP_NET" -d "$L2TP_NET" -j ACCEPT - iptables -I FORWARD 5 -i "$NET_IFACE" -d "$XAUTH_NET" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT - iptables -I FORWARD 6 -s "$XAUTH_NET" -o "$NET_IFACE" -j ACCEPT + iptables -I FORWARD 5 -i "$net_iface" -d "$XAUTH_NET" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT + iptables -I FORWARD 6 -s "$XAUTH_NET" -o "$net_iface" -j ACCEPT # Uncomment if you wish to disallow traffic between VPN clients themselves # iptables -I FORWARD 2 -i ppp+ -o ppp+ -s "$L2TP_NET" -d "$L2TP_NET" -j DROP # iptables -I FORWARD 3 -s "$XAUTH_NET" -d "$XAUTH_NET" -j DROP iptables -A FORWARD -j DROP - iptables -t nat -I POSTROUTING -s "$XAUTH_NET" -o "$NET_IFACE" -m policy --dir out --pol none -j MASQUERADE - iptables -t nat -I POSTROUTING -s "$L2TP_NET" -o "$NET_IFACE" -j MASQUERADE + iptables -t nat -I POSTROUTING -s "$XAUTH_NET" -o "$net_iface" -m policy --dir out --pol none -j MASQUERADE + iptables -t nat -I POSTROUTING -s "$L2TP_NET" -o "$net_iface" -j MASQUERADE echo "# Modified by hwdsl2 VPN script" > "$IPT_FILE" iptables-save >> "$IPT_FILE" @@ -434,6 +445,7 @@ cat >> /etc/rc.local <<'EOF' (sleep 15 service ipsec restart service xl2tpd restart +[ -f "/usr/sbin/netplan" ] && iptables-restore < /etc/iptables.rules echo 1 > /proc/sys/net/ipv4/ip_forward)& exit 0 EOF @@ -478,4 +490,9 @@ Setup VPN clients: https://git.io/vpnclients EOF +} + +## Defer setup until we have the complete script +vpnsetup "$@" + exit 0 diff --git a/vpnsetup_centos.sh b/vpnsetup_centos.sh index 14e7158..0c8121a 100755 --- a/vpnsetup_centos.sh +++ b/vpnsetup_centos.sh @@ -22,7 +22,7 @@ # Define your own values for these variables # - IPsec pre-shared key, VPN username and password # - All values MUST be placed inside 'single quotes' -# - DO NOT use these characters within values: \ " ' +# - DO NOT use these special characters within values: \ " ' YOUR_IPSEC_PSK='' YOUR_USERNAME='' @@ -34,62 +34,55 @@ YOUR_PASSWORD='' # ===================================================== export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" -SYS_DT="$(date +%Y-%m-%d-%H:%M:%S)"; export SYS_DT +SYS_DT="$(date +%F-%T)" exiterr() { echo "Error: $1" >&2; exit 1; } -exiterr2() { echo "Error: 'yum install' failed." >&2; exit 1; } +exiterr2() { exiterr "'yum install' failed."; } conf_bk() { /bin/cp -f "$1" "$1.old-$SYS_DT" 2>/dev/null; } bigecho() { echo; echo "## $1"; echo; } check_ip() { - IP_REGEX="^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" - printf %s "$1" | tr -d '\n' | grep -Eq "$IP_REGEX" + IP_REGEX='^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' + printf '%s' "$1" | tr -d '\n' | grep -Eq "$IP_REGEX" } +vpnsetup() { + if ! grep -qs -e "release 6" -e "release 7" /etc/redhat-release; then exiterr "This script only supports CentOS/RHEL 6 and 7." fi if [ -f /proc/user_beancounters ]; then - echo "Error: This script does not support OpenVZ VPS." >&2 - echo "Try OpenVPN: https://github.com/Nyr/openvpn-install" >&2 - exit 1 + exiterr "OpenVZ VPS is not supported. Try OpenVPN: github.com/Nyr/openvpn-install" fi if [ "$(id -u)" != 0 ]; then exiterr "Script must be run as root. Try 'sudo sh $0'" fi -NET_IFACE=${VPN_NET_IFACE:-'eth0'} -DEF_IFACE="$(route 2>/dev/null | grep '^default' | grep -o '[^ ]*$')" -[ -z "$DEF_IFACE" ] && DEF_IFACE="$(ip -4 route list 0/0 2>/dev/null | grep -Po '(?<=dev )(\S+)')" +net_iface=${VPN_NET_IFACE:-'eth0'} +def_iface="$(route 2>/dev/null | grep '^default' | grep -o '[^ ]*$')" +[ -z "$def_iface" ] && def_iface="$(ip -4 route list 0/0 2>/dev/null | grep -Po '(?<=dev )(\S+)')" -if_state1=$(cat "/sys/class/net/$DEF_IFACE/operstate" 2>/dev/null) -if [ -z "$VPN_NET_IFACE" ] && [ -n "$if_state1" ] && [ "$if_state1" != "down" ]; then +def_iface_state=$(cat "/sys/class/net/$def_iface/operstate" 2>/dev/null) +if [ -n "$def_iface_state" ] && [ "$def_iface_state" != "down" ]; then if ! grep -qs raspbian /etc/os-release; then - case "$DEF_IFACE" in + case "$def_iface" in wl*) -cat 1>&2 <> DO NOT RUN THIS SCRIPT ON YOUR PC OR MAC! << -If you are certain that this script is running on a server, re-run it with: - sudo VPN_NET_IFACE="$DEF_IFACE" sh "$0" -EOF - exit 1 + exiterr "Wireless interface '$def_iface' detected. DO NOT run this script on your PC or Mac!" ;; esac fi - NET_IFACE="$DEF_IFACE" + net_iface="$def_iface" fi -if_state2=$(cat "/sys/class/net/$NET_IFACE/operstate" 2>/dev/null) -if [ -z "$if_state2" ] || [ "$if_state2" = "down" ] || [ "$NET_IFACE" = "lo" ]; then - printf "Error: Network interface '%s' is not available.\n" "$NET_IFACE" >&2 +net_iface_state=$(cat "/sys/class/net/$net_iface/operstate" 2>/dev/null) +if [ -z "$net_iface_state" ] || [ "$net_iface_state" = "down" ] || [ "$net_iface" = "lo" ]; then + printf "Error: Network interface '%s' is not available.\n" "$net_iface" >&2 if [ -z "$VPN_NET_IFACE" ]; then cat 1>&2 < Makefile.inc.local <<'EOF' WERROR_CFLAGS = USE_DNSSEC = false EOF -make -s programs && make -s install +NPROCS="$(grep -c ^processor /proc/cpuinfo)" +[ -z "$NPROCS" ] && NPROCS=1 +make "-j$((NPROCS+1))" -s base && make -s install-base # Verify the install and clean up cd /opt/src || exiterr "Cannot enter /opt/src." -/bin/rm -rf "/opt/src/libreswan-$swan_ver" -if ! /usr/local/sbin/ipsec --version 2>/dev/null | grep -qF "$swan_ver"; then - exiterr "Libreswan $swan_ver failed to build." +/bin/rm -rf "/opt/src/libreswan-$SWAN_VER" +if ! /usr/local/sbin/ipsec --version 2>/dev/null | grep -qF "$SWAN_VER"; then + exiterr "Libreswan $SWAN_VER failed to build." fi bigecho "Creating VPN configuration..." @@ -213,9 +210,8 @@ cat > /etc/ipsec.conf < /etc/ppp/chap-secrets <> /etc/sysctl.conf </dev/null \ - || ! iptables -t nat -C POSTROUTING -s "$XAUTH_NET" -o "$NET_IFACE" -m policy --dir out --pol none -j MASQUERADE 2>/dev/null; then + || ! iptables -t nat -C POSTROUTING -s "$L2TP_NET" -o "$net_iface" -j MASQUERADE 2>/dev/null \ + || ! iptables -t nat -C POSTROUTING -s "$XAUTH_NET" -o "$net_iface" -m policy --dir out --pol none -j MASQUERADE 2>/dev/null; then ipt_flag=1 fi @@ -374,17 +370,17 @@ if [ "$ipt_flag" = "1" ]; then iptables -I INPUT 5 -p udp --dport 1701 -m policy --dir in --pol ipsec -j ACCEPT iptables -I INPUT 6 -p udp --dport 1701 -j DROP iptables -I FORWARD 1 -m conntrack --ctstate INVALID -j DROP - iptables -I FORWARD 2 -i "$NET_IFACE" -o ppp+ -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT - iptables -I FORWARD 3 -i ppp+ -o "$NET_IFACE" -j ACCEPT + iptables -I FORWARD 2 -i "$net_iface" -o ppp+ -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT + iptables -I FORWARD 3 -i ppp+ -o "$net_iface" -j ACCEPT iptables -I FORWARD 4 -i ppp+ -o ppp+ -s "$L2TP_NET" -d "$L2TP_NET" -j ACCEPT - iptables -I FORWARD 5 -i "$NET_IFACE" -d "$XAUTH_NET" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT - iptables -I FORWARD 6 -s "$XAUTH_NET" -o "$NET_IFACE" -j ACCEPT + iptables -I FORWARD 5 -i "$net_iface" -d "$XAUTH_NET" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT + iptables -I FORWARD 6 -s "$XAUTH_NET" -o "$net_iface" -j ACCEPT # Uncomment if you wish to disallow traffic between VPN clients themselves # iptables -I FORWARD 2 -i ppp+ -o ppp+ -s "$L2TP_NET" -d "$L2TP_NET" -j DROP # iptables -I FORWARD 3 -s "$XAUTH_NET" -d "$XAUTH_NET" -j DROP iptables -A FORWARD -j DROP - iptables -t nat -I POSTROUTING -s "$XAUTH_NET" -o "$NET_IFACE" -m policy --dir out --pol none -j MASQUERADE - iptables -t nat -I POSTROUTING -s "$L2TP_NET" -o "$NET_IFACE" -j MASQUERADE + iptables -t nat -I POSTROUTING -s "$XAUTH_NET" -o "$net_iface" -m policy --dir out --pol none -j MASQUERADE + iptables -t nat -I POSTROUTING -s "$L2TP_NET" -o "$net_iface" -j MASQUERADE echo "# Modified by hwdsl2 VPN script" > "$IPT_FILE" iptables-save >> "$IPT_FILE" fi @@ -444,11 +440,10 @@ chmod 600 /etc/ipsec.secrets* /etc/ppp/chap-secrets* /etc/ipsec.d/passwd* # Apply new IPTables rules iptables-restore < "$IPT_FILE" -# Fix xl2tpd on CentOS 7 for providers such as Linode, -# where kernel module "l2tp_ppp" is unavailable +# Fix xl2tpd on CentOS 7, if kernel module "l2tp_ppp" is unavailable if grep -qs "release 7" /etc/redhat-release; then if ! modprobe -q l2tp_ppp; then - sed -i '/ExecStartPre/s/^/#/' /usr/lib/systemd/system/xl2tpd.service + sed -i '/^ExecStartPre/s/^/#/' /usr/lib/systemd/system/xl2tpd.service systemctl daemon-reload fi fi @@ -481,4 +476,9 @@ Setup VPN clients: https://git.io/vpnclients EOF +} + +## Defer setup until we have the complete script +vpnsetup "$@" + exit 0