Add IPv6 support

- Add initial IPv6 support for IKEv2 mode. For VPN servers with
  a public (global unicast) IPv6 address, IPv6 support for
  IKEv2 clients is automatically enabled during VPN setup.
- Currently tested on Android using the strongSwan VPN client.
  Other platforms (e.g. Windows, macOS, iOS) may have limitations
  or require additional configuration for IPv6 to work.
This commit is contained in:
hwdsl2
2026-03-17 00:21:43 -05:00
parent c4bafc9c0a
commit 8167d54c44
8 changed files with 249 additions and 18 deletions

View File

@@ -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 <linsongui@gmail.com>
# Copyright (C) 2020-2026 Lin Song <linsongui@gmail.com>
#
# 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

View File

@@ -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)

View File

@@ -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

View File

@@ -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 <linsongui@gmail.com>
# Copyright (C) 2021-2026 Lin Song <linsongui@gmail.com>
#
# 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

View File

@@ -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 <linsongui@gmail.com>
# Copyright (C) 2021-2026 Lin Song <linsongui@gmail.com>
#
# 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 <<EOF
@@ -342,7 +364,7 @@ version 2.0
config setup
ikev1-policy=accept
virtual-private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:!$L2TP_NET,%v4:!$XAUTH_NET
virtual-private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:!$L2TP_NET,%v4:!$XAUTH_NET$vp_ip6
uniqueids=no
conn shared
@@ -468,6 +490,11 @@ net.core.rmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 87380 16777216
EOF
if [ -n "$ip6" ]; then
cat >> /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

View File

@@ -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 <linsongui@gmail.com>
# Copyright (C) 2020-2026 Lin Song <linsongui@gmail.com>
#
# 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 <<EOF
@@ -366,7 +388,7 @@ version 2.0
config setup
ikev1-policy=accept
virtual-private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:!$L2TP_NET,%v4:!$XAUTH_NET
virtual-private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:!$L2TP_NET,%v4:!$XAUTH_NET$vp_ip6
uniqueids=no
conn shared
@@ -487,6 +509,11 @@ net.core.rmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 87380 16777216
EOF
if [ -n "$ip6" ]; then
cat >> /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

View File

@@ -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 <linsongui@gmail.com>
# Copyright (C) 2015-2026 Lin Song <linsongui@gmail.com>
# 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 <<EOF
@@ -473,7 +495,7 @@ version 2.0
config setup
ikev1-policy=accept
virtual-private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:!$L2TP_NET,%v4:!$XAUTH_NET
virtual-private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:!$L2TP_NET,%v4:!$XAUTH_NET$vp_ip6
uniqueids=no
conn shared
@@ -600,6 +622,11 @@ EOF
cat >> /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

View File

@@ -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 <linsongui@gmail.com>
# Copyright (C) 2014-2026 Lin Song <linsongui@gmail.com>
# 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 <<EOF
@@ -430,7 +452,7 @@ version 2.0
config setup
ikev1-policy=accept
virtual-private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:!$L2TP_NET,%v4:!$XAUTH_NET
virtual-private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:!$L2TP_NET,%v4:!$XAUTH_NET$vp_ip6
uniqueids=no
conn shared
@@ -562,6 +584,11 @@ EOF
cat >> /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