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: # The latest version of this script is available at:
# https://github.com/hwdsl2/setup-ipsec-vpn # 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 # This work is licensed under the Creative Commons Attribution-ShareAlike 3.0
# Unported License: http://creativecommons.org/licenses/by-sa/3.0/ # Unported License: http://creativecommons.org/licenses/by-sa/3.0/
@@ -169,7 +169,7 @@ confirm_or_abort() {
show_header() { show_header() {
cat <<'EOF' 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 EOF
} }
@@ -1177,6 +1177,13 @@ EOF
add_ikev2_connection() { add_ikev2_connection() {
bigecho2 "Adding a new IKEv2 connection..." bigecho2 "Adding a new IKEv2 connection..."
XAUTH_POOL=${VPN_XAUTH_POOL:-'192.168.43.10-192.168.43.250'} 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 if ! grep -qs '^include /etc/ipsec\.d/\*\.conf$' "$IPSEC_CONF"; then
echo >> "$IPSEC_CONF" echo >> "$IPSEC_CONF"
echo 'include /etc/ipsec.d/*.conf' >> "$IPSEC_CONF" echo 'include /etc/ipsec.d/*.conf' >> "$IPSEC_CONF"
@@ -1187,11 +1194,11 @@ conn ikev2-cp
left=%defaultroute left=%defaultroute
leftcert=$server_addr leftcert=$server_addr
leftsendcert=always leftsendcert=always
leftsubnet=0.0.0.0/0 leftsubnet=$lsubnet
leftrsasigkey=%cert leftrsasigkey=%cert
right=%any right=%any
rightid=%fromcert rightid=%fromcert
rightaddresspool=$XAUTH_POOL rightaddresspool=$rpool
rightca=%same rightca=%same
rightrsasigkey=%cert rightrsasigkey=%cert
narrowing=yes narrowing=yes

View File

@@ -184,9 +184,15 @@ update_sysctl() {
count=17 count=17
line1=$(grep -A 18 "hwdsl2 VPN script" /etc/sysctl.conf | tail -n 1) 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) 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" ] \ if [ "$line1" = "net.core.default_qdisc = fq" ] \
&& [ "$line2" = "net.ipv4.tcp_congestion_control = bbr" ]; then && [ "$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 fi
if [ "$os_type" = "alpine" ]; then if [ "$os_type" = "alpine" ]; then
sed -i "/# Added by hwdsl2 VPN script/,+${count}d" /etc/sysctl.conf 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 \ if ! grep -q "$L2TP_NET" /etc/ipsec.conf \
|| ! grep -q "$XAUTH_NET" /etc/ipsec.conf; then || ! grep -q "$XAUTH_NET" /etc/ipsec.conf; then
vipr=$(grep "virtual-private=" /etc/ipsec.conf) vipr=$(grep "virtual-private=" /etc/ipsec.conf)
l2tpnet=$(printf '%s' "$vipr" | cut -f2 -d '!' | sed 's/,%v4://') l2tpnet=$(printf '%s' "$vipr" | cut -f2 -d '!' | cut -f1 -d ',')
xauthnet=$(printf '%s' "$vipr" | cut -f3 -d '!') xauthnet=$(printf '%s' "$vipr" | cut -f3 -d '!' | cut -f1 -d ',')
check_cidr "$l2tpnet" && L2TP_NET="$l2tpnet" check_cidr "$l2tpnet" && L2TP_NET="$l2tpnet"
check_cidr "$xauthnet" && XAUTH_NET="$xauthnet" check_cidr "$xauthnet" && XAUTH_NET="$xauthnet"
fi fi
@@ -276,6 +282,30 @@ update_iptables_rules() {
/bin/cp -f "$IPT_FILE" "$IPT_FILE2" /bin/cp -f "$IPT_FILE" "$IPT_FILE2"
fi fi
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 else
nft_bk=$(find /etc/sysconfig -maxdepth 1 -name 'nftables.conf.old-*-*-*-*_*_*' -print0 \ nft_bk=$(find /etc/sysconfig -maxdepth 1 -name 'nftables.conf.old-*-*-*-*_*_*' -print0 \
| xargs -r -0 ls -1 -t | head -1) | xargs -r -0 ls -1 -t | head -1)

View File

@@ -143,7 +143,7 @@ install_pkgs() {
bigecho "Installing required packages..." bigecho "Installing required packages..."
( (
set -x 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 \ 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 \ 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 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: # The latest version of this script is available at:
# https://github.com/hwdsl2/setup-ipsec-vpn # 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 # This work is licensed under the Creative Commons Attribution-ShareAlike 3.0
# Unported License: http://creativecommons.org/licenses/by-sa/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_PROTECT_CONFIG="$VPN_PROTECT_CONFIG" \
VPN_CLIENT_VALIDITY="$VPN_CLIENT_VALIDITY" \ VPN_CLIENT_VALIDITY="$VPN_CLIENT_VALIDITY" \
VPN_SKIP_IKEV2="$VPN_SKIP_IKEV2" VPN_SWAN_VER="$VPN_SWAN_VER" \ 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 /bin/bash "$tmpdir/vpn.sh" || status=1
else else
status=1 status=1

View File

@@ -7,7 +7,7 @@
# The latest version of this script is available at: # The latest version of this script is available at:
# https://github.com/hwdsl2/setup-ipsec-vpn # 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 # This work is licensed under the Creative Commons Attribution-ShareAlike 3.0
# Unported License: http://creativecommons.org/licenses/by-sa/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" 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() { check_dns_name() {
FQDN_REGEX='^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$' 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" printf '%s' "$1" | tr -d '\n' | grep -Eq "$FQDN_REGEX"
@@ -165,7 +170,7 @@ install_setup_pkgs() {
bigecho "Installing packages required for setup..." bigecho "Installing packages required for setup..."
( (
set -x 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 ) || 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." 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() { install_vpn_pkgs() {
bigecho "Installing packages required for the VPN..." bigecho "Installing packages required for the VPN..."
( (
@@ -335,6 +354,9 @@ create_vpn_config() {
DNS_SRV2=${VPN_DNS_SRV2:-'8.8.4.4'} DNS_SRV2=${VPN_DNS_SRV2:-'8.8.4.4'}
DNS_SRVS="\"$DNS_SRV1 $DNS_SRV2\"" DNS_SRVS="\"$DNS_SRV1 $DNS_SRV2\""
[ -n "$VPN_DNS_SRV1" ] && [ -z "$VPN_DNS_SRV2" ] && DNS_SRVS="$DNS_SRV1" [ -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 # Create IPsec config
conf_bk "/etc/ipsec.conf" conf_bk "/etc/ipsec.conf"
cat > /etc/ipsec.conf <<EOF cat > /etc/ipsec.conf <<EOF
@@ -342,7 +364,7 @@ version 2.0
config setup config setup
ikev1-policy=accept 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 uniqueids=no
conn shared conn shared
@@ -468,6 +490,11 @@ net.core.rmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216 net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 87380 16777216 net.ipv4.tcp_wmem = 4096 87380 16777216
EOF EOF
if [ -n "$ip6" ]; then
cat >> /etc/sysctl.conf <<'EOF'
net.ipv6.conf.all.forwarding = 1
EOF
fi
fi fi
} }
@@ -503,6 +530,23 @@ update_iptables() {
$ipp -s "$L2TP_NET" -o "$NET_IFACE" -j MASQUERADE $ipp -s "$L2TP_NET" -o "$NET_IFACE" -j MASQUERADE
echo "# Modified by hwdsl2 VPN script" > "$IPT_FILE" echo "# Modified by hwdsl2 VPN script" > "$IPT_FILE"
iptables-save >> "$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 fi
} }
@@ -512,6 +556,7 @@ enable_on_boot() {
cat > /etc/network/if-pre-up.d/iptablesload <<'EOF' cat > /etc/network/if-pre-up.d/iptablesload <<'EOF'
#!/bin/sh #!/bin/sh
iptables-restore < /etc/iptables.rules iptables-restore < /etc/iptables.rules
[ -f /etc/ip6tables.rules ] && ip6tables-restore < /etc/ip6tables.rules
exit 0 exit 0
EOF EOF
chmod +x /etc/network/if-pre-up.d/iptablesload 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_DNS_SRV1="$VPN_DNS_SRV1" VPN_DNS_SRV2="$VPN_DNS_SRV2" \
VPN_PROTECT_CONFIG="$VPN_PROTECT_CONFIG" \ VPN_PROTECT_CONFIG="$VPN_PROTECT_CONFIG" \
VPN_CLIENT_VALIDITY="$VPN_CLIENT_VALIDITY" \ VPN_CLIENT_VALIDITY="$VPN_CLIENT_VALIDITY" \
VPN_PUBLIC_IP6="$ip6" \
/bin/bash /opt/src/ikev2.sh --auto || status=1 /bin/bash /opt/src/ikev2.sh --auto || status=1
fi fi
elif [ -s /opt/src/ikev2.sh ]; then elif [ -s /opt/src/ikev2.sh ]; then
@@ -614,6 +660,7 @@ vpnsetup() {
start_setup start_setup
install_setup_pkgs install_setup_pkgs
detect_ip detect_ip
detect_ipv6
install_vpn_pkgs install_vpn_pkgs
install_fail2ban install_fail2ban
get_helper_scripts get_helper_scripts

View File

@@ -7,7 +7,7 @@
# The latest version of this script is available at: # The latest version of this script is available at:
# https://github.com/hwdsl2/setup-ipsec-vpn # 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 # This work is licensed under the Creative Commons Attribution-ShareAlike 3.0
# Unported License: http://creativecommons.org/licenses/by-sa/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" 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() { check_dns_name() {
FQDN_REGEX='^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$' 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" 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." 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() { add_epel_repo() {
bigecho "Adding the EPEL repository..." bigecho "Adding the EPEL repository..."
( (
@@ -359,6 +378,9 @@ create_vpn_config() {
DNS_SRV2=${VPN_DNS_SRV2:-'8.8.4.4'} DNS_SRV2=${VPN_DNS_SRV2:-'8.8.4.4'}
DNS_SRVS="\"$DNS_SRV1 $DNS_SRV2\"" DNS_SRVS="\"$DNS_SRV1 $DNS_SRV2\""
[ -n "$VPN_DNS_SRV1" ] && [ -z "$VPN_DNS_SRV2" ] && DNS_SRVS="$DNS_SRV1" [ -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 # Create IPsec config
conf_bk "/etc/ipsec.conf" conf_bk "/etc/ipsec.conf"
cat > /etc/ipsec.conf <<EOF cat > /etc/ipsec.conf <<EOF
@@ -366,7 +388,7 @@ version 2.0
config setup config setup
ikev1-policy=accept 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 uniqueids=no
conn shared conn shared
@@ -487,6 +509,11 @@ net.core.rmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216 net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 87380 16777216 net.ipv4.tcp_wmem = 4096 87380 16777216
EOF EOF
if [ -n "$ip6" ]; then
cat >> /etc/sysctl.conf <<'EOF'
net.ipv6.conf.all.forwarding = 1
EOF
fi
fi fi
} }
@@ -522,6 +549,23 @@ update_iptables() {
$ipp -s "$L2TP_NET" -o "$NET_IFACE" -j MASQUERADE $ipp -s "$L2TP_NET" -o "$NET_IFACE" -j MASQUERADE
echo "# Modified by hwdsl2 VPN script" > "$IPT_FILE" echo "# Modified by hwdsl2 VPN script" > "$IPT_FILE"
iptables-save >> "$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 fi
} }
@@ -606,6 +650,7 @@ set_up_ikev2() {
VPN_DNS_SRV1="$VPN_DNS_SRV1" VPN_DNS_SRV2="$VPN_DNS_SRV2" \ VPN_DNS_SRV1="$VPN_DNS_SRV1" VPN_DNS_SRV2="$VPN_DNS_SRV2" \
VPN_PROTECT_CONFIG="$VPN_PROTECT_CONFIG" \ VPN_PROTECT_CONFIG="$VPN_PROTECT_CONFIG" \
VPN_CLIENT_VALIDITY="$VPN_CLIENT_VALIDITY" \ VPN_CLIENT_VALIDITY="$VPN_CLIENT_VALIDITY" \
VPN_PUBLIC_IP6="$ip6" \
/bin/bash /opt/src/ikev2.sh --auto || status=1 /bin/bash /opt/src/ikev2.sh --auto || status=1
fi fi
elif [ -s /opt/src/ikev2.sh ]; then elif [ -s /opt/src/ikev2.sh ]; then
@@ -638,6 +683,7 @@ vpnsetup() {
start_setup start_setup
install_setup_pkgs install_setup_pkgs
detect_ip detect_ip
detect_ipv6
add_epel_repo add_epel_repo
install_vpn_pkgs_1 install_vpn_pkgs_1
install_vpn_pkgs_2 install_vpn_pkgs_2

View File

@@ -8,7 +8,7 @@
# The latest version of this script is available at: # The latest version of this script is available at:
# https://github.com/hwdsl2/setup-ipsec-vpn # 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) # Based on the work of Thomas Sarlandie (Copyright 2012)
# #
# This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 # 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" 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() { check_dns_name() {
FQDN_REGEX='^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$' 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" 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." 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() { add_epel_repo() {
bigecho "Adding the EPEL repository..." bigecho "Adding the EPEL repository..."
epel_url="https://dl.fedoraproject.org/pub/epel/epel-release-latest-$(rpm -E '%{rhel}').noarch.rpm" 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_SRV2=${VPN_DNS_SRV2:-'8.8.4.4'}
DNS_SRVS="\"$DNS_SRV1 $DNS_SRV2\"" DNS_SRVS="\"$DNS_SRV1 $DNS_SRV2\""
[ -n "$VPN_DNS_SRV1" ] && [ -z "$VPN_DNS_SRV2" ] && DNS_SRVS="$DNS_SRV1" [ -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 # Create IPsec config
conf_bk "/etc/ipsec.conf" conf_bk "/etc/ipsec.conf"
cat > /etc/ipsec.conf <<EOF cat > /etc/ipsec.conf <<EOF
@@ -473,7 +495,7 @@ version 2.0
config setup config setup
ikev1-policy=accept 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 uniqueids=no
conn shared conn shared
@@ -600,6 +622,11 @@ EOF
cat >> /etc/sysctl.conf <<'EOF' cat >> /etc/sysctl.conf <<'EOF'
net.core.default_qdisc = fq net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr net.ipv4.tcp_congestion_control = bbr
EOF
fi
if [ -n "$ip6" ]; then
cat >> /etc/sysctl.conf <<'EOF'
net.ipv6.conf.all.forwarding = 1
EOF EOF
fi fi
fi fi
@@ -654,6 +681,19 @@ update_iptables() {
$ipp -s "$XAUTH_NET" -o "$NET_IFACE" -m policy --dir out --pol none -j MASQUERADE $ipp -s "$XAUTH_NET" -o "$NET_IFACE" -m policy --dir out --pol none -j MASQUERADE
fi fi
$ipp -s "$L2TP_NET" -o "$NET_IFACE" -j MASQUERADE $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" echo "# Modified by hwdsl2 VPN script" > "$IPT_FILE"
if [ "$use_nft" = 1 ]; then if [ "$use_nft" = 1 ]; then
for vport in 500 4500 1701; do for vport in 500 4500 1701; do
@@ -670,6 +710,12 @@ update_iptables() {
nft list ruleset >> "$IPT_FILE" nft list ruleset >> "$IPT_FILE"
else else
iptables-save >> "$IPT_FILE" 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
fi fi
} }
@@ -792,6 +838,7 @@ set_up_ikev2() {
VPN_DNS_SRV1="$VPN_DNS_SRV1" VPN_DNS_SRV2="$VPN_DNS_SRV2" \ VPN_DNS_SRV1="$VPN_DNS_SRV1" VPN_DNS_SRV2="$VPN_DNS_SRV2" \
VPN_PROTECT_CONFIG="$VPN_PROTECT_CONFIG" \ VPN_PROTECT_CONFIG="$VPN_PROTECT_CONFIG" \
VPN_CLIENT_VALIDITY="$VPN_CLIENT_VALIDITY" \ VPN_CLIENT_VALIDITY="$VPN_CLIENT_VALIDITY" \
VPN_PUBLIC_IP6="$ip6" \
/bin/bash /opt/src/ikev2.sh --auto || status=1 /bin/bash /opt/src/ikev2.sh --auto || status=1
fi fi
elif [ -s /opt/src/ikev2.sh ]; then elif [ -s /opt/src/ikev2.sh ]; then
@@ -826,6 +873,7 @@ vpnsetup() {
start_setup start_setup
install_setup_pkgs install_setup_pkgs
detect_ip detect_ip
detect_ipv6
add_epel_repo add_epel_repo
install_vpn_pkgs_1 install_vpn_pkgs_1
install_vpn_pkgs_2 install_vpn_pkgs_2

View File

@@ -7,7 +7,7 @@
# The latest version of this script is available at: # The latest version of this script is available at:
# https://github.com/hwdsl2/setup-ipsec-vpn # 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) # Based on the work of Thomas Sarlandie (Copyright 2012)
# #
# This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 # 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" 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() { check_dns_name() {
FQDN_REGEX='^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$' 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" 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." 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() { install_vpn_pkgs() {
bigecho "Installing packages required for the VPN..." bigecho "Installing packages required for the VPN..."
p1=libcurl4-nss-dev p1=libcurl4-nss-dev
@@ -423,6 +442,9 @@ create_vpn_config() {
DNS_SRV2=${VPN_DNS_SRV2:-'8.8.4.4'} DNS_SRV2=${VPN_DNS_SRV2:-'8.8.4.4'}
DNS_SRVS="\"$DNS_SRV1 $DNS_SRV2\"" DNS_SRVS="\"$DNS_SRV1 $DNS_SRV2\""
[ -n "$VPN_DNS_SRV1" ] && [ -z "$VPN_DNS_SRV2" ] && DNS_SRVS="$DNS_SRV1" [ -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 # Create IPsec config
conf_bk "/etc/ipsec.conf" conf_bk "/etc/ipsec.conf"
cat > /etc/ipsec.conf <<EOF cat > /etc/ipsec.conf <<EOF
@@ -430,7 +452,7 @@ version 2.0
config setup config setup
ikev1-policy=accept 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 uniqueids=no
conn shared conn shared
@@ -562,6 +584,11 @@ EOF
cat >> /etc/sysctl.conf <<'EOF' cat >> /etc/sysctl.conf <<'EOF'
net.core.default_qdisc = fq net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr net.ipv4.tcp_congestion_control = bbr
EOF
fi
if [ -n "$ip6" ]; then
cat >> /etc/sysctl.conf <<'EOF'
net.ipv6.conf.all.forwarding = 1
EOF EOF
fi fi
fi fi
@@ -604,6 +631,28 @@ update_iptables() {
conf_bk "$IPT_FILE2" conf_bk "$IPT_FILE2"
/bin/cp -f "$IPT_FILE" "$IPT_FILE2" /bin/cp -f "$IPT_FILE" "$IPT_FILE2"
fi 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 fi
} }
@@ -635,6 +684,7 @@ enable_on_boot() {
cat > /etc/network/if-pre-up.d/iptablesload <<'EOF' cat > /etc/network/if-pre-up.d/iptablesload <<'EOF'
#!/bin/sh #!/bin/sh
iptables-restore < /etc/iptables.rules iptables-restore < /etc/iptables.rules
[ -f /etc/ip6tables.rules ] && ip6tables-restore < /etc/ip6tables.rules
exit 0 exit 0
EOF EOF
chmod +x /etc/network/if-pre-up.d/iptablesload 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_DNS_SRV1="$VPN_DNS_SRV1" VPN_DNS_SRV2="$VPN_DNS_SRV2" \
VPN_PROTECT_CONFIG="$VPN_PROTECT_CONFIG" \ VPN_PROTECT_CONFIG="$VPN_PROTECT_CONFIG" \
VPN_CLIENT_VALIDITY="$VPN_CLIENT_VALIDITY" \ VPN_CLIENT_VALIDITY="$VPN_CLIENT_VALIDITY" \
VPN_PUBLIC_IP6="$ip6" \
/bin/bash /opt/src/ikev2.sh --auto || status=1 /bin/bash /opt/src/ikev2.sh --auto || status=1
fi fi
elif [ -s /opt/src/ikev2.sh ]; then elif [ -s /opt/src/ikev2.sh ]; then
@@ -783,6 +834,7 @@ vpnsetup() {
update_apt_cache update_apt_cache
install_setup_pkgs install_setup_pkgs
detect_ip detect_ip
detect_ipv6
install_vpn_pkgs install_vpn_pkgs
install_fail2ban install_fail2ban
get_helper_scripts get_helper_scripts