diff --git a/extras/ikev2setup.sh b/extras/ikev2setup.sh index 7bbf815..200f95e 100644 --- a/extras/ikev2setup.sh +++ b/extras/ikev2setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Script to set up IKEv2 on Ubuntu, Debian and CentOS/RHEL +# Script to set up IKEv2 on Ubuntu, Debian, CentOS/RHEL and Amazon Linux 2 # # The latest version of this script is available at: # https://github.com/hwdsl2/setup-ipsec-vpn @@ -341,6 +341,7 @@ if [ "$mobike_support" = "1" ]; then [ "$os_type" = "ubuntu" ] && os_type=Ubuntu fi [ -z "$os_type" ] && [ -f /etc/redhat-release ] && os_type=CentOS/RHEL + grep -qs "Amazon Linux release 2" /etc/system-release && os_type=Amzn # Linux kernels on Ubuntu do not support MOBIKE if [ -z "$os_type" ] || [ "$os_type" = "Ubuntu" ]; then mobike_support=0 diff --git a/extras/vpnupgrade_amzn.sh b/extras/vpnupgrade_amzn.sh new file mode 100644 index 0000000..cef4887 --- /dev/null +++ b/extras/vpnupgrade_amzn.sh @@ -0,0 +1,262 @@ +#!/bin/sh +# +# Script to upgrade Libreswan on Amazon Linux 2 +# +# The latest version of this script is available at: +# https://github.com/hwdsl2/setup-ipsec-vpn +# +# Copyright (C) 2020 Lin Song +# +# This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 +# Unported License: http://creativecommons.org/licenses/by-sa/3.0/ +# +# Attribution required: please include my name in any derivative and let me +# know how you have improved it! + +# Specify which Libreswan version to install. See: https://libreswan.org +SWAN_VER=4.1 + +### 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() { exiterr "'yum install' failed."; } + +vpnupgrade() { + +if ! grep -qs "Amazon Linux release 2" /etc/system-release; then + echo "Error: This script only supports Amazon Linux 2." >&2 + echo "For Ubuntu/Debian, use https://git.io/vpnupgrade" >&2 + echo "For CentOS/RHEL, use https://git.io/vpnupgrade-centos" >&2 + exit 1 +fi + +if [ "$(id -u)" != 0 ]; then + exiterr "Script must be run as root. Try 'sudo sh $0'" +fi + +case "$SWAN_VER" in + 3.2[679]|3.3[12]|4.1) + /bin/true + ;; + *) +cat 1>&2 </dev/null) +ipsec_ver_short=$(printf '%s' "$ipsec_ver" | sed -e 's/Linux Libreswan/Libreswan/' -e 's/ (netkey) on .*//') +swan_ver_old=$(printf '%s' "$ipsec_ver_short" | sed -e 's/Libreswan //') +if ! printf '%s' "$ipsec_ver" | grep -q "Libreswan"; then +cat 1>&2 <<'EOF' +Error: This script requires Libreswan already installed. + See: https://github.com/hwdsl2/setup-ipsec-vpn +EOF + exit 1 +fi + +if [ "$swan_ver_old" = "$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 want to continue anyway? [y/N] " + read -r response + case $response in + [yY][eE][sS]|[yY]) + echo + ;; + *) + echo "Abort. No changes were made." + exit 1 + ;; + esac +fi + +clear + +cat <st_seen_fragvid) { return FALSE; }' programs/pluto/ikev2.c + sed -i '1033s/if (/if (LIN(POLICY_IKE_FRAG_ALLOW, sk->ike->sa.st_connection->policy) \&\& sk->ike->sa.st_seen_fragvid \&\& /' \ + programs/pluto/ikev2_message.c +fi +[ "$SWAN_VER" = "4.1" ] && sed -i 's/ sysv )/ sysvinit )/' programs/setup/setup.in +cat > Makefile.inc.local <<'EOF' +WERROR_CFLAGS=-w +USE_DNSSEC=false +EOF +if [ "$SWAN_VER" = "3.31" ] || [ "$SWAN_VER" = "3.32" ] || [ "$SWAN_VER" = "4.1" ]; then + echo "USE_DH2=true" >> Makefile.inc.local + if ! grep -qs IFLA_XFRM_LINK /usr/include/linux/if_link.h; then + echo "USE_XFRM_INTERFACE_IFLA_HEADER=true" >> Makefile.inc.local + fi +fi +if [ "$SWAN_VER" = "4.1" ]; then + echo "USE_NSS_KDF=false" >> Makefile.inc.local + echo "FINALNSSDIR=/etc/ipsec.d" >> Makefile.inc.local +fi +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 || exit 1 +/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 +restorecon /etc/ipsec.d/*db 2>/dev/null +restorecon /usr/local/sbin -Rv 2>/dev/null +restorecon /usr/local/libexec/ipsec -Rv 2>/dev/null + +# Update IPsec config +IKE_NEW=" ike=aes256-sha2,aes128-sha2,aes256-sha1,aes128-sha1,aes256-sha2;modp1024,aes128-sha1;modp1024" +PHASE2_NEW=" phase2alg=aes_gcm-null,aes128-sha1,aes256-sha1,aes256-sha2_512,aes128-sha2,aes256-sha2" + +dns_state=0 +DNS_SRV1=$(grep "modecfgdns1=" /etc/ipsec.conf | head -n 1 | cut -d '=' -f 2) +DNS_SRV2=$(grep "modecfgdns2=" /etc/ipsec.conf | head -n 1 | cut -d '=' -f 2) +[ -n "$DNS_SRV1" ] && dns_state=2 +[ -n "$DNS_SRV1" ] && [ -n "$DNS_SRV2" ] && dns_state=1 +[ "$(grep -c "modecfgdns1=" /etc/ipsec.conf)" -gt "1" ] && dns_state=3 + +sed -i".old-$(date +%F-%T)" \ + -e "s/^[[:space:]]\+auth=/ phase2=/" \ + -e "s/^[[:space:]]\+forceencaps=/ encapsulation=/" \ + -e "s/^[[:space:]]\+ike-frag=/ fragmentation=/" \ + -e "s/^[[:space:]]\+sha2_truncbug=/ sha2-truncbug=/" \ + -e "s/^[[:space:]]\+sha2-truncbug=yes/ sha2-truncbug=no/" \ + -e "s/^[[:space:]]\+ike=.\+/$IKE_NEW/" \ + -e "s/^[[:space:]]\+phase2alg=.\+/$PHASE2_NEW/" /etc/ipsec.conf + +if [ "$dns_state" = "1" ]; then + sed -i -e "s/^[[:space:]]\+modecfgdns1=.\+/ modecfgdns=\"$DNS_SRV1 $DNS_SRV2\"/" \ + -e "/modecfgdns2=/d" /etc/ipsec.conf +elif [ "$dns_state" = "2" ]; then + sed -i "s/^[[:space:]]\+modecfgdns1=.\+/ modecfgdns=$DNS_SRV1/" /etc/ipsec.conf +fi + +case "$SWAN_VER" in + 3.29|3.3[12]|4.1) + sed -i "/ikev2=never/d" /etc/ipsec.conf + sed -i "/conn shared/a \ ikev2=never" /etc/ipsec.conf + ;; +esac + +if grep -qs ike-frag /etc/ipsec.d/ikev2.conf; then + sed -i 's/^[[:space:]]\+ike-frag=/ fragmentation=/' /etc/ipsec.d/ikev2.conf +fi + +# Restart IPsec service +mkdir -p /run/pluto +service ipsec restart + +cat < +# +# This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 +# Unported License: http://creativecommons.org/licenses/by-sa/3.0/ +# +# Attribution required: please include my name in any derivative and let me +# know how you have improved it! + +# ===================================================== + +# 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 special characters within values: \ " ' + +YOUR_IPSEC_PSK='' +YOUR_USERNAME='' +YOUR_PASSWORD='' + +# Important notes: https://git.io/vpnnotes +# Setup VPN clients: https://git.io/vpnclients +# IKEv2 guide: https://git.io/ikev2 + +# ===================================================== + +export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" +SYS_DT=$(date +%F-%T | tr ':' '_') + +exiterr() { echo "Error: $1" >&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" +} + +vpnsetup() { + +if ! grep -qs "Amazon Linux release 2" /etc/system-release; then + echo "Error: This script only supports Amazon Linux 2." >&2 + echo "For Ubuntu/Debian, use https://git.io/vpnsetup" >&2 + echo "For CentOS/RHEL, use https://git.io/vpnsetup-centos" >&2 + exit 1 +fi + +if [ "$(id -u)" != 0 ]; then + exiterr "Script must be run as root. Try 'sudo sh $0'" +fi + +def_iface=$(route 2>/dev/null | grep -m 1 '^default' | grep -o '[^ ]*$') +[ -z "$def_iface" ] && def_iface=$(ip -4 route list 0/0 2>/dev/null | grep -m 1 -Po '(?<=dev )(\S+)') +def_state=$(cat "/sys/class/net/$def_iface/operstate" 2>/dev/null) +if [ -n "$def_state" ] && [ "$def_state" != "down" ]; then + case "$def_iface" in + wl*) + exiterr "Wireless interface '$def_iface' detected. DO NOT run this script on your PC or Mac!" + ;; + esac + NET_IFACE="$def_iface" +else + eth0_state=$(cat "/sys/class/net/eth0/operstate" 2>/dev/null) + if [ -z "$eth0_state" ] || [ "$eth0_state" = "down" ]; then + exiterr "Could not detect the default network interface." + fi + NET_IFACE=eth0 +fi + +[ -n "$YOUR_IPSEC_PSK" ] && VPN_IPSEC_PSK="$YOUR_IPSEC_PSK" +[ -n "$YOUR_USERNAME" ] && VPN_USER="$YOUR_USERNAME" +[ -n "$YOUR_PASSWORD" ] && VPN_PASSWORD="$YOUR_PASSWORD" + +if [ -z "$VPN_IPSEC_PSK" ] && [ -z "$VPN_USER" ] && [ -z "$VPN_PASSWORD" ]; then + bigecho "VPN credentials not set by user. Generating random PSK and password..." + VPN_IPSEC_PSK=$(LC_CTYPE=C tr -dc 'A-HJ-NPR-Za-km-z2-9' < /dev/urandom | head -c 20) + VPN_USER=vpnuser + VPN_PASSWORD=$(LC_CTYPE=C tr -dc 'A-HJ-NPR-Za-km-z2-9' < /dev/urandom | head -c 16) +fi + +if [ -z "$VPN_IPSEC_PSK" ] || [ -z "$VPN_USER" ] || [ -z "$VPN_PASSWORD" ]; then + exiterr "All VPN credentials must be specified. Edit the script and re-enter them." +fi + +if printf '%s' "$VPN_IPSEC_PSK $VPN_USER $VPN_PASSWORD" | LC_ALL=C grep -q '[^ -~]\+'; then + exiterr "VPN credentials must not contain non-ASCII characters." +fi + +case "$VPN_IPSEC_PSK $VPN_USER $VPN_PASSWORD" in + *[\\\"\']*) + exiterr "VPN credentials must not contain these special characters: \\ \" '" + ;; +esac + +if { [ -n "$VPN_DNS_SRV1" ] && ! check_ip "$VPN_DNS_SRV1"; } \ + || { [ -n "$VPN_DNS_SRV2" ] && ! check_ip "$VPN_DNS_SRV2"; } then + exiterr "The DNS server specified is invalid." +fi + +bigecho "VPN setup in progress... Please be patient." + +# Create and change to working dir +mkdir -p /opt/src +cd /opt/src || exit 1 + +bigecho "Installing packages required for setup..." + +yum -y install wget bind-utils openssl tar \ + iptables 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, +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. +PUBLIC_IP=${VPN_PUBLIC_IP:-''} + +[ -z "$PUBLIC_IP" ] && PUBLIC_IP=$(dig @resolver1.opendns.com -t A -4 myip.opendns.com +short) + +check_ip "$PUBLIC_IP" || PUBLIC_IP=$(wget -t 3 -T 15 -qO- http://ipv4.icanhazip.com) +check_ip "$PUBLIC_IP" || exiterr "Cannot detect this server's public IP. Edit the script and manually enter it." + +bigecho "Adding the EPEL repository..." + +amazon-linux-extras install epel -y || exiterr2 + +bigecho "Installing packages required for the VPN..." + +REPO1='--enablerepo=epel' + +yum -y install nss-devel nspr-devel pkgconfig pam-devel \ + libcap-ng-devel libselinux-devel curl-devel nss-tools \ + flex bison gcc make ppp \ + systemd-devel iptables-services \ + libevent-devel fipscheck-devel || exiterr2 + +yum "$REPO1" -y install xl2tpd || exiterr2 + +bigecho "Installing Fail2Ban to protect SSH..." + +yum "$REPO1" -y install fail2ban || exiterr2 + +bigecho "Compiling and installing Libreswan..." + +SWAN_VER=4.1 +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 + exit 1 +fi +/bin/rm -rf "/opt/src/libreswan-$SWAN_VER" +tar xzf "$swan_file" && /bin/rm -f "$swan_file" +cd "libreswan-$SWAN_VER" || exit 1 +sed -i 's/ sysv )/ sysvinit )/' programs/setup/setup.in +cat > Makefile.inc.local <<'EOF' +WERROR_CFLAGS=-w +USE_DNSSEC=false +USE_DH2=true +USE_NSS_KDF=false +FINALNSSDIR=/etc/ipsec.d +EOF +if ! grep -qs IFLA_XFRM_LINK /usr/include/linux/if_link.h; then + echo "USE_XFRM_INTERFACE_IFLA_HEADER=true" >> Makefile.inc.local +fi +NPROCS=$(grep -c ^processor /proc/cpuinfo) +[ -z "$NPROCS" ] && NPROCS=1 +make "-j$((NPROCS+1))" -s base && make -s install-base + +cd /opt/src || exit 1 +/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..." + +L2TP_NET=${VPN_L2TP_NET:-'192.168.42.0/24'} +L2TP_LOCAL=${VPN_L2TP_LOCAL:-'192.168.42.1'} +L2TP_POOL=${VPN_L2TP_POOL:-'192.168.42.10-192.168.42.250'} +XAUTH_NET=${VPN_XAUTH_NET:-'192.168.43.0/24'} +XAUTH_POOL=${VPN_XAUTH_POOL:-'192.168.43.10-192.168.43.250'} +DNS_SRV1=${VPN_DNS_SRV1:-'8.8.8.8'} +DNS_SRV2=${VPN_DNS_SRV2:-'8.8.4.4'} +DNS_SRVS="\"$DNS_SRV1 $DNS_SRV2\"" +[ -n "$VPN_DNS_SRV1" ] && [ -z "$VPN_DNS_SRV2" ] && DNS_SRVS="$DNS_SRV1" + +# Create IPsec config +conf_bk "/etc/ipsec.conf" +cat > /etc/ipsec.conf < /etc/ipsec.secrets < /etc/xl2tpd/xl2tpd.conf < /etc/ppp/options.xl2tpd <> /etc/ppp/options.xl2tpd < /etc/ppp/chap-secrets < /etc/ipsec.d/passwd <> /etc/sysctl.conf < "$F2B_FILE" <<'EOF' +[ssh-iptables] +enabled = true +filter = sshd +logpath = /var/log/secure +action = iptables[name=SSH, port=ssh, protocol=tcp] +EOF +fi + +bigecho "Updating IPTables rules..." + +IPT_FILE=/etc/sysconfig/iptables +ipt_flag=0 +if ! grep -qs "hwdsl2 VPN script" "$IPT_FILE"; then + ipt_flag=1 +fi + +if [ "$ipt_flag" = "1" ]; then + service fail2ban stop >/dev/null 2>&1 + iptables-save > "$IPT_FILE.old-$SYS_DT" + iptables -I INPUT 1 -p udp --dport 1701 -m policy --dir in --pol none -j DROP + iptables -I INPUT 2 -m conntrack --ctstate INVALID -j DROP + iptables -I INPUT 3 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT + iptables -I INPUT 4 -p udp -m multiport --dports 500,4500 -j ACCEPT + 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 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 + # Uncomment to disallow traffic between VPN clients + # 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 -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 -A FORWARD -j DROP + iptables-save >> "$IPT_FILE" +fi + +bigecho "Enabling services on boot..." + +systemctl --now mask firewalld 2>/dev/null +systemctl enable iptables fail2ban 2>/dev/null + +if ! grep -qs "hwdsl2 VPN script" /etc/rc.local; then + if [ -f /etc/rc.local ]; then + conf_bk "/etc/rc.local" + else + echo '#!/bin/sh' > /etc/rc.local + fi +cat >> /etc/rc.local <<'EOF' + +# Added by hwdsl2 VPN script +(sleep 15 +service ipsec restart +service xl2tpd restart +echo 1 > /proc/sys/net/ipv4/ip_forward)& +EOF +fi + +bigecho "Starting services..." + +restorecon /etc/ipsec.d/*db 2>/dev/null +restorecon /usr/local/sbin -Rv 2>/dev/null +restorecon /usr/local/libexec/ipsec -Rv 2>/dev/null + +sysctl -e -q -p + +chmod +x /etc/rc.local +chmod 600 /etc/ipsec.secrets* /etc/ppp/chap-secrets* /etc/ipsec.d/passwd* + +iptables-restore < "$IPT_FILE" + +# Fix xl2tpd if l2tp_ppp is unavailable +if ! modprobe -q l2tp_ppp; then + sed -i '/^ExecStartPre=\//s/=/=-/' /usr/lib/systemd/system/xl2tpd.service + systemctl daemon-reload +fi + +mkdir -p /run/pluto +service fail2ban restart 2>/dev/null +service ipsec restart 2>/dev/null +service xl2tpd restart 2>/dev/null + +cat <