diff --git a/extras/ikev2setup.sh b/extras/ikev2setup.sh index a02c8c5..e7e9844 100755 --- a/extras/ikev2setup.sh +++ b/extras/ikev2setup.sh @@ -8,7 +8,7 @@ # The latest version of this script is available at: # https://github.com/hwdsl2/setup-ipsec-vpn # -# Copyright (C) 2020-2025 Lin Song +# Copyright (C) 2020-2026 Lin Song # # This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 # Unported License: http://creativecommons.org/licenses/by-sa/3.0/ @@ -169,7 +169,7 @@ confirm_or_abort() { show_header() { cat <<'EOF' -IKEv2 Script Copyright (c) 2020-2025 Lin Song 2 Sep 2025 +IKEv2 Script Copyright (c) 2020-2026 Lin Song 16 Mar 2026 EOF } @@ -1177,6 +1177,13 @@ EOF add_ikev2_connection() { bigecho2 "Adding a new IKEv2 connection..." XAUTH_POOL=${VPN_XAUTH_POOL:-'192.168.43.10-192.168.43.250'} + IP6_NET=${VPN_IP6_NET:-'fddd:500:500:500::/64'} + lsubnet="0.0.0.0/0" + rpool="$XAUTH_POOL" + if [ -n "$VPN_PUBLIC_IP6" ]; then + lsubnet="0.0.0.0/0,::/0" + rpool="$XAUTH_POOL,$IP6_NET" + fi if ! grep -qs '^include /etc/ipsec\.d/\*\.conf$' "$IPSEC_CONF"; then echo >> "$IPSEC_CONF" echo 'include /etc/ipsec.d/*.conf' >> "$IPSEC_CONF" @@ -1187,11 +1194,11 @@ conn ikev2-cp left=%defaultroute leftcert=$server_addr leftsendcert=always - leftsubnet=0.0.0.0/0 + leftsubnet=$lsubnet leftrsasigkey=%cert right=%any rightid=%fromcert - rightaddresspool=$XAUTH_POOL + rightaddresspool=$rpool rightca=%same rightrsasigkey=%cert narrowing=yes diff --git a/extras/vpnuninstall.sh b/extras/vpnuninstall.sh index 6841966..6da1cb4 100755 --- a/extras/vpnuninstall.sh +++ b/extras/vpnuninstall.sh @@ -184,9 +184,15 @@ update_sysctl() { count=17 line1=$(grep -A 18 "hwdsl2 VPN script" /etc/sysctl.conf | tail -n 1) line2=$(grep -A 19 "hwdsl2 VPN script" /etc/sysctl.conf | tail -n 1) + line3=$(grep -A 20 "hwdsl2 VPN script" /etc/sysctl.conf | tail -n 1) if [ "$line1" = "net.core.default_qdisc = fq" ] \ && [ "$line2" = "net.ipv4.tcp_congestion_control = bbr" ]; then - count=19 + count=19 + if [ "$line3" = "net.ipv6.conf.all.forwarding = 1" ]; then + count=20 + fi + elif [ "$line1" = "net.ipv6.conf.all.forwarding = 1" ]; then + count=18 fi if [ "$os_type" = "alpine" ]; then sed -i "/# Added by hwdsl2 VPN script/,+${count}d" /etc/sysctl.conf @@ -219,8 +225,8 @@ get_vpn_subnets() { if ! grep -q "$L2TP_NET" /etc/ipsec.conf \ || ! grep -q "$XAUTH_NET" /etc/ipsec.conf; then vipr=$(grep "virtual-private=" /etc/ipsec.conf) - l2tpnet=$(printf '%s' "$vipr" | cut -f2 -d '!' | sed 's/,%v4://') - xauthnet=$(printf '%s' "$vipr" | cut -f3 -d '!') + l2tpnet=$(printf '%s' "$vipr" | cut -f2 -d '!' | cut -f1 -d ',') + xauthnet=$(printf '%s' "$vipr" | cut -f3 -d '!' | cut -f1 -d ',') check_cidr "$l2tpnet" && L2TP_NET="$l2tpnet" check_cidr "$xauthnet" && XAUTH_NET="$xauthnet" fi @@ -276,6 +282,30 @@ update_iptables_rules() { /bin/cp -f "$IPT_FILE" "$IPT_FILE2" fi fi + if [ "$os_type" = "ubuntu" ] || [ "$os_type" = "debian" ] \ + || [ "$os_type" = "alpine" ]; then + IPT6_FILE=/etc/ip6tables.rules + IPT6_FILE2=/etc/iptables/rules.v6 + else + IPT6_FILE=/etc/sysconfig/ip6tables + IPT6_FILE2="" + fi + if grep -qs "hwdsl2 VPN script" "$IPT6_FILE" 2>/dev/null; then + IP6_NET=$(grep 'FORWARD.*-d ' "$IPT6_FILE" \ + | sed -n 's/.* -d \([^ ]*\).*/\1/p' | head -n 1) + [ -z "$IP6_NET" ] && IP6_NET='fddd:500:500:500::/64' + ip6tables -D INPUT -m conntrack --ctstate INVALID -j DROP 2>/dev/null + ip6tables -D INPUT -m conntrack --ctstate "$res" -j ACCEPT 2>/dev/null + ip6tables -D INPUT -p udp -m multiport --dports 500,4500 -j ACCEPT 2>/dev/null + ip6tables -D FORWARD -m conntrack --ctstate INVALID -j DROP 2>/dev/null + ip6tables -D FORWARD -i "$NET_IFACE" -d "$IP6_NET" \ + -m conntrack --ctstate "$res" -j ACCEPT 2>/dev/null + ip6tables -D FORWARD -s "$IP6_NET" -o "$NET_IFACE" -j ACCEPT 2>/dev/null + ip6tables -t nat -D POSTROUTING -s "$IP6_NET" -o "$NET_IFACE" \ + -m policy --dir out --pol none -j MASQUERADE 2>/dev/null + /bin/rm -f "$IPT6_FILE" + [ -n "$IPT6_FILE2" ] && /bin/rm -f "$IPT6_FILE2" + fi else nft_bk=$(find /etc/sysconfig -maxdepth 1 -name 'nftables.conf.old-*-*-*-*_*_*' -print0 \ | xargs -r -0 ls -1 -t | head -1) diff --git a/extras/vpnupgrade_alpine.sh b/extras/vpnupgrade_alpine.sh index ba301ac..7855b29 100755 --- a/extras/vpnupgrade_alpine.sh +++ b/extras/vpnupgrade_alpine.sh @@ -143,7 +143,7 @@ install_pkgs() { bigecho "Installing required packages..." ( set -x - apk add -U -q bash bind-tools coreutils openssl wget iptables iproute2 \ + apk add -U -q bash bind-tools coreutils openssl wget iptables ip6tables iproute2 \ sed grep libcap-ng libcurl libevent linux-pam musl nspr nss nss-tools \ bison flex gcc make libc-dev bsd-compat-headers linux-pam-dev nss-dev \ libcap-ng-dev libevent-dev curl-dev nspr-dev uuidgen openrc diff --git a/vpnsetup.sh b/vpnsetup.sh index b1afe09..1012264 100755 --- a/vpnsetup.sh +++ b/vpnsetup.sh @@ -8,7 +8,7 @@ # The latest version of this script is available at: # https://github.com/hwdsl2/setup-ipsec-vpn # -# Copyright (C) 2021-2025 Lin Song +# Copyright (C) 2021-2026 Lin Song # # This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 # Unported License: http://creativecommons.org/licenses/by-sa/3.0/ @@ -282,6 +282,7 @@ run_setup() { VPN_PROTECT_CONFIG="$VPN_PROTECT_CONFIG" \ VPN_CLIENT_VALIDITY="$VPN_CLIENT_VALIDITY" \ VPN_SKIP_IKEV2="$VPN_SKIP_IKEV2" VPN_SWAN_VER="$VPN_SWAN_VER" \ + VPN_PUBLIC_IP6="$VPN_PUBLIC_IP6" VPN_IP6_NET="$VPN_IP6_NET" \ /bin/bash "$tmpdir/vpn.sh" || status=1 else status=1 diff --git a/vpnsetup_alpine.sh b/vpnsetup_alpine.sh index f93c55a..b9c6cc8 100755 --- a/vpnsetup_alpine.sh +++ b/vpnsetup_alpine.sh @@ -7,7 +7,7 @@ # The latest version of this script is available at: # https://github.com/hwdsl2/setup-ipsec-vpn # -# Copyright (C) 2021-2025 Lin Song +# Copyright (C) 2021-2026 Lin Song # # This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 # Unported License: http://creativecommons.org/licenses/by-sa/3.0/ @@ -41,6 +41,11 @@ check_ip() { printf '%s' "$1" | tr -d '\n' | grep -Eq "$IP_REGEX" } +check_ip6() { + IP6_REGEX='^[0-9a-fA-F]{0,4}(:[0-9a-fA-F]{0,4}){1,7}$' + printf '%s' "$1" | tr -d '\n' | grep -Eq "$IP6_REGEX" +} + check_dns_name() { FQDN_REGEX='^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$' printf '%s' "$1" | tr -d '\n' | grep -Eq "$FQDN_REGEX" @@ -165,7 +170,7 @@ install_setup_pkgs() { bigecho "Installing packages required for setup..." ( set -x - apk add -U -q bash bind-tools coreutils openssl wget iptables iproute2 sed grep + apk add -U -q bash bind-tools coreutils openssl wget iptables ip6tables iproute2 sed grep ) || exiterr2 } @@ -188,6 +193,20 @@ detect_ip() { check_ip "$public_ip" || exiterr "Cannot detect this server's public IP. Define it as variable 'VPN_PUBLIC_IP' and re-run this script." } +detect_ipv6() { + ip6="" + if ! printf '%s\n%s' "5.0" "$SWAN_VER" | sort -C -V; then + return 0 + fi + if [ -n "$VPN_PUBLIC_IP6" ]; then + ip6="$VPN_PUBLIC_IP6" + check_ip6 "$ip6" || exiterr "Invalid IPv6 address. Check variable 'VPN_PUBLIC_IP6'." + else + ip6_addr=$(ip -6 addr 2>/dev/null | awk '/inet6 [23]/ {print $2}' | cut -d'/' -f1 | head -n1) + [ -n "$ip6_addr" ] && ip6="$ip6_addr" + fi +} + install_vpn_pkgs() { bigecho "Installing packages required for the VPN..." ( @@ -335,6 +354,9 @@ create_vpn_config() { 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" + IP6_NET=${VPN_IP6_NET:-'fddd:500:500:500::/64'} + vp_ip6="" + [ -n "$ip6" ] && vp_ip6=",%v6:fc00::/7,%v6:!$IP6_NET" # Create IPsec config conf_bk "/etc/ipsec.conf" cat > /etc/ipsec.conf <> /etc/sysctl.conf <<'EOF' +net.ipv6.conf.all.forwarding = 1 +EOF + fi fi } @@ -503,6 +530,23 @@ update_iptables() { $ipp -s "$L2TP_NET" -o "$NET_IFACE" -j MASQUERADE echo "# Modified by hwdsl2 VPN script" > "$IPT_FILE" iptables-save >> "$IPT_FILE" + if [ -n "$ip6" ]; then + IP6_NET=${VPN_IP6_NET:-'fddd:500:500:500::/64'} + IPT6_FILE=/etc/ip6tables.rules + ip6tables-save > "$IPT6_FILE.old-$SYS_DT" + ip6ti='ip6tables -I INPUT' + ip6tf='ip6tables -I FORWARD' + ip6tp='ip6tables -t nat -I POSTROUTING' + $ip6ti 1 -m conntrack --ctstate INVALID -j DROP + $ip6ti 2 -m conntrack --ctstate "$res" -j ACCEPT + $ip6ti 3 -p udp -m multiport --dports 500,4500 -j ACCEPT + $ip6tf 1 -m conntrack --ctstate INVALID -j DROP + $ip6tf 2 -i "$NET_IFACE" -d "$IP6_NET" -m conntrack --ctstate "$res" -j ACCEPT + $ip6tf 3 -s "$IP6_NET" -o "$NET_IFACE" -j ACCEPT + $ip6tp -s "$IP6_NET" -o "$NET_IFACE" -m policy --dir out --pol none -j MASQUERADE + echo "# Modified by hwdsl2 VPN script" > "$IPT6_FILE" + ip6tables-save >> "$IPT6_FILE" + fi fi } @@ -512,6 +556,7 @@ enable_on_boot() { cat > /etc/network/if-pre-up.d/iptablesload <<'EOF' #!/bin/sh iptables-restore < /etc/iptables.rules +[ -f /etc/ip6tables.rules ] && ip6tables-restore < /etc/ip6tables.rules exit 0 EOF chmod +x /etc/network/if-pre-up.d/iptablesload @@ -581,6 +626,7 @@ set_up_ikev2() { VPN_DNS_SRV1="$VPN_DNS_SRV1" VPN_DNS_SRV2="$VPN_DNS_SRV2" \ VPN_PROTECT_CONFIG="$VPN_PROTECT_CONFIG" \ VPN_CLIENT_VALIDITY="$VPN_CLIENT_VALIDITY" \ + VPN_PUBLIC_IP6="$ip6" \ /bin/bash /opt/src/ikev2.sh --auto || status=1 fi elif [ -s /opt/src/ikev2.sh ]; then @@ -614,6 +660,7 @@ vpnsetup() { start_setup install_setup_pkgs detect_ip + detect_ipv6 install_vpn_pkgs install_fail2ban get_helper_scripts diff --git a/vpnsetup_amzn.sh b/vpnsetup_amzn.sh index a7fe0f6..d44fdcb 100755 --- a/vpnsetup_amzn.sh +++ b/vpnsetup_amzn.sh @@ -7,7 +7,7 @@ # The latest version of this script is available at: # https://github.com/hwdsl2/setup-ipsec-vpn # -# Copyright (C) 2020-2025 Lin Song +# Copyright (C) 2020-2026 Lin Song # # This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 # Unported License: http://creativecommons.org/licenses/by-sa/3.0/ @@ -41,6 +41,11 @@ check_ip() { printf '%s' "$1" | tr -d '\n' | grep -Eq "$IP_REGEX" } +check_ip6() { + IP6_REGEX='^[0-9a-fA-F]{0,4}(:[0-9a-fA-F]{0,4}){1,7}$' + printf '%s' "$1" | tr -d '\n' | grep -Eq "$IP6_REGEX" +} + check_dns_name() { FQDN_REGEX='^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$' printf '%s' "$1" | tr -d '\n' | grep -Eq "$FQDN_REGEX" @@ -175,6 +180,20 @@ detect_ip() { check_ip "$public_ip" || exiterr "Cannot detect this server's public IP. Define it as variable 'VPN_PUBLIC_IP' and re-run this script." } +detect_ipv6() { + ip6="" + if ! printf '%s\n%s' "5.0" "$SWAN_VER" | sort -C -V; then + return 0 + fi + if [ -n "$VPN_PUBLIC_IP6" ]; then + ip6="$VPN_PUBLIC_IP6" + check_ip6 "$ip6" || exiterr "Invalid IPv6 address. Check variable 'VPN_PUBLIC_IP6'." + else + ip6_addr=$(ip -6 addr 2>/dev/null | awk '/inet6 [23]/ {print $2}' | cut -d'/' -f1 | head -n1) + [ -n "$ip6_addr" ] && ip6="$ip6_addr" + fi +} + add_epel_repo() { bigecho "Adding the EPEL repository..." ( @@ -359,6 +378,9 @@ create_vpn_config() { 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" + IP6_NET=${VPN_IP6_NET:-'fddd:500:500:500::/64'} + vp_ip6="" + [ -n "$ip6" ] && vp_ip6=",%v6:fc00::/7,%v6:!$IP6_NET" # Create IPsec config conf_bk "/etc/ipsec.conf" cat > /etc/ipsec.conf <> /etc/sysctl.conf <<'EOF' +net.ipv6.conf.all.forwarding = 1 +EOF + fi fi } @@ -522,6 +549,23 @@ update_iptables() { $ipp -s "$L2TP_NET" -o "$NET_IFACE" -j MASQUERADE echo "# Modified by hwdsl2 VPN script" > "$IPT_FILE" iptables-save >> "$IPT_FILE" + if [ -n "$ip6" ]; then + IP6_NET=${VPN_IP6_NET:-'fddd:500:500:500::/64'} + IPT6_FILE=/etc/sysconfig/ip6tables + ip6tables-save > "$IPT6_FILE.old-$SYS_DT" + ip6ti='ip6tables -I INPUT' + ip6tf='ip6tables -I FORWARD' + ip6tp='ip6tables -t nat -I POSTROUTING' + $ip6ti 1 -m conntrack --ctstate INVALID -j DROP + $ip6ti 2 -m conntrack --ctstate "$res" -j ACCEPT + $ip6ti 3 -p udp -m multiport --dports 500,4500 -j ACCEPT + $ip6tf 1 -m conntrack --ctstate INVALID -j DROP + $ip6tf 2 -i "$NET_IFACE" -d "$IP6_NET" -m conntrack --ctstate "$res" -j ACCEPT + $ip6tf 3 -s "$IP6_NET" -o "$NET_IFACE" -j ACCEPT + $ip6tp -s "$IP6_NET" -o "$NET_IFACE" -m policy --dir out --pol none -j MASQUERADE + echo "# Modified by hwdsl2 VPN script" > "$IPT6_FILE" + ip6tables-save >> "$IPT6_FILE" + fi fi } @@ -606,6 +650,7 @@ set_up_ikev2() { VPN_DNS_SRV1="$VPN_DNS_SRV1" VPN_DNS_SRV2="$VPN_DNS_SRV2" \ VPN_PROTECT_CONFIG="$VPN_PROTECT_CONFIG" \ VPN_CLIENT_VALIDITY="$VPN_CLIENT_VALIDITY" \ + VPN_PUBLIC_IP6="$ip6" \ /bin/bash /opt/src/ikev2.sh --auto || status=1 fi elif [ -s /opt/src/ikev2.sh ]; then @@ -638,6 +683,7 @@ vpnsetup() { start_setup install_setup_pkgs detect_ip + detect_ipv6 add_epel_repo install_vpn_pkgs_1 install_vpn_pkgs_2 diff --git a/vpnsetup_centos.sh b/vpnsetup_centos.sh index 4be0ff2..fcd6428 100755 --- a/vpnsetup_centos.sh +++ b/vpnsetup_centos.sh @@ -8,7 +8,7 @@ # The latest version of this script is available at: # https://github.com/hwdsl2/setup-ipsec-vpn # -# Copyright (C) 2015-2025 Lin Song +# Copyright (C) 2015-2026 Lin Song # Based on the work of Thomas Sarlandie (Copyright 2012) # # This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 @@ -43,6 +43,11 @@ check_ip() { printf '%s' "$1" | tr -d '\n' | grep -Eq "$IP_REGEX" } +check_ip6() { + IP6_REGEX='^[0-9a-fA-F]{0,4}(:[0-9a-fA-F]{0,4}){1,7}$' + printf '%s' "$1" | tr -d '\n' | grep -Eq "$IP6_REGEX" +} + check_dns_name() { FQDN_REGEX='^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$' printf '%s' "$1" | tr -d '\n' | grep -Eq "$FQDN_REGEX" @@ -229,6 +234,20 @@ detect_ip() { check_ip "$public_ip" || exiterr "Cannot detect this server's public IP. Define it as variable 'VPN_PUBLIC_IP' and re-run this script." } +detect_ipv6() { + ip6="" + if ! printf '%s\n%s' "5.0" "$SWAN_VER" | sort -C -V; then + return 0 + fi + if [ -n "$VPN_PUBLIC_IP6" ]; then + ip6="$VPN_PUBLIC_IP6" + check_ip6 "$ip6" || exiterr "Invalid IPv6 address. Check variable 'VPN_PUBLIC_IP6'." + else + ip6_addr=$(ip -6 addr 2>/dev/null | awk '/inet6 [23]/ {print $2}' | cut -d'/' -f1 | head -n1) + [ -n "$ip6_addr" ] && ip6="$ip6_addr" + fi +} + add_epel_repo() { bigecho "Adding the EPEL repository..." epel_url="https://dl.fedoraproject.org/pub/epel/epel-release-latest-$(rpm -E '%{rhel}').noarch.rpm" @@ -466,6 +485,9 @@ create_vpn_config() { 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" + IP6_NET=${VPN_IP6_NET:-'fddd:500:500:500::/64'} + vp_ip6="" + [ -n "$ip6" ] && vp_ip6=",%v6:fc00::/7,%v6:!$IP6_NET" # Create IPsec config conf_bk "/etc/ipsec.conf" cat > /etc/ipsec.conf <> /etc/sysctl.conf <<'EOF' net.core.default_qdisc = fq net.ipv4.tcp_congestion_control = bbr +EOF + fi + if [ -n "$ip6" ]; then +cat >> /etc/sysctl.conf <<'EOF' +net.ipv6.conf.all.forwarding = 1 EOF fi fi @@ -654,6 +681,19 @@ update_iptables() { $ipp -s "$XAUTH_NET" -o "$NET_IFACE" -m policy --dir out --pol none -j MASQUERADE fi $ipp -s "$L2TP_NET" -o "$NET_IFACE" -j MASQUERADE + if [ -n "$ip6" ]; then + IP6_NET=${VPN_IP6_NET:-'fddd:500:500:500::/64'} + ip6ti='ip6tables -I INPUT' + ip6tf='ip6tables -I FORWARD' + ip6tp='ip6tables -t nat -I POSTROUTING' + $ip6ti 1 -m conntrack --ctstate INVALID -j DROP + $ip6ti 2 -m conntrack --ctstate "$res" -j ACCEPT + $ip6ti 3 -p udp -m multiport --dports 500,4500 -j ACCEPT + $ip6tf 1 -m conntrack --ctstate INVALID -j DROP + $ip6tf 2 -i "$NET_IFACE" -d "$IP6_NET" -m conntrack --ctstate "$res" -j ACCEPT + $ip6tf 3 -s "$IP6_NET" -o "$NET_IFACE" -j ACCEPT + $ip6tp -s "$IP6_NET" -o "$NET_IFACE" -m policy --dir out --pol none -j MASQUERADE + fi echo "# Modified by hwdsl2 VPN script" > "$IPT_FILE" if [ "$use_nft" = 1 ]; then for vport in 500 4500 1701; do @@ -670,6 +710,12 @@ update_iptables() { nft list ruleset >> "$IPT_FILE" else iptables-save >> "$IPT_FILE" + if [ -n "$ip6" ]; then + IPT6_FILE=/etc/sysconfig/ip6tables + ip6tables-save > "$IPT6_FILE.old-$SYS_DT" + echo "# Modified by hwdsl2 VPN script" > "$IPT6_FILE" + ip6tables-save >> "$IPT6_FILE" + fi fi fi } @@ -792,6 +838,7 @@ set_up_ikev2() { VPN_DNS_SRV1="$VPN_DNS_SRV1" VPN_DNS_SRV2="$VPN_DNS_SRV2" \ VPN_PROTECT_CONFIG="$VPN_PROTECT_CONFIG" \ VPN_CLIENT_VALIDITY="$VPN_CLIENT_VALIDITY" \ + VPN_PUBLIC_IP6="$ip6" \ /bin/bash /opt/src/ikev2.sh --auto || status=1 fi elif [ -s /opt/src/ikev2.sh ]; then @@ -826,6 +873,7 @@ vpnsetup() { start_setup install_setup_pkgs detect_ip + detect_ipv6 add_epel_repo install_vpn_pkgs_1 install_vpn_pkgs_2 diff --git a/vpnsetup_ubuntu.sh b/vpnsetup_ubuntu.sh index e3d5824..2a82a54 100755 --- a/vpnsetup_ubuntu.sh +++ b/vpnsetup_ubuntu.sh @@ -7,7 +7,7 @@ # The latest version of this script is available at: # https://github.com/hwdsl2/setup-ipsec-vpn # -# Copyright (C) 2014-2025 Lin Song +# Copyright (C) 2014-2026 Lin Song # Based on the work of Thomas Sarlandie (Copyright 2012) # # This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 @@ -42,6 +42,11 @@ check_ip() { printf '%s' "$1" | tr -d '\n' | grep -Eq "$IP_REGEX" } +check_ip6() { + IP6_REGEX='^[0-9a-fA-F]{0,4}(:[0-9a-fA-F]{0,4}){1,7}$' + printf '%s' "$1" | tr -d '\n' | grep -Eq "$IP6_REGEX" +} + check_dns_name() { FQDN_REGEX='^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$' printf '%s' "$1" | tr -d '\n' | grep -Eq "$FQDN_REGEX" @@ -253,6 +258,20 @@ detect_ip() { check_ip "$public_ip" || exiterr "Cannot detect this server's public IP. Define it as variable 'VPN_PUBLIC_IP' and re-run this script." } +detect_ipv6() { + ip6="" + if ! printf '%s\n%s' "5.0" "$SWAN_VER" | sort -C -V; then + return 0 + fi + if [ -n "$VPN_PUBLIC_IP6" ]; then + ip6="$VPN_PUBLIC_IP6" + check_ip6 "$ip6" || exiterr "Invalid IPv6 address. Check variable 'VPN_PUBLIC_IP6'." + else + ip6_addr=$(ip -6 addr 2>/dev/null | awk '/inet6 [23]/ {print $2}' | cut -d'/' -f1 | head -n1) + [ -n "$ip6_addr" ] && ip6="$ip6_addr" + fi +} + install_vpn_pkgs() { bigecho "Installing packages required for the VPN..." p1=libcurl4-nss-dev @@ -423,6 +442,9 @@ create_vpn_config() { 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" + IP6_NET=${VPN_IP6_NET:-'fddd:500:500:500::/64'} + vp_ip6="" + [ -n "$ip6" ] && vp_ip6=",%v6:fc00::/7,%v6:!$IP6_NET" # Create IPsec config conf_bk "/etc/ipsec.conf" cat > /etc/ipsec.conf <> /etc/sysctl.conf <<'EOF' net.core.default_qdisc = fq net.ipv4.tcp_congestion_control = bbr +EOF + fi + if [ -n "$ip6" ]; then +cat >> /etc/sysctl.conf <<'EOF' +net.ipv6.conf.all.forwarding = 1 EOF fi fi @@ -604,6 +631,28 @@ update_iptables() { conf_bk "$IPT_FILE2" /bin/cp -f "$IPT_FILE" "$IPT_FILE2" fi + if [ -n "$ip6" ]; then + IP6_NET=${VPN_IP6_NET:-'fddd:500:500:500::/64'} + IPT6_FILE=/etc/ip6tables.rules + IPT6_FILE2=/etc/iptables/rules.v6 + ip6tables-save > "$IPT6_FILE.old-$SYS_DT" + ip6ti='ip6tables -I INPUT' + ip6tf='ip6tables -I FORWARD' + ip6tp='ip6tables -t nat -I POSTROUTING' + $ip6ti 1 -m conntrack --ctstate INVALID -j DROP + $ip6ti 2 -m conntrack --ctstate "$res" -j ACCEPT + $ip6ti 3 -p udp -m multiport --dports 500,4500 -j ACCEPT + $ip6tf 1 -m conntrack --ctstate INVALID -j DROP + $ip6tf 2 -i "$NET_IFACE" -d "$IP6_NET" -m conntrack --ctstate "$res" -j ACCEPT + $ip6tf 3 -s "$IP6_NET" -o "$NET_IFACE" -j ACCEPT + $ip6tp -s "$IP6_NET" -o "$NET_IFACE" -m policy --dir out --pol none -j MASQUERADE + echo "# Modified by hwdsl2 VPN script" > "$IPT6_FILE" + ip6tables-save >> "$IPT6_FILE" + if [ -f "$IPT6_FILE2" ]; then + conf_bk "$IPT6_FILE2" + /bin/cp -f "$IPT6_FILE" "$IPT6_FILE2" + fi + fi fi } @@ -635,6 +684,7 @@ enable_on_boot() { cat > /etc/network/if-pre-up.d/iptablesload <<'EOF' #!/bin/sh iptables-restore < /etc/iptables.rules +[ -f /etc/ip6tables.rules ] && ip6tables-restore < /etc/ip6tables.rules exit 0 EOF chmod +x /etc/network/if-pre-up.d/iptablesload @@ -746,6 +796,7 @@ set_up_ikev2() { VPN_DNS_SRV1="$VPN_DNS_SRV1" VPN_DNS_SRV2="$VPN_DNS_SRV2" \ VPN_PROTECT_CONFIG="$VPN_PROTECT_CONFIG" \ VPN_CLIENT_VALIDITY="$VPN_CLIENT_VALIDITY" \ + VPN_PUBLIC_IP6="$ip6" \ /bin/bash /opt/src/ikev2.sh --auto || status=1 fi elif [ -s /opt/src/ikev2.sh ]; then @@ -783,6 +834,7 @@ vpnsetup() { update_apt_cache install_setup_pkgs detect_ip + detect_ipv6 install_vpn_pkgs install_fail2ban get_helper_scripts