Repository: hwdsl2/setup-ipsec-vpn
Branch: master
Commit: dac31b87874f
Files: 59
Total size: 700.9 KB
Directory structure:
gitextract_z3qo90ab/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── 00-bug-report.md
│ │ ├── 10-bug-report-zh.md
│ │ ├── 20-enhancement-request.md
│ │ └── 30-enhancement-request-zh.md
│ └── workflows/
│ ├── check_urls.yml
│ ├── cron.yml
│ ├── main.yml
│ ├── shellcheck.yml
│ ├── test_set_1.yml
│ └── test_set_2.yml
├── LICENSE.md
├── README-ja.md
├── README-ru.md
├── README-zh-Hant.md
├── README-zh.md
├── README.md
├── aws/
│ ├── README-zh.md
│ ├── README.md
│ └── cloudformation-template-ipsec.json
├── azure/
│ ├── README-zh.md
│ ├── README.md
│ ├── azuredeploy.json
│ ├── azuredeploy.parameters.json
│ └── install.sh
├── docs/
│ ├── advanced-usage-zh.md
│ ├── advanced-usage.md
│ ├── bbr-zh.md
│ ├── bbr.md
│ ├── clients-xauth-zh.md
│ ├── clients-xauth.md
│ ├── clients-zh.md
│ ├── clients.md
│ ├── ikev2-howto-zh.md
│ ├── ikev2-howto.md
│ ├── manage-users-zh.md
│ ├── manage-users.md
│ ├── uninstall-zh.md
│ ├── uninstall.md
│ ├── vpn-book-ja.md
│ ├── vpn-book-zh-Hant.md
│ ├── vpn-book-zh.md
│ └── vpn-book.md
├── extras/
│ ├── add_vpn_user.sh
│ ├── del_vpn_user.sh
│ ├── ikev2changeaddr.sh
│ ├── ikev2onlymode.sh
│ ├── ikev2setup.sh
│ ├── update_vpn_users.sh
│ ├── vpnuninstall.sh
│ ├── vpnupgrade.sh
│ ├── vpnupgrade_alpine.sh
│ ├── vpnupgrade_amzn.sh
│ ├── vpnupgrade_centos.sh
│ └── vpnupgrade_ubuntu.sh
├── vpnsetup.sh
├── vpnsetup_alpine.sh
├── vpnsetup_amzn.sh
├── vpnsetup_centos.sh
└── vpnsetup_ubuntu.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/00-bug-report.md
================================================
---
name: Bug report
about: Tell us about a problem you are experiencing
title: ''
labels: ''
assignees: ''
---
**Checklist**
- [ ] I read the [README](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/README.md)
- [ ] I read the [Important notes](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/README.md#important-notes)
- [ ] I followed instructions to [configure VPN clients](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/README.md#next-steps)
- [ ] I checked [IKEv1 troubleshooting](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/clients.md#ikev1-troubleshooting), [IKEv2 troubleshooting](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/ikev2-howto.md#ikev2-troubleshooting) and [VPN status](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/clients.md#check-logs-and-vpn-status)
- [ ] I searched existing [Issues](https://github.com/hwdsl2/setup-ipsec-vpn/issues?q=is%3Aissue)
- [ ] This bug is about the VPN setup scripts, and not IPsec VPN itself
**Describe the issue**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. ...
2. ...
**Expected behavior**
A clear and concise description of what you expected to happen.
**Logs**
[Check logs and VPN status](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/clients.md#check-logs-and-vpn-status), and add error logs to help explain the problem, if applicable.
**Server (please complete the following information)**
- OS: [e.g. Debian 11]
- Hosting provider (if applicable): [e.g. GCP, AWS]
**Client (please complete the following information)**
- Device: [e.g. iPhone 12]
- OS: [e.g. iOS 15]
- VPN mode: [IPsec/L2TP, IPsec/XAuth ("Cisco IPsec") or IKEv2]
**Additional context**
Add any other context about the problem here.
================================================
FILE: .github/ISSUE_TEMPLATE/10-bug-report-zh.md
================================================
---
name: 错误报告
about: 请使用这个模板来提交 bug
title: ''
labels: ''
assignees: ''
---
**任务列表**
- [ ] 我已阅读[自述文件](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/README-zh.md)
- [ ] 我已阅读[重要提示](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/README-zh.md#重要提示)
- [ ] 我已按照说明[配置 VPN 客户端](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/README-zh.md#下一步)
- [ ] 我检查了 [IKEv1 故障排除](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/clients-zh.md#ikev1-故障排除),[IKEv2 故障排除](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/ikev2-howto-zh.md#ikev2-故障排除)以及 [VPN 状态](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/clients-zh.md#检查日志及-vpn-状态)
- [ ] 我搜索了已有的 [Issues](https://github.com/hwdsl2/setup-ipsec-vpn/issues?q=is%3Aissue)
- [ ] 这个 bug 是关于 VPN 安装脚本,而不是 IPsec VPN 本身
**问题描述**
使用清楚简明的语言描述这个 bug。
**重现步骤**
重现该 bug 的步骤:
1. ...
2. ...
**期待的正确结果**
简要地描述你期望的正确结果。
**日志**
[检查日志及 VPN 状态](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/clients-zh.md#检查日志及-vpn-状态),并添加错误日志以帮助解释该问题(如果适用)。
**服务器信息(请填写以下信息)**
- 操作系统: [比如 Debian 11]
- 服务提供商(如果适用): [比如 GCP, AWS]
**客户端信息(请填写以下信息)**
- 设备: [比如 iPhone 12]
- 操作系统: [比如 iOS 15]
- VPN 模式: [IPsec/L2TP, IPsec/XAuth ("Cisco IPsec") 或 IKEv2]
**其它信息**
添加关于该 bug 的其它信息。
================================================
FILE: .github/ISSUE_TEMPLATE/20-enhancement-request.md
================================================
---
name: Enhancement request
about: Suggest an improvement for this project
title: ''
labels: ''
assignees: ''
---
**Checklist**
- [ ] I searched existing [Issues](https://github.com/hwdsl2/setup-ipsec-vpn/issues?q=is%3Aissue), and did not find a similar enhancement request
- [ ] This enhancement request is about the VPN setup scripts, and not IPsec VPN itself
- [ ] I read the [README](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/README.md)
- [ ] I read the [Important notes](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/README.md#important-notes)
- [ ] I followed instructions to [configure VPN clients](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/README.md#next-steps)
- [ ] I checked [IKEv1 troubleshooting](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/clients.md#ikev1-troubleshooting), [IKEv2 troubleshooting](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/ikev2-howto.md#ikev2-troubleshooting) and [VPN status](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/clients.md#check-logs-and-vpn-status)
**Describe the enhancement request**
A clear and concise description of your enhancement request.
**Is your enhancement request related to a problem? Please describe.**
(If applicable) A clear and concise description of what the problem is.
**Additional context**
Add any other context about the enhancement request here.
================================================
FILE: .github/ISSUE_TEMPLATE/30-enhancement-request-zh.md
================================================
---
name: 改进建议
about: 请使用这个模板来提交改进建议
title: ''
labels: ''
assignees: ''
---
**任务列表**
- [ ] 我搜索了已有的 [Issues](https://github.com/hwdsl2/setup-ipsec-vpn/issues?q=is%3Aissue),没有找到类似的改进建议
- [ ] 这个改进建议是关于 VPN 安装脚本,而不是 IPsec VPN 本身
- [ ] 我已阅读[自述文件](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/README-zh.md)
- [ ] 我已阅读[重要提示](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/README-zh.md#重要提示)
- [ ] 我已按照说明[配置 VPN 客户端](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/README-zh.md#下一步)
- [ ] 我检查了 [IKEv1 故障排除](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/clients-zh.md#ikev1-故障排除),[IKEv2 故障排除](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/ikev2-howto-zh.md#ikev2-故障排除)以及 [VPN 状态](https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/clients-zh.md#检查日志及-vpn-状态)
**描述改进建议**
使用清楚简明的语言描述你的改进建议。
**你的改进建议与遇到的问题有关吗?请描述。**
(如果适用)清楚,简洁地说明问题所在。
**其它信息**
添加关于该改进建议的其它信息。
================================================
FILE: .github/workflows/check_urls.yml
================================================
#
# 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/
#
# Attribution required: please include my name in any derivative and let me
# know how you have improved it!
name: check_urls
on: workflow_call
jobs:
check_urls:
runs-on: ubuntu-24.04
if: github.repository_owner == 'hwdsl2'
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: Check
run: |
cd "$GITHUB_WORKSPACE"
mkdir workdir
cd workdir
set -ex
export DEBIAN_FRONTEND=noninteractive
sudo apt-get -yqq update
sudo apt-get -yqq install wget
wg="wget -t 3 -T 30 -nv -O"
sl="sleep 1"
gi="https://raw.githubusercontent.com/hwdsl2/setup-ipsec-vpn/master"
gh="https://github.com/hwdsl2/setup-ipsec-vpn/raw/master"
$wg vpnsetup.sh "$gi/vpnsetup.sh"; $sl
$wg vpnsetup_centos.sh "$gi/vpnsetup_centos.sh"; $sl
$wg vpnsetup_amzn.sh "$gi/vpnsetup_amzn.sh"; $sl
$wg vpnsetup_ubuntu.sh "$gi/vpnsetup_ubuntu.sh"; $sl
$wg vpnsetup_alpine.sh "$gi/vpnsetup_alpine.sh"; $sl
$wg ikev2setup.sh "$gi/extras/ikev2setup.sh"; $sl
$wg vpnupgrade.sh "$gi/extras/vpnupgrade.sh"; $sl
$wg vpnupgrade_centos.sh "$gi/extras/vpnupgrade_centos.sh"; $sl
$wg vpnupgrade_amzn.sh "$gi/extras/vpnupgrade_amzn.sh"; $sl
$wg vpnupgrade_ubuntu.sh "$gi/extras/vpnupgrade_ubuntu.sh"; $sl
$wg vpnupgrade_alpine.sh "$gi/extras/vpnupgrade_alpine.sh"; $sl
$wg vpnuninstall.sh "$gi/extras/vpnuninstall.sh"; $sl
$wg add_vpn_user.sh "$gi/extras/add_vpn_user.sh"; $sl
$wg del_vpn_user.sh "$gi/extras/del_vpn_user.sh"; $sl
$wg update_vpn_users.sh "$gi/extras/update_vpn_users.sh"; $sl
$wg ikev2changeaddr.sh "$gi/extras/ikev2changeaddr.sh"; $sl
$wg ikev2onlymode.sh "$gi/extras/ikev2onlymode.sh"; $sl
$wg vpnsetup2.sh "$gh/vpnsetup.sh"; $sl
$wg vpnsetup_centos2.sh "$gh/vpnsetup_centos.sh"; $sl
$wg vpnsetup_amzn2.sh "$gh/vpnsetup_amzn.sh"; $sl
$wg vpnsetup_ubuntu2.sh "$gh/vpnsetup_ubuntu.sh"; $sl
$wg vpnsetup_alpine2.sh "$gh/vpnsetup_alpine.sh"; $sl
$wg ikev2setup2.sh "$gh/extras/ikev2setup.sh"; $sl
$wg vpnupgrade2.sh "$gh/extras/vpnupgrade.sh"; $sl
$wg vpnupgrade_centos2.sh "$gh/extras/vpnupgrade_centos.sh"; $sl
$wg vpnupgrade_amzn2.sh "$gh/extras/vpnupgrade_amzn.sh"; $sl
$wg vpnupgrade_ubuntu2.sh "$gh/extras/vpnupgrade_ubuntu.sh"; $sl
$wg vpnupgrade_alpine2.sh "$gh/extras/vpnupgrade_alpine.sh"; $sl
$wg vpnuninstall2.sh "$gh/extras/vpnuninstall.sh"; $sl
$wg add_vpn_user2.sh "$gh/extras/add_vpn_user.sh"; $sl
$wg del_vpn_user2.sh "$gh/extras/del_vpn_user.sh"; $sl
$wg update_vpn_users2.sh "$gh/extras/update_vpn_users.sh"; $sl
$wg ikev2changeaddr2.sh "$gh/extras/ikev2changeaddr.sh"; $sl
$wg ikev2onlymode2.sh "$gh/extras/ikev2onlymode.sh"
diff vpnsetup.sh ../vpnsetup.sh
diff vpnsetup_centos.sh ../vpnsetup_centos.sh
diff vpnsetup_amzn.sh ../vpnsetup_amzn.sh
diff vpnsetup_ubuntu.sh ../vpnsetup_ubuntu.sh
diff vpnsetup_alpine.sh ../vpnsetup_alpine.sh
diff ikev2setup.sh ../extras/ikev2setup.sh
diff vpnupgrade.sh ../extras/vpnupgrade.sh
diff vpnupgrade_centos.sh ../extras/vpnupgrade_centos.sh
diff vpnupgrade_amzn.sh ../extras/vpnupgrade_amzn.sh
diff vpnupgrade_ubuntu.sh ../extras/vpnupgrade_ubuntu.sh
diff vpnupgrade_alpine.sh ../extras/vpnupgrade_alpine.sh
diff vpnuninstall.sh ../extras/vpnuninstall.sh
diff add_vpn_user.sh ../extras/add_vpn_user.sh
diff del_vpn_user.sh ../extras/del_vpn_user.sh
diff update_vpn_users.sh ../extras/update_vpn_users.sh
diff ikev2changeaddr.sh ../extras/ikev2changeaddr.sh
diff ikev2onlymode.sh ../extras/ikev2onlymode.sh
diff vpnsetup2.sh ../vpnsetup.sh
diff vpnsetup_centos2.sh ../vpnsetup_centos.sh
diff vpnsetup_amzn2.sh ../vpnsetup_amzn.sh
diff vpnsetup_ubuntu2.sh ../vpnsetup_ubuntu.sh
diff vpnsetup_alpine2.sh ../vpnsetup_alpine.sh
diff ikev2setup2.sh ../extras/ikev2setup.sh
diff vpnupgrade2.sh ../extras/vpnupgrade.sh
diff vpnupgrade_centos2.sh ../extras/vpnupgrade_centos.sh
diff vpnupgrade_amzn2.sh ../extras/vpnupgrade_amzn.sh
diff vpnupgrade_ubuntu2.sh ../extras/vpnupgrade_ubuntu.sh
diff vpnupgrade_alpine2.sh ../extras/vpnupgrade_alpine.sh
diff vpnuninstall2.sh ../extras/vpnuninstall.sh
diff add_vpn_user2.sh ../extras/add_vpn_user.sh
diff del_vpn_user2.sh ../extras/del_vpn_user.sh
diff update_vpn_users2.sh ../extras/update_vpn_users.sh
diff ikev2changeaddr2.sh ../extras/ikev2changeaddr.sh
diff ikev2onlymode2.sh ../extras/ikev2onlymode.sh
================================================
FILE: .github/workflows/cron.yml
================================================
#
# 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/
#
# Attribution required: please include my name in any derivative and let me
# know how you have improved it!
name: build cron
on:
schedule:
- cron: '25 2 * * 0,4'
jobs:
check_urls:
if: github.repository_owner == 'hwdsl2'
uses: ./.github/workflows/check_urls.yml
test_set_1:
needs: check_urls
uses: ./.github/workflows/test_set_1.yml
test_set_2:
needs: check_urls
uses: ./.github/workflows/test_set_2.yml
================================================
FILE: .github/workflows/main.yml
================================================
#
# 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/
#
# Attribution required: please include my name in any derivative and let me
# know how you have improved it!
name: build
on:
push:
branches: [master]
paths:
- '**.sh'
- '.github/workflows/main.yml'
- '.github/workflows/shellcheck.yml'
- '.github/workflows/test_set_1.yml'
- '.github/workflows/test_set_2.yml'
jobs:
shellcheck:
if: github.repository_owner == 'hwdsl2'
uses: ./.github/workflows/shellcheck.yml
test_set_1:
needs: shellcheck
uses: ./.github/workflows/test_set_1.yml
test_set_2:
needs: shellcheck
uses: ./.github/workflows/test_set_2.yml
================================================
FILE: .github/workflows/shellcheck.yml
================================================
#
# 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/
#
# Attribution required: please include my name in any derivative and let me
# know how you have improved it!
name: shellcheck
on: workflow_call
jobs:
shellcheck:
runs-on: ubuntu-24.04
if: github.repository_owner == 'hwdsl2'
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: Check
run: |
if [ ! -x /usr/bin/shellcheck ]; then
export DEBIAN_FRONTEND=noninteractive
sudo apt-get -yqq update
sudo apt-get -yqq install shellcheck
fi
cd "$GITHUB_WORKSPACE"
pwd
ls -ld vpnsetup.sh
export SHELLCHECK_OPTS="-e SC1090,SC1091"
shellcheck --version
shopt -s globstar
ls -ld -- **/*.sh
shellcheck **/*.sh
================================================
FILE: .github/workflows/test_set_1.yml
================================================
#
# 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/
#
# Attribution required: please include my name in any derivative and let me
# know how you have improved it!
name: test_set_1
on: workflow_call
jobs:
test_set_1:
runs-on: ubuntu-22.04
if: github.repository_owner == 'hwdsl2'
strategy:
matrix:
os_version: ["centos:10s", "centos:9s", "rockylinux:8", "almalinux:10", "almalinux:9", "almalinux:8", "oraclelinux:10", "oraclelinux:9", "oraclelinux:8"]
fail-fast: false
env:
OS_VERSION: ${{ matrix.os_version }}
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: Build
run: |
mkdir -p "$GITHUB_WORKSPACE/testing/${OS_VERSION//:}"
cd "$GITHUB_WORKSPACE/testing/${OS_VERSION//:}"
mkdir -p scripts/extras
ls -ld "$GITHUB_WORKSPACE/vpnsetup.sh"
cp -f "$GITHUB_WORKSPACE"/*.sh scripts/
cp -f "$GITHUB_WORKSPACE"/extras/*.sh scripts/extras/
cat > run.sh <<'EOF'
#!/bin/bash
set -eEx
log1=/var/log/secure
log2=/var/log/messages
trap 'catch $? $LINENO' ERR
catch() {
echo "Error $1 occurred on line $2."
cat -n -- "$0" | tail -n+"$(($2 - 3))" | head -n7
exit 1
}
restart_ipsec() {
if [ -f /etc/oracle-release ]; then
sleep 3
fi
systemctl restart ipsec
if grep -qs -i stream /etc/redhat-release \
&& grep -qsE 'release (9|1[0-9])' /etc/redhat-release; then
sleep 5
return 0
fi
echo "Waiting for IPsec to restart."
count=0
while ! grep -q "pluto\[$(cat /var/run/pluto/pluto.pid)\]: listening for IKE messages" "$log1"; do
[ "$count" -ge "30" ] && { echo "IPsec failed to start."; exit 1; }
count=$((count+1))
printf '%s' '.'
sleep 0.5
done
echo
}
restart_fail2ban() {
rm -f /var/log/fail2ban.log
systemctl restart fail2ban
echo "Waiting for Fail2ban to restart."
count=0
while ! grep -qs -E "Jail '(sshd?|ssh-iptables)' started" /var/log/fail2ban.log; do
[ "$count" -ge "30" ] && { echo "Fail2ban failed to start."; exit 1; }
count=$((count+1))
printf '%s' '.'
sleep 0.5
done
echo
}
cd /opt/src
if grep -qs -i rocky /etc/redhat-release; then
yum -y -q update
fi
yum -y -q install wget rsyslog
if grep -qsE 'release (9|1[0-9])' /etc/redhat-release; then
if grep -qs -i rocky /etc/redhat-release \
|| grep -qs -i alma /etc/redhat-release; then
yum -y -q install diffutils
fi
fi
if ! grep -qs -i stream /etc/redhat-release \
|| ! grep -qsE 'release (9|1[0-9])' /etc/redhat-release; then
systemctl start rsyslog
fi
cp -f /opt/src/scripts/vpnsetup.sh .
cp -f /opt/src/scripts/extras/vpnuninstall.sh ./vpnunst.sh
sed -i -e '/curl /a sed -i "/swan_ver_latest=/s/^/#/" "$tmpdir/vpn.sh"' \
-e '/curl /a sed -i \x27/status=0/a sed -i "/swan_ver_latest=/s/^/#/" /opt/src/ikev2.sh\x27 "$tmpdir/vpn.sh"' \
vpnsetup.sh
sh vpnsetup.sh
systemctl restart xl2tpd
restart_ipsec
if ! grep -qsE 'release (9|1[0-9])' /etc/oracle-release; then
if ! grep -qs -i stream /etc/redhat-release \
|| ! grep -qsE 'release (9|1[0-9])' /etc/redhat-release; then
restart_fail2ban
cat /var/log/fail2ban.log
fi
fi
netstat -anpu | grep pluto
netstat -anpu | grep xl2tpd
if grep -qsE 'release (9|1[0-9])' /etc/redhat-release; then
nft list ruleset
nft list ruleset | grep -q '192\.168\.42\.0/24'
nft list ruleset | grep -q '192\.168\.43\.0/24'
else
iptables -nvL
iptables -nvL | grep -q 'ppp+'
iptables -nvL | grep -q '192\.168\.43\.0/24'
iptables -nvL -t nat
iptables -nvL -t nat | grep -q '192\.168\.42\.0/24'
iptables -nvL -t nat | grep -q '192\.168\.43\.0/24'
fi
if ! grep -qs -i stream /etc/redhat-release \
|| ! grep -qsE 'release (9|1[0-9])' /etc/redhat-release; then
grep pluto "$log1"
grep xl2tpd "$log2"
fi
ipsec status
ipsec status | grep -q l2tp-psk
ipsec status | grep -q xauth-psk
ipsec status | grep -q ikev2-cp
ls -ld /etc/ipsec.d/vpnclient.mobileconfig
ls -ld /etc/ipsec.d/vpnclient.sswan
ls -ld /etc/ipsec.d/vpnclient.p12
ls -l /usr/bin/ikev2.sh
ls -l /usr/bin/addvpnuser.sh
ls -l /usr/bin/delvpnuser.sh
ls -l /opt/src/ikev2.sh
ls -l /opt/src/addvpnuser.sh
ls -l /opt/src/delvpnuser.sh
bash vpnunst.sh <&1 | grep -i "abort"
4
vpnclient2
ANSWERS
bash ikev2.sh <&1 | grep -i "abort"
2
vpnclient2
ANSWERS
bash ikev2.sh <&1 | grep -i "abort"
6
ANSWERS
bash ikev2.sh <&1 | grep -i "invalid"
sed -i '/^include /d' /etc/ipsec.conf
VPN_CLIENT_NAME=vpnclient1 \
VPN_DNS_NAME=vpn.example.com \
VPN_DNS_SRV1=1.1.1.1 \
VPN_DNS_SRV2=1.0.0.1 \
bash ikev2.sh --auto
grep -q 'leftid=@vpn.example.com' /etc/ipsec.d/ikev2.conf
grep -q 'modecfgdns="1.1.1.1 1.0.0.1"' /etc/ipsec.d/ikev2.conf
ls -ld /etc/ipsec.d/vpnclient1.mobileconfig
ls -ld /etc/ipsec.d/vpnclient1.sswan
ls -ld /etc/ipsec.d/vpnclient1.p12
grep -q 'vpn.example.com' /etc/ipsec.d/vpnclient1.mobileconfig
grep -q 'vpn.example.com' /etc/ipsec.d/vpnclient1.sswan
restart_ipsec
ipsec status | grep -q ikev2-cp
bash ikev2.sh --addclient invalidclient: 2>&1 | grep -i "invalid"
bash ikev2.sh --addclient vpnclient1 2>&1 | grep -i "already exists"
bash ikev2.sh --addclient vpnclient2
ls -ld /etc/ipsec.d/vpnclient2.mobileconfig
ls -ld /etc/ipsec.d/vpnclient2.sswan
ls -ld /etc/ipsec.d/vpnclient2.p12
bash ikev2.sh --exportclient nonexistclient 2>&1 | grep -i "does not exist"
rm -f /etc/ipsec.d/vpnclient2*
bash ikev2.sh --exportclient vpnclient2
ls -ld /etc/ipsec.d/vpnclient2.mobileconfig
ls -ld /etc/ipsec.d/vpnclient2.sswan
ls -ld /etc/ipsec.d/vpnclient2.p12
bash ikev2.sh --addclient vpnclient2 --exportclient vpnclient2 2>&1 | grep -i "invalid"
bash ikev2.sh --listclients | grep "vpnclient1 \+valid"
bash ikev2.sh --listclients | grep "vpnclient2 \+valid"
bash ikev2.sh --listclients | grep "2 clients"
bash ikev2.sh --revokeclient nonexistclient 2>&1 | grep -i "does not exist"
bash ikev2.sh --revokeclient vpnclient2 <&1 | grep -i "already been revoked"
bash ikev2.sh --exportclient vpnclient2 2>&1 | grep -i "revoked"
bash ikev2.sh --deleteclient nonexistclient 2>&1 | grep -i "does not exist"
bash ikev2.sh --deleteclient vpnclient1 <&1 | grep -i "usage:"
bash ikev2.sh --invalidoption 2>&1 | grep -i "usage:"
bash ikev2.sh --removeikev2 --exportclient vpnclient1 2>&1 | grep -i "invalid"
bash ikev2.sh --removeikev2 < Dockerfile
elif [ "$OS_VERSION" = "centos:10s" ]; then
echo "FROM quay.io/centos/centos:stream10" > Dockerfile
else
echo "FROM $OS_VERSION" > Dockerfile
fi
cat >> Dockerfile <<'EOF'
ENV container=docker
WORKDIR /opt/src
EOF
if [ "$OS_VERSION" = "centos:9s" ] || [ "$OS_VERSION" = "centos:10s" ]; then
echo "RUN yum -y -q install systemd" >> Dockerfile
fi
cat >> Dockerfile <<'EOF'
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ "$i" = \
systemd-tmpfiles-setup.service ] || rm -f "$i"; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*; \
rm -f /etc/systemd/system/*.wants/*; \
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*; \
rm -f /lib/systemd/system/anaconda.target.wants/*;
COPY scripts/ /opt/src/scripts/
COPY ./run.sh /opt/src/run.sh
RUN chmod 755 /opt/src/run.sh
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/sbin/init"]
EOF
cat Dockerfile
cat run.sh
docker build -t "${OS_VERSION//:}-test" .
- name: Test
run: |
docker run -d --name "${OS_VERSION//:}-test-1" -v /sys/fs/cgroup:/sys/fs/cgroup:rw \
--cgroupns=host --privileged "${OS_VERSION//:}-test"
sleep 5
docker exec "${OS_VERSION//:}-test-1" /opt/src/run.sh "${OS_VERSION::6}"
- name: Clear
if: always()
run: |
rm -rf "$GITHUB_WORKSPACE/testing/${OS_VERSION//:}"
docker rm -f "${OS_VERSION//:}-test-1" || true
docker rmi "${OS_VERSION//:}-test" || true
================================================
FILE: .github/workflows/test_set_2.yml
================================================
#
# 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/
#
# Attribution required: please include my name in any derivative and let me
# know how you have improved it!
name: test_set_2
on: workflow_call
jobs:
test_set_2:
runs-on: ubuntu-24.04
if: github.repository_owner == 'hwdsl2'
strategy:
matrix:
os_version: ["ubuntu:24.04", "ubuntu:22.04", "debian:13", "debian:12", "debian:11", "alpine:3.23", "alpine:3.22"]
fail-fast: false
container:
image: ${{ matrix.os_version }}
options: --cap-add=NET_ADMIN --device=/dev/ppp
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: Test
run: |
set -ex
os_type=""
[ -f /etc/os-release ] && os_type=$(. /etc/os-release && printf '%s' "$ID")
[ -z "$os_type" ] && exit 1
if [ "$os_type" != "alpine" ]; then
os_ver=$(sed 's/\..*//' /etc/debian_version | tr -dc 'A-Za-z0-9')
fi
log1=/var/log/auth.log
if [ "$os_type" = "alpine" ]; then
log2=/var/log/messages
else
log2=/var/log/syslog
fi
restart_ipsec() {
if [ "$os_type" = "alpine" ] || [ "$os_ver" = "trixiesid" ] || [ "$os_ver" = 13 ]; then
ipsec whack --shutdown || true
ipsec pluto --config /etc/ipsec.conf
fi
echo "Waiting for IPsec to restart."
count=0
while ! grep -q "pluto\[$(cat /var/run/pluto/pluto.pid)\]: listening for IKE messages" "$log1"; do
[ "$count" -ge "30" ] && { echo "IPsec failed to start."; exit 1; }
count=$((count+1))
printf '%s' '.'
sleep 0.5
done
echo
}
restart_fail2ban() {
rm -f /var/log/fail2ban.log
service fail2ban restart
echo "Waiting for Fail2ban to restart."
count=0
while ! grep -qs -E "Jail '(sshd?|ssh-iptables)' started" /var/log/fail2ban.log; do
[ "$count" -ge "30" ] && { echo "Fail2ban failed to start."; exit 1; }
count=$((count+1))
printf '%s' '.'
sleep 0.5
done
echo
}
mkdir -p /opt/src
cd /opt/src
ls -ld "$GITHUB_WORKSPACE/vpnsetup.sh"
echo "# hwdsl2" > run.sh
if [ "$os_type" = "alpine" ]; then
apk add -U wget rsyslog sed bash
rsyslogd
else
export DEBIAN_FRONTEND=noninteractive
apt-get -yqq update
apt-get -yqq install wget rsyslog
if [ "$os_ver" = "bookwormsid" ] || [ "$os_ver" = "trixiesid" ] \
|| [ "$os_ver" = 13 ] || [ "$os_ver" = 12 ]; then
rsyslogd
else
service rsyslog start
fi
fi
cp -f "$GITHUB_WORKSPACE"/vpnsetup.sh .
cp -f "$GITHUB_WORKSPACE"/extras/vpnuninstall.sh ./vpnunst.sh
sed -i -e '/curl /a sed -i "/swan_ver_latest=/s/^/#/" "$tmpdir/vpn.sh"' \
-e '/curl /a sed -i \x27/status=0/a sed -i "/swan_ver_latest=/s/^/#/" /opt/src/ikev2.sh\x27 "$tmpdir/vpn.sh"' \
vpnsetup.sh
sh vpnsetup.sh
if [ "$os_type" = "alpine" ]; then
xl2tpd -c /etc/xl2tpd/xl2tpd.conf
restart_ipsec
else
restart_ipsec
restart_fail2ban
cat /var/log/fail2ban.log
fi
netstat -anpu | grep pluto
netstat -anpu | grep xl2tpd
iptables -nvL
iptables -nvL | grep -q 'ppp+'
iptables -nvL | grep -q '192\.168\.43\.0/24'
iptables -nvL -t nat
iptables -nvL -t nat | grep -q '192\.168\.42\.0/24'
iptables -nvL -t nat | grep -q '192\.168\.43\.0/24'
grep pluto "$log1"
grep xl2tpd "$log2"
ipsec status
ipsec status | grep -q l2tp-psk
ipsec status | grep -q xauth-psk
ipsec status | grep -q ikev2-cp
ls -ld /etc/ipsec.d/vpnclient.mobileconfig
ls -ld /etc/ipsec.d/vpnclient.sswan
ls -ld /etc/ipsec.d/vpnclient.p12
ls -l /usr/bin/ikev2.sh
ls -l /usr/bin/addvpnuser.sh
ls -l /usr/bin/delvpnuser.sh
ls -l /opt/src/ikev2.sh
ls -l /opt/src/addvpnuser.sh
ls -l /opt/src/delvpnuser.sh
bash vpnunst.sh <&1 | grep -i "abort"
4
vpnclient2
ANSWERS
bash ikev2.sh <&1 | grep -i "abort"
2
vpnclient2
ANSWERS
bash ikev2.sh <&1 | grep -i "abort"
6
ANSWERS
bash ikev2.sh <&1 | grep -i "invalid"
if [ "$os_type" = "alpine" ]; then
apk del uuidgen
else
apt-get -yqq remove uuid-runtime
fi
sed -i '/^include /d' /etc/ipsec.conf
VPN_CLIENT_NAME=vpnclient1 \
VPN_DNS_NAME=vpn.example.com \
VPN_DNS_SRV1=1.1.1.1 \
VPN_DNS_SRV2=1.0.0.1 \
bash ikev2.sh --auto
grep -q 'leftid=@vpn.example.com' /etc/ipsec.d/ikev2.conf
grep -q 'modecfgdns="1.1.1.1 1.0.0.1"' /etc/ipsec.d/ikev2.conf
ls -ld /etc/ipsec.d/vpnclient1.mobileconfig
ls -ld /etc/ipsec.d/vpnclient1.sswan
ls -ld /etc/ipsec.d/vpnclient1.p12
grep -q 'vpn.example.com' /etc/ipsec.d/vpnclient1.mobileconfig
grep -q 'vpn.example.com' /etc/ipsec.d/vpnclient1.sswan
restart_ipsec
ipsec status | grep -q ikev2-cp
bash ikev2.sh --addclient invalidclient: 2>&1 | grep -i "invalid"
bash ikev2.sh --addclient vpnclient1 2>&1 | grep -i "already exists"
bash ikev2.sh --addclient vpnclient2
ls -ld /etc/ipsec.d/vpnclient2.mobileconfig
ls -ld /etc/ipsec.d/vpnclient2.sswan
ls -ld /etc/ipsec.d/vpnclient2.p12
bash ikev2.sh --exportclient nonexistclient 2>&1 | grep -i "does not exist"
rm -f /etc/ipsec.d/vpnclient2*
bash ikev2.sh --exportclient vpnclient2
ls -ld /etc/ipsec.d/vpnclient2.mobileconfig
ls -ld /etc/ipsec.d/vpnclient2.sswan
ls -ld /etc/ipsec.d/vpnclient2.p12
bash ikev2.sh --addclient vpnclient2 --exportclient vpnclient2 2>&1 | grep -i "invalid"
bash ikev2.sh --listclients | grep "vpnclient1 \+valid"
bash ikev2.sh --listclients | grep "vpnclient2 \+valid"
bash ikev2.sh --listclients | grep "2 clients"
bash ikev2.sh --revokeclient nonexistclient 2>&1 | grep -i "does not exist"
bash ikev2.sh --revokeclient vpnclient2 <&1 | grep -i "already been revoked"
bash ikev2.sh --exportclient vpnclient2 2>&1 | grep -i "revoked"
bash ikev2.sh --deleteclient nonexistclient 2>&1 | grep -i "does not exist"
bash ikev2.sh --deleteclient vpnclient1 <&1 | grep -i "usage:"
bash ikev2.sh --invalidoption 2>&1 | grep -i "usage:"
bash ikev2.sh --removeikev2 --exportclient vpnclient1 2>&1 | grep -i "invalid"
bash ikev2.sh --removeikev2 <THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS
OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR
"LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER
APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS
PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU
ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE.
TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A
CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE
IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
CONDITIONS.
1. Definitions
- "Adaptation" means a work based upon
the Work, or upon the Work and other pre-existing works,
such as a translation, adaptation, derivative work,
arrangement of music or other alterations of a literary
or artistic work, or phonogram or performance and
includes cinematographic adaptations or any other form in
which the Work may be recast, transformed, or adapted
including in any form recognizably derived from the
original, except that a work that constitutes a
Collection will not be considered an Adaptation for the
purpose of this License. For the avoidance of doubt,
where the Work is a musical work, performance or
phonogram, the synchronization of the Work in
timed-relation with a moving image ("synching") will be
considered an Adaptation for the purpose of this
License.
- "Collection" means a collection of
literary or artistic works, such as encyclopedias and
anthologies, or performances, phonograms or broadcasts,
or other works or subject matter other than works listed
in Section 1(f) below, which, by reason of the selection
and arrangement of their contents, constitute
intellectual creations, in which the Work is included in
its entirety in unmodified form along with one or more
other contributions, each constituting separate and
independent works in themselves, which together are
assembled into a collective whole. A work that
constitutes a Collection will not be considered an
Adaptation (as defined below) for the purposes of this
License.
- "Creative Commons Compatible
License" means a license that is listed at
https://creativecommons.org/compatiblelicenses that has
been approved by Creative Commons as being essentially
equivalent to this License, including, at a minimum,
because that license: (i) contains terms that have the
same purpose, meaning and effect as the License Elements
of this License; and, (ii) explicitly permits the
relicensing of adaptations of works made available under
that license under this License or a Creative Commons
jurisdiction license with the same License Elements as
this License.
- "Distribute" means to make available
to the public the original and copies of the Work or
Adaptation, as appropriate, through sale or other
transfer of ownership.
- "License Elements" means the
following high-level license attributes as selected by
Licensor and indicated in the title of this License:
Attribution, ShareAlike.
- "Licensor" means the individual,
individuals, entity or entities that offer(s) the Work
under the terms of this License.
- "Original Author" means, in the case
of a literary or artistic work, the individual,
individuals, entity or entities who created the Work or
if no individual or entity can be identified, the
publisher; and in addition (i) in the case of a
performance the actors, singers, musicians, dancers, and
other persons who act, sing, deliver, declaim, play in,
interpret or otherwise perform literary or artistic works
or expressions of folklore; (ii) in the case of a
phonogram the producer being the person or legal entity
who first fixes the sounds of a performance or other
sounds; and, (iii) in the case of broadcasts, the
organization that transmits the broadcast.
- "Work" means the literary and/or
artistic work offered under the terms of this License
including without limitation any production in the
literary, scientific and artistic domain, whatever may be
the mode or form of its expression including digital
form, such as a book, pamphlet and other writing; a
lecture, address, sermon or other work of the same
nature; a dramatic or dramatico-musical work; a
choreographic work or entertainment in dumb show; a
musical composition with or without words; a
cinematographic work to which are assimilated works
expressed by a process analogous to cinematography; a
work of drawing, painting, architecture, sculpture,
engraving or lithography; a photographic work to which
are assimilated works expressed by a process analogous to
photography; a work of applied art; an illustration, map,
plan, sketch or three-dimensional work relative to
geography, topography, architecture or science; a
performance; a broadcast; a phonogram; a compilation of
data to the extent it is protected as a copyrightable
work; or a work performed by a variety or circus
performer to the extent it is not otherwise considered a
literary or artistic work.
- "You" means an individual or entity
exercising rights under this License who has not
previously violated the terms of this License with
respect to the Work, or who has received express
permission from the Licensor to exercise rights under
this License despite a previous violation.
- "Publicly Perform" means to perform
public recitations of the Work and to communicate to the
public those public recitations, by any means or process,
including by wire or wireless means or public digital
performances; to make available to the public Works in
such a way that members of the public may access these
Works from a place and at a place individually chosen by
them; to perform the Work to the public by any means or
process and the communication to the public of the
performances of the Work, including by public digital
performance; to broadcast and rebroadcast the Work by any
means including signs, sounds or images.
- "Reproduce" means to make copies of
the Work by any means including without limitation by
sound or visual recordings and the right of fixation and
reproducing fixations of the Work, including storage of a
protected performance or phonogram in digital form or
other electronic medium.
2. Fair Dealing Rights. Nothing in this
License is intended to reduce, limit, or restrict any uses
free from copyright or rights arising from limitations or
exceptions that are provided for in connection with the
copyright protection under copyright law or other
applicable laws.
3. License Grant. Subject to the terms
and conditions of this License, Licensor hereby grants You
a worldwide, royalty-free, non-exclusive, perpetual (for
the duration of the applicable copyright) license to
exercise the rights in the Work as stated below:
- to Reproduce the Work, to incorporate the Work into
one or more Collections, and to Reproduce the Work as
incorporated in the Collections;
- to create and Reproduce Adaptations provided that any
such Adaptation, including any translation in any medium,
takes reasonable steps to clearly label, demarcate or
otherwise identify that changes were made to the original
Work. For example, a translation could be marked "The
original work was translated from English to Spanish," or
a modification could indicate "The original work has been
modified.";
- to Distribute and Publicly Perform the Work including
as incorporated in Collections; and,
- to Distribute and Publicly Perform Adaptations.
-
For the avoidance of doubt:
- Non-waivable Compulsory License
Schemes. In those jurisdictions in which the
right to collect royalties through any statutory or
compulsory licensing scheme cannot be waived, the
Licensor reserves the exclusive right to collect such
royalties for any exercise by You of the rights
granted under this License;
- Waivable Compulsory License
Schemes. In those jurisdictions in which the
right to collect royalties through any statutory or
compulsory licensing scheme can be waived, the
Licensor waives the exclusive right to collect such
royalties for any exercise by You of the rights
granted under this License; and,
- Voluntary License Schemes. The
Licensor waives the right to collect royalties,
whether individually or, in the event that the
Licensor is a member of a collecting society that
administers voluntary licensing schemes, via that
society, from any exercise by You of the rights
granted under this License.
The above rights may be exercised in all media and
formats whether now known or hereafter devised. The above
rights include the right to make such modifications as are
technically necessary to exercise the rights in other media
and formats. Subject to Section 8(f), all rights not
expressly granted by Licensor are hereby reserved.
4. Restrictions. The license granted in
Section 3 above is expressly made subject to and limited by
the following restrictions:
- You may Distribute or Publicly Perform the Work only
under the terms of this License. You must include a copy
of, or the Uniform Resource Identifier (URI) for, this
License with every copy of the Work You Distribute or
Publicly Perform. You may not offer or impose any terms
on the Work that restrict the terms of this License or
the ability of the recipient of the Work to exercise the
rights granted to that recipient under the terms of the
License. You may not sublicense the Work. You must keep
intact all notices that refer to this License and to the
disclaimer of warranties with every copy of the Work You
Distribute or Publicly Perform. When You Distribute or
Publicly Perform the Work, You may not impose any
effective technological measures on the Work that
restrict the ability of a recipient of the Work from You
to exercise the rights granted to that recipient under
the terms of the License. This Section 4(a) applies to
the Work as incorporated in a Collection, but this does
not require the Collection apart from the Work itself to
be made subject to the terms of this License. If You
create a Collection, upon notice from any Licensor You
must, to the extent practicable, remove from the
Collection any credit as required by Section 4(c), as
requested. If You create an Adaptation, upon notice from
any Licensor You must, to the extent practicable, remove
from the Adaptation any credit as required by Section
4(c), as requested.
- You may Distribute or Publicly Perform an Adaptation
only under the terms of: (i) this License; (ii) a later
version of this License with the same License Elements as
this License; (iii) a Creative Commons jurisdiction
license (either this or a later license version) that
contains the same License Elements as this License (e.g.,
Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons
Compatible License. If you license the Adaptation under
one of the licenses mentioned in (iv), you must comply
with the terms of that license. If you license the
Adaptation under the terms of any of the licenses
mentioned in (i), (ii) or (iii) (the "Applicable
License"), you must comply with the terms of the
Applicable License generally and the following
provisions: (I) You must include a copy of, or the URI
for, the Applicable License with every copy of each
Adaptation You Distribute or Publicly Perform; (II) You
may not offer or impose any terms on the Adaptation that
restrict the terms of the Applicable License or the
ability of the recipient of the Adaptation to exercise
the rights granted to that recipient under the terms of
the Applicable License; (III) You must keep intact all
notices that refer to the Applicable License and to the
disclaimer of warranties with every copy of the Work as
included in the Adaptation You Distribute or Publicly
Perform; (IV) when You Distribute or Publicly Perform the
Adaptation, You may not impose any effective
technological measures on the Adaptation that restrict
the ability of a recipient of the Adaptation from You to
exercise the rights granted to that recipient under the
terms of the Applicable License. This Section 4(b)
applies to the Adaptation as incorporated in a
Collection, but this does not require the Collection
apart from the Adaptation itself to be made subject to
the terms of the Applicable License.
- If You Distribute, or Publicly Perform the Work or
any Adaptations or Collections, You must, unless a
request has been made pursuant to Section 4(a), keep
intact all copyright notices for the Work and provide,
reasonable to the medium or means You are utilizing: (i)
the name of the Original Author (or pseudonym, if
applicable) if supplied, and/or if the Original Author
and/or Licensor designate another party or parties (e.g.,
a sponsor institute, publishing entity, journal) for
attribution ("Attribution Parties") in Licensor's
copyright notice, terms of service or by other reasonable
means, the name of such party or parties; (ii) the title
of the Work if supplied; (iii) to the extent reasonably
practicable, the URI, if any, that Licensor specifies to
be associated with the Work, unless such URI does not
refer to the copyright notice or licensing information
for the Work; and (iv) , consistent with Ssection 3(b),
in the case of an Adaptation, a credit identifying the
use of the Work in the Adaptation (e.g., "French
translation of the Work by Original Author," or
"Screenplay based on original Work by Original Author").
The credit required by this Section 4(c) may be
implemented in any reasonable manner; provided, however,
that in the case of a Adaptation or Collection, at a
minimum such credit will appear, if a credit for all
contributing authors of the Adaptation or Collection
appears, then as part of these credits and in a manner at
least as prominent as the credits for the other
contributing authors. For the avoidance of doubt, You may
only use the credit required by this Section for the
purpose of attribution in the manner set out above and,
by exercising Your rights under this License, You may not
implicitly or explicitly assert or imply any connection
with, sponsorship or endorsement by the Original Author,
Licensor and/or Attribution Parties, as appropriate, of
You or Your use of the Work, without the separate,
express prior written permission of the Original Author,
Licensor and/or Attribution Parties.
- Except as otherwise agreed in writing by the Licensor
or as may be otherwise permitted by applicable law, if
You Reproduce, Distribute or Publicly Perform the Work
either by itself or as part of any Adaptations or
Collections, You must not distort, mutilate, modify or
take other derogatory action in relation to the Work
which would be prejudicial to the Original Author's honor
or reputation. Licensor agrees that in those
jurisdictions (e.g. Japan), in which any exercise of the
right granted in Section 3(b) of this License (the right
to make Adaptations) would be deemed to be a distortion,
mutilation, modification or other derogatory action
prejudicial to the Original Author's honor and
reputation, the Licensor will waive or not assert, as
appropriate, this Section, to the fullest extent
permitted by the applicable national law, to enable You
to reasonably exercise Your right under Section 3(b) of
this License (right to make Adaptations) but not
otherwise.
5. Representations, Warranties and
Disclaimer
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN
WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO
REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE
WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING,
WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE
ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE
PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE.
SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED
WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
6. Limitation on Liability. EXCEPT TO
THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL
LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY
SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY
DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK,
EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
7. Termination
- This License and the rights granted hereunder will
terminate automatically upon any breach by You of the
terms of this License. Individuals or entities who have
received Adaptations or Collections from You under this
License, however, will not have their licenses terminated
provided such individuals or entities remain in full
compliance with those licenses. Sections 1, 2, 5, 6, 7,
and 8 will survive any termination of this License.
- Subject to the above terms and conditions, the
license granted here is perpetual (for the duration of
the applicable copyright in the Work). Notwithstanding
the above, Licensor reserves the right to release the
Work under different license terms or to stop
distributing the Work at any time; provided, however that
any such election will not serve to withdraw this License
(or any other license that has been, or is required to
be, granted under the terms of this License), and this
License will continue in full force and effect unless
terminated as stated above.
8. Miscellaneous
- Each time You Distribute or Publicly Perform the Work
or a Collection, the Licensor offers to the recipient a
license to the Work on the same terms and conditions as
the license granted to You under this License.
- Each time You Distribute or Publicly Perform an
Adaptation, Licensor offers to the recipient a license to
the original Work on the same terms and conditions as the
license granted to You under this License.
- If any provision of this License is invalid or
unenforceable under applicable law, it shall not affect
the validity or enforceability of the remainder of the
terms of this License, and without further action by the
parties to this agreement, such provision shall be
reformed to the minimum extent necessary to make such
provision valid and enforceable.
- No term or provision of this License shall be deemed
waived and no breach consented to unless such waiver or
consent shall be in writing and signed by the party to be
charged with such waiver or consent.
- This License constitutes the entire agreement between
the parties with respect to the Work licensed here. There
are no understandings, agreements or representations with
respect to the Work not specified here. Licensor shall
not be bound by any additional provisions that may appear
in any communication from You. This License may not be
modified without the mutual written agreement of the
Licensor and You.
- The rights granted under, and the subject matter
referenced, in this License were drafted utilizing the
terminology of the Berne Convention for the Protection of
Literary and Artistic Works (as amended on September 28,
1979), the Rome Convention of 1961, the WIPO Copyright
Treaty of 1996, the WIPO Performances and Phonograms
Treaty of 1996 and the Universal Copyright Convention (as
revised on July 24, 1971). These rights and subject
matter take effect in the relevant jurisdiction in which
the License terms are sought to be enforced according to
the corresponding provisions of the implementation of
those treaty provisions in the applicable national law.
If the standard suite of rights granted under applicable
copyright law includes additional rights not granted
under this License, such additional rights are deemed to
be included in the License; this License is not intended
to restrict the license of any rights under applicable
law.
================================================
FILE: README-ja.md
================================================
[English](README.md) | [简体中文](README-zh.md) | [繁體中文](README-zh-Hant.md) | [日本語](README-ja.md) | [Русский](README-ru.md)
# IPsec VPN サーバー自動セットアップスクリプト
[](https://github.com/hwdsl2/setup-ipsec-vpn/actions/workflows/main.yml) [](https://github.com/hwdsl2/setup-ipsec-vpn/stargazers) [](https://github.com/hwdsl2/docker-ipsec-vpn-server) [](https://github.com/hwdsl2/docker-ipsec-vpn-server)
数分で自分のIPsec VPNサーバーをセットアップし、IPsec/L2TP、Cisco IPsec、IKEv2をサポートします。
IPsec VPNはネットワークトラフィックを暗号化し、インターネット経由でデータが送信される際に、VPNサーバーとあなたの間の誰もがデータを盗聴できないようにします。これは、コーヒーショップ、空港、ホテルの部屋などの安全でないネットワークを使用する際に特に有用です。
IPsecサーバーとして[Libreswan](https://libreswan.org/)を使用し、L2TPプロバイダーとして[xl2tpd](https://github.com/xelerance/xl2tpd)を使用します。
**[» :book: 本:Privacy Tools in the Age of AI](docs/vpn-book-ja.md) [VPNサーバーの構築方法](docs/vpn-book-ja.md)**
## クイックスタート
まず、Ubuntu、Debian、またはCentOSをインストールしたLinuxサーバー\*を準備します。
このワンライナーを使用してIPsec VPNサーバーをセットアップします:
```bash
wget https://get.vpnsetup.net -O vpn.sh && sudo sh vpn.sh
```
VPNログイン情報はランダムに生成され、完了時に表示されます。
**オプション:** 同じサーバーに[WireGuard](https://github.com/hwdsl2/wireguard-install)および/または[OpenVPN](https://github.com/hwdsl2/openvpn-install)をインストールします。
スクリプトの動作を確認する(ターミナル記録)。
**注:** この記録はデモ目的のみです。この記録のVPN資格情報は**無効**です。

ダウンロードできない場合はこちらをクリックしてください。
`curl`を使用してダウンロードすることもできます:
```bash
curl -fsSL https://get.vpnsetup.net -o vpn.sh && sudo sh vpn.sh
```
代替セットアップURL:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/vpnsetup.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/vpnsetup.sh
```
ダウンロードできない場合は、[vpnsetup.sh](vpnsetup.sh)を開き、右側の`Raw`ボタンをクリックします。`Ctrl/Cmd+A`を押してすべて選択し、`Ctrl/Cmd+C`を押してコピーし、お気に入りのエディタに貼り付けます。
事前構築された[Dockerイメージ](https://github.com/hwdsl2/docker-ipsec-vpn-server)も利用可能です。他のオプションやクライアントのセットアップについては、以下のセクションを参照してください。
\* クラウドサーバー、仮想プライベートサーバー(VPS)、または専用サーバー。
## 機能
- 完全自動化されたIPsec VPNサーバーのセットアップ、ユーザー入力不要
- 強力で高速な暗号(例:AES-GCM)をサポートするIKEv2をサポート
- iOS、macOS、Androidデバイスを自動設定するVPNプロファイルを生成
- Windows、macOS、iOS、Android、Chrome OS、LinuxをVPNクライアントとしてサポート
- VPNユーザーと証明書を管理するためのヘルパースクリプトを含む
## 要件
以下のいずれかのインストールを備えたクラウドサーバー、仮想プライベートサーバー(VPS)、または専用サーバー:
- Ubuntu 24.04または22.04
- Debian 13、12、または11
- CentOS Stream 10または9
- Rocky LinuxまたはAlmaLinux
- Oracle Linux
- Amazon Linux 2
他のサポートされているLinuxディストリビューション。
- Raspberry Pi OS(Raspbian)
- Kali Linux
- Alpine Linux
- Red Hat Enterprise Linux(RHEL)
これは、[DigitalOcean](https://blog.ls20.com/digitalocean)、[Vultr](https://blog.ls20.com/vultr)、[Linode](https://blog.ls20.com/linode)、[OVH](https://www.ovhcloud.com/en/vps/)、および[Microsoft Azure](https://azure.microsoft.com)などのパブリッククラウドのLinux VMも含まれます。パブリッククラウドユーザーは、[ユーザーデータ](https://blog.ls20.com/ipsec-l2tp-vpn-auto-setup-for-ubuntu-12-04-on-amazon-ec2/#vpnsetup)を使用してデプロイすることもできます。
クイックデプロイ:
[](https://cloud.linode.com/stackscripts/37239) [](aws/README.md) [](azure/README.md)
[**» 自分のVPNを運用したいが、そのためのサーバーがない**](https://blog.ls20.com/ipsec-l2tp-vpn-auto-setup-for-ubuntu-12-04-on-amazon-ec2/#gettingavps)
外部ファイアウォールを持つサーバー(例:[EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)/[GCE](https://cloud.google.com/vpc/docs/firewalls))の場合、VPNのUDPポート500および4500を開きます。
事前構築された[Dockerイメージ](https://github.com/hwdsl2/docker-ipsec-vpn-server)も利用可能です。上級ユーザーは[Raspberry Pi](https://www.raspberrypi.com)にインストールできます。[[1]](https://elasticbyte.net/posts/setting-up-a-native-cisco-ipsec-vpn-server-using-a-raspberry-pi/) [[2]](https://www.stewright.me/2018/07/create-a-raspberry-pi-vpn-server-using-l2tpipsec/)
:warning: これらのスクリプトをPCやMacで実行しないでください!これらはサーバーでのみ使用する必要があります!
## インストール
まず、サーバーを更新します:`sudo apt-get update && sudo apt-get dist-upgrade`(Ubuntu/Debian)または`sudo yum update`を実行し、再起動します。これはオプションですが、推奨されます。
VPNをインストールするには、次のオプションのいずれかを選択してください:
**オプション1:** スクリプトにランダムなVPN資格情報を生成させる(完了時に表示されます)。
```bash
wget https://get.vpnsetup.net -O vpn.sh && sudo sh vpn.sh
```
**オプション2:** スクリプトを編集し、自分のVPN資格情報を提供する。
```bash
wget https://get.vpnsetup.net -O vpn.sh
nano -w vpn.sh
[自分の値に置き換える:YOUR_IPSEC_PSK、YOUR_USERNAME、およびYOUR_PASSWORD]
sudo sh vpn.sh
```
**注:** 安全なIPsec PSKは少なくとも20のランダムな文字で構成されるべきです。
**オプション3:** 環境変数として自分のVPN資格情報を定義する。
```bash
# すべての値は 'シングルクォート' で囲む必要があります
# これらの特殊文字を値に使用しないでください: \ " '
wget https://get.vpnsetup.net -O vpn.sh
sudo VPN_IPSEC_PSK='your_ipsec_pre_shared_key' \
VPN_USER='your_vpn_username' \
VPN_PASSWORD='your_vpn_password' \
sh vpn.sh
```
同じサーバーに[WireGuard](https://github.com/hwdsl2/wireguard-install)および/または[OpenVPN](https://github.com/hwdsl2/openvpn-install)をインストールすることもできます。サーバーがCentOS Stream、Rocky Linux、またはAlmaLinuxを実行している場合、最初にOpenVPN/WireGuardをインストールし、その後IPsec VPNをインストールします。
ダウンロードできない場合はこちらをクリックしてください。
`curl`を使用してダウンロードすることもできます。例えば:
```bash
curl -fL https://get.vpnsetup.net -o vpn.sh
sudo sh vpn.sh
```
代替セットアップURL:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/vpnsetup.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/vpnsetup.sh
```
ダウンロードできない場合は、[vpnsetup.sh](vpnsetup.sh)を開き、右側の`Raw`ボタンをクリックします。`Ctrl/Cmd+A`を押してすべて選択し、`Ctrl/Cmd+C`を押してコピーし、お気に入りのエディタに貼り付けます。
古いLibreswanバージョン4をインストールしたい。
一般的には、最新の[Libreswan](https://libreswan.org/)バージョン5を使用することをお勧めします。これはこのプロジェクトのデフォルトバージョンです。ただし、古いLibreswanバージョン4をインストールしたい場合:
```bash
wget https://get.vpnsetup.net -O vpn.sh
sudo VPN_SWAN_VER=4.15 sh vpn.sh
```
**注:** Libreswanバージョン5がすでにインストールされている場合、最初に[VPNをアンインストール](docs/uninstall.md)してからLibreswanバージョン4をインストールする必要があるかもしれません。あるいは、[アップデートスクリプト](#libreswanのアップグレード)をダウンロードし、`SWAN_VER=4.15`を指定して編集し、スクリプトを実行します。
## VPNオプションのカスタマイズ
### 代替DNSサーバーの使用
デフォルトでは、VPNがアクティブなときにクライアントは[Google Public DNS](https://developers.google.com/speed/public-dns/)を使用するように設定されています。VPNをインストールする際に、すべてのVPNモードに対してカスタムDNSサーバーを指定することができます。例:
```bash
sudo VPN_DNS_SRV1=1.1.1.1 VPN_DNS_SRV2=1.0.0.1 sh vpn.sh
```
`VPN_DNS_SRV1`を使用してプライマリDNSサーバーを指定し、`VPN_DNS_SRV2`を使用してセカンダリDNSサーバーを指定します(オプション)。
以下は、参考のためのいくつかの人気のあるパブリックDNSプロバイダーのリストです。
| プロバイダー | プライマリDNS | セカンダリDNS | 注記 |
| -------- | ----------- | ------------- | ----- |
| [Google Public DNS](https://developers.google.com/speed/public-dns) | 8.8.8.8 | 8.8.4.4 | このプロジェクトのデフォルト |
| [Cloudflare](https://1.1.1.1/dns/) | 1.1.1.1 | 1.0.0.1 | 参照:[Cloudflare for families](https://1.1.1.1/family/) |
| [Quad9](https://www.quad9.net) | 9.9.9.9 | 149.112.112.112 | 悪意のあるドメインをブロック |
| [OpenDNS](https://www.opendns.com/home-internet-security/) | 208.67.222.222 | 208.67.220.220 | フィッシングドメインをブロック、設定可能。 |
| [CleanBrowsing](https://cleanbrowsing.org/filters/) | 185.228.168.9 | 185.228.169.9 | [ドメインフィルター](https://cleanbrowsing.org/filters/)利用可能 |
| [NextDNS](https://nextdns.io/?from=bg25bwmp) | さまざま | さまざま | 広告ブロック、無料プラン利用可能。[詳細はこちら](https://nextdns.io/?from=bg25bwmp)。 |
| [Control D](https://controld.com/free-dns) | さまざま | さまざま | 広告ブロック、設定可能。[詳細はこちら](https://controld.com/free-dns)。 |
VPNセットアップ後にDNSサーバーを変更する必要がある場合は、[高度な使用法](docs/advanced-usage.md)を参照してください。
**注:** サーバーにIKEv2がすでに設定されている場合、上記の変数はIKEv2モードには影響しません。その場合、DNSサーバーなどのIKEv2オプションをカスタマイズするには、まず[IKEv2を削除](docs/ikev2-howto.md#remove-ikev2)し、`sudo ikev2.sh`を使用して再設定します。
### IKEv2オプションのカスタマイズ
VPNをインストールする際に、上級ユーザーはオプションでIKEv2オプションをカスタマイズできます。
オプション1: VPNセットアップ時にIKEv2をスキップし、カスタムオプションを使用してIKEv2を設定します。
VPNをインストールする際に、IKEv2をスキップし、IPsec/L2TPおよびIPsec/XAuth("Cisco IPsec")モードのみをインストールできます:
```bash
sudo VPN_SKIP_IKEV2=yes sh vpn.sh
```
(オプション)VPNクライアントにカスタムDNSサーバーを指定する場合は、`VPN_DNS_SRV1`およびオプションで`VPN_DNS_SRV2`を定義します。詳細については、[代替DNSサーバーの使用](#代替dnsサーバーの使用)を参照してください。
その後、IKEv2ヘルパースクリプトを実行して、カスタムオプションを使用して対話的にIKEv2を設定します:
```bash
sudo ikev2.sh
```
次のオプションをカスタマイズできます:VPNサーバーのDNS名、最初のクライアントの名前と有効期間、VPNクライアントのDNSサーバー、およびクライアント構成ファイルをパスワードで保護するかどうか。
**注:** サーバーにIKEv2がすでに設定されている場合、`VPN_SKIP_IKEV2`変数は影響しません。その場合、IKEv2オプションをカスタマイズするには、まず[IKEv2を削除](docs/ikev2-howto.md#remove-ikev2)し、`sudo ikev2.sh`を使用して再設定します。
オプション2: 環境変数を使用してIKEv2オプションをカスタマイズします。
VPNをインストールする際に、オプションでIKEv2サーバーアドレスのDNS名を指定できます。DNS名は完全修飾ドメイン名(FQDN)である必要があります。例:
```bash
sudo VPN_DNS_NAME='vpn.example.com' sh vpn.sh
```
同様に、最初のIKEv2クライアントの名前を指定できます。指定しない場合、デフォルトは`vpnclient`です。
```bash
sudo VPN_CLIENT_NAME='your_client_name' sh vpn.sh
```
デフォルトでは、VPNがアクティブなときにクライアントは[Google Public DNS](https://developers.google.com/speed/public-dns/)を使用するように設定されています。すべてのVPNモードに対してカスタムDNSサーバーを指定できます。例:
```bash
sudo VPN_DNS_SRV1=1.1.1.1 VPN_DNS_SRV2=1.0.0.1 sh vpn.sh
```
デフォルトでは、IKEv2クライアント構成のインポート時にパスワードは必要ありません。ランダムなパスワードを使用してクライアント構成ファイルを保護することを選択できます。
```bash
sudo VPN_PROTECT_CONFIG=yes sh vpn.sh
```
参考のために:IKEv1およびIKEv2パラメータのリスト。
| IKEv1パラメータ\* | デフォルト値 | カスタマイズ(環境変数)\*\* |
| ------------ | ---- | ----------------- |
| サーバーアドレス(DNS名)| - | いいえ、ただしDNS名を使用して接続できます |
| サーバーアドレス(パブリックIP)| 自動検出 | VPN_PUBLIC_IP |
| IPsec事前共有キー | 自動生成 | VPN_IPSEC_PSK |
| VPNユーザー名 | vpnuser | VPN_USER |
| VPNパスワード | 自動生成 | VPN_PASSWORD |
| クライアントのDNSサーバー | Google Public DNS | VPN_DNS_SRV1、VPN_DNS_SRV2 |
| IKEv2セットアップをスキップ | いいえ | VPN_SKIP_IKEV2=yes |
\* これらのIKEv1パラメータは、IPsec/L2TPおよびIPsec/XAuth("Cisco IPsec")モード用です。
\*\* vpn(setup).shを実行する際に、これらを環境変数として定義します。
| IKEv2パラメータ\* | デフォルト値 | カスタマイズ(環境変数)\*\* | カスタマイズ(対話型)\*\*\* |
| ----------- | ---- | ------------------ | ----------------- |
| サーバーアドレス(DNS名)| - | VPN_DNS_NAME | ✅ |
| サーバーアドレス(パブリックIP)| 自動検出 | VPN_PUBLIC_IP | ✅ |
| 最初のクライアントの名前 | vpnclient | VPN_CLIENT_NAME | ✅ |
| クライアントのDNSサーバー | Google Public DNS | VPN_DNS_SRV1、VPN_DNS_SRV2 | ✅ |
| クライアント構成ファイルを保護する | いいえ | VPN_PROTECT_CONFIG=yes | ✅ |
| MOBIKEの有効/無効 | サポートされている場合は有効 | ❌ | ✅ |
| クライアント証明書の有効期間 | 10年(120ヶ月)| VPN_CLIENT_VALIDITY\*\*\*\* | ✅ |
| CAおよびサーバー証明書の有効期間 | 10年(120ヶ月)| ❌ | ❌ |
| CA証明書名 | IKEv2 VPN CA | ❌ | ❌ |
| 証明書キーサイズ | 3072ビット | ❌ | ❌ |
\* これらのIKEv2パラメータは、IKEv2モード用です。
\*\* vpn(setup).shを実行する際、または自動モードでIKEv2を設定する際に、これらを環境変数として定義します(`sudo ikev2.sh --auto`)。
\*\*\* 対話型IKEv2セットアップ中にカスタマイズできます(`sudo ikev2.sh`)。上記のオプション1を参照してください。
\*\*\*\* `VPN_CLIENT_VALIDITY`を使用して、クライアント証明書の有効期間を月単位で指定します。1から120の間の整数である必要があります。
これらのパラメータに加えて、上級ユーザーはVPNセットアップ中に[VPNサブネットをカスタマイズ](docs/advanced-usage.md#customize-vpn-subnets)することもできます。
## 次のステップ
*他の言語で読む:[English](README.md#next-steps)、[简体中文](README-zh.md#下一步)、[繁體中文](README-zh-Hant.md#下一步)、[日本語](README-ja.md#次のステップ)、[Русский](README-ru.md#следующие-шаги)。*
コンピュータやデバイスをVPNに接続します。詳細は以下のリンク(英語)をご覧ください。
**[IKEv2 VPNクライアントの設定(推奨)](docs/ikev2-howto.md)**
**[IPsec/L2TP VPNクライアントの設定](docs/clients.md)**
**[IPsec/XAuth("Cisco IPsec")VPNクライアントの設定](docs/clients-xauth.md)**
**:book: [VPN本](docs/vpn-book.md)を読んで[追加コンテンツ](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-O5O7FVF8J)にアクセスしてください。**
自分のVPNを楽しんでください! :sparkles::tada::rocket::sparkles:
## 重要な注意事項
**Windowsユーザー**:IPsec/L2TPモードの場合、VPNサーバーまたはクライアントがNAT(例:家庭用ルーター)の背後にある場合、[一度だけレジストリを変更](docs/clients.md#windows-error-809)する必要があります。
同じVPNアカウントを複数のデバイスで使用できます。ただし、IPsec/L2TPの制限により、同じNAT(例:家庭用ルーター)の背後から複数のデバイスを接続する場合は、[IKEv2](docs/ikev2-howto.md)または[IPsec/XAuth](docs/clients-xauth.md)モードを使用する必要があります。VPNユーザーアカウントを表示または更新するには、[VPNユーザーの管理](docs/manage-users.md)を参照してください。
外部ファイアウォールを持つサーバー(例:[EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)/[GCE](https://cloud.google.com/vpc/docs/firewalls))の場合、VPNのUDPポート500および4500を開きます。Aliyunユーザーは、[#433](https://github.com/hwdsl2/setup-ipsec-vpn/issues/433)を参照してください。
クライアントは、VPNがアクティブなときに[Google Public DNS](https://developers.google.com/speed/public-dns/)を使用するように設定されています。別のDNSプロバイダーを好む場合は、[高度な使用法](docs/advanced-usage.md)を参照してください。
カーネルサポートを使用すると、IPsec/L2TPのパフォーマンスが向上する可能性があります。これは[すべてのサポートされているOS](#要件)で利用可能です。Ubuntuユーザーは`linux-modules-extra-$(uname -r)`パッケージをインストールし、`service xl2tpd restart`を実行する必要があります。
スクリプトは、変更を加える前に既存の構成ファイルをバックアップし、`.old-date-time`サフィックスを付けます。
## Libreswanのアップグレード
このワンライナーを使用して、VPNサーバー上の[Libreswan](https://libreswan.org)([変更ログ](https://github.com/libreswan/libreswan/blob/main/CHANGES) | [アナウンス](https://lists.libreswan.org))を更新します。
```bash
wget https://get.vpnsetup.net/upg -O vpnup.sh && sudo sh vpnup.sh
```
ダウンロードできない場合はこちらをクリックしてください。
`curl`を使用してダウンロードすることもできます:
```bash
curl -fsSL https://get.vpnsetup.net/upg -o vpnup.sh && sudo sh vpnup.sh
```
代替アップデートURL:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/extras/vpnupgrade.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras/vpnupgrade.sh
```
ダウンロードできない場合は、[vpnupgrade.sh](extras/vpnupgrade.sh)を開き、右側の`Raw`ボタンをクリックします。`Ctrl/Cmd+A`を押してすべて選択し、`Ctrl/Cmd+C`を押してコピーし、お気に入りのエディタに貼り付けます。
最新のサポートされているLibreswanバージョンは`5.2`です。インストールされているバージョンを確認します:`ipsec --version`。
**注:** `xl2tpd`は、Ubuntu/Debianの`apt-get`などのシステムのパッケージマネージャーを使用して更新できます。
## VPNユーザーの管理
[VPNユーザーの管理](docs/manage-users.md)(英語)を参照してください。
- [ヘルパースクリプトを使用してVPNユーザーを管理する](docs/manage-users.md#manage-vpn-users-using-helper-scripts)
- [VPNユーザーを表示する](docs/manage-users.md#view-vpn-users)
- [IPsec PSKを表示または更新する](docs/manage-users.md#view-or-update-the-ipsec-psk)
- [VPNユーザーを手動で管理する](docs/manage-users.md#manually-manage-vpn-users)
## 高度な使用法
[高度な使用法](docs/advanced-usage.md)(英語)を参照してください。
- [代替DNSサーバーの使用](docs/advanced-usage.md#use-alternative-dns-servers)
- [DNS名とサーバーIPの変更](docs/advanced-usage.md#dns-name-and-server-ip-changes)
- [IKEv2専用VPN](docs/advanced-usage.md#ikev2-only-vpn)
- [内部VPN IPとトラフィック](docs/advanced-usage.md#internal-vpn-ips-and-traffic)
- [VPNサーバーのパブリックIPを指定する](docs/advanced-usage.md#specify-vpn-servers-public-ip)
- [VPNサブネットのカスタマイズ](docs/advanced-usage.md#customize-vpn-subnets)
- [IPv6サポート](docs/advanced-usage.md#ipv6-support)
- [VPNクライアントへのポートフォワーディング](docs/advanced-usage.md#port-forwarding-to-vpn-clients)
- [スプリットトンネリング](docs/advanced-usage.md#split-tunneling)
- [VPNサーバーのサブネットにアクセスする](docs/advanced-usage.md#access-vpn-servers-subnet)
- [サーバーのサブネットからVPNクライアントにアクセスする](docs/advanced-usage.md#access-vpn-clients-from-servers-subnet)
- [IPTablesルールの変更](docs/advanced-usage.md#modify-iptables-rules)
- [Google BBR輻輳制御の展開](docs/advanced-usage.md#deploy-google-bbr-congestion-control)
## VPNのアンインストール
IPsec VPNをアンインストールするには、[ヘルパースクリプト](extras/vpnuninstall.sh)を実行します:
**警告:** このヘルパースクリプトは、サーバーからIPsec VPNを削除します。すべてのVPN構成は**永久に削除**され、Libreswanおよびxl2tpdは削除されます。これは**元に戻すことはできません**!
```bash
wget https://get.vpnsetup.net/unst -O unst.sh && sudo bash unst.sh
```
ダウンロードできない場合はこちらをクリックしてください。
`curl`を使用してダウンロードすることもできます:
```bash
curl -fsSL https://get.vpnsetup.net/unst -o unst.sh && sudo bash unst.sh
```
代替スクリプトURL:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/extras/vpnuninstall.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras/vpnuninstall.sh
```
詳細については、[VPNのアンインストール](docs/uninstall.md)を参照してください。
## フィードバックと質問
- このプロジェクトに提案がありますか?[改善リクエスト](https://github.com/hwdsl2/setup-ipsec-vpn/issues/new/choose)を開いてください。[プルリクエスト](https://github.com/hwdsl2/setup-ipsec-vpn/pulls)も歓迎します。
- 再現可能なバグを見つけた場合、[IPsec VPN](https://github.com/libreswan/libreswan/issues?q=is%3Aissue)または[VPNスクリプト](https://github.com/hwdsl2/setup-ipsec-vpn/issues/new/choose)のバグレポートを開いてください。
- 質問がありますか?まず、[既存の問題](https://github.com/hwdsl2/setup-ipsec-vpn/issues?q=is%3Aissue)と、この[Gist](https://gist.github.com/hwdsl2/9030462#comments)および[私のブログ](https://blog.ls20.com/ipsec-l2tp-vpn-auto-setup-for-ubuntu-12-04-on-amazon-ec2/#disqus_thread)のコメントを検索してください。
- VPNに関連する質問は、[Libreswan](https://lists.libreswan.org)または[strongSwan](https://lists.strongswan.org)のメーリングリストで質問するか、次のウィキを参照してください:[[1]](https://libreswan.org/wiki/Main_Page) [[2]](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/sec-securing_virtual_private_networks) [[3]](https://wiki.strongswan.org/projects/strongswan/wiki/UserDocumentation) [[4]](https://wiki.gentoo.org/wiki/IPsec_L2TP_VPN_server) [[5]](https://wiki.archlinux.org/index.php/Openswan_L2TP/IPsec_VPN_client_setup)。
## ライセンス
著作権 (C) 2014-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
[Thomas Sarlandieの作品](https://github.com/sarfata/voodooprivacy)に基づく(著作権2012)
[](http://creativecommons.org/licenses/by-sa/3.0/)
この作品は[クリエイティブ・コモンズ表示-継承3.0非移植ライセンス](http://creativecommons.org/licenses/by-sa/3.0/)の下でライセンスされています。
帰属が必要です:私の名前を派生物に含め、改善方法を教えてください!
================================================
FILE: README-ru.md
================================================
[English](README.md) | [简体中文](README-zh.md) | [繁體中文](README-zh-Hant.md) | [日本語](README-ja.md) | [Русский](README-ru.md)
# Скрипты автоматической настройки сервера IPsec VPN
[](https://github.com/hwdsl2/setup-ipsec-vpn/actions/workflows/main.yml) [](https://github.com/hwdsl2/setup-ipsec-vpn/stargazers) [](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-ru.md) [](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-ru.md)
Разверните собственный сервер IPsec VPN всего за несколько минут с поддержкой IPsec/L2TP, Cisco IPsec и IKEv2.
IPsec VPN шифрует сетевой трафик, поэтому никто между вами и VPN-сервером не сможет перехватывать ваши данные во время их передачи через Интернет. Это особенно полезно при использовании незащищённых сетей, например в кофейнях, аэропортах или гостиничных номерах.
Мы будем использовать [Libreswan](https://libreswan.org/) в качестве сервера IPsec и [xl2tpd](https://github.com/xelerance/xl2tpd) в качестве поставщика L2TP.
**[» :book: Книга: Privacy Tools in the Age of AI](docs/vpn-book.md) [Build Your Own VPN Server](docs/vpn-book.md)**
## Быстрый старт
Сначала подготовьте ваш Linux-сервер\* с установленной системой Ubuntu, Debian или CentOS.
Используйте эту однострочную команду для настройки сервера IPsec VPN:
```bash
wget https://get.vpnsetup.net -O vpn.sh && sudo sh vpn.sh
```
Данные для входа в VPN будут сгенерированы случайным образом и показаны после завершения установки.
**Дополнительно:** Установите [WireGuard](https://github.com/hwdsl2/wireguard-install/blob/master/README-ru.md) и/или [OpenVPN](https://github.com/hwdsl2/openvpn-install/blob/master/README-ru.md) на тот же сервер.
Посмотреть работу скрипта (запись терминала).
**Примечание:** Эта запись предназначена только для демонстрационных целей. Учетные данные VPN в этой записи **НЕ** являются действительными.

Нажмите здесь, если не удаётся скачать.
Вы также можете использовать `curl` для загрузки:
```bash
curl -fsSL https://get.vpnsetup.net -o vpn.sh && sudo sh vpn.sh
```
Альтернативные URL для установки:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/vpnsetup.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/vpnsetup.sh
```
Если вы не можете скачать файл, откройте [vpnsetup.sh](vpnsetup.sh), затем нажмите кнопку `Raw` справа. Нажмите `Ctrl/Cmd+A`, чтобы выделить всё, `Ctrl/Cmd+C`, чтобы скопировать, затем вставьте в ваш любимый редактор.
Также доступен готовый [образ Docker](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-ru.md). Для других вариантов и настройки клиентов прочитайте разделы ниже.
\* Облачный сервер, виртуальный частный сервер (VPS) или выделенный сервер.
## Возможности
- Полностью автоматическая настройка сервера IPsec VPN, ввод пользователя не требуется
- Поддержка IKEv2 с мощными и быстрыми шифрами (например, AES-GCM)
- Генерация профилей VPN для автоматической настройки устройств iOS, macOS и Android
- Поддержка Windows, macOS, iOS, Android, Chrome OS и Linux в качестве VPN-клиентов
- Включает вспомогательные скрипты для управления пользователями VPN и сертификатами
## Требования
Облачный сервер, виртуальный частный сервер (VPS) или выделенный сервер с установленной системой:
- Ubuntu 24.04 или 22.04
- Debian 13, 12 или 11
- CentOS Stream 10 или 9
- Rocky Linux или AlmaLinux
- Oracle Linux
- Amazon Linux 2
Другие поддерживаемые дистрибутивы Linux.
- Raspberry Pi OS (Raspbian)
- Kali Linux
- Alpine Linux
- Red Hat Enterprise Linux (RHEL)
Это также включает виртуальные машины Linux в публичных облаках, таких как [DigitalOcean](https://blog.ls20.com/digitalocean), [Vultr](https://blog.ls20.com/vultr), [Linode](https://blog.ls20.com/linode), [OVH](https://www.ovhcloud.com/en/vps/) и [Microsoft Azure](https://azure.microsoft.com). Пользователи публичных облаков также могут выполнить развёртывание с помощью [пользовательскими данными](https://blog.ls20.com/ipsec-l2tp-vpn-auto-setup-for-ubuntu-12-04-on-amazon-ec2/#vpnsetup).
Быстрое развёртывание в:
[](https://cloud.linode.com/stackscripts/37239) [](aws/README.md) [](azure/README.md)
[**» Я хочу запустить собственный VPN, но у меня нет сервера для этого**](https://blog.ls20.com/ipsec-l2tp-vpn-auto-setup-for-ubuntu-12-04-on-amazon-ec2/#gettingavps)
Для серверов с внешним файрволом (например, [EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)/[GCE](https://cloud.google.com/vpc/docs/firewalls)) откройте UDP-порты 500 и 4500 для VPN.
Также доступен готовый [образ Docker](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-ru.md). Продвинутые пользователи могут установить его на [Raspberry Pi](https://www.raspberrypi.com). [[1]](https://elasticbyte.net/posts/setting-up-a-native-cisco-ipsec-vpn-server-using-a-raspberry-pi/) [[2]](https://www.stewright.me/2018/07/create-a-raspberry-pi-vpn-server-using-l2tpipsec/)
:warning: **НЕ** запускайте эти скрипты на вашем ПК или Mac! Их следует использовать только на сервере!
## Установка
Сначала обновите ваш сервер с помощью `sudo apt-get update && sudo apt-get dist-upgrade` (Ubuntu/Debian) или `sudo yum update`, затем перезагрузите систему. Это необязательно, но рекомендуется.
Чтобы установить VPN, выберите один из следующих вариантов:
**Вариант 1:** Позвольте скрипту сгенерировать случайные учетные данные VPN (они будут показаны после завершения).
```bash
wget https://get.vpnsetup.net -O vpn.sh && sudo sh vpn.sh
```
**Вариант 2:** Отредактируйте скрипт и укажите собственные учетные данные VPN.
```bash
wget https://get.vpnsetup.net -O vpn.sh
nano -w vpn.sh
[Замените на собственные значения: YOUR_IPSEC_PSK, YOUR_USERNAME и YOUR_PASSWORD]
sudo sh vpn.sh
```
**Примечание:** Безопасный IPsec PSK должен состоять как минимум из 20 случайных символов.
**Вариант 3:** Определите учетные данные VPN как переменные окружения.
```bash
# Все значения ДОЛЖНЫ быть заключены в 'одинарные кавычки'
# НЕ используйте внутри значений следующие специальные символы: \ " '
wget https://get.vpnsetup.net -O vpn.sh
sudo VPN_IPSEC_PSK='your_ipsec_pre_shared_key' \
VPN_USER='your_vpn_username' \
VPN_PASSWORD='your_vpn_password' \
sh vpn.sh
```
При желании вы можете установить [WireGuard](https://github.com/hwdsl2/wireguard-install/blob/master/README-ru.md) и/или [OpenVPN](https://github.com/hwdsl2/openvpn-install/blob/master/README-ru.md) на том же сервере. Если ваш сервер работает на CentOS Stream, Rocky Linux или AlmaLinux, сначала установите OpenVPN/WireGuard, а затем установите IPsec VPN.
Нажмите здесь, если не удаётся скачать.
Вы также можете использовать `curl` для загрузки. Например:
```bash
curl -fL https://get.vpnsetup.net -o vpn.sh
sudo sh vpn.sh
```
Альтернативные URL для установки:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/vpnsetup.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/vpnsetup.sh
```
Если вы не можете скачать файл, откройте [vpnsetup.sh](vpnsetup.sh), затем нажмите кнопку `Raw` справа. Нажмите `Ctrl/Cmd+A`, чтобы выделить всё, `Ctrl/Cmd+C`, чтобы скопировать, затем вставьте в ваш любимый редактор.
Я хочу установить более старую версию Libreswan 4.
Обычно рекомендуется использовать последнюю версию [Libreswan](https://libreswan.org/) 5, которая является версией по умолчанию в этом проекте. Однако если вы хотите установить более старую версию Libreswan 4:
```bash
wget https://get.vpnsetup.net -O vpn.sh
sudo VPN_SWAN_VER=4.15 sh vpn.sh
```
**Примечание:** Если версия Libreswan 5 уже установлена, возможно, вам сначала потребуется [удалить VPN](docs/uninstall.md), прежде чем устанавливать Libreswan версии 4. В качестве альтернативы можно скачать [скрипт обновления](#обновление-libreswan), отредактировать его, указав `SWAN_VER=4.15`, затем запустить скрипт.
## Настройка параметров VPN
### Использование альтернативных DNS-серверов
По умолчанию клиенты настроены использовать [Google Public DNS](https://developers.google.com/speed/public-dns/) при активном VPN. При установке VPN вы можете при желании указать собственные DNS-серверы для всех режимов VPN. Пример:
```bash
sudo VPN_DNS_SRV1=1.1.1.1 VPN_DNS_SRV2=1.0.0.1 sh vpn.sh
```
Используйте `VPN_DNS_SRV1` для указания основного DNS-сервера и `VPN_DNS_SRV2` для указания резервного DNS-сервера (необязательно).
Ниже приведён список некоторых популярных публичных DNS-провайдеров для справки.
| Провайдер | Основной DNS | Резервный DNS | Примечания |
| -------- | ----------- | ------------- | ----- |
| [Google Public DNS](https://developers.google.com/speed/public-dns) | 8.8.8.8 | 8.8.4.4 | Используется по умолчанию в этом проекте |
| [Cloudflare](https://1.1.1.1/dns/) | 1.1.1.1 | 1.0.0.1 | См. также: [Cloudflare for families](https://1.1.1.1/family/) |
| [Quad9](https://www.quad9.net) | 9.9.9.9 | 149.112.112.112 | Блокирует вредоносные домены |
| [OpenDNS](https://www.opendns.com/home-internet-security/) | 208.67.222.222 | 208.67.220.220 | Блокирует фишинговые домены, настраиваемый |
| [CleanBrowsing](https://cleanbrowsing.org/filters/) | 185.228.168.9 | 185.228.169.9 | Доступны [фильтры доменов](https://cleanbrowsing.org/filters/) |
| [NextDNS](https://nextdns.io/?from=bg25bwmp) | Различается | Различается | Блокировка рекламы, доступен бесплатный тариф. [Подробнее](https://nextdns.io/?from=bg25bwmp). |
| [Control D](https://controld.com/free-dns) | Различается | Различается | Блокировка рекламы, настраиваемый. [Подробнее](https://controld.com/free-dns). |
Если вам нужно изменить DNS-серверы после настройки VPN, см. раздел [Расширенное использование](docs/advanced-usage.md).
**Примечание:** Если IKEv2 уже настроен на сервере, переменные выше не влияют на режим IKEv2. В этом случае для настройки параметров IKEv2, таких как DNS-серверы, вы можете сначала [удалить IKEv2](docs/ikev2-howto.md#remove-ikev2), а затем снова настроить его с помощью `sudo ikev2.sh`.
### Настройка параметров IKEv2
При установке VPN продвинутые пользователи могут при желании настроить параметры IKEv2.
Вариант 1: Пропустить IKEv2 во время настройки VPN, затем настроить IKEv2 с пользовательскими параметрами.
При установке VPN вы можете пропустить IKEv2 и установить только режимы IPsec/L2TP и IPsec/XAuth («Cisco IPsec»):
```bash
sudo VPN_SKIP_IKEV2=yes sh vpn.sh
```
(Необязательно) Если вы хотите указать пользовательские DNS-серверы для клиентов VPN, определите `VPN_DNS_SRV1` и при необходимости `VPN_DNS_SRV2`. Подробности смотрите в разделе [Использование альтернативных DNS-серверов](#использование-альтернативных-dns-серверов).
После этого запустите вспомогательный скрипт IKEv2, чтобы настроить IKEv2 в интерактивном режиме с пользовательскими параметрами:
```bash
sudo ikev2.sh
```
Вы можете настроить следующие параметры: DNS-имя VPN-сервера, имя и срок действия первого клиента, DNS-сервер для VPN-клиентов и необходимость защиты файлов конфигурации клиента паролем.
**Примечание:** Переменная `VPN_SKIP_IKEV2` не действует, если IKEv2 уже настроен на сервере. В этом случае для настройки параметров IKEv2 вы можете сначала [удалить IKEv2](docs/ikev2-howto.md#remove-ikev2), а затем снова настроить его с помощью `sudo ikev2.sh`.
Вариант 2: Настройка параметров IKEv2 с помощью переменных окружения.
При установке VPN вы можете при желании указать DNS-имя для адреса сервера IKEv2. DNS-имя должно быть полным доменным именем (FQDN). Пример:
```bash
sudo VPN_DNS_NAME='vpn.example.com' sh vpn.sh
```
Аналогично вы можете указать имя для первого клиента IKEv2. По умолчанию используется `vpnclient`, если имя не указано.
```bash
sudo VPN_CLIENT_NAME='your_client_name' sh vpn.sh
```
По умолчанию клиенты используют [Google Public DNS](https://developers.google.com/speed/public-dns/) при активном VPN. Вы можете указать собственные DNS-серверы для всех режимов VPN. Пример:
```bash
sudo VPN_DNS_SRV1=1.1.1.1 VPN_DNS_SRV2=1.0.0.1 sh vpn.sh
```
По умолчанию пароль не требуется при импорте конфигурации клиента IKEv2. Вы можете защитить файлы конфигурации клиента случайным паролем.
```bash
sudo VPN_PROTECT_CONFIG=yes sh vpn.sh
```
Для справки: список параметров IKEv1 и IKEv2.
| Параметр IKEv1\* | Значение по умолчанию | Настройка (переменная окружения)\*\* |
| --------------------------- | --------------------- | ------------------------------------ |
| Адрес сервера (DNS-имя) | - | Нет, но можно подключаться по DNS-имени |
| Адрес сервера (публичный IP)| Автоопределение | VPN_PUBLIC_IP |
| Предварительно общий ключ IPsec | Автоматическая генерация | VPN_IPSEC_PSK |
| Имя пользователя VPN | vpnuser | VPN_USER |
| Пароль VPN | Автоматическая генерация | VPN_PASSWORD |
| DNS-серверы для клиентов | Google Public DNS | VPN_DNS_SRV1, VPN_DNS_SRV2 |
| Пропустить настройку IKEv2 | no | VPN_SKIP_IKEV2=yes |
\* Эти параметры IKEv1 используются для режимов IPsec/L2TP и IPsec/XAuth («Cisco IPsec»).
\*\* Определяются как переменные окружения при запуске vpn(setup).sh.
| Параметр IKEv2\* | Значение по умолчанию | Настройка (переменная окружения)\*\* | Настройка (интерактивно)\*\*\* |
| --------------------------- | --------------------- | ------------------------------------ | ------------------------------- |
| Адрес сервера (DNS-имя) | - | VPN_DNS_NAME | ✅ |
| Адрес сервера (публичный IP)| Автоопределение | VPN_PUBLIC_IP | ✅ |
| Имя первого клиента | vpnclient | VPN_CLIENT_NAME | ✅ |
| DNS-серверы для клиентов | Google Public DNS | VPN_DNS_SRV1, VPN_DNS_SRV2 | ✅ |
| Защита файлов конфигурации клиента | no | VPN_PROTECT_CONFIG=yes | ✅ |
| Включить/отключить MOBIKE | Включено, если поддерживается | ❌ | ✅ |
| Срок действия сертификата клиента | 10 лет (120 месяцев) | VPN_CLIENT_VALIDITY\*\*\*\* | ✅ |
| Срок действия сертификатов CA и сервера | 10 лет (120 месяцев) | ❌ | ❌ |
| Имя сертификата CA | IKEv2 VPN CA | ❌ | ❌ |
| Размер ключа сертификата | 3072 бита | ❌ | ❌ |
\* Эти параметры IKEv2 используются для режима IKEv2.
\*\* Определяются как переменные окружения при запуске vpn(setup).sh или при автоматической настройке IKEv2 (`sudo ikev2.sh --auto`).
\*\*\* Можно настроить во время интерактивной настройки IKEv2 (`sudo ikev2.sh`). См. вариант 1 выше.
\*\*\*\* Используйте `VPN_CLIENT_VALIDITY`, чтобы указать срок действия сертификата клиента в месяцах. Значение должно быть целым числом от 1 до 120.
Помимо этих параметров, продвинутые пользователи также могут [настроить подсети VPN](docs/advanced-usage.md#customize-vpn-subnets) во время настройки VPN.
## Следующие шаги
*Прочитать на других языках: [English](README.md#next-steps), [简体中文](README-zh.md#下一步), [繁體中文](README-zh-Hant.md#下一步), [日本語](README-ja.md#次のステップ), [Русский](README-ru.md#следующие-шаги).*
Настройте ваш компьютер или устройство для использования VPN. Пожалуйста, обратитесь к следующим инструкциям (на английском языке):
**[Настройка клиентов IKEv2 VPN (рекомендуется)](docs/ikev2-howto.md)**
**[Настройка клиентов IPsec/L2TP VPN](docs/clients.md)**
**[Настройка клиентов IPsec/XAuth («Cisco IPsec»)](docs/clients-xauth.md)**
**Прочитайте [:book: книгу о VPN](docs/vpn-book.md), чтобы получить доступ к [дополнительному контенту](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-O5O7FVF8J).**
Наслаждайтесь собственным VPN! :sparkles::tada::rocket::sparkles:
## Важные замечания
**Пользователи Windows**: для режима IPsec/L2TP требуется [одноразовое изменение реестра](docs/clients.md#windows-error-809), если VPN-сервер или клиент находится за NAT (например, домашним роутером).
Одна и та же учетная запись VPN может использоваться на нескольких ваших устройствах. Однако из-за ограничения IPsec/L2TP, если вы хотите подключить несколько устройств из-за одного NAT (например, домашнего роутера), необходимо использовать режим [IKEv2](docs/ikev2-howto.md) или [IPsec/XAuth](docs/clients-xauth.md). Чтобы просмотреть или изменить учетные записи пользователей VPN, см. [Управление пользователями VPN](docs/manage-users.md).
Для серверов с внешним файрволом (например, [EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)/[GCE](https://cloud.google.com/vpc/docs/firewalls)) откройте UDP-порты 500 и 4500 для VPN. Пользователям Aliyun см. [#433](https://github.com/hwdsl2/setup-ipsec-vpn/issues/433).
Клиенты настроены использовать [Google Public DNS](https://developers.google.com/speed/public-dns/) при активном VPN. Если вы предпочитаете другого DNS-провайдера, см. [Расширенное использование](docs/advanced-usage.md).
Использование поддержки ядра может повысить производительность IPsec/L2TP. Она доступна на [всех поддерживаемых ОС](#требования). Пользователям Ubuntu следует установить пакет `linux-modules-extra-$(uname -r)` и выполнить `service xl2tpd restart`.
Скрипты создадут резервные копии существующих файлов конфигурации перед внесением изменений, с суффиксом `.old-date-time`.
## Обновление Libreswan
Используйте эту однострочную команду для обновления [Libreswan](https://libreswan.org) ([список изменений](https://github.com/libreswan/libreswan/blob/main/CHANGES) | [объявления](https://lists.libreswan.org)) на вашем VPN-сервере.
```bash
wget https://get.vpnsetup.net/upg -O vpnup.sh && sudo sh vpnup.sh
```
Нажмите здесь, если не удаётся скачать.
Вы также можете использовать `curl` для загрузки:
```bash
curl -fsSL https://get.vpnsetup.net/upg -o vpnup.sh && sudo sh vpnup.sh
```
Альтернативные URL для обновления:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/extras/vpnupgrade.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras/vpnupgrade.sh
```
Если вы не можете скачать файл, откройте [vpnupgrade.sh](extras/vpnupgrade.sh), затем нажмите кнопку `Raw` справа. Нажмите `Ctrl/Cmd+A`, чтобы выделить всё, `Ctrl/Cmd+C`, чтобы скопировать, затем вставьте в ваш любимый редактор.
Последняя поддерживаемая версия Libreswan — `5.3`. Проверить установленную версию: `ipsec --version`.
**Примечание:** `xl2tpd` можно обновить с помощью менеджера пакетов вашей системы, например `apt-get` в Ubuntu/Debian.
## Управление пользователями VPN
См. [Управление пользователями VPN](docs/manage-users.md) (на английском языке).
- [Управление пользователями VPN с помощью вспомогательных скриптов](docs/manage-users.md#manage-vpn-users-using-helper-scripts)
- [Просмотр пользователей VPN](docs/manage-users.md#view-vpn-users)
- [Просмотр или обновление IPsec PSK](docs/manage-users.md#view-or-update-the-ipsec-psk)
- [Ручное управление пользователями VPN](docs/manage-users.md#manually-manage-vpn-users)
## Расширенное использование
См. [Расширенное использование](docs/advanced-usage.md) (на английском языке).
- [Использование альтернативных DNS-серверов](docs/advanced-usage.md#use-alternative-dns-servers)
- [Изменения DNS-имени и IP-адреса сервера](docs/advanced-usage.md#dns-name-and-server-ip-changes)
- [VPN только с IKEv2](docs/advanced-usage.md#ikev2-only-vpn)
- [Внутренние IP-адреса VPN и трафик](docs/advanced-usage.md#internal-vpn-ips-and-traffic)
- [Указание публичного IP-адреса VPN-сервера](docs/advanced-usage.md#specify-vpn-servers-public-ip)
- [Настройка подсетей VPN](docs/advanced-usage.md#customize-vpn-subnets)
- [Поддержка IPv6](docs/advanced-usage.md#ipv6-support)
- [Переадресация портов клиентам VPN](docs/advanced-usage.md#port-forwarding-to-vpn-clients)
- [Раздельная маршрутизация (Split tunneling)](docs/advanced-usage.md#split-tunneling)
- [Доступ к подсети VPN-сервера](docs/advanced-usage.md#access-vpn-servers-subnet)
- [Доступ к клиентам VPN из подсети сервера](docs/advanced-usage.md#access-vpn-clients-from-servers-subnet)
- [Изменение правил IPTables](docs/advanced-usage.md#modify-iptables-rules)
- [Развёртывание алгоритма управления перегрузкой Google BBR](docs/advanced-usage.md#deploy-google-bbr-congestion-control)
## Удаление VPN
Чтобы удалить IPsec VPN, запустите [вспомогательный скрипт](extras/vpnuninstall.sh):
**Предупреждение:** Этот вспомогательный скрипт удалит IPsec VPN с вашего сервера. Вся конфигурация VPN будет **безвозвратно удалена**, а Libreswan и xl2tpd будут удалены. Это **нельзя отменить**!
```bash
wget https://get.vpnsetup.net/unst -O unst.sh && sudo bash unst.sh
```
Нажмите здесь, если не удаётся скачать.
Вы также можете использовать `curl` для загрузки:
```bash
curl -fsSL https://get.vpnsetup.net/unst -o unst.sh && sudo bash unst.sh
```
Альтернативные URL скрипта:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/extras/vpnuninstall.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras/vpnuninstall.sh
```
Для получения дополнительной информации см. [Удаление VPN](docs/uninstall.md).
## Обратная связь и вопросы
- Есть предложение по улучшению этого проекта? Создайте [Предложить улучшение](https://github.com/hwdsl2/setup-ipsec-vpn/issues/new/choose). [Pull request](https://github.com/hwdsl2/setup-ipsec-vpn/pulls) также приветствуются.
- Если вы нашли воспроизводимую ошибку, создайте отчёт об ошибке для [IPsec VPN](https://github.com/libreswan/libreswan/issues?q=is%3Aissue) или для [скрипты VPN](https://github.com/hwdsl2/setup-ipsec-vpn/issues/new/choose).
- Есть вопрос? Пожалуйста, сначала выполните поиск по [существующим issues](https://github.com/hwdsl2/setup-ipsec-vpn/issues?q=is%3Aissue) и комментариям [в этом Gist](https://gist.github.com/hwdsl2/9030462#comments) и [в моём блоге](https://blog.ls20.com/ipsec-l2tp-vpn-auto-setup-for-ubuntu-12-04-on-amazon-ec2/#disqus_thread).
- Задавайте вопросы, связанные с VPN, в списках рассылки [Libreswan](https://lists.libreswan.org) или [strongSwan](https://lists.strongswan.org), либо прочитайте эти вики: [[1]](https://libreswan.org/wiki/Main_Page) [[2]](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/sec-securing_virtual_private_networks) [[3]](https://wiki.strongswan.org/projects/strongswan/wiki/UserDocumentation) [[4]](https://wiki.gentoo.org/wiki/IPsec_L2TP_VPN_server) [[5]](https://wiki.archlinux.org/index.php/Openswan_L2TP/IPsec_VPN_client_setup).
## Лицензия
Copyright (C) 2014-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
Основано на [работе Thomas Sarlandie](https://github.com/sarfata/voodooprivacy) (Copyright 2012)
[](http://creativecommons.org/licenses/by-sa/3.0/)
Эта работа распространяется по лицензии [Creative Commons Attribution-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/)
Требуется указание авторства: пожалуйста, указывайте моё имя в любых производных работах и сообщайте мне, как вы её улучшили!
================================================
FILE: README-zh-Hant.md
================================================
[English](README.md) | [简体中文](README-zh.md) | [繁體中文](README-zh-Hant.md) | [日本語](README-ja.md) | [Русский](README-ru.md)
# IPsec VPN 伺服器一鍵安裝腳本
[](https://github.com/hwdsl2/setup-ipsec-vpn/actions/workflows/main.yml) [](https://github.com/hwdsl2/setup-ipsec-vpn/stargazers) [](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh-Hant.md) [](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh-Hant.md)
使用 Linux 腳本一鍵快速架設自己的 IPsec VPN 伺服器。支援 IPsec/L2TP、Cisco IPsec 和 IKEv2 協議。
IPsec VPN 可以加密你的網路流量,以防止在透過網際網路傳送時,你和 VPN 伺服器之間的任何人對你的資料進行未經授權的存取。在使用不安全的網路時,這一點特別有用,例如在咖啡廳、機場或旅館房間。
我們將使用 [Libreswan](https://libreswan.org/) 作為 IPsec 伺服器,以及 [xl2tpd](https://github.com/xelerance/xl2tpd) 作為 L2TP 提供者。
**[» :book: Book: Privacy Tools in the Age of AI](docs/vpn-book-zh-Hant.md) [架設自己的 VPN 伺服器](docs/vpn-book-zh-Hant.md)**
## 快速開始
首先,在你的 Linux 伺服器\* 上安裝 Ubuntu、Debian 或 CentOS。
使用以下命令快速架設 IPsec VPN 伺服器:
```bash
wget https://get.vpnsetup.net -O vpn.sh && sudo sh vpn.sh
```
你的 VPN 登入憑證將會自動隨機生成,並在安裝完成後顯示。
**可選:** 在同一台伺服器上安裝 [WireGuard](https://github.com/hwdsl2/wireguard-install/blob/master/README-zh-Hant.md) 和/或 [OpenVPN](https://github.com/hwdsl2/openvpn-install/blob/master/README-zh-Hant.md)。
查看腳本的範例輸出(終端記錄)。
**註:** 此終端記錄僅用於示範目的。該記錄中的 VPN 憑據 **無效**。

如果無法下載,請點這裡。
你也可以使用 `curl` 下載:
```bash
curl -fsSL https://get.vpnsetup.net -o vpn.sh && sudo sh vpn.sh
```
或者,你也可以使用這些連結:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/vpnsetup.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/vpnsetup.sh
```
如果無法下載,打開 [vpnsetup.sh](vpnsetup.sh),然後點擊右側的 `Raw` 按鈕。按快捷鍵 `Ctrl/Cmd+A` 全選,`Ctrl/Cmd+C` 複製,然後貼上到你喜歡的編輯器。
另外,你也可以使用預先建構的 [Docker 映像](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh-Hant.md)。如需了解其他選項以及客戶端設定,請繼續閱讀以下部分。
\* 一個雲端伺服器、虛擬專用伺服器 (VPS) 或專用伺服器。
## 功能特性
- 全自動的 IPsec VPN 伺服器設定,無需使用者輸入
- 支援具有強大且快速加密演算法(例如 AES-GCM)的 IKEv2 模式
- 生成 VPN 設定檔以自動設定 iOS、macOS 和 Android 裝置
- 支援 Windows、macOS、iOS、Android、Chrome OS 和 Linux 客戶端
- 包含輔助腳本以管理 VPN 使用者和憑證
## 系統需求
一個雲端伺服器、虛擬專用伺服器 (VPS) 或專用伺服器,安裝以下作業系統之一:
- Ubuntu 24.04 或 22.04
- Debian 13、12 或 11
- CentOS Stream 10 或 9
- Rocky Linux 或 AlmaLinux
- Oracle Linux
- Amazon Linux 2
其他受支援的 Linux 發行版。
- Raspberry Pi OS (Raspbian)
- Kali Linux
- Alpine Linux
- Red Hat Enterprise Linux (RHEL)
這也包括公共雲服務中的 Linux 虛擬機,例如 [DigitalOcean](https://blog.ls20.com/digitalocean)、[Vultr](https://blog.ls20.com/vultr)、[Linode](https://blog.ls20.com/linode)、[OVH](https://www.ovhcloud.com/en/vps/) 和 [Microsoft Azure](https://azure.microsoft.com)。公共雲使用者也可以使用[使用者資料](https://blog.ls20.com/ipsec-l2tp-vpn-auto-setup-for-ubuntu-12-04-on-amazon-ec2/#vpnsetup)部署。
使用以下按鈕快速部署:
[](https://cloud.linode.com/stackscripts/37239) [](aws/README-zh.md) [](azure/README-zh.md)
[**» 我想建立並使用自己的 VPN,但沒有可用的伺服器**](https://blog.ls20.com/ipsec-l2tp-vpn-auto-setup-for-ubuntu-12-04-on-amazon-ec2/#gettingavps)
對於有外部防火牆的伺服器(例如 [EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)/[GCE](https://cloud.google.com/vpc/docs/firewalls)),請為 VPN 開啟 UDP 連接埠 500 和 4500。
另外,你也可以使用預先建構的 [Docker 映像](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh-Hant.md)。進階使用者可以在 [Raspberry Pi](https://www.raspberrypi.com) 上安裝。[[1]](https://elasticbyte.net/posts/setting-up-a-native-cisco-ipsec-vpn-server-using-a-raspberry-pi/) [[2]](https://www.stewright.me/2018/07/create-a-raspberry-pi-vpn-server-using-l2tpipsec/)
:warning: **不要** 在你的 PC 或 Mac 上執行這些腳本!它們只能用在伺服器上!
## 安裝說明
首先,更新你的伺服器:執行 `sudo apt-get update && sudo apt-get dist-upgrade` (Ubuntu/Debian) 或 `sudo yum update` 並重新啟動。此步驟為可選,但建議執行。
要安裝 VPN,請從以下選項中選擇一個:
**選項 1:** 使用腳本隨機生成的 VPN 登入憑證(完成後會顯示)。
```bash
wget https://get.vpnsetup.net -O vpn.sh && sudo sh vpn.sh
```
**選項 2:** 編輯腳本並提供你自己的 VPN 登入憑證。
```bash
wget https://get.vpnsetup.net -O vpn.sh
nano -w vpn.sh
[替換為你自己的值: YOUR_IPSEC_PSK, YOUR_USERNAME 和 YOUR_PASSWORD]
sudo sh vpn.sh
```
**註:** 一個安全的 IPsec PSK 應至少包含 20 個隨機字元。
**選項 3:** 將你自己的 VPN 登入憑證定義為環境變數。
```bash
# 所有變數值必須用 '單引號' 括起來
# *不要* 在值中使用這些字元: \ " '
wget https://get.vpnsetup.net -O vpn.sh
sudo VPN_IPSEC_PSK='你的IPsec預共享金鑰' \
VPN_USER='你的VPN使用者名稱' \
VPN_PASSWORD='你的VPN密碼' \
sh vpn.sh
```
你可以選擇在同一台伺服器上安裝 [WireGuard](https://github.com/hwdsl2/wireguard-install/blob/master/README-zh-Hant.md) 和/或 [OpenVPN](https://github.com/hwdsl2/openvpn-install/blob/master/README-zh-Hant.md)。如果你的伺服器執行 CentOS Stream、Rocky Linux 或 AlmaLinux,請先安裝 OpenVPN/WireGuard,然後再安裝 IPsec VPN。
如果無法下載,請點這裡。
你也可以使用 `curl` 下載。例如:
```bash
curl -fL https://get.vpnsetup.net -o vpn.sh
sudo sh vpn.sh
```
或者,你也可以使用這些連結:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/vpnsetup.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/vpnsetup.sh
```
如果無法下載,打開 [vpnsetup.sh](vpnsetup.sh),然後點擊右側的 `Raw` 按鈕。按快捷鍵 `Ctrl/Cmd+A` 全選,`Ctrl/Cmd+C` 複製,然後貼上到你喜歡的編輯器。
我需要安裝較舊版本的 Libreswan 版本 4。
一般建議使用最新的 [Libreswan](https://libreswan.org/) 版本 5,它是本專案的預設版本。不過,如果你想要安裝較舊版本的 Libreswan 版本 4:
```bash
wget https://get.vpnsetup.net -O vpn.sh
sudo VPN_SWAN_VER=4.15 sh vpn.sh
```
**註:** 如果 Libreswan 版本 5 已經安裝,你可能需要先[解除安裝 VPN](docs/uninstall-zh.md),然後再安裝 Libreswan 版本 4。或者,你也可以下載[升級腳本](#升級libreswan),編輯它並指定 `SWAN_VER=4.15`,然後執行腳本。
## 自訂 VPN 選項
### 使用其他 DNS 伺服器
在 VPN 已連線時,客戶端預設設定為使用 [Google Public DNS](https://developers.google.com/speed/public-dns/)。在安裝 VPN 時,你可以為所有 VPN 模式指定其他 DNS 伺服器。此為可選設定。示例如下:
```bash
sudo VPN_DNS_SRV1=1.1.1.1 VPN_DNS_SRV2=1.0.0.1 sh vpn.sh
```
使用 `VPN_DNS_SRV1` 指定主要 DNS 伺服器,使用 `VPN_DNS_SRV2` 指定次要 DNS 伺服器(可選)。
以下是一些常見的公共 DNS 提供商列表,供你參考。
| 提供商 | 主 DNS | 輔助 DNS | 註解 |
| ----- | ------ | ------- | ---- |
| [Google Public DNS](https://developers.google.com/speed/public-dns) | 8.8.8.8 | 8.8.4.4 | 本專案預設 |
| [Cloudflare](https://1.1.1.1/dns/) | 1.1.1.1 | 1.0.0.1 | 另見:[Cloudflare for families](https://1.1.1.1/family/) |
| [Quad9](https://www.quad9.net) | 9.9.9.9 | 149.112.112.112 | 阻擋惡意網域 |
| [OpenDNS](https://www.opendns.com/home-internet-security/) | 208.67.222.222 | 208.67.220.220 | 阻擋網路釣魚網域,可設定。 |
| [CleanBrowsing](https://cleanbrowsing.org/filters/) | 185.228.168.9 | 185.228.169.9 | 提供[網域過濾器](https://cleanbrowsing.org/filters/) |
| [NextDNS](https://nextdns.io/?from=bg25bwmp) | 依需求選擇 | 依需求選擇 | 廣告攔截,提供免費方案。[了解更多](https://nextdns.io/?from=bg25bwmp)。 |
| [Control D](https://controld.com/free-dns) | 依需求選擇 | 依需求選擇 | 廣告攔截,可自訂設定。[了解更多](https://controld.com/free-dns)。 |
如果你需要在安裝 VPN 之後更改 DNS 伺服器,請參見[進階用法](docs/advanced-usage-zh.md)。
**註:** 如果伺服器上已經設定 IKEv2,以上變數對 IKEv2 模式無效。在此情況下,如需自訂 IKEv2 選項(例如 DNS 伺服器),你可以先[移除 IKEv2](docs/ikev2-howto-zh.md#移除-ikev2),然後執行 `sudo ikev2.sh` 重新設定。
### 自訂 IKEv2 選項
在安裝 VPN 時,進階使用者可以自訂 IKEv2 選項。此為可選設定。
選項 1:在安裝 VPN 時跳過 IKEv2,然後使用自訂選項設定 IKEv2。
在安裝 VPN 時,你可以跳過 IKEv2,只安裝 IPsec/L2TP 和 IPsec/XAuth("Cisco IPsec")模式:
```bash
sudo VPN_SKIP_IKEV2=yes sh vpn.sh
```
(可選)如果要為 VPN 客戶端指定其他 DNS 伺服器,你可以定義 `VPN_DNS_SRV1` 和 `VPN_DNS_SRV2`(可選)。更多資訊請參見[使用其他 DNS 伺服器](#使用其他-dns-伺服器)。
然後執行 IKEv2 輔助腳本,以互動方式使用自訂選項設定 IKEv2:
```bash
sudo ikev2.sh
```
你可以自訂以下選項:VPN 伺服器的網域名稱、第一個客戶端的名稱與憑證有效期限、VPN 客戶端的 DNS 伺服器,以及是否對客戶端設定檔進行密碼保護。
**註:** 如果伺服器上已經設定 IKEv2,則 `VPN_SKIP_IKEV2` 變數無效。在此情況下,如需自訂 IKEv2 選項,你可以先[移除 IKEv2](docs/ikev2-howto-zh.md#移除-ikev2),然後執行 `sudo ikev2.sh` 重新設定。
選項 2:使用環境變數自訂 IKEv2 選項。
在安裝 VPN 時,你可以指定一個網域名稱作為 IKEv2 伺服器位址。此為可選設定。該網域名稱必須是完整網域名稱 (FQDN)。示例如下:
```bash
sudo VPN_DNS_NAME='vpn.example.com' sh vpn.sh
```
同樣地,你也可以指定第一個 IKEv2 客戶端的名稱。如果未指定,則使用預設值 `vpnclient`。
```bash
sudo VPN_CLIENT_NAME='your_client_name' sh vpn.sh
```
在 VPN 已連線時,客戶端預設設定為使用 [Google Public DNS](https://developers.google.com/speed/public-dns/)。你可以為所有 VPN 模式指定其他 DNS 伺服器。示例如下:
```bash
sudo VPN_DNS_SRV1=1.1.1.1 VPN_DNS_SRV2=1.0.0.1 sh vpn.sh
```
預設情況下,匯入 IKEv2 客戶端設定時不需要密碼。你可以選擇使用隨機密碼保護客戶端設定檔。
```bash
sudo VPN_PROTECT_CONFIG=yes sh vpn.sh
```
供參考:IKEv1 和 IKEv2 參數列表。
| IKEv1 參數\* |預設值 |自訂(環境變數)\*\* |
| ------------ | ---- | ----------------- |
|伺服器位址(DNS 網域名稱)| - |不能,但你可以使用 DNS 網域名稱進行連線 |
|伺服器位址(公網 IP)|自動偵測 | VPN_PUBLIC_IP |
| IPsec 預共享金鑰 |自動生成 | VPN_IPSEC_PSK |
| VPN 使用者名稱 | vpnuser | VPN_USER |
| VPN 密碼 |自動生成 | VPN_PASSWORD |
|客戶端的 DNS 伺服器 |Google Public DNS | VPN_DNS_SRV1, VPN_DNS_SRV2 |
|跳過 IKEv2 安裝 |no | VPN_SKIP_IKEV2=yes |
\* 這些 IKEv1 參數適用於 IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式。
\*\* 在執行 vpn(setup).sh 時將這些定義為環境變數。
| IKEv2 參數\* |預設值 |自訂(環境變數)\*\* |自訂(互動式)\*\*\* |
| ----------- | ---- | ------------------ | ----------------- |
|伺服器位址(DNS 網域名稱)| - | VPN_DNS_NAME | ✅ |
|伺服器位址(公網 IP)|自動偵測 | VPN_PUBLIC_IP | ✅ |
|第一個客戶端的名稱 | vpnclient | VPN_CLIENT_NAME | ✅ |
|客戶端的 DNS 伺服器 |Google Public DNS | VPN_DNS_SRV1, VPN_DNS_SRV2 | ✅ |
|保護客戶端設定檔 |no | VPN_PROTECT_CONFIG=yes | ✅ |
|啟用/停用 MOBIKE |如果系統支援則啟用 | ❌ | ✅ |
|客戶端憑證有效期限 | 10 年(120 個月)| VPN_CLIENT_VALIDITY\*\*\*\* | ✅ |
| CA 和伺服器憑證有效期限 | 10 年(120 個月)| ❌ | ❌ |
| CA 憑證名稱 | IKEv2 VPN CA | ❌ | ❌ |
|憑證金鑰長度 | 3072 bits | ❌ | ❌ |
\* 這些 IKEv2 參數適用於 IKEv2 模式。
\*\* 在執行 vpn(setup).sh 時,或在自動模式下設定 IKEv2 時 (`sudo ikev2.sh --auto`) 將這些定義為環境變數。
\*\*\* 可以在互動式設定 IKEv2 期間自訂 (`sudo ikev2.sh`)。參見上面的選項 1。
\*\*\*\* 使用 `VPN_CLIENT_VALIDITY` 定義客戶端憑證的有效期限(單位:月)。它必須是 1 到 120 之間的整數。
除了這些參數,高級使用者還可以在安裝時[自訂 VPN 子網](docs/advanced-usage-zh.md#自定义-vpn-子网)。
## 下一步
*其他語言版本: [English](README.md#next-steps), [简体中文](README-zh.md#下一步), [繁體中文](README-zh-Hant.md#下一步), [日本語](README-ja.md#次のステップ), [Русский](README-ru.md#следующие-шаги)。*
設定你的電腦或其他裝置使用 VPN。請參見以下連結(簡體中文):
**[設定 IKEv2 VPN 客戶端(推薦)](docs/ikev2-howto-zh.md)**
**[設定 IPsec/L2TP VPN 客戶端](docs/clients-zh.md)**
**[設定 IPsec/XAuth ("Cisco IPsec") VPN 客戶端](docs/clients-xauth-zh.md)**
**閱讀 [:book: VPN book](docs/vpn-book-zh-Hant.md) 以存取[額外內容](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-X8X5FVFZC)。**
開始使用自己的專屬 VPN! :sparkles::tada::rocket::sparkles:
## 重要提示
**Windows 使用者** 對於 IPsec/L2TP 模式,在首次連線之前需要[修改登錄檔](docs/clients-zh.md#windows-错误-809),以解決 VPN 伺服器或客戶端與 NAT(例如家用路由器)的相容問題。
同一個 VPN 帳戶可以在你的多個裝置上使用。但由於 IPsec/L2TP 的限制,如果需要連線到同一個 NAT(例如家用路由器)後面的多個裝置,你必須使用 [IKEv2](docs/ikev2-howto-zh.md) 或 [IPsec/XAuth](docs/clients-xauth-zh.md) 模式。要查看或變更 VPN 使用者帳戶,請參見[管理 VPN 使用者](docs/manage-users-zh.md)。
對於有外部防火牆的伺服器(例如 [EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)/[GCE](https://cloud.google.com/vpc/docs/firewalls)),請為 VPN 開啟 UDP 連接埠 500 和 4500。阿里雲使用者請參見 [#433](https://github.com/hwdsl2/setup-ipsec-vpn/issues/433)。
在 VPN 已連線時,客戶端設定為使用 [Google Public DNS](https://developers.google.com/speed/public-dns/)。如果偏好其他的網域解析服務,請參見[進階用法](docs/advanced-usage-zh.md)。
使用核心支援有助於提升 IPsec/L2TP 效能。它在所有[支援的系統](#系統需求)上可用。Ubuntu 系統需要安裝 `linux-modules-extra-$(uname -r)` 軟體套件並執行 `service xl2tpd restart`。
這些腳本在變更現有設定檔之前會先建立備份,並使用 `.old-日期-時間` 作為檔名後綴。
## 升級Libreswan
使用以下命令更新你的 VPN 伺服器上的 [Libreswan](https://libreswan.org)([更新日誌](https://github.com/libreswan/libreswan/blob/main/CHANGES) | [通知清單](https://lists.libreswan.org))。
```bash
wget https://get.vpnsetup.net/upg -O vpnup.sh && sudo sh vpnup.sh
```
如果無法下載,請點這裡。
你也可以使用 `curl` 下載:
```bash
curl -fsSL https://get.vpnsetup.net/upg -o vpnup.sh && sudo sh vpnup.sh
```
或者,你也可以使用這些連結:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/extras/vpnupgrade.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras/vpnupgrade.sh
```
如果無法下載,打開 [vpnupgrade.sh](extras/vpnupgrade.sh),然後點擊右側的 `Raw` 按鈕。按快捷鍵 `Ctrl/Cmd+A` 全選,`Ctrl/Cmd+C` 複製,然後貼上到你喜歡的編輯器。
目前支援的 Libreswan 最新版本是 `5.3`。查看已安裝版本:`ipsec --version`。
**註:** `xl2tpd` 可以使用系統的套件管理器進行更新,例如 Ubuntu/Debian 上的 `apt-get`。
## 管理 VPN 使用者
請參見[管理 VPN 使用者](docs/manage-users-zh.md)(簡體中文)。
- [使用輔助腳本管理 VPN 使用者](docs/manage-users-zh.md#使用辅助脚本管理-vpn-用户)
- [查看 VPN 使用者](docs/manage-users-zh.md#查看-vpn-用户)
- [查看或變更 IPsec PSK](docs/manage-users-zh.md#查看或更改-ipsec-psk)
- [手動管理 VPN 使用者](docs/manage-users-zh.md#手动管理-vpn-用户)
## 進階用法
請參見[進階用法](docs/advanced-usage-zh.md)(簡體中文)。
- [使用其他 DNS 伺服器](docs/advanced-usage-zh.md#使用其他的-dns-服务器)
- [網域名稱與變更伺服器 IP](docs/advanced-usage-zh.md#域名和更改服务器-ip)
- [僅限 IKEv2 的 VPN](docs/advanced-usage-zh.md#仅限-ikev2-的-vpn)
- [VPN 內網 IP 與流量](docs/advanced-usage-zh.md#vpn-内网-ip-和流量)
- [指定 VPN 伺服器的公有 IP](docs/advanced-usage-zh.md#指定-vpn-服务器的公有-ip)
- [自訂 VPN 子網](docs/advanced-usage-zh.md#自定义-vpn-子网)
- [IPv6 支援](docs/advanced-usage-zh.md#ipv6-支持)
- [轉發連接埠到 VPN 客戶端](docs/advanced-usage-zh.md#转发端口到-vpn-客户端)
- [VPN 分流](docs/advanced-usage-zh.md#vpn-分流)
- [存取 VPN 伺服器的網段](docs/advanced-usage-zh.md#访问-vpn-服务器的网段)
- [VPN 伺服器網段存取 VPN 客戶端](docs/advanced-usage-zh.md#vpn-服务器网段访问-vpn-客户端)
- [變更 IPTables 規則](docs/advanced-usage-zh.md#更改-iptables-规则)
- [部署 Google BBR 壅塞控制](docs/advanced-usage-zh.md#部署-google-bbr-拥塞控制)
## 移除 VPN
要移除 IPsec VPN,執行[輔助腳本](extras/vpnuninstall.sh):
**警告:** 此輔助腳本將從你的伺服器中刪除 IPsec VPN。所有 VPN 設定將被**永久刪除**,並且 Libreswan 和 xl2tpd 將被移除。此操作**無法復原**!
```bash
wget https://get.vpnsetup.net/unst -O unst.sh && sudo bash unst.sh
```
如果無法下載,請點這裡。
你也可以使用 `curl` 下載:
```bash
curl -fsSL https://get.vpnsetup.net/unst -o unst.sh && sudo bash unst.sh
```
或者,你也可以使用這些連結:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/extras/vpnuninstall.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras/vpnuninstall.sh
```
更多資訊請參見[移除 VPN](docs/uninstall-zh.md)。
## 問題與回饋
- 如果你對本專案有建議,請提交一個[改進建議](https://github.com/hwdsl2/setup-ipsec-vpn/issues/new/choose),或歡迎提交 [Pull request](https://github.com/hwdsl2/setup-ipsec-vpn/pulls)。
- 如果你發現可重現的程式漏洞,請為 [IPsec VPN](https://github.com/libreswan/libreswan/issues?q=is%3Aissue) 或 [VPN 腳本](https://github.com/hwdsl2/setup-ipsec-vpn/issues/new/choose)提交錯誤回報。
- 有問題想提問?請先搜尋[既有的 issues](https://github.com/hwdsl2/setup-ipsec-vpn/issues?q=is%3Aissue) 以及[這個 Gist](https://gist.github.com/hwdsl2/9030462#comments) 和[我的部落格](https://blog.ls20.com/ipsec-l2tp-vpn-auto-setup-for-ubuntu-12-04-on-amazon-ec2/#disqus_thread)上已有的留言。
- VPN 相關問題可在 [Libreswan](https://lists.libreswan.org) 或 [strongSwan](https://lists.strongswan.org) 郵件列表提問,或參考以下網站:[[1]](https://libreswan.org/wiki/Main_Page) [[2]](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/sec-securing_virtual_private_networks) [[3]](https://wiki.strongswan.org/projects/strongswan/wiki/UserDocumentation) [[4]](https://wiki.gentoo.org/wiki/IPsec_L2TP_VPN_server) [[5]](https://wiki.archlinux.org/index.php/Openswan_L2TP/IPsec_VPN_client_setup)。
## 授權條款
版權所有 (C) 2014-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
基於 [Thomas Sarlandie 的工作](https://github.com/sarfata/voodooprivacy)(版權所有 2012)
[](http://creativecommons.org/licenses/by-sa/3.0/)
此專案採用 [Creative Commons 姓名標示-相同方式分享 3.0](http://creativecommons.org/licenses/by-sa/3.0/) 授權條款。
必須署名:請在任何衍生作品中包含我的名字,並且讓我知道你是如何改進它的!
================================================
FILE: README-zh.md
================================================
[English](README.md) | [简体中文](README-zh.md) | [繁體中文](README-zh-Hant.md) | [日本語](README-ja.md) | [Русский](README-ru.md)
# IPsec VPN 服务器一键安装脚本
[](https://github.com/hwdsl2/setup-ipsec-vpn/actions/workflows/main.yml) [](https://github.com/hwdsl2/setup-ipsec-vpn/stargazers) [](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh.md) [](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh.md)
使用 Linux 脚本一键快速搭建自己的 IPsec VPN 服务器。支持 IPsec/L2TP, Cisco IPsec 和 IKEv2 协议。
IPsec VPN 可以加密你的网络流量,以防止在通过因特网传送时,你和 VPN 服务器之间的任何人对你的数据的未经授权的访问。在使用不安全的网络时,这是特别有用的,例如在咖啡厅,机场或旅馆房间。
我们将使用 [Libreswan](https://libreswan.org/) 作为 IPsec 服务器,以及 [xl2tpd](https://github.com/xelerance/xl2tpd) 作为 L2TP 提供者。
**[» :book: Book: Privacy Tools in the Age of AI](docs/vpn-book-zh.md) [搭建自己的 VPN 服务器](docs/vpn-book-zh.md)**
## 快速开始
首先,在你的 Linux 服务器\* 上安装 Ubuntu, Debian 或者 CentOS。
使用以下命令快速搭建 IPsec VPN 服务器:
```bash
wget https://get.vpnsetup.net -O vpn.sh && sudo sh vpn.sh
```
你的 VPN 登录凭证将会被自动随机生成,并在安装完成后显示。
**可选:** 在同一台服务器上安装 [WireGuard](https://github.com/hwdsl2/wireguard-install/blob/master/README-zh.md) 和/或 [OpenVPN](https://github.com/hwdsl2/openvpn-install/blob/master/README-zh.md)。
查看脚本的示例输出(终端记录)。
**注:** 此终端记录仅用于演示目的。该记录中的 VPN 凭据 **无效**。

如果无法下载,请点这里。
你也可以使用 `curl` 下载:
```bash
curl -fsSL https://get.vpnsetup.net -o vpn.sh && sudo sh vpn.sh
```
或者,你也可以使用这些链接:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/vpnsetup.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/vpnsetup.sh
```
如果无法下载,打开 [vpnsetup.sh](vpnsetup.sh),然后点击右边的 `Raw` 按钮。按快捷键 `Ctrl/Cmd+A` 全选,`Ctrl/Cmd+C` 复制,然后粘贴到你喜欢的编辑器。
另外,你也可以使用预构建的 [Docker 镜像](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh.md)。如需了解其它选项以及客户端配置,请继续阅读以下部分。
\* 一个云服务器,虚拟专用服务器 (VPS) 或者专用服务器。
## 功能特性
- 全自动的 IPsec VPN 服务器配置,无需用户输入
- 支持具有强大和快速加密算法(例如 AES-GCM)的 IKEv2 模式
- 生成 VPN 配置文件以自动配置 iOS, macOS 和 Android 设备
- 支持 Windows, macOS, iOS, Android, Chrome OS 和 Linux 客户端
- 包括辅助脚本以管理 VPN 用户和证书
## 系统要求
一个云服务器,虚拟专用服务器 (VPS) 或者专用服务器,安装以下操作系统之一:
- Ubuntu 24.04 或者 22.04
- Debian 13、12 或者 11
- CentOS Stream 10 或者 9
- Rocky Linux 或者 AlmaLinux
- Oracle Linux
- Amazon Linux 2
其他受支持的 Linux 发行版。
- Raspberry Pi OS (Raspbian)
- Kali Linux
- Alpine Linux
- Red Hat Enterprise Linux (RHEL)
这也包括公共云服务中的 Linux 虚拟机,例如 [DigitalOcean](https://blog.ls20.com/digitalocean), [Vultr](https://blog.ls20.com/vultr), [Linode](https://blog.ls20.com/linode), [OVH](https://www.ovhcloud.com/en/vps/) 和 [Microsoft Azure](https://azure.microsoft.com)。公共云用户也可以使用[用户数据](https://blog.ls20.com/ipsec-l2tp-vpn-auto-setup-for-ubuntu-12-04-on-amazon-ec2/#vpnsetup)部署。
使用以下按钮快速部署:
[](https://cloud.linode.com/stackscripts/37239) [](aws/README-zh.md) [](azure/README-zh.md)
[**» 我想建立并使用自己的 VPN,但是没有可用的服务器**](https://blog.ls20.com/ipsec-l2tp-vpn-auto-setup-for-ubuntu-12-04-on-amazon-ec2/#gettingavps)
对于有外部防火墙的服务器(比如 [EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)/[GCE](https://cloud.google.com/vpc/docs/firewalls)),请为 VPN 打开 UDP 端口 500 和 4500。
另外,你也可以使用预构建的 [Docker 镜像](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh.md)。高级用户可以在 [Raspberry Pi](https://www.raspberrypi.com) 上安装。[[1]](https://elasticbyte.net/posts/setting-up-a-native-cisco-ipsec-vpn-server-using-a-raspberry-pi/) [[2]](https://www.stewright.me/2018/07/create-a-raspberry-pi-vpn-server-using-l2tpipsec/)
:warning: **不要** 在你的 PC 或者 Mac 上运行这些脚本!它们只能用在服务器上!
## 安装说明
首先,更新你的服务器:运行 `sudo apt-get update && sudo apt-get dist-upgrade` (Ubuntu/Debian) 或者 `sudo yum update` 并重启。这一步是可选的,但推荐。
要安装 VPN,请从以下选项中选择一个:
**选项 1:** 使用脚本随机生成的 VPN 登录凭证(完成后会显示)。
```bash
wget https://get.vpnsetup.net -O vpn.sh && sudo sh vpn.sh
```
**选项 2:** 编辑脚本并提供你自己的 VPN 登录凭证。
```bash
wget https://get.vpnsetup.net -O vpn.sh
nano -w vpn.sh
[替换为你自己的值: YOUR_IPSEC_PSK, YOUR_USERNAME 和 YOUR_PASSWORD]
sudo sh vpn.sh
```
**注:** 一个安全的 IPsec PSK 应该至少包含 20 个随机字符。
**选项 3:** 将你自己的 VPN 登录凭证定义为环境变量。
```bash
# 所有变量值必须用 '单引号' 括起来
# *不要* 在值中使用这些字符: \ " '
wget https://get.vpnsetup.net -O vpn.sh
sudo VPN_IPSEC_PSK='你的IPsec预共享密钥' \
VPN_USER='你的VPN用户名' \
VPN_PASSWORD='你的VPN密码' \
sh vpn.sh
```
你可以选择在同一台服务器上安装 [WireGuard](https://github.com/hwdsl2/wireguard-install/blob/master/README-zh.md) 和/或 [OpenVPN](https://github.com/hwdsl2/openvpn-install/blob/master/README-zh.md)。如果你的服务器运行 CentOS Stream, Rocky Linux 或 AlmaLinux,请先安装 OpenVPN/WireGuard,然后安装 IPsec VPN。
如果无法下载,请点这里。
你也可以使用 `curl` 下载。例如:
```bash
curl -fL https://get.vpnsetup.net -o vpn.sh
sudo sh vpn.sh
```
或者,你也可以使用这些链接:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/vpnsetup.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/vpnsetup.sh
```
如果无法下载,打开 [vpnsetup.sh](vpnsetup.sh),然后点击右边的 `Raw` 按钮。按快捷键 `Ctrl/Cmd+A` 全选,`Ctrl/Cmd+C` 复制,然后粘贴到你喜欢的编辑器。
我需要安装较旧版本的 Libreswan 版本 4。
一般建议使用最新的 [Libreswan](https://libreswan.org/) 版本 5,它是本项目的默认版本。但是,如果你想要安装较旧版本的 Libreswan 版本 4:
```bash
wget https://get.vpnsetup.net -O vpn.sh
sudo VPN_SWAN_VER=4.15 sh vpn.sh
```
**注:** 如果 Libreswan 版本 5 已经安装,你可能需要首先[卸载 VPN](docs/uninstall-zh.md),然后安装 Libreswan 版本 4。或者,你也可以下载[升级脚本](#升级libreswan),编辑它并指定 `SWAN_VER=4.15`,然后运行脚本。
## 自定义 VPN 选项
### 使用其他的 DNS 服务器
在 VPN 已连接时,客户端默认配置为使用 [Google Public DNS](https://developers.google.com/speed/public-dns/)。在安装 VPN 时,你可以为所有的 VPN 模式指定另外的 DNS 服务器。这是可选的。示例如下:
```bash
sudo VPN_DNS_SRV1=1.1.1.1 VPN_DNS_SRV2=1.0.0.1 sh vpn.sh
```
使用 `VPN_DNS_SRV1` 指定主 DNS 服务器,使用 `VPN_DNS_SRV2` 指定辅助 DNS 服务器(可选)。
以下是一些流行的公共 DNS 提供商的列表,供你参考。
| 提供商 | 主 DNS | 辅助 DNS | 注释 |
| ----- | ------ | ------- | ---- |
| [Google Public DNS](https://developers.google.com/speed/public-dns) | 8.8.8.8 | 8.8.4.4 | 本项目默认 |
| [Cloudflare](https://1.1.1.1/dns/) | 1.1.1.1 | 1.0.0.1 | 另见:[Cloudflare for families](https://1.1.1.1/family/) |
| [Quad9](https://www.quad9.net) | 9.9.9.9 | 149.112.112.112 | 阻止恶意域 |
| [OpenDNS](https://www.opendns.com/home-internet-security/) | 208.67.222.222 | 208.67.220.220 | 阻止网络钓鱼域,可配置。 |
| [CleanBrowsing](https://cleanbrowsing.org/filters/) | 185.228.168.9 | 185.228.169.9 | [域过滤器](https://cleanbrowsing.org/filters/)可用 |
| [NextDNS](https://nextdns.io/?from=bg25bwmp) | 按需选择 | 按需选择 | 广告拦截,免费套餐可用。[了解更多](https://nextdns.io/?from=bg25bwmp)。 |
| [Control D](https://controld.com/free-dns) | 按需选择 | 按需选择 | 广告拦截,可配置。[了解更多](https://controld.com/free-dns)。 |
如果你需要在安装 VPN 之后更改 DNS 服务器,参见[高级用法](docs/advanced-usage-zh.md)。
**注:** 如果服务器上已经配置了 IKEv2,则以上变量对 IKEv2 模式无效。在这种情况下,如需自定义 IKEv2 选项(例如 DNS 服务器),你可以首先[移除 IKEv2](docs/ikev2-howto-zh.md#移除-ikev2),然后运行 `sudo ikev2.sh` 重新配置。
### 自定义 IKEv2 选项
在安装 VPN 时,高级用户可以自定义 IKEv2 选项。这是可选的。
选项 1: 在安装 VPN 时跳过 IKEv2,然后使用自定义选项配置 IKEv2。
在安装 VPN 时,你可以跳过 IKEv2,仅安装 IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式:
```bash
sudo VPN_SKIP_IKEV2=yes sh vpn.sh
```
(可选)如需为 VPN 客户端指定另外的 DNS 服务器,你可以定义 `VPN_DNS_SRV1` 和 `VPN_DNS_SRV2`(可选)。有关详细信息,参见[使用其他的 DNS 服务器](#使用其他的-dns-服务器)。
然后运行 IKEv2 辅助脚本以使用自定义选项以交互方式配置 IKEv2:
```bash
sudo ikev2.sh
```
你可以自定义以下选项:VPN 服务器的域名,第一个客户端的名称和证书有效期,VPN 客户端的 DNS 服务器以及是否对客户端配置文件进行密码保护。
**注:** 如果服务器上已经配置了 IKEv2,则 `VPN_SKIP_IKEV2` 变量无效。在这种情况下,如需自定义 IKEv2 选项,你可以首先[移除 IKEv2](docs/ikev2-howto-zh.md#移除-ikev2),然后运行 `sudo ikev2.sh` 重新配置。
选项 2: 使用环境变量自定义 IKEv2 选项。
在安装 VPN 时,你可以指定一个域名作为 IKEv2 服务器地址。这是可选的。该域名必须是一个全称域名(FQDN)。示例如下:
```bash
sudo VPN_DNS_NAME='vpn.example.com' sh vpn.sh
```
类似地,你可以指定第一个 IKEv2 客户端的名称。如果未指定,则使用默认值 `vpnclient`。
```bash
sudo VPN_CLIENT_NAME='your_client_name' sh vpn.sh
```
在 VPN 已连接时,客户端默认配置为使用 [Google Public DNS](https://developers.google.com/speed/public-dns/)。你可以为所有的 VPN 模式指定另外的 DNS 服务器。示例如下:
```bash
sudo VPN_DNS_SRV1=1.1.1.1 VPN_DNS_SRV2=1.0.0.1 sh vpn.sh
```
默认情况下,导入 IKEv2 客户端配置时不需要密码。你可以选择使用随机密码保护客户端配置文件。
```bash
sudo VPN_PROTECT_CONFIG=yes sh vpn.sh
```
供参考:IKEv1 和 IKEv2 参数列表。
| IKEv1 参数\* |默认值 |自定义(环境变量)\*\* |
| ------------ | ---- | ----------------- |
|服务器地址(DNS域名)| - |不能,但你可以使用 DNS 域名进行连接 |
|服务器地址(公网IP)|自动检测 | VPN_PUBLIC_IP |
| IPsec 预共享密钥 |自动生成 | VPN_IPSEC_PSK |
| VPN 用户名 | vpnuser | VPN_USER |
| VPN 密码 |自动生成 | VPN_PASSWORD |
|客户端的 DNS 服务器 |Google Public DNS | VPN_DNS_SRV1, VPN_DNS_SRV2 |
|跳过 IKEv2 安装 |no | VPN_SKIP_IKEV2=yes |
\* 这些 IKEv1 参数适用于 IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式。
\*\* 在运行 vpn(setup).sh 时将这些定义为环境变量。
| IKEv2 参数\* |默认值 |自定义(环境变量)\*\* |自定义(交互式)\*\*\* |
| ----------- | ---- | ------------------ | ----------------- |
|服务器地址(DNS域名)| - | VPN_DNS_NAME | ✅ |
|服务器地址(公网IP)|自动检测 | VPN_PUBLIC_IP | ✅ |
|第一个客户端的名称 | vpnclient | VPN_CLIENT_NAME | ✅ |
|客户端的 DNS 服务器 |Google Public DNS | VPN_DNS_SRV1, VPN_DNS_SRV2 | ✅ |
|保护客户端配置文件 |no | VPN_PROTECT_CONFIG=yes | ✅ |
|启用/禁用 MOBIKE |如果系统支持则启用 | ❌ | ✅ |
|客户端证书有效期 | 10 年(120 个月)| VPN_CLIENT_VALIDITY\*\*\*\* | ✅ |
| CA 和服务器证书有效期 | 10 年(120 个月)| ❌ | ❌ |
| CA 证书名称 | IKEv2 VPN CA | ❌ | ❌ |
|证书密钥长度 | 3072 bits | ❌ | ❌ |
\* 这些 IKEv2 参数适用于 IKEv2 模式。
\*\* 在运行 vpn(setup).sh 时,或者在自动模式下配置 IKEv2 时 (`sudo ikev2.sh --auto`) 将这些定义为环境变量。
\*\*\* 可以在交互式配置 IKEv2 期间自定义 (`sudo ikev2.sh`)。参见上面的选项 1。
\*\*\*\* 使用 `VPN_CLIENT_VALIDITY` 定义客户端证书的有效期(单位:月)。它必须是 1 到 120 之间的整数。
除了这些参数,高级用户还可以在安装时[自定义 VPN 子网](docs/advanced-usage-zh.md#自定义-vpn-子网)。
## 下一步
*其他语言版本: [English](README.md#next-steps), [简体中文](README-zh.md#下一步), [繁體中文](README-zh-Hant.md#下一步), [日本語](README-ja.md#次のステップ), [Русский](README-ru.md#следующие-шаги)。*
配置你的计算机或其它设备使用 VPN。请参见:
**[配置 IKEv2 VPN 客户端(推荐)](docs/ikev2-howto-zh.md)**
**[配置 IPsec/L2TP VPN 客户端](docs/clients-zh.md)**
**[配置 IPsec/XAuth ("Cisco IPsec") VPN 客户端](docs/clients-xauth-zh.md)**
**阅读 [:book: VPN book](docs/vpn-book-zh.md) 以访问[额外内容](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-X8X5FVFZC)。**
开始使用自己的专属 VPN! :sparkles::tada::rocket::sparkles:
## 重要提示
**Windows 用户** 对于 IPsec/L2TP 模式,在首次连接之前需要[修改注册表](docs/clients-zh.md#windows-错误-809),以解决 VPN 服务器或客户端与 NAT(比如家用路由器)的兼容问题。
同一个 VPN 账户可以在你的多个设备上使用。但是由于 IPsec/L2TP 的局限性,如果需要连接在同一个 NAT(比如家用路由器)后面的多个设备,你必须使用 [IKEv2](docs/ikev2-howto-zh.md) 或者 [IPsec/XAuth](docs/clients-xauth-zh.md) 模式。要查看或更改 VPN 用户账户,请参见[管理 VPN 用户](docs/manage-users-zh.md)。
对于有外部防火墙的服务器(比如 [EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)/[GCE](https://cloud.google.com/vpc/docs/firewalls)),请为 VPN 打开 UDP 端口 500 和 4500。阿里云用户请参见 [#433](https://github.com/hwdsl2/setup-ipsec-vpn/issues/433)。
在 VPN 已连接时,客户端配置为使用 [Google Public DNS](https://developers.google.com/speed/public-dns/)。如果偏好其它的域名解析服务,请参见[高级用法](docs/advanced-usage-zh.md)。
使用内核支持有助于提高 IPsec/L2TP 性能。它在所有[受支持的系统](#系统要求)上可用。Ubuntu 系统需要安装 `linux-modules-extra-$(uname -r)` 软件包并运行 `service xl2tpd restart`。
这些脚本在更改现有的配置文件之前会先做备份,使用 `.old-日期-时间` 为文件名后缀。
## 升级Libreswan
使用以下命令更新你的 VPN 服务器上的 [Libreswan](https://libreswan.org)([更新日志](https://github.com/libreswan/libreswan/blob/main/CHANGES) | [通知列表](https://lists.libreswan.org))。
```bash
wget https://get.vpnsetup.net/upg -O vpnup.sh && sudo sh vpnup.sh
```
如果无法下载,请点这里。
你也可以使用 `curl` 下载:
```bash
curl -fsSL https://get.vpnsetup.net/upg -o vpnup.sh && sudo sh vpnup.sh
```
或者,你也可以使用这些链接:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/extras/vpnupgrade.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras/vpnupgrade.sh
```
如果无法下载,打开 [vpnupgrade.sh](extras/vpnupgrade.sh),然后点击右边的 `Raw` 按钮。按快捷键 `Ctrl/Cmd+A` 全选,`Ctrl/Cmd+C` 复制,然后粘贴到你喜欢的编辑器。
当前支持的 Libreswan 最新版本是 `5.3`。查看已安装版本:`ipsec --version`。
**注:** `xl2tpd` 可以使用系统的软件包管理器进行更新,例如 Ubuntu/Debian 上的 `apt-get`。
## 管理 VPN 用户
请参见[管理 VPN 用户](docs/manage-users-zh.md)。
- [使用辅助脚本管理 VPN 用户](docs/manage-users-zh.md#使用辅助脚本管理-vpn-用户)
- [查看 VPN 用户](docs/manage-users-zh.md#查看-vpn-用户)
- [查看或更改 IPsec PSK](docs/manage-users-zh.md#查看或更改-ipsec-psk)
- [手动管理 VPN 用户](docs/manage-users-zh.md#手动管理-vpn-用户)
## 高级用法
请参见[高级用法](docs/advanced-usage-zh.md)。
- [使用其他的 DNS 服务器](docs/advanced-usage-zh.md#使用其他的-dns-服务器)
- [域名和更改服务器 IP](docs/advanced-usage-zh.md#域名和更改服务器-ip)
- [仅限 IKEv2 的 VPN](docs/advanced-usage-zh.md#仅限-ikev2-的-vpn)
- [VPN 内网 IP 和流量](docs/advanced-usage-zh.md#vpn-内网-ip-和流量)
- [指定 VPN 服务器的公有 IP](docs/advanced-usage-zh.md#指定-vpn-服务器的公有-ip)
- [自定义 VPN 子网](docs/advanced-usage-zh.md#自定义-vpn-子网)
- [IPv6 支持](docs/advanced-usage-zh.md#ipv6-支持)
- [转发端口到 VPN 客户端](docs/advanced-usage-zh.md#转发端口到-vpn-客户端)
- [VPN 分流](docs/advanced-usage-zh.md#vpn-分流)
- [访问 VPN 服务器的网段](docs/advanced-usage-zh.md#访问-vpn-服务器的网段)
- [VPN 服务器网段访问 VPN 客户端](docs/advanced-usage-zh.md#vpn-服务器网段访问-vpn-客户端)
- [更改 IPTables 规则](docs/advanced-usage-zh.md#更改-iptables-规则)
- [部署 Google BBR 拥塞控制](docs/advanced-usage-zh.md#部署-google-bbr-拥塞控制)
## 卸载 VPN
要卸载 IPsec VPN,运行[辅助脚本](extras/vpnuninstall.sh):
**警告:** 此辅助脚本将从你的服务器中删除 IPsec VPN。所有的 VPN 配置将被**永久删除**,并且 Libreswan 和 xl2tpd 将被移除。此操作**不可撤销**!
```bash
wget https://get.vpnsetup.net/unst -O unst.sh && sudo bash unst.sh
```
如果无法下载,请点这里。
你也可以使用 `curl` 下载:
```bash
curl -fsSL https://get.vpnsetup.net/unst -o unst.sh && sudo bash unst.sh
```
或者,你也可以使用这些链接:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/extras/vpnuninstall.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras/vpnuninstall.sh
```
更多信息请参见[卸载 VPN](docs/uninstall-zh.md)。
## 问题和反馈
- 如果你有对本项目的建议,请提交一个[改进建议](https://github.com/hwdsl2/setup-ipsec-vpn/issues/new/choose),或者欢迎提交 [Pull request](https://github.com/hwdsl2/setup-ipsec-vpn/pulls)。
- 如果你发现了一个可重复的程序漏洞,请为 [IPsec VPN](https://github.com/libreswan/libreswan/issues?q=is%3Aissue) 或者 [VPN 脚本](https://github.com/hwdsl2/setup-ipsec-vpn/issues/new/choose)提交一个错误报告。
- 有问题需要提问?请先搜索[已有的 issues](https://github.com/hwdsl2/setup-ipsec-vpn/issues?q=is%3Aissue) 以及在[这个 Gist](https://gist.github.com/hwdsl2/9030462#comments) 和[我的博客](https://blog.ls20.com/ipsec-l2tp-vpn-auto-setup-for-ubuntu-12-04-on-amazon-ec2/#disqus_thread)上已有的留言。
- VPN 的相关问题可在 [Libreswan](https://lists.libreswan.org) 或 [strongSwan](https://lists.strongswan.org) 邮件列表提问,或者参考这些网站:[[1]](https://libreswan.org/wiki/Main_Page) [[2]](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/sec-securing_virtual_private_networks) [[3]](https://wiki.strongswan.org/projects/strongswan/wiki/UserDocumentation) [[4]](https://wiki.gentoo.org/wiki/IPsec_L2TP_VPN_server) [[5]](https://wiki.archlinux.org/index.php/Openswan_L2TP/IPsec_VPN_client_setup)。
## 授权协议
版权所有 (C) 2014-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
基于 [Thomas Sarlandie 的工作](https://github.com/sarfata/voodooprivacy) (版权所有 2012)
[](http://creativecommons.org/licenses/by-sa/3.0/)
这个项目是以[知识共享署名-相同方式共享3.0](http://creativecommons.org/licenses/by-sa/3.0/) 许可协议授权。
必须署名: 请包括我的名字在任何衍生产品,并且让我知道你是如何改善它的!
================================================
FILE: README.md
================================================
[English](README.md) | [简体中文](README-zh.md) | [繁體中文](README-zh-Hant.md) | [日本語](README-ja.md) | [Русский](README-ru.md)
# IPsec VPN Server Auto Setup Scripts
[](https://github.com/hwdsl2/setup-ipsec-vpn/actions/workflows/main.yml) [](https://github.com/hwdsl2/setup-ipsec-vpn/stargazers) [](https://github.com/hwdsl2/docker-ipsec-vpn-server) [](https://github.com/hwdsl2/docker-ipsec-vpn-server)
Set up your own IPsec VPN server in just a few minutes, with IPsec/L2TP, Cisco IPsec and IKEv2.
An IPsec VPN encrypts your network traffic, so that nobody between you and the VPN server can eavesdrop on your data as it travels via the Internet. This is especially useful when using unsecured networks, e.g. at coffee shops, airports or hotel rooms.
We will use [Libreswan](https://libreswan.org/) as the IPsec server, and [xl2tpd](https://github.com/xelerance/xl2tpd) as the L2TP provider.
**[» :book: Book: Privacy Tools in the Age of AI](docs/vpn-book.md) [Build Your Own VPN Server](docs/vpn-book.md)**
## Quick start
First, prepare your Linux server\* with an install of Ubuntu, Debian or CentOS.
Use this one-liner to set up an IPsec VPN server:
```bash
wget https://get.vpnsetup.net -O vpn.sh && sudo sh vpn.sh
```
Your VPN login details will be randomly generated, and displayed when finished.
**Optional:** Install [WireGuard](https://github.com/hwdsl2/wireguard-install) and/or [OpenVPN](https://github.com/hwdsl2/openvpn-install) on the same server.
See the script in action (terminal recording).
**Note:** This recording is for demo purposes only. VPN credentials in this recording are **NOT** valid.

Click here if you are unable to download.
You may also use `curl` to download:
```bash
curl -fsSL https://get.vpnsetup.net -o vpn.sh && sudo sh vpn.sh
```
Alternative setup URLs:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/vpnsetup.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/vpnsetup.sh
```
If you are unable to download, open [vpnsetup.sh](vpnsetup.sh), then click the `Raw` button on the right. Press `Ctrl/Cmd+A` to select all, `Ctrl/Cmd+C` to copy, then paste into your favorite editor.
A pre-built [Docker image](https://github.com/hwdsl2/docker-ipsec-vpn-server) is also available. For other options and client setup, read the sections below.
\* A cloud server, virtual private server (VPS) or dedicated server.
## Features
- Fully automated IPsec VPN server setup, no user input needed
- Supports IKEv2 with strong and fast ciphers (e.g. AES-GCM)
- Generates VPN profiles to auto-configure iOS, macOS and Android devices
- Supports Windows, macOS, iOS, Android, Chrome OS and Linux as VPN clients
- Includes helper scripts to manage VPN users and certificates
## Requirements
A cloud server, virtual private server (VPS) or dedicated server, with an install of:
- Ubuntu 24.04 or 22.04
- Debian 13, 12 or 11
- CentOS Stream 10 or 9
- Rocky Linux or AlmaLinux
- Oracle Linux
- Amazon Linux 2
Other supported Linux distributions.
- Raspberry Pi OS (Raspbian)
- Kali Linux
- Alpine Linux
- Red Hat Enterprise Linux (RHEL)
This also includes Linux VMs in public clouds, such as [DigitalOcean](https://blog.ls20.com/digitalocean), [Vultr](https://blog.ls20.com/vultr), [Linode](https://blog.ls20.com/linode), [OVH](https://www.ovhcloud.com/en/vps/) and [Microsoft Azure](https://azure.microsoft.com). Public cloud users can also deploy using [user data](https://blog.ls20.com/ipsec-l2tp-vpn-auto-setup-for-ubuntu-12-04-on-amazon-ec2/#vpnsetup).
Quick deploy to:
[](https://cloud.linode.com/stackscripts/37239) [](aws/README.md) [](azure/README.md)
[**» I want to run my own VPN but don't have a server for that**](https://blog.ls20.com/ipsec-l2tp-vpn-auto-setup-for-ubuntu-12-04-on-amazon-ec2/#gettingavps)
For servers with an external firewall (e.g. [EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)/[GCE](https://cloud.google.com/vpc/docs/firewalls)), open UDP ports 500 and 4500 for the VPN.
A pre-built [Docker image](https://github.com/hwdsl2/docker-ipsec-vpn-server) is also available. Advanced users can install on a [Raspberry Pi](https://www.raspberrypi.com). [[1]](https://elasticbyte.net/posts/setting-up-a-native-cisco-ipsec-vpn-server-using-a-raspberry-pi/) [[2]](https://www.stewright.me/2018/07/create-a-raspberry-pi-vpn-server-using-l2tpipsec/)
:warning: **DO NOT** run these scripts on your PC or Mac! They should only be used on a server!
## Installation
First, update your server with `sudo apt-get update && sudo apt-get dist-upgrade` (Ubuntu/Debian) or `sudo yum update` and reboot. This is optional, but recommended.
To install the VPN, please choose one of the following options:
**Option 1:** Have the script generate random VPN credentials for you (will be displayed when finished).
```bash
wget https://get.vpnsetup.net -O vpn.sh && sudo sh vpn.sh
```
**Option 2:** Edit the script and provide your own VPN credentials.
```bash
wget https://get.vpnsetup.net -O vpn.sh
nano -w vpn.sh
[Replace with your own values: YOUR_IPSEC_PSK, YOUR_USERNAME and YOUR_PASSWORD]
sudo sh vpn.sh
```
**Note:** A secure IPsec PSK should consist of at least 20 random characters.
**Option 3:** Define your VPN credentials as environment variables.
```bash
# All values MUST be placed inside 'single quotes'
# DO NOT use these special characters within values: \ " '
wget https://get.vpnsetup.net -O vpn.sh
sudo VPN_IPSEC_PSK='your_ipsec_pre_shared_key' \
VPN_USER='your_vpn_username' \
VPN_PASSWORD='your_vpn_password' \
sh vpn.sh
```
You may optionally install [WireGuard](https://github.com/hwdsl2/wireguard-install) and/or [OpenVPN](https://github.com/hwdsl2/openvpn-install) on the same server. If your server runs CentOS Stream, Rocky Linux or AlmaLinux, first install OpenVPN/WireGuard, then install the IPsec VPN.
Click here if you are unable to download.
You may also use `curl` to download. For example:
```bash
curl -fL https://get.vpnsetup.net -o vpn.sh
sudo sh vpn.sh
```
Alternative setup URLs:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/vpnsetup.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/vpnsetup.sh
```
If you are unable to download, open [vpnsetup.sh](vpnsetup.sh), then click the `Raw` button on the right. Press `Ctrl/Cmd+A` to select all, `Ctrl/Cmd+C` to copy, then paste into your favorite editor.
I want to install the older Libreswan version 4.
It is generally recommended to use the latest [Libreswan](https://libreswan.org/) version 5, which is the default version in this project. However, if you want to install the older Libreswan version 4:
```bash
wget https://get.vpnsetup.net -O vpn.sh
sudo VPN_SWAN_VER=4.15 sh vpn.sh
```
**Note:** If Libreswan version 5 is already installed, you may need to first [Uninstall the VPN](docs/uninstall.md) before installing Libreswan version 4. Alternatively, download the [update script](#upgrade-libreswan), edit it to specify `SWAN_VER=4.15`, then run the script.
## Customize VPN options
### Use alternative DNS servers
By default, clients are set to use [Google Public DNS](https://developers.google.com/speed/public-dns/) when the VPN is active. When installing the VPN, you may optionally specify custom DNS server(s) for all VPN modes. Example:
```bash
sudo VPN_DNS_SRV1=1.1.1.1 VPN_DNS_SRV2=1.0.0.1 sh vpn.sh
```
Use `VPN_DNS_SRV1` to specify the primary DNS server, and `VPN_DNS_SRV2` to specify the secondary DNS server (optional).
Below is a list of some popular public DNS providers for your reference.
| Provider | Primary DNS | Secondary DNS | Notes |
| -------- | ----------- | ------------- | ----- |
| [Google Public DNS](https://developers.google.com/speed/public-dns) | 8.8.8.8 | 8.8.4.4 | Default in this project |
| [Cloudflare](https://1.1.1.1/dns/) | 1.1.1.1 | 1.0.0.1 | See also: [Cloudflare for families](https://1.1.1.1/family/) |
| [Quad9](https://www.quad9.net) | 9.9.9.9 | 149.112.112.112 | Blocks malicious domains |
| [OpenDNS](https://www.opendns.com/home-internet-security/) | 208.67.222.222 | 208.67.220.220 | Blocks phishing domains, configurable. |
| [CleanBrowsing](https://cleanbrowsing.org/filters/) | 185.228.168.9 | 185.228.169.9 | [Domain filters](https://cleanbrowsing.org/filters/) available |
| [NextDNS](https://nextdns.io/?from=bg25bwmp) | Varies | Varies | Ad blocking, free tier available. [Learn more](https://nextdns.io/?from=bg25bwmp). |
| [Control D](https://controld.com/free-dns) | Varies | Varies | Ad blocking, configurable. [Learn more](https://controld.com/free-dns). |
If you need to change DNS servers after VPN setup, see [Advanced usage](docs/advanced-usage.md).
**Note:** If IKEv2 is already set up on the server, the variables above have no effect for IKEv2 mode. In that case, to customize IKEv2 options such as DNS servers, you can first [remove IKEv2](docs/ikev2-howto.md#remove-ikev2), then set it up again using `sudo ikev2.sh`.
### Customize IKEv2 options
When installing the VPN, advanced users can optionally customize IKEv2 options.
Option 1: Skip IKEv2 during VPN setup, then set up IKEv2 using custom options.
When installing the VPN, you can skip IKEv2 and only install the IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes:
```bash
sudo VPN_SKIP_IKEV2=yes sh vpn.sh
```
(Optional) If you want to specify custom DNS server(s) for VPN clients, define `VPN_DNS_SRV1` and optionally `VPN_DNS_SRV2`. See [Use alternative DNS servers](#use-alternative-dns-servers) for details.
After that, run the IKEv2 helper script to set up IKEv2 interactively using custom options:
```bash
sudo ikev2.sh
```
You can customize the following options: VPN server's DNS name, name and validity period of the first client, DNS server for VPN clients and whether to password protect client config files.
**Note:** The `VPN_SKIP_IKEV2` variable has no effect if IKEv2 is already set up on the server. In that case, to customize IKEv2 options, you can first [remove IKEv2](docs/ikev2-howto.md#remove-ikev2), then set it up again using `sudo ikev2.sh`.
Option 2: Customize IKEv2 options using environment variables.
When installing the VPN, you can optionally specify a DNS name for the IKEv2 server address. The DNS name must be a fully qualified domain name (FQDN). Example:
```bash
sudo VPN_DNS_NAME='vpn.example.com' sh vpn.sh
```
Similarly, you may specify a name for the first IKEv2 client. The default is `vpnclient` if not specified.
```bash
sudo VPN_CLIENT_NAME='your_client_name' sh vpn.sh
```
By default, clients are set to use [Google Public DNS](https://developers.google.com/speed/public-dns/) when the VPN is active. You may specify custom DNS server(s) for all VPN modes. Example:
```bash
sudo VPN_DNS_SRV1=1.1.1.1 VPN_DNS_SRV2=1.0.0.1 sh vpn.sh
```
By default, no password is required when importing IKEv2 client configuration. You can choose to protect client config files using a random password.
```bash
sudo VPN_PROTECT_CONFIG=yes sh vpn.sh
```
For reference: List of IKEv1 and IKEv2 parameters.
| IKEv1 parameter\* | Default value | Customize (env variable)\*\* |
| --------------------------- | --------------------- | ---------------------------------------- |
| Server address (DNS name) | - | No, but you can connect using a DNS name |
| Server address (public IP) | Auto detect | VPN_PUBLIC_IP |
| IPsec pre-shared key | Auto generate | VPN_IPSEC_PSK |
| VPN username | vpnuser | VPN_USER |
| VPN password | Auto generate | VPN_PASSWORD |
| DNS servers for clients | Google Public DNS | VPN_DNS_SRV1, VPN_DNS_SRV2 |
| Skip IKEv2 setup | no | VPN_SKIP_IKEV2=yes |
\* These IKEv1 parameters are for IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes.
\*\* Define these as environment variables when running vpn(setup).sh.
| IKEv2 parameter\* | Default value | Customize (env variable)\*\* | Customize (interactive)\*\*\* |
| --------------------------- | --------------------- | ---------------------------- | ----------------------------- |
| Server address (DNS name) | - | VPN_DNS_NAME | ✅ |
| Server address (public IP) | Auto detect | VPN_PUBLIC_IP | ✅ |
| Name of first client | vpnclient | VPN_CLIENT_NAME | ✅ |
| DNS servers for clients | Google Public DNS | VPN_DNS_SRV1, VPN_DNS_SRV2 | ✅ |
| Protect client config files | no | VPN_PROTECT_CONFIG=yes | ✅ |
| Enable/Disable MOBIKE | Enable if supported | ❌ | ✅ |
| Client cert validity | 10 years (120 months) | VPN_CLIENT_VALIDITY\*\*\*\* | ✅ |
| CA & server cert validity | 10 years (120 months) | ❌ | ❌ |
| CA certificate name | IKEv2 VPN CA | ❌ | ❌ |
| Certificate key size | 3072 bits | ❌ | ❌ |
\* These IKEv2 parameters are for IKEv2 mode.
\*\* Define these as environment variables when running vpn(setup).sh, or when setting up IKEv2 in auto mode (`sudo ikev2.sh --auto`).
\*\*\* Can be customized during interactive IKEv2 setup (`sudo ikev2.sh`). Refer to option 1 above.
\*\*\*\* Use `VPN_CLIENT_VALIDITY` to specify the client cert validity period in months. Must be an integer between 1 and 120.
In addition to these parameters, advanced users can also [customize VPN subnets](docs/advanced-usage.md#customize-vpn-subnets) during VPN setup.
## Next steps
*Read this in other languages: [English](README.md#next-steps), [简体中文](README-zh.md#下一步), [繁體中文](README-zh-Hant.md#下一步), [日本語](README-ja.md#次のステップ), [Русский](README-ru.md#следующие-шаги).*
Get your computer or device to use the VPN. Please refer to:
**[Configure IKEv2 VPN Clients (recommended)](docs/ikev2-howto.md)**
**[Configure IPsec/L2TP VPN Clients](docs/clients.md)**
**[Configure IPsec/XAuth ("Cisco IPsec") VPN Clients](docs/clients-xauth.md)**
**Read [:book: VPN book](docs/vpn-book.md) to access [extra content](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-O5O7FVF8J).**
Enjoy your very own VPN! :sparkles::tada::rocket::sparkles:
## Important notes
**Windows users**: For IPsec/L2TP mode, a [one-time registry change](docs/clients.md#windows-error-809) is required if the VPN server 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 from behind the same NAT (e.g. home router), you must use [IKEv2](docs/ikev2-howto.md) or [IPsec/XAuth](docs/clients-xauth.md) mode. To view or update VPN user accounts, see [Manage VPN users](docs/manage-users.md).
For servers with an external firewall (e.g. [EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)/[GCE](https://cloud.google.com/vpc/docs/firewalls)), open UDP ports 500 and 4500 for the VPN. Aliyun users, see [#433](https://github.com/hwdsl2/setup-ipsec-vpn/issues/433).
Clients are set to use [Google Public DNS](https://developers.google.com/speed/public-dns/) when the VPN is active. If another DNS provider is preferred, see [Advanced usage](docs/advanced-usage.md).
Using kernel support could improve IPsec/L2TP performance. It is available on [all supported OS](#requirements). Ubuntu users should install the `linux-modules-extra-$(uname -r)` package and run `service xl2tpd restart`.
The scripts will backup existing config files before making changes, with `.old-date-time` suffix.
## Upgrade Libreswan
Use this one-liner to update [Libreswan](https://libreswan.org) ([changelog](https://github.com/libreswan/libreswan/blob/main/CHANGES) | [announce](https://lists.libreswan.org)) on your VPN server.
```bash
wget https://get.vpnsetup.net/upg -O vpnup.sh && sudo sh vpnup.sh
```
Click here if you are unable to download.
You may also use `curl` to download:
```bash
curl -fsSL https://get.vpnsetup.net/upg -o vpnup.sh && sudo sh vpnup.sh
```
Alternative update URLs:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/extras/vpnupgrade.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras/vpnupgrade.sh
```
If you are unable to download, open [vpnupgrade.sh](extras/vpnupgrade.sh), then click the `Raw` button on the right. Press `Ctrl/Cmd+A` to select all, `Ctrl/Cmd+C` to copy, then paste into your favorite editor.
The latest supported Libreswan version is `5.3`. Check installed version: `ipsec --version`.
**Note:** `xl2tpd` can be updated using your system's package manager, such as `apt-get` on Ubuntu/Debian.
## Manage VPN users
See [Manage VPN users](docs/manage-users.md).
- [Manage VPN users using helper scripts](docs/manage-users.md#manage-vpn-users-using-helper-scripts)
- [View VPN users](docs/manage-users.md#view-vpn-users)
- [View or update the IPsec PSK](docs/manage-users.md#view-or-update-the-ipsec-psk)
- [Manually manage VPN users](docs/manage-users.md#manually-manage-vpn-users)
## Advanced usage
See [Advanced usage](docs/advanced-usage.md).
- [Use alternative DNS servers](docs/advanced-usage.md#use-alternative-dns-servers)
- [DNS name and server IP changes](docs/advanced-usage.md#dns-name-and-server-ip-changes)
- [IKEv2-only VPN](docs/advanced-usage.md#ikev2-only-vpn)
- [Internal VPN IPs and traffic](docs/advanced-usage.md#internal-vpn-ips-and-traffic)
- [Specify VPN server's public IP](docs/advanced-usage.md#specify-vpn-servers-public-ip)
- [Customize VPN subnets](docs/advanced-usage.md#customize-vpn-subnets)
- [IPv6 support](docs/advanced-usage.md#ipv6-support)
- [Port forwarding to VPN clients](docs/advanced-usage.md#port-forwarding-to-vpn-clients)
- [Split tunneling](docs/advanced-usage.md#split-tunneling)
- [Access VPN server's subnet](docs/advanced-usage.md#access-vpn-servers-subnet)
- [Access VPN clients from server's subnet](docs/advanced-usage.md#access-vpn-clients-from-servers-subnet)
- [Modify IPTables rules](docs/advanced-usage.md#modify-iptables-rules)
- [Deploy Google BBR congestion control](docs/advanced-usage.md#deploy-google-bbr-congestion-control)
## Uninstall the VPN
To uninstall IPsec VPN, run the [helper script](extras/vpnuninstall.sh):
**Warning:** This helper script will remove IPsec VPN from your server. All VPN configuration will be **permanently deleted**, and Libreswan and xl2tpd will be removed. This **cannot be undone**!
```bash
wget https://get.vpnsetup.net/unst -O unst.sh && sudo bash unst.sh
```
Click here if you are unable to download.
You may also use `curl` to download:
```bash
curl -fsSL https://get.vpnsetup.net/unst -o unst.sh && sudo bash unst.sh
```
Alternative script URLs:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/extras/vpnuninstall.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras/vpnuninstall.sh
```
For more information, see [Uninstall the VPN](docs/uninstall.md).
## Feedback & Questions
- Have a suggestion for this project? Open an [Enhancement request](https://github.com/hwdsl2/setup-ipsec-vpn/issues/new/choose). [Pull requests](https://github.com/hwdsl2/setup-ipsec-vpn/pulls) are also welcome.
- If you found a reproducible bug, open a bug report for the [IPsec VPN](https://github.com/libreswan/libreswan/issues?q=is%3Aissue) or for the [VPN scripts](https://github.com/hwdsl2/setup-ipsec-vpn/issues/new/choose).
- Got a question? Please first search [existing issues](https://github.com/hwdsl2/setup-ipsec-vpn/issues?q=is%3Aissue) and comments [in this Gist](https://gist.github.com/hwdsl2/9030462#comments) and [on my blog](https://blog.ls20.com/ipsec-l2tp-vpn-auto-setup-for-ubuntu-12-04-on-amazon-ec2/#disqus_thread).
- Ask VPN related questions on the [Libreswan](https://lists.libreswan.org) or [strongSwan](https://lists.strongswan.org) mailing list, or read these wikis: [[1]](https://libreswan.org/wiki/Main_Page) [[2]](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/sec-securing_virtual_private_networks) [[3]](https://wiki.strongswan.org/projects/strongswan/wiki/UserDocumentation) [[4]](https://wiki.gentoo.org/wiki/IPsec_L2TP_VPN_server) [[5]](https://wiki.archlinux.org/index.php/Openswan_L2TP/IPsec_VPN_client_setup).
## License
Copyright (C) 2014-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
Based on [the work of Thomas Sarlandie](https://github.com/sarfata/voodooprivacy) (Copyright 2012)
[](http://creativecommons.org/licenses/by-sa/3.0/)
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!
================================================
FILE: aws/README-zh.md
================================================
[English](README.md) | [中文](README-zh.md)
# 使用 CloudFormation 在 Amazon EC2 上部署
使用这个模板,你可以在 Amazon Elastic Compute Cloud(Amazon EC2)上快速搭建一个 IPsec VPN 服务器。在继续之前,请参见 EC2 [定价细节](https://aws.amazon.com/cn/ec2/pricing/on-demand/)。在部署中使用 `t2.micro` 或 `t3.micro` 服务器实例可能符合 [AWS 免费套餐](https://aws.amazon.com/cn/free/)的资格。
可用的自定义参数:
- Amazon EC2 实例类型
> 注: 在某些 AWS 区域中,此模版提供的某些实例类型可能不可用。(点击查看详情)
>
>
> 比如 `m5a.large` 可能无法在 `ap-east-1` 区域部署(仅为假设)。在此情况下,你会在部署过程中遇到此错误:`The requested configuration is currently not supported. Please check the documentation for supported configurations`。新开放的 AWS 区域更容易出现此问题,因为它们提供的实例类型较少。如需了解更多关于实例可用性的信息,请参见 [https://instances.vantage.sh/](https://instances.vantage.sh/)。
- VPN 服务器的操作系统(Ubuntu **24.04**/22.04, Debian 12/11, Amazon Linux 2)
- 你的 VPN 用户名
- 你的 VPN 密码
- 你的 VPN IPsec PSK(预共享密钥)
> **注:** 一个安全的 IPsec PSK 应该至少包含 20 个随机字符。\*不要\* 在值中使用这些字符: `\ " '`
确保使用 **AWS 账户根用户** 或者有 **管理员权限** 的 **IAM 用户** 部署此模板。
右键单击这个 [**模板链接**](https://raw.githubusercontent.com/hwdsl2/setup-ipsec-vpn/master/aws/cloudformation-template-ipsec.json),并将它保存到你的计算机上的一个新文件。然后在 ["创建堆栈" 向导](https://console.aws.amazon.com/cloudformation/home#/stacks/new)中将其作为模板源上传。要指定一个 AWS 区域,你可以使用导航栏上你的帐户信息右侧的选择器。继续创建堆栈,在最后一步你需要确认(选择)此模板可以创建 IAM 资源。
当你在最后一步中点击 "create stack" 之后,请等待堆栈创建和 VPN 安装完成,可能需要最多 15 分钟。一旦堆栈的部署状态变成 **"CREATE_COMPLETE"** ,你就可以连接到 VPN 服务器了。单击 **Outputs** 选项卡以查看你的 VPN 登录信息,然后继续下一步:[配置 VPN 客户端](../README-zh.md#下一步)。
点击下面的图标开始:
[](https://console.aws.amazon.com/cloudformation/home#/stacks/new)
## 延伸阅读
了解有关此 CloudFormation 模板设计的更多信息:
[Introduction to AWS CloudFormation with Example Project Walk-Through](https://nixsanctuary.com/introduction-to-aws-cloudformation-with-example-project-walk-through/)
## 屏幕截图
点这里查看屏幕截图。




## 常见问题
如何在部署结束后提取 IKEv2 连接配置文件?
部署完成之后,生成的 IKEv2 配置文件已经被上传到了一个新创建的 AWS Simple Storage Service (S3) 储存桶。下载配置文件的链接可以在 **Outputs** 页面下找到。
点击下载链接下载名为 `profiles.zip` 的压缩包文件。解压密码为**你在创建堆栈时输入的 VPN 连接密码**。
值得注意的是,IKEv2 配置文件的下载链接将会在**1天后过期**,从堆栈部署完成时算起。如果你将堆栈删除,存放 IKEv2 配置文件的储存桶不会被自动删除。
关于如何在 IKEv2 模式下配置你的客户端,请参见: [IKEv2 VPN 配置和使用指南](../docs/ikev2-howto-zh.md)。

部署后如何通过 SSH 连接到服务器?
**选项 1:** 使用 [EC2 Instance Connect](https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/ec2-instance-connect-methods.html) 进行连接。
**选项 2:** 使用 SSH 连接到服务器。详情如下。
你需要你的 Amazon EC2 实例的用户名和私钥,才能通过 SSH 登录到该实例。
EC2 上的每个 Linux 服务器发行版本都有它自己的默认登录用户名。新实例默认禁用密码登录,必须使用私钥或 “密钥对” 登录。
默认用户名列表:
> **参考链接:** [https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/connection-prereqs.html#connection-prereqs-private-key](https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/connection-prereqs.html#connection-prereqs-private-key)
| 发行版本 | 默认登录用户名 |
| --- | --- |
| Ubuntu | `ubuntu` |
| Debian | `admin` |
| Amazon Linux 2 | `ec2-user` |
此模板在部署期间为你生成一个密钥对。在成功创建堆栈后,你可以使用以下的其中一种方式来获取私钥。
1. 在 **Outputs** 页面下拷贝密钥对 ID ,然后使用以下命令来提取私钥内容并且将其保存为一个证书文件:
> **注:** 在使用以下命令前,你需要在你的电脑上正确的安装和配置好 AWS 命令行。更多关于开始使用 AWS 命令行的信息,请参照 [Get started with the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html) 。
```
$ aws ssm get-parameter --region your-region --name /ec2/keypair/your-key-pair-id --with-decryption --query Parameter.Value --output text > new-key-file.pem
```

2. 直接从 **Outputs** 页面拷贝私钥对内容 ,然后将其保存入一个证书文件。请注意在保存到你的计算机之前,你可能需要修改私钥的格式,比如用换行符替换所有的空格。在保存后,需要为该私钥文件设置[适当的权限](https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/connection-prereqs.html#connection-prereqs-private-key)才能使用。

要为私钥文件设置适当的权限,请在该文件所在的目录下运行以下命令:
```bash
$ sudo chmod 400 new-key-file.pem
```
使用 SSH 登录到 EC2 实例的示例命令:
```bash
$ ssh -i path/to/your/new-key-file.pem instance-username@instance-ip-address
```
如何删除 CloudFormation 堆栈?
你可以使用 CloudFormation 堆栈页面上的 "Delete" 按钮删除你创建的 CloudFormation 堆栈和它相关的资源。请注意,删除堆栈时存放生成的 IKEv2 配置文件的 S3 储存桶不会被自动删除。参见上面的 "如何在部署结束后提取 IKEv2 连接配置文件"。
## 作者
版权所有 (C) 2020-2025 [Scott X. L.](https://github.com/scottpedia) <[ge105@ncf.ca](mailto:ge105@ncf.ca)>
================================================
FILE: aws/README.md
================================================
[English](README.md) | [中文](README-zh.md)
# Deploy to Amazon EC2 using CloudFormation
This template will create a fully-working IPsec VPN server on Amazon Elastic Compute Cloud (Amazon EC2). Please make sure to check the EC2 [pricing details](https://aws.amazon.com/ec2/pricing/on-demand/) before continuing. Using a `t2.micro` or `t3.micro` server instance for your deployment may qualify for the [AWS Free Tier](https://aws.amazon.com/free/).
Available customization parameters:
- Amazon EC2 instance type
> Note: It is possible that not all instance type options offered by this template are available in a specific AWS region.(expand for details)
>
>
> For example, you may not be able to deploy an `m5a.large` instance in `ap-east-1` (hypothetically). In that case, you might experience the following error during deployment: `The requested configuration is currently not supported. Please check the documentation for supported configurations`. Newly released regions are more prone to having this problem as there are less variety of instances. For more info about instance type availability, refer to [https://instances.vantage.sh/](https://instances.vantage.sh/).
- OS for your VPN server (Ubuntu **24.04**/22.04, Debian 12/11, Amazon Linux 2)
- Your VPN username
- Your VPN password
- Your VPN IPsec PSK (pre-shared key)
> **Note:** A secure IPsec PSK should consist of at least 20 random characters. DO NOT use these special characters within values: `\ " '`
Make sure to deploy this template with an **AWS Account Root User** or an **IAM Account** with **Administrator Access**.
Right-click this [**template link**](https://raw.githubusercontent.com/hwdsl2/setup-ipsec-vpn/master/aws/cloudformation-template-ipsec.json) and save as a file on your computer. Then upload it as the template source in the [stack creation wizard](https://console.aws.amazon.com/cloudformation/home#/stacks/new). You may choose an AWS region using the selector to the right of your account information on the navigation bar. Continue creating the stack, and in the final step make sure to confirm that this template may create IAM resources.
After you click "create stack" in the final step, please wait for the stack creation and VPN setup to complete, which may take up to 15 minutes. As soon as the stack's status changes to **"CREATE_COMPLETE"**, you are ready to connect to the VPN server. Click the **Outputs** tab to view your VPN login details. Then continue to [Next steps: Configure VPN Clients](../README.md#next-steps).
Click the icon below to start:
[](https://console.aws.amazon.com/cloudformation/home#/stacks/new)
## Further reading
Learn more about the design of this CloudFormation template:
[Introduction to AWS CloudFormation with Example Project Walk-Through](https://nixsanctuary.com/introduction-to-aws-cloudformation-with-example-project-walk-through/)
## Screenshots
Click here to view screenshots.




## FAQs
How to retrieve the IKEv2 credentials following the deployment?
After the deployment completes, connection credentials generated for IKEv2 mode are uploaded to a newly created AWS Simple Storage Service (S3) bucket. The download link is then provided under the **Outputs** tab.
Simply click on the link to download an archive named `profiles.zip`. To extract the contents from the archive, you will be prompted to enter a password, which is the **VPN password you specified when creating the stack**.
It's important to note that the link provided for downloading the IKEv2 credentials **will expire in 1 day** following the successful deployment of the stack. If you delete the stack, the bucket that stores the IKEv2 crendentials will not be automatically deleted.
To learn more about how to configure your clients using IKEv2 mode, please refer to: [Guide: How to Set Up and Use IKEv2 VPN](../docs/ikev2-howto.md).

How to connect to the server via SSH after deployment?
**Option 1:** Connect using [EC2 Instance Connect](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-connect-methods.html).
**Option 2:** Connect to the server using SSH. See details below.
You need to know the username and the private key for your Amazon EC2 instance in order to login to it via SSH.
Each Linux server distribution on EC2 has its own default login username. Password login is disabled by default for new instances, and the use of private keys, or "key pairs", is enforced.
List of default usernames:
> **Reference:** [https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connection-prereqs.html](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connection-prereqs.html)
| Distribution | Default Login Username |
| --- | --- |
| Ubuntu | `ubuntu` |
| Debian | `admin` |
| Amazon Linux 2 | `ec2-user` |
This template generates a key pair for you during deployment, and to acquire the private key you can choose one of the following two methods.
1. Copy the key pair ID displayed under the **Outputs** tab, and use the following command to retrieve the private key material and save it into a certificate file:
> **Note:** You need to first properly set up the AWS CLI on your computer before using the following command. For more information on how to get started with AWS CLI, please refer to [Get started with the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html).
```
$ aws ssm get-parameter --region your-region --name /ec2/keypair/your-key-pair-id --with-decryption --query Parameter.Value --output text > new-key-file.pem
```

2. Copy the private key material directly from the **Outputs** tab, and save it into a certificate file. Note that You may need to format the private key by replacing all spaces with newlines, before saving to a file. The file will need to be set with [proper permissions](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connection-prereqs.html#connection-prereqs-private-key) before using.

To apply proper permissions to your private key file, run the following command under the directory where the file is located:
```bash
$ sudo chmod 400 new-key-file.pem
```
Example command to login to your EC2 instance using SSH:
```bash
$ ssh -i path/to/your/new-key-file.pem instance-username@instance-ip-address
```
How to delete the CloudFormation stack?
You may use the "Delete" button on the CloudFormation stack page to delete the CloudFormation stack you created and its associated resources. Note that when deleting the stack, the S3 bucket that stores the generated IKEv2 credentials will not be automatically deleted. Refer to "How to retrieve the IKEv2 credentials following the deployment" above.
## Author
Copyright (C) 2020-2025 [Scott X. L.](https://github.com/scottpedia) <[ge105@ncf.ca](mailto:ge105@ncf.ca)>
================================================
FILE: aws/cloudformation-template-ipsec.json
================================================
{
"Metadata": {
"README": {
"Fn::Join": [
"\n",
[
"",
"AWS Cloudformation Template for deploying IPSec VPN Servers on AWS EC2,",
"based on the work of Lin Song : https://github.com/hwdsl2/setup-ipsec-vpn",
"The latest version of this template can be found at : https://github.com/hwdsl2/setup-ipsec-vpn/aws",
"",
"Copyright (C) 2020-2025 Scott X. L. ",
"",
"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!",
""
]
]
}
},
"AWSTemplateFormatVersion": "2010-09-09",
"Mappings": {
"OS": {
"Ubuntu2204": {
"HelperInstallationCommands": "export DEBIAN_FRONTEND=noninteractive\napt-get -yq update\napt-get -yq install python3-pip zip awscli\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz"
},
"Ubuntu2404": {
"HelperInstallationCommands": "export DEBIAN_FRONTEND=noninteractive\nrm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED\napt-get -yq update\napt-get -yq install python3-pip zip\nsnap install aws-cli --classic\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz"
},
"Debian11": {
"HelperInstallationCommands": "export DEBIAN_FRONTEND=noninteractive\napt-get -yq update\napt-get -yq install python3-pip zip awscli\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz"
},
"Debian12": {
"HelperInstallationCommands": "export DEBIAN_FRONTEND=noninteractive\nrm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED\napt-get -yq update\napt-get -yq install python3-pip zip awscli\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz"
},
"AmazonLinux2": {
"HelperInstallationCommands": "export PATH=\"$PATH:/opt/aws/bin\""
}
}
},
"Resources": {
"IAMInstanceProfile": {
"Type": "AWS::IAM::InstanceProfile",
"Properties": {
"InstanceProfileName": {
"Ref": "KeyPair"
},
"Path": "/setup-ipsec-vpn/",
"Roles": [
{
"Ref": "S3ExecutionRole"
}
]
},
"DependsOn": [
"S3ExecutionRole",
"KeyPair"
]
},
"Ikev2S3Bucket": {
"Type": "AWS::S3::Bucket",
"DeletionPolicy": "Retain",
"Properties": {
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": false,
"BlockPublicPolicy": false,
"IgnorePublicAcls": false,
"RestrictPublicBuckets": false
},
"LifecycleConfiguration": {
"Rules": [
{
"Id": "DeletionAfterOneDay",
"Status": "Enabled",
"ExpirationInDays": 1
}
]
},
"BucketName": {
"Fn::GetAtt": [
"KeyPairDisplayFunctionInfo",
"Combination"
]
}
},
"Metadata": {},
"DependsOn": [
"KeyPair"
]
},
"OpenBucketPolicy": {
"Type": "AWS::S3::BucketPolicy",
"Properties": {
"Bucket": {
"Ref": "Ikev2S3Bucket"
},
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": {
"Fn::Join": [
"",
[
"arn:aws:s3:::",
{
"Ref": "Ikev2S3Bucket"
},
"/*"
]
]
}
}
]
}
}
},
"VpnVpc": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/24"
},
"Metadata": {}
},
"VpnSubnet": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VpnVpc"
},
"CidrBlock": "10.0.0.0/24",
"MapPublicIpOnLaunch": true,
"AvailabilityZone": {
"Fn::Select": [
"0",
{
"Fn::GetAZs": ""
}
]
}
},
"Metadata": {},
"DependsOn": [
"VpnVpc",
"VpcInternetGateway"
]
},
"VpnRouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VpnVpc"
}
},
"Metadata": {},
"DependsOn": [
"VpnSubnet"
]
},
"PublicInternetRoute": {
"Type": "AWS::EC2::Route",
"Properties": {
"DestinationCidrBlock": "0.0.0.0/0",
"RouteTableId": {
"Ref": "VpnRouteTable"
},
"GatewayId": {
"Ref": "VpcInternetGateway"
}
},
"Metadata": {},
"DependsOn": [
"VpnRouteTable",
"VpcInternetGateway",
"InternetGatewayAttachment"
]
},
"VpnInstance": {
"Type": "AWS::EC2::Instance",
"CreationPolicy": {
"ResourceSignal": {
"Timeout": "PT15M"
}
},
"Properties": {
"IamInstanceProfile": {
"Ref": "IAMInstanceProfile"
},
"UserData": {
"Fn::Base64": {
"Fn::Join": [
"\n",
[
"#!/bin/bash -xe",
{ "Fn::Sub": "trap 'cfn-signal -e 1 --resource VpnInstance --stack ${AWS::StackName} --region ${AWS::Region}' ERR" },
"sleep 60",
{
"Fn::FindInMap": [
"OS",
{
"Ref": "OS"
},
"HelperInstallationCommands"
]
},
{ "Fn::Sub": "export VPN_IPSEC_PSK='${VpnIpsecPsk}'" },
{ "Fn::Sub": "export VPN_USER='${VpnUser}'" },
{ "Fn::Sub": "export VPN_PASSWORD='${VpnPassword}'" },
"wget -t 3 -T 30 -nv -O vpn.sh https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/vpnsetup.sh",
"sh vpn.sh",
"mkdir /root/profiles",
"cp /root/vpnclient* /root/profiles",
{ "Fn::Sub": "cd /root/ && zip -er --password '${VpnPassword}' profiles.zip ./profiles" },
{ "Fn::Sub": "aws s3 cp /root/profiles.zip s3://${Ikev2S3Bucket}/" },
{ "Fn::Sub": "cfn-signal -e 0 --stack ${AWS::StackName} --resource VpnInstance --region ${AWS::Region}" }
]
]
}
},
"SecurityGroupIds": [
{
"Fn::GetAtt": [
"VpnSecurityGroup",
"GroupId"
]
}
],
"SubnetId": {
"Ref": "VpnSubnet"
},
"AvailabilityZone": {
"Fn::Select": [
"0",
{
"Fn::GetAZs": ""
}
]
},
"InstanceType": {
"Ref": "InstanceType"
},
"KeyName": {
"Ref": "KeyPair"
},
"ImageId": {
"Fn::GetAtt": [
"AMIInfo",
"AMIId"
]
}
},
"Metadata": {},
"DependsOn": [
"VpnRouteTable",
"KeyPair",
"AMIInfoFunction",
"VpnSecurityGroup",
"Ikev2S3Bucket",
"IAMInstanceProfile"
]
},
"KeyPair": {
"Type": "AWS::EC2::KeyPair",
"Properties": {
"KeyName": {
"Fn::Join": [
"-",
[
"setup-ipsec-vpn",
{
"Ref": "AWS::StackName"
}
]
]
}
}
},
"VpnSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "The VPN Security Group, allowing ingress UDP traffic at port 4500 and 500.",
"GroupName": "VpnSecurityGroup",
"VpcId": {
"Ref": "VpnVpc"
},
"SecurityGroupIngress": [
{
"CidrIp": "0.0.0.0/0",
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 22
},
{
"CidrIp": "0.0.0.0/0",
"IpProtocol": "udp",
"FromPort": 500,
"ToPort": 500
},
{
"CidrIp": "0.0.0.0/0",
"IpProtocol": "udp",
"FromPort": 4500,
"ToPort": 4500
}
],
"SecurityGroupEgress": [
{
"CidrIp": "0.0.0.0/0",
"IpProtocol": -1
}
]
},
"Metadata": {}
},
"VpcInternetGateway": {
"Type": "AWS::EC2::InternetGateway",
"Properties": {},
"Metadata": {},
"DependsOn": [
"VpnVpc"
]
},
"SubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": {
"Ref": "VpnRouteTable"
},
"SubnetId": {
"Ref": "VpnSubnet"
}
},
"Metadata": {}
},
"KeyPairDisplayFunction": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Handler": "index.handler",
"Runtime": "python3.12",
"Role": {
"Fn::GetAtt": [
"LambdaExecutionRole",
"Arn"
]
},
"Code": {
"ZipFile": {
"Fn::Join": [
"\n",
[
"import boto3",
"import cfnresponse",
"import string",
"import random",
"import traceback",
"'''",
"This python program should be embedded into its designated cloudformation",
"template as the inline code of one of the lambda functions.",
"Its function is to create a random combination of 20 characters for the naming of the Ikev2S3Bucket, and",
"to retrieve the private key material for display under the Outputs tab.",
"'''",
"def handler(event, context):",
" try:",
" if event['RequestType'] == 'Delete':",
" cfnresponse.send(event, context, cfnresponse.SUCCESS, {})",
" elif event['RequestType'] == 'Create':",
" rCombination = 'setup-ipsec-vpn-' + ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(20)).lower()",
" region = event['ResourceProperties']['Region']",
" ssm = boto3.client('ssm',region)",
" response = ssm.get_parameter(",
{
"Fn::Join": [
"",
[
" Name='/ec2/keypair/",
{
"Fn::GetAtt": [
"KeyPair",
"KeyPairId"
]
},
"',"
]
]
},
" WithDecryption=True",
" )",
" keyMaterial = response['Parameter']['Value']",
" cfnresponse.send(event, context, cfnresponse.SUCCESS, {'KeyMaterial':keyMaterial, 'Combination':rCombination}, 'KeyPairDisplayFunctionInfo')",
" except Exception as e:",
" cfnresponse.send(event, context, cfnresponse.FAILED, {'ErrorMsg':traceback.format_exc()})"
]
]
}
},
"Timeout": 30
},
"Metadata": {},
"DependsOn": [
"LambdaExecutionRole",
"KeyPair"
]
},
"KeyPairDisplayFunctionInfo": {
"Type": "Custom::KeyPairDisplayFunctionInfo",
"Properties": {
"Region": {
"Ref": "AWS::Region"
},
"ServiceToken": {
"Fn::GetAtt": [
"KeyPairDisplayFunction",
"Arn"
]
}
},
"Metadata": {},
"DependsOn": [
"KeyPairDisplayFunction",
"KeyPair"
]
},
"AMIInfo": {
"Type": "Custom::AMIInfo",
"Properties": {
"Region": {
"Ref": "AWS::Region"
},
"ServiceToken": {
"Fn::GetAtt": [
"AMIInfoFunction",
"Arn"
]
},
"Distribution": {
"Ref": "OS"
}
},
"Metadata": {},
"DependsOn": [
"AMIInfoFunction"
]
},
"AMIInfoFunction": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Handler": "index.handler",
"Runtime": "python3.12",
"Role": {
"Fn::GetAtt": [
"LambdaExecutionRole",
"Arn"
]
},
"Code": {
"ZipFile": {
"Fn::Join": [
"\n",
[
"import boto3",
"import cfnresponse",
"import traceback",
"'''",
"This python script should be embeded into its designated cloudformation template.",
"Its function is to sort out the correct AMI image to use for each of the distribution options available.",
"'''",
"def creation_date(e):",
" return e['CreationDate']",
"",
"def handler(event, context):",
" try:",
" regionName = event['ResourceProperties']['Region']",
" distribution = event['ResourceProperties']['Distribution']",
" ec2 = boto3.client('ec2',regionName)",
" AMIName = {",
" 'Ubuntu2204': 'ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*',",
" 'Ubuntu2404': 'ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*',",
" 'Debian11': 'debian-11-amd64-*',",
" 'Debian12': 'debian-12-amd64-*',",
" 'AmazonLinux2': 'amzn2-ami-hvm-*.*-x86_64-gp2',",
" }[distribution]",
" response = ec2.describe_images(Filters=[{'Name':'name', 'Values':[AMIName]}], Owners=['099720109477', '136693071363', 'amazon'])",
" images = response['Images']",
" images.sort(key=creation_date,reverse=True)",
" AMIId = images[0]['ImageId']",
" cfnresponse.send(event, context, cfnresponse.SUCCESS, {'AMIId':AMIId}, 'AMIInfo')",
" except Exception:",
" cfnresponse.send(event, context, cfnresponse.FAILED, {'ErrorMsg':traceback.format_exc()})"
]
]
}
},
"Timeout": 30
},
"Metadata": {},
"DependsOn": [
"LambdaExecutionRole"
]
},
"LambdaExecutionRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/",
"Policies": [
{
"PolicyName": "root",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
}
]
},
"Metadata": {}
},
"S3ExecutionRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"ec2.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/",
"Policies": [
{
"PolicyName": "s3-bucket-specific-policy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": [
{
"Fn::Join": [
"",
[
{
"Fn::GetAtt": [
"Ikev2S3Bucket",
"Arn"
]
},
"/*"
]
]
}
]
}
]
}
}
]
},
"Metadata": {}
},
"InternetGatewayAttachment": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"InternetGatewayId": {
"Ref": "VpcInternetGateway"
},
"VpcId": {
"Ref": "VpnVpc"
}
},
"Metadata": {}
}
},
"Parameters": {
"VpnUser": {
"Type": "String",
"Description": "Your VPN username"
},
"VpnIpsecPsk": {
"Type": "String",
"Description": "Your VPN IPsec PSK (pre-shared key)"
},
"VpnPassword": {
"Type": "String",
"Description": "Your VPN password"
},
"OS": {
"Type": "String",
"Description": "The OS of your VPN server. Default: Ubuntu 24.04",
"Default": "Ubuntu2404",
"AllowedValues": [
"Ubuntu2404",
"Ubuntu2204",
"Debian12",
"Debian11",
"AmazonLinux2"
]
},
"InstanceType": {
"Type": "String",
"Description": "The instance type of your VPN server. Using t2.micro or t3.micro may qualify for the AWS Free Tier.",
"AllowedValues": [
"t2.micro",
"t3.nano",
"m5.large",
"t3.micro",
"t3.small",
"t2.nano",
"t2.small",
"t3a.nano",
"t3a.micro",
"t3a.small",
"m5a.large",
"t1.micro"
],
"Default": "t2.micro"
}
},
"Outputs": {
"1VPNAddress": {
"Description": "This is the public IP of your newly-launched VPN server.",
"Value": {
"Fn::GetAtt": [
"VpnInstance",
"PublicIp"
]
}
},
"2VPNUsername": {
"Description": "Your VPN username",
"Value": {
"Ref": "VpnUser"
}
},
"3VPNPassword": {
"Description": "Your VPN password",
"Value": {
"Ref": "VpnPassword"
}
},
"4VPNKey": {
"Description": "Your VPN IPsec PSK (pre-shared key)",
"Value": {
"Ref": "VpnIpsecPsk"
}
},
"5EC2PrivateKeyId": {
"Description": "The ID of the key pair created. For more information regarding how to retrieve the private key for authentication, please refer to: https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/aws/README.md#faqs",
"Value": {
"Fn::GetAtt": [
"KeyPair",
"KeyPairId"
]
}
},
"6EC2PrivateKeyMaterial": {
"Description": "The content of your private key for accessing the VPN server via SSH. Save it as a file for use when connecting.",
"Value": {
"Fn::GetAtt": [
"KeyPairDisplayFunctionInfo",
"KeyMaterial"
]
}
},
"7NextStep": {
"Description": "Learn how to configure VPN clients.",
"Value": "https://github.com/hwdsl2/setup-ipsec-vpn#next-steps"
},
"8WarningForDebianUsers": {
"Description": "Please be noted that due to Debian images on AWS EC2 using cloud kernels, you are unable to use IPSec/L2TP mode if your server is running Debian. For more information, please refer to the link to the left.",
"Value": "https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/clients.md#debian-kernel"
},
"9RetrieveYourIkev2Credentials": {
"Description": "Please use the following link to download your IKEv2 connection credentials. The password to the ZIP file that stores the credentials, is the same password used to connect to your VPN server. The download link for the credentials will expire in ONE day.",
"Value": {
"Fn::Join": [
"",
[
"https://",
{
"Fn::GetAtt": [
"Ikev2S3Bucket",
"RegionalDomainName"
]
},
"/profiles.zip"
]
]
}
}
}
}
================================================
FILE: azure/README-zh.md
================================================
[English](README.md) | [中文](README-zh.md)
# 在 Microsoft Azure 上部署
使用这个模板,你可以在 Microsoft Azure Cloud 上快速搭建一个 VPN 服务器([定价细节](https://azure.microsoft.com/zh-cn/pricing/details/virtual-machines/))。
可根据偏好设置以下选项:
- Username for VPN **and** SSH (VPN 和 SSH 用户名)
- Password for VPN **and** SSH (VPN 和 SSH 密码)
- IPsec Pre-Shared Key for VPN (IPsec 预共享密钥)
- Operating System Image (操作系统镜像,Ubuntu 24.04 或 22.04)
- Virtual Machine Size (虚拟机大小,默认值: Standard_B1s)
**注:** \*不要\* 在值中使用这些字符: `\ " '`
请单击以下按钮开始:
[](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fhwdsl2%2Fsetup-ipsec-vpn%2Fmaster%2Fazure%2Fazuredeploy.json)
在完成部署之后,Azure 会有提示。下一步:[配置 VPN 客户端](../README-zh.md#下一步)。
**注:** 在使用 SSH 连接到服务器时,请使用你在部署模板中指定的用户名和密码。如果要添加或者导出 IKEv2 客户端,运行 `sudo ikev2.sh`。如果你在输入正确的登录凭证后仍然无法使用 SSH 连接到服务器,请参见[解决与 Azure Linux VM 的 SSH 连接失败、出错或被拒绝的问题](https://learn.microsoft.com/zh-cn/troubleshoot/azure/virtual-machines/linux/troubleshoot-ssh-connection)和/或[无法 SSH 到 Azure Linux VM,因为权限太开放](https://learn.microsoft.com/zh-cn/troubleshoot/azure/virtual-machines/linux/troubleshoot-ssh-permissions-too-open)。
## 作者
版权所有 (C) 2016 [Daniel Falkner](https://github.com/derdanu)
版权所有 (C) 2017-2025 [Lin Song](https://github.com/hwdsl2)
## 屏幕截图
单击查看屏幕截图。

================================================
FILE: azure/README.md
================================================
[English](README.md) | [中文](README-zh.md)
# Deploy to Microsoft Azure
This template will create a fully working VPN server on the Microsoft Azure Cloud ([pricing details](https://azure.microsoft.com/en-us/pricing/details/virtual-machines/)).
Customizable with the following options:
- Username for VPN **and** SSH
- Password for VPN **and** SSH
- IPsec Pre-Shared Key for VPN
- Operating System Image (Ubuntu 24.04 or 22.04)
- Virtual Machine Size (Default: Standard_B1s)
**Note:** DO NOT use these special characters within values: `\ " '`
Press this button to start:
[](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fhwdsl2%2Fsetup-ipsec-vpn%2Fmaster%2Fazure%2Fazuredeploy.json)
When the deployment finishes, Azure displays a notification. Next steps: [Configure VPN Clients](../README.md#next-steps).
**Note:** When connecting to the server using SSH, use the username and password you specified in the deployment template. To add or export IKEv2 clients, run `sudo ikev2.sh`. If somehow you still cannot SSH into the VM after entering the correct login credentials, see [Troubleshoot SSH connections to an Azure Linux VM that fails, errors out, or is refused](https://learn.microsoft.com/en-us/troubleshoot/azure/virtual-machines/linux/troubleshoot-ssh-connection) and/or [Can't SSH to Azure Linux VM because permissions are too open](https://learn.microsoft.com/en-us/troubleshoot/azure/virtual-machines/linux/troubleshoot-ssh-permissions-too-open).
## Authors
Copyright (C) 2016 [Daniel Falkner](https://github.com/derdanu)
Copyright (C) 2017-2025 [Lin Song](https://github.com/hwdsl2)
## Screenshot
Click to see screenshot.

================================================
FILE: azure/azuredeploy.json
================================================
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"username": {
"type": "string",
"minLength": 1,
"metadata": {
"description": "Username for VPN and SSH"
}
},
"password": {
"type": "securestring",
"metadata": {
"description": "Password for VPN and SSH"
}
},
"preSharedKey": {
"type": "securestring",
"metadata": {
"description": "IPsec Pre-Shared Key for VPN"
}
},
"image": {
"type": "string",
"allowedValues": [
"ubuntu24.04",
"ubuntu22.04"
],
"defaultValue": "ubuntu24.04",
"metadata": {
"description": "OS to use. Ubuntu 24.04 or 22.04."
}
},
"VMSize": {
"type": "string",
"defaultValue": "Standard_B1s",
"allowedValues": [
"Standard_B1ls",
"Standard_B1s",
"Standard_B1ms",
"Standard_B2s",
"Standard_B2ms"
],
"metadata": {
"description": "The size of the Virtual Machine."
}
}
},
"variables": {
"quote": "'",
"location": "[resourceGroup().location]",
"vmName": "vpnserver",
"virtualNetworkName": "vpnVnet",
"addressPrefix": "10.0.0.0/16",
"subnetName": "VPNSubnet",
"subnetPrefix": "10.0.1.0/24",
"apiVersion": "2015-06-15",
"storageName": "[concat(uniqueString(resourceGroup().id), 'vpnsa')]",
"vhdStorageType": "Standard_LRS",
"vnetId": "[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]",
"SubnetRef": "[concat(variables('vnetId'), '/subnets/', variables('subnetName'))]",
"ubuntu24.04": {
"publisher": "Canonical",
"offer": "0001-com-ubuntu-server-noble",
"sku": "24_04-lts",
"version": "latest"
},
"ubuntu22.04": {
"publisher": "Canonical",
"offer": "0001-com-ubuntu-server-jammy",
"sku": "22_04-lts",
"version": "latest"
},
"installScriptURL": "https://raw.githubusercontent.com/hwdsl2/setup-ipsec-vpn/master/azure/install.sh",
"installCommand": "[concat('sh install.sh ', variables('quote'), parameters('preSharedKey'), variables('quote'), ' ', variables('quote'), parameters('username'), variables('quote'), ' ', variables('quote'), parameters('password'), variables('quote'))]"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"name": "[variables('storageName')]",
"apiVersion": "2016-01-01",
"location": "[variables('location')]",
"tags": {
"displayName": "StorageAccount"
},
"properties": {},
"sku": {
"name": "[variables('vhdStorageType')]"
},
"kind": "Storage"
},
{
"apiVersion": "[variables('apiVersion')]",
"type": "Microsoft.Network/virtualNetworks",
"name": "[variables('virtualNetworkName')]",
"location": "[variables('location')]",
"tags": {
"displayName": "VirtualNetwork"
},
"properties": {
"addressSpace": {
"addressPrefixes": [
"[variables('addressPrefix')]"
]
},
"subnets": [
{
"name": "[variables('subnetName')]",
"properties": {
"addressPrefix": "[variables('subnetPrefix')]"
}
}
]
}
},
{
"apiVersion": "[variables('apiVersion')]",
"type": "Microsoft.Network/networkInterfaces",
"name": "[concat(variables('vmName'), 'nic')]",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "NetworkInterface"
},
"dependsOn": [
"[concat('Microsoft.Network/virtualNetworks/', concat(variables('virtualNetworkName')))]",
"[concat('Microsoft.Network/publicIPAddresses/', concat(variables('vmName'), 'pip'))]",
"[concat('Microsoft.Network/networkSecurityGroups/', concat(variables('vmName'), 'nsg'))]"
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"publicIPAddress": {
"id": "[resourceId('Microsoft.Network/publicIPAddresses', concat(variables('vmName'), 'pip'))]"
},
"subnet": {
"id": "[variables('subnetRef')]"
}
}
}
],
"networkSecurityGroup": {
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', concat(variables('vmName'), 'nsg'))]"
}
}
},
{
"type": "Microsoft.Compute/virtualMachines",
"name": "[variables('vmName')]",
"apiVersion": "2016-03-30",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "VirtualMachine"
},
"dependsOn": [
"[concat('Microsoft.Network/networkInterfaces/', concat(variables('vmName'), 'nic'))]"
],
"properties": {
"hardwareProfile": {
"vmSize": "[parameters('vmSize')]"
},
"osProfile": {
"computerName": "[variables('vmName')]",
"adminUsername": "[parameters('username')]",
"adminPassword": "[parameters('password')]"
},
"storageProfile": {
"imageReference": "[variables(parameters('image'))]",
"osDisk": {
"name": "osdisk",
"vhd": {
"uri": "[concat(reference(resourceId('Microsoft.Storage/storageAccounts/', variables('storageName'))).primaryEndpoints.blob, 'vmachines/', variables('vmName'), '.vhd')]"
},
"caching": "ReadWrite",
"createOption": "FromImage"
}
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('vmName'), 'nic'))]"
}
]
}
}
},
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat(variables('vmName'),'/installcustomscript')]",
"apiVersion": "[variables('apiVersion')]",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "VirtualMachineCustomScriptExtension"
},
"dependsOn": [
"[concat('Microsoft.Compute/virtualMachines/', variables('vmName'))]"
],
"properties": {
"publisher": "Microsoft.Azure.Extensions",
"type": "CustomScript",
"typeHandlerVersion": "2.0",
"autoUpgradeMinorVersion": true,
"settings": {
"fileUris": [ "[variables('installScriptURL')]" ],
"commandToExecute": "[variables('installCommand')]"
}
}
},
{
"type": "Microsoft.Network/networkSecurityGroups",
"name": "[concat(variables('vmName'), 'nsg')]",
"tags": {
"displayName": "NetworkSecurityGroup"
},
"apiVersion": "[variables('apiVersion')]",
"location": "[resourceGroup().location]",
"properties": {
"securityRules": [
{
"name": "default-ssh",
"properties": {
"protocol": "Tcp",
"sourcePortRange": "*",
"destinationPortRange": "22",
"sourceAddressPrefix": "*",
"destinationAddressPrefix": "*",
"access": "Allow",
"priority": 1000,
"direction": "Inbound"
}
},
{
"name": "default-udp-500",
"properties": {
"protocol": "Udp",
"sourcePortRange": "*",
"destinationPortRange": "500",
"sourceAddressPrefix": "*",
"destinationAddressPrefix": "*",
"access": "Allow",
"priority": 2000,
"direction": "Inbound"
}
},
{
"name": "default-udp-4500",
"properties": {
"protocol": "Udp",
"sourcePortRange": "*",
"destinationPortRange": "4500",
"sourceAddressPrefix": "*",
"destinationAddressPrefix": "*",
"access": "Allow",
"priority": 2001,
"direction": "Inbound"
}
}
]
}
},
{
"apiVersion": "[variables('apiVersion')]",
"type": "Microsoft.Network/publicIPAddresses",
"name": "[concat(variables('vmName'), 'pip')]",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "PublicIPAddress"
},
"properties": {
"publicIPAllocationMethod": "Static"
}
}
],
"outputs": {
"Public IP": {
"type": "string",
"value": "[reference(concat(variables('vmName'), 'pip')).ipAddress]"
}
}
}
================================================
FILE: azure/azuredeploy.parameters.json
================================================
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"username": {
"value": "Vpnuser"
},
"password": {
"value": "Password123#"
},
"preSharedKey": {
"value": "mypsksupersecure"
}
}
}
================================================
FILE: azure/install.sh
================================================
#!/bin/sh
export VPN_IPSEC_PSK="$1"
export VPN_USER="$2"
export VPN_PASSWORD="$3"
wget -t 3 -T 30 -nv -O vpn.sh https://raw.githubusercontent.com/hwdsl2/setup-ipsec-vpn/master/vpnsetup.sh && sh vpn.sh
================================================
FILE: docs/advanced-usage-zh.md
================================================
[English](advanced-usage.md) | [中文](advanced-usage-zh.md)
# 高级用法
* [使用其他的 DNS 服务器](#使用其他的-dns-服务器)
* [域名和更改服务器 IP](#域名和更改服务器-ip)
* [仅限 IKEv2 的 VPN](#仅限-ikev2-的-vpn)
* [VPN 内网 IP 和流量](#vpn-内网-ip-和流量)
* [指定 VPN 服务器的公有 IP](#指定-vpn-服务器的公有-ip)
* [自定义 VPN 子网](#自定义-vpn-子网)
* [IPv6 支持](#ipv6-支持)
* [转发端口到 VPN 客户端](#转发端口到-vpn-客户端)
* [VPN 分流](#vpn-分流)
* [访问 VPN 服务器的网段](#访问-vpn-服务器的网段)
* [VPN 服务器网段访问 VPN 客户端](#vpn-服务器网段访问-vpn-客户端)
* [更改 IPTables 规则](#更改-iptables-规则)
* [部署 Google BBR 拥塞控制](#部署-google-bbr-拥塞控制)
## 使用其他的 DNS 服务器
在 VPN 已连接时,客户端默认配置为使用 [Google Public DNS](https://developers.google.com/speed/public-dns/)。如果偏好其它的域名解析服务,你可以编辑以下文件:`/etc/ppp/options.xl2tpd`, `/etc/ipsec.conf` 和 `/etc/ipsec.d/ikev2.conf`(如果存在),并替换 `8.8.8.8` 和 `8.8.4.4`。然后运行 `service ipsec restart` 和 `service xl2tpd restart`。
以下是一些流行的公共 DNS 提供商的列表,供你参考。
| 提供商 | 主 DNS | 辅助 DNS | 注释 |
| ----- | ------ | ------- | ---- |
| [Google Public DNS](https://developers.google.com/speed/public-dns) | 8.8.8.8 | 8.8.4.4 | 本项目默认 |
| [Cloudflare](https://1.1.1.1/dns/) | 1.1.1.1 | 1.0.0.1 | 另见:[Cloudflare for families](https://1.1.1.1/family/) |
| [Quad9](https://www.quad9.net) | 9.9.9.9 | 149.112.112.112 | 阻止恶意域 |
| [OpenDNS](https://www.opendns.com/home-internet-security/) | 208.67.222.222 | 208.67.220.220 | 阻止网络钓鱼域,可配置。 |
| [CleanBrowsing](https://cleanbrowsing.org/filters/) | 185.228.168.9 | 185.228.169.9 | [域过滤器](https://cleanbrowsing.org/filters/)可用 |
| [NextDNS](https://nextdns.io/?from=bg25bwmp) | 按需选择 | 按需选择 | 广告拦截,免费套餐可用。[了解更多](https://nextdns.io/?from=bg25bwmp)。 |
| [Control D](https://controld.com/free-dns) | 按需选择 | 按需选择 | 广告拦截,可配置。[了解更多](https://controld.com/free-dns)。 |
高级用户可以在运行 VPN 安装脚本时定义 `VPN_DNS_SRV1` 和 `VPN_DNS_SRV2`(可选)。有关更多详细信息,请参见[自定义 VPN 选项](../README-zh.md#自定义-vpn-选项)。
你可以为特定的 IKEv2 客户端设置不同的 DNS 服务器。对于此用例,请参见 [#1562](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1562#issuecomment-2151361658)。
如果你的用例需要使用 IPTables 规则将 DNS 流量重定向到另一台服务器,请参见 [#1565](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1565)。
在某些情况下,你可能希望 VPN 客户端仅使用指定的 DNS 服务器来解析内部域名,并使用其本地配置的 DNS 服务器来解析所有其他域名。这可以使用 `modecfgdomains` 选项进行配置,例如 `modecfgdomains="internal.example.com, home"`。对于 IKEv2,将此选项添加到 `/etc/ipsec.d/ikev2.conf` 中的 `conn ikev2-cp` 小节。对于 IPsec/XAuth ("Cisco IPsec"),将此选项添加到 `/etc/ipsec.conf` 中的 `conn xauth-psk` 小节。然后运行 `service ipsec restart`。IPsec/L2TP 模式不支持此选项。
## 域名和更改服务器 IP
对于 [IPsec/L2TP](clients-zh.md) 和 [IPsec/XAuth ("Cisco IPsec")](clients-xauth-zh.md) 模式,你可以在不需要额外配置的情况下使用一个域名(比如 `vpn.example.com`)而不是 IP 地址连接到 VPN 服务器。另外,一般来说,在服务器的 IP 更改后,比如在恢复一个映像到具有不同 IP 的新服务器后,VPN 会继续正常工作,虽然可能需要重启服务器。
对于 [IKEv2](ikev2-howto-zh.md) 模式,如果你想要 VPN 在服务器的 IP 更改后继续正常工作,参见[这一小节](ikev2-howto-zh.md#更改-ikev2-服务器地址)。或者,你也可以在[配置 IKEv2](ikev2-howto-zh.md#使用辅助脚本配置-ikev2) 时指定一个域名作为 IKEv2 服务器地址。该域名必须是一个全称域名(FQDN)。示例如下:
```
sudo VPN_DNS_NAME='vpn.example.com' ikev2.sh --auto
```
另外,你也可以自定义 IKEv2 选项,通过在运行[辅助脚本](ikev2-howto-zh.md#使用辅助脚本配置-ikev2)时去掉 `--auto` 参数来实现。
## 仅限 IKEv2 的 VPN
使用 Libreswan 4.2 或更新版本,高级用户可以为 VPN 服务器启用仅限 IKEv2 模式。当启用该模式时,VPN 客户端仅能使用 IKEv2 连接到 VPN 服务器。所有的 IKEv1 连接(包括 IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式)将被丢弃。
要启用仅限 IKEv2 模式,首先按照[自述文件](../README-zh.md)中的说明安装 VPN 服务器并且配置 IKEv2。然后运行[辅助脚本](../extras/ikev2onlymode.sh)并按提示操作。
```bash
wget https://get.vpnsetup.net/ikev2only -O ikev2only.sh
sudo bash ikev2only.sh
```
要禁用仅限 IKEv2 模式,再次运行辅助脚本并选择适当的选项。
另外,你也可以手动启用仅限 IKEv2 模式。
另外,你也可以手动启用仅限 IKEv2 模式。首先使用 `ipsec --version` 命令检查 Libreswan 版本,并[更新 Libreswan](../README-zh.md#升级libreswan)(如果需要)。然后编辑 VPN 服务器上的 `/etc/ipsec.conf`。将 `ikev1-policy=accept` 替换为 `ikev1-policy=drop`。如果该行不存在,则在 `config setup` 小节的末尾添加 `ikev1-policy=drop`,开头必须空两格。保存文件并运行 `service ipsec restart`。在完成后,你可以使用 `ipsec status` 命令来验证仅启用了 `ikev2-cp` 连接。
## VPN 内网 IP 和流量
在使用 [IPsec/L2TP](clients-zh.md) 模式连接时,VPN 服务器在虚拟网络 `192.168.42.0/24` 内具有内网 IP `192.168.42.1`。为客户端分配的内网 IP 在这个范围内:`192.168.42.10` 到 `192.168.42.250`。要找到为特定的客户端分配的 IP,可以查看该 VPN 客户端上的连接状态。
在使用 [IPsec/XAuth ("Cisco IPsec")](clients-xauth-zh.md) 或 [IKEv2](ikev2-howto-zh.md) 模式连接时,VPN 服务器在虚拟网络 `192.168.43.0/24` 内 **没有** 内网 IP。为客户端分配的内网 IP 在这个范围内:`192.168.43.10` 到 `192.168.43.250`。
你可以使用这些 VPN 内网 IP 进行通信。但是请注意,为 VPN 客户端分配的 IP 是动态的,而且客户端设备上的防火墙可能会阻止这些流量。
高级用户可以将静态 IP 分配给 VPN 客户端。这是可选的。展开以查看详细信息。
IPsec/L2TP 模式:为 VPN 客户端分配静态 IP
下面的示例 **仅适用于** IPsec/L2TP 模式。这些命令必须用 `root` 账户运行。
1. 首先为要分配静态 IP 的每个 VPN 客户端创建一个新的 VPN 用户。参见[管理 VPN 用户](manage-users-zh.md)。该文档包含辅助脚本,以方便管理 VPN 用户。
1. 编辑 VPN 服务器上的 `/etc/xl2tpd/xl2tpd.conf`。将 `ip range = 192.168.42.10-192.168.42.250` 替换为比如 `ip range = 192.168.42.100-192.168.42.250`。这样可以缩小自动分配的 IP 地址池,从而使更多的 IP 可以作为静态 IP 分配给客户端。
1. 编辑 VPN 服务器上的 `/etc/ppp/chap-secrets`。例如,如果文件内容是:
```
"username1" l2tpd "password1" *
"username2" l2tpd "password2" *
"username3" l2tpd "password3" *
```
假设你要为 VPN 用户 `username2` 分配静态 IP `192.168.42.2`,为 VPN 用户 `username3` 分配静态 IP `192.168.42.3`,同时保持 `username1` 不变(从池中自动分配)。在编辑完成后,文件内容应该如下所示:
```
"username1" l2tpd "password1" *
"username2" l2tpd "password2" 192.168.42.2
"username3" l2tpd "password3" 192.168.42.3
```
**注:** 分配的静态 IP 必须来自子网 `192.168.42.0/24`,并且必须 **不是** 来自自动分配的 IP 地址池(参见上面的 `ip range`)。另外,`192.168.42.1` 保留给 VPN 服务器本身使用。在上面的示例中,你只能分配 `192.168.42.2-192.168.42.99` 范围内的静态 IP。
1. **(重要)** 重启 xl2tpd 服务:
```
service xl2tpd restart
```
IPsec/XAuth ("Cisco IPsec") 模式:为 VPN 客户端分配静态 IP
下面的示例 **仅适用于** IPsec/XAuth ("Cisco IPsec") 模式。这些命令必须用 `root` 账户运行。
1. 首先为要分配静态 IP 的每个 VPN 客户端创建一个新的 VPN 用户。参见[管理 VPN 用户](manage-users-zh.md)。该文档包含辅助脚本,以方便管理 VPN 用户。
1. 编辑 VPN 服务器上的 `/etc/ipsec.conf`。将 `rightaddresspool=192.168.43.10-192.168.43.250` 替换为比如 `rightaddresspool=192.168.43.100-192.168.43.250`。这样可以缩小自动分配的 IP 地址池,从而使更多的 IP 可以作为静态 IP 分配给客户端。
1. 编辑 VPN 服务器上的 `/etc/ipsec.d/ikev2.conf`(如果存在)。将 `rightaddresspool=192.168.43.10-192.168.43.250` 替换为与上一步 **相同的值**。
1. 编辑 VPN 服务器上的 `/etc/ipsec.d/passwd`。例如,如果文件内容是:
```
username1:password1hashed:xauth-psk
username2:password2hashed:xauth-psk
username3:password3hashed:xauth-psk
```
假设你要为 VPN 用户 `username2` 分配静态 IP `192.168.43.2`,为 VPN 用户 `username3` 分配静态 IP `192.168.43.3`,同时保持 `username1` 不变(从池中自动分配)。在编辑完成后,文件内容应该如下所示:
```
username1:password1hashed:xauth-psk
username2:password2hashed:xauth-psk:192.168.42.2
username3:password3hashed:xauth-psk:192.168.42.3
```
**注:** 分配的静态 IP 必须来自子网 `192.168.43.0/24`,并且必须 **不是** 来自自动分配的 IP 地址池(参见上面的 `rightaddresspool`)。在上面的示例中,你只能分配 `192.168.43.1-192.168.43.99` 范围内的静态 IP。
1. **(重要)** 重启 IPsec 服务:
```
service ipsec restart
```
IKEv2 模式:为 VPN 客户端分配静态 IP
下面的示例 **仅适用于** IKEv2 模式。这些命令必须用 `root` 账户运行。
1. 首先为要分配静态 IP 的每个客户端创建一个新的 IKEv2 客户端证书,并且在纸上记下每个客户端的名称。参见[添加客户端证书](ikev2-howto-zh.md#添加客户端证书)。
1. 编辑 VPN 服务器上的 `/etc/ipsec.d/ikev2.conf`。将 `rightaddresspool=192.168.43.10-192.168.43.250` 替换为比如 `rightaddresspool=192.168.43.100-192.168.43.250`。这样可以缩小自动分配的 IP 地址池,从而使更多的 IP 可以作为静态 IP 分配给客户端。
1. 编辑 VPN 服务器上的 `/etc/ipsec.conf`。将 `rightaddresspool=192.168.43.10-192.168.43.250` 替换为与上一步 **相同的值**。
1. 再次编辑 VPN 服务器上的 `/etc/ipsec.d/ikev2.conf`。例如,如果文件内容是:
```
conn ikev2-cp
left=%defaultroute
... ...
```
假设你要为 IKEv2 客户端 `client1` 分配静态 IP `192.168.43.4`,为客户端 `client2` 分配静态 IP `192.168.43.5`,同时保持其它客户端不变(从池中自动分配)。在编辑完成后,文件内容应该如下所示:
```
conn ikev2-cp
left=%defaultroute
... ...
conn ikev2-shared
# 复制/粘贴 ikev2-cp 小节中 *除了下面三项之外* 的所有内容
# rightid, rightaddresspool, auto=add
conn client1
rightid=@client1
rightaddresspool=192.168.43.4-192.168.43.4
auto=add
also=ikev2-shared
conn client2
rightid=@client2
rightaddresspool=192.168.43.5-192.168.43.5
auto=add
also=ikev2-shared
```
**注:** 为要分配静态 IP 的每个客户端添加一个新的 `conn` 小节。`rightid=` 右边的客户端名称必须添加 `@` 前缀。该客户端名称必须与你在[添加客户端证书](ikev2-howto-zh.md#添加客户端证书)时指定的名称完全一致。分配的静态 IP 必须来自子网 `192.168.43.0/24`,并且必须 **不是** 来自自动分配的 IP 地址池(参见上面的 `rightaddresspool`)。在上面的示例中,你只能分配 `192.168.43.1-192.168.43.99` 范围内的静态 IP。
**注:** 对于 Windows 7/8/10/11 和 [RouterOS](ikev2-howto-zh.md#routeros) 客户端,你必须对 `rightid=` 使用不同的语法。例如,如果客户端名称为 `client1`,则在上面的示例中设置 `rightid="CN=client1, O=IKEv2 VPN"`。
1. **(重要)** 重启 IPsec 服务:
```
service ipsec restart
```
在默认配置下,允许客户端之间的流量。如果你想要 **不允许** 客户端之间的流量,可以在 VPN 服务器上运行以下命令。将它们添加到 `/etc/rc.local` 以便在重启后继续有效。
```
iptables -I FORWARD 2 -i ppp+ -o ppp+ -s 192.168.42.0/24 -d 192.168.42.0/24 -j DROP
iptables -I FORWARD 3 -s 192.168.43.0/24 -d 192.168.43.0/24 -j DROP
iptables -I FORWARD 4 -i ppp+ -d 192.168.43.0/24 -j DROP
iptables -I FORWARD 5 -s 192.168.43.0/24 -o ppp+ -j DROP
```
## 指定 VPN 服务器的公有 IP
在具有多个公有 IP 地址的服务器上,高级用户可以使用变量 `VPN_PUBLIC_IP` 为 VPN 服务器指定一个公有 IP。例如,如果服务器的 IP 为 `192.0.2.1` 和 `192.0.2.2`,并且你想要 VPN 服务器使用 `192.0.2.2`:
```
sudo VPN_PUBLIC_IP=192.0.2.2 sh vpn.sh
```
请注意,如果在服务器上已经配置了 IKEv2,则此变量对 IKEv2 模式无效。在这种情况下,你可以移除 IKEv2 并使用自定义选项重新配置它。参见[使用辅助脚本配置 IKEv2](ikev2-howto-zh.md#使用辅助脚本配置-ikev2)。
如果你想要 VPN 客户端在 VPN 连接处于活动状态时使用指定的公有 IP 作为其 "出站 IP",并且指定的 IP **不是** 服务器上的主 IP(或默认路由),则可能需要额外的配置。在这种情况下,你可能需要更改服务器上的 IPTables 规则。如果要在重启后继续有效,你可以将这些命令添加到 `/etc/rc.local`。
继续上面的例子,如果你希望 "出站 IP" 为 `192.0.2.2`:
```
# 获取默认网络接口名称
netif=$(ip -4 route list 0/0 | grep -m 1 -Po '(?<=dev )(\S+)')
# 移除 MASQUERADE 规则
iptables -t nat -D POSTROUTING -s 192.168.43.0/24 -o "$netif" -m policy --dir out --pol none -j MASQUERADE
iptables -t nat -D POSTROUTING -s 192.168.42.0/24 -o "$netif" -j MASQUERADE
# 添加 SNAT 规则
iptables -t nat -I POSTROUTING -s 192.168.43.0/24 -o "$netif" -m policy --dir out --pol none -j SNAT --to 192.0.2.2
iptables -t nat -I POSTROUTING -s 192.168.42.0/24 -o "$netif" -j SNAT --to 192.0.2.2
```
**注:** 以上方法仅适用于服务器的默认网络接口对应多个公有 IP 的情况。如果服务器有多个网络接口,对应不同的公有 IP,则此方法无效。
要检查一个已连接的 VPN 客户端的 "出站 IP",你可以在该客户端上打开浏览器并到[这里](https://www.ipchicken.com)检测 IP 地址。
## 自定义 VPN 子网
默认情况下,IPsec/L2TP VPN 客户端将使用内部 VPN 子网 `192.168.42.0/24`,而 IPsec/XAuth ("Cisco IPsec") 和 IKEv2 VPN 客户端将使用内部 VPN 子网 `192.168.43.0/24`。有关更多详细信息,请参见 [VPN 内网 IP 和流量](#vpn-内网-ip-和流量)。
对于大多数用例,没有必要也 **不建议** 自定义这些子网。但是,如果你的用例需要它,你可以在安装 VPN 时指定自定义子网。
**重要:** 你只能在 **初始 VPN 安装时** 指定自定义子网。如果 IPsec VPN 已安装,你 **必须** 首先[卸载 VPN](uninstall-zh.md),然后指定自定义子网并重新安装。否则,VPN 可能会停止工作。
```
# 示例:为 IPsec/L2TP 模式指定自定义 VPN 子网
# 注:必须指定所有三个变量。
sudo VPN_L2TP_NET=10.1.0.0/16 \
VPN_L2TP_LOCAL=10.1.0.1 \
VPN_L2TP_POOL=10.1.0.10-10.1.254.254 \
sh vpn.sh
```
```
# 示例:为 IPsec/XAuth 和 IKEv2 模式指定自定义 VPN 子网
# 注:必须指定以下两个变量。
sudo VPN_XAUTH_NET=10.2.0.0/16 \
VPN_XAUTH_POOL=10.2.0.10-10.2.254.254 \
sh vpn.sh
```
在上面的例子中,`VPN_L2TP_LOCAL` 是在 IPsec/L2TP 模式下的 VPN 服务器的内网 IP。`VPN_L2TP_POOL` 和 `VPN_XAUTH_POOL` 是为 VPN 客户端自动分配的 IP 地址池。
## IPv6 支持
如果你的 VPN 服务器拥有公共(全局单播)IPv6 地址并且满足以下要求,IKEv2 客户端的 IPv6 支持将在 VPN 安装时自动启用,无需手动配置。
**注:** IPv6 支持已在 Android 上使用 strongSwan VPN 客户端进行测试。其他平台(例如 Windows、macOS、iOS)可能存在限制,或者需要进行额外配置才能使 IPv6 通过 IKEv2 VPN 正常工作。
**注:** 对于 **Windows** 客户端,你需要在 PowerShell 窗口中运行以下命令一次,以通过 VPN 路由 IPv6 流量。将 `IKEv2 VPN X.X.X.X` 替换为你的 VPN 连接的实际名称。完成后,重新连接到 IKEv2 VPN。
```powershell
Add-VpnConnectionRoute -ConnectionName "IKEv2 VPN X.X.X.X" -DestinationPrefix ::/1
Add-VpnConnectionRoute -ConnectionName "IKEv2 VPN X.X.X.X" -DestinationPrefix 8000::/1
```
启用 IPv6 后,IKEv2 VPN 客户端将同时获得来自 `192.168.43.0/24` 地址池的 IPv4 地址和来自 `fddd:500:500:500::/64` 地址池的 IPv6 地址。VPN 服务器通过将客户端地址池的 IPv6 流量伪装(NAT)为服务器自身的 IPv6 地址,从而使 VPN 客户端能够通过该隧道获得完整的 IPv6 互联网访问。
**要求:**
- VPN 服务器必须拥有可路由的全局单播 IPv6 地址(即以 `2` 或 `3` 开头的地址)。链路本地地址 (`fe80::/10`) 和 ULA 地址 (`fc00::/7`) 不满足要求。
- Libreswan 5.0 或更新版本(VPN 安装脚本默认使用 5.x)。
- IPv6 仅支持 **IKEv2 模式**。IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式不支持 IPv6。
要验证 IPv6 是否正常工作,请使用 IKEv2 连接到 VPN,然后检查你的 IPv6 地址,例如使用 [test-ipv6.com](https://test-ipv6.com)。
你可以在安装 VPN 时选择指定自定义 IPv6 地址池子网,这是可选的。该子网必须是 `/64` ULA 范围内的子网(推荐使用 `fddd::/16`)。
```
# 示例:为 IKEv2 模式指定自定义 IPv6 地址池子网
sudo VPN_IP6_NET=fddd:1234:5678:9012::/64 \
sh vpn.sh
```
**注:** `VPN_IP6_NET` 变量只能在初始 VPN 安装时指定。
## 转发端口到 VPN 客户端
在某些情况下,你可能想要将 VPN 服务器上的端口转发到一个已连接的 VPN 客户端。这可以通过在 VPN 服务器上添加 IPTables 规则来实现。
**警告:** 端口转发会将 VPN 客户端上的端口暴露给整个因特网,这可能会带来**安全风险**!**不建议**这样做,除非你的用例需要它。
**注:** 为 VPN 客户端分配的内网 IP 是动态的,而且客户端设备上的防火墙可能会阻止转发的流量。如果要将静态 IP 分配给 VPN 客户端,请参见 [VPN 内网 IP 和流量](#vpn-内网-ip-和流量)。要找到为特定的客户端分配的 IP,可以查看该 VPN 客户端上的连接状态。
示例 1:将 VPN 服务器上的 TCP 端口 443 转发到位于 `192.168.42.10` 的 IPsec/L2TP 客户端。
```
# 获取默认网络接口名称
netif=$(ip -4 route list 0/0 | grep -m 1 -Po '(?<=dev )(\S+)')
iptables -I FORWARD 2 -i "$netif" -o ppp+ -p tcp --dport 443 -j ACCEPT
iptables -t nat -A PREROUTING -i "$netif" -p tcp --dport 443 -j DNAT --to 192.168.42.10
```
示例 2:将 VPN 服务器上的 UDP 端口 123 转发到位于 `192.168.43.10` 的 IKEv2(或 IPsec/XAuth)客户端。
```
# 获取默认网络接口名称
netif=$(ip -4 route list 0/0 | grep -m 1 -Po '(?<=dev )(\S+)')
iptables -I FORWARD 2 -i "$netif" -d 192.168.43.0/24 -p udp --dport 123 -j ACCEPT
iptables -t nat -A PREROUTING -i "$netif" ! -s 192.168.43.0/24 -p udp --dport 123 -j DNAT --to 192.168.43.10
```
如果你想要这些规则在重启后仍然有效,可以将这些命令添加到 `/etc/rc.local`。要删除添加的 IPTables 规则,请再次运行这些命令,但是将 `-I FORWARD 2` 替换为 `-D FORWARD`,并且将 `-A PREROUTING` 替换为 `-D PREROUTING`。
## VPN 分流
在启用 VPN 分流 (split tunneling) 时,VPN 客户端将仅通过 VPN 隧道发送特定目标子网的流量。其他流量 **不会** 通过 VPN 隧道。这允许你通过 VPN 安全访问指定的网络,而无需通过 VPN 发送所有客户端的流量。VPN 分流有一些局限性,而且并非所有的 VPN 客户端都支持。
高级用户可以为 [IPsec/XAuth ("Cisco IPsec")](clients-xauth-zh.md) 和/或 [IKEv2](ikev2-howto-zh.md) 模式启用 VPN 分流。这是可选的。展开查看详情。IPsec/L2TP 模式不支持此功能(Windows 除外,见下文)。
IPsec/XAuth ("Cisco IPsec") 模式:启用 VPN 分流 (split tunneling)
下面的示例 **仅适用于** IPsec/XAuth ("Cisco IPsec") 模式。这些命令必须用 `root` 账户运行。
1. 编辑 VPN 服务器上的 `/etc/ipsec.conf`。在 `conn xauth-psk` 小节中,将 `leftsubnet=0.0.0.0/0` 替换为你想要 VPN 客户端通过 VPN 隧道发送流量的子网。例如:
对于单个子网:
```
leftsubnet=10.123.123.0/24
```
对于多个子网(使用 `leftsubnets`):
```
leftsubnets="10.123.123.0/24,10.100.0.0/16"
```
1. **(重要)** 重启 IPsec 服务:
```
service ipsec restart
```
IKEv2 模式:启用 VPN 分流 (split tunneling)
下面的示例 **仅适用于** IKEv2 模式。这些命令必须用 `root` 账户运行。
1. 编辑 VPN 服务器上的 `/etc/ipsec.d/ikev2.conf`。在 `conn ikev2-cp` 小节中,将 `leftsubnet=0.0.0.0/0` 替换为你想要 VPN 客户端通过 VPN 隧道发送流量的子网。例如:
对于单个子网:
```
leftsubnet=10.123.123.0/24
```
对于多个子网(使用 `leftsubnets`):
```
leftsubnets="10.123.123.0/24,10.100.0.0/16"
```
1. **(重要)** 重启 IPsec 服务:
```
service ipsec restart
```
**注:** 高级用户可以为特定的 IKEv2 客户端设置不同的 VPN 分流配置。请参见 [VPN 内网 IP 和流量](#vpn-内网-ip-和流量)部分并展开 "IKEv2 模式:为 VPN 客户端分配静态 IP"。在该部分中的示例的基础上,你可以将 `leftsubnet=...` 选项添加到特定 IKEv2 客户端的 `conn` 小节,然后重启 IPsec 服务。
另外,Windows 用户也可以通过手动添加路由的方式启用 VPN 分流:
1. 右键单击系统托盘中的无线/网络图标。
1. **Windows 11:** 选择 **网络和 Internet 设置**,然后在打开的页面中单击 **高级网络设置**。单击 **更多网络适配器选项**。
**Windows 10:** 选择 **打开"网络和 Internet"设置**,然后在打开的页面中单击 **网络和共享中心**。单击左侧的 **更改适配器设置**。
**Windows 8/7:** 选择 **打开网络和共享中心**。单击左侧的 **更改适配器设置**。
1. 右键单击新的 VPN 连接,并选择 **属性**。
1. 单击 **网络** 选项卡,选择 **Internet Protocol Version 4 (TCP/IPv4)**,然后单击 **属性**。
1. 单击 **高级**,然后取消选中 **在远程网络上使用默认网关**。
1. 单击 **确定** 以关闭 **属性** 对话框。
1. **(重要)** 断开 VPN 连接,然后重新连接。
1. 假设你想要 VPN 客户端通过 VPN 隧道发送流量的子网是 `10.123.123.0/24`。打开[提升权限命令提示符](http://www.cnblogs.com/xxcanghai/p/4610054.html)并运行以下命令之一。
对于 IKEv2 和 IPsec/XAuth ("Cisco IPsec") 模式:
```
route add -p 10.123.123.0 mask 255.255.255.0 192.168.43.1
```
对于 IPsec/L2TP 模式:
```
route add -p 10.123.123.0 mask 255.255.255.0 192.168.42.1
```
1. 完成后,VPN 客户端将通过 VPN 隧道仅发送指定子网的流量。其他流量将绕过 VPN。
## 访问 VPN 服务器的网段
连接到 VPN 后,VPN 客户端通常可以访问与 VPN 服务器位于同一本地子网内的其他设备上运行的服务,而无需进行其他配置。例如,如果 VPN 服务器的本地子网为 `192.168.0.0/24`,并且一个 Nginx 服务器在 IP `192.168.0.2` 上运行,则 VPN 客户端可以使用 IP `192.168.0.2`来访问 Nginx 服务器。
请注意,如果 VPN 服务器具有多个网络接口(例如 `eth0` 和 `eth1`),并且你想要 VPN 客户端访问服务器上 **不用于** Internet 访问的网络接口后面的本地子网,则需要进行额外的配置。在此情形下,你必须运行以下命令来添加 IPTables 规则。为了在重启后仍然有效,你可以将这些命令添加到 `/etc/rc.local`。
```bash
# 将 eth1 替换为 VPN 服务器上你想要客户端访问的网络接口名称
netif=eth1
iptables -I FORWARD 2 -i "$netif" -o ppp+ -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I FORWARD 2 -i ppp+ -o "$netif" -j ACCEPT
iptables -I FORWARD 2 -i "$netif" -d 192.168.43.0/24 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I FORWARD 2 -s 192.168.43.0/24 -o "$netif" -j ACCEPT
iptables -t nat -I POSTROUTING -s 192.168.43.0/24 -o "$netif" -m policy --dir out --pol none -j MASQUERADE
iptables -t nat -I POSTROUTING -s 192.168.42.0/24 -o "$netif" -j MASQUERADE
```
## VPN 服务器网段访问 VPN 客户端
在某些情况下,你可能需要从 VPN 服务器位于同一本地子网内的其他设备访问 VPN 客户端上的服务。这可以通过以下几个步骤实现。
假设 VPN 服务器 IP 是 `10.1.0.2`,你想要访问 VPN 客户端的设备的 IP 是 `10.1.0.3`。
1. 在 VPN 服务器上添加 IPTables 规则以允许该流量。例如:
```
# 获取默认网络接口名称
netif=$(ip -4 route list 0/0 | grep -m 1 -Po '(?<=dev )(\S+)')
iptables -I FORWARD 2 -i "$netif" -o ppp+ -s 10.1.0.3 -j ACCEPT
iptables -I FORWARD 2 -i "$netif" -d 192.168.43.0/24 -s 10.1.0.3 -j ACCEPT
```
2. 在你想要访问 VPN 客户端的设备上添加路由规则。例如:
```
# 将 eth0 替换为设备的本地子网的网络接口名称
route add -net 192.168.42.0 netmask 255.255.255.0 gw 10.1.0.2 dev eth0
route add -net 192.168.43.0 netmask 255.255.255.0 gw 10.1.0.2 dev eth0
```
在 [VPN 内网 IP 和流量](#vpn-内网-ip-和流量)小节了解 VPN 内网 IP 的更多信息。
## 更改 IPTables 规则
如果你想要在安装后更改 IPTables 规则,请编辑 `/etc/iptables.rules` 和/或 `/etc/iptables/rules.v4` (Ubuntu/Debian),或者 `/etc/sysconfig/iptables` (CentOS/RHEL)。然后重启服务器。
如果启用了 [IPv6 支持](#ipv6-支持),相应的 ip6tables 规则将保存在 `/etc/ip6tables.rules` 和 `/etc/iptables/rules.v6` (Ubuntu/Debian),或者 `/etc/sysconfig/ip6tables` (CentOS/RHEL)。
**注:** 如果你的服务器运行 CentOS Linux(或类似系统),并且在安装 VPN 时 firewalld 处于活动状态,则可能已配置 nftables。在这种情况下,编辑 `/etc/sysconfig/nftables.conf` 而不是 `/etc/sysconfig/iptables`。
## 部署 Google BBR 拥塞控制
VPN 服务器搭建完成后,可以通过部署 Google BBR 拥塞控制算法提升性能。
这通常只需要在配置文件 `/etc/sysctl.conf` 中插入设定即可完成。但是部分 Linux 发行版可能需要额外更新 Linux 内核。
详细的部署方法,可以参考[这篇文档](bbr-zh.md)。
## 授权协议
版权所有 (C) 2021-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
[](http://creativecommons.org/licenses/by-sa/3.0/)
这个项目是以[知识共享署名-相同方式共享3.0](http://creativecommons.org/licenses/by-sa/3.0/) 许可协议授权。
必须署名: 请包括我的名字在任何衍生产品,并且让我知道你是如何改善它的!
================================================
FILE: docs/advanced-usage.md
================================================
[English](advanced-usage.md) | [中文](advanced-usage-zh.md)
# Advanced Usage
* [Use alternative DNS servers](#use-alternative-dns-servers)
* [DNS name and server IP changes](#dns-name-and-server-ip-changes)
* [IKEv2-only VPN](#ikev2-only-vpn)
* [Internal VPN IPs and traffic](#internal-vpn-ips-and-traffic)
* [Specify VPN server's public IP](#specify-vpn-servers-public-ip)
* [Customize VPN subnets](#customize-vpn-subnets)
* [IPv6 support](#ipv6-support)
* [Port forwarding to VPN clients](#port-forwarding-to-vpn-clients)
* [Split tunneling](#split-tunneling)
* [Access VPN server's subnet](#access-vpn-servers-subnet)
* [Access VPN clients from server's subnet](#access-vpn-clients-from-servers-subnet)
* [Modify IPTables rules](#modify-iptables-rules)
* [Deploy Google BBR congestion control](#deploy-google-bbr-congestion-control)
## Use alternative DNS servers
By default, clients are set to use [Google Public DNS](https://developers.google.com/speed/public-dns/) when the VPN is active. If another DNS provider is preferred, you may replace `8.8.8.8` and `8.8.4.4` in these files: `/etc/ppp/options.xl2tpd`, `/etc/ipsec.conf` and `/etc/ipsec.d/ikev2.conf` (if exists). Then run `service ipsec restart` and `service xl2tpd restart`.
Below is a list of some popular public DNS providers for your reference.
| Provider | Primary DNS | Secondary DNS | Notes |
| -------- | ----------- | ------------- | ----- |
| [Google Public DNS](https://developers.google.com/speed/public-dns) | 8.8.8.8 | 8.8.4.4 | Default in this project |
| [Cloudflare](https://1.1.1.1/dns/) | 1.1.1.1 | 1.0.0.1 | See also: [Cloudflare for families](https://1.1.1.1/family/) |
| [Quad9](https://www.quad9.net) | 9.9.9.9 | 149.112.112.112 | Blocks malicious domains |
| [OpenDNS](https://www.opendns.com/home-internet-security/) | 208.67.222.222 | 208.67.220.220 | Blocks phishing domains, configurable. |
| [CleanBrowsing](https://cleanbrowsing.org/filters/) | 185.228.168.9 | 185.228.169.9 | [Domain filters](https://cleanbrowsing.org/filters/) available |
| [NextDNS](https://nextdns.io/?from=bg25bwmp) | Varies | Varies | Ad blocking, free tier available. [Learn more](https://nextdns.io/?from=bg25bwmp). |
| [Control D](https://controld.com/free-dns) | Varies | Varies | Ad blocking, configurable. [Learn more](https://controld.com/free-dns). |
Advanced users can define `VPN_DNS_SRV1` and optionally `VPN_DNS_SRV2` when running the VPN setup script. For more details, see [Customize VPN options](../README.md#customize-vpn-options).
It is possible to set different DNS server(s) for specific IKEv2 client(s). For this use case, please refer to [#1562](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1562#issuecomment-2151361658).
If your use case requires redirecting DNS traffic to another server using IPTables rules, see [#1565](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1565).
In certain circumstances, you may want VPN clients to use the specified DNS server(s) only for resolving internal domain name(s), and use their locally configured DNS servers to resolve all other domain names. This can be configured using the `modecfgdomains` option, e.g. `modecfgdomains="internal.example.com, home"`. Add this option to section `conn ikev2-cp` in `/etc/ipsec.d/ikev2.conf` for IKEv2, and to section `conn xauth-psk` in `/etc/ipsec.conf` for IPsec/XAuth ("Cisco IPsec"). Then run `service ipsec restart`. IPsec/L2TP mode does not support this option.
## DNS name and server IP changes
For [IPsec/L2TP](clients.md) and [IPsec/XAuth ("Cisco IPsec")](clients-xauth.md) modes, you may use a DNS name (e.g. `vpn.example.com`) instead of an IP address to connect to the VPN server, without additional configuration. In addition, the VPN should generally continue to work after server IP changes, such as after restoring a snapshot to a new server with a different IP, although a reboot may be required.
For [IKEv2](ikev2-howto.md) mode, if you want the VPN to continue to work after server IP changes, read [this section](ikev2-howto.md#change-ikev2-server-address). Alternatively, you may specify a DNS name for the IKEv2 server address when [setting up IKEv2](ikev2-howto.md#set-up-ikev2-using-helper-script). The DNS name must be a fully qualified domain name (FQDN). Example:
```
sudo VPN_DNS_NAME='vpn.example.com' ikev2.sh --auto
```
Alternatively, you may customize IKEv2 options by running the [helper script](ikev2-howto.md#set-up-ikev2-using-helper-script) without the `--auto` parameter.
## IKEv2-only VPN
Using Libreswan 4.2 or newer, advanced users can enable IKEv2-only mode on the VPN server. With IKEv2-only mode enabled, VPN clients can only connect to the VPN server using IKEv2. All IKEv1 connections (including IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes) will be dropped.
To enable IKEv2-only mode, first install the VPN server and set up IKEv2 using instructions in the [README](../README.md). Then run the [helper script](../extras/ikev2onlymode.sh) and follow the prompts.
```bash
wget https://get.vpnsetup.net/ikev2only -O ikev2only.sh
sudo bash ikev2only.sh
```
To disable IKEv2-only mode, run the helper script again and select the appropriate option.
Alternatively, you may manually enable IKEv2-only mode.
Alternatively, you may manually enable IKEv2-only mode. First check Libreswan version using `ipsec --version`, and [update Libreswan](../README.md#upgrade-libreswan) if needed. Then edit `/etc/ipsec.conf` on the VPN server. Replace `ikev1-policy=accept` with `ikev1-policy=drop`. If the line does not exist, append `ikev1-policy=drop` to the end of the `config setup` section, indented by two spaces. Save the file and run `service ipsec restart`. When finished, you can run `ipsec status` to verify that only the `ikev2-cp` connection is enabled.
## Internal VPN IPs and traffic
When connecting using [IPsec/L2TP](clients.md) mode, the VPN server has internal IP `192.168.42.1` within the VPN subnet `192.168.42.0/24`. Clients are assigned internal IPs from `192.168.42.10` to `192.168.42.250`. To check which IP is assigned to a client, view the connection status on the VPN client.
When connecting using [IPsec/XAuth ("Cisco IPsec")](clients-xauth.md) or [IKEv2](ikev2-howto.md) mode, the VPN server does NOT have an internal IP within the VPN subnet `192.168.43.0/24`. Clients are assigned internal IPs from `192.168.43.10` to `192.168.43.250`.
You may use these internal VPN IPs for communication. However, note that the IPs assigned to VPN clients are dynamic, and firewalls on client devices may block such traffic.
Advanced users may optionally assign static IPs to VPN clients. Expand for details.
IPsec/L2TP mode: Assign static IPs to VPN clients
The example below **ONLY** applies to IPsec/L2TP mode. Commands must be run as `root`.
1. First, create a new VPN user for each VPN client that you want to assign a static IP to. Refer to [Manage VPN Users](manage-users.md). Helper scripts are included for convenience.
1. Edit `/etc/xl2tpd/xl2tpd.conf` on the VPN server. Replace `ip range = 192.168.42.10-192.168.42.250` with e.g. `ip range = 192.168.42.100-192.168.42.250`. This reduces the pool of auto-assigned IP addresses, so that more IPs are available to assign to clients as static IPs.
1. Edit `/etc/ppp/chap-secrets` on the VPN server. For example, if the file contains:
```
"username1" l2tpd "password1" *
"username2" l2tpd "password2" *
"username3" l2tpd "password3" *
```
Let's assume that you want to assign static IP `192.168.42.2` to VPN user `username2`, assign static IP `192.168.42.3` to VPN user `username3`, while keeping `username1` unchanged (auto-assign from the pool). After editing, the file should look like:
```
"username1" l2tpd "password1" *
"username2" l2tpd "password2" 192.168.42.2
"username3" l2tpd "password3" 192.168.42.3
```
**Note:** The assigned static IP(s) must be from the subnet `192.168.42.0/24`, and must NOT be from the pool of auto-assigned IPs (see `ip range` above). In addition, `192.168.42.1` is reserved for the VPN server itself. In the example above, you can only assign static IP(s) from the range `192.168.42.2-192.168.42.99`.
1. **(Important)** Restart the xl2tpd service:
```
service xl2tpd restart
```
IPsec/XAuth ("Cisco IPsec") mode: Assign static IPs to VPN clients
The example below **ONLY** applies to IPsec/XAuth ("Cisco IPsec") mode. Commands must be run as `root`.
1. First, create a new VPN user for each VPN client that you want to assign a static IP to. Refer to [Manage VPN Users](manage-users.md). Helper scripts are included for convenience.
1. Edit `/etc/ipsec.conf` on the VPN server. Replace `rightaddresspool=192.168.43.10-192.168.43.250` with e.g. `rightaddresspool=192.168.43.100-192.168.43.250`. This reduces the pool of auto-assigned IP addresses, so that more IPs are available to assign to clients as static IPs.
1. Edit `/etc/ipsec.d/ikev2.conf` on the VPN server (if exists). Replace `rightaddresspool=192.168.43.10-192.168.43.250` with the **same value** as the previous step.
1. Edit `/etc/ipsec.d/passwd` on the VPN server. For example, if the file contains:
```
username1:password1hashed:xauth-psk
username2:password2hashed:xauth-psk
username3:password3hashed:xauth-psk
```
Let's assume that you want to assign static IP `192.168.43.2` to VPN user `username2`, assign static IP `192.168.43.3` to VPN user `username3`, while keeping `username1` unchanged (auto-assign from the pool). After editing, the file should look like:
```
username1:password1hashed:xauth-psk
username2:password2hashed:xauth-psk:192.168.42.2
username3:password3hashed:xauth-psk:192.168.42.3
```
**Note:** The assigned static IP(s) must be from the subnet `192.168.43.0/24`, and must NOT be from the pool of auto-assigned IPs (see `rightaddresspool` above). In the example above, you can only assign static IP(s) from the range `192.168.43.1-192.168.43.99`.
1. **(Important)** Restart the IPsec service:
```
service ipsec restart
```
IKEv2 mode: Assign static IPs to VPN clients
The example below **ONLY** applies to IKEv2 mode. Commands must be run as `root`.
1. First, create a new IKEv2 client certificate for each client that you want to assign a static IP to, and write down the name of each IKEv2 client. Refer to [Add a client certificate](ikev2-howto.md#add-a-client-certificate).
1. Edit `/etc/ipsec.d/ikev2.conf` on the VPN server. Replace `rightaddresspool=192.168.43.10-192.168.43.250` with e.g. `rightaddresspool=192.168.43.100-192.168.43.250`. This reduces the pool of auto-assigned IP addresses, so that more IPs are available to assign to clients as static IPs.
1. Edit `/etc/ipsec.conf` on the VPN server. Replace `rightaddresspool=192.168.43.10-192.168.43.250` with the **same value** as the previous step.
1. Edit `/etc/ipsec.d/ikev2.conf` on the VPN server again. For example, if the file contains:
```
conn ikev2-cp
left=%defaultroute
... ...
```
Let's assume that you want to assign static IP `192.168.43.4` to IKEv2 client `client1`, assign static IP `192.168.43.5` to client `client2`, while keeping other clients unchanged (auto-assign from the pool). After editing, the file should look like:
```
conn ikev2-cp
left=%defaultroute
... ...
conn ikev2-shared
# COPY everything from the ikev2-cp section, EXCEPT FOR:
# rightid, rightaddresspool, auto=add
conn client1
rightid=@client1
rightaddresspool=192.168.43.4-192.168.43.4
auto=add
also=ikev2-shared
conn client2
rightid=@client2
rightaddresspool=192.168.43.5-192.168.43.5
auto=add
also=ikev2-shared
```
**Note:** Add a new `conn` section for each client that you want to assign a static IP to. You must add a `@` prefix to the client name for `rightid=`. The client name must exactly match the name you specified when [adding the client certificate](ikev2-howto.md#add-a-client-certificate). The assigned static IP(s) must be from the subnet `192.168.43.0/24`, and must NOT be from the pool of auto-assigned IPs (see `rightaddresspool` above). In the example above, you can only assign static IP(s) from the range `192.168.43.1-192.168.43.99`.
**Note:** For Windows 7/8/10/11 and [RouterOS](ikev2-howto.md#routeros) clients, you must use a different syntax for `rightid=`. For example, if the client name is `client1`, set `rightid="CN=client1, O=IKEv2 VPN"` in the example above.
1. **(Important)** Restart the IPsec service:
```
service ipsec restart
```
Client-to-client traffic is allowed by default. If you want to **disallow** client-to-client traffic, run the following commands on the VPN server. Add them to `/etc/rc.local` to persist after reboot.
```
iptables -I FORWARD 2 -i ppp+ -o ppp+ -s 192.168.42.0/24 -d 192.168.42.0/24 -j DROP
iptables -I FORWARD 3 -s 192.168.43.0/24 -d 192.168.43.0/24 -j DROP
iptables -I FORWARD 4 -i ppp+ -d 192.168.43.0/24 -j DROP
iptables -I FORWARD 5 -s 192.168.43.0/24 -o ppp+ -j DROP
```
## Specify VPN server's public IP
On servers with multiple public IP addresses, advanced users can specify a public IP for the VPN server using variable `VPN_PUBLIC_IP`. For example, if the server has IPs `192.0.2.1` and `192.0.2.2`, and you want the VPN server to use `192.0.2.2`:
```
sudo VPN_PUBLIC_IP=192.0.2.2 sh vpn.sh
```
Note that this variable has no effect for IKEv2 mode, if IKEv2 is already set up on the server. In this case, you may remove IKEv2 and set it up again using custom options. Refer to [Set up IKEv2 using helper script](ikev2-howto.md#set-up-ikev2-using-helper-script).
Additional configuration may be required if you want VPN clients to use the specified public IP as their "outgoing IP" when the VPN connection is active, and the specified IP is NOT the main IP (or default route) on the server. In this case, you may need to change IPTables rules on the server. To persist after reboot, you can add these commands to `/etc/rc.local`.
Continuing with the example above, if you want the "outgoing IP" to be `192.0.2.2`:
```
# Get default network interface name
netif=$(ip -4 route list 0/0 | grep -m 1 -Po '(?<=dev )(\S+)')
# Remove MASQUERADE rules
iptables -t nat -D POSTROUTING -s 192.168.43.0/24 -o "$netif" -m policy --dir out --pol none -j MASQUERADE
iptables -t nat -D POSTROUTING -s 192.168.42.0/24 -o "$netif" -j MASQUERADE
# Add SNAT rules
iptables -t nat -I POSTROUTING -s 192.168.43.0/24 -o "$netif" -m policy --dir out --pol none -j SNAT --to 192.0.2.2
iptables -t nat -I POSTROUTING -s 192.168.42.0/24 -o "$netif" -j SNAT --to 192.0.2.2
```
**Note:** The method above only applies if the VPN server's default network interface maps to multiple public IPs. This method may not work if the server has multiple network interfaces, each with a different public IP.
To check the "outgoing IP" for a connected VPN client, you may open a browser on the client and [look up the IP address on Google](https://www.google.com/search?q=my+ip).
## Customize VPN subnets
By default, IPsec/L2TP VPN clients will use internal VPN subnet `192.168.42.0/24`, while IPsec/XAuth ("Cisco IPsec") and IKEv2 VPN clients will use internal VPN subnet `192.168.43.0/24`. For more details, see [Internal VPN IPs and traffic](#internal-vpn-ips-and-traffic).
For most use cases, it is NOT necessary and NOT recommended to customize these subnets. If your use case requires it, however, you may specify custom subnet(s) when installing the VPN.
**Important:** You may only specify custom subnets **during initial VPN install**. If the IPsec VPN is already installed, you **must** first [uninstall the VPN](uninstall.md), then specify custom subnets and re-install. Otherwise, the VPN may stop working.
```
# Example: Specify custom VPN subnet for IPsec/L2TP mode
# Note: All three variables must be specified.
sudo VPN_L2TP_NET=10.1.0.0/16 \
VPN_L2TP_LOCAL=10.1.0.1 \
VPN_L2TP_POOL=10.1.0.10-10.1.254.254 \
sh vpn.sh
```
```
# Example: Specify custom VPN subnet for IPsec/XAuth and IKEv2 modes
# Note: Both variables must be specified.
sudo VPN_XAUTH_NET=10.2.0.0/16 \
VPN_XAUTH_POOL=10.2.0.10-10.2.254.254 \
sh vpn.sh
```
In the examples above, `VPN_L2TP_LOCAL` is the VPN server's internal IP for IPsec/L2TP mode. `VPN_L2TP_POOL` and `VPN_XAUTH_POOL` are the pools of auto-assigned IP addresses for VPN clients.
## IPv6 support
If your VPN server has a public (global unicast) IPv6 address and the requirements below are met, IPv6 support for IKEv2 clients is automatically enabled during VPN setup. No manual configuration is needed.
**Note:** IPv6 support has been 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 over the IKEv2 VPN.
**Note:** For **Windows** clients, you need to run the following commands once in a PowerShell window to route IPv6 traffic through the VPN. Replace `IKEv2 VPN X.X.X.X` with the actual name of your VPN connection. When finished, reconnect to the IKEv2 VPN.
```powershell
Add-VpnConnectionRoute -ConnectionName "IKEv2 VPN X.X.X.X" -DestinationPrefix ::/1
Add-VpnConnectionRoute -ConnectionName "IKEv2 VPN X.X.X.X" -DestinationPrefix 8000::/1
```
When IPv6 is enabled, IKEv2 VPN clients receive both an IPv4 address from the `192.168.43.0/24` pool and an IPv6 address from the `fddd:500:500:500::/64` pool. The VPN server masquerades IPv6 traffic from the client pool through the server's own IPv6 address, giving VPN clients full IPv6 internet access through the tunnel.
**Requirements:**
- The VPN server must have a routable global unicast IPv6 address (i.e., an address starting with `2` or `3`). Link-local (`fe80::/10`) and ULA (`fc00::/7`) addresses are not sufficient.
- Libreswan 5.0 or newer (the VPN setup scripts use 5.x by default).
- IPv6 is only supported for **IKEv2 mode**. IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes do not support IPv6.
To verify that IPv6 is working, connect to the VPN using IKEv2 and check your IPv6 address, e.g. using [test-ipv6.com](https://test-ipv6.com).
You may optionally specify a custom IPv6 pool subnet when installing the VPN. The subnet must be a `/64` from the ULA range (`fddd::/16` is recommended).
```
# Example: Specify custom IPv6 pool subnet for IKEv2 mode
sudo VPN_IP6_NET=fddd:1234:5678:9012::/64 \
sh vpn.sh
```
**Note:** The `VPN_IP6_NET` variable may only be specified during initial VPN install.
## Port forwarding to VPN clients
In certain circumstances, you may want to forward port(s) on the VPN server to a connected VPN client. This can be done by adding IPTables rules on the VPN server.
**Warning:** Port forwarding will expose port(s) on the VPN client to the entire Internet, which could be a **security risk**! This is NOT recommended, unless your use case requires it.
**Note:** The internal VPN IPs assigned to VPN clients are dynamic, and firewalls on client devices may block forwarded traffic. To assign static IPs to VPN clients, see [Internal VPN IPs and traffic](#internal-vpn-ips-and-traffic). To check which IP is assigned to a client, view the connection status on the VPN client.
Example 1: Forward TCP port 443 on the VPN server to the IPsec/L2TP client at `192.168.42.10`.
```
# Get default network interface name
netif=$(ip -4 route list 0/0 | grep -m 1 -Po '(?<=dev )(\S+)')
iptables -I FORWARD 2 -i "$netif" -o ppp+ -p tcp --dport 443 -j ACCEPT
iptables -t nat -A PREROUTING -i "$netif" -p tcp --dport 443 -j DNAT --to 192.168.42.10
```
Example 2: Forward UDP port 123 on the VPN server to the IKEv2 (or IPsec/XAuth) client at `192.168.43.10`.
```
# Get default network interface name
netif=$(ip -4 route list 0/0 | grep -m 1 -Po '(?<=dev )(\S+)')
iptables -I FORWARD 2 -i "$netif" -d 192.168.43.0/24 -p udp --dport 123 -j ACCEPT
iptables -t nat -A PREROUTING -i "$netif" ! -s 192.168.43.0/24 -p udp --dport 123 -j DNAT --to 192.168.43.10
```
If you want the rules to persist after reboot, you may add these commands to `/etc/rc.local`. To remove the added IPTables rules, run the commands again, but replace `-I FORWARD 2` with `-D FORWARD`, and replace `-A PREROUTING` with `-D PREROUTING`.
## Split tunneling
With split tunneling, VPN clients will only send traffic for specific destination subnet(s) through the VPN tunnel. Other traffic will NOT go through the VPN tunnel. This allows you to gain secure access to a network through your VPN, without routing all your client's traffic through the VPN. Split tunneling has some limitations, and is not supported by all VPN clients.
Advanced users can optionally enable split tunneling for the [IPsec/XAuth ("Cisco IPsec")](clients-xauth.md) and/or [IKEv2](ikev2-howto.md) modes. Expand for details. IPsec/L2TP mode does not support this feature (except on Windows, see below).
IPsec/XAuth ("Cisco IPsec") mode: Enable split tunneling
The example below **ONLY** applies to IPsec/XAuth ("Cisco IPsec") mode. Commands must be run as `root`.
1. Edit `/etc/ipsec.conf` on the VPN server. In the section `conn xauth-psk`, replace `leftsubnet=0.0.0.0/0` with the subnet(s) you want VPN clients to send traffic through the VPN tunnel. For example:
For a single subnet:
```
leftsubnet=10.123.123.0/24
```
For multiple subnets (use `leftsubnets` instead):
```
leftsubnets="10.123.123.0/24,10.100.0.0/16"
```
1. **(Important)** Restart the IPsec service:
```
service ipsec restart
```
IKEv2 mode: Enable split tunneling
The example below **ONLY** applies to IKEv2 mode. Commands must be run as `root`.
1. Edit `/etc/ipsec.d/ikev2.conf` on the VPN server. In the section `conn ikev2-cp`, replace `leftsubnet=0.0.0.0/0` with the subnet(s) you want VPN clients to send traffic through the VPN tunnel. For example:
For a single subnet:
```
leftsubnet=10.123.123.0/24
```
For multiple subnets (use `leftsubnets` instead):
```
leftsubnets="10.123.123.0/24,10.100.0.0/16"
```
1. **(Important)** Restart the IPsec service:
```
service ipsec restart
```
**Note:** Advanced users can set a different split tunneling configuration for specific IKEv2 client(s). Refer to section [Internal VPN IPs and traffic](#internal-vpn-ips-and-traffic) and expand "IKEv2 mode: Assign static IPs to VPN clients". Based on the example in that section, you may add the `leftsubnet=...` option to the `conn` section of the specific IKEv2 client, then restart the IPsec service.
Alternatively, Windows users can enable split tunneling by manually adding routes:
1. Right-click on the wireless/network icon in your system tray.
1. **Windows 11:** Select **Network and Internet settings**, then on the page that opens, click **Advanced network settings**. Click **More network adapter options**.
**Windows 10:** Select **Open Network & Internet settings**, then on the page that opens, click **Network and Sharing Center**. On the left, click **Change adapter settings**.
**Windows 8/7:** Select **Open Network and Sharing Center**. On the left, click **Change adapter settings**.
1. Right-click on the new VPN connection, and choose **Properties**.
1. Click the **Network** tab. Select **Internet Protocol Version 4 (TCP/IPv4)**, then click **Properties**.
1. Click **Advanced**. Uncheck **Use default gateway on remote network**.
1. Click **OK** to close the **Properties** window.
1. **(Important)** Disconnect the VPN, then re-connect.
1. Assume that the subnet you want VPN clients to send traffic through the VPN tunnel is `10.123.123.0/24`. Open an [elevated command prompt](http://www.winhelponline.com/blog/open-elevated-command-prompt-windows/) and run one of the following commands:
For IKEv2 and IPsec/XAuth ("Cisco IPsec") modes:
```
route add -p 10.123.123.0 mask 255.255.255.0 192.168.43.1
```
For IPsec/L2TP mode:
```
route add -p 10.123.123.0 mask 255.255.255.0 192.168.42.1
```
1. When finished, VPN clients will send traffic through the VPN tunnel for the specified subnet only. Other traffic will bypass the VPN.
## Access VPN server's subnet
After connecting to the VPN, VPN clients can generally access services running on other devices that are within the same local subnet as the VPN server, without additional configuration. For example, if the VPN server's local subnet is `192.168.0.0/24`, and an Nginx server is running on IP `192.168.0.2`, VPN clients can use IP `192.168.0.2` to access the Nginx server.
Please note, additional configuration is required if the VPN server has multiple network interfaces (e.g. `eth0` and `eth1`), and you want VPN clients to access the local subnet behind the network interface that is NOT for Internet access. In this scenario, you must run the following commands to add IPTables rules. To persist after reboot, you may add these commands to `/etc/rc.local`.
```bash
# Replace eth1 with the name of the network interface
# on the VPN server that you want VPN clients to access
netif=eth1
iptables -I FORWARD 2 -i "$netif" -o ppp+ -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I FORWARD 2 -i ppp+ -o "$netif" -j ACCEPT
iptables -I FORWARD 2 -i "$netif" -d 192.168.43.0/24 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I FORWARD 2 -s 192.168.43.0/24 -o "$netif" -j ACCEPT
iptables -t nat -I POSTROUTING -s 192.168.43.0/24 -o "$netif" -m policy --dir out --pol none -j MASQUERADE
iptables -t nat -I POSTROUTING -s 192.168.42.0/24 -o "$netif" -j MASQUERADE
```
## Access VPN clients from server's subnet
In certain circumstances, you may need to access services on VPN clients from other devices that are on the same local subnet as the VPN server. This can be done using the following steps.
Assume that the VPN server IP is `10.1.0.2`, and the IP of the device from which you want to access VPN clients is `10.1.0.3`.
1. Add IPTables rules on the VPN server to allow this traffic. For example:
```
# Get default network interface name
netif=$(ip -4 route list 0/0 | grep -m 1 -Po '(?<=dev )(\S+)')
iptables -I FORWARD 2 -i "$netif" -o ppp+ -s 10.1.0.3 -j ACCEPT
iptables -I FORWARD 2 -i "$netif" -d 192.168.43.0/24 -s 10.1.0.3 -j ACCEPT
```
2. Add routing rules on the device you want to access VPN clients. For example:
```
# Replace eth0 with the network interface name of the device's local subnet
route add -net 192.168.42.0 netmask 255.255.255.0 gw 10.1.0.2 dev eth0
route add -net 192.168.43.0 netmask 255.255.255.0 gw 10.1.0.2 dev eth0
```
Learn more about internal VPN IPs in [Internal VPN IPs and traffic](#internal-vpn-ips-and-traffic).
## Modify IPTables rules
If you want to modify IPTables rules after install, edit `/etc/iptables.rules` and/or `/etc/iptables/rules.v4` (Ubuntu/Debian), or `/etc/sysconfig/iptables` (CentOS/RHEL). Then reboot your server.
If [IPv6 support](#ipv6-support) is enabled, the corresponding ip6tables rules are saved in `/etc/ip6tables.rules` and `/etc/iptables/rules.v6` (Ubuntu/Debian), or `/etc/sysconfig/ip6tables` (CentOS/RHEL).
**Note:** If your server runs CentOS Linux (or similar), and firewalld was active during VPN setup, nftables may be configured. In this case, edit `/etc/sysconfig/nftables.conf` instead of `/etc/sysconfig/iptables`.
## Deploy Google BBR congestion control
After the VPN server is set up, the performance can be improved by deploying the Google BBR congestion control algorithm.
This is usually done by modifying the configuration file `/etc/sysctl.conf`. However, some Linux distributions may additionally require updates to the Linux kernel.
For detailed deployment methods, please refer to [this document](bbr.md).
## License
Copyright (C) 2021-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
[](http://creativecommons.org/licenses/by-sa/3.0/)
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!
================================================
FILE: docs/bbr-zh.md
================================================
[English](bbr.md) | [中文](bbr-zh.md)
# 高级用法:部署 Google BBR 拥塞控制算法
Google BBR是一种拥塞控制算法,它能够显著提升服务器吞吐率并降低延迟。
Google BBR已经被内置于Linux内核4.9及更高版本中,但是需要手动开启。
关于Google BBR算法,可以在这篇[官方博客](https://cloud.google.com/blog/products/networking/tcp-bbr-congestion-control-comes-to-gcp-your-internet-just-got-faster)或者这个[官方库](https://github.com/google/bbr)中找到更多信息。
## 准备
可以通过命令 `uname -r` 来查看当前Linux内核版本。版本大于等于4.9时,可以直接参照[下方的说明](#部署-google-bbr)部署BBR。
通常而言,Ubuntu 18.04+, Debian 10+,CentOS 8+及RHEL 8+的内核版本都大于4.9。但是对于Amazon Linux 2,需要通过以下的方式更新内核之后才能部署Google BBR。
### Amazon Linux 2
Amazon Linux 2提供过经过验证的新版Linux内核,并可以通过启用预置的Extras库安装。
1. 从Extras库安装 `kernel-ng`
```bash
sudo amazon-linux-extras install kernel-ng
```
2. 更新包
```bash
sudo yum update
```
3. 重启系统
```bash
sudo reboot
```
4. 检查Linux内核版本
```bash
uname -r
```
## 部署 Google BBR
在这个部分,我们将通过修改配置文件启动Google BBR。
1. 备份 `/etc/sysctl.conf`
```bash
sudo cp /etc/sysctl.conf /etc/sysctl.conf.backup
```
2. 修改 `/etc/sysctl.conf`
```bash
sudo vim /etc/sysctl.conf
```
在文件中增加以下行
```
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
```
3. 启用Google BBR
首先使用 `uname -r` 检查你的服务器的内核版本。
对于内核版本 >= 4.20,应用 `sysctl` 设置:
```bash
sudo sysctl -p
```
对于内核版本 < 4.20,你必须重启服务器:
```bash
sudo reboot
```
4. 检查Google BBR状态
```bash
sudo sysctl net.ipv4.tcp_available_congestion_control
# net.ipv4.tcp_available_congestion_control = reno cubic bbr
sudo sysctl -n net.ipv4.tcp_congestion_control
# bbr
lsmod | grep bbr
# tcp_bbr 16384 0
```
## 文档作者
版权所有 (C) 2022 [Leo Liu](https://github.com/optimusleobear)
================================================
FILE: docs/bbr.md
================================================
[English](bbr.md) | [中文](bbr-zh.md)
# Advanced usage: Deploy Google BBR congestion control algorithm
Google BBR is a congestion control algorithm that could significantly increase server throughput and reduce latency.
Google BBR has been built into Linux kernel 4.9 and higher, but needs to be manually turned on.
To learn more about the Google BBR algorithm, see this [official blog](https://cloud.google.com/blog/products/networking/tcp-bbr-congestion-control-comes-to-gcp-your-internet-just-got-faster) or this [official repository](https://github.com/google/bbr).
## Prepare
You can check the current Linux kernel version with the command `uname -r`. When the version is greater than or equal to 4.9, you can deploy BBR directly by referring to the [instructions below](#deploy-google-bbr).
Generally speaking, the kernel versions of Ubuntu 18.04+, Debian 10+, CentOS 8+ and RHEL 8+ are greater than 4.9. But for Amazon Linux 2, you need to update the kernel in the following ways before deploying Google BBR.
### Amazon Linux 2
Amazon Linux 2 provides newer versions of the verified Linux kernel, which can be installed from the Extras repository.
1. Install `kernel-ng` from the Extras repository
```bash
sudo amazon-linux-extras install kernel-ng
```
2. Update packages
```bash
sudo yum update
```
3. Restart the system
```bash
sudo reboot
```
4. Check the Linux kernel version
```bash
uname -r
```
## Deploy Google BBR
In this section, we will start Google BBR by modifying the configuration file.
1. Backup `/etc/sysctl.conf`
```bash
sudo cp /etc/sysctl.conf /etc/sysctl.conf.backup
```
2. Modify `/etc/sysctl.conf`
```bash
sudo vim /etc/sysctl.conf
```
Add the following lines to the file
```
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
```
3. Enable Google BBR
First, check your server's kernel version using `uname -r`.
For kernel versions >= 4.20, apply `sysctl` settings:
```bash
sudo sysctl -p
```
For kernel versions < 4.20, you must reboot the server:
```bash
sudo reboot
```
4. Check Google BBR status
```bash
sudo sysctl net.ipv4.tcp_available_congestion_control
# net.ipv4.tcp_available_congestion_control = reno cubic bbr
sudo sysctl -n net.ipv4.tcp_congestion_control
# bbr
lsmod | grep bbr
# tcp_bbr 16384 0
```
## Document author
Copyright (C) 2022 [Leo Liu](https://github.com/optimusleobear)
Translated by [Lin Song](https://github.com/hwdsl2)
================================================
FILE: docs/clients-xauth-zh.md
================================================
[English](clients-xauth.md) | [中文](clients-xauth-zh.md)
# 配置 IPsec/XAuth VPN 客户端
在成功[搭建自己的 VPN 服务器](../README-zh.md)之后,按照下面的步骤来配置你的设备。IPsec/XAuth ("Cisco IPsec") 在 Android, iOS 和 OS X 上均受支持,无需安装额外的软件。Windows 用户可以使用免费的 [Shrew Soft 客户端](https://www.shrew.net/download/vpn)。如果无法连接,请首先检查是否输入了正确的 VPN 登录凭证。
IPsec/XAuth 模式也称为 "Cisco IPsec"。该模式通常能够比 IPsec/L2TP **更高效**地传输数据(较低的额外开销)。
---
* 平台名称
* [Windows](#windows)
* [OS X (macOS)](#os-x-macos)
* [Android](#android)
* [iOS (iPhone/iPad)](#ios)
* [Linux](#linux)
## Windows
> 你也可以使用 [IKEv2](ikev2-howto-zh.md)(推荐)或者 [IPsec/L2TP](clients-zh.md) 模式连接。无需安装额外的软件。
1. 下载并安装免费的 [Shrew Soft VPN 客户端](https://www.shrew.net/download/vpn)。在安装时请选择 **Standard Edition**。
**注:** 该 VPN 客户端 **不支持** Windows 10/11。
1. 单击开始菜单 -> 所有程序 -> ShrewSoft VPN Client -> VPN Access Manager
1. 单击工具栏中的 **Add (+)** 按钮。
1. 在 **Host Name or IP Address** 字段中输入`你的 VPN 服务器 IP`。
1. 单击 **Authentication** 选项卡,从 **Authentication Method** 下拉菜单中选择 **Mutual PSK + XAuth**。
1. 在 **Local Identity** 子选项卡中,从 **Identification Type** 下拉菜单中选择 **IP Address**。
1. 单击 **Credentials** 子选项卡,并在 **Pre Shared Key** 字段中输入`你的 VPN IPsec PSK`。
1. 单击 **Phase 1** 选项卡,从 **Exchange Type** 下拉菜单中选择 **main**。
1. 单击 **Phase 2** 选项卡,从 **HMAC Algorithm** 下拉菜单中选择 **sha1**。
1. 单击 **Save** 保存 VPN 连接的详细信息。
1. 选择新添加的 VPN 连接。单击工具栏中的 **Connect** 按钮。
1. 在 **Username** 字段中输入`你的 VPN 用户名`。
1. 在 **Password** 字段中输入`你的 VPN 密码`。
1. 单击 **Connect**。
连接成功后,你会在 VPN Connect 状态窗口中看到 **tunnel enabled** 字样。单击 "Network" 选项卡,并确认 **Established - 1** 显示在 "Security Associations" 下面。最后你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](clients-zh.md#ikev1-故障排除)。
## OS X (macOS)
### macOS 13 (Ventura) 及以上
> 你也可以使用 [IKEv2](ikev2-howto-zh.md)(推荐)或者 [IPsec/L2TP](clients-zh.md) 模式连接。
1. 打开系统设置并转到网络部分。
1. 在窗口右方单击 **VPN**。
1. 从 **添加VPN配置** 下拉菜单选择 **Cisco IPSec**。
1. 在打开的窗口中的 **显示名称** 字段中输入任意内容。
1. 在 **服务器地址** 字段中输入`你的 VPN 服务器 IP`。
1. 在 **帐户名称** 字段中输入`你的 VPN 用户名`。
1. 在 **密码** 字段中输入`你的 VPN 密码`。
1. 从 **类型** 下拉菜单选择 **共享密钥**。
1. 在 **共享密钥** 字段中输入`你的 VPN IPsec PSK`。
1. 保持 **群组名称** 字段空白。
1. 单击 **创建** 保存 VPN 连接信息。
1. 如果要在菜单栏显示 VPN 状态并快速访问相关设置,你可以转到系统设置的控制中心部分,滚动到页面底部并在 **VPN** 下拉菜单选择 **在菜单栏中显示**。
要连接到 VPN:使用菜单栏中的图标,或者打开系统设置的 **VPN** 部分并启用 VPN 连接。最后你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](clients-zh.md#ikev1-故障排除)。
### macOS 12 (Monterey) 及以下
> 你也可以使用 [IKEv2](ikev2-howto-zh.md)(推荐)或者 [IPsec/L2TP](clients-zh.md) 模式连接。
1. 打开系统偏好设置并转到网络部分。
1. 在窗口左下角单击 **+** 按钮。
1. 从 **接口** 下拉菜单选择 **VPN**。
1. 从 **VPN类型** 下拉菜单选择 **Cisco IPSec**。
1. 在 **服务名称** 字段中输入任意内容。
1. 单击 **创建**。
1. 在 **服务器地址** 字段中输入`你的 VPN 服务器 IP`。
1. 在 **帐户名称** 字段中输入`你的 VPN 用户名`。
1. 在 **密码** 字段中输入`你的 VPN 密码`。
1. 单击 **认证设置** 按钮。
1. 在 **机器认证** 部分,选择 **共享的密钥** 单选按钮,然后输入`你的 VPN IPsec PSK`。
1. 保持 **群组名称** 字段空白。
1. 单击 **好**。
1. 选中 **在菜单栏中显示 VPN 状态** 复选框。
1. 单击 **应用** 保存 VPN 连接信息。
要连接到 VPN:使用菜单栏中的图标,或者打开系统偏好设置的网络部分,选择 VPN 并单击 **连接**。最后你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](clients-zh.md#ikev1-故障排除)。
## Android
**重要:** Android 用户应该使用更安全的 [IKEv2 模式](ikev2-howto-zh.md)连接(推荐)。Android 12+ 仅支持 IKEv2 模式。Android 系统自带的 VPN 客户端对 IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式使用安全性较低的 `modp1024` (DH group 2)。
如果你仍然想用 IPsec/XAuth 模式连接,你必须首先编辑 VPN 服务器上的 `/etc/ipsec.conf` 并在 `ike=...` 一行的末尾加上 `,aes256-sha2;modp1024,aes128-sha1;modp1024` 字样。保存文件并运行 `service ipsec restart`。
Docker 用户:在[你的 env 文件](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh.md#如何使用本镜像)中添加 `VPN_ENABLE_MODP1024=yes`,然后重新创建 Docker 容器。
然后在你的 Android 设备上进行以下步骤:
1. 启动 **设置** 应用程序。
1. 单击 **网络和互联网**。或者,如果你使用 Android 7 或更早版本,在 **无线和网络** 部分单击 **更多...**。
1. 单击 **VPN**。
1. 单击 **添加VPN配置文件** 或窗口右上角的 **+**。
1. 在 **名称** 字段中输入任意内容。
1. 在 **类型** 下拉菜单选择 **IPSec Xauth PSK**。
1. 在 **服务器地址** 字段中输入`你的 VPN 服务器 IP`。
1. 保持 **IPSec 标识符** 字段空白。
1. 在 **IPSec 预共享密钥** 字段中输入`你的 VPN IPsec PSK`。
1. 单击 **保存**。
1. 单击新的VPN连接。
1. 在 **用户名** 字段中输入`你的 VPN 用户名`。
1. 在 **密码** 字段中输入`你的 VPN 密码`。
1. 选中 **保存帐户信息** 复选框。
1. 单击 **连接**。
连接成功后,会在通知栏显示图标。最后你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](clients-zh.md#ikev1-故障排除)。
## iOS
> 你也可以使用 [IKEv2](ikev2-howto-zh.md)(推荐)或者 [IPsec/L2TP](clients-zh.md) 模式连接。
1. 进入设置 -> 通用 -> VPN。
1. 单击 **添加VPN配置...**。
1. 单击 **类型** 。选择 **IPSec** 并返回。
1. 在 **描述** 字段中输入任意内容。
1. 在 **服务器** 字段中输入`你的 VPN 服务器 IP`。
1. 在 **帐户** 字段中输入`你的 VPN 用户名`。
1. 在 **密码** 字段中输入`你的 VPN 密码`。
1. 保持 **群组名称** 字段空白。
1. 在 **密钥** 字段中输入`你的 VPN IPsec PSK`。
1. 单击右上角的 **完成**。
1. 启用 **VPN** 连接。
连接成功后,会在通知栏显示图标。最后你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](clients-zh.md#ikev1-故障排除)。
## Linux
> 你也可以使用 [IKEv2](ikev2-howto-zh.md) 模式连接(推荐)。
### Fedora 和 CentOS
Fedora 28 (和更新版本)和 CentOS 8/7 用户可以使用 `yum` 安装 `NetworkManager-libreswan-gnome` 软件包,然后通过 GUI 配置 IPsec/XAuth VPN 客户端。
1. 进入 Settings -> Network -> VPN。单击 **+** 按钮。
1. 选择 **IPsec based VPN**。
1. 在 **Name** 字段中输入任意内容。
1. 在 **Gateway** 字段中输入`你的 VPN 服务器 IP`。
1. 在 **Type** 下拉菜单选择 **IKEv1 (XAUTH)**。
1. 在 **User name** 字段中输入`你的 VPN 用户名`。
1. 右键单击 **User password** 字段中的 **?**,选择 **Store the password only for this user**。
1. 在 **User password** 字段中输入`你的 VPN 密码`。
1. 保持 **Group name** 字段空白。
1. 右键单击 **Secret** 字段中的 **?**,选择 **Store the password only for this user**。
1. 在 **Secret** 字段中输入`你的 VPN IPsec PSK`。
1. 保持 **Remote ID** 字段空白。
1. 单击 **Add** 保存 VPN 连接信息。
1. 启用 **VPN** 连接。
连接成功后,你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
### 其它 Linux
其它 Linux 版本用户可以使用 [IPsec/L2TP](clients-zh.md#linux) 模式连接。
## 授权协议
注: 这个协议仅适用于本文档。
版权所有 (C) 2016-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
受到 [Joshua Lund 的工作](https://github.com/StreisandEffect/streisand/blob/6aa6b6b2735dd829ca8c417d72eb2768a89b6639/playbooks/roles/l2tp-ipsec/templates/instructions.md.j2)的启发
本程序为自由软件,在自由软件联盟发布的[ GNU 通用公共许可协议](https://www.gnu.org/licenses/gpl.html)的约束下,你可以对其进行再发布及修改。协议版本为第三版或(随你)更新的版本。
我们希望发布的这款程序有用,但不保证,甚至不保证它有经济价值和适合特定用途。详情参见GNU通用公共许可协议。
================================================
FILE: docs/clients-xauth.md
================================================
[English](clients-xauth.md) | [中文](clients-xauth-zh.md)
# Configure IPsec/XAuth VPN Clients
After [setting up your own VPN server](https://github.com/hwdsl2/setup-ipsec-vpn), follow these steps to configure your devices. IPsec/XAuth ("Cisco IPsec") is natively supported by Android, iOS and OS X. There is no additional software to install. Windows users can use the free [Shrew Soft client](https://www.shrew.net/download/vpn). In case you are unable to connect, first check to make sure the VPN credentials were entered correctly.
IPsec/XAuth mode is also called "Cisco IPsec". This mode is generally **faster than** IPsec/L2TP with less overhead.
---
* Platforms
* [Windows](#windows)
* [OS X (macOS)](#os-x-macos)
* [Android](#android)
* [iOS (iPhone/iPad)](#ios)
* [Linux](#linux)
## Windows
> You may also connect using [IKEv2](ikev2-howto.md) (recommended) or [IPsec/L2TP](clients.md) mode. No additional software is required.
1. Download and install the free [Shrew Soft VPN client](https://www.shrew.net/download/vpn). When prompted during install, select **Standard Edition**.
**Note:** This VPN client does NOT support Windows 10/11.
1. Click Start Menu -> All Programs -> ShrewSoft VPN Client -> VPN Access Manager
1. Click the **Add (+)** button on toolbar.
1. Enter `Your VPN Server IP` in the **Host Name or IP Address** field.
1. Click the **Authentication** tab. Select **Mutual PSK + XAuth** from the **Authentication Method** drop-down menu.
1. Under the **Local Identity** sub-tab, select **IP Address** from the **Identification Type** drop-down menu.
1. Click the **Credentials** sub-tab. Enter `Your VPN IPsec PSK` in the **Pre Shared Key** field.
1. Click the **Phase 1** tab. Select **main** from the **Exchange Type** drop-down menu.
1. Click the **Phase 2** tab. Select **sha1** from the **HMAC Algorithm** drop-down menu.
1. Click **Save** to save the VPN connection details.
1. Select the new VPN connection. Click the **Connect** button on toolbar.
1. Enter `Your VPN Username` in the **Username** field.
1. Enter `Your VPN Password` in the **Password** field.
1. Click **Connect**.
Once connected, you will see **tunnel enabled** in the VPN Connect status window. Click the "Network" tab, and confirm that **Established - 1** is displayed under "Security Associations". You can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](clients.md#ikev1-troubleshooting).
## OS X (macOS)
### macOS 13 (Ventura) and newer
> You may also connect using [IKEv2](ikev2-howto.md) (recommended) or [IPsec/L2TP](clients.md) mode.
1. Open **System Settings** and go to the **Network** section.
1. Click **VPN** on the right hand side of the window.
1. Click the **Add VPN Configuration** drop-down menu and select **Cisco IPSec**.
1. In the window that opens, enter anything you like for the **Display name**.
1. Enter `Your VPN Server IP` for the **Server address**.
1. Enter `Your VPN Username` for the **Account name**.
1. Enter `Your VPN Password` for the **Password**.
1. Select **Shared secret** from the **Type** drop-down menu.
1. Enter `Your VPN IPsec PSK` for the **Shared secret**.
1. Leave the **Group name** field blank.
1. Click **Create** to save the VPN configuration.
1. To show VPN status in your menu bar and for shortcut access, go to the **Control Center** section of **System Settings**. Scroll to the bottom and select `Show in Menu Bar` from the **VPN** drop-down menu.
To connect to the VPN: Use the menu bar icon, or go to the **VPN** section of **System Settings** and toggle the switch for your VPN configuration. You can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](clients.md#ikev1-troubleshooting).
### macOS 12 (Monterey) and older
> You may also connect using [IKEv2](ikev2-howto.md) (recommended) or [IPsec/L2TP](clients.md) mode.
1. Open System Preferences and go to the Network section.
1. Click the **+** button in the lower-left corner of the window.
1. Select **VPN** from the **Interface** drop-down menu.
1. Select **Cisco IPSec** from the **VPN Type** drop-down menu.
1. Enter anything you like for the **Service Name**.
1. Click **Create**.
1. Enter `Your VPN Server IP` for the **Server Address**.
1. Enter `Your VPN Username` for the **Account Name**.
1. Enter `Your VPN Password` for the **Password**.
1. Click the **Authentication Settings** button.
1. In the **Machine Authentication** section, select the **Shared Secret** radio button and enter `Your VPN IPsec PSK`.
1. Leave the **Group Name** field blank.
1. Click **OK**.
1. Check the **Show VPN status in menu bar** checkbox.
1. Click **Apply** to save the VPN connection information.
To connect to the VPN: Use the menu bar icon, or go to the Network section of System Preferences, select the VPN and choose **Connect**. You can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](clients.md#ikev1-troubleshooting).
## Android
**Important:** Android users should instead connect using [IKEv2 mode](ikev2-howto.md) (recommended), which is more secure. Android 12+ only supports IKEv2 mode. The native VPN client in Android uses the less secure `modp1024` (DH group 2) for the IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes.
If you still want to connect using IPsec/XAuth mode, you must first edit `/etc/ipsec.conf` on the VPN server. Find the line `ike=...` and append `,aes256-sha2;modp1024,aes128-sha1;modp1024` at the end. Save the file and run `service ipsec restart`.
Docker users: Add `VPN_ENABLE_MODP1024=yes` to [your env file](https://github.com/hwdsl2/docker-ipsec-vpn-server#how-to-use-this-image), then re-create the Docker container.
After that, follow the steps below on your Android device:
1. Launch the **Settings** application.
1. Tap "Network & internet". Or, if using Android 7 or earlier, tap **More...** in the **Wireless & networks** section.
1. Tap **VPN**.
1. Tap **Add VPN Profile** or the **+** icon at top-right of screen.
1. Enter anything you like in the **Name** field.
1. Select **IPSec Xauth PSK** in the **Type** drop-down menu.
1. Enter `Your VPN Server IP` in the **Server address** field.
1. Leave the **IPSec identifier** field blank.
1. Enter `Your VPN IPsec PSK` in the **IPSec pre-shared key** field.
1. Tap **Save**.
1. Tap the new VPN connection.
1. Enter `Your VPN Username` in the **Username** field.
1. Enter `Your VPN Password` in the **Password** field.
1. Check the **Save account information** checkbox.
1. Tap **Connect**.
Once connected, you will see a VPN icon in the notification bar. You can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](clients.md#ikev1-troubleshooting).
## iOS
> You may also connect using [IKEv2](ikev2-howto.md) (recommended) or [IPsec/L2TP](clients.md) mode.
1. Go to Settings -> General -> VPN.
1. Tap **Add VPN Configuration...**.
1. Tap **Type**. Select **IPSec** and go back.
1. Tap **Description** and enter anything you like.
1. Tap **Server** and enter `Your VPN Server IP`.
1. Tap **Account** and enter `Your VPN Username`.
1. Tap **Password** and enter `Your VPN Password`.
1. Leave the **Group Name** field blank.
1. Tap **Secret** and enter `Your VPN IPsec PSK`.
1. Tap **Done**.
1. Slide the **VPN** switch ON.
Once connected, you will see a VPN icon in the status bar. You can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](clients.md#ikev1-troubleshooting).
## Linux
> You may also connect using [IKEv2](ikev2-howto.md) mode (recommended).
### Fedora and CentOS
Fedora 28 (and newer) and CentOS 8/7 users can install the `NetworkManager-libreswan-gnome` package using `yum`, then configure the IPsec/XAuth VPN client using the GUI.
1. Go to Settings -> Network -> VPN. Click the **+** button.
1. Select **IPsec based VPN**.
1. Enter anything you like in the **Name** field.
1. Enter `Your VPN Server IP` for the **Gateway**.
1. Select **IKEv1 (XAUTH)** in the **Type** drop-down menu.
1. Enter `Your VPN Username` for the **User name**.
1. Right-click the **?** in the **User password** field, select **Store the password only for this user**.
1. Enter `Your VPN Password` for the **User password**.
1. Leave the **Group name** field blank.
1. Right-click the **?** in the **Secret** field, select **Store the password only for this user**.
1. Enter `Your VPN IPsec PSK` for the **Secret**.
1. Leave the **Remote ID** field blank.
1. Click **Add** to save the VPN connection information.
1. Turn the **VPN** switch ON.
Once connected, you can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
### Other Linux
Other Linux users can connect using [IPsec/L2TP](clients.md#linux) mode.
## License
Note: This license applies to this document only.
Copyright (C) 2016-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
Inspired by [the work of Joshua Lund](https://github.com/StreisandEffect/streisand/blob/6aa6b6b2735dd829ca8c417d72eb2768a89b6639/playbooks/roles/l2tp-ipsec/templates/instructions.md.j2)
This program is free software: you can redistribute it and/or modify it under the terms of the [GNU General Public License](https://www.gnu.org/licenses/gpl.html) as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
================================================
FILE: docs/clients-zh.md
================================================
[English](clients.md) | [中文](clients-zh.md)
# 配置 IPsec/L2TP VPN 客户端
在成功[搭建自己的 VPN 服务器](../README-zh.md)之后,按照下面的步骤来配置你的设备。IPsec/L2TP 在 Android, iOS, OS X 和 Windows 上均受支持,无需安装额外的软件。设置过程通常只需要几分钟。如果无法连接,请首先检查是否输入了正确的 VPN 登录凭证。
---
* 平台名称
* [Windows](#windows)
* [OS X (macOS)](#os-x-macos)
* [Android](#android)
* [iOS (iPhone/iPad)](#ios)
* [Chrome OS (Chromebook)](#chrome-os)
* [Linux](#linux)
* [IKEv1 故障排除](#ikev1-故障排除)
## Windows
> 你也可以使用 [IKEv2](ikev2-howto-zh.md) 模式连接(推荐)。
### Windows 11
1. 右键单击系统托盘中的无线/网络图标。
1. 选择 **网络和 Internet 设置**,然后在打开的页面中单击 **VPN**。
1. 单击 **添加 VPN** 按钮。
1. 从 **VPN 提供商** 下拉菜单选择 **Windows (内置)**。
1. 在 **连接名称** 字段中输入任意内容。
1. 在 **服务器名称或地址** 字段中输入`你的 VPN 服务器 IP`。
1. 从 **VPN 类型** 下拉菜单选择 **使用预共享密钥的 L2TP/IPsec**。
1. 在 **预共享密钥** 字段中输入`你的 VPN IPsec PSK`。
1. 在 **用户名** 字段中输入`你的 VPN 用户名`。
1. 在 **密码** 字段中输入`你的 VPN 密码`。
1. 选中 **记住我的登录信息** 复选框。
1. 单击 **保存** 保存 VPN 连接的详细信息。
**注:** 在首次连接之前需要[修改一次注册表](#windows-错误-809),以解决 VPN 服务器 和/或 客户端与 NAT (比如家用路由器)的兼容问题。
要连接到 VPN:单击 **连接** 按钮,或者单击系统托盘中的无线/网络图标,单击 **VPN**,然后选择新的 VPN 连接并单击 **连接**。如果出现提示,在登录窗口中输入 `你的 VPN 用户名` 和 `密码` ,并单击 **确定**。最后你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](#ikev1-故障排除)。
### Windows 10 and 8
1. 右键单击系统托盘中的无线/网络图标。
1. 选择 **打开"网络和 Internet"设置**,然后在打开的页面中单击 **网络和共享中心**。
1. 单击 **设置新的连接或网络**。
1. 选择 **连接到工作区**,然后单击 **下一步**。
1. 单击 **使用我的Internet连接 (VPN)**。
1. 在 **Internet地址** 字段中输入`你的 VPN 服务器 IP`。
1. 在 **目标名称** 字段中输入任意内容。单击 **创建**。
1. 返回 **网络和共享中心**。单击左侧的 **更改适配器设置**。
1. 右键单击新创建的 VPN 连接,并选择 **属性**。
1. 单击 **安全** 选项卡,从 **VPN 类型** 下拉菜单中选择 "使用 IPsec 的第 2 层隧道协议 (L2TP/IPSec)"。
1. 单击 **允许使用这些协议**。选中 "质询握手身份验证协议 (CHAP)" 和 "Microsoft CHAP 版本 2 (MS-CHAP v2)" 复选框。
1. 单击 **高级设置** 按钮。
1. 单击 **使用预共享密钥作身份验证** 并在 **密钥** 字段中输入`你的 VPN IPsec PSK`。
1. 单击 **确定** 关闭 **高级设置**。
1. 单击 **确定** 保存 VPN 连接的详细信息。
**注:** 在首次连接之前需要[修改一次注册表](#windows-错误-809),以解决 VPN 服务器 和/或 客户端与 NAT (比如家用路由器)的兼容问题。
要连接到 VPN:单击系统托盘中的无线/网络图标,选择新的 VPN 连接,然后单击 **连接**。如果出现提示,在登录窗口中输入 `你的 VPN 用户名` 和 `密码` ,并单击 **确定**。最后你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](#ikev1-故障排除)。
另外,除了按照以上步骤操作,你也可以运行下面的 Windows PowerShell 命令来创建 VPN 连接。将 `你的 VPN 服务器 IP` 和 `你的 VPN IPsec PSK` 换成你自己的值,用单引号括起来:
```console
# 不保存命令行历史记录
Set-PSReadlineOption –HistorySaveStyle SaveNothing
# 创建 VPN 连接
Add-VpnConnection -Name 'My IPsec VPN' -ServerAddress '你的 VPN 服务器 IP' `
-L2tpPsk '你的 VPN IPsec PSK' -TunnelType L2tp -EncryptionLevel Required `
-AuthenticationMethod Chap,MSChapv2 -Force -RememberCredential -PassThru
# 忽略 data encryption 警告(数据在 IPsec 隧道中已被加密)
```
### Windows 7, Vista and XP
1. 单击开始菜单,选择控制面板。
1. 进入 **网络和Internet** 部分。
1. 单击 **网络和共享中心**。
1. 单击 **设置新的连接或网络**。
1. 选择 **连接到工作区**,然后单击 **下一步**。
1. 单击 **使用我的Internet连接 (VPN)**。
1. 在 **Internet地址** 字段中输入`你的 VPN 服务器 IP`。
1. 在 **目标名称** 字段中输入任意内容。
1. 选中 **现在不连接;仅进行设置以便稍后连接** 复选框。
1. 单击 **下一步**。
1. 在 **用户名** 字段中输入`你的 VPN 用户名`。
1. 在 **密码** 字段中输入`你的 VPN 密码`。
1. 选中 **记住此密码** 复选框。
1. 单击 **创建**,然后单击 **关闭** 按钮。
1. 返回 **网络和共享中心**。单击左侧的 **更改适配器设置**。
1. 右键单击新创建的 VPN 连接,并选择 **属性**。
1. 单击 **选项** 选项卡,取消选中 **包括Windows登录域** 复选框。
1. 单击 **安全** 选项卡,从 **VPN 类型** 下拉菜单中选择 "使用 IPsec 的第 2 层隧道协议 (L2TP/IPSec)"。
1. 单击 **允许使用这些协议**。选中 "质询握手身份验证协议 (CHAP)" 和 "Microsoft CHAP 版本 2 (MS-CHAP v2)" 复选框。
1. 单击 **高级设置** 按钮。
1. 单击 **使用预共享密钥作身份验证** 并在 **密钥** 字段中输入`你的 VPN IPsec PSK`。
1. 单击 **确定** 关闭 **高级设置**。
1. 单击 **确定** 保存 VPN 连接的详细信息。
**注:** 在首次连接之前需要[修改一次注册表](#windows-错误-809),以解决 VPN 服务器 和/或 客户端与 NAT (比如家用路由器)的兼容问题。
要连接到 VPN:单击系统托盘中的无线/网络图标,选择新的 VPN 连接,然后单击 **连接**。如果出现提示,在登录窗口中输入 `你的 VPN 用户名` 和 `密码` ,并单击 **确定**。最后你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](#ikev1-故障排除)。
## OS X (macOS)
### macOS 13 (Ventura) 及以上
> 你也可以使用 [IKEv2](ikev2-howto-zh.md)(推荐)或者 [IPsec/XAuth](clients-xauth-zh.md) 模式连接。
1. 打开系统设置并转到网络部分。
1. 在窗口右方单击 **VPN**。
1. 从 **添加VPN配置** 下拉菜单选择 **L2TP/IPSec**。
1. 在打开的窗口中的 **显示名称** 字段中输入任意内容。
1. 保持 **配置** 为 **默认**。
1. 在 **服务器地址** 字段中输入`你的 VPN 服务器 IP`。
1. 在 **帐户名称** 字段中输入`你的 VPN 用户名`。
1. 从 **用户认证** 下拉菜单选择 **密码**。
1. 在 **密码** 字段中输入`你的 VPN 密码`。
1. 从 **机器认证** 下拉菜单选择 **共享密钥**。
1. 在 **共享密钥** 字段中输入`你的 VPN IPsec PSK`。
1. 保持 **群组名称** 字段空白。
1. **(重要)** 单击 **选项** 选项卡,并启用 **通过VPN连接发送所有流量**。
1. **(重要)** 单击 **TCP/IP** 选项卡,然后在 **配置IPv6** 下拉菜单选择 **仅本地链接**。
1. 单击 **创建** 保存 VPN 连接信息。
1. 如果要在菜单栏显示 VPN 状态并快速访问相关设置,你可以转到系统设置的控制中心部分,滚动到页面底部并在 **VPN** 下拉菜单选择 **在菜单栏中显示**。
要连接到 VPN:使用菜单栏中的图标,或者打开系统设置的 **VPN** 部分并启用 VPN 连接。最后你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](#ikev1-故障排除)。
### macOS 12 (Monterey) 及以下
> 你也可以使用 [IKEv2](ikev2-howto-zh.md)(推荐)或者 [IPsec/XAuth](clients-xauth-zh.md) 模式连接。
1. 打开系统偏好设置并转到网络部分。
1. 在窗口左下角单击 **+** 按钮。
1. 从 **接口** 下拉菜单选择 **VPN**。
1. 从 **VPN类型** 下拉菜单选择 **IPSec 上的 L2TP**。
1. 在 **服务名称** 字段中输入任意内容。
1. 单击 **创建**。
1. 在 **服务器地址** 字段中输入`你的 VPN 服务器 IP`。
1. 在 **帐户名称** 字段中输入`你的 VPN 用户名`。
1. 单击 **认证设置** 按钮。
1. 在 **用户认证** 部分,选择 **密码** 单选按钮,然后输入`你的 VPN 密码`。
1. 在 **机器认证** 部分,选择 **共享的密钥** 单选按钮,然后输入`你的 VPN IPsec PSK`。
1. 保持 **群组名称** 字段空白。
1. 单击 **好**。
1. 选中 **在菜单栏中显示 VPN 状态** 复选框。
1. **(重要)** 单击 **高级** 按钮,并选中 **通过VPN连接发送所有通信** 复选框。
1. **(重要)** 单击 **TCP/IP** 选项卡,并在 **配置IPv6** 部分中选择 **仅本地链接**。
1. 单击 **好** 关闭高级设置,然后单击 **应用** 保存 VPN 连接信息。
要连接到 VPN:使用菜单栏中的图标,或者打开系统偏好设置的网络部分,选择 VPN 并单击 **连接**。最后你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](#ikev1-故障排除)。
## Android
**重要:** Android 用户应该使用更安全的 [IKEv2 模式](ikev2-howto-zh.md)连接(推荐)。Android 12+ 仅支持 IKEv2 模式。Android 系统自带的 VPN 客户端对 IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式使用安全性较低的 `modp1024` (DH group 2)。
如果你仍然想用 IPsec/L2TP 模式连接,你必须首先编辑 VPN 服务器上的 `/etc/ipsec.conf` 并在 `ike=...` 一行的末尾加上 `,aes256-sha2;modp1024,aes128-sha1;modp1024` 字样。保存文件并运行 `service ipsec restart`。
Docker 用户:在[你的 env 文件](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh.md#如何使用本镜像)中添加 `VPN_ENABLE_MODP1024=yes`,然后重新创建 Docker 容器。
然后在你的 Android 设备上进行以下步骤:
1. 启动 **设置** 应用程序。
1. 单击 **网络和互联网**。或者,如果你使用 Android 7 或更早版本,在 **无线和网络** 部分单击 **更多...**。
1. 单击 **VPN**。
1. 单击 **添加VPN配置文件** 或窗口右上角的 **+**。
1. 在 **名称** 字段中输入任意内容。
1. 在 **类型** 下拉菜单选择 **L2TP/IPSec PSK**。
1. 在 **服务器地址** 字段中输入`你的 VPN 服务器 IP`。
1. 保持 **L2TP 密钥** 字段空白。
1. 保持 **IPSec 标识符** 字段空白。
1. 在 **IPSec 预共享密钥** 字段中输入`你的 VPN IPsec PSK`。
1. 单击 **保存**。
1. 单击新的VPN连接。
1. 在 **用户名** 字段中输入`你的 VPN 用户名`。
1. 在 **密码** 字段中输入`你的 VPN 密码`。
1. 选中 **保存帐户信息** 复选框。
1. 单击 **连接**。
连接成功后,会在通知栏显示图标。最后你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](#ikev1-故障排除)。
## iOS
> 你也可以使用 [IKEv2](ikev2-howto-zh.md)(推荐)或者 [IPsec/XAuth](clients-xauth-zh.md) 模式连接。
1. 进入设置 -> 通用 -> VPN。
1. 单击 **添加VPN配置...**。
1. 单击 **类型** 。选择 **L2TP** 并返回。
1. 在 **描述** 字段中输入任意内容。
1. 在 **服务器** 字段中输入`你的 VPN 服务器 IP`。
1. 在 **帐户** 字段中输入`你的 VPN 用户名`。
1. 在 **密码** 字段中输入`你的 VPN 密码`。
1. 在 **密钥** 字段中输入`你的 VPN IPsec PSK`。
1. 启用 **发送所有流量** 选项。
1. 单击右上角的 **完成**。
1. 启用 **VPN** 连接。
连接成功后,会在通知栏显示图标。最后你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](#ikev1-故障排除)。
## Chrome OS
> 你也可以使用 [IKEv2](ikev2-howto-zh.md) 模式连接(推荐)。
1. 进入设置 -> 网络。
1. 单击 **添加连接**,然后单击 **添加内置 VPN**。
1. 在 **服务名称** 字段中输入任意内容。
1. 在 **提供商类型** 下拉菜单选择 **L2TP/IPsec**。
1. 在 **服务器主机名** 字段中输入`你的 VPN 服务器 IP`。
1. 在 **身份验证类型** 下拉菜单选择 **预共享密钥**。
1. 在 **用户名** 字段中输入`你的 VPN 用户名`。
1. 在 **密码** 字段中输入`你的 VPN 密码`。
1. 在 **预共享密钥** 字段中输入`你的 VPN IPsec PSK`。
1. 保持其他字段空白。
1. 启用 **保存身份信息和密码**。
1. 单击 **连接**。
连接成功后,网络状态图标上会出现 VPN 指示。你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](#ikev1-故障排除)。
## Linux
> 你也可以使用 [IKEv2](ikev2-howto-zh.md) 模式连接(推荐)。
### Ubuntu Linux
Ubuntu 18.04 和更新版本用户可以使用 `apt` 安装 [network-manager-l2tp-gnome](https://packages.ubuntu.com/search?keywords=network-manager-l2tp-gnome) 软件包,然后通过 GUI 配置 IPsec/L2TP VPN 客户端。
1. 进入 Settings -> Network -> VPN。单击 **+** 按钮。
1. 选择 **Layer 2 Tunneling Protocol (L2TP)**。
1. 在 **Name** 字段中输入任意内容。
1. 在 **Gateway** 字段中输入`你的 VPN 服务器 IP`。
1. 在 **User name** 字段中输入`你的 VPN 用户名`。
1. 右键单击 **Password** 字段中的 **?**,选择 **Store the password only for this user**。
1. 在 **Password** 字段中输入`你的 VPN 密码`。
1. 保持 **NT Domain** 字段空白。
1. 单击 **IPsec Settings...** 按钮。
1. 选中 **Enable IPsec tunnel to L2TP host** 复选框。
1. 保持 **Gateway ID** 字段空白。
1. 在 **Pre-shared key** 字段中输入`你的 VPN IPsec PSK`。
1. 展开 **Advanced** 部分。
1. 在 **Phase1 Algorithms** 字段中输入 `aes128-sha1-modp2048`。
1. 在 **Phase2 Algorithms** 字段中输入 `aes128-sha1`。
1. 单击 **OK**,然后单击 **Add** 保存 VPN 连接信息。
1. 启用 **VPN** 连接。
如果在连接过程中遇到错误,请尝试[这个解决方案](https://github.com/nm-l2tp/NetworkManager-l2tp/blob/2926ea0239fe970ff08cb8a7863f8cb519ece032/README.md#unable-to-establish-l2tp-connection-without-udp-source-port-1701)。
连接成功后,你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
### Fedora 和 CentOS
Fedora 28(和更新版本)和 CentOS 8/7 用户可以使用 [IPsec/XAuth](clients-xauth-zh.md) 模式连接。
### 其它 Linux
首先看[这里](https://github.com/nm-l2tp/NetworkManager-l2tp/wiki/Prebuilt-Packages)以确认 `network-manager-l2tp` 和 `network-manager-l2tp-gnome` 软件包是否在你的 Linux 版本上可用。如果可用,安装它们(选择使用 strongSwan)并参见上面的说明。另外,你也可以使用命令行配置 Linux VPN 客户端。
### 使用命令行配置 Linux VPN 客户端
高级用户可以使用命令行配置 Linux VPN 客户端。另外,你也可以使用 [IKEv2](ikev2-howto-zh.md) 模式连接(推荐),或者[使用图形界面配置](#linux)。以下说明受到 [Peter Sanford 的工作](https://gist.github.com/psanford/42c550a1a6ad3cb70b13e4aaa94ddb1c)的启发。这些命令必须在你的 VPN 客户端上使用 `root` 账户运行。
要配置 VPN 客户端,首先安装以下软件包:
```bash
# Ubuntu and Debian
apt-get update
apt-get install strongswan xl2tpd net-tools
# Fedora
yum install strongswan xl2tpd net-tools
# CentOS
yum install epel-release
yum --enablerepo=epel install strongswan xl2tpd net-tools
```
创建 VPN 变量(替换为你自己的值):
```bash
VPN_SERVER_IP='你的VPN服务器IP'
VPN_IPSEC_PSK='你的IPsec预共享密钥'
VPN_USER='你的VPN用户名'
VPN_PASSWORD='你的VPN密码'
```
配置 strongSwan:
```bash
cat > /etc/ipsec.conf < /etc/ipsec.secrets </dev/null
mv /etc/strongswan/ipsec.secrets /etc/strongswan/ipsec.secrets.old 2>/dev/null
ln -s /etc/ipsec.conf /etc/strongswan/ipsec.conf
ln -s /etc/ipsec.secrets /etc/strongswan/ipsec.secrets
```
配置 xl2tpd:
```bash
cat > /etc/xl2tpd/xl2tpd.conf < /etc/ppp/options.l2tpd.client < /var/run/xl2tpd/l2tp-control
```
运行 `ifconfig` 并且检查输出。现在你应该看到一个新的网络接口 `ppp0`。
检查你现有的默认路由:
```bash
ip route
```
在输出中查找以下行: `default via X.X.X.X ...`。记下这个网关 IP,并且在下面的两个命令中使用。
从新的默认路由中排除你的 VPN 服务器的公有 IP(替换为你自己的值):
```bash
route add 你的VPN服务器的公有IP gw X.X.X.X
```
如果你的 VPN 客户端是一个远程服务器,则必须从新的默认路由中排除你的本地电脑的公有 IP,以避免 SSH 会话被断开(替换为[实际值](https://www.ipchicken.com)):
```bash
route add 你的本地电脑的公有IP gw X.X.X.X
```
添加一个新的默认路由,并且开始通过 VPN 服务器发送数据:
```bash
route add default dev ppp0
```
至此 VPN 连接已成功完成。检查 VPN 是否正常工作:
```bash
wget -qO- http://ipv4.icanhazip.com; echo
```
以上命令应该返回 `你的 VPN 服务器 IP`。
要停止通过 VPN 服务器发送数据:
```bash
route del default dev ppp0
```
要断开连接:
```bash
# Ubuntu and Debian
echo "d myvpn" > /var/run/xl2tpd/l2tp-control
ipsec down myvpn
# CentOS and Fedora
echo "d myvpn" > /var/run/xl2tpd/l2tp-control
strongswan down myvpn
```
## IKEv1 故障排除
*其他语言版本: [English](clients.md#ikev1-troubleshooting), [中文](clients-zh.md#ikev1-故障排除)。*
**另见:** [IKEv2 故障排除](ikev2-howto-zh.md#ikev2-故障排除)和[高级用法](advanced-usage-zh.md)。
* [检查日志及 VPN 状态](#检查日志及-vpn-状态)
* [Windows 错误 809](#windows-错误-809)
* [Windows 错误 789 或 691](#windows-错误-789-或-691)
* [Windows 错误 628 或 766](#windows-错误-628-或-766)
* [Windows 10 正在连接](#windows-10-正在连接)
* [Windows 10/11 升级](#windows-1011-升级)
* [Windows DNS 泄漏和 IPv6](#windows-dns-泄漏和-ipv6)
* [Android/Linux MTU/MSS 问题](#androidlinux-mtumss-问题)
* [macOS 通过 VPN 发送通信](#macos-通过-vpn-发送通信)
* [iOS/Android 睡眠模式](#iosandroid-睡眠模式)
* [Debian 内核](#debian-内核)
### 检查日志及 VPN 状态
以下命令需要使用 `root` 账户(或者 `sudo`)运行。
首先,重启 VPN 服务器上的相关服务:
```bash
service ipsec restart
service xl2tpd restart
```
**Docker 用户:** 运行 `docker restart ipsec-vpn-server`。
然后重启你的 VPN 客户端设备,并重试连接。如果仍然无法连接,可以尝试删除并重新创建 VPN 连接。请确保输入了正确的 VPN 服务器地址和 VPN 登录凭证。
对于有外部防火墙的服务器(比如 [EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)/[GCE](https://cloud.google.com/vpc/docs/firewalls)),请为 VPN 打开 UDP 端口 500 和 4500。
检查 Libreswan (IPsec) 和 xl2tpd 日志是否有错误:
```bash
# Ubuntu & Debian
grep pluto /var/log/auth.log
grep xl2tpd /var/log/syslog
# CentOS/RHEL, Rocky Linux, AlmaLinux, Oracle Linux & Amazon Linux 2
grep pluto /var/log/secure
grep xl2tpd /var/log/messages
# Alpine Linux
grep pluto /var/log/messages
grep xl2tpd /var/log/messages
```
检查 IPsec VPN 服务器状态:
```bash
ipsec status
```
查看当前已建立的 VPN 连接:
```bash
ipsec trafficstatus
```
### Windows 错误 809
> 错误 809:无法建立计算机与 VPN 服务器之间的网络连接,因为远程服务器未响应。这可能是因为未将计算机与远程服务器之间的某种网络设备(如防火墙、NAT、路由器等)配置为允许 VPN 连接。请与管理员或服务提供商联系以确定哪种设备可能产生此问题。
**注:** 仅当你使用 IPsec/L2TP 模式连接到 VPN 时,才需要进行下面的注册表更改。对于 [IKEv2](ikev2-howto-zh.md) 和 [IPsec/XAuth](clients-xauth-zh.md) 模式,**不需要** 进行此更改。
要解决此错误,在首次连接之前需要修改一次注册表,以解决 VPN 服务器 和/或 客户端与 NAT (比如家用路由器)的兼容问题。请下载并导入下面的 `.reg` 文件,或者打开[提升权限命令提示符](http://www.cnblogs.com/xxcanghai/p/4610054.html)并运行以下命令。**完成后必须重启计算机。**
- 适用于 Windows Vista, 7, 8, 10 和 11 ([下载 .reg 文件](https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0/Fix_VPN_Error_809_Windows_Vista_7_8_10_Reboot_Required.reg))
```console
REG ADD HKLM\SYSTEM\CurrentControlSet\Services\PolicyAgent /v AssumeUDPEncapsulationContextOnSendRule /t REG_DWORD /d 0x2 /f
```
- 仅适用于 Windows XP ([下载 .reg 文件](https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0/Fix_VPN_Error_809_Windows_XP_ONLY_Reboot_Required.reg))
```console
REG ADD HKLM\SYSTEM\CurrentControlSet\Services\IPSec /v AssumeUDPEncapsulationContextOnSendRule /t REG_DWORD /d 0x2 /f
```
另外,某些个别的 Windows 系统配置禁用了 IPsec 加密,此时也会导致连接失败。要重新启用它,可以运行以下命令并重启。
- 适用于 Windows XP, Vista, 7, 8, 10 和 11 ([下载 .reg 文件](https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0/Fix_VPN_Error_809_Allow_IPsec_Reboot_Required.reg))
```console
REG ADD HKLM\SYSTEM\CurrentControlSet\Services\RasMan\Parameters /v ProhibitIpSec /t REG_DWORD /d 0x0 /f
```
### Windows 错误 789 或 691
> 错误 789:L2TP 连接尝试失败,因为安全层在初始化与远程计算机的协商时遇到一个处理错误。
> 错误 691:由于指定的用户名和/或密码无效而拒绝连接。下列条件可能会导致此情况:用户名和/或密码键入错误...
对于错误 789,点击[这里](https://documentation.meraki.com/MX/Client_VPN/Guided_Client_VPN_Troubleshooting/Unable_to_Connect_to_Client_VPN_from_Some_Devices)查看故障排除信息。对于错误 691,你可以尝试删除并重新创建 VPN 连接,按照本文档中的步骤操作。请确保输入了正确的 VPN 登录凭证。
### Windows 错误 628 或 766
> 错误 628:在连接完成前,连接被远程计算机终止。
> 错误 766:找不到证书。使用通过 IPSec 的 L2TP 协议的连接要求安装一个机器证书。它也叫做计算机证书。
要解决这些错误,请按以下步骤操作:
1. 右键单击系统托盘中的无线/网络图标。
1. **Windows 11:** 选择 **网络和 Internet 设置**,然后在打开的页面中单击 **高级网络设置**。单击 **更多网络适配器选项**。
**Windows 10:** 选择 **打开"网络和 Internet"设置**,然后在打开的页面中单击 **网络和共享中心**。单击左侧的 **更改适配器设置**。
**Windows 8/7:** 选择 **打开网络和共享中心**。单击左侧的 **更改适配器设置**。
1. 右键单击新的 VPN 连接,并选择 **属性**。
1. 单击 **安全** 选项卡,从 **VPN 类型** 下拉菜单中选择 "使用 IPsec 的第 2 层隧道协议 (L2TP/IPSec)"。
1. 单击 **允许使用这些协议**。选中 "质询握手身份验证协议 (CHAP)" 和 "Microsoft CHAP 版本 2 (MS-CHAP v2)" 复选框。
1. 单击 **高级设置** 按钮。
1. 单击 **使用预共享密钥作身份验证** 并在 **密钥** 字段中输入`你的 VPN IPsec PSK`。
1. 单击 **确定** 关闭 **高级设置**。
1. 单击 **确定** 保存 VPN 连接的详细信息。
### Windows 10 正在连接
如果你使用 Windows 10 并且 VPN 卡在 "正在连接" 状态超过几分钟,尝试以下步骤:
1. 右键单击系统托盘中的无线/网络图标。
1. 选择 **打开"网络和 Internet"设置**,然后在打开的页面中单击左侧的 **VPN**。
1. 选择新的 VPN 连接,然后单击 **连接**。如果出现提示,在登录窗口中输入 `你的 VPN 用户名` 和 `密码` ,并单击 **确定**。
### Windows 10/11 升级
在升级 Windows 10/11 版本之后(比如从 21H2 到 22H2),你可能需要重新按照 [Windows 错误 809](#windows-错误-809) 中的步骤修改注册表并重启。
### Windows DNS 泄漏和 IPv6
Windows 8, 10 和 11 默认使用 "smart multi-homed name resolution" (智能多宿主名称解析)。如果你的因特网适配器的 DNS 服务器在本地网段上,在使用 Windows 自带的 IPsec VPN 客户端时可能会导致 "DNS 泄漏"。要解决这个问题,你可以[禁用智能多宿主名称解析](https://www.neowin.net/news/guide-prevent-dns-leakage-while-using-a-vpn-on-windows-10-and-windows-8/),或者配置你的因特网适配器以使用在你的本地网段之外的 DNS 服务器(比如 8.8.8.8 和 8.8.4.4)。在完成后重启计算机。
另外,如果你的计算机启用了 IPv6,所有的 IPv6 流量(包括 DNS 请求)都将绕过 VPN。要在 Windows 上禁用 IPv6,请看[这里](https://support.microsoft.com/zh-cn/help/929852/guidance-for-configuring-ipv6-in-windows-for-advanced-users)。
如果你需要支持 IPv6 的 VPN,请尝试 [IKEv2 模式](ikev2-howto-zh.md)(参见 [IPv6 支持](advanced-usage-zh.md#ipv6-支持),需要具有公共 IPv6 地址的 VPN 服务器),或者尝试 [OpenVPN](https://github.com/hwdsl2/openvpn-install/blob/master/README-zh.md) 或 [WireGuard](https://github.com/hwdsl2/wireguard-install/blob/master/README-zh.md)。
### Android/Linux MTU/MSS 问题
某些 Android 设备和 Linux 系统有 MTU/MSS 问题,表现为使用 IPsec/XAuth ("Cisco IPsec") 或者 IKEv2 模式可以连接到 VPN 但是无法打开网站。如果你遇到该问题,尝试在 VPN 服务器上运行以下命令。如果成功解决,你可以将这些命令添加到 `/etc/rc.local` 以使它们重启后继续有效。
```
iptables -t mangle -A FORWARD -m policy --pol ipsec --dir in \
-p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 \
-j TCPMSS --set-mss 1360
iptables -t mangle -A FORWARD -m policy --pol ipsec --dir out \
-p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 \
-j TCPMSS --set-mss 1360
echo 1 > /proc/sys/net/ipv4/ip_no_pmtu_disc
```
**Docker 用户:** 要修复这个问题,不需要运行以上命令。你可以在[你的 env 文件](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh.md#如何使用本镜像)中添加 `VPN_ANDROID_MTU_FIX=yes`,然后重新创建 Docker 容器。
参考链接:[[1]](https://www.zeitgeist.se/2013/11/26/mtu-woes-in-ipsec-tunnels-how-to-fix/)。
### macOS 通过 VPN 发送通信
OS X (macOS) 用户:如果可以成功地使用 IPsec/L2TP 模式连接,但是你的公有 IP 没有显示为 `你的 VPN 服务器 IP`,请阅读上面的 [macOS](#os-x-macos) 部分并完成以下步骤。保存 VPN 配置然后重新连接。
对于 macOS 13 (Ventura) 及以上:
1. 单击 **选项** 选项卡,并启用 **通过VPN连接发送所有流量**。
1. 单击 **TCP/IP** 选项卡,然后在 **配置IPv6** 下拉菜单选择 **仅本地链接**。
对于 macOS 12 (Monterey) 及以下:
1. 单击 **高级** 按钮,并选中 **通过VPN连接发送所有通信** 复选框。
1. 单击 **TCP/IP** 选项卡,并在 **配置IPv6** 部分中选择 **仅本地链接**。
如果在尝试上面步骤之后,你的计算机仍然不能通过 VPN 连接发送通信,检查一下服务顺序。进入系统偏好设置中的网络部分,单击左侧连接列表下方的齿轮按钮,选择 "设定服务顺序"。然后将 VPN 连接拖动到顶端。
### iOS/Android 睡眠模式
为了节约电池,iOS 设备 (iPhone/iPad) 在屏幕变黑(睡眠模式)之后会自动断开 Wi-Fi 连接。这会导致 IPsec VPN 断开。该行为是被[故意设计的](https://discussions.apple.com/thread/2333948)并且不能被配置。
如果需要 VPN 在设备唤醒后自动重连,你可以使用 [IKEv2](ikev2-howto-zh.md) 模式连接(推荐)并启用 "VPN On Demand" 功能。或者你也可以另外尝试使用 [OpenVPN](https://github.com/hwdsl2/openvpn-install/blob/master/README-zh.md),它支持[一些选项](https://openvpn.net/vpn-server-resources/faq-regarding-openvpn-connect-ios/)比如 "Reconnect on Wakeup" 和 "Seamless Tunnel"。
Android 设备在进入睡眠模式后也会断开 Wi-Fi 连接。你可以尝试打开 "始终开启 VPN" 选项以保持连接。详情请看[这里](https://support.google.com/android/answer/9089766?hl=zh-Hans)。
### Debian 内核
Debian 用户:运行 `uname -r` 检查你的服务器的 Linux 内核版本。如果它包含 `cloud` 字样,并且 `/dev/ppp` 不存在,则该内核缺少 `ppp` 支持从而不能使用 IPsec/L2TP 模式。VPN 安装脚本会尝试检测此情形并显示警告。在这种情况下,你可以另外使用 [IKEv2](ikev2-howto-zh.md) 或者 [IPsec/XAuth](clients-xauth-zh.md) 模式连接到 VPN。
要解决 IPsec/L2TP 模式的问题,你可以换用标准的 Linux 内核,通过安装比如 `linux-image-amd64` 软件包来实现。然后更新 GRUB 的内核默认值并重启服务器。
## 授权协议
注: 这个协议仅适用于本文档。
版权所有 (C) 2016-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
受到 [Joshua Lund 的工作](https://github.com/StreisandEffect/streisand/blob/6aa6b6b2735dd829ca8c417d72eb2768a89b6639/playbooks/roles/l2tp-ipsec/templates/instructions.md.j2)的启发
本程序为自由软件,在自由软件联盟发布的[ GNU 通用公共许可协议](https://www.gnu.org/licenses/gpl.html)的约束下,你可以对其进行再发布及修改。协议版本为第三版或(随你)更新的版本。
我们希望发布的这款程序有用,但不保证,甚至不保证它有经济价值和适合特定用途。详情参见GNU通用公共许可协议。
================================================
FILE: docs/clients.md
================================================
[English](clients.md) | [中文](clients-zh.md)
# Configure IPsec/L2TP VPN Clients
After [setting up your own VPN server](https://github.com/hwdsl2/setup-ipsec-vpn), follow these steps to configure your devices. IPsec/L2TP is natively supported by Android, iOS, OS X, and Windows. There is no additional software to install. Setup should only take a few minutes. In case you are unable to connect, first check to make sure the VPN credentials were entered correctly.
---
* Platforms
* [Windows](#windows)
* [OS X (macOS)](#os-x-macos)
* [Android](#android)
* [iOS (iPhone/iPad)](#ios)
* [Chrome OS (Chromebook)](#chrome-os)
* [Linux](#linux)
* [IKEv1 troubleshooting](#ikev1-troubleshooting)
## Windows
> You may also connect using [IKEv2](ikev2-howto.md) mode (recommended).
### Windows 11
1. Right-click on the wireless/network icon in your system tray.
1. Select **Network and Internet settings**, then on the page that opens, click **VPN**.
1. Click the **Add VPN** button.
1. Select **Windows (built-in)** in the **VPN provider** drop-down menu.
1. Enter anything you like in the **Connection name** field.
1. Enter `Your VPN Server IP` in the **Server name or address** field.
1. Select **L2TP/IPsec with pre-shared key** in the **VPN type** drop-down menu.
1. Enter `Your VPN IPsec PSK` in the **Pre-shared key** field.
1. Enter `Your VPN Username` in the **User name** field.
1. Enter `Your VPN Password` in the **Password** field.
1. Check the **Remember my sign-in info** checkbox.
1. Click **Save** to save the VPN connection details.
**Note:** This [one-time registry change](#windows-error-809) is required if the VPN server and/or client is behind NAT (e.g. home router).
To connect to the VPN: Click the **Connect** button, or click on the wireless/network icon in your system tray, click **VPN**, then select the new VPN entry and click **Connect**. If prompted, enter `Your VPN Username` and `Password`, then click **OK**. You can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](#ikev1-troubleshooting).
### Windows 10 and 8
1. Right-click on the wireless/network icon in your system tray.
1. Select **Open Network & Internet settings**, then on the page that opens, click **Network and Sharing Center**.
1. Click **Set up a new connection or network**.
1. Select **Connect to a workplace** and click **Next**.
1. Click **Use my Internet connection (VPN)**.
1. Enter `Your VPN Server IP` in the **Internet address** field.
1. Enter anything you like in the **Destination name** field, and then click **Create**.
1. Return to **Network and Sharing Center**. On the left, click **Change adapter settings**.
1. Right-click on the new VPN entry and choose **Properties**.
1. Click the **Security** tab. Select "Layer 2 Tunneling Protocol with IPsec (L2TP/IPSec)" for the **Type of VPN**.
1. Click **Allow these protocols**. Check the "Challenge Handshake Authentication Protocol (CHAP)" and "Microsoft CHAP Version 2 (MS-CHAP v2)" checkboxes.
1. Click the **Advanced settings** button.
1. Select **Use preshared key for authentication** and enter `Your VPN IPsec PSK` for the **Key**.
1. Click **OK** to close the **Advanced settings**.
1. Click **OK** to save the VPN connection details.
**Note:** This [one-time registry change](#windows-error-809) is required if the VPN server and/or client is behind NAT (e.g. home router).
To connect to the VPN: Click on the wireless/network icon in your system tray, select the new VPN entry, and click **Connect**. If prompted, enter `Your VPN Username` and `Password`, then click **OK**. You can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](#ikev1-troubleshooting).
Alternatively, instead of following the steps above, you may create the VPN connection using these Windows PowerShell commands. Replace `Your VPN Server IP` and `Your VPN IPsec PSK` with your own values, enclosed in single quotes:
```console
# Disable persistent command history
Set-PSReadlineOption –HistorySaveStyle SaveNothing
# Create VPN connection
Add-VpnConnection -Name 'My IPsec VPN' -ServerAddress 'Your VPN Server IP' `
-L2tpPsk 'Your VPN IPsec PSK' -TunnelType L2tp -EncryptionLevel Required `
-AuthenticationMethod Chap,MSChapv2 -Force -RememberCredential -PassThru
# Ignore the data encryption warning (data is encrypted in the IPsec tunnel)
```
### Windows 7, Vista and XP
1. Click on the Start Menu and go to the Control Panel.
1. Go to the **Network and Internet** section.
1. Click **Network and Sharing Center**.
1. Click **Set up a new connection or network**.
1. Select **Connect to a workplace** and click **Next**.
1. Click **Use my Internet connection (VPN)**.
1. Enter `Your VPN Server IP` in the **Internet address** field.
1. Enter anything you like in the **Destination name** field.
1. Check the **Don't connect now; just set it up so I can connect later** checkbox.
1. Click **Next**.
1. Enter `Your VPN Username` in the **User name** field.
1. Enter `Your VPN Password` in the **Password** field.
1. Check the **Remember this password** checkbox.
1. Click **Create**, and then **Close**.
1. Return to **Network and Sharing Center**. On the left, click **Change adapter settings**.
1. Right-click on the new VPN entry and choose **Properties**.
1. Click the **Options** tab and uncheck **Include Windows logon domain**.
1. Click the **Security** tab. Select "Layer 2 Tunneling Protocol with IPsec (L2TP/IPSec)" for the **Type of VPN**.
1. Click **Allow these protocols**. Check the "Challenge Handshake Authentication Protocol (CHAP)" and "Microsoft CHAP Version 2 (MS-CHAP v2)" checkboxes.
1. Click the **Advanced settings** button.
1. Select **Use preshared key for authentication** and enter `Your VPN IPsec PSK` for the **Key**.
1. Click **OK** to close the **Advanced settings**.
1. Click **OK** to save the VPN connection details.
**Note:** This [one-time registry change](#windows-error-809) is required if the VPN server and/or client is behind NAT (e.g. home router).
To connect to the VPN: Click on the wireless/network icon in your system tray, select the new VPN entry, and click **Connect**. If prompted, enter `Your VPN Username` and `Password`, then click **OK**. You can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](#ikev1-troubleshooting).
## OS X (macOS)
### macOS 13 (Ventura) and newer
> You may also connect using [IKEv2](ikev2-howto.md) (recommended) or [IPsec/XAuth](clients-xauth.md) mode.
1. Open **System Settings** and go to the **Network** section.
1. Click **VPN** on the right hand side of the window.
1. Click the **Add VPN Configuration** drop-down menu and select **L2TP over IPSec**.
1. In the window that opens, enter anything you like for the **Display name**.
1. Leave **Configuration** as **Default**.
1. Enter `Your VPN Server IP` for the **Server address**.
1. Enter `Your VPN Username` for the **Account name**.
1. Select **Password** from the **User authentication** drop-down menu.
1. Enter `Your VPN Password` for the **Password**.
1. Select **Shared secret** from the **Machine authentication** drop-down menu.
1. Enter `Your VPN IPsec PSK` for the **Shared secret**.
1. Leave the **Group name** field blank.
1. **(Important before you click create)** Click the **Options** tab, and make sure the **Send all traffic over VPN connection** toggle is ON.
1. **(Important before you click create)** Click the **TCP/IP** tab, and select **Link-local only** from the **Configure IPv6** drop-down menu.
1. Click **Create** to save the VPN configuration.
1. To show VPN status in your menu bar and for shortcut access, go to the **Control Center** section of **System Settings**. Scroll to the bottom and select `Show in Menu Bar` from the **VPN** drop-down menu.
To connect to the VPN: Use the menu bar icon, or go to the **VPN** section of **System Settings** and toggle the switch for your VPN configuration. You can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](#ikev1-troubleshooting).
### macOS 12 (Monterey) and older
> You may also connect using [IKEv2](ikev2-howto.md) (recommended) or [IPsec/XAuth](clients-xauth.md) mode.
1. Open System Preferences and go to the Network section.
1. Click the **+** button in the lower-left corner of the window.
1. Select **VPN** from the **Interface** drop-down menu.
1. Select **L2TP over IPSec** from the **VPN Type** drop-down menu.
1. Enter anything you like for the **Service Name**.
1. Click **Create**.
1. Enter `Your VPN Server IP` for the **Server Address**.
1. Enter `Your VPN Username` for the **Account Name**.
1. Click the **Authentication Settings** button.
1. In the **User Authentication** section, select the **Password** radio button and enter `Your VPN Password`.
1. In the **Machine Authentication** section, select the **Shared Secret** radio button and enter `Your VPN IPsec PSK`.
1. Click **OK**.
1. Check the **Show VPN status in menu bar** checkbox.
1. **(Important)** Click the **Advanced** button and make sure the **Send all traffic over VPN connection** checkbox is checked.
1. **(Important)** Click the **TCP/IP** tab, and make sure **Link-local only** is selected in the **Configure IPv6** section.
1. Click **OK** to close the Advanced settings, and then click **Apply** to save the VPN connection information.
To connect to the VPN: Use the menu bar icon, or go to the Network section of System Preferences, select the VPN and choose **Connect**. You can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](#ikev1-troubleshooting).
## Android
**Important:** Android users should instead connect using [IKEv2 mode](ikev2-howto.md) (recommended), which is more secure. Android 12+ only supports IKEv2 mode. The native VPN client in Android uses the less secure `modp1024` (DH group 2) for the IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes.
If you still want to connect using IPsec/L2TP mode, you must first edit `/etc/ipsec.conf` on the VPN server. Find the line `ike=...` and append `,aes256-sha2;modp1024,aes128-sha1;modp1024` at the end. Save the file and run `service ipsec restart`.
Docker users: Add `VPN_ENABLE_MODP1024=yes` to [your env file](https://github.com/hwdsl2/docker-ipsec-vpn-server#how-to-use-this-image), then re-create the Docker container.
After that, follow the steps below on your Android device:
1. Launch the **Settings** application.
1. Tap "Network & internet". Or, if using Android 7 or earlier, tap **More...** in the **Wireless & networks** section.
1. Tap **VPN**.
1. Tap **Add VPN Profile** or the **+** icon at top-right of screen.
1. Enter anything you like in the **Name** field.
1. Select **L2TP/IPSec PSK** in the **Type** drop-down menu.
1. Enter `Your VPN Server IP` in the **Server address** field.
1. Leave the **L2TP secret** field blank.
1. Leave the **IPSec identifier** field blank.
1. Enter `Your VPN IPsec PSK` in the **IPSec pre-shared key** field.
1. Tap **Save**.
1. Tap the new VPN connection.
1. Enter `Your VPN Username` in the **Username** field.
1. Enter `Your VPN Password` in the **Password** field.
1. Check the **Save account information** checkbox.
1. Tap **Connect**.
Once connected, you will see a VPN icon in the notification bar. You can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](#ikev1-troubleshooting).
## iOS
> You may also connect using [IKEv2](ikev2-howto.md) (recommended) or [IPsec/XAuth](clients-xauth.md) mode.
1. Go to Settings -> General -> VPN.
1. Tap **Add VPN Configuration...**.
1. Tap **Type**. Select **L2TP** and go back.
1. Tap **Description** and enter anything you like.
1. Tap **Server** and enter `Your VPN Server IP`.
1. Tap **Account** and enter `Your VPN Username`.
1. Tap **Password** and enter `Your VPN Password`.
1. Tap **Secret** and enter `Your VPN IPsec PSK`.
1. Make sure the **Send All Traffic** switch is ON.
1. Tap **Done**.
1. Slide the **VPN** switch ON.
Once connected, you will see a VPN icon in the status bar. You can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](#ikev1-troubleshooting).
## Chrome OS
> You may also connect using [IKEv2](ikev2-howto.md) mode (recommended).
1. Go to Settings -> Network.
1. Click **Add connection**, then click **Add built-in VPN**.
1. Enter anything you like for the **Service name**.
1. Select **L2TP/IPsec** in the **Provider type** drop-down menu.
1. Enter `Your VPN Server IP` for the **Server hostname**.
1. Select **Pre-shared key** in the **Authentication type** drop-down menu.
1. Enter `Your VPN Username` for the **Username**.
1. Enter `Your VPN Password` for the **Password**.
1. Enter `Your VPN IPsec PSK` for the **Pre-shared key**.
1. Leave other fields blank.
1. Enable **Save identity and password**.
1. Click **Connect**.
Once connected, you will see a VPN icon overlay on the network status icon. You can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](#ikev1-troubleshooting).
## Linux
> You may also connect using [IKEv2](ikev2-howto.md) mode (recommended).
### Ubuntu Linux
Ubuntu 18.04 (and newer) users can install the [network-manager-l2tp-gnome](https://packages.ubuntu.com/search?keywords=network-manager-l2tp-gnome) package using `apt`, then configure the IPsec/L2TP VPN client using the GUI.
1. Go to Settings -> Network -> VPN. Click the **+** button.
1. Select **Layer 2 Tunneling Protocol (L2TP)**.
1. Enter anything you like in the **Name** field.
1. Enter `Your VPN Server IP` for the **Gateway**.
1. Enter `Your VPN Username` for the **User name**.
1. Right-click the **?** in the **Password** field, select **Store the password only for this user**.
1. Enter `Your VPN Password` for the **Password**.
1. Leave the **NT Domain** field blank.
1. Click the **IPsec Settings...** button.
1. Check the **Enable IPsec tunnel to L2TP host** checkbox.
1. Leave the **Gateway ID** field blank.
1. Enter `Your VPN IPsec PSK` for the **Pre-shared key**.
1. Expand the **Advanced** section.
1. Enter `aes128-sha1-modp2048` for the **Phase1 Algorithms**.
1. Enter `aes128-sha1` for the **Phase2 Algorithms**.
1. Click **OK**, then click **Add** to save the VPN connection information.
1. Turn the **VPN** switch ON.
If you get an error when trying to connect, try [this fix](https://github.com/nm-l2tp/NetworkManager-l2tp/blob/2926ea0239fe970ff08cb8a7863f8cb519ece032/README.md#unable-to-establish-l2tp-connection-without-udp-source-port-1701).
Once connected, you can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
### Fedora and CentOS
Fedora 28 (and newer) and CentOS 8/7 users can connect using [IPsec/XAuth](clients-xauth.md) mode.
### Other Linux
First check [here](https://github.com/nm-l2tp/NetworkManager-l2tp/wiki/Prebuilt-Packages) to see if the `network-manager-l2tp` and `network-manager-l2tp-gnome` packages are available for your Linux distribution. If yes, install them (select strongSwan) and follow the instructions above. Alternatively, you may configure Linux VPN clients using the command line.
### Configure Linux VPN clients using the command line
Advanced users can configure Linux VPN clients using the command line. Alternatively, you may connect using [IKEv2](ikev2-howto.md) mode (recommended), or [configure using the GUI](#linux). Instructions below are inspired by [the work of Peter Sanford](https://gist.github.com/psanford/42c550a1a6ad3cb70b13e4aaa94ddb1c). Commands must be run as `root` on your VPN client.
To set up the VPN client, first install the following packages:
```bash
# Ubuntu and Debian
apt-get update
apt-get install strongswan xl2tpd net-tools
# Fedora
yum install strongswan xl2tpd net-tools
# CentOS
yum install epel-release
yum --enablerepo=epel install strongswan xl2tpd net-tools
```
Create VPN variables (replace with actual values):
```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'
```
Configure strongSwan:
```bash
cat > /etc/ipsec.conf < /etc/ipsec.secrets </dev/null
mv /etc/strongswan/ipsec.secrets /etc/strongswan/ipsec.secrets.old 2>/dev/null
ln -s /etc/ipsec.conf /etc/strongswan/ipsec.conf
ln -s /etc/ipsec.secrets /etc/strongswan/ipsec.secrets
```
Configure xl2tpd:
```bash
cat > /etc/xl2tpd/xl2tpd.conf < /etc/ppp/options.l2tpd.client < /var/run/xl2tpd/l2tp-control
```
Run `ifconfig` and check the output. You should now see a new interface `ppp0`.
Check your existing default route:
```bash
ip route
```
Find this line in the output: `default via X.X.X.X ...`. Write down this gateway IP for use in the two commands below.
Exclude your VPN server's public IP from the new default route (replace with actual value):
```bash
route add YOUR_VPN_SERVER_PUBLIC_IP gw X.X.X.X
```
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](https://www.google.com/search?q=my+ip)):
```bash
route add YOUR_LOCAL_PC_PUBLIC_IP gw X.X.X.X
```
Add a new default route to start routing traffic via the VPN server:
```bash
route add default dev ppp0
```
The VPN connection is now complete. Verify that your traffic is being routed properly:
```bash
wget -qO- http://ipv4.icanhazip.com; echo
```
The above command should return `Your VPN Server IP`.
To stop routing traffic via the VPN server:
```bash
route del default dev ppp0
```
To disconnect:
```bash
# Ubuntu and Debian
echo "d myvpn" > /var/run/xl2tpd/l2tp-control
ipsec down myvpn
# CentOS and Fedora
echo "d myvpn" > /var/run/xl2tpd/l2tp-control
strongswan down myvpn
```
## IKEv1 troubleshooting
*Read this in other languages: [English](clients.md#ikev1-troubleshooting), [中文](clients-zh.md#ikev1-故障排除).*
**See also:** [IKEv2 troubleshooting](ikev2-howto.md#ikev2-troubleshooting) and [Advanced usage](advanced-usage.md).
* [Check logs and VPN status](#check-logs-and-vpn-status)
* [Windows error 809](#windows-error-809)
* [Windows error 789 or 691](#windows-error-789-or-691)
* [Windows error 628 or 766](#windows-error-628-or-766)
* [Windows 10 connecting](#windows-10-connecting)
* [Windows 10/11 upgrades](#windows-1011-upgrades)
* [Windows DNS leaks and IPv6](#windows-dns-leaks-and-ipv6)
* [Android/Linux MTU/MSS issues](#androidlinux-mtumss-issues)
* [macOS send traffic over VPN](#macos-send-traffic-over-vpn)
* [iOS/Android sleep mode](#iosandroid-sleep-mode)
* [Debian kernel](#debian-kernel)
### Check logs and VPN status
Commands below must be run as `root` (or using `sudo`).
First, restart services on the VPN server:
```bash
service ipsec restart
service xl2tpd restart
```
**Docker users:** Run `docker restart ipsec-vpn-server`.
Then reboot your VPN client device, and retry the connection. If still unable to connect, try removing and recreating the VPN connection. Make sure that the VPN server address and VPN credentials are entered correctly.
For servers with an external firewall (e.g. [EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)/[GCE](https://cloud.google.com/vpc/docs/firewalls)), open UDP ports 500 and 4500 for the VPN.
Check the Libreswan (IPsec) and xl2tpd logs for errors:
```bash
# Ubuntu & Debian
grep pluto /var/log/auth.log
grep xl2tpd /var/log/syslog
# CentOS/RHEL, Rocky Linux, AlmaLinux, Oracle Linux & Amazon Linux 2
grep pluto /var/log/secure
grep xl2tpd /var/log/messages
# Alpine Linux
grep pluto /var/log/messages
grep xl2tpd /var/log/messages
```
Check the status of the IPsec VPN server:
```bash
ipsec status
```
Show currently established VPN connections:
```bash
ipsec trafficstatus
```
### Windows error 809
> Error 809: The network connection between your computer and the VPN server could not be established because the remote server is not responding. This could be because one of the network devices (e.g, firewalls, NAT, routers, etc) between your computer and the remote server is not configured to allow VPN connections. Please contact your Administrator or your service provider to determine which device may be causing the problem.
**Note:** The registry change below is only required if you use IPsec/L2TP mode to connect to the VPN. It is NOT required for the [IKEv2](ikev2-howto.md) and [IPsec/XAuth](clients-xauth.md) modes.
To fix this error, a one-time registry change is required because the VPN server and/or client is behind NAT (e.g. home router). Download and import the `.reg` file below, or run the following from an [elevated command prompt](http://www.winhelponline.com/blog/open-elevated-command-prompt-windows/). **You must reboot your PC when finished.**
- For Windows Vista, 7, 8, 10 and 11 ([download .reg file](https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0/Fix_VPN_Error_809_Windows_Vista_7_8_10_Reboot_Required.reg))
```console
REG ADD HKLM\SYSTEM\CurrentControlSet\Services\PolicyAgent /v AssumeUDPEncapsulationContextOnSendRule /t REG_DWORD /d 0x2 /f
```
- For Windows XP ONLY ([download .reg file](https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0/Fix_VPN_Error_809_Windows_XP_ONLY_Reboot_Required.reg))
```console
REG ADD HKLM\SYSTEM\CurrentControlSet\Services\IPSec /v AssumeUDPEncapsulationContextOnSendRule /t REG_DWORD /d 0x2 /f
```
Although uncommon, some Windows systems disable IPsec encryption, causing the connection to fail. To re-enable it, run the following command and reboot your PC.
- For Windows XP, Vista, 7, 8, 10 and 11 ([download .reg file](https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0/Fix_VPN_Error_809_Allow_IPsec_Reboot_Required.reg))
```console
REG ADD HKLM\SYSTEM\CurrentControlSet\Services\RasMan\Parameters /v ProhibitIpSec /t REG_DWORD /d 0x0 /f
```
### Windows error 789 or 691
> Error 789: The L2TP connection attempt failed because the security layer encountered a processing error during initial negotiations with the remote computer.
> Error 691: The remote connection was denied because the user name and password combination you provided is not recognized, or the selected authentication protocol is not permitted on the remote access server.
For error 789, click [here](https://documentation.meraki.com/MX/Client_VPN/Guided_Client_VPN_Troubleshooting/Unable_to_Connect_to_Client_VPN_from_Some_Devices) for troubleshooting information. For error 691, you may try removing and recreating the VPN connection, by following the instructions in this document. Make sure that the VPN credentials are entered correctly.
### Windows error 628 or 766
> Error 628: The connection was terminated by the remote computer before it could be completed.
> Error 766: A certificate could not be found. Connections that use the L2TP protocol over IPSec require the installation of a machine certificate, also known as a computer certificate.
To fix these errors, please follow these steps:
1. Right-click on the wireless/network icon in your system tray.
1. **Windows 11:** Select **Network and Internet settings**, then on the page that opens, click **Advanced network settings**. Click **More network adapter options**.
**Windows 10:** Select **Open Network & Internet settings**, then on the page that opens, click **Network and Sharing Center**. On the left, click **Change adapter settings**.
**Windows 8/7:** Select **Open Network and Sharing Center**. On the left, click **Change adapter settings**.
1. Right-click on the new VPN connection, and choose **Properties**.
1. Click the **Security** tab. Select "Layer 2 Tunneling Protocol with IPsec (L2TP/IPSec)" for **Type of VPN**.
1. Click **Allow these protocols**. Check the "Challenge Handshake Authentication Protocol (CHAP)" and "Microsoft CHAP Version 2 (MS-CHAP v2)" checkboxes.
1. Click the **Advanced settings** button.
1. Select **Use preshared key for authentication** and enter `Your VPN IPsec PSK` for the **Key**.
1. Click **OK** to close the **Advanced settings**.
1. Click **OK** to save the VPN connection details.
### Windows 10 connecting
If using Windows 10 and the VPN is stuck on "connecting" for more than a few minutes, try these steps:
1. Right-click on the wireless/network icon in your system tray.
1. Select **Open Network & Internet settings**, then on the page that opens, click **VPN** on the left.
1. Select the new VPN entry, then click **Connect**. If prompted, enter `Your VPN Username` and `Password`, then click **OK**.
### Windows 10/11 upgrades
After upgrading Windows 10/11 version (e.g. from 21H2 to 22H2), you may need to re-apply the fix above for [Windows Error 809](#windows-error-809) and reboot.
### Windows DNS leaks and IPv6
Windows 8, 10 and 11 use "smart multi-homed name resolution" by default, which may cause "DNS leaks" when using the native IPsec VPN client if your DNS servers on the Internet adapter are from the local network segment. To fix, you may either [disable smart multi-homed name resolution](https://www.neowin.net/news/guide-prevent-dns-leakage-while-using-a-vpn-on-windows-10-and-windows-8/), or configure your Internet adapter to use DNS servers outside your local network (e.g. 8.8.8.8 and 8.8.4.4). When finished, reboot your PC.
In addition, if your computer has IPv6 enabled, all IPv6 traffic (including DNS queries) will bypass the VPN. Learn how to [disable IPv6](https://support.microsoft.com/en-us/help/929852/guidance-for-configuring-ipv6-in-windows-for-advanced-users) in Windows.
If you need IPv6 support through the VPN, try [IKEv2 mode](ikev2-howto.md) (see [IPv6 support](advanced-usage.md#ipv6-support), requires a VPN server with a public IPv6 address), or try [OpenVPN](https://github.com/hwdsl2/openvpn-install) or [WireGuard](https://github.com/hwdsl2/wireguard-install).
### Android/Linux MTU/MSS issues
Some Android devices and Linux systems have MTU/MSS issues, that they are able to connect to the VPN using IPsec/XAuth ("Cisco IPsec") or IKEv2 mode, but cannot open websites. If you encounter this problem, try running the following commands on the VPN server. If successful, you may add these commands to `/etc/rc.local` to persist after reboot.
```
iptables -t mangle -A FORWARD -m policy --pol ipsec --dir in \
-p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 \
-j TCPMSS --set-mss 1360
iptables -t mangle -A FORWARD -m policy --pol ipsec --dir out \
-p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 \
-j TCPMSS --set-mss 1360
echo 1 > /proc/sys/net/ipv4/ip_no_pmtu_disc
```
**Docker users:** Instead of running the commands above, you may apply this fix by adding `VPN_ANDROID_MTU_FIX=yes` to [your env file](https://github.com/hwdsl2/docker-ipsec-vpn-server#how-to-use-this-image), then re-create the Docker container.
Reference: [[1]](https://www.zeitgeist.se/2013/11/26/mtu-woes-in-ipsec-tunnels-how-to-fix/).
### macOS send traffic over VPN
OS X (macOS) users: If you can successfully connect using IPsec/L2TP mode, but your public IP does not show `Your VPN Server IP`, read the [macOS](#os-x-macos) section above and complete these steps. Save VPN configuration and re-connect.
For macOS 13 (Ventura) and newer:
1. Click the **Options** tab, and make sure the **Send all traffic over VPN connection** toggle is ON.
1. Click the **TCP/IP** tab, and select **Link-local only** from the **Configure IPv6** drop-down menu.
For macOS 12 (Monterey) and older:
1. Click the **Advanced** button and make sure the **Send all traffic over VPN connection** checkbox is checked.
1. Click the **TCP/IP** tab, and make sure **Link-local only** is selected in the **Configure IPv6** section.
After trying the steps above, if your computer is still not sending traffic over the VPN, check the service order. From the main network preferences screen, select "set service order" in the cog drop down under the list of connections. Drag the VPN connection to the top.
### iOS/Android sleep mode
To save battery, iOS devices (iPhone/iPad) will automatically disconnect Wi-Fi shortly after the screen turns off (sleep mode). As a result, the IPsec VPN disconnects. This behavior is [by design](https://discussions.apple.com/thread/2333948) and cannot be configured.
If you need the VPN to auto-reconnect when the device wakes up, you may connect using [IKEv2](ikev2-howto.md) mode (recommended) and enable the "VPN On Demand" feature. Alternatively, you may try [OpenVPN](https://github.com/hwdsl2/openvpn-install) instead, which [has support for options](https://openvpn.net/vpn-server-resources/faq-regarding-openvpn-connect-ios/) such as "Reconnect on Wakeup" and "Seamless Tunnel".
Android devices may also disconnect Wi-Fi after entering sleep mode. You may try enabling the "Always-on VPN" option to stay connected. Learn more [here](https://support.google.com/android/answer/9089766).
### Debian kernel
Debian users: Run `uname -r` to check your server's Linux kernel version. If it contains the word "cloud", and `/dev/ppp` is missing, then the kernel lacks `ppp` support and cannot use IPsec/L2TP mode. The VPN setup scripts try to detect this and show a warning. In this case, you may instead use [IKEv2](ikev2-howto.md) or [IPsec/XAuth](clients-xauth.md) mode to connect to the VPN.
To fix the issue with IPsec/L2TP mode, you may switch to the standard Linux kernel by installing e.g. the `linux-image-amd64` package. Then update the default kernel in GRUB and reboot your server.
## License
Note: This license applies to this document only.
Copyright (C) 2016-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
Inspired by [the work of Joshua Lund](https://github.com/StreisandEffect/streisand/blob/6aa6b6b2735dd829ca8c417d72eb2768a89b6639/playbooks/roles/l2tp-ipsec/templates/instructions.md.j2)
This program is free software: you can redistribute it and/or modify it under the terms of the [GNU General Public License](https://www.gnu.org/licenses/gpl.html) as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
================================================
FILE: docs/ikev2-howto-zh.md
================================================
[English](ikev2-howto.md) | [中文](ikev2-howto-zh.md)
# IKEv2 VPN 配置和使用指南
* [导言](#导言)
* [配置 IKEv2 VPN 客户端](#配置-ikev2-vpn-客户端)
* [IKEv2 故障排除](#ikev2-故障排除)
* [管理 IKEv2 客户端](#管理-ikev2-客户端)
* [更改 IKEv2 服务器地址](#更改-ikev2-服务器地址)
* [更新 IKEv2 辅助脚本](#更新-ikev2-辅助脚本)
* [使用辅助脚本配置 IKEv2](#使用辅助脚本配置-ikev2)
* [手动配置 IKEv2](#手动配置-ikev2)
* [移除 IKEv2](#移除-ikev2)
## 导言
现代操作系统支持 IKEv2 协议标准。因特网密钥交换(英语:Internet Key Exchange,简称 IKE 或 IKEv2)是一种网络协议,归属于 IPsec 协议族之下,用以创建安全关联 (Security Association, SA)。与 IKE 版本 1 相比较,IKEv2 的[功能改进](https://en.wikipedia.org/wiki/Internet_Key_Exchange#Improvements_with_IKEv2)包括比如通过 MOBIKE 实现 Standard Mobility 支持,以及更高的可靠性。
Libreswan 支持通过使用 RSA 签名算法的 X.509 Machine Certificates 来对 IKEv2 客户端进行身份验证。该方法无需 IPsec PSK, 用户名或密码。它可以用于 Windows, macOS, iOS, Android, Chrome OS, Linux 和 RouterOS。
默认情况下,运行 VPN 安装脚本时会自动配置 IKEv2。如果你想了解有关配置 IKEv2 的更多信息,请参见[使用辅助脚本配置 IKEv2](#使用辅助脚本配置-ikev2)。Docker 用户请看[配置并使用 IKEv2 VPN](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh.md#配置并使用-ikev2-vpn)。
## 配置 IKEv2 VPN 客户端
**注:** 如果要添加或者导出 IKEv2 客户端,运行 `sudo ikev2.sh`。使用 `-h` 显示使用信息。客户端配置文件可以在导入后安全删除。
* [Windows 7, 8, 10 和 11](#windows-7-8-10-和-11)
* [OS X (macOS)](#os-x-macos)
* [iOS (iPhone/iPad)](#ios)
* [Android](#android)
* [Chrome OS (Chromebook)](#chrome-os)
* [Linux](#linux)
* [MikroTik RouterOS](#routeros)
了解如何更改 IKEv2 服务器地址。
在某些情况下,你可能需要更改 IKEv2 服务器地址,例如切换为使用域名,或者在服务器的 IP 更改之后。要了解更多信息,参见[这一小节](#更改-ikev2-服务器地址)。
### Windows 7, 8, 10 和 11
#### 自动导入配置
[**屏幕录影:** 在 Windows 上自动导入 IKEv2 配置](https://ko-fi.com/post/IKEv2-Auto-Import-Configuration-on-Windows-8-10-a-K3K1DQCHW)
**Windows 8, 10 和 11+** 用户可以自动导入 IKEv2 配置:
1. 将生成的 `.p12` 文件安全地传送到你的计算机。
1. 右键单击 [ikev2_config_import.cmd](https://github.com/hwdsl2/vpn-extras/releases/latest/download/ikev2_config_import.cmd) 并保存这个辅助脚本到与 `.p12` 文件 **相同的文件夹**。
1. 右键单击保存的脚本,选择 **属性**。单击对话框下方的 **解除锁定**,然后单击 **确定**。
1. 右键单击保存的脚本,选择 **以管理员身份运行** 并按提示操作。
要连接到 VPN:单击系统托盘中的无线/网络图标,选择新的 VPN 连接,然后单击 **连接**。连接成功后,你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](#ikev2-故障排除)。
**注:** 如果你重新安装了 VPN 服务器,你可能需要先删除现有的 IKEv2 客户端和 CA 证书,然后按照上述步骤导入新的 `.p12` 文件。这有助于确保 Windows 在连接到 VPN 时使用正确的客户端证书。有关详细信息,请参阅下面的 "删除 IKEv2 VPN 连接"。
#### 手动导入配置
[[支持者] **屏幕录影:** 在 Windows 上手动导入 IKEv2 配置](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-X8X5FVFZC)
或者,**Windows 7, 8, 10 和 11+** 用户可以手动导入 IKEv2 配置:
1. 将生成的 `.p12` 文件安全地传送到你的计算机,然后导入到证书存储。
要导入 `.p12` 文件,打开[提升权限命令提示符](http://www.cnblogs.com/xxcanghai/p/4610054.html)并运行以下命令:
```console
# 导入 .p12 文件(换成你自己的值)
certutil -f -importpfx "\path\to\your\file.p12" NoExport
```
**注:** 如果客户端配置文件没有密码,请按回车键继续,或者在手动导入 `.p12` 文件时保持密码字段空白。
或者,你也可以[手动导入 .p12 文件](https://wiki.strongswan.org/projects/strongswan/wiki/Win7Certs/9)。在导入证书后,确保将客户端证书放在 "个人 -> 证书" 目录中,并且将 CA 证书放在 "受信任的根证书颁发机构 -> 证书" 目录中。
1. 在 Windows 计算机上添加一个新的 IKEv2 VPN 连接。
对于 **Windows 8, 10 和 11+**,推荐从命令提示符运行以下命令创建 VPN 连接,以达到更佳的安全性和性能。
```console
# 创建 VPN 连接(将服务器地址换成你自己的值)
powershell -command ^"Add-VpnConnection -ServerAddress '你的 VPN 服务器 IP(或者域名)' ^
-Name 'My IKEv2 VPN' -TunnelType IKEv2 -AuthenticationMethod MachineCertificate ^
-EncryptionLevel Required -PassThru^"
# 设置 IPsec 参数
powershell -command ^"Set-VpnConnectionIPsecConfiguration -ConnectionName 'My IKEv2 VPN' ^
-AuthenticationTransformConstants GCMAES128 -CipherTransformConstants GCMAES128 ^
-EncryptionMethod AES256 -IntegrityCheckMethod SHA256 -PfsGroup None ^
-DHGroup Group14 -PassThru -Force^"
```
**Windows 7** 不支持这些命令,你可以[手动创建 VPN 连接](https://wiki.strongswan.org/projects/strongswan/wiki/Win7Config/8)。
**注:** 你输入的服务器地址必须与 IKEv2 辅助脚本输出中的服务器地址 **完全一致**。例如,如果你在配置 IKEv2 时指定了服务器的域名,则必须在 **Internet地址** 字段中输入该域名。
1. **此步骤为必须,如果你手动创建了 VPN 连接。**
为 IKEv2 启用更强的加密算法,通过修改一次注册表来实现。请下载并导入下面的 `.reg` 文件,或者打开提升权限命令提示符并运行以下命令。更多信息请看[这里](https://docs.strongswan.org/docs/5.9/interop/windowsClients.html)。
- 适用于 Windows 7, 8, 10 和 11 ([下载 .reg 文件](https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0/Enable_Stronger_Ciphers_for_IKEv2_on_Windows.reg))
```console
REG ADD HKLM\SYSTEM\CurrentControlSet\Services\RasMan\Parameters /v NegotiateDH2048_AES256 /t REG_DWORD /d 0x1 /f
```
要连接到 VPN:单击系统托盘中的无线/网络图标,选择新的 VPN 连接,然后单击 **连接**。连接成功后,你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](#ikev2-故障排除)。
删除 IKEv2 VPN 连接。
通过以下的步骤,可以删除添加的 VPN 连接,并将计算机恢复到导入 IKEv2 配置之前的状态(可选)。
1. 在系统设置 -> 网络 -> VPN 中删除添加的 VPN 连接。Windows 7 用户可以在网络和共享中心 -> 更改适配器设置中删除 VPN 连接。
1. (可选)删除 IKEv2 证书。
1. **Windows 8, 10 和 11:** 按 Win+R 然后输入 `certlm.msc`,或在开始菜单中搜索 `certlm.msc`。打开 *证书 - 本地计算机*。
**Windows 7:** 按 Win+R 然后输入 `mmc`,或在开始菜单中搜索 `mmc`。打开 *管理控制台*。在 `文件 - 添加/删除管理单元` 的窗口中,选择添加 `证书` 并在弹出的窗口中选择 `计算机帐户 -> 本地计算机`。点击 `完成 -> 确定` 以保存设置。
1. 在 证书 -> 个人 -> 证书 中删除 IKEv2 客户端证书。该证书的名称与你指定的 IKEv2 客户端名称一致,默认为 `vpnclient`,该证书由 `IKEv2 VPN CA` 颁发。
1. 在 证书 -> 受信任的根证书颁发机构 -> 证书 中删除 IKEv2 VPN CA 证书。该证书是由 `IKEv2 VPN CA` 颁发的,颁发给 `IKEv2 VPN CA` 的证书。需要注意,删除这一步的证书时,证书 -> 个人 -> 证书 中应不存在其他由 `IKEv2 VPN CA` 颁发的证书。
1. (可选,适用于手动创建了 VPN 连接的用户)还原注册表配置。注意,在编辑注册表前应备份。
1. 按 Win+R 或在开始菜单中搜索 `regedit` 打开 *注册表编辑器*。
1. 在 `HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Rasman\Parameters` 中删除名为 `NegotiateDH2048_AES256` 的项目,如果它存在。
### OS X (macOS)
[[支持者] **屏幕录影:** 在 macOS 上导入 IKEv2 配置并连接](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-X8X5FVFZC)
首先,将生成的 `.mobileconfig` 文件安全地传送到你的 Mac,然后双击并按提示操作,以导入为 macOS 配置描述文件。如果你的 Mac 运行 macOS Big Sur 或更新版本,打开系统偏好设置并转到描述文件部分以完成导入。对于 macOS Ventura 和更新版本,打开系统设置并搜索描述文件。在完成之后,检查并确保 "IKEv2 VPN" 显示在系统偏好设置 -> 描述文件中。
要连接到 VPN:
1. 打开系统偏好设置并转到网络部分。
1. 选择与 `你的 VPN 服务器 IP`(或者域名)对应的 VPN 连接。
1. 选中 **在菜单栏中显示 VPN 状态** 复选框。对于 macOS Ventura 和更新版本,你可以到系统设置 -> 控制中心 -> 仅菜单栏部分配置该选项。
1. 单击 **连接**,或启用 VPN 连接。
(可选功能)启用 **VPN On Demand(按需连接)** 以在你的 Mac 连接到 Wi-Fi 时自动启动 VPN 连接。要启用它,选中 VPN 连接的 **按需连接** 复选框,然后单击 **应用**。对于 macOS Ventura 和更新版本,首先单击 VPN 连接右边的 "i" 图标,然后配置该选项。
你可以自定义按需连接规则,以排除某些 Wi-Fi 网络(例如你的家庭网络)。有关更多详细信息,请参阅 [:book: Book: 搭建自己的 VPN 服务器](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-X8X5FVFZC)中的 "指南:为 macOS 和 iOS 自定义 IKEv2 VPN On Demand 规则" 一章。
如果你手动配置 IKEv2 而不是使用辅助脚本,点这里查看步骤。
首先,将生成的 `.p12` 文件安全地传送到你的 Mac,然后双击以导入到 **钥匙串访问** 中的 **登录** 钥匙串。下一步,双击导入的 `IKEv2 VPN CA` 证书,展开 **信任** 并从 **IP 安全 (IPsec)** 下拉菜单中选择 **始终信任**。单击左上角的红色 "X" 关闭窗口。根据提示使用触控 ID,或者输入密码并单击 "更新设置"。
在完成之后,检查并确保新的客户端证书和 `IKEv2 VPN CA` 都显示在 **登录** 钥匙串 的 **证书** 类别中。
1. 打开系统偏好设置并转到网络部分。
1. 在窗口左下角单击 **+** 按钮。
1. 从 **接口** 下拉菜单选择 **VPN**。
1. 从 **VPN 类型** 下拉菜单选择 **IKEv2**。
1. 在 **服务名称** 字段中输入任意内容。
1. 单击 **创建**。
1. 在 **服务器地址** 字段中输入 `你的 VPN 服务器 IP` (或者域名)。
**注:** 如果你在配置 IKEv2 时指定了服务器的域名(而不是 IP 地址),则必须在 **服务器地址** 和 **远程 ID** 字段中输入该域名。
1. 在 **远程 ID** 字段中输入 `你的 VPN 服务器 IP` (或者域名)。
1. 在 **本地 ID** 字段中输入 `你的 VPN 客户端名称`。
**注:** 该名称必须和你在 IKEv2 配置过程中指定的客户端名称一致。它与你的 `.p12` 文件名的第一部分相同。
1. 单击 **认证设置** 按钮。
1. 从 **认证设置** 下拉菜单中选择 **无**。
1. 选择 **证书** 单选按钮,然后选择新的客户端证书。
1. 单击 **好**。
1. 选中 **在菜单栏中显示 VPN 状态** 复选框。
1. 单击 **应用** 保存 VPN 连接信息。
1. 单击 **连接**。
连接成功后,你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](#ikev2-故障排除)。
**注:** macOS 14 (Sonoma) 存在一个小问题,可能会导致 IKEv2 VPN 每 24-48 分钟断开并重新连接一次。其他 macOS 版本不受影响。有关详细信息和解决方法,请参阅 [macOS Sonoma 客户端重新连接](#macos-sonoma-客户端重新连接)。
删除 IKEv2 VPN 连接。
要删除 IKEv2 VPN 连接,打开系统偏好设置 -> 描述文件并移除你添加的 IKEv2 VPN 描述文件。
### iOS
[[支持者] **屏幕录影:** 在 iOS (iPhone & iPad) 上导入 IKEv2 配置并连接](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-X8X5FVFZC)
首先,将生成的 `.mobileconfig` 文件安全地传送到你的 iOS 设备,并且导入为 iOS 配置描述文件。要传送文件,你可以使用:
1. AirDrop(隔空投送),或者
1. 使用[文件共享](https://support.apple.com/zh-cn/HT210598)功能上传到设备(任何 App 目录),然后打开 iOS 设备上的 "文件" App,将上传的文件移动到 "On My iPhone" 目录下。然后单击它并到 "设置" App 中导入,或者
1. 将文件放在一个你的安全的托管网站上,然后在 Mobile Safari 中下载并导入它们。
在完成之后,检查并确保 "IKEv2 VPN" 显示在设置 -> 通用 -> VPN 与设备管理(或者描述文件)中。
要连接到 VPN:
1. 进入设置 -> VPN。选择与 `你的 VPN 服务器 IP`(或者域名)对应的 VPN 连接。
1. 启用 **VPN** 连接。
(可选功能)启用 **VPN On Demand(按需连接)** 以在你的 iOS 设备连接到 Wi-Fi 时自动启动 VPN 连接。要启用它,单击 VPN 连接右边的 "i" 图标,然后启用 **按需连接**。
你可以自定义按需连接规则,以排除某些 Wi-Fi 网络(例如你的家庭网络)。有关更多详细信息,请参阅 [:book: Book: 搭建自己的 VPN 服务器](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-X8X5FVFZC)中的 "指南:为 macOS 和 iOS 自定义 IKEv2 VPN On Demand 规则" 一章。
自定义按需连接规则:在 Wi-Fi 和蜂窝网络上连接。
默认的 VPN On Demand 配置仅在 Wi-Fi 网络上启动 VPN 连接,而不会在蜂窝网络上启动 VPN 连接。如果你希望 VPN 在 Wi-Fi 和蜂窝网络上都启动连接:
1. 编辑 VPN 服务器上的 `/opt/src/ikev2.sh`。找到以下行:
```
InterfaceTypeMatch
Cellular
Action
Disconnect
```
并将 "Disconnect" 替换为 "Connect":
```
InterfaceTypeMatch
Cellular
Action
Connect
```
2. 保存文件,然后运行 `sudo ikev2.sh` 为你的 iOS 设备导出更新后的客户端配置文件。
3. 从你的 iOS 设备中移除之前导入的 VPN 配置文件,然后导入步骤 2 中生成的新 `.mobileconfig` 文件。
如果你手动配置 IKEv2 而不是使用辅助脚本,点这里查看步骤。
首先,将生成的 `ca.cer` 和 `.p12` 文件安全地传送到你的 iOS 设备,并且逐个导入为 iOS 配置描述文件。要传送文件,你可以使用:
1. AirDrop(隔空投送),或者
1. 使用[文件共享](https://support.apple.com/zh-cn/HT210598)功能上传到设备(任何 App 目录),然后打开 iOS 设备上的 "文件" App,将上传的文件移动到 "On My iPhone" 目录下。然后逐个单击它们并到 "设置" App 中导入,或者
1. 将文件放在一个你的安全的托管网站上,然后在 Mobile Safari 中下载并导入它们。
在完成之后,检查并确保新的客户端证书和 `IKEv2 VPN CA` 都显示在设置 -> 通用 -> VPN 与设备管理(或者描述文件)中。
1. 进入设置 -> 通用 -> VPN 与设备管理 -> VPN。
1. 单击 **添加VPN配置...**。
1. 单击 **类型** 。选择 **IKEv2** 并返回。
1. 在 **描述** 字段中输入任意内容。
1. 在 **服务器** 字段中输入 `你的 VPN 服务器 IP` (或者域名)。
**注:** 如果你在配置 IKEv2 时指定了服务器的域名(而不是 IP 地址),则必须在 **服务器** 和 **远程 ID** 字段中输入该域名。
1. 在 **远程 ID** 字段中输入 `你的 VPN 服务器 IP` (或者域名)。
1. 在 **本地 ID** 字段中输入 `你的 VPN 客户端名称`。
**注:** 该名称必须和你在 IKEv2 配置过程中指定的客户端名称一致。它与你的 `.p12` 文件名的第一部分相同。
1. 单击 **用户鉴定** 。选择 **无** 并返回。
1. 启用 **使用证书** 选项。
1. 单击 **证书** 。选择新的客户端证书并返回。
1. 单击右上角的 **完成**。
1. 启用 **VPN** 连接。
连接成功后,你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](#ikev2-故障排除)。
删除 IKEv2 VPN 连接。
要删除 IKEv2 VPN 连接,打开设置 -> 通用 -> VPN 与设备管理(或者描述文件)并移除你添加的 IKEv2 VPN 描述文件。
### Android
#### 使用 strongSwan VPN 客户端
[[支持者] **屏幕录影:** 使用 Android strongSwan VPN 客户端连接](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-X8X5FVFZC)
Android 用户可以使用 strongSwan VPN 客户端连接(推荐)。
1. 将生成的 `.sswan` 文件安全地传送到你的 Android 设备。
1. 从 [**Google Play**](https://play.google.com/store/apps/details?id=org.strongswan.android),[**F-Droid**](https://f-droid.org/en/packages/org.strongswan.android/) 或 [**strongSwan 下载网站**](https://download.strongswan.org/Android/)下载并安装 strongSwan VPN 客户端。
1. 启动 strongSwan VPN 客户端。
1. 单击右上角的 "更多选项" 菜单,然后单击 **导入VPN配置**。
1. 选择你从服务器传送过来的 `.sswan` 文件。
**注:** 要查找 `.sswan` 文件,单击左上角的抽拉式菜单,然后浏览到你保存文件的目录。
1. 在 "导入VPN配置" 屏幕上,单击 **从VPN配置导入证书**,并按提示操作。
1. 在 "选择证书" 屏幕上,选择新的客户端证书并单击 **选择**。
1. 单击 **导入**。
1. 单击新的 VPN 配置文件以开始连接。
(可选功能)你可以选择启用 Android 上的 "始终开启的 VPN" 功能。启动 **设置** App,进入 网络和互联网 -> 高级 -> VPN,单击 "strongSwan VPN 客户端" 右边的设置图标,然后启用 **始终开启的 VPN** 以及 **屏蔽未使用 VPN 的所有连接** 选项。
如果你的设备运行 Android 6.0 或更早版本,点这里查看额外的步骤。
如果你的设备运行 Android 6.0 (Marshmallow) 或更早版本,要使用 strongSwan VPN 客户端连接,你必须更改 VPN 服务器上的以下设置:编辑服务器上的 `/etc/ipsec.d/ikev2.conf`。在 `conn ikev2-cp` 小节的末尾添加 `authby=rsa-sha1`,开头必须空两格。保存文件并运行 `service ipsec restart`。
如果你手动配置 IKEv2 而不是使用辅助脚本,点这里查看步骤。
**Android 10 和更新版本:**
1. 将生成的 `.p12` 文件安全地传送到你的 Android 设备。
1. 从 [**Google Play**](https://play.google.com/store/apps/details?id=org.strongswan.android),[**F-Droid**](https://f-droid.org/en/packages/org.strongswan.android/) 或 [**strongSwan 下载网站**](https://download.strongswan.org/Android/)下载并安装 strongSwan VPN 客户端。
1. 启动 **设置** App。
1. 进入 安全 -> 高级 -> 加密与凭据。
1. 单击 **安装证书**。
1. 单击 **VPN 和应用用户证书**。
1. 选择你从服务器传送过来的 `.p12` 文件,并按提示操作。
**注:** 要查找 `.p12` 文件,单击左上角的抽拉式菜单,然后浏览到你保存文件的目录。
1. 启动 strongSwan VPN 客户端,然后单击 **添加VPN配置**。
1. 在 **服务器地址** 字段中输入 `你的 VPN 服务器 IP` (或者域名)。
**注:** 如果你在配置 IKEv2 时指定了服务器的域名(而不是 IP 地址),则必须在 **服务器地址** 字段中输入该域名。
1. 在 **VPN 类型** 下拉菜单选择 **IKEv2 证书**。
1. 单击 **选择用户证书**,选择新的客户端证书并单击 **选择**。
1. **(重要)** 单击 **显示高级设置**。向下滚动,找到并启用 **Use RSA/PSS signatures** 选项。
1. 保存新的 VPN 连接,然后单击它以开始连接。
**Android 4 to 9:**
1. 将生成的 `.p12` 文件安全地传送到你的 Android 设备。
1. 从 [**Google Play**](https://play.google.com/store/apps/details?id=org.strongswan.android),[**F-Droid**](https://f-droid.org/en/packages/org.strongswan.android/) 或 [**strongSwan 下载网站**](https://download.strongswan.org/Android/)下载并安装 strongSwan VPN 客户端。
1. 启动 strongSwan VPN 客户端,然后单击 **添加VPN配置**。
1. 在 **服务器地址** 字段中输入 `你的 VPN 服务器 IP` (或者域名)。
**注:** 如果你在配置 IKEv2 时指定了服务器的域名(而不是 IP 地址),则必须在 **服务器地址** 字段中输入该域名。
1. 在 **VPN 类型** 下拉菜单选择 **IKEv2 证书**。
1. 单击 **选择用户证书**,然后单击 **安装证书**。
1. 选择你从服务器传送过来的 `.p12` 文件,并按提示操作。
**注:** 要查找 `.p12` 文件,单击左上角的抽拉式菜单,然后浏览到你保存文件的目录。
1. **(重要)** 单击 **显示高级设置**。向下滚动,找到并启用 **Use RSA/PSS signatures** 选项。
1. 保存新的 VPN 连接,然后单击它以开始连接。
连接成功后,你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](#ikev2-故障排除)。
#### 使用系统自带的 IKEv2 客户端
[[支持者] **屏幕录影:** 使用 Android 11+ 系统自带的 VPN 客户端连接](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-X8X5FVFZC)
Android 11+ 用户也可以使用系统自带的 IKEv2 客户端连接。
1. 将生成的 `.p12` 文件安全地传送到你的 Android 设备。
1. 启动 **设置** App。
1. 进入 安全 -> 高级 -> 加密与凭据。
1. 单击 **安装证书**。
1. 单击 **VPN 和应用用户证书**。
1. 选择你从服务器传送过来的 `.p12` 文件。
**注:** 要查找 `.p12` 文件,单击左上角的抽拉式菜单,然后浏览到你保存文件的目录。
1. 为证书输入名称,然后单击 **确定**。
1. 进入 设置 -> 网络和互联网 -> VPN,然后单击 "+" 按钮。
1. 为 VPN 配置文件输入名称。
1. 在 **类型** 下拉菜单选择 **IKEv2/IPSec RSA**。
1. 在 **服务器地址** 字段中输入 `你的 VPN 服务器 IP` (或者域名)。
**注:** 它必须与 IKEv2 辅助脚本输出中的服务器地址 **完全一致**。
1. 在 **IPSec 标识符** 字段中输入任意内容。
**注:** 该字段不应该为必填项。它是 Android 的一个 bug。
1. 在 **IPSec 用户证书** 下拉菜单选择你导入的证书。
1. 在 **IPSec CA 证书** 下拉菜单选择你导入的证书。
1. 在 **IPSec 服务器证书** 下拉菜单选择 **(来自服务器)**。
1. 单击 **保存**。然后单击新的 VPN 连接并单击 **连接**。
连接成功后,你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](#ikev2-故障排除)。
### Chrome OS
首先,在 VPN 服务器上导出 CA 证书到 `ca.cer`:
```bash
sudo certutil -L -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" -a -o ca.cer
```
将生成的 `.p12` 文件和 `ca.cer` 文件安全地传送到你的 Chrome OS 设备。
安装用户证书和 CA 证书:
1. 在 Google Chrome 中打开新标签页。
1. 在地址栏中输入 **chrome://settings/certificates**
1. **(重要)** 单击 **导入并绑定** 而不是 **导入**。
1. 在对话框中选择你从服务器传送过来的 `.p12` 文件并选择 **打开**。
1. 如果证书没有密码,单击 **确定**。否则输入该证书的密码。
1. 单击上面的 **授权机构** 选项卡,然后单击 **导入**。
1. 在对话框中左下角的下拉菜单选择 **所有文件**。
1. 选择你从服务器传送过来的 `ca.cer` 文件并选择 **打开**。
1. 保持默认选项并单击 **确定**。
添加 VPN 连接:
1. 进入设置 -> 网络。
1. 单击 **添加连接**,然后单击 **添加内置 VPN**。
1. 在 **服务名称** 字段中输入任意内容。
1. 在 **提供商类型** 下拉菜单选择 **IPsec (IKEv2)**。
1. 在 **服务器主机名** 字段中输入 `你的 VPN 服务器 IP`(或者域名)。
1. 在 **身份验证类型** 下拉菜单选择 **用户证书**。
1. 在 **服务器 CA 证书** 下拉菜单选择 **IKEv2 VPN CA [IKEv2 VPN CA]**。
1. 在 **用户证书** 下拉菜单选择 **IKEv2 VPN CA [客户端名称]**。
1. 保持其他字段空白。
1. 启用 **保存身份信息和密码**。
1. 单击 **连接**。
连接成功后,网络状态图标上会出现 VPN 指示。你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
(可选功能)你可以选择启用 Chrome OS 上的 "始终开启的 VPN" 功能。要管理该设置,进入设置 -> 网络,然后单击 **VPN**。
如果在连接过程中遇到错误,请参见[故障排除](#ikev2-故障排除)。
### Linux
在配置 Linux 客户端之前,你必须更改 VPN 服务器上的以下设置:编辑服务器上的 `/etc/ipsec.d/ikev2.conf`。在 `conn ikev2-cp` 小节的末尾添加 `authby=rsa-sha1`,开头必须空两格。保存文件并运行 `service ipsec restart`。
要配置你的 Linux 计算机以作为客户端连接到 IKEv2,首先安装 NetworkManager 的 strongSwan 插件:
```bash
# Ubuntu and Debian
sudo apt-get update
sudo apt-get install network-manager-strongswan
# Arch Linux
sudo pacman -Syu # 升级所有软件包
sudo pacman -S networkmanager-strongswan
# Fedora
sudo yum install NetworkManager-strongswan-gnome
# CentOS
sudo yum install epel-release
sudo yum --enablerepo=epel install NetworkManager-strongswan-gnome
```
下一步,将生成的 `.p12` 文件安全地从 VPN 服务器传送到你的 Linux 计算机。然后提取 CA 证书,客户端证书和私钥。将下面示例中的 `vpnclient.p12` 换成你的 `.p12` 文件名。
```bash
# 示例:提取 CA 证书,客户端证书和私钥。在完成后可以删除 .p12 文件。
# 注:你可能需要输入 import password,它可以在 IKEv2 辅助脚本的输出中找到。
# 如果在脚本的输出中没有 import password,请按回车键继续。
# 注:如果使用 OpenSSL 3.x (运行 "openssl version" 进行检查),
# 请将 "-legacy" 附加到下面的 3 个命令。
openssl pkcs12 -in vpnclient.p12 -cacerts -nokeys -out ca.cer
openssl pkcs12 -in vpnclient.p12 -clcerts -nokeys -out client.cer
openssl pkcs12 -in vpnclient.p12 -nocerts -nodes -out client.key
rm vpnclient.p12
# (重要)保护证书和私钥文件
# 注:这一步是可选的,但强烈推荐。
sudo chown root:root ca.cer client.cer client.key
sudo chmod 600 ca.cer client.cer client.key
```
然后你可以创建并启用 VPN 连接:
1. 进入 Settings -> Network -> VPN。单击 **+** 按钮。
1. 选择 **IPsec/IKEv2 (strongswan)**。
1. 在 **Name** 字段中输入任意内容。
1. 在 **Gateway (Server)** 部分的 **Address** 字段中输入 `你的 VPN 服务器 IP`(或者域名)。
1. 为 **Certificate** 字段选择 `ca.cer` 文件。
1. 在 **Client** 部分的 **Authentication** 下拉菜单选择 **Certificate(/private key)**。
1. 在 **Certificate** 下拉菜单(如果存在)选择 **Certificate/private key**。
1. 为 **Certificate (file)** 字段选择 `client.cer` 文件。
1. 为 **Private key** 字段选择 `client.key` 文件。
1. 在 **Options** 部分,选中 **Request an inner IP address** 复选框。
1. 在 **Cipher proposals (Algorithms)** 部分,选中 **Enable custom proposals** 复选框。
1. 保持 **IKE** 字段空白。
1. 在 **ESP** 字段中输入 `aes128gcm16`.
1. 单击 **Add** 保存 VPN 连接信息。
1. 启用 **VPN** 连接。
另外,你也可以使用命令行连接。示例步骤请参见 [#1399](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1399)、[#1007](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1007) 和 [#1789](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1789)。如果你遇到错误 `Could not find source connection`,编辑 `/etc/netplan/01-netcfg.yaml` 并将 `renderer: networkd` 替换为 `renderer: NetworkManager`,然后运行 `sudo netplan apply`。如果使用 `nmcli` 连接到 VPN,运行 `sudo nmcli c up VPN`。要断开连接:`sudo nmcli c down VPN`。
连接成功后,你可以到[这里](https://www.ipchicken.com)检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。
如果在连接过程中遇到错误,请参见[故障排除](#ikev2-故障排除)。
### RouterOS
**注:** 这些步骤由 [@Unix-User](https://github.com/Unix-User) 提供。建议通过 SSH 连接运行终端命令,例如通过 Putty。
1. 将生成的 `.p12` 文件安全地传送到你的计算机。
单击查看屏幕录影。

2. 在 WinBox 中,转到 System > certificates > import. 将 `.p12` 证书文件导入两次(是的,导入同一个文件两次)。检查你的 certificates panel。你应该看到 2 个文件,其中标注 KT 的是密钥。
单击查看屏幕录影。

或者,你也可以使用终端命令 (empty passphrase):
```bash
[admin@MikroTik] > /certificate/import file-name=mikrotik.p12
passphrase:
certificates-imported: 2
private-keys-imported: 0
files-imported: 1
decryption-failures: 0
keys-with-no-certificate: 0
[admin@MikroTik] > /certificate/import file-name=mikrotik.p12
passphrase:
certificates-imported: 0
private-keys-imported: 1
files-imported: 1
decryption-failures: 0
keys-with-no-certificate: 0
```
3. 在 terminal 中运行以下命令。将以下内容替换为你自己的值。
`YOUR_VPN_SERVER_IP_OR_DNS_NAME` 是你的 VPN 服务器 IP 或域名。
`IMPORTED_CERTIFICATE` 是上面第 2 步中的证书名称,例如 `vpnclient.p12_0`
(标记为 KT 的行 - Priv. Key Trusted - 如果未标记为 KT,请再次导入证书)。
`THESE_ADDRESSES_GO_THROUGH_VPN` 是你想要通过 VPN 浏览因特网的本地网络地址。
假设 RouterOS 后面的本地网络是 `192.168.0.0/24`,你可以使用 `192.168.0.0/24`
来指定整个网络,或者使用 `192.168.0.10` 来指定仅用于一个设备,依此类推。
```bash
/ip firewall address-list add address=THESE_ADDRESSES_GO_THROUGH_VPN list=local
/ip ipsec mode-config add name=ike2-rw responder=no src-address-list=local
/ip ipsec policy group add name=ike2-rw
/ip ipsec profile add name=ike2-rw
/ip ipsec peer add address=YOUR_VPN_SERVER_IP_OR_DNS_NAME exchange-mode=ike2 \
name=ike2-rw-client profile=ike2-rw
/ip ipsec proposal add name=ike2-rw pfs-group=none
/ip ipsec identity add auth-method=digital-signature certificate=IMPORTED_CERTIFICATE \
generate-policy=port-strict mode-config=ike2-rw \
peer=ike2-rw-client policy-template-group=ike2-rw
/ip ipsec policy add group=ike2-rw proposal=ike2-rw template=yes
```
4. 更多信息请参见 [#1112](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1112#issuecomment-1059628623)。
> 已在以下系统测试
> mar/02/2022 12:52:57 by RouterOS 6.48
> RouterBOARD 941-2nD
## IKEv2 故障排除
*其他语言版本: [English](ikev2-howto.md#ikev2-troubleshooting), [中文](ikev2-howto-zh.md#ikev2-故障排除)。*
**另见:** [检查日志及 VPN 状态](clients-zh.md#检查日志及-vpn-状态),[IKEv1 故障排除](clients-zh.md#ikev1-故障排除)和[高级用法](advanced-usage-zh.md)。
* [无法连接到 VPN 服务器](#无法连接到-vpn-服务器)
* [Ubuntu 20.04 无法导入客户端配置](#ubuntu-2004-无法导入客户端配置)
* [macOS Sonoma 客户端重新连接](#macos-sonoma-客户端重新连接)
* [无法连接多个 IKEv2 客户端](#无法连接多个-ikev2-客户端)
* [IKE 身份验证凭证不可接受](#ike-身份验证凭证不可接受)
* [参数错误 policy match error](#参数错误-policy-match-error)
* [参数错误 parameter is incorrect](#参数错误-parameter-is-incorrect)
* [连接 IKEv2 后不能打开网站](#连接-ikev2-后不能打开网站)
* [Windows 10 正在连接](#windows-10-正在连接)
* [其它已知问题](#其它已知问题)
### 无法连接到 VPN 服务器
首先,请确保你的 VPN 客户端设备上指定的 VPN 服务器地址与 IKEv2 辅助脚本输出中的服务器地址**完全一致**。例如,如果在配置 IKEv2 时未指定域名,则不可以使用域名进行连接。要更改 IKEv2 服务器地址,参见[这一小节](#更改-ikev2-服务器地址)。
对于有外部防火墙的服务器(比如 [EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)/[GCE](https://cloud.google.com/vpc/docs/firewalls)),请为 VPN 打开 UDP 端口 500 和 4500。阿里云用户请参见 [#433](https://github.com/hwdsl2/setup-ipsec-vpn/issues/433)。
[检查日志及 VPN 状态](clients-zh.md#检查日志及-vpn-状态)是否有错误。如果你遇到 retransmission 相关错误并且无法连接,说明 VPN 客户端和服务器之间的网络可能有问题。如果你从中国大陆进行连接,请考虑改用 IPsec VPN 以外的其他解决方案。
### Ubuntu 20.04 无法导入客户端配置
如果你在 2024-04-10 之前安装了 IPsec VPN,并且你的 VPN 服务器运行的是 Ubuntu Linux 版本 20.04,那么你可能会遇到无法在 iOS 或 macOS 设备上导入新生成的客户端配置文件 (`.mobileconfig`) 的问题,例如提示密码不正确。这可能是由 Ubuntu 20.04 上 libnss3 相关软件包的更新引起的,需要对 IKEv2 脚本进行一些更改 ([25670f3](https://github.com/hwdsl2/setup-ipsec-vpn/commit/25670f3))。
要解决此问题,请首先按照[这些步骤](#更新-ikev2-辅助脚本)将服务器上的 IKEv2 脚本更新到最新版本。然后运行 `sudo ikev2.sh` 并选择 "export" 以重新创建客户端配置文件。
### macOS Sonoma 客户端重新连接
macOS 14 (Sonoma) 存在[一个小问题](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1486),可能会导致 IKEv2 VPN 每 24-48 分钟断开并重新连接一次。其他 macOS 版本不受影响。首先[检查你的 macOS 版本](https://support.apple.com/zh-cn/HT201260)。要解决此问题,请按以下步骤操作。
**注:** 如果你在 2023 年 12 月 10 日之后安装了 IPsec VPN,则无需执行任何操作,因为已经包含以下修复。
1. 编辑 VPN 服务器上的 `/etc/ipsec.d/ikev2.conf`。找到这一行:
```
ike=aes256-sha2,aes128-sha2,aes256-sha1,aes128-sha1
```
并将它替换为以下内容:
```
ike=aes_gcm_c_256-hmac_sha2_256-ecp_256,aes256-sha2,aes128-sha2,aes256-sha1,aes128-sha1
```
**注:** Docker 用户需要首先[在容器中运行 Bash shell](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/docs/advanced-usage-zh.md#在容器中运行-bash-shell)。
1. 保存文件并运行 `service ipsec restart`。Docker 用户:在下面的第 4 步之后退出 (`exit`) 容器并运行 `docker restart ipsec-vpn-server`。
1. 编辑 VPN 服务器上的 `/opt/src/ikev2.sh`。找到以下部分并将其替换为这些新值:
```
ChildSecurityAssociationParameters
DiffieHellmanGroup
19
EncryptionAlgorithm
AES-256-GCM
LifeTimeInMinutes
1410
```
```
IKESecurityAssociationParameters
DiffieHellmanGroup
19
EncryptionAlgorithm
AES-256-GCM
IntegrityAlgorithm
SHA2-256
LifeTimeInMinutes
1410
```
1. 运行 `sudo ikev2.sh` 为你的每个 macOS 设备导出(或添加)更新后的客户端配置文件。
1. 从你的 macOS 设备中移除之前导入的 IKEv2 配置文件(如果有),然后导入更新后的 `.mobileconfig` 文件。请参阅[配置 IKEv2 VPN 客户端](#配置-ikev2-vpn-客户端)。Docker 用户请看[配置并使用 IKEv2 VPN](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh.md#配置并使用-ikev2-vpn)。
### 无法连接多个 IKEv2 客户端
如果要同时连接在同一个 NAT(比如家用路由器)后面的多个 IKEv2 客户端,你需要为每个客户端生成唯一的证书。否则,你可能会遇到稍后连接的客户端影响现有客户端的 VPN 连接,从而导致无法访问 Internet 的问题。
要为其它的 IKEv2 客户端生成证书,运行辅助脚本并添加 `--addclient` 选项。要自定义客户端选项,可以在不添加参数的情况下运行脚本。
```bash
sudo ikev2.sh --addclient [client name]
```
### IKE 身份验证凭证不可接受
如果遇到此错误,请确保你的 VPN 客户端设备上指定的 VPN 服务器地址与 IKEv2 辅助脚本输出中的服务器地址**完全一致**。例如,如果在配置 IKEv2 时未指定域名,则不可以使用域名进行连接。要更改 IKEv2 服务器地址,参见[这一小节](#更改-ikev2-服务器地址)。
### 参数错误 policy match error
要解决此错误,你需要为 IKEv2 启用更强的加密算法,通过修改一次注册表来实现。请下载并导入下面的 `.reg` 文件,或者打开提升权限命令提示符并运行以下命令。
- 适用于 Windows 7, 8, 10 和 11 ([下载 .reg 文件](https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0/Enable_Stronger_Ciphers_for_IKEv2_on_Windows.reg))
```console
REG ADD HKLM\SYSTEM\CurrentControlSet\Services\RasMan\Parameters /v NegotiateDH2048_AES256 /t REG_DWORD /d 0x1 /f
```
### 参数错误 parameter is incorrect
如果你在尝试使用 IKEv2 模式连接时遇到 "错误 87:参数错误 The parameter is incorrect",请尝试[这个 Issue](https://github.com/trailofbits/algo/issues/1051) 中的解决方案,更具体地说,第 2 步 "reset device manager adapters"。
### 连接 IKEv2 后不能打开网站
如果你的 VPN 客户端设备在成功连接到 IKEv2 后无法打开网站,请尝试以下解决方案:
1. 某些云服务提供商,比如 [Google Cloud](https://cloud.google.com),[默认设置较低的 MTU](https://cloud.google.com/network-connectivity/docs/vpn/concepts/mtu-considerations)。这可能会导致 IKEv2 VPN 客户端的网络问题。要解决此问题,尝试在 VPN 服务器上将 MTU 设置为 1500:
```bash
# 将 ens4 替换为你的服务器上的网络接口名称
sudo ifconfig ens4 mtu 1500
```
此设置 **不会** 在重启后保持。要永久更改 MTU 大小,请参阅网络上的相关文章。
1. 如果你的 Android 或 Linux VPN 客户端可以连接到 IKEv2 但是无法打开网站,请尝试 [Android/Linux MTU/MSS 问题](clients-zh.md#androidlinux-mtumss-问题)中的解决方案。
1. Windows VPN 客户端在连接后可能不使用 IKEv2 指定的 DNS 服务器,如果该客户端的因特网适配器的 DNS 服务器在本地网段上。要解决此问题,可以在网络连接属性 -> TCP/IPv4 中手动输入 DNS 服务器,例如 Google Public DNS (8.8.8.8, 8.8.4.4)。更多信息请参见 [Windows DNS 泄漏和 IPv6](clients-zh.md#windows-dns-泄漏和-ipv6)。
### Windows 10 正在连接
如果你使用 Windows 10 并且 VPN 卡在 "正在连接" 状态超过几分钟,尝试以下步骤:
1. 右键单击系统托盘中的无线/网络图标。
1. 选择 **打开"网络和 Internet"设置**,然后在打开的页面中单击左侧的 **VPN**。
1. 选择新的 VPN 连接,然后单击 **连接**。
### 其它已知问题
Windows 自带的 VPN 客户端可能不支持 IKEv2 fragmentation(该功能[需要](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-ikee/74df968a-7125-431d-9c98-4ea929e548dc) Windows 10 v1803 或更新版本)。在有些网络上,这可能会导致连接错误或其它连接问题。你可以尝试换用 [IPsec/L2TP](clients-zh.md) 或 [IPsec/XAuth](clients-xauth-zh.md) 模式。
## 管理 IKEv2 客户端
* [列出已有的客户端](#列出已有的客户端)
* [添加客户端证书](#添加客户端证书)
* [导出已有的客户端的配置](#导出已有的客户端的配置)
* [删除客户端证书](#删除客户端证书)
* [吊销客户端证书](#吊销客户端证书)
### 列出已有的客户端
要列出已有的 IKEv2 客户端的名称,运行辅助脚本并添加 `--listclients` 选项。使用参数 `-h` 显示使用信息。
```bash
sudo ikev2.sh --listclients
```
### 添加客户端证书
要为其它的 IKEv2 客户端生成证书,运行辅助脚本并添加 `--addclient` 选项。要自定义客户端选项,可以在不添加参数的情况下运行脚本。
```bash
sudo ikev2.sh --addclient [client name]
```
另外,你也可以手动添加客户端证书。参见[这一小节](#手动配置-ikev2)的第 4 步。
### 导出已有的客户端的配置
在默认情况下,IKEv2 辅助脚本在运行后会导出客户端配置。如果之后你想要导出一个已有的客户端,可以运行:
```bash
sudo ikev2.sh --exportclient [client name]
```
### 删除客户端证书
**重要:** 从 IPsec 数据库中删除一个客户端证书 **并不能** 阻止 VPN 客户端使用该证书连接!对于此用例,你 **必须** [吊销该客户端证书](#吊销客户端证书),而不是删除证书。
首先,请阅读上面的重要说明。然后点这里查看详情。
**警告:** 这将**永久删除**客户端证书和私钥。此操作**不可撤销**!
如果要删除一个现有的客户端:
```bash
sudo ikev2.sh --deleteclient [client name]
```
或者,你也可以手动删除一个客户端证书。
1. 列出 IPsec 证书数据库中的证书:
```bash
certutil -L -d sql:/etc/ipsec.d
```
示例输出:
```
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
IKEv2 VPN CA CTu,u,u
($PUBLIC_IP) u,u,u
vpnclient u,u,u
```
1. 删除客户端证书和私钥。将下面的 "Nickname" 替换为你想要删除的客户端证书的昵称,例如 `vpnclient`。
```bash
certutil -F -d sql:/etc/ipsec.d -n "Nickname"
certutil -D -d sql:/etc/ipsec.d -n "Nickname" 2>/dev/null
```
1. (可选步骤)删除之前为该客户端生成的配置文件(`.p12`, `.mobileconfig` 和 `.sswan` 文件),如果存在。
### 吊销客户端证书
在某些情况下,你可能需要吊销一个之前生成的 VPN 客户端证书。
如果要吊销一个现有的客户端:
```bash
sudo ikev2.sh --revokeclient [client name]
```
另外,你也可以手动吊销客户端证书。
另外,你也可以手动吊销客户端证书。这可以通过 `crlutil` 实现。下面举例说明,这些命令必须用 `root` 账户运行。
1. 检查证书数据库,并且找到想要吊销的客户端证书的昵称。
```bash
certutil -L -d sql:/etc/ipsec.d
```
```
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
IKEv2 VPN CA CTu,u,u
($PUBLIC_IP) u,u,u
vpnclient-to-revoke u,u,u
```
在这个例子中,我们将要吊销昵称为 `vpnclient-to-revoke` 的客户端证书。它是由 `IKEv2 VPN CA` 签发的。
1. 找到该客户端证书的序列号。
```bash
certutil -L -d sql:/etc/ipsec.d -n "vpnclient-to-revoke"
```
```
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
00:cd:69:ff:74
... ...
```
根据上面的输出,我们知道该序列号为十六进制的 `CD69FF74`,也就是十进制的 `3446275956`。它将在以下步骤中使用。
1. 创建一个新的证书吊销列表 (CRL)。该步骤对于每个 CA 只需运行一次。
```bash
if ! crlutil -L -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" 2>/dev/null; then
crlutil -G -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" -c /dev/null
fi
```
```
CRL Info:
:
Version: 2 (0x1)
Signature Algorithm: PKCS #1 SHA-256 With RSA Encryption
Issuer: "O=IKEv2 VPN,CN=IKEv2 VPN CA"
This Update: Sat Jun 06 22:00:00 2020
CRL Extensions:
```
1. 将你想要吊销的客户端证书添加到 CRL。在这里我们指定该证书的(十进制)序列号,以及吊销时间(UTC时间,格式:GeneralizedTime (YYYYMMDDhhmmssZ))。
```bash
crlutil -M -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" <
## 更改 IKEv2 服务器地址
在某些情况下,你可能需要在配置之后更改 IKEv2 服务器地址。例如切换为使用域名,或者在服务器的 IP 更改之后。请注意,你在 VPN 客户端指定的服务器地址必须与 IKEv2 辅助脚本输出中的服务器地址 **完全一致**,否则客户端可能无法连接。
要更改服务器地址,运行[辅助脚本](../extras/ikev2changeaddr.sh)并按提示操作。
```bash
wget https://get.vpnsetup.net/ikev2addr -O ikev2addr.sh
sudo bash ikev2addr.sh
```
**重要:** 运行此脚本后,你必须手动更新任何现有 IKEv2 客户端设备上的服务器地址以及 Remote ID(如果适用)。对于 iOS 客户端,你需要运行 `sudo ikev2.sh` 以导出更新后的客户端配置文件并导入 iOS 设备。
## 更新 IKEv2 辅助脚本
IKEv2 辅助脚本会不时更新,以进行错误修复和改进([更新日志](https://github.com/hwdsl2/setup-ipsec-vpn/commits/master/extras/ikev2setup.sh))。 当有新版本可用时,你可以更新服务器上的 IKEv2 辅助脚本。这是可选的。请注意,这些命令将覆盖任何现有的 `ikev2.sh`。
```bash
wget https://get.vpnsetup.net/ikev2 -O /opt/src/ikev2.sh
chmod +x /opt/src/ikev2.sh && ln -s /opt/src/ikev2.sh /usr/bin 2>/dev/null
```
## 使用辅助脚本配置 IKEv2
**注:** 默认情况下,运行 VPN 安装脚本时会自动配置 IKEv2。你可以跳过此部分并转到[配置 IKEv2 VPN 客户端](#配置-ikev2-vpn-客户端)。
**重要:** 在继续之前,你应该已经成功地[搭建自己的 VPN 服务器](../README-zh.md)。Docker 用户请看[配置并使用 IKEv2 VPN](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh.md#配置并使用-ikev2-vpn)。
使用这个[辅助脚本](../extras/ikev2setup.sh)来自动地在 VPN 服务器上配置 IKEv2:
```bash
# 使用默认选项配置 IKEv2
sudo ikev2.sh --auto
# 或者你也可以自定义 IKEv2 选项
sudo ikev2.sh
```
**注:** 如果已配置 IKEv2,但是你想要自定义 IKEv2 选项,首先[移除 IKEv2](#移除-ikev2),然后运行 `sudo ikev2.sh` 重新配置。
在完成之后,请转到[配置 IKEv2 VPN 客户端](#配置-ikev2-vpn-客户端)。高级用户可以启用[仅限 IKEv2 模式](advanced-usage-zh.md#仅限-ikev2-的-vpn)。这是可选的。
错误:"sudo: ikev2.sh: command not found".
如果你使用了较早版本的 VPN 安装脚本,这是正常的。首先下载 IKEv2 辅助脚本:
```bash
wget https://get.vpnsetup.net/ikev2 -O /opt/src/ikev2.sh
chmod +x /opt/src/ikev2.sh && ln -s /opt/src/ikev2.sh /usr/bin
```
然后按照上面的说明运行脚本。
你可以指定一个域名,客户端名称和/或另外的 DNS 服务器。这是可选的。
在使用自动模式安装 IKEv2 时,高级用户可以指定一个域名作为 IKEv2 服务器地址。这是可选的。该域名必须是一个全称域名(FQDN)。示例如下:
```bash
sudo VPN_DNS_NAME='vpn.example.com' ikev2.sh --auto
```
类似地,你可以指定第一个 IKEv2 客户端的名称。如果未指定,则使用默认值 `vpnclient`。
```bash
sudo VPN_CLIENT_NAME='your_client_name' ikev2.sh --auto
```
在 VPN 已连接时,IKEv2 客户端默认配置为使用 [Google Public DNS](https://developers.google.com/speed/public-dns/)。你可以为 IKEv2 指定另外的 DNS 服务器。示例如下:
```bash
sudo VPN_DNS_SRV1=1.1.1.1 VPN_DNS_SRV2=1.0.0.1 ikev2.sh --auto
```
默认情况下,导入 IKEv2 客户端配置时不需要密码。你可以选择使用随机密码保护客户端配置文件。
```bash
sudo VPN_PROTECT_CONFIG=yes ikev2.sh --auto
```
查看 IKEv2 脚本的使用信息。
```
Usage: bash ikev2.sh [options]
Options:
--auto run IKEv2 setup in auto mode using default options (for initial setup only)
--addclient [client name] add a new client using default options
--exportclient [client name] export configuration for an existing client
--listclients list the names of existing clients
--revokeclient [client name] revoke an existing client
--deleteclient [client name] delete an existing client
--removeikev2 remove IKEv2 and delete all certificates and keys from the IPsec database
-y, --yes assume "yes" as answer to prompts when revoking/deleting a client or removing IKEv2
-h, --help show this help message and exit
To customize IKEv2 or client options, run this script without arguments.
```
## 手动配置 IKEv2
除了使用[辅助脚本](#使用辅助脚本配置-ikev2)之外,高级用户也可以手动在 VPN 服务器上配置 IKEv2。在继续之前,推荐[升级 Libreswan](../README-zh.md#升级libreswan) 到最新版本。
下面举例说明如何手动在 Libreswan 上配置 IKEv2。以下命令必须用 `root` 账户运行。
查看手动在 Libreswan 上配置 IKEv2 的示例步骤。
1. 获取 VPN 服务器的公共 IP 地址,将它保存到变量并检查。
```bash
PUBLIC_IP=$(dig @resolver1.opendns.com -t A -4 myip.opendns.com +short)
[ -z "$PUBLIC_IP" ] && PUBLIC_IP=$(wget -t 2 -T 10 -qO- http://ipv4.icanhazip.com)
printf '%s\n' "$PUBLIC_IP"
```
检查并确保以上命令的输出与服务器的公共 IP 一致。该变量将在以下步骤中使用。
**注:** 另外,在这里你也可以指定 VPN 服务器的域名。例如: `PUBLIC_IP=myvpn.example.com`。
1. 添加一个新的 IKEv2 连接:
```bash
if ! grep -qs '^include /etc/ipsec\.d/\*\.conf$' /etc/ipsec.conf; then
echo >> /etc/ipsec.conf
echo 'include /etc/ipsec.d/*.conf' >> /etc/ipsec.conf
fi
```
**注:** 如果你在上面的第一步指定了服务器的域名(而不是 IP 地址),则必须将以下命令中的 `leftid=$PUBLIC_IP` 换成 `leftid=@$PUBLIC_IP`。
```bash
cat > /etc/ipsec.d/ikev2.conf <> /etc/ipsec.d/ikev2.conf <> /etc/ipsec.d/ikev2.conf <> /etc/ipsec.d/ikev2.conf <
Is this a critical extension [y/N]?
N
```
生成 VPN 服务器证书:
**注:** 如果你在上面的第一步指定了服务器的域名(而不是 IP 地址),则必须将以下命令中的 `--extSAN "ip:$PUBLIC_IP,dns:$PUBLIC_IP"` 换成 `--extSAN "dns:$PUBLIC_IP"`。
```bash
certutil -z <(head -c 1024 /dev/urandom) \
-S -c "IKEv2 VPN CA" -n "$PUBLIC_IP" \
-s "O=IKEv2 VPN,CN=$PUBLIC_IP" \
-k rsa -g 3072 -v 120 \
-d sql:/etc/ipsec.d -t ",," \
--keyUsage digitalSignature,keyEncipherment \
--extKeyUsage serverAuth \
--extSAN "ip:$PUBLIC_IP,dns:$PUBLIC_IP"
```
```
Generating key. This may take a few moments...
```
1. 生成客户端证书,然后导出 `.p12` 文件,该文件包含客户端证书,私钥以及 CA 证书。
**注:** 你可以重复本步骤来为其它的客户端生成证书,但必须将所有的 `vpnclient` 换成比如 `vpnclient2`,等等。如果要同时连接在同一个 NAT(比如家用路由器)后面的多个 IKEv2 客户端,你需要为每个客户端生成唯一的证书。
生成客户端证书:
```bash
certutil -z <(head -c 1024 /dev/urandom) \
-S -c "IKEv2 VPN CA" -n "vpnclient" \
-s "O=IKEv2 VPN,CN=vpnclient" \
-k rsa -g 3072 -v 120 \
-d sql:/etc/ipsec.d -t ",," \
--keyUsage digitalSignature,keyEncipherment \
--extKeyUsage serverAuth,clientAuth -8 "vpnclient"
```
```
Generating key. This may take a few moments...
```
导出 `.p12` 文件:
```bash
pk12util -d sql:/etc/ipsec.d -n "vpnclient" -o vpnclient.p12
```
```
Enter password for PKCS12 file:
Re-enter password:
pk12util: PKCS12 EXPORT SUCCESSFUL
```
指定一个安全的密码以保护导出的 `.p12` 文件(在导入到 iOS 或 macOS 设备时,该密码不能为空)。
1. (适用于 iOS 客户端) 导出 CA 证书到 `ca.cer`:
```bash
certutil -L -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" -a -o ca.cer
```
1. 证书数据库现在应该包含以下内容:
```bash
certutil -L -d sql:/etc/ipsec.d
```
```
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
IKEv2 VPN CA CTu,u,u
($PUBLIC_IP) u,u,u
vpnclient u,u,u
```
**注:** 如需显示证书内容,可使用 `certutil -L -d sql:/etc/ipsec.d -n "Nickname"`。要吊销客户端证书,请转到[这一节](#吊销客户端证书)。关于 `certutil` 的其它用法参见[这里](https://firefox-source-docs.mozilla.org/security/nss/legacy/tools/nss_tools_certutil/index.html)。
1. **(重要)重启 IPsec 服务**:
```bash
service ipsec restart
```
在继续之前,你**必须**重启 IPsec 服务。VPN 服务器上的 IKEv2 配置到此已完成。下一步:[配置 VPN 客户端](#配置-ikev2-vpn-客户端)。
## 移除 IKEv2
如果你想要从 VPN 服务器移除 IKEv2,但是保留 [IPsec/L2TP](clients-zh.md) 和 [IPsec/XAuth ("Cisco IPsec")](clients-xauth-zh.md) 模式(如果已安装),可以运行辅助脚本。**警告:** 这将**永久删除**所有的 IKEv2 配置(包括证书和密钥),并且**不可撤销**!
```bash
sudo ikev2.sh --removeikev2
```
在移除 IKEv2 之后,如果你想要重新配置 IKEv2,参见[这一小节](#使用辅助脚本配置-ikev2)。
另外,你也可以手动移除 IKEv2。
要手动从 VPN 服务器移除 IKEv2,但是保留 [IPsec/L2TP](clients-zh.md) 和 [IPsec/XAuth ("Cisco IPsec")](clients-xauth-zh.md) 模式,按照以下步骤操作。这些命令必须用 `root` 账户运行。
**警告:** 这将**永久删除**所有的 IKEv2 配置(包括证书和密钥),并且**不可撤销**!
1. 重命名(或者删除)IKEv2 配置文件:
```bash
mv /etc/ipsec.d/ikev2.conf /etc/ipsec.d/ikev2.conf.bak
```
**注:** 如果你使用了较旧版本(2020-05-31 之前)的 IKEv2 辅助脚本或者配置说明,文件 `/etc/ipsec.d/ikev2.conf` 可能不存在。在该情况下,请移除文件 `/etc/ipsec.conf` 中的 `conn ikev2-cp` 部分。
1. **(重要)重启 IPsec 服务**:
```bash
service ipsec restart
```
1. 列出 IPsec 证书数据库中的证书:
```bash
certutil -L -d sql:/etc/ipsec.d
```
示例输出:
```
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
IKEv2 VPN CA CTu,u,u
($PUBLIC_IP) u,u,u
vpnclient u,u,u
```
1. 删除证书吊销列表 (CRL),如果存在:
```bash
crlutil -D -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" 2>/dev/null
```
1. 删除证书和密钥。将下面的 "Nickname" 替换为每个证书的昵称。为每个证书重复这些命令。在完成后,再次列出 IPsec 证书数据库中的证书,并确认列表为空。
```bash
certutil -F -d sql:/etc/ipsec.d -n "Nickname"
certutil -D -d sql:/etc/ipsec.d -n "Nickname" 2>/dev/null
```
## 参考链接
* https://libreswan.org/wiki/VPN_server_for_remote_clients_using_IKEv2
* https://libreswan.org/wiki/HOWTO:_Using_NSS_with_libreswan
* https://libreswan.org/man/ipsec.conf.5.html
* https://docs.strongswan.org/docs/5.9/interop/windowsClients.html
* https://docs.strongswan.org/docs/5.9/os/androidVpnClient.html
* https://firefox-source-docs.mozilla.org/security/nss/legacy/tools/nss_tools_certutil/index.html
* https://firefox-source-docs.mozilla.org/security/nss/legacy/tools/nss_tools_crlutil/index.html
## 授权协议
版权所有 (C) 2016-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
[](http://creativecommons.org/licenses/by-sa/3.0/)
这个项目是以[知识共享署名-相同方式共享3.0](http://creativecommons.org/licenses/by-sa/3.0/) 许可协议授权。
必须署名: 请包括我的名字在任何衍生产品,并且让我知道你是如何改善它的!
================================================
FILE: docs/ikev2-howto.md
================================================
[English](ikev2-howto.md) | [中文](ikev2-howto-zh.md)
# Guide: How to Set Up and Use IKEv2 VPN
* [Introduction](#introduction)
* [Configure IKEv2 VPN clients](#configure-ikev2-vpn-clients)
* [IKEv2 troubleshooting](#ikev2-troubleshooting)
* [Manage IKEv2 clients](#manage-ikev2-clients)
* [Change IKEv2 server address](#change-ikev2-server-address)
* [Update IKEv2 helper script](#update-ikev2-helper-script)
* [Set up IKEv2 using helper script](#set-up-ikev2-using-helper-script)
* [Manually set up IKEv2](#manually-set-up-ikev2)
* [Remove IKEv2](#remove-ikev2)
## Introduction
Modern operating systems support the IKEv2 standard. Internet Key Exchange (IKE or IKEv2) is the protocol used to set up a Security Association (SA) in the IPsec protocol suite. Compared to IKE version 1, IKEv2 contains [improvements](https://en.wikipedia.org/wiki/Internet_Key_Exchange#Improvements_with_IKEv2) such as Standard Mobility support through MOBIKE, and improved reliability.
Libreswan can authenticate IKEv2 clients on the basis of X.509 Machine Certificates using RSA signatures. This method does not require an IPsec PSK, username or password. It can be used with Windows, macOS, iOS, Android, Chrome OS, Linux and RouterOS.
By default, IKEv2 is automatically set up when running the VPN setup script. If you want to learn more about setting up IKEv2, see [Set up IKEv2 using helper script](#set-up-ikev2-using-helper-script). Docker users, see [Configure and use IKEv2 VPN](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README.md#configure-and-use-ikev2-vpn).
## Configure IKEv2 VPN clients
**Note:** To add or export IKEv2 clients, run `sudo ikev2.sh`. Use `-h` to show usage. Client config files can be safely deleted after import.
* [Windows 7, 8, 10 and 11](#windows-7-8-10-and-11)
* [OS X (macOS)](#os-x-macos)
* [iOS (iPhone/iPad)](#ios)
* [Android](#android)
* [Chrome OS (Chromebook)](#chrome-os)
* [Linux](#linux)
* [MikroTik RouterOS](#routeros)
Learn how to change the IKEv2 server address.
In certain circumstances, you may need to change the IKEv2 server address. For example, to switch to use a DNS name, or after server IP changes. Learn more in [this section](#change-ikev2-server-address).
### Windows 7, 8, 10 and 11
#### Auto-import configuration
[**Screencast:** IKEv2 Auto Import Configuration on Windows](https://ko-fi.com/post/IKEv2-Auto-Import-Configuration-on-Windows-8-10-a-K3K1DQCHW)
**Windows 8, 10 and 11+** users can automatically import IKEv2 configuration:
1. Securely transfer the generated `.p12` file to your computer.
1. Right-click on [ikev2_config_import.cmd](https://github.com/hwdsl2/vpn-extras/releases/latest/download/ikev2_config_import.cmd) and save this helper script to the **same folder** as the `.p12` file.
1. Right-click on the saved script, select **Properties**. Click on **Unblock** at the bottom, then click on **OK**.
1. Right-click on the saved script, select **Run as administrator** and follow the prompts.
To connect to the VPN: Click on the wireless/network icon in your system tray, select the new VPN entry, and click **Connect**. Once connected, you can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](#ikev2-troubleshooting).
**Note:** If you reinstalled the VPN server, you may want to first remove existing IKEv2 client and CA certificates, then follow the steps above to import the new `.p12` file. This helps make sure that Windows uses the correct client certificate when connecting to the VPN. See "Remove the IKEv2 VPN connection" below for more details.
#### Manually import configuration
[[Supporters] **Screencast:** IKEv2 Manually Import Configuration on Windows](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-O5O7FVF8J)
Alternatively, **Windows 7, 8, 10 and 11+** users can manually import IKEv2 configuration:
1. Securely transfer the generated `.p12` file to your computer, then import it into the certificate store.
To import the `.p12` file, run the following from an [elevated command prompt](http://www.winhelponline.com/blog/open-elevated-command-prompt-windows/):
```console
# Import .p12 file (replace with your own value)
certutil -f -importpfx "\path\to\your\file.p12" NoExport
```
**Note:** If there is no password for client config files, press Enter to continue, or if manually importing the `.p12` file, leave the password field blank.
Alternatively, you can [manually import the .p12 file](https://wiki.strongswan.org/projects/strongswan/wiki/Win7Certs/9). Make sure that the client cert is placed in "Personal -> Certificates", and the CA cert is placed in "Trusted Root Certification Authorities -> Certificates".
1. On the Windows computer, add a new IKEv2 VPN connection.
For **Windows 8, 10 and 11+**, it is recommended to create the VPN connection using the following commands from a command prompt, for improved security and performance.
```console
# Create VPN connection (replace server address with your own value)
powershell -command ^"Add-VpnConnection -ServerAddress 'Your VPN Server IP (or DNS name)' ^
-Name 'My IKEv2 VPN' -TunnelType IKEv2 -AuthenticationMethod MachineCertificate ^
-EncryptionLevel Required -PassThru^"
# Set IPsec configuration
powershell -command ^"Set-VpnConnectionIPsecConfiguration -ConnectionName 'My IKEv2 VPN' ^
-AuthenticationTransformConstants GCMAES128 -CipherTransformConstants GCMAES128 ^
-EncryptionMethod AES256 -IntegrityCheckMethod SHA256 -PfsGroup None ^
-DHGroup Group14 -PassThru -Force^"
```
**Windows 7** does not support these commands, you can [manually create the VPN connection](https://wiki.strongswan.org/projects/strongswan/wiki/Win7Config/8).
**Note:** The server address you specify must **exactly match** the server address in the output of the IKEv2 helper script. For example, if you specified the server's DNS name during IKEv2 setup, you must enter the DNS name in the **Internet address** field.
1. **This step is required if you manually created the VPN connection.**
Enable stronger ciphers for IKEv2 with a one-time registry change. Download and import the `.reg` file below, or run the following from an elevated command prompt. Read more [here](https://docs.strongswan.org/docs/5.9/interop/windowsClients.html).
- For Windows 7, 8, 10 and 11 ([download .reg file](https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0/Enable_Stronger_Ciphers_for_IKEv2_on_Windows.reg))
```console
REG ADD HKLM\SYSTEM\CurrentControlSet\Services\RasMan\Parameters /v NegotiateDH2048_AES256 /t REG_DWORD /d 0x1 /f
```
To connect to the VPN: Click on the wireless/network icon in your system tray, select the new VPN entry, and click **Connect**. Once connected, you can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](#ikev2-troubleshooting).
Remove the IKEv2 VPN connection.
Using the following steps, you can remove the VPN connection and optionally restore the computer to the status before IKEv2 configuration import.
1. Remove the added VPN connection in Windows Settings -> Network -> VPN. Windows 7 users can remove the VPN connection in Network and Sharing Center -> Change adapter settings.
1. (Optional) Remove IKEv2 certificates.
1. **Windows 8, 10 and 11:** Press Win+R and enter `certlm.msc`, or search for `certlm.msc` in the Start Menu. Open *Certificates - Local Computer*.
**Windows 7:** Press Win+R and enter `mmc`, or search for `mmc` in the Start Menu. Open *Management Console*. Open `File - Add/Remove Snap-In`. Select to add `Certificates` and in the window that opens, select `Computer account -> Local Computer`. Click on `Finish -> OK` to save the settings.
1. Go to Certificates -> Personal -> Certificates and delete the IKEv2 client certificate. The name of the certificate is the same as the IKEv2 client name you specified (default: `vpnclient`). The certificate was issued by `IKEv2 VPN CA`.
1. Go to Certificates -> Trusted Root Certification Authorities -> Certificates and delete the IKEv2 VPN CA certificate. The certificate was issued to `IKEv2 VPN CA` by `IKEv2 VPN CA`. Before deleting, make sure that there are no other certificate(s) issued by `IKEv2 VPN CA` in Certificates -> Personal -> Certificates.
1. (Optional. For users who manually created the VPN connection) Restore registry settings. Note that you should backup the registry before editing.
1. Press Win+R, or search for `regedit` in the Start Menu. Open *Registry Editor*.
1. Go to `HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Rasman\Parameters` and delete the item with name `NegotiateDH2048_AES256`, if it exists.
### OS X (macOS)
[[Supporters] **Screencast:** IKEv2 Import Configuration and Connect on macOS](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-O5O7FVF8J)
First, securely transfer the generated `.mobileconfig` file to your Mac, then double-click and follow the prompts to import as a macOS profile. If your Mac runs macOS Big Sur or newer, open System Preferences and go to the Profiles section to finish importing. For macOS Ventura and newer, open System Settings and search for Profiles. When finished, check to make sure "IKEv2 VPN" is listed under System Preferences -> Profiles.
To connect to the VPN:
1. Open System Preferences and go to the Network section.
1. Select the VPN connection with `Your VPN Server IP` (or DNS name).
1. Check the **Show VPN status in menu bar** checkbox. For macOS Ventura and newer, this setting can be configured in System Settings -> Control Center -> Menu Bar Only section.
1. Click **Connect**, or slide the VPN switch ON.
(Optional feature) Enable **VPN On Demand** to automatically start a VPN connection when your Mac is on Wi-Fi. To enable, check the **Connect on demand** checkbox for the VPN connection, and click **Apply**. To find this setting on macOS Ventura and newer, click on the "i" icon on the right of the VPN connection.
You can customize VPN On Demand rules to exclude certain Wi-Fi networks (such as your home network). For more information, see the chapter "Guide: Customize IKEv2 VPN On Demand rules for macOS and iOS" in [:book: Book: Set Up Your Own IPsec VPN, OpenVPN and WireGuard Server](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-O5O7FVF8J).
If you manually set up IKEv2 without using the helper script, click here for instructions.
First, securely transfer the generated `.p12` file to your Mac, then double-click to import into the **login** keychain in **Keychain Access**. Next, double-click on the imported `IKEv2 VPN CA` certificate, expand **Trust** and select **Always Trust** from the **IP Security (IPsec)** drop-down menu. Close the dialog using the red "X" on the top-left corner. When prompted, use Touch ID or enter your password and click "Update Settings".
When finished, check to make sure both the new client certificate and `IKEv2 VPN CA` are listed under the **Certificates** category of **login** keychain.
1. Open System Preferences and go to the Network section.
1. Click the **+** button in the lower-left corner of the window.
1. Select **VPN** from the **Interface** drop-down menu.
1. Select **IKEv2** from the **VPN Type** drop-down menu.
1. Enter anything you like for the **Service Name**.
1. Click **Create**.
1. Enter `Your VPN Server IP` (or DNS name) for the **Server Address**.
**Note:** If you specified the server's DNS name (instead of its IP address) during IKEv2 setup, you must enter the DNS name in the **Server Address** and **Remote ID** fields.
1. Enter `Your VPN Server IP` (or DNS name) for the **Remote ID**.
1. Enter `Your VPN client name` in the **Local ID** field.
**Note:** This must match exactly the client name you specified during IKEv2 setup. Same as the first part of your `.p12` filename.
1. Click the **Authentication Settings...** button.
1. Select **None** from the **Authentication Settings** drop-down menu.
1. Select the **Certificate** radio button, then select the new client certificate.
1. Click **OK**.
1. Check the **Show VPN status in menu bar** checkbox.
1. Click **Apply** to save the VPN connection information.
1. Click **Connect**.
Once connected, you can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](#ikev2-troubleshooting).
**Note:** macOS 14 (Sonoma) has a minor issue that may cause IKEv2 VPN to disconnect and reconnect once every 24-48 minutes. Other macOS versions are not affected. For more details and a workaround, see [macOS Sonoma clients reconnect](#macos-sonoma-clients-reconnect).
Remove the IKEv2 VPN connection.
To remove the IKEv2 VPN connection, open System Preferences -> Profiles and remove the IKEv2 VPN profile you added.
### iOS
[[Supporters] **Screencast:** IKEv2 Import Configuration and Connect on iOS (iPhone & iPad)](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-O5O7FVF8J)
First, securely transfer the generated `.mobileconfig` file to your iOS device, then import it as an iOS profile. To transfer the file, you may use:
1. AirDrop, or
1. Upload to your device (any App folder) using [File Sharing](https://support.apple.com/en-us/HT210598), then open the "Files" App on your iOS device, move the uploaded file to the "On My iPhone" folder. After that, tap the file and go to the "Settings" App to import, or
1. Host the file on a secure website of yours, then download and import it in Mobile Safari.
When finished, check to make sure "IKEv2 VPN" is listed under Settings -> General -> VPN & Device Management or Profile(s).
To connect to the VPN:
1. Go to Settings -> VPN. Select the VPN connection with `Your VPN Server IP` (or DNS name).
1. Slide the **VPN** switch ON.
(Optional feature) Enable **VPN On Demand** to automatically start a VPN connection when your iOS device is on Wi-Fi. To enable, tap the "i" icon on the right of the VPN connection, and enable **Connect On Demand**.
You can customize VPN On Demand rules to exclude certain Wi-Fi networks (such as your home network). For more information, see the chapter "Guide: Customize IKEv2 VPN On Demand rules for macOS and iOS" in [:book: Book: Set Up Your Own IPsec VPN, OpenVPN and WireGuard Server](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-O5O7FVF8J).
Customize VPN On Demand rules: Connect on Wi-Fi and cellular networks.
The default VPN On Demand configuration only starts a VPN connection on Wi-Fi networks, but not on cellular networks. If you want the VPN to connect on both Wi-Fi and cellular networks:
1. Edit `/opt/src/ikev2.sh` on the VPN server. Find the lines:
```
InterfaceTypeMatch
Cellular
Action
Disconnect
```
and replace "Disconnect" with "Connect":
```
InterfaceTypeMatch
Cellular
Action
Connect
```
2. Save the file, then run `sudo ikev2.sh` to export updated client config files for your iOS device(s).
3. Remove the previously imported VPN profile from your iOS device(s), then import the new `.mobileconfig` file(s) from step 2.
If you manually set up IKEv2 without using the helper script, click here for instructions.
First, securely transfer the generated `ca.cer` and `.p12` files to your iOS device, then import them one by one as iOS profiles. To transfer the files, you may use:
1. AirDrop, or
1. Upload to your device (any App folder) using [File Sharing](https://support.apple.com/en-us/HT210598), then open the "Files" App on your iOS device, move the uploaded files to the "On My iPhone" folder. After that, tap each file and go to the "Settings" App to import, or
1. Host the files on a secure website of yours, then download and import them in Mobile Safari.
When finished, check to make sure both the new client certificate and `IKEv2 VPN CA` are listed under Settings -> General -> VPN & Device Management or Profile(s).
1. Go to Settings -> General -> VPN & Device Management -> VPN.
1. Tap **Add VPN Configuration...**.
1. Tap **Type**. Select **IKEv2** and go back.
1. Tap **Description** and enter anything you like.
1. Tap **Server** and enter `Your VPN Server IP` (or DNS name).
**Note:** If you specified the server's DNS name (instead of its IP address) during IKEv2 setup, you must enter the DNS name in the **Server** and **Remote ID** fields.
1. Tap **Remote ID** and enter `Your VPN Server IP` (or DNS name).
1. Enter `Your VPN client name` in the **Local ID** field.
**Note:** This must match exactly the client name you specified during IKEv2 setup. Same as the first part of your `.p12` filename.
1. Tap **User Authentication**. Select **None** and go back.
1. Make sure the **Use Certificate** switch is ON.
1. Tap **Certificate**. Select the new client certificate and go back.
1. Tap **Done**.
1. Slide the **VPN** switch ON.
Once connected, you can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](#ikev2-troubleshooting).
Remove the IKEv2 VPN connection.
To remove the IKEv2 VPN connection, open Settings -> General -> VPN & Device Management or Profile(s) and remove the IKEv2 VPN profile you added.
### Android
#### Using strongSwan VPN client
[[Supporters] **Screencast:** Connect using Android strongSwan VPN Client](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-O5O7FVF8J)
Android users can connect using strongSwan VPN client (recommended).
1. Securely transfer the generated `.sswan` file to your Android device.
1. Install strongSwan VPN Client from [**Google Play**](https://play.google.com/store/apps/details?id=org.strongswan.android), [**F-Droid**](https://f-droid.org/en/packages/org.strongswan.android/) or [**strongSwan download server**](https://download.strongswan.org/Android/).
1. Launch the strongSwan VPN client.
1. Tap the "more options" menu on top right, then tap **Import VPN profile**.
1. Choose the `.sswan` file you transferred from the VPN server.
**Note:** To find the `.sswan` file, tap the three-line menu button, then browse to the location you saved the file.
1. On the "Import VPN profile" screen, tap **IMPORT CERTIFICATE FROM VPN PROFILE**, and follow the prompts.
1. On the "Choose certificate" screen, select the new client certificate, then tap **Select**.
1. Tap **IMPORT**.
1. Tap the new VPN profile to connect.
(Optional feature) You can choose to enable the "Always-on VPN" feature on Android. Launch the **Settings** app, go to Network & internet -> Advanced -> VPN, click the gear icon on the right of "strongSwan VPN Client", then enable the **Always-on VPN** and **Block connections without VPN** options.
If your device runs Android 6.0 or older, click here for additional instructions.
If your device runs Android 6.0 (Marshmallow) or older, in order to connect using the strongSwan VPN client, you must make the following change on the VPN server: Edit `/etc/ipsec.d/ikev2.conf` on the server. Append `authby=rsa-sha1` to the end of the `conn ikev2-cp` section, indented by two spaces. Save the file and run `service ipsec restart`.
If you manually set up IKEv2 without using the helper script, click here for instructions.
**Android 10 and newer:**
1. Securely transfer the generated `.p12` file to your Android device.
1. Install strongSwan VPN Client from [**Google Play**](https://play.google.com/store/apps/details?id=org.strongswan.android), [**F-Droid**](https://f-droid.org/en/packages/org.strongswan.android/) or [**strongSwan download server**](https://download.strongswan.org/Android/).
1. Launch the **Settings** application.
1. Go to Security -> Advanced -> Encryption & credentials.
1. Tap **Install a certificate**.
1. Tap **VPN & app user certificate**.
1. Choose the `.p12` file you transferred from the VPN server, and follow the prompts.
**Note:** To find the `.p12` file, tap the three-line menu button, then browse to the location you saved the file.
1. Launch the strongSwan VPN client and tap **Add VPN Profile**.
1. Enter `Your VPN Server IP` (or DNS name) in the **Server** field.
**Note:** If you specified the server's DNS name (instead of its IP address) during IKEv2 setup, you must enter the DNS name in the **Server** field.
1. Select **IKEv2 Certificate** from the **VPN Type** drop-down menu.
1. Tap **Select user certificate**, select the new client certificate and confirm.
1. **(Important)** Tap **Show advanced settings**. Scroll down, find and enable the **Use RSA/PSS signatures** option.
1. Save the new VPN connection, then tap to connect.
**Android 4 to 9:**
1. Securely transfer the generated `.p12` file to your Android device.
1. Install strongSwan VPN Client from [**Google Play**](https://play.google.com/store/apps/details?id=org.strongswan.android), [**F-Droid**](https://f-droid.org/en/packages/org.strongswan.android/) or [**strongSwan download server**](https://download.strongswan.org/Android/).
1. Launch the strongSwan VPN client and tap **Add VPN Profile**.
1. Enter `Your VPN Server IP` (or DNS name) in the **Server** field.
**Note:** If you specified the server's DNS name (instead of its IP address) during IKEv2 setup, you must enter the DNS name in the **Server** field.
1. Select **IKEv2 Certificate** from the **VPN Type** drop-down menu.
1. Tap **Select user certificate**, then tap **Install certificate**.
1. Choose the `.p12` file you transferred from the VPN server, and follow the prompts.
**Note:** To find the `.p12` file, tap the three-line menu button, then browse to the location you saved the file.
1. **(Important)** Tap **Show advanced settings**. Scroll down, find and enable the **Use RSA/PSS signatures** option.
1. Save the new VPN connection, then tap to connect.
Once connected, you can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](#ikev2-troubleshooting).
#### Using native IKEv2 client
[[Supporters] **Screencast:** Connect using Native VPN Client on Android 11+](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-O5O7FVF8J)
Android 11+ users can also connect using the native IKEv2 client.
1. Securely transfer the generated `.p12` file to your Android device.
1. Launch the **Settings** application.
1. Go to Security -> Advanced -> Encryption & credentials.
1. Tap **Install a certificate**.
1. Tap **VPN & app user certificate**.
1. Choose the `.p12` file you transferred from the VPN server.
**Note:** To find the `.p12` file, tap the three-line menu button, then browse to the location you saved the file.
1. Enter a name for the certificate, then tap **OK**.
1. Go to Settings -> Network & internet -> VPN, then tap the "+" button.
1. Enter a name for the VPN profile.
1. Select **IKEv2/IPSec RSA** from the **Type** drop-down menu.
1. Enter `Your VPN Server IP` (or DNS name) in the **Server address** field.
**Note:** This must **exactly match** the server address in the output of the IKEv2 helper script.
1. Enter anything you like for the **IPSec identifier**.
**Note:** This field should not be required. It is a bug in Android.
1. Select the certificate you imported from the **IPSec user certificate** drop-down menu.
1. Select the certificate you imported from the **IPSec CA certificate** drop-down menu.
1. Select **(receive from server)** from the **IPSec server certificate** drop-down menu.
1. Tap **Save**. Then tap the new VPN connection and tap **Connect**.
Once connected, you can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](#ikev2-troubleshooting).
### Chrome OS
First, on your VPN server, export the CA certificate as `ca.cer`:
```bash
sudo certutil -L -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" -a -o ca.cer
```
Securely transfer the generated `.p12` and `ca.cer` files to your Chrome OS device.
Install user and CA certificates:
1. Open a new tab in Google Chrome.
1. In the address bar, enter **chrome://settings/certificates**
1. **(Important)** Click **Import and Bind**, not **Import**.
1. In the box that opens, choose the `.p12` file you transferred from the VPN server and select **Open**.
1. Click **OK** if the certificate does not have a password. Otherwise, enter the certificate's password.
1. Click the **Authorities** tab. Then click **Import**.
1. In the box that opens, select **All files** in the drop-down menu at the bottom left.
1. Choose the `ca.cer` file you transferred from the VPN server and select **Open**.
1. Keep the default options and click **OK**.
Add a new VPN connection:
1. Go to Settings -> Network.
1. Click **Add connection**, then click **Add built-in VPN**.
1. Enter anything you like for the **Service name**.
1. Select **IPsec (IKEv2)** in the **Provider type** drop-down menu.
1. Enter `Your VPN Server IP` (or DNS name) for the **Server hostname**.
1. Select **User certificate** in the **Authentication type** drop-down menu.
1. Select **IKEv2 VPN CA [IKEv2 VPN CA]** in the **Server CA certificate** drop-down menu.
1. Select **IKEv2 VPN CA [client name]** in the **User certificate** drop-down menu.
1. Leave other fields blank.
1. Enable **Save identity and password**.
1. Click **Connect**.
Once connected, you will see a VPN icon overlay on the network status icon. You can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
(Optional feature) You can choose to enable the "Always-on VPN" feature on Chrome OS. To manage this setting, go to Settings -> Network, then click **VPN**.
If you get an error when trying to connect, see [Troubleshooting](#ikev2-troubleshooting).
### Linux
Before configuring Linux VPN clients, you must make the following change on the VPN server: Edit `/etc/ipsec.d/ikev2.conf` on the server. Append `authby=rsa-sha1` to the end of the `conn ikev2-cp` section, indented by two spaces. Save the file and run `service ipsec restart`.
To configure your Linux computer to connect to IKEv2 as a VPN client, first install the strongSwan plugin for NetworkManager:
#### Ubuntu and Debian
```bash
sudo apt-get update
sudo apt-get install network-manager-strongswan
```
#### Arch Linux
```bash
sudo pacman -Syu # upgrade all packages
sudo pacman -S networkmanager-strongswan
```
#### Fedora
For KDE Plasma/LXQt users:
```bash
sudo dnf install NetworkManager-strongswan-gnome plasma-nm-strongswan
```
Other DEs:
```bash
sudo dnf install NetworkManager-strongswan-gnome
```
#### CentOS
```bash
sudo yum install epel-release
sudo yum --enablerepo=epel install NetworkManager-strongswan-gnome
```
Next, securely transfer the generated `.p12` file from the VPN server to your Linux computer. After that, extract the CA certificate, client certificate and private key. Replace `vpnclient.p12` in the example below with the name of your `.p12` file.
```bash
# Example: Extract CA certificate, client certificate and private key.
# You may delete the .p12 file when finished.
# Note: You may need to enter the import password, which can be found
# in the output of the IKEv2 helper script. If the output does not
# contain an import password, press Enter to continue.
# Note: If using OpenSSL 3.x (run "openssl version" to check),
# append "-legacy" to the 3 commands below.
openssl pkcs12 -in vpnclient.p12 -cacerts -nokeys -out ca.cer
openssl pkcs12 -in vpnclient.p12 -clcerts -nokeys -out client.cer
openssl pkcs12 -in vpnclient.p12 -nocerts -nodes -out client.key
rm vpnclient.p12
# (Important) Protect certificate and private key files
# Note: This step is optional, but strongly recommended.
sudo chown root:root ca.cer client.cer client.key
sudo chmod 600 ca.cer client.cer client.key
```
>[!IMPORTANT]
>
>**_Fedora_** and its derivatives require a few extra steps to setup due to their default security policies.
>
>For Fedora/Nobara 39+ clients:
>
>
>
>## 1. Enable SHA1 Support
>
>Fedora 39+ disables SHA-1 cryptographic support by default. Since this VPN setup uses SHA-1 for certificate generation, you need to re-enable it system-wide. Run the following command:
>
>```
>sudo update-crypto-policies --set DEFAULT:SHA1
>```
>**Reboot your system** after running this command.
>
>## 2. Set Secure File Ownership
>
>Fedora systems require that certificate and key files be owned by root. You can set the correct ownership using the `chown` command.
>
>```
>sudo chown root:root ca.cer client.cer client.key
>```
>
>## 3. Create System Directories
>
>Create the official directories where the strongSwan service looks for certificates and private keys.
>
>```
>sudo mkdir -p /etc/ipsec.d/{certs,private}
>```
>
>## 4. Move Files into Place
>
>Move the certificate and key files from your current location into the newly created system directories.
>
>
>```
># Move certificates
>sudo mv /path/to/ca.cer /path/to/client.cer /etc/ipsec.d/certs/
>
># Move private key
>sudo mv /path/to/client.key /etc/ipsec.d/private/
>```
>
>## 5. Apply SELinux Contexts (If SELinux is Active)
>
>This command updates the security context of the files, ensuring they are correctly labeled for use by the VPN service. It will only run if SELinux is enabled on your system (_à la_ Fedora).
>
>```bash
> bash -c '
># Check if SELinux is enabled and apply contexts if necessary
>if command -v sestatus >/dev/null 2>&1 && sestatus | grep -q "SELinux status:.*enabled"; then
> sudo restorecon -R -v /etc/ipsec.d/
> echo "SELinux contexts applied successfully. Proceed to step 6."
>else
> echo "SELinux not active or not found - skipping context restoration. Proceed to step 6."
>fi'
>```
>
>## 6. Continue to NetworkManager Setup
>
>You are now ready to configure the connection using the graphical editor. Open it with:
>
>```
>sudo nm-connection-editor
>```
>Proceed with the general Linux instructions below. When prompted to select certificate and key files during setup, use the files you just transferred to `/etc/ipsec.d/`. (Press **`Ctrl+L`** in the file picker to type the full paths directly.)
>
>The paths, for your convenience, are:
>
>`/etc/ipsec.d/certs/` & `/etc/ipsec.d/private/`
>
You can then set up and enable the VPN connection:
1. Go to Settings -> Network -> VPN. Click the **+** button.
1. Select **IPsec/IKEv2 (strongswan)**.
1. Enter anything you like in the **Name** field.
1. In the **Gateway (Server)** section, enter `Your VPN Server IP` (or DNS name) for the **Address**.
1. Select the `ca.cer` file for the **Certificate**.
1. In the **Client** section, select **Certificate(/private key)** in the **Authentication** drop-down menu.
1. Select **Certificate/private key** in the **Certificate** drop-down menu (if exists).
1. Select the `client.cer` file for the **Certificate (file)**.
1. Select the `client.key` file for the **Private key**.
1. In the **Options** section, check the **Request an inner IP address** checkbox.
1. In the **Cipher proposals (Algorithms)** section, check the **Enable custom proposals** checkbox.
1. Leave the **IKE** field blank.
1. Enter `aes128gcm16` in the **ESP** field.
1. Click **Add** to save the VPN connection information.
1. Turn the **VPN** switch ON.
>[!TIP]
> If you're using the KDE Plasma desktop, you might encounter issues when configuring the VPN through the graphical System Settings. To ensure a smooth setup, we recommend launching the dedicated connection editor instead by running `sudo nm-connection-editor` in a terminal.
Alternatively, you may connect using the command line. See [#1399](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1399), [#1007](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1007) and [#1789](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1789) for example steps. If you encounter error `Could not find source connection`, edit `/etc/netplan/01-netcfg.yaml` and replace `renderer: networkd` with `renderer: NetworkManager`, then run `sudo netplan apply`. If using `nmcli` to connect to the VPN, run `sudo nmcli c up VPN`. To disconnect: `sudo nmcli c down VPN`.
Once connected, you can verify that your traffic is being routed properly by [looking up your IP address on Google](https://www.google.com/search?q=my+ip). It should say "Your public IP address is `Your VPN Server IP`".
If you get an error when trying to connect, see [Troubleshooting](#ikev2-troubleshooting).
### RouterOS
**Note:** These steps were contributed by [@Unix-User](https://github.com/Unix-User). It is recommended to run terminal commands via an SSH connection, e.g. via Putty.
1. Securely transfer the generated `.p12` file to your computer.
Click to see screencast.

2. In WinBox, go to System > certificates > import. Import the `.p12` certificate file twice (yes, import the same file two times!). Verify in your certificates panel. You will see 2 files, the one that is marked KT is the key.
Click to see screencast.

Or you can use terminal instead (empty passphrase):
```bash
[admin@MikroTik] > /certificate/import file-name=mikrotik.p12
passphrase:
certificates-imported: 2
private-keys-imported: 0
files-imported: 1
decryption-failures: 0
keys-with-no-certificate: 0
[admin@MikroTik] > /certificate/import file-name=mikrotik.p12
passphrase:
certificates-imported: 0
private-keys-imported: 1
files-imported: 1
decryption-failures: 0
keys-with-no-certificate: 0
```
3. Run these commands in terminal. Replace the following with your own values.
`YOUR_VPN_SERVER_IP_OR_DNS_NAME` is your VPN server IP or DNS name.
`IMPORTED_CERTIFICATE` is the name of the certificate from step 2 above, e.g. `vpnclient.p12_0`
(the one flagged with KT - Priv. Key Trusted - if not flagged as KT, import certificate again).
`THESE_ADDRESSES_GO_THROUGH_VPN` are the local network addresses that you want to browse through the VPN.
Assuming that your local network behind RouterOS is `192.168.0.0/24`, you can use `192.168.0.0/24`
for the entire network, or use `192.168.0.10` for just one device, and so on.
```bash
/ip firewall address-list add address=THESE_ADDRESSES_GO_THROUGH_VPN list=local
/ip ipsec mode-config add name=ike2-rw responder=no src-address-list=local
/ip ipsec policy group add name=ike2-rw
/ip ipsec profile add name=ike2-rw
/ip ipsec peer add address=YOUR_VPN_SERVER_IP_OR_DNS_NAME exchange-mode=ike2 \
name=ike2-rw-client profile=ike2-rw
/ip ipsec proposal add name=ike2-rw pfs-group=none
/ip ipsec identity add auth-method=digital-signature certificate=IMPORTED_CERTIFICATE \
generate-policy=port-strict mode-config=ike2-rw \
peer=ike2-rw-client policy-template-group=ike2-rw
/ip ipsec policy add group=ike2-rw proposal=ike2-rw template=yes
```
4. For more information, see [#1112](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1112#issuecomment-1059628623).
> tested on
> mar/02/2022 12:52:57 by RouterOS 6.48
> RouterBOARD 941-2nD
## IKEv2 troubleshooting
*Read this in other languages: [English](ikev2-howto.md#ikev2-troubleshooting), [中文](ikev2-howto-zh.md#ikev2-故障排除).*
**See also:** [Check logs and VPN status](clients.md#check-logs-and-vpn-status), [IKEv1 troubleshooting](clients.md#ikev1-troubleshooting) and [Advanced usage](advanced-usage.md).
* [Cannot connect to the VPN server](#cannot-connect-to-the-vpn-server)
* [Ubuntu 20.04 cannot import client config](#ubuntu-2004-cannot-import-client-config)
* [macOS Sonoma clients reconnect](#macos-sonoma-clients-reconnect)
* [Unable to connect multiple IKEv2 clients](#unable-to-connect-multiple-ikev2-clients)
* [IKE authentication credentials are unacceptable](#ike-authentication-credentials-are-unacceptable)
* [Policy match error](#policy-match-error)
* [Parameter is incorrect](#parameter-is-incorrect)
* [Cannot open websites after connecting to IKEv2](#cannot-open-websites-after-connecting-to-ikev2)
* [Windows 10 connecting](#windows-10-connecting)
* [Other known issues](#other-known-issues)
### Cannot connect to the VPN server
First, make sure that the VPN server address specified on your VPN client device **exactly matches** the server address in the output of the IKEv2 helper script. For example, you cannot use a DNS name to connect if it was not specified when setting up IKEv2. To change the IKEv2 server address, read [this section](#change-ikev2-server-address).
For servers with an external firewall (e.g. [EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)/[GCE](https://cloud.google.com/vpc/docs/firewalls)), open UDP ports 500 and 4500 for the VPN. Aliyun users, see [#433](https://github.com/hwdsl2/setup-ipsec-vpn/issues/433).
[Check logs and VPN status](clients.md#check-logs-and-vpn-status) for errors. If you encounter retransmission related errors and are unable to connect, there may be network issues between the VPN client and server. If you are connecting from mainland China, consider switching to alternative solutions other than IPsec VPN.
### Ubuntu 20.04 cannot import client config
If you installed the IPsec VPN before 2024-04-10, and your VPN server runs Ubuntu Linux version 20.04, you may have encountered an issue where newly generated client configuration files (`.mobileconfig`) fail to import on iOS or macOS device(s) with errors like "incorrect password". This could be caused by updates to libnss3 related packages on Ubuntu 20.04, which required some changes ([25670f3](https://github.com/hwdsl2/setup-ipsec-vpn/commit/25670f3)) in the IKEv2 script.
To fix this issue, first update the IKEv2 script on your server to the latest version using [these instructions](#update-ikev2-helper-script). After that, run `sudo ikev2.sh` and select "export" to re-create the client configuration files.
### macOS Sonoma clients reconnect
macOS 14 (Sonoma) has [a minor issue](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1486) that may cause IKEv2 VPN to disconnect and reconnect once every 24-48 minutes. Other macOS versions are not affected. First [check your macOS version](https://support.apple.com/en-us/HT201260). To work around this issue, follow the steps below.
**Note:** If you installed IPsec VPN after December 10, 2023, no action is required because the following fixes are already included.
1. Edit `/etc/ipsec.d/ikev2.conf` on the VPN server. Find the line:
```
ike=aes256-sha2,aes128-sha2,aes256-sha1,aes128-sha1
```
and replace it with the following:
```
ike=aes_gcm_c_256-hmac_sha2_256-ecp_256,aes256-sha2,aes128-sha2,aes256-sha1,aes128-sha1
```
**Note:** Docker users should first [open a Bash shell inside the container](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/docs/advanced-usage.md#bash-shell-inside-container).
1. Save the file and run `service ipsec restart`. Docker users: After step 4 below, `exit` the container and run `docker restart ipsec-vpn-server`.
1. Edit `/opt/src/ikev2.sh` on the VPN server. Find and replace the following sections with these new values:
```
ChildSecurityAssociationParameters
DiffieHellmanGroup
19
EncryptionAlgorithm
AES-256-GCM
LifeTimeInMinutes
1410
```
```
IKESecurityAssociationParameters
DiffieHellmanGroup
19
EncryptionAlgorithm
AES-256-GCM
IntegrityAlgorithm
SHA2-256
LifeTimeInMinutes
1410
```
1. Run `sudo ikev2.sh` to export (or add) updated client config files for each macOS device you have.
1. Remove the previously imported IKEv2 profile (if any) from your macOS device(s), then import the updated `.mobileconfig` file(s). See [Configure IKEv2 VPN clients](#configure-ikev2-vpn-clients). Docker users, see [Configure and use IKEv2 VPN](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README.md#configure-and-use-ikev2-vpn).
### Unable to connect multiple IKEv2 clients
To connect multiple IKEv2 clients from behind the same NAT (e.g. home router) at the same time, you will need to generate a unique certificate for each client. Otherwise, you could encounter the issue where a later connected client affects the VPN connection of an existing client, which may lose Internet access.
To generate certificates for additional IKEv2 clients, run the helper script with the `--addclient` option. To customize client options, run the script without arguments.
```bash
sudo ikev2.sh --addclient [client name]
```
### IKE authentication credentials are unacceptable
If you encounter this error, make sure that the VPN server address specified on your VPN client device **exactly matches** the server address in the output of the IKEv2 helper script. For example, you cannot use a DNS name to connect if it was not specified when setting up IKEv2. To change the IKEv2 server address, read [this section](#change-ikev2-server-address).
### Policy match error
To fix this error, you will need to enable stronger ciphers for IKEv2 with a one-time registry change. Download and import the `.reg` file below, or run the following from an elevated command prompt.
- For Windows 7, 8, 10 and 11 ([download .reg file](https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0/Enable_Stronger_Ciphers_for_IKEv2_on_Windows.reg))
```console
REG ADD HKLM\SYSTEM\CurrentControlSet\Services\RasMan\Parameters /v NegotiateDH2048_AES256 /t REG_DWORD /d 0x1 /f
```
### Parameter is incorrect
If you encounter "Error 87: The parameter is incorrect" when trying to connect using IKEv2 mode, try the solutions in [this issue](https://github.com/trailofbits/algo/issues/1051), more specifically, step 2 "reset device manager adapters".
### Cannot open websites after connecting to IKEv2
If your VPN client device cannot open websites after successfully connecting to IKEv2, try the following fixes:
1. Some cloud providers, such as [Google Cloud](https://cloud.google.com), [set a lower MTU by default](https://cloud.google.com/network-connectivity/docs/vpn/concepts/mtu-considerations). This could cause network issues with IKEv2 VPN clients. To fix, try setting the MTU to 1500 on the VPN server:
```bash
# Replace ens4 with the network interface name on your server
sudo ifconfig ens4 mtu 1500
```
This setting **does not** persist after a reboot. To change the MTU size permanently, refer to relevant articles on the web.
1. If your Android or Linux VPN client can connect using IKEv2 mode, but cannot open websites, try the fix in [Android/Linux MTU/MSS issues](clients.md#androidlinux-mtumss-issues).
1. Windows VPN clients may not use the DNS servers specified by IKEv2 after connecting, if the client's configured DNS servers on the Internet adapter are from the local network segment. This can be fixed by manually entering DNS servers such as Google Public DNS (8.8.8.8, 8.8.4.4) in network interface properties -> TCP/IPv4. For more information, see [Windows DNS leaks and IPv6](clients.md#windows-dns-leaks-and-ipv6).
### Windows 10 connecting
If using Windows 10 and the VPN is stuck on "connecting" for more than a few minutes, try these steps:
1. Right-click on the wireless/network icon in your system tray.
1. Select **Open Network & Internet settings**, then on the page that opens, click **VPN** on the left.
1. Select the new VPN entry, then click **Connect**.
### Other known issues
The built-in VPN client in Windows may not support IKEv2 fragmentation (this feature [requires](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-ikee/74df968a-7125-431d-9c98-4ea929e548dc) Windows 10 v1803 or newer). On some networks, this can cause the connection to fail or have other issues. You may instead try the [IPsec/L2TP](clients.md) or [IPsec/XAuth](clients-xauth.md) mode.
## Manage IKEv2 clients
* [List existing clients](#list-existing-clients)
* [Add a client certificate](#add-a-client-certificate)
* [Export configuration for an existing client](#export-configuration-for-an-existing-client)
* [Delete a client certificate](#delete-a-client-certificate)
* [Revoke a client certificate](#revoke-a-client-certificate)
### List existing clients
To list the names of existing IKEv2 clients, run the helper script with the `--listclients` option. Use option `-h` to show usage.
```bash
sudo ikev2.sh --listclients
```
### Add a client certificate
To generate certificates for additional IKEv2 clients, run the helper script with the `--addclient` option. To customize client options, run the script without arguments.
```bash
sudo ikev2.sh --addclient [client name]
```
Alternatively, you may manually add a client certificate. Refer to step 4 in [this section](#manually-set-up-ikev2).
### Export configuration for an existing client
By default, the IKEv2 helper script exports client configuration after running. If later you want to export an existing client, you may use:
```bash
sudo ikev2.sh --exportclient [client name]
```
### Delete a client certificate
**Important:** Deleting a client certificate from the IPsec database **WILL NOT** prevent VPN client(s) from connecting using that certificate! For this use case, you **MUST** [revoke the client certificate](#revoke-a-client-certificate) instead of deleting it.
First, read the important note above. Then click here for instructions.
**Warning:** The client certificate and private key will be **permanently deleted**. This **cannot be undone**!
To delete an existing client:
```bash
sudo ikev2.sh --deleteclient [client name]
```
Alternatively, you can manually delete a client certificate.
1. List certificates in the IPsec database:
```bash
certutil -L -d sql:/etc/ipsec.d
```
Example output:
```
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
IKEv2 VPN CA CTu,u,u
($PUBLIC_IP) u,u,u
vpnclient u,u,u
```
1. Delete the client certificate and private key. Replace "Nickname" below with the nickname of the client certificate you want to delete, e.g. `vpnclient`.
```bash
certutil -F -d sql:/etc/ipsec.d -n "Nickname"
certutil -D -d sql:/etc/ipsec.d -n "Nickname" 2>/dev/null
```
1. (Optional) Delete the previously generated client configuration files (`.p12`, `.mobileconfig` and `.sswan` files) for this VPN client, if any.
### Revoke a client certificate
In certain circumstances, you may need to revoke a previously generated VPN client certificate.
To revoke an existing client:
```bash
sudo ikev2.sh --revokeclient [client name]
```
Alternatively, you can manually revoke a client certificate.
Alternatively, you can manually revoke a client certificate. This can be done using `crlutil`. See example steps below, commands must be run as `root`.
1. Check the database, and identify the nickname of the client certificate you want to revoke.
```bash
certutil -L -d sql:/etc/ipsec.d
```
```
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
IKEv2 VPN CA CTu,u,u
($PUBLIC_IP) u,u,u
vpnclient-to-revoke u,u,u
```
In this example, we will revoke the certificate with nickname `vpnclient-to-revoke`, issued by `IKEv2 VPN CA`.
1. Find the serial number of this client certificate.
```bash
certutil -L -d sql:/etc/ipsec.d -n "vpnclient-to-revoke"
```
```
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
00:cd:69:ff:74
... ...
```
From the output, we see that the serial number is `CD69FF74` in hexadecimal, which is `3446275956` in decimal. It will be used in the next steps.
1. Create a new Certificate Revocation List (CRL). You only need to do this once for each CA.
```bash
if ! crlutil -L -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" 2>/dev/null; then
crlutil -G -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" -c /dev/null
fi
```
```
CRL Info:
:
Version: 2 (0x1)
Signature Algorithm: PKCS #1 SHA-256 With RSA Encryption
Issuer: "O=IKEv2 VPN,CN=IKEv2 VPN CA"
This Update: Sat Jun 06 22:00:00 2020
CRL Extensions:
```
1. Add the client certificate you want to revoke to the CRL. Here we specify the certificate's serial number in decimal, and the revocation time in GeneralizedTime format (YYYYMMDDhhmmssZ) in UTC.
```bash
crlutil -M -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" <
## Change IKEv2 server address
In certain circumstances, you may need to change the IKEv2 server address after setup. For example, to switch to use a DNS name, or after server IP changes. Note that the server address you specify on VPN client devices must **exactly match** the server address in the output of the IKEv2 helper script. Otherwise, devices may be unable to connect.
To change the server address, run the [helper script](../extras/ikev2changeaddr.sh) and follow the prompts.
```bash
wget https://get.vpnsetup.net/ikev2addr -O ikev2addr.sh
sudo bash ikev2addr.sh
```
**Important:** After running this script, you must manually update the server address (and remote ID, if applicable) on any existing IKEv2 client devices. For iOS clients, you'll need to run `sudo ikev2.sh` to export the updated client config file and import it to the iOS device.
## Update IKEv2 helper script
The IKEv2 helper script is updated from time to time for bug fixes and improvements ([commit log](https://github.com/hwdsl2/setup-ipsec-vpn/commits/master/extras/ikev2setup.sh)). When a newer version is available, you may optionally update the IKEv2 helper script on your server. Note that these commands will overwrite any existing `ikev2.sh`.
```bash
wget https://get.vpnsetup.net/ikev2 -O /opt/src/ikev2.sh
chmod +x /opt/src/ikev2.sh && ln -s /opt/src/ikev2.sh /usr/bin 2>/dev/null
```
## Set up IKEv2 using helper script
**Note:** By default, IKEv2 is automatically set up when running the VPN setup script. You may skip this section and continue to [configure IKEv2 VPN clients](#configure-ikev2-vpn-clients).
**Important:** Before continuing, you should have successfully [set up your own VPN server](https://github.com/hwdsl2/setup-ipsec-vpn). Docker users, see [Configure and use IKEv2 VPN](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README.md#configure-and-use-ikev2-vpn).
Use this [helper script](../extras/ikev2setup.sh) to automatically set up IKEv2 on the VPN server:
```bash
# Set up IKEv2 using default options
sudo ikev2.sh --auto
# Alternatively, you may customize IKEv2 options
sudo ikev2.sh
```
**Note:** If IKEv2 is already set up, but you want to customize IKEv2 options, first [remove IKEv2](#remove-ikev2), then set it up again using `sudo ikev2.sh`.
When finished, continue to [configure IKEv2 VPN clients](#configure-ikev2-vpn-clients). Advanced users can optionally enable [IKEv2-only mode](advanced-usage.md#ikev2-only-vpn).
Error: "sudo: ikev2.sh: command not found".
This is normal if you used an older version of the VPN setup script. First, download the IKEv2 helper script:
```bash
wget https://get.vpnsetup.net/ikev2 -O /opt/src/ikev2.sh
chmod +x /opt/src/ikev2.sh && ln -s /opt/src/ikev2.sh /usr/bin
```
Then run the script using the instructions above.
You may optionally specify a DNS name, client name and/or custom DNS servers.
When running IKEv2 setup in auto mode, advanced users can optionally specify a DNS name for the IKEv2 server address. The DNS name must be a fully qualified domain name (FQDN). Example:
```bash
sudo VPN_DNS_NAME='vpn.example.com' ikev2.sh --auto
```
Similarly, you may specify a name for the first IKEv2 client. The default is `vpnclient` if not specified.
```bash
sudo VPN_CLIENT_NAME='your_client_name' ikev2.sh --auto
```
By default, IKEv2 clients are set to use [Google Public DNS](https://developers.google.com/speed/public-dns/) when the VPN is active. You may specify custom DNS server(s) for IKEv2. Example:
```bash
sudo VPN_DNS_SRV1=1.1.1.1 VPN_DNS_SRV2=1.0.0.1 ikev2.sh --auto
```
By default, no password is required when importing IKEv2 client configuration. You can choose to protect client config files using a random password.
```bash
sudo VPN_PROTECT_CONFIG=yes ikev2.sh --auto
```
View usage information for the IKEv2 script.
```
Usage: bash ikev2.sh [options]
Options:
--auto run IKEv2 setup in auto mode using default options (for initial setup only)
--addclient [client name] add a new client using default options
--exportclient [client name] export configuration for an existing client
--listclients list the names of existing clients
--revokeclient [client name] revoke an existing client
--deleteclient [client name] delete an existing client
--removeikev2 remove IKEv2 and delete all certificates and keys from the IPsec database
-y, --yes assume "yes" as answer to prompts when revoking/deleting a client or removing IKEv2
-h, --help show this help message and exit
To customize IKEv2 or client options, run this script without arguments.
```
## Manually set up IKEv2
As an alternative to using the [helper script](#set-up-ikev2-using-helper-script), advanced users can manually set up IKEv2 on the VPN server. Before continuing, it is recommended to [update Libreswan](../README.md#upgrade-libreswan) to the latest version.
The following example shows how to manually configure IKEv2 with Libreswan. Commands below must be run as `root`.
View example steps for manually configuring IKEv2 with Libreswan.
1. Find the VPN server's public IP, save it to a variable and check.
```bash
PUBLIC_IP=$(dig @resolver1.opendns.com -t A -4 myip.opendns.com +short)
[ -z "$PUBLIC_IP" ] && PUBLIC_IP=$(wget -t 2 -T 10 -qO- http://ipv4.icanhazip.com)
printf '%s\n' "$PUBLIC_IP"
```
Check to make sure the output matches the server's public IP. This variable is required in the steps below.
**Note:** Alternatively, you may specify the server's DNS name here. e.g. `PUBLIC_IP=myvpn.example.com`.
1. Add a new IKEv2 connection:
```bash
if ! grep -qs '^include /etc/ipsec\.d/\*\.conf$' /etc/ipsec.conf; then
echo >> /etc/ipsec.conf
echo 'include /etc/ipsec.d/*.conf' >> /etc/ipsec.conf
fi
```
**Note:** If you specified the server's DNS name (instead of its IP address) in step 1 above, you must replace `leftid=$PUBLIC_IP` in the command below with `leftid=@$PUBLIC_IP`.
```bash
cat > /etc/ipsec.d/ikev2.conf <> /etc/ipsec.d/ikev2.conf <> /etc/ipsec.d/ikev2.conf <> /etc/ipsec.d/ikev2.conf <
Is this a critical extension [y/N]?
N
```
Generate VPN server certificate:
**Note:** If you specified the server's DNS name (instead of its IP address) in step 1 above, you must replace `--extSAN "ip:$PUBLIC_IP,dns:$PUBLIC_IP"` in the command below with `--extSAN "dns:$PUBLIC_IP"`.
```bash
certutil -z <(head -c 1024 /dev/urandom) \
-S -c "IKEv2 VPN CA" -n "$PUBLIC_IP" \
-s "O=IKEv2 VPN,CN=$PUBLIC_IP" \
-k rsa -g 3072 -v 120 \
-d sql:/etc/ipsec.d -t ",," \
--keyUsage digitalSignature,keyEncipherment \
--extKeyUsage serverAuth \
--extSAN "ip:$PUBLIC_IP,dns:$PUBLIC_IP"
```
```
Generating key. This may take a few moments...
```
1. Generate client certificate(s), then export the `.p12` file that contains the client certificate, private key, and CA certificate.
**Note:** You may repeat this step to generate certificates for additional VPN clients, but make sure to replace every `vpnclient` with `vpnclient2`, etc. To connect multiple IKEv2 clients from behind the same NAT (e.g. home router) at the same time, you will need to generate a unique certificate for each client.
Generate client certificate:
```bash
certutil -z <(head -c 1024 /dev/urandom) \
-S -c "IKEv2 VPN CA" -n "vpnclient" \
-s "O=IKEv2 VPN,CN=vpnclient" \
-k rsa -g 3072 -v 120 \
-d sql:/etc/ipsec.d -t ",," \
--keyUsage digitalSignature,keyEncipherment \
--extKeyUsage serverAuth,clientAuth -8 "vpnclient"
```
```
Generating key. This may take a few moments...
```
Export `.p12` file:
```bash
pk12util -d sql:/etc/ipsec.d -n "vpnclient" -o vpnclient.p12
```
```
Enter password for PKCS12 file:
Re-enter password:
pk12util: PKCS12 EXPORT SUCCESSFUL
```
Enter a secure password to protect the exported `.p12` file (when importing into an iOS or macOS device, this password cannot be empty).
1. (For iOS clients) Export the CA certificate as `ca.cer`:
```bash
certutil -L -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" -a -o ca.cer
```
1. The database should now contain:
```bash
certutil -L -d sql:/etc/ipsec.d
```
```
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
IKEv2 VPN CA CTu,u,u
($PUBLIC_IP) u,u,u
vpnclient u,u,u
```
**Note:** To display a certificate, use `certutil -L -d sql:/etc/ipsec.d -n "Nickname"`. To revoke a client certificate, follow [these steps](#revoke-a-client-certificate). For other `certutil` usage, read [here](https://firefox-source-docs.mozilla.org/security/nss/legacy/tools/nss_tools_certutil/index.html).
1. **(Important) Restart the IPsec service**:
```bash
service ipsec restart
```
Before continuing, you **must** restart the IPsec service. The IKEv2 setup on the VPN server is now complete. Follow instructions to [configure VPN clients](#configure-ikev2-vpn-clients).
## Remove IKEv2
If you want to remove IKEv2 from the VPN server, but keep the [IPsec/L2TP](clients.md) and [IPsec/XAuth ("Cisco IPsec")](clients-xauth.md) modes (if installed), run the helper script. **Warning:** All IKEv2 configuration including certificates and keys will be **permanently deleted**. This **cannot be undone**!
```bash
sudo ikev2.sh --removeikev2
```
After removing IKEv2, if you want to set it up again, refer to [this section](#set-up-ikev2-using-helper-script).
Alternatively, you can manually remove IKEv2.
To manually remove IKEv2 from the VPN server, but keep the [IPsec/L2TP](clients.md) and [IPsec/XAuth ("Cisco IPsec")](clients-xauth.md) modes, follow these steps. Commands must be run as `root`.
**Warning:** All IKEv2 configuration including certificates and keys will be **permanently deleted**. This **cannot be undone**!
1. Rename (or delete) the IKEv2 config file:
```bash
mv /etc/ipsec.d/ikev2.conf /etc/ipsec.d/ikev2.conf.bak
```
**Note:** If you used an older version (before 2020-05-31) of the IKEv2 helper script or instructions, file `/etc/ipsec.d/ikev2.conf` may not exist. In this case, please instead remove the `conn ikev2-cp` section from file `/etc/ipsec.conf`.
1. **(Important) Restart the IPsec service**:
```bash
service ipsec restart
```
1. List certificates in the IPsec database:
```bash
certutil -L -d sql:/etc/ipsec.d
```
Example output:
```
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
IKEv2 VPN CA CTu,u,u
($PUBLIC_IP) u,u,u
vpnclient u,u,u
```
1. Delete the Certificate Revocation List (CRL), if any:
```bash
crlutil -D -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" 2>/dev/null
```
1. Delete certificates and keys. Replace "Nickname" below with each certificate's nickname. Repeat these commands for each certificate. When finished, list certificates in the IPsec database again, and confirm that the list is empty.
```bash
certutil -F -d sql:/etc/ipsec.d -n "Nickname"
certutil -D -d sql:/etc/ipsec.d -n "Nickname" 2>/dev/null
```
## References
* https://libreswan.org/wiki/VPN_server_for_remote_clients_using_IKEv2
* https://libreswan.org/wiki/HOWTO:_Using_NSS_with_libreswan
* https://libreswan.org/man/ipsec.conf.5.html
* https://docs.strongswan.org/docs/5.9/interop/windowsClients.html
* https://docs.strongswan.org/docs/5.9/os/androidVpnClient.html
* https://firefox-source-docs.mozilla.org/security/nss/legacy/tools/nss_tools_certutil/index.html
* https://firefox-source-docs.mozilla.org/security/nss/legacy/tools/nss_tools_crlutil/index.html
## License
Copyright (C) 2016-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
[](http://creativecommons.org/licenses/by-sa/3.0/)
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!
================================================
FILE: docs/manage-users-zh.md
================================================
[English](manage-users.md) | [中文](manage-users-zh.md)
# 管理 VPN 用户
在默认情况下,将只创建一个用于 VPN 登录的用户账户。如果你需要查看或管理 IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式的用户,请阅读本文档。对于 IKEv2,参见[管理 IKEv2 客户端](ikev2-howto-zh.md#管理-ikev2-客户端)。
* [使用辅助脚本管理 VPN 用户](#使用辅助脚本管理-vpn-用户)
* [查看 VPN 用户](#查看-vpn-用户)
* [查看或更改 IPsec PSK](#查看或更改-ipsec-psk)
* [手动管理 VPN 用户](#手动管理-vpn-用户)
## 使用辅助脚本管理 VPN 用户
你可以使用辅助脚本添加,删除或者更新 VPN 用户。它们将同时更新 IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式的用户。对于 IKEv2,参见[管理 IKEv2 客户端](ikev2-howto-zh.md#管理-ikev2-客户端)。
**注:** 将下面的命令的参数换成你自己的值。VPN 用户信息保存在文件 `/etc/ppp/chap-secrets` 和 `/etc/ipsec.d/passwd`。脚本在修改这些文件之前会先做备份,使用 `.old-日期-时间` 为后缀。
### 添加或更改一个 VPN 用户
添加一个新 VPN 用户,或者为一个已有的 VPN 用户更改密码。
运行[辅助脚本](../extras/add_vpn_user.sh)并按提示操作:
```bash
sudo addvpnuser.sh
```
错误:"sudo: addvpnuser.sh: command not found".
如果你使用了较早版本的 VPN 安装脚本,这是正常的。首先下载辅助脚本:
```bash
wget https://get.vpnsetup.net/adduser -O /opt/src/addvpnuser.sh
chmod +x /opt/src/addvpnuser.sh && ln -s /opt/src/addvpnuser.sh /usr/bin
```
然后按照说明运行脚本。
另外,你也可以在添加参数的情况下运行脚本:
```bash
# 所有变量值必须用 '单引号' 括起来
# *不要* 在值中使用这些字符: \ " '
sudo addvpnuser.sh '要添加的用户名' '密码'
# 或者
sudo addvpnuser.sh '要更新的用户名' '新密码'
```
### 删除一个 VPN 用户
删除指定的 VPN 用户。
运行[辅助脚本](../extras/del_vpn_user.sh)并按提示操作:
```bash
sudo delvpnuser.sh
```
错误:"sudo: delvpnuser.sh: command not found".
如果你使用了较早版本的 VPN 安装脚本,这是正常的。首先下载辅助脚本:
```bash
wget https://get.vpnsetup.net/deluser -O /opt/src/delvpnuser.sh
chmod +x /opt/src/delvpnuser.sh && ln -s /opt/src/delvpnuser.sh /usr/bin
```
然后按照说明运行脚本。
另外,你也可以在添加参数的情况下运行脚本:
```bash
# 所有变量值必须用 '单引号' 括起来
# *不要* 在值中使用这些字符: \ " '
sudo delvpnuser.sh '要删除的用户名'
```
### 更新所有的 VPN 用户
移除 **所有的 VPN 用户** 并替换为你指定的列表中的用户。
首先下载[辅助脚本](../extras/update_vpn_users.sh):
```bash
wget https://get.vpnsetup.net/updateusers -O updateusers.sh
```
**重要:** 这个脚本会将你当前 **所有的 VPN 用户** 移除并替换为你指定的列表中的用户。如果你需要保留已有的 VPN 用户,则必须将它们包含在下面的变量中。
要使用这个脚本,从以下选项中选择一个:
**选项 1:** 编辑脚本并输入 VPN 用户信息:
```bash
nano -w updateusers.sh
[替换为你自己的值: YOUR_USERNAMES 和 YOUR_PASSWORDS]
sudo bash updateusers.sh
```
**选项 2:** 将 VPN 用户信息定义为环境变量:
```bash
# VPN用户名和密码列表,用空格分隔
# 所有变量值必须用 '单引号' 括起来
# *不要* 在值中使用这些字符: \ " '
sudo \
VPN_USERS='用户名1 用户名2 ...' \
VPN_PASSWORDS='密码1 密码2 ...' \
bash updateusers.sh
```
## 查看 VPN 用户
在默认情况下,VPN 安装脚本将为 IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式创建相同的用户。
对于 IPsec/L2TP,VPN 用户信息保存在文件 `/etc/ppp/chap-secrets`。该文件的格式如下:
```bash
"用户名1" l2tpd "密码1" *
"用户名2" l2tpd "密码2" *
... ...
```
对于 IPsec/XAuth ("Cisco IPsec"),VPN 用户信息保存在文件 `/etc/ipsec.d/passwd`。这个文件中的密码以加盐哈希值的形式保存。更多详情请见[手动管理 VPN 用户](#手动管理-vpn-用户)。
## 查看或更改 IPsec PSK
IPsec PSK(预共享密钥)保存在文件 `/etc/ipsec.secrets`。所有的 VPN 用户将共享同一个 IPsec PSK。该文件的格式如下:
```bash
%any %any : PSK "你的IPsec预共享密钥"
```
如果要更换一个新的 PSK,可以编辑此文件。**不要**在值中使用这些字符:`\ " '`
完成后必须重启服务:
```bash
service ipsec restart
service xl2tpd restart
```
## 手动管理 VPN 用户
对于 IPsec/L2TP,VPN 用户信息保存在文件 `/etc/ppp/chap-secrets`。该文件的格式如下:
```bash
"用户名1" l2tpd "密码1" *
"用户名2" l2tpd "密码2" *
... ...
```
你可以添加更多用户,每个用户对应文件中的一行。**不要**在值中使用这些字符:`\ " '`
对于 IPsec/XAuth ("Cisco IPsec"),VPN 用户信息保存在文件 `/etc/ipsec.d/passwd`。该文件的格式如下:
```bash
用户名1:密码1的加盐哈希值:xauth-psk
用户名2:密码2的加盐哈希值:xauth-psk
... ...
```
这个文件中的密码以加盐哈希值的形式保存。该步骤可以借助比如 `openssl` 工具来完成:
```bash
# 以下命令的输出为:密码1的加盐哈希值
# 将你的密码用 '单引号' 括起来
openssl passwd -1 '密码1'
```
## 授权协议
版权所有 (C) 2016-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
[](http://creativecommons.org/licenses/by-sa/3.0/)
这个项目是以[知识共享署名-相同方式共享3.0](http://creativecommons.org/licenses/by-sa/3.0/) 许可协议授权。
必须署名: 请包括我的名字在任何衍生产品,并且让我知道你是如何改善它的!
================================================
FILE: docs/manage-users.md
================================================
[English](manage-users.md) | [中文](manage-users-zh.md)
# Manage VPN Users
By default, a single user account for VPN login is created. If you wish to view or manage users for the IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes, read this document. For IKEv2, see [Manage IKEv2 clients](ikev2-howto.md#manage-ikev2-clients).
* [Manage VPN users using helper scripts](#manage-vpn-users-using-helper-scripts)
* [View VPN users](#view-vpn-users)
* [View or update the IPsec PSK](#view-or-update-the-ipsec-psk)
* [Manually manage VPN users](#manually-manage-vpn-users)
## Manage VPN users using helper scripts
You may use helper scripts to add, delete or update VPN users for both IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes. For IKEv2, see [Manage IKEv2 clients](ikev2-howto.md#manage-ikev2-clients).
**Note:** Replace command arguments below with your own values. VPN users are stored in `/etc/ppp/chap-secrets` and `/etc/ipsec.d/passwd`. The scripts will backup these files before making changes, with `.old-date-time` suffix.
### Add or edit a VPN user
Add a new VPN user, or update an existing VPN user with a new password.
Run the [helper script](../extras/add_vpn_user.sh) and follow the prompts:
```bash
sudo addvpnuser.sh
```
Error: "sudo: addvpnuser.sh: command not found".
This is normal if you used an older version of the VPN setup script. First, download the helper script:
```bash
wget https://get.vpnsetup.net/adduser -O /opt/src/addvpnuser.sh
chmod +x /opt/src/addvpnuser.sh && ln -s /opt/src/addvpnuser.sh /usr/bin
```
Then run the script using the instructions.
Alternatively, you can run the script with arguments:
```bash
# All values MUST be placed inside 'single quotes'
# DO NOT use these special characters within values: \ " '
sudo addvpnuser.sh 'username_to_add' 'password'
# OR
sudo addvpnuser.sh 'username_to_update' 'new_password'
```
### Delete a VPN user
Delete the specified VPN user.
Run the [helper script](../extras/del_vpn_user.sh) and follow the prompts:
```bash
sudo delvpnuser.sh
```
Error: "sudo: delvpnuser.sh: command not found".
This is normal if you used an older version of the VPN setup script. First, download the helper script:
```bash
wget https://get.vpnsetup.net/deluser -O /opt/src/delvpnuser.sh
chmod +x /opt/src/delvpnuser.sh && ln -s /opt/src/delvpnuser.sh /usr/bin
```
Then run the script using the instructions.
Alternatively, you can run the script with arguments:
```bash
# All values MUST be placed inside 'single quotes'
# DO NOT use these special characters within values: \ " '
sudo delvpnuser.sh 'username_to_delete'
```
### Update all VPN users
Remove **all existing VPN users** and replace with the list of users you specify.
First, download the [helper script](../extras/update_vpn_users.sh):
```bash
wget https://get.vpnsetup.net/updateusers -O updateusers.sh
```
**Important:** This script will remove **all existing VPN users** and replace with the list of users you specify. Therefore, you must include any existing user(s) you want to keep in the variables below.
To use this script, choose one of the following options:
**Option 1:** Edit the script and enter VPN user details:
```bash
nano -w updateusers.sh
[Replace with your own values: YOUR_USERNAMES and YOUR_PASSWORDS]
sudo bash updateusers.sh
```
**Option 2:** Define VPN user details as environment variables:
```bash
# List of VPN usernames and passwords, separated by spaces
# All values MUST be placed inside 'single quotes'
# DO NOT use these special characters within values: \ " '
sudo \
VPN_USERS='username1 username2 ...' \
VPN_PASSWORDS='password1 password2 ...' \
bash updateusers.sh
```
## View VPN users
By default, the VPN setup scripts will create the same VPN user for both IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes.
For IPsec/L2TP, VPN users are specified in `/etc/ppp/chap-secrets`. The format of this file is:
```bash
"username1" l2tpd "password1" *
"username2" l2tpd "password2" *
... ...
```
For IPsec/XAuth ("Cisco IPsec"), VPN users are specified in `/etc/ipsec.d/passwd`. Passwords in this file are salted and hashed. See [Manually manage VPN users](#manually-manage-vpn-users) for more details.
## View or update the IPsec PSK
The IPsec PSK (pre-shared key) is stored in `/etc/ipsec.secrets`. All VPN users will share the same IPsec PSK. The format of this file is:
```bash
%any %any : PSK "your_ipsec_pre_shared_key"
```
To change to a new PSK, just edit this file. DO NOT use these special characters within values: `\ " '`
You must restart services when finished:
```bash
service ipsec restart
service xl2tpd restart
```
## Manually manage VPN users
For IPsec/L2TP, VPN users are specified in `/etc/ppp/chap-secrets`. The format of this file is:
```bash
"username1" l2tpd "password1" *
"username2" l2tpd "password2" *
... ...
```
You can add more users, use one line for each user. DO NOT use these special characters within values: `\ " '`
For IPsec/XAuth ("Cisco IPsec"), VPN users are specified in `/etc/ipsec.d/passwd`. The format of this file is:
```bash
username1:password1hashed:xauth-psk
username2:password2hashed:xauth-psk
... ...
```
Passwords in this file are salted and hashed. This step can be done using e.g. the `openssl` utility:
```bash
# The output will be password1hashed
# Put your password inside 'single quotes'
openssl passwd -1 'password1'
```
## License
Copyright (C) 2016-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
[](http://creativecommons.org/licenses/by-sa/3.0/)
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!
================================================
FILE: docs/uninstall-zh.md
================================================
[English](uninstall.md) | [中文](uninstall-zh.md)
# 卸载 VPN
* [使用辅助脚本卸载 VPN](#使用辅助脚本卸载-vpn)
* [手动卸载 VPN](#手动卸载-vpn)
## 使用辅助脚本卸载 VPN
要卸载 IPsec VPN,运行[辅助脚本](../extras/vpnuninstall.sh):
**警告:** 此辅助脚本将从你的服务器中删除 IPsec VPN。所有的 VPN 配置将被**永久删除**,并且 Libreswan 和 xl2tpd 将被移除。此操作**不可撤销**!
```bash
wget https://get.vpnsetup.net/unst -O unst.sh && sudo bash unst.sh
```
如果无法下载,请点这里。
你也可以使用 `curl` 下载:
```bash
curl -fsSL https://get.vpnsetup.net/unst -o unst.sh && sudo bash unst.sh
```
或者,你也可以使用这些链接:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/extras/vpnuninstall.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras/vpnuninstall.sh
```
## 手动卸载 VPN
另外,你也可以手动卸载 IPsec VPN。按照以下步骤操作。这些命令需要用 `root` 账户运行,或者使用 `sudo`。
**警告:** 以下步骤将从你的服务器中删除 IPsec VPN。所有的 VPN 配置将被**永久删除**,并且 Libreswan 和 xl2tpd 将被移除。此操作**不可撤销**!
### 步骤
* [第一步](#第一步)
* [第二步](#第二步)
* [第三步](#第三步)
* [第四步](#第四步)
* [可选步骤](#可选步骤)
* [完成后](#完成后)
### 第一步
```bash
service ipsec stop
service xl2tpd stop
rm -rf /usr/local/sbin/ipsec /usr/local/libexec/ipsec /usr/local/share/doc/libreswan
rm -f /etc/init/ipsec.conf /lib/systemd/system/ipsec.service /etc/init.d/ipsec \
/usr/lib/systemd/system/ipsec.service /etc/logrotate.d/libreswan \
/usr/lib/tmpfiles.d/libreswan.conf
```
### 第二步
#### Ubuntu & Debian
`apt-get purge xl2tpd`
#### CentOS/RHEL, Rocky Linux, AlmaLinux, Oracle Linux & Amazon Linux 2
`yum remove xl2tpd`
#### Alpine Linux
`apk del xl2tpd`
### 第三步
#### Ubuntu, Debian & Alpine Linux
编辑 `/etc/iptables.rules` 并删除不需要的规则。你之前的防火墙规则(如果有)备份在 `/etc/iptables.rules.old-日期-时间`。另外如果文件 `/etc/iptables/rules.v4` 存在,请编辑它。
如果启用了 IPv6 支持,请也编辑 `/etc/ip6tables.rules` 以及 `/etc/iptables/rules.v6`(如果存在)并删除不需要的规则。
#### CentOS/RHEL, Rocky Linux, AlmaLinux, Oracle Linux & Amazon Linux 2
编辑 `/etc/sysconfig/iptables` 并删除不需要的规则。你之前的防火墙规则(如果有)备份在 `/etc/sysconfig/iptables.old-日期-时间`。
如果启用了 IPv6 支持,请也编辑 `/etc/sysconfig/ip6tables` 并删除不需要的规则。
**注:** 如果使用 Rocky Linux, AlmaLinux, Oracle Linux 8 或者 CentOS/RHEL 8 并且在安装 VPN 时 firewalld 正在运行,则可能已配置 nftables。编辑 `/etc/sysconfig/nftables.conf` 并删除不需要的规则。你之前的防火墙规则备份在 `/etc/sysconfig/nftables.conf.old-日期-时间`。
### 第四步
编辑 `/etc/sysctl.conf` 并删除该标记后面的行: `# Added by hwdsl2 VPN script`。
编辑 `/etc/rc.local` 并删除该标记后面的行: `# Added by hwdsl2 VPN script`。\*不要\* 删除 `exit 0` (如果有)。
### 可选步骤
**注:** 这一步是可选的。
删除这些配置文件:
* /etc/ipsec.conf*
* /etc/ipsec.secrets*
* /etc/ppp/chap-secrets*
* /etc/ppp/options.xl2tpd*
* /etc/pam.d/pluto
* /etc/sysconfig/pluto
* /etc/default/pluto
* /etc/ipsec.d (目录)
* /etc/xl2tpd (目录)
要快速删除,可以复制并粘贴以下命令:
```bash
rm -f /etc/ipsec.conf* /etc/ipsec.secrets* /etc/ppp/chap-secrets* /etc/ppp/options.xl2tpd* \
/etc/pam.d/pluto /etc/sysconfig/pluto /etc/default/pluto
rm -rf /etc/ipsec.d /etc/xl2tpd
```
删除辅助脚本:
```bash
rm -f /usr/bin/ikev2.sh /opt/src/ikev2.sh \
/usr/bin/addvpnuser.sh /opt/src/addvpnuser.sh \
/usr/bin/delvpnuser.sh /opt/src/delvpnuser.sh
```
删除 fail2ban:
**注:** 这是可选的。Fail2ban 可以帮助保护你的服务器上的 SSH。\*不推荐\*删除它。
```bash
service fail2ban stop
# Ubuntu & Debian
apt-get purge fail2ban
# CentOS/RHEL, Rocky Linux, AlmaLinux, Oracle Linux & Amazon Linux 2
yum remove fail2ban
# Alpine Linux
apk del fail2ban
```
### 完成后
重启你的服务器。
## 授权协议
版权所有 (C) 2016-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
[](http://creativecommons.org/licenses/by-sa/3.0/)
这个项目是以[知识共享署名-相同方式共享3.0](http://creativecommons.org/licenses/by-sa/3.0/) 许可协议授权。
必须署名: 请包括我的名字在任何衍生产品,并且让我知道你是如何改善它的!
================================================
FILE: docs/uninstall.md
================================================
[English](uninstall.md) | [中文](uninstall-zh.md)
# Uninstall the VPN
* [Uninstall using helper script](#uninstall-using-helper-script)
* [Manually uninstall the VPN](#manually-uninstall-the-vpn)
## Uninstall using helper script
To uninstall IPsec VPN, run the [helper script](../extras/vpnuninstall.sh):
**Warning:** This helper script will remove IPsec VPN from your server. All VPN configuration will be **permanently deleted**, and Libreswan and xl2tpd will be removed. This **cannot be undone**!
```bash
wget https://get.vpnsetup.net/unst -O unst.sh && sudo bash unst.sh
```
Click here if you are unable to download.
You may also use `curl` to download:
```bash
curl -fsSL https://get.vpnsetup.net/unst -o unst.sh && sudo bash unst.sh
```
Alternative script URLs:
```bash
https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/extras/vpnuninstall.sh
https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras/vpnuninstall.sh
```
## Manually uninstall the VPN
Alternatively, you may manually uninstall IPsec VPN by following these steps. Commands must be run as `root`, or with `sudo`.
**Warning:** These steps will remove IPsec VPN from your server. All VPN configuration will be **permanently deleted**, and Libreswan and xl2tpd will be removed. This **cannot be undone**!
### Steps
* [First step](#first-step)
* [Second step](#second-step)
* [Third step](#third-step)
* [Fourth step](#fourth-step)
* [Optional](#optional)
* [When finished](#when-finished)
### First step
```bash
service ipsec stop
service xl2tpd stop
rm -rf /usr/local/sbin/ipsec /usr/local/libexec/ipsec /usr/local/share/doc/libreswan
rm -f /etc/init/ipsec.conf /lib/systemd/system/ipsec.service /etc/init.d/ipsec \
/usr/lib/systemd/system/ipsec.service /etc/logrotate.d/libreswan \
/usr/lib/tmpfiles.d/libreswan.conf
```
### Second step
#### Ubuntu & Debian
`apt-get purge xl2tpd`
#### CentOS/RHEL, Rocky Linux, AlmaLinux, Oracle Linux & Amazon Linux 2
`yum remove xl2tpd`
#### Alpine Linux
`apk del xl2tpd`
### Third step
#### Ubuntu, Debian & Alpine Linux
Edit `/etc/iptables.rules` and remove unneeded rules. Your original rules (if any) are backed up as `/etc/iptables.rules.old-date-time`. In addition, edit `/etc/iptables/rules.v4` if the file exists.
If IPv6 support was enabled, also edit `/etc/ip6tables.rules` and `/etc/iptables/rules.v6` (if it exists) and remove unneeded rules.
#### CentOS/RHEL, Rocky Linux, AlmaLinux, Oracle Linux & Amazon Linux 2
Edit `/etc/sysconfig/iptables` and remove unneeded rules. Your original rules (if any) are backed up as `/etc/sysconfig/iptables.old-date-time`.
If IPv6 support was enabled, also edit `/etc/sysconfig/ip6tables` and remove unneeded rules.
**Note:** If using Rocky Linux, AlmaLinux, Oracle Linux 8 or CentOS/RHEL 8 and firewalld was active during VPN setup, nftables may be configured. Edit `/etc/sysconfig/nftables.conf` and remove unneeded rules. Your original rules are backed up as `/etc/sysconfig/nftables.conf.old-date-time`.
### Fourth step
Edit `/etc/sysctl.conf` and remove the lines after `# Added by hwdsl2 VPN script`.
Edit `/etc/rc.local` and remove the lines after `# Added by hwdsl2 VPN script`. DO NOT remove `exit 0` (if any).
### Optional
**Note:** This step is optional.
Remove these config files:
* /etc/ipsec.conf*
* /etc/ipsec.secrets*
* /etc/ppp/chap-secrets*
* /etc/ppp/options.xl2tpd*
* /etc/pam.d/pluto
* /etc/sysconfig/pluto
* /etc/default/pluto
* /etc/ipsec.d (directory)
* /etc/xl2tpd (directory)
Copy and paste for fast removal:
```bash
rm -f /etc/ipsec.conf* /etc/ipsec.secrets* /etc/ppp/chap-secrets* /etc/ppp/options.xl2tpd* \
/etc/pam.d/pluto /etc/sysconfig/pluto /etc/default/pluto
rm -rf /etc/ipsec.d /etc/xl2tpd
```
Remove helper scripts:
```bash
rm -f /usr/bin/ikev2.sh /opt/src/ikev2.sh \
/usr/bin/addvpnuser.sh /opt/src/addvpnuser.sh \
/usr/bin/delvpnuser.sh /opt/src/delvpnuser.sh
```
Remove fail2ban:
**Note:** This is optional. Fail2ban can help protect SSH on your server. Removing it is NOT recommended.
```bash
service fail2ban stop
# Ubuntu & Debian
apt-get purge fail2ban
# CentOS/RHEL, Rocky Linux, AlmaLinux, Oracle Linux & Amazon Linux 2
yum remove fail2ban
# Alpine Linux
apk del fail2ban
```
### When finished
Reboot your server.
## License
Copyright (C) 2016-2026 [Lin Song](https://github.com/hwdsl2) [](https://www.linkedin.com/in/linsongui)
[](http://creativecommons.org/licenses/by-sa/3.0/)
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!
================================================
FILE: docs/vpn-book-ja.md
================================================
[« トップページへ戻る](../README-ja.md) | [English](vpn-book.md) | [简体中文](vpn-book-zh.md) | [繁體中文](vpn-book-zh-Hant.md) | [日本語](vpn-book-ja.md)
## 新刊:Privacy Tools in the Age of AI
AI時代において、次世代レベルのプライバシー保護を構築する方法を学びましょう。この本は電子書籍、紙版、オーディオブックの各形式で入手できます:
» [Amazon](https://books2read.com/privacy?store=amazon)
» [Google Play](https://books2read.com/privacy?store=google)
» [Apple Books](https://books2read.com/privacy?store=apple)
» [Hoopla](https://books2read.com/privacy?store=hoopla)
» [その他のプラットフォーム](https://books2read.com/privacy)
他言語版:[Español](https://books2read.com/privacyes)、[Deutsch](https://books2read.com/privacyde)、[Français](https://books2read.com/privacyfr)、[Italiano](https://books2read.com/privacyit)。
## VPNサーバーの構築方法: ステップバイステップガイド
この本は、IPsec VPN、OpenVPN、WireGuardサーバーを自前で構築するための**ステップバイステップガイド**です。この本は電子書籍とペーパーバックの形式で入手できます:
» [Amazon](https://books2read.com/vpnguideja?store=amazon)
» [その他のプラットフォーム](https://books2read.com/vpnguideja)
他言語版:[English](https://books2read.com/vpnguide)、[简体中文](https://books2read.com/vpnguidezh)、[繁體中文](https://books2read.com/vpnguidezht)、[Español](https://books2read.com/vpnguidees)、[Deutsch](https://books2read.com/vpnguidede)、[Français](https://books2read.com/vpnguidefr)、[Italiano](https://books2read.com/vpnguideit)、[Nederlands](https://books2read.com/vpnguidenl)、[Português](https://books2read.com/vpnguidept)。
## VPNサーバー完全ガイド: クラウド上で自前のVPNを構築するには
この本は、IPsec VPN、OpenVPN、WireGuardサーバーを自前で構築するための**完全ガイド**です。この本は電子書籍とペーパーバックの形式で入手できます:
» [Amazon](https://books2read.com/vpnja?store=amazon)
» [その他のプラットフォーム](https://books2read.com/vpnja)
他言語版:[English](https://books2read.com/vpn)、[简体中文](https://books2read.com/vpnzh)、[繁體中文](https://books2read.com/vpnzht)、[Español](https://books2read.com/vpnes)、[Deutsch](https://books2read.com/vpnde)、[Français](https://books2read.com/vpnfr)、[Italiano](https://books2read.com/vpnit)。
著者ページ:[amazon.com/author/linsong](https://amazon.com/author/linsong)
================================================
FILE: docs/vpn-book-zh-Hant.md
================================================
[« 返回首頁](../README-zh-Hant.md) | [English](vpn-book.md) | [简体中文](vpn-book-zh.md) | [繁體中文](vpn-book-zh-Hant.md) | [日本語](vpn-book-ja.md)
## 新:Privacy Tools in the Age of AI
了解如何在人工智慧時代建立更高等級的隱私保護。本書提供電子書、精裝本、平裝本與有聲書格式。
» [Amazon](https://books2read.com/privacy?store=amazon)
» [Google Play](https://books2read.com/privacy?store=google)
» [Apple Books](https://books2read.com/privacy?store=apple)
» [Hoopla](https://books2read.com/privacy?store=hoopla)
» [其他平台](https://books2read.com/privacy)
其他語言版本:[Español](https://books2read.com/privacyes)、[Deutsch](https://books2read.com/privacyde)、[Français](https://books2read.com/privacyfr)、[Italiano](https://books2read.com/privacyit)。
## 架設自己的 VPN 伺服器:IPsec VPN、OpenVPN 與 WireGuard 實作指南
本書是架設你自己的 IPsec VPN、OpenVPN 與 WireGuard 伺服器的**實作指南**。提供電子書與平裝本格式。
» [Google Play](https://books2read.com/vpnguidezht?store=google)
» [Apple Books](https://books2read.com/vpnguidezht?store=apple)
» [Amazon](https://books2read.com/vpnguidezht?store=amazon)
» [Amazon 平裝本](https://books2read.com/vpnguidezht?store=amazon-paperback&format=PAPERBACK)
» [其他平台](https://books2read.com/vpnguidezht)
其他語言版本:[简体中文](https://books2read.com/vpnguidezh)、[English](https://books2read.com/vpnguide)、[Español](https://books2read.com/vpnguidees)、[Deutsch](https://books2read.com/vpnguidede)、[Français](https://books2read.com/vpnguidefr)、[Italiano](https://books2read.com/vpnguideit)、[Nederlands](https://books2read.com/vpnguidenl)、[Português](https://books2read.com/vpnguidept)、[日本語](https://books2read.com/vpnguideja)。
## 架設自己的 VPN 伺服器:IPsec VPN、OpenVPN 與 WireGuard 完整指南
本書是架設你自己的 IPsec VPN、OpenVPN 與 WireGuard 伺服器的**完整指南**。提供電子書與平裝本格式。
» [Google Play](https://books2read.com/vpnzht?store=google)
» [Apple Books](https://books2read.com/vpnzht?store=apple)
» [Amazon](https://books2read.com/vpnzht?store=amazon)
» [Amazon 平裝本](https://books2read.com/vpnzht?store=amazon-paperback&format=PAPERBACK)
» [其他平台](https://books2read.com/vpnzht)
其他語言版本:[简体中文](https://books2read.com/vpnzh)、[English](https://books2read.com/vpn)、[Español](https://books2read.com/vpnes)、[Deutsch](https://books2read.com/vpnde)、[Français](https://books2read.com/vpnfr)、[Italiano](https://books2read.com/vpnit)、[日本語](https://books2read.com/vpnja)。
作者頁面:[amazon.com/author/linsong](https://amazon.com/author/linsong)
================================================
FILE: docs/vpn-book-zh.md
================================================
[« 返回主页](../README-zh.md) | [English](vpn-book.md) | [简体中文](vpn-book-zh.md) | [繁體中文](vpn-book-zh-Hant.md) | [日本語](vpn-book-ja.md)
## 新:Privacy Tools in the Age of AI
了解如何在人工智能时代构建更高级别的隐私保护。本书提供电子书、精装本、平装本和有声读物格式。
» [Amazon](https://books2read.com/privacy?store=amazon)
» [Google Play](https://books2read.com/privacy?store=google)
» [Apple Books](https://books2read.com/privacy?store=apple)
» [Hoopla](https://books2read.com/privacy?store=hoopla)
» [其他平台](https://books2read.com/privacy)
其他语言版本:[Español](https://books2read.com/privacyes)、[Deutsch](https://books2read.com/privacyde)、[Français](https://books2read.com/privacyfr)、[Italiano](https://books2read.com/privacyit)。
## 搭建自己的 VPN 服务器:IPsec VPN、OpenVPN 与 WireGuard 实战指南
本书是搭建你自己的 IPsec VPN、OpenVPN 和 WireGuard 服务器的**实战指南**。提供电子书和平装本格式。
» [Google Play](https://books2read.com/vpnguidezh?store=google)
» [Apple Books](https://books2read.com/vpnguidezh?store=apple)
» [Amazon](https://books2read.com/vpnguidezh?store=amazon)
» [Amazon 平装本](https://books2read.com/vpnguidezh?store=amazon-paperback&format=PAPERBACK)
» [其他平台](https://books2read.com/vpnguidezh)
其他语言版本:[繁體中文](https://books2read.com/vpnguidezht)、[English](https://books2read.com/vpnguide)、[Español](https://books2read.com/vpnguidees)、[Deutsch](https://books2read.com/vpnguidede)、[Français](https://books2read.com/vpnguidefr)、[Italiano](https://books2read.com/vpnguideit)、[Nederlands](https://books2read.com/vpnguidenl)、[Português](https://books2read.com/vpnguidept)、[日本語](https://books2read.com/vpnguideja)。
## 搭建自己的 VPN 服务器:IPsec VPN、OpenVPN 与 WireGuard 完整指南
本书是搭建你自己的 IPsec VPN、OpenVPN 和 WireGuard 服务器的**完整指南**。提供电子书和平装本格式。
» [Google Play](https://books2read.com/vpnzh?store=google)
» [Apple Books](https://books2read.com/vpnzh?store=apple)
» [Amazon](https://books2read.com/vpnzh?store=amazon)
» [Amazon 平装本](https://books2read.com/vpnzh?store=amazon-paperback&format=PAPERBACK)
» [其他平台](https://books2read.com/vpnzh)
其他语言版本:[繁體中文](https://books2read.com/vpnzht)、[English](https://books2read.com/vpn)、[Español](https://books2read.com/vpnes)、[Deutsch](https://books2read.com/vpnde)、[Français](https://books2read.com/vpnfr)、[Italiano](https://books2read.com/vpnit)、[日本語](https://books2read.com/vpnja)。
作者页面:[amazon.com/author/linsong](https://amazon.com/author/linsong)
================================================
FILE: docs/vpn-book.md
================================================
[« Back to home page](../README.md) | [English](vpn-book.md) | [简体中文](vpn-book-zh.md) | [繁體中文](vpn-book-zh-Hant.md) | [日本語](vpn-book-ja.md)
## New: Privacy Tools in the Age of AI
Learn how to build next-level privacy protection in the age of AI. This book is available in eBook, print and audiobook formats on:
» [Amazon](https://books2read.com/privacy?store=amazon)
» [Google Play](https://books2read.com/privacy?store=google)
» [Apple Books](https://books2read.com/privacy?store=apple)
» [Hoopla](https://books2read.com/privacy?store=hoopla)
» [Other Platforms](https://books2read.com/privacy)
Other language versions: [Español](https://books2read.com/privacyes), [Deutsch](https://books2read.com/privacyde), [Français](https://books2read.com/privacyfr), [Italiano](https://books2read.com/privacyit).
## Build Your Own VPN Server: A Step by Step Guide
This book is a **step-by-step guide** to building your own IPsec VPN, OpenVPN and WireGuard server. Available in eBook, print and audiobook formats on:
» [Amazon](https://books2read.com/vpnguide?store=amazon)
» [Google Play](https://books2read.com/vpnguide?store=google)
» [Apple Books](https://books2read.com/vpnguide?store=apple)
» [Hoopla](https://books2read.com/vpnguide?store=hoopla)
» [Other Platforms](https://books2read.com/vpnguide)
Other language versions: [简体中文](https://books2read.com/vpnguidezh), [繁體中文](https://books2read.com/vpnguidezht), [Español](https://books2read.com/vpnguidees), [Deutsch](https://books2read.com/vpnguidede), [Français](https://books2read.com/vpnguidefr), [Italiano](https://books2read.com/vpnguideit), [Nederlands](https://books2read.com/vpnguidenl), [Português](https://books2read.com/vpnguidept), [日本語](https://books2read.com/vpnguideja).
## Set Up Your Own IPsec VPN, OpenVPN and WireGuard Server
This book is a **comprehensive guide** to building your own IPsec VPN, OpenVPN and WireGuard server. Available in eBook, print and audiobook formats on:
» [Amazon](https://books2read.com/vpn?store=amazon)
» [Google Play](https://books2read.com/vpn?store=google)
» [Apple Books](https://books2read.com/vpn?store=apple)
» [Hoopla](https://books2read.com/vpn?store=hoopla)
» [Other Platforms](https://books2read.com/vpn)
Other language versions: [简体中文](https://books2read.com/vpnzh), [繁體中文](https://books2read.com/vpnzht), [Español](https://books2read.com/vpnes), [Deutsch](https://books2read.com/vpnde), [Français](https://books2read.com/vpnfr), [Italiano](https://books2read.com/vpnit), [日本語](https://books2read.com/vpnja).
Author page: [amazon.com/author/linsong](https://amazon.com/author/linsong)
================================================
FILE: extras/add_vpn_user.sh
================================================
#!/bin/bash
#
# Script to add/update a VPN user for both IPsec/L2TP and Cisco IPsec
#
# Copyright (C) 2018-2024 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!
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; }
conf_bk() { /bin/cp -f "$1" "$1.old-$SYS_DT" 2>/dev/null; }
show_intro() {
cat <<'EOF'
Welcome! Use this script to add or update a VPN user account for both
IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes.
If the username you specify already exists, it will be updated
with the new password. Otherwise, a new VPN user will be added.
EOF
}
add_vpn_user() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo bash $0'"
fi
if ! grep -qs "hwdsl2 VPN script" /etc/sysctl.conf \
|| [ ! -f /etc/ppp/chap-secrets ] || [ ! -f /etc/ipsec.d/passwd ]; then
cat 1>&2 <<'EOF'
Error: Your must first set up the IPsec VPN server before adding VPN users.
See: https://github.com/hwdsl2/setup-ipsec-vpn
EOF
exit 1
fi
command -v openssl >/dev/null 2>&1 || exiterr "'openssl' not found. Abort."
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
cat 1>&2 <&2
exit 1
fi
read -rp "Password: " VPN_PASSWORD
if [ -z "$VPN_PASSWORD" ]; then
echo "Abort. No changes were made." >&2
exit 1
fi
fi
if printf '%s' "$VPN_USER $VPN_PASSWORD" | LC_ALL=C grep -q '[^ -~]\+'; then
exiterr "VPN credentials must not contain non-ASCII characters."
fi
case "$VPN_USER $VPN_PASSWORD" in
*[\\\"\']*)
exiterr "VPN credentials must not contain these special characters: \\ \" '"
;;
esac
if [ -n "$1" ] && [ -n "$2" ]; then
show_intro
fi
cat <> /etc/ppp/chap-secrets <> /etc/ipsec.d/passwd <
#
# 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!
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; }
conf_bk() { /bin/cp -f "$1" "$1.old-$SYS_DT" 2>/dev/null; }
show_intro() {
cat <<'EOF'
Welcome! Use this script to delete a VPN user account for both
IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes.
EOF
}
del_vpn_user() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo bash $0'"
fi
if ! grep -qs "hwdsl2 VPN script" /etc/sysctl.conf \
|| [ ! -f /etc/ppp/chap-secrets ] || [ ! -f /etc/ipsec.d/passwd ]; then
cat 1>&2 <<'EOF'
Error: Your must first set up the IPsec VPN server before deleting VPN users.
See: https://github.com/hwdsl2/setup-ipsec-vpn
EOF
exit 1
fi
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
cat 1>&2 <&2
exit 1
fi
fi
if printf '%s' "$VPN_USER" | LC_ALL=C grep -q '[^ -~]\+'; then
exiterr "VPN username must not contain non-ASCII characters."
fi
case "$VPN_USER" in
*[\\\"\']*)
exiterr "VPN username must not contain these special characters: \\ \" '"
;;
esac
if [ "$(grep -c "^\"$VPN_USER\" " /etc/ppp/chap-secrets)" = 0 ] \
|| [ "$(grep -c "^$VPN_USER:\\\$1\\\$" /etc/ipsec.d/passwd)" = 0 ]; then
cat 1>&2 <<'EOF'
Error: The specified VPN user does not exist in /etc/ppp/chap-secrets
and/or /etc/ipsec.d/passwd.
EOF
exit 1
fi
if [ "$(grep -c -v -e '^#' -e '^[[:space:]]*$' /etc/ppp/chap-secrets)" = 1 ] \
|| [ "$(grep -c -v -e '^#' -e '^[[:space:]]*$' /etc/ipsec.d/passwd)" = 1 ]; then
cat 1>&2 <<'EOF'
Error: Could not delete the only VPN user from /etc/ppp/chap-secrets
and/or /etc/ipsec.d/passwd.
EOF
exit 1
fi
[ -n "$1" ] && show_intro
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!
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; }
bigecho() { echo "## $1"; }
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"
}
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"
}
check_root() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo bash $0'"
fi
}
check_os() {
os_type=$(lsb_release -si 2>/dev/null)
[ -z "$os_type" ] && [ -f /etc/os-release ] && os_type=$(. /etc/os-release && printf '%s' "$ID")
case $os_type in
[Aa]lpine)
os_type=alpine
;;
*)
os_type=other
;;
esac
}
check_libreswan() {
ipsec_ver=$(ipsec --version 2>/dev/null)
if ( ! grep -qs "hwdsl2 VPN script" /etc/sysctl.conf && ! grep -qs "hwdsl2" /opt/src/run.sh ) \
|| ! printf '%s' "$ipsec_ver" | grep -qi 'libreswan'; then
cat 1>&2 <<'EOF'
Error: This script can only be used with an IPsec server created using:
https://github.com/hwdsl2/setup-ipsec-vpn
EOF
exit 1
fi
}
check_ikev2() {
if ! grep -qs "conn ikev2-cp" /etc/ipsec.d/ikev2.conf; then
cat 1>&2 <<'EOF'
Error: You must first set up IKEv2 before changing IKEv2 server address.
See: https://vpnsetup.net/ikev2
EOF
exit 1
fi
}
check_utils_exist() {
command -v certutil >/dev/null 2>&1 || exiterr "'certutil' not found. Abort."
}
abort_and_exit() {
echo "Abort. No changes were made." >&2
exit 1
}
check_cert_exists() {
certutil -L -d sql:/etc/ipsec.d -n "$1" >/dev/null 2>&1
}
check_ca_cert_exists() {
check_cert_exists "IKEv2 VPN CA" || exiterr "Certificate 'IKEv2 VPN CA' does not exist. Abort."
}
get_server_address() {
server_addr_old=$(grep -s "leftcert=" /etc/ipsec.d/ikev2.conf | cut -f2 -d= | head -n 1)
check_ip "$server_addr_old" || check_dns_name "$server_addr_old" || exiterr "Could not get current VPN server address."
}
show_welcome() {
cat </dev/null)
if check_ip "$def_ip" \
&& ! printf '%s' "$def_ip" | grep -Eq '^(10|127|172\.(1[6-9]|2[0-9]|3[0-1])|192\.168|169\.254)\.'; then
public_ip="$def_ip"
fi
}
get_server_ip() {
use_default_ip=0
public_ip=${VPN_PUBLIC_IP:-''}
check_ip "$public_ip" || get_default_ip
check_ip "$public_ip" && { use_default_ip=1; return 0; }
bigecho "Trying to auto discover IP of this server..."
check_ip "$public_ip" || public_ip=$(dig @resolver1.opendns.com -t A -4 myip.opendns.com +short)
check_ip "$public_ip" || public_ip=$(wget -t 2 -T 10 -qO- http://ipv4.icanhazip.com)
check_ip "$public_ip" || public_ip=$(wget -t 2 -T 10 -qO- http://ip1.dynupdate.no-ip.com)
}
enter_server_address() {
echo "Do you want IKEv2 VPN clients to connect to this server using a DNS name,"
printf "e.g. vpn.example.com, instead of its IP address? [y/N] "
read -r response
case $response in
[yY][eE][sS]|[yY])
use_dns_name=1
echo
;;
*)
use_dns_name=0
echo
;;
esac
if [ "$use_dns_name" = 1 ]; then
read -rp "Enter the DNS name of this VPN server: " server_addr
until check_dns_name "$server_addr"; do
echo "Invalid DNS name. You must enter a fully qualified domain name (FQDN)."
read -rp "Enter the DNS name of this VPN server: " server_addr
done
else
get_server_ip
[ "$use_default_ip" = 0 ] && echo
read -rp "Enter the IPv4 address of this VPN server: [$public_ip] " server_addr
[ -z "$server_addr" ] && server_addr="$public_ip"
until check_ip "$server_addr"; do
echo "Invalid IP address."
read -rp "Enter the IPv4 address of this VPN server: [$public_ip] " server_addr
[ -z "$server_addr" ] && server_addr="$public_ip"
done
fi
}
check_server_address() {
if [ "$server_addr" = "$server_addr_old" ]; then
echo >&2
echo "Error: IKEv2 server address is already '$server_addr'. Nothing to do." >&2
abort_and_exit
fi
}
confirm_changes() {
cat </dev/null 2>&1 || exiterr "Failed to create server certificate."
else
certutil -z <(head -c 1024 /dev/urandom) \
-S -c "IKEv2 VPN CA" -n "$server_addr" \
-s "O=IKEv2 VPN,CN=$server_addr" \
-k rsa -g 3072 -v 120 \
-d sql:/etc/ipsec.d -t ",," \
--keyUsage digitalSignature,keyEncipherment \
--extKeyUsage serverAuth \
--extSAN "ip:$server_addr,dns:$server_addr" >/dev/null 2>&1 || exiterr "Failed to create server certificate."
fi
fi
}
update_ikev2_conf() {
bigecho "Updating IKEv2 configuration..."
if ! grep -qs '^include /etc/ipsec\.d/\*\.conf$' /etc/ipsec.conf; then
echo >> /etc/ipsec.conf
echo 'include /etc/ipsec.d/*.conf' >> /etc/ipsec.conf
fi
sed -i".old-$SYS_DT" \
-e "/^[[:space:]]\+leftcert=/d" \
-e "/^[[:space:]]\+leftid=/d" /etc/ipsec.d/ikev2.conf
if [ "$use_dns_name" = 1 ]; then
sed -i "/conn ikev2-cp/a \ leftid=@$server_addr" /etc/ipsec.d/ikev2.conf
else
sed -i "/conn ikev2-cp/a \ leftid=$server_addr" /etc/ipsec.d/ikev2.conf
fi
sed -i "/conn ikev2-cp/a \ leftcert=$server_addr" /etc/ipsec.d/ikev2.conf
}
update_ikev2_log() {
ikev2_log="/etc/ipsec.d/ikev2setup.log"
if [ -s "$ikev2_log" ]; then
sed -i "/VPN server address:/s/$server_addr_old/$server_addr/" "$ikev2_log"
fi
}
restart_ipsec_service() {
bigecho "Restarting IPsec service..."
mkdir -p /run/pluto
service ipsec restart 2>/dev/null
}
print_client_info() {
cat </dev/null
else
restart_ipsec_service
fi
print_client_info
}
## Defer until we have the complete script
ikev2changeaddr "$@"
exit 0
================================================
FILE: extras/ikev2onlymode.sh
================================================
#!/bin/bash
#
# Script to enable or disable IKEv2-only mode
#
# Copyright (C) 2022-2024 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!
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; }
bigecho() { echo "## $1"; }
check_root() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo bash $0'"
fi
}
abort_and_exit() {
echo "Abort. No changes were made." >&2
exit 1
}
continue_or_abort() {
printf '%s' "$1"
read -r response
case $response in
[yY][eE][sS]|[yY]|'')
echo
;;
*)
abort_and_exit
;;
esac
}
check_ikev2_exists() {
grep -qs "conn ikev2-cp" /etc/ipsec.conf || [ -f /etc/ipsec.d/ikev2.conf ]
}
check_libreswan() {
ipsec_ver=$(ipsec --version 2>/dev/null)
swan_ver=$(printf '%s' "$ipsec_ver" | sed -e 's/.*Libreswan U\?//' -e 's/\( (\|\/K\).*//')
if ! grep -qs "hwdsl2 VPN script" /etc/sysctl.conf \
|| ! grep -qs "config setup" /etc/ipsec.conf \
|| ! printf '%s' "$ipsec_ver" | grep -qi 'libreswan'; then
cat 1>&2 <<'EOF'
Error: Your must first set up the IPsec VPN server before selecting IKEv2-only mode.
See: https://github.com/hwdsl2/setup-ipsec-vpn
EOF
exit 1
fi
if ! check_ikev2_exists; then
cat 1>&2 <<'EOF'
Error: Your must first set up IKEv2 before selecting IKEv2-only mode.
See: https://vpnsetup.net/ikev2
EOF
exit 1
fi
}
check_swan_ver() {
if ! printf '%s\n%s' "4.2" "$swan_ver" | sort -C -V; then
cat 1>&2 </dev/null
}
print_complete() {
cat <<'EOF'
Done!
EOF
}
select_menu_option() {
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!
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
exiterr() { echo "Error: $1" >&2; exit 1; }
bigecho() { echo "## $1"; }
bigecho2() { printf '\e[2K\r%s' "## $1"; }
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"
}
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"
}
check_root() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo bash $0'"
fi
}
check_container() {
in_container=0
if grep -qs "hwdsl2" /opt/src/run.sh; then
in_container=1
fi
}
check_os() {
rh_file="/etc/redhat-release"
if [ -f "$rh_file" ]; then
os_type=centos
if grep -q "Red Hat" "$rh_file"; then
os_type=rhel
fi
[ -f /etc/oracle-release ] && os_type=ol
grep -qi rocky "$rh_file" && os_type=rocky
grep -qi alma "$rh_file" && os_type=alma
if grep -q "release 7" "$rh_file"; then
os_ver=7
elif grep -q "release 8" "$rh_file"; then
os_ver=8
grep -qi stream "$rh_file" && os_ver=8s
elif grep -q "release 9" "$rh_file"; then
os_ver=9
grep -qi stream "$rh_file" && os_ver=9s
elif grep -q "release 10" "$rh_file"; then
os_ver=10
grep -qi stream "$rh_file" && os_ver=10s
else
exiterr "This script only supports CentOS/RHEL 7-10."
fi
if [ "$os_type" = "centos" ] \
&& { [ "$os_ver" = 7 ] || [ "$os_ver" = 8 ] || [ "$os_ver" = 8s ]; }; then
exiterr "CentOS Linux $os_ver is EOL and not supported."
fi
elif grep -qs "Amazon Linux release 2 " /etc/system-release; then
os_type=amzn
os_ver=2
else
os_type=$(lsb_release -si 2>/dev/null)
[ -z "$os_type" ] && [ -f /etc/os-release ] && os_type=$(. /etc/os-release && printf '%s' "$ID")
case $os_type in
[Uu]buntu)
os_type=ubuntu
;;
[Dd]ebian|[Kk]ali)
os_type=debian
;;
[Rr]aspbian)
os_type=raspbian
;;
[Aa]lpine)
os_type=alpine
;;
*)
cat 1>&2 <<'EOF'
Error: This script only supports one of the following OS:
Ubuntu, Debian, CentOS/RHEL, Rocky Linux, AlmaLinux,
Oracle Linux, Amazon Linux 2 or Alpine Linux
EOF
exit 1
;;
esac
if [ "$os_type" = "alpine" ]; then
os_ver=$(. /etc/os-release && printf '%s' "$VERSION_ID" | cut -d '.' -f 1,2)
else
os_ver=$(sed 's/\..*//' /etc/debian_version | tr -dc 'A-Za-z0-9')
if [ "$os_ver" = 8 ] || [ "$os_ver" = 9 ] || [ "$os_ver" = "stretchsid" ] \
|| [ "$os_ver" = "bustersid" ] || [ -z "$os_ver" ]; then
cat 1>&2 <= 10 or Ubuntu >= 20.04.
This version of Ubuntu/Debian is too old and not supported.
EOF
exit 1
fi
fi
fi
}
check_libreswan() {
ipsec_ver=$(ipsec --version 2>/dev/null)
if ( ! grep -qs "hwdsl2 VPN script" /etc/sysctl.conf && ! grep -qs "hwdsl2" /opt/src/run.sh ) \
|| ! printf '%s' "$ipsec_ver" | grep -qi 'libreswan'; then
cat 1>&2 <<'EOF'
Error: Your must first set up the IPsec VPN server before setting up IKEv2.
See: https://github.com/hwdsl2/setup-ipsec-vpn
EOF
exit 1
fi
}
check_swan_ver() {
swan_ver=$(printf '%s' "$ipsec_ver" | sed -e 's/.*Libreswan U\?//' -e 's/\( (\|\/K\).*//')
if ! printf '%s\n%s' "3.23" "$swan_ver" | sort -C -V; then
cat 1>&2 </dev/null 2>&1 || exiterr "'certutil' not found. Abort."
command -v crlutil >/dev/null 2>&1 || exiterr "'crlutil' not found. Abort."
command -v pk12util >/dev/null 2>&1 || exiterr "'pk12util' not found. Abort."
}
abort_and_exit() {
echo "Abort. No changes were made." >&2
exit 1
}
confirm_or_abort() {
printf '%s' "$1"
read -r response
case $response in
[yY][eE][sS]|[yY])
echo
;;
*)
abort_and_exit
;;
esac
}
show_header() {
cat <<'EOF'
IKEv2 Script Copyright (c) 2020-2026 Lin Song 20 Mar 2026
EOF
}
show_usage() {
if [ -n "$1" ]; then
echo "Error: $1" >&2
fi
show_header
cat 1>&2 </dev/null 2>&1
}
check_cert_exists_and_exit() {
if certutil -L -d "$CERT_DB" -n "$1" >/dev/null 2>&1; then
echo "Error: Certificate '$1' already exists." >&2
abort_and_exit
fi
}
check_cert_status() {
cert_status=$(certutil -V -u C -d "$CERT_DB" -n "$1")
}
check_arguments() {
if [ "$use_defaults" = 1 ] && check_ikev2_exists; then
echo "Error: Invalid parameter '--auto'. IKEv2 is already set up on this server." >&2
echo " To manage VPN clients, re-run this script without '--auto'." >&2
echo " To change IKEv2 server address, see https://vpnsetup.net/ikev2" >&2
exit 1
fi
if [ "$((add_client + export_client + list_clients + revoke_client + delete_client))" -gt 1 ]; then
show_usage "Invalid parameters. Specify only one of '--addclient', '--exportclient', '--listclients', '--revokeclient' or '--deleteclient'."
fi
if [ "$remove_ikev2" = 1 ]; then
if [ "$((add_client + export_client + list_clients + revoke_client + delete_client + use_defaults))" -gt 0 ]; then
show_usage "Invalid parameters. '--removeikev2' cannot be specified with other parameters."
fi
fi
if ! check_ikev2_exists; then
[ "$add_client" = 1 ] && exiterr "You must first set up IKEv2 before adding a client."
[ "$export_client" = 1 ] && exiterr "You must first set up IKEv2 before exporting a client."
[ "$list_clients" = 1 ] && exiterr "You must first set up IKEv2 before listing clients."
[ "$revoke_client" = 1 ] && exiterr "You must first set up IKEv2 before revoking a client."
[ "$delete_client" = 1 ] && exiterr "You must first set up IKEv2 before deleting a client."
[ "$remove_ikev2" = 1 ] && exiterr "Cannot remove IKEv2 because it has not been set up on this server."
fi
if [ "$add_client" = 1 ]; then
if [ -z "$client_name" ] || ! check_client_name "$client_name"; then
exiterr "Invalid client name. Use one word only, no special characters except '-' and '_'."
elif check_cert_exists "$client_name"; then
exiterr "Invalid client name. Client '$client_name' already exists."
fi
fi
if [ "$export_client" = 1 ] || [ "$revoke_client" = 1 ] || [ "$delete_client" = 1 ]; then
get_server_address
if [ -z "$client_name" ] || ! check_client_name "$client_name" \
|| [ "$client_name" = "$CA_NAME" ] || [ "$client_name" = "$server_addr" ] \
|| ! check_cert_exists "$client_name"; then
exiterr "Invalid client name, or client does not exist."
fi
if [ "$delete_client" = 0 ] && ! check_cert_status "$client_name"; then
printf '%s' "Error: Certificate '$client_name' " >&2
if printf '%s' "$cert_status" | grep -q "revoked"; then
if [ "$revoke_client" = 1 ]; then
echo "has already been revoked." >&2
else
echo "has been revoked." >&2
fi
elif printf '%s' "$cert_status" | grep -q "expired"; then
echo "has expired." >&2
else
echo "is invalid." >&2
fi
exit 1
fi
fi
}
check_server_dns_name() {
if [ -n "$VPN_DNS_NAME" ]; then
check_dns_name "$VPN_DNS_NAME" || exiterr "Invalid DNS name. 'VPN_DNS_NAME' must be a fully qualified domain name (FQDN)."
fi
}
check_custom_dns() {
if { [ -n "$VPN_DNS_SRV1" ] && ! check_ip "$VPN_DNS_SRV1"; } \
|| { [ -n "$VPN_DNS_SRV2" ] && ! check_ip "$VPN_DNS_SRV2"; }; then
exiterr "Invalid DNS server(s)."
fi
}
check_client_validity() {
! { printf '%s' "$1" | LC_ALL=C grep -q '[^0-9]\+' || [ "$1" -lt "1" ] \
|| [ "$1" -gt "120" ] || [ "$1" != "$((10#$1))" ]; }
}
check_and_set_client_name() {
if [ -n "$VPN_CLIENT_NAME" ]; then
client_name="$VPN_CLIENT_NAME"
check_client_name "$client_name" \
|| exiterr "Invalid client name. Use one word only, no special characters except '-' and '_'."
else
client_name=vpnclient
fi
check_cert_exists "$client_name" && exiterr "Client '$client_name' already exists."
}
check_and_set_client_validity() {
if [ -n "$VPN_CLIENT_VALIDITY" ]; then
client_validity="$VPN_CLIENT_VALIDITY"
if ! check_client_validity "$client_validity"; then
cat </dev/null 2>&1; then
user_home_dir=$(getent passwd "$SUDO_USER" 2>/dev/null | cut -d: -f6)
if [ -d "$user_home_dir" ] && [ "$user_home_dir" != "/" ]; then
export_dir="$user_home_dir/"
export_to_home_dir=1
fi
fi
fi
}
get_default_ip() {
def_ip=$(ip -4 route get 1 | sed 's/ uid .*//' | awk '{print $NF;exit}' 2>/dev/null)
if check_ip "$def_ip" \
&& ! printf '%s' "$def_ip" | grep -Eq '^(10|127|172\.(1[6-9]|2[0-9]|3[0-1])|192\.168|169\.254)\.'; then
public_ip="$def_ip"
fi
}
get_server_ip() {
use_default_ip=0
public_ip=${VPN_PUBLIC_IP:-''}
check_ip "$public_ip" || get_default_ip
check_ip "$public_ip" && { use_default_ip=1; return 0; }
bigecho2 "Trying to auto discover IP of this server..."
check_ip "$public_ip" || public_ip=$(dig @resolver1.opendns.com -t A -4 myip.opendns.com +short)
check_ip "$public_ip" || public_ip=$(wget -t 2 -T 10 -qO- http://ipv4.icanhazip.com)
check_ip "$public_ip" || public_ip=$(wget -t 2 -T 10 -qO- http://ip1.dynupdate.no-ip.com)
}
get_server_address() {
server_addr=$(grep -s "leftcert=" "$IKEV2_CONF" | cut -f2 -d= | head -n 1)
[ -z "$server_addr" ] && server_addr=$(grep -s "leftcert=" "$IPSEC_CONF" | cut -f2 -d= | head -n 1)
check_ip "$server_addr" || check_dns_name "$server_addr" || exiterr "Could not get VPN server address."
}
list_existing_clients() {
echo "Checking for existing IKEv2 client(s)..."
echo
client_names=$(certutil -L -d "$CERT_DB" | grep -v -e '^$' -e "$CA_NAME" -e '\.' | tail -n +3 | cut -f1 -d ' ')
max_len=$(printf '%s\n' "$client_names" | wc -L 2>/dev/null)
[[ $max_len =~ ^[0-9]+$ ]] || max_len=64
[ "$max_len" -gt "64" ] && max_len=64
[ "$max_len" -lt "16" ] && max_len=16
printf "%-${max_len}s %s\n" 'Client Name' 'Certificate Status'
printf "%-${max_len}s %s\n" '------------' '-------------------'
if [ -n "$client_names" ]; then
client_list=$(printf '%s\n' "$client_names" | LC_ALL=C sort)
while IFS= read -r line; do
printf "%-${max_len}s " "$line"
client_status=$(certutil -V -u C -d "$CERT_DB" -n "$line" | grep -o -e ' valid' -e expired -e revoked | sed -e 's/^ //')
[ -z "$client_status" ] && client_status=unknown
printf '%s\n' "$client_status"
done <<< "$client_list"
fi
client_count=$(printf '%s\n' "$client_names" | wc -l 2>/dev/null)
[ -z "$client_names" ] && client_count=0
if [ "$client_count" = 1 ]; then
printf '\n%s\n' "Total: 1 client"
elif [ -n "$client_count" ]; then
printf '\n%s\n' "Total: $client_count clients"
fi
}
enter_server_address() {
echo "Do you want IKEv2 clients to connect to this server using a DNS name,"
printf "e.g. vpn.example.com, instead of its IP address? [y/N] "
read -r response
case $response in
[yY][eE][sS]|[yY])
use_dns_name=1
echo
;;
*)
use_dns_name=0
echo
;;
esac
if [ "$use_dns_name" = 1 ]; then
read -rp "Enter the DNS name of this VPN server: " server_addr
until check_dns_name "$server_addr"; do
echo "Invalid DNS name. You must enter a fully qualified domain name (FQDN)."
read -rp "Enter the DNS name of this VPN server: " server_addr
done
else
get_server_ip
[ "$use_default_ip" = 0 ] && { echo; echo; }
read -rp "Enter the IPv4 address of this VPN server: [$public_ip] " server_addr
[ -z "$server_addr" ] && server_addr="$public_ip"
until check_ip "$server_addr"; do
echo "Invalid IP address."
read -rp "Enter the IPv4 address of this VPN server: [$public_ip] " server_addr
[ -z "$server_addr" ] && server_addr="$public_ip"
done
fi
}
enter_client_name() {
echo
echo "Provide a name for the IKEv2 client."
echo "Use one word only, no special characters except '-' and '_'."
if [ "$1" = "with_defaults" ]; then
read -rp "Client name: [vpnclient] " client_name
[ -z "$client_name" ] && client_name=vpnclient
else
read -rp "Client name: " client_name
[ -z "$client_name" ] && abort_and_exit
fi
while ! check_client_name "$client_name" || check_cert_exists "$client_name"; do
if ! check_client_name "$client_name"; then
echo "Invalid client name."
else
echo "Invalid client name. Client '$client_name' already exists."
fi
if [ "$1" = "with_defaults" ]; then
read -rp "Client name: [vpnclient] " client_name
[ -z "$client_name" ] && client_name=vpnclient
else
read -rp "Client name: " client_name
[ -z "$client_name" ] && abort_and_exit
fi
done
}
enter_client_name_for() {
echo
list_existing_clients
if [ "$client_count" = 0 ]; then
echo
echo "No IKEv2 clients in the IPsec database. Nothing to $1." >&2
exit 1
fi
get_server_address
echo
read -rp "Enter the name of the IKEv2 client to $1: " client_name
[ -z "$client_name" ] && abort_and_exit
while ! check_client_name "$client_name" || [ "$client_name" = "$CA_NAME" ] \
|| [ "$client_name" = "$server_addr" ] || ! check_cert_exists "$client_name" \
|| ! check_cert_status "$client_name"; do
if ! check_client_name "$client_name" || [ "$client_name" = "$CA_NAME" ] \
|| [ "$client_name" = "$server_addr" ] || ! check_cert_exists "$client_name"; then
echo "Invalid client name, or client does not exist."
else
[ "$1" = "delete" ] && break
printf '%s' "Error: Certificate '$client_name' "
if printf '%s' "$cert_status" | grep -q "revoked"; then
if [ "$1" = "revoke" ]; then
echo "has already been revoked."
else
echo "has been revoked."
fi
elif printf '%s' "$cert_status" | grep -q "expired"; then
echo "has expired."
else
echo "is invalid."
fi
fi
read -rp "Enter the name of the IKEv2 client to $1: " client_name
[ -z "$client_name" ] && abort_and_exit
done
}
enter_client_validity() {
echo
echo "Specify the validity period (in months) for this client certificate."
read -rp "Enter an integer between 1 and 120: [120] " client_validity
[ -z "$client_validity" ] && client_validity=120
while ! check_client_validity "$client_validity"; do
echo "Invalid validity period."
read -rp "Enter an integer between 1 and 120: [120] " client_validity
[ -z "$client_validity" ] && client_validity=120
done
}
enter_custom_dns() {
echo
echo "By default, clients are set to use Google Public DNS when the VPN is active."
printf "Do you want to specify custom DNS servers for IKEv2? [y/N] "
read -r response
case $response in
[yY][eE][sS]|[yY])
use_custom_dns=1
;;
*)
use_custom_dns=0
dns_server_1=8.8.8.8
dns_server_2=8.8.4.4
dns_servers="8.8.8.8 8.8.4.4"
;;
esac
if [ "$use_custom_dns" = 1 ]; then
read -rp "Enter primary DNS server: " dns_server_1
until check_ip "$dns_server_1"; do
echo "Invalid DNS server."
read -rp "Enter primary DNS server: " dns_server_1
done
read -rp "Enter secondary DNS server (Enter to skip): " dns_server_2
until [ -z "$dns_server_2" ] || check_ip "$dns_server_2"; do
echo "Invalid DNS server."
read -rp "Enter secondary DNS server (Enter to skip): " dns_server_2
done
if [ -n "$dns_server_2" ]; then
dns_servers="$dns_server_1 $dns_server_2"
else
dns_servers="$dns_server_1"
fi
else
echo "Using Google Public DNS (8.8.8.8, 8.8.4.4)."
fi
echo
}
check_mobike_support() {
mobike_support=1
if uname -m | grep -qi -e '^arm' -e '^aarch64'; then
modprobe -q configs
if [ -f /proc/config.gz ]; then
if ! zcat /proc/config.gz | grep -q "CONFIG_XFRM_MIGRATE=y"; then
mobike_support=0
fi
else
mobike_support=0
fi
fi
kernel_conf="/boot/config-$(uname -r)"
if [ -f "$kernel_conf" ]; then
if ! grep -qs "CONFIG_XFRM_MIGRATE=y" "$kernel_conf"; then
mobike_support=0
fi
fi
# Linux kernels on Ubuntu do not support MOBIKE
if [ "$in_container" = 0 ]; then
if [ "$os_type" = "ubuntu" ] || uname -v | grep -qi ubuntu; then
mobike_support=0
fi
else
if uname -v | grep -qi ubuntu; then
mobike_support=0
fi
fi
if uname -a | grep -qi qnap; then
mobike_support=0
fi
if uname -a | grep -qi synology; then
mobike_support=0
fi
if [ "$mobike_support" = 1 ]; then
bigecho2 "Checking for MOBIKE support... available"
else
bigecho2 "Checking for MOBIKE support... not available"
fi
}
select_mobike() {
echo
mobike_enable=0
if [ "$mobike_support" = 1 ]; then
cat <<'EOF'
The MOBIKE IKEv2 extension allows VPN clients to change network attachment points,
e.g. switch between mobile data and Wi-Fi and keep the IPsec tunnel up on the new IP.
EOF
printf "Enable MOBIKE support? [Y/n] "
read -r response
case $response in
[yY][eE][sS]|[yY]|'')
mobike_enable=1
;;
*)
mobike_enable=0
;;
esac
fi
}
check_config_password() {
use_config_password=0
case $VPN_PROTECT_CONFIG in
[yY][eE][sS])
use_config_password=1
;;
*)
if grep -qs '^IKEV2_CONFIG_PASSWORD=.\+' "$CONF_FILE"; then
use_config_password=1
fi
;;
esac
}
select_config_password() {
if [ "$use_config_password" = 0 ]; then
cat <<'EOF'
IKEv2 client config files contain the client certificate, private key and CA certificate.
This script can optionally generate a random password to protect these files.
EOF
printf "Protect client config files using a password? [y/N] "
read -r response
case $response in
[yY][eE][sS]|[yY])
use_config_password=1
;;
*)
use_config_password=0
;;
esac
fi
}
select_menu_option() {
cat <<'EOF'
IKEv2 is already set up on this server.
Select an option:
1) Add a new client
2) Export config for an existing client
3) List existing clients
4) Revoke an existing client
5) Delete an existing client
6) Remove IKEv2
7) Exit
EOF
read -rp "Option: " selected_option
until [[ "$selected_option" =~ ^[1-7]$ ]]; do
printf '%s\n' "$selected_option: invalid selection."
read -rp "Option: " selected_option
done
}
print_server_info() {
cat </dev/null 2>&1 || exiterr "Failed to create client certificate."
}
create_p12_password() {
p12_password=$(LC_CTYPE=C tr -dc 'A-HJ-NPR-Za-km-z2-9' /dev/null | head -c 18)
[ -z "$p12_password" ] && exiterr "Could not generate a random password for .p12 file."
}
get_p12_password() {
if [ "$use_config_password" = 0 ]; then
create_p12_password
else
p12_password=$(grep -s '^IKEV2_CONFIG_PASSWORD=.\+' "$CONF_FILE" | tail -n 1 | cut -f2- -d= | sed -e "s/^'//" -e "s/'$//")
if [ -z "$p12_password" ]; then
create_p12_password
if [ -n "$CONF_FILE" ] && [ -n "$CONF_DIR" ]; then
mkdir -p "$CONF_DIR"
printf '%s\n' "IKEV2_CONFIG_PASSWORD='$p12_password'" >> "$CONF_FILE"
chmod 600 "$CONF_FILE"
fi
fi
fi
}
export_p12_file() {
bigecho2 "Creating client configuration..."
get_p12_password
p12_file="$export_dir$client_name.p12"
p12_file_enc="$export_dir$client_name.enc.p12"
pk12util -W "$p12_password" -d "$CERT_DB" -n "$client_name" -o "$p12_file_enc" >/dev/null || exit 1
if [ "$os_ver" = "bookwormsid" ] || openssl version 2>/dev/null | grep -q "^OpenSSL 3"; then
ca_crt="$export_dir$client_name.ca.crt"
client_crt="$export_dir$client_name.client.crt"
client_key="$export_dir$client_name.client.key"
pem_file="$export_dir$client_name.temp.pem"
openssl pkcs12 -in "$p12_file_enc" -passin "pass:$p12_password" -cacerts -nokeys -out "$ca_crt" || exit 1
openssl pkcs12 -in "$p12_file_enc" -passin "pass:$p12_password" -clcerts -nokeys -out "$client_crt" || exit 1
openssl pkcs12 -in "$p12_file_enc" -passin "pass:$p12_password" -passout "pass:$p12_password" \
-nocerts -out "$client_key" || exit 1
cat "$client_key" "$client_crt" "$ca_crt" > "$pem_file"
/bin/rm -f "$client_key" "$client_crt" "$ca_crt"
openssl pkcs12 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -export -in "$pem_file" -out "$p12_file_enc" \
-legacy -name "$client_name" -passin "pass:$p12_password" -passout "pass:$p12_password" || exit 1
if [ "$use_config_password" = 0 ]; then
openssl pkcs12 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -export -in "$pem_file" -out "$p12_file" \
-legacy -name "$client_name" -passin "pass:$p12_password" -passout pass: || exit 1
fi
/bin/rm -f "$pem_file"
elif [ "$os_type" = "alpine" ] || [ "$os_ver" = "kalirolling" ] || [ "$os_ver" = "bullseyesid" ]; then
pem_file="$export_dir$client_name.temp.pem"
openssl pkcs12 -in "$p12_file_enc" -out "$pem_file" -passin "pass:$p12_password" -passout "pass:$p12_password" || exit 1
openssl pkcs12 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -export -in "$pem_file" -out "$p12_file_enc" \
-name "$client_name" -passin "pass:$p12_password" -passout "pass:$p12_password" || exit 1
if [ "$use_config_password" = 0 ]; then
openssl pkcs12 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -export -in "$pem_file" -out "$p12_file" \
-name "$client_name" -passin "pass:$p12_password" -passout pass: || exit 1
fi
/bin/rm -f "$pem_file"
elif [ "$use_config_password" = 0 ]; then
pk12util -W "" -d "$CERT_DB" -n "$client_name" -o "$p12_file" >/dev/null || exit 1
fi
if [ "$use_config_password" = 1 ]; then
/bin/cp -f "$p12_file_enc" "$p12_file"
fi
if [ "$export_to_home_dir" = 1 ]; then
chown "$SUDO_USER:$SUDO_USER" "$p12_file"
fi
chmod 600 "$p12_file"
}
install_base64_uuidgen() {
if ! command -v base64 >/dev/null 2>&1 || ! command -v uuidgen >/dev/null 2>&1; then
bigecho2 "Installing required packages..."
if [ "$os_type" = "ubuntu" ] || [ "$os_type" = "debian" ] || [ "$os_type" = "raspbian" ]; then
export DEBIAN_FRONTEND=noninteractive
apt-get -yqq update || apt-get -yqq update || exiterr "'apt-get update' failed."
fi
fi
if ! command -v base64 >/dev/null 2>&1; then
if [ "$os_type" = "ubuntu" ] || [ "$os_type" = "debian" ] || [ "$os_type" = "raspbian" ]; then
apt-get -yqq install coreutils >/dev/null || exiterr "'apt-get install' failed."
else
yum -y -q install coreutils >/dev/null || exiterr "'yum install' failed."
fi
fi
if ! command -v uuidgen >/dev/null 2>&1; then
if [ "$os_type" = "ubuntu" ] || [ "$os_type" = "debian" ] || [ "$os_type" = "raspbian" ]; then
apt-get -yqq install uuid-runtime >/dev/null || exiterr "'apt-get install' failed."
else
yum -y -q install util-linux >/dev/null || exiterr "'yum install' failed."
fi
fi
}
install_uuidgen() {
if ! command -v uuidgen >/dev/null 2>&1; then
bigecho2 "Installing required packages..."
apk add -U -q uuidgen || exiterr "'apk add' failed."
fi
}
update_ikev2_conf() {
if grep -qs 'ike=aes256-sha2,aes128-sha2,aes256-sha1,aes128-sha1$' "$IKEV2_CONF"; then
bigecho2 "Updating IKEv2 configuration..."
sed -i \
"/ike=aes256-sha2,aes128-sha2,aes256-sha1,aes128-sha1$/s/ike=/ike=aes_gcm_c_256-hmac_sha2_256-ecp_256,/" \
"$IKEV2_CONF"
if [ "$os_type" = "alpine" ]; then
ipsec auto --add ikev2-cp >/dev/null
else
restart_ipsec_service >/dev/null
fi
fi
}
create_mobileconfig() {
[ -z "$server_addr" ] && get_server_address
p12_file_enc="$export_dir$client_name.enc.p12"
p12_base64=$(base64 -w 52 "$p12_file_enc")
/bin/rm -f "$p12_file_enc"
[ -z "$p12_base64" ] && exiterr "Could not encode .p12 file."
ca_base64=$(certutil -L -d "$CERT_DB" -n "$CA_NAME" -a | grep -v CERTIFICATE)
[ -z "$ca_base64" ] && exiterr "Could not encode $CA_NAME certificate."
uuid1=$(uuidgen)
[ -z "$uuid1" ] && exiterr "Could not generate UUID value."
mc_file="$export_dir$client_name.mobileconfig"
cat > "$mc_file" <
PayloadContent
IKEv2
AuthenticationMethod
Certificate
ChildSecurityAssociationParameters
DiffieHellmanGroup
19
EncryptionAlgorithm
AES-256-GCM
LifeTimeInMinutes
1410
DeadPeerDetectionRate
Medium
DisableRedirect
EnableCertificateRevocationCheck
0
EnablePFS
0
IKESecurityAssociationParameters
DiffieHellmanGroup
19
EncryptionAlgorithm
AES-256-GCM
IntegrityAlgorithm
SHA2-256
LifeTimeInMinutes
1410
LocalIdentifier
$client_name
PayloadCertificateUUID
$uuid1
OnDemandEnabled
0
OnDemandRules
InterfaceTypeMatch
WiFi
URLStringProbe
http://captive.apple.com/hotspot-detect.html
Action
Connect
InterfaceTypeMatch
Cellular
Action
Disconnect
Action
Ignore
RemoteAddress
$server_addr
RemoteIdentifier
$server_addr
UseConfigurationAttributeInternalIPSubnet
0
IPv4
OverridePrimary
1
PayloadDescription
Configures VPN settings
PayloadDisplayName
VPN
PayloadOrganization
IKEv2 VPN
PayloadIdentifier
com.apple.vpn.managed.$(uuidgen)
PayloadType
com.apple.vpn.managed
PayloadUUID
$(uuidgen)
PayloadVersion
1
Proxies
HTTPEnable
0
HTTPSEnable
0
UserDefinedName
$server_addr
VPNType
IKEv2
EOF
if [ "$use_config_password" = 0 ]; then
cat >> "$mc_file" <Password
$p12_password
EOF
fi
cat >> "$mc_file" <PayloadCertificateFileName
$client_name
PayloadContent
$p12_base64
PayloadDescription
Adds a PKCS#12-formatted certificate
PayloadDisplayName
$client_name
PayloadIdentifier
com.apple.security.pkcs12.$(uuidgen)
PayloadType
com.apple.security.pkcs12
PayloadUUID
$uuid1
PayloadVersion
1
PayloadContent
$ca_base64
PayloadCertificateFileName
ikev2vpnca
PayloadDescription
Adds a CA root certificate
PayloadDisplayName
Certificate Authority (CA)
PayloadIdentifier
com.apple.security.root.$(uuidgen)
PayloadType
com.apple.security.root
PayloadUUID
$(uuidgen)
PayloadVersion
1
PayloadDisplayName
IKEv2 VPN $server_addr
PayloadIdentifier
com.apple.vpn.managed.$(uuidgen)
PayloadRemovalDisallowed
PayloadType
Configuration
PayloadUUID
$(uuidgen)
PayloadVersion
1
EOF
if [ "$export_to_home_dir" = 1 ]; then
chown "$SUDO_USER:$SUDO_USER" "$mc_file"
fi
chmod 600 "$mc_file"
}
create_android_profile() {
[ -z "$server_addr" ] && get_server_address
p12_base64_oneline=$(base64 -w 52 "$export_dir$client_name.p12" | sed 's/$/\\n/' | tr -d '\n')
[ -z "$p12_base64_oneline" ] && exiterr "Could not encode .p12 file."
uuid2=$(uuidgen)
[ -z "$uuid2" ] && exiterr "Could not generate UUID value."
sswan_file="$export_dir$client_name.sswan"
cat > "$sswan_file" </dev/null 2>&1 </dev/null 2>&1 || exiterr "Failed to create server certificate."
else
certutil -z <(head -c 1024 /dev/urandom) \
-S -c "$CA_NAME" -n "$server_addr" \
-s "O=IKEv2 VPN,CN=$server_addr" \
-k rsa -g 3072 -v 120 \
-d "$CERT_DB" -t ",," \
--keyUsage digitalSignature,keyEncipherment \
--extKeyUsage serverAuth \
--extSAN "ip:$server_addr,dns:$server_addr" >/dev/null 2>&1 || exiterr "Failed to create server certificate."
fi
}
create_config_readme() {
readme_file="$export_dir$client_name-README.txt"
if [ "$in_container" = 0 ] && [ "$use_config_password" = 0 ] \
&& [ "$use_defaults" = 1 ] && [ ! -t 1 ] && [ ! -f "$readme_file" ]; then
cat > "$readme_file" <<'EOF'
These IKEv2 client config files were created during IPsec VPN setup.
To configure IKEv2 clients, see: https://vpnsetup.net/clients
EOF
if [ "$export_to_home_dir" = 1 ]; then
chown "$SUDO_USER:$SUDO_USER" "$readme_file"
fi
chmod 600 "$readme_file"
fi
}
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'}
IP6_PREFIX=$(printf '%s' "$IP6_NET" | sed 's|/[0-9]*$||; s|::$||')
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_PREFIX}::1000-${IP6_PREFIX}::1fff"
fi
if ! grep -qs '^include /etc/ipsec\.d/\*\.conf$' "$IPSEC_CONF"; then
echo >> "$IPSEC_CONF"
echo 'include /etc/ipsec.d/*.conf' >> "$IPSEC_CONF"
fi
cat > "$IKEV2_CONF" <> "$IKEV2_CONF" <> "$IKEV2_CONF" <> "$IKEV2_CONF" <> "$IKEV2_CONF" <> "$IKEV2_CONF"
else
echo " mobike=no" >> "$IKEV2_CONF"
fi
}
restart_ipsec_service() {
if [ "$in_container" = 0 ] || { [ "$in_container" = 1 ] && service ipsec status >/dev/null 2>&1; }; then
bigecho2 "Restarting IPsec service..."
mkdir -p /run/pluto
service ipsec restart 2>/dev/null
fi
}
check_ikev2_connection() {
if grep -qs 'mobike=yes' "$IKEV2_CONF"; then
(sleep 3
if ! ipsec status | grep -q ikev2-cp; then
sed -i '/mobike=yes/s/yes/no/' "$IKEV2_CONF"
if [ "$os_type" = "alpine" ]; then
ipsec auto --add ikev2-cp >/dev/null
else
restart_ipsec_service >/dev/null
fi
fi) >/dev/null 2>&1 &
fi
}
create_crl() {
bigecho "Revoking client certificate..."
if ! crlutil -L -d "$CERT_DB" -n "$CA_NAME" >/dev/null 2>&1; then
crlutil -G -d "$CERT_DB" -n "$CA_NAME" -c /dev/null >/dev/null
fi
sleep 2
}
add_client_cert_to_crl() {
sn_txt=$(certutil -L -d "$CERT_DB" -n "$client_name" | grep -A 1 'Serial Number' | tail -n 1)
sn_hex=$(printf '%s' "$sn_txt" | sed -e 's/^ *//' -e 's/://g')
sn_dec=$((16#$sn_hex))
[ -z "$sn_dec" ] && exiterr "Could not find serial number of client certificate."
crlutil -M -d "$CERT_DB" -n "$CA_NAME" >/dev/null </dev/null
}
remove_client_config() {
p12_file="$export_dir$client_name.p12"
mc_file="$export_dir$client_name.mobileconfig"
sswan_file="$export_dir$client_name.sswan"
if [ -f "$p12_file" ] || [ -f "$mc_file" ] || [ -f "$sswan_file" ]; then
bigecho "Removing client config files..."
if [ -f "$p12_file" ]; then
printf '%s\n' "$p12_file"
/bin/rm -f "$p12_file"
fi
if [ -f "$mc_file" ]; then
printf '%s\n' "$mc_file"
/bin/rm -f "$mc_file"
fi
if [ -f "$sswan_file" ]; then
printf '%s\n' "$sswan_file"
/bin/rm -f "$sswan_file"
fi
fi
}
print_client_added() {
cat <&2 <&2 </dev/null
done <<< "$cert_list"
crlutil -D -d "$CERT_DB" -n "$CA_NAME" 2>/dev/null
certutil -F -d "$CERT_DB" -n "$CA_NAME"
certutil -D -d "$CERT_DB" -n "$CA_NAME" 2>/dev/null
if grep -qs '^IKEV2_CONFIG_PASSWORD=.\+' "$CONF_FILE"; then
sed -i '/IKEV2_CONFIG_PASSWORD=/d' "$CONF_FILE"
fi
}
print_ikev2_removed() {
echo
echo "IKEv2 removed!"
}
ikev2setup() {
check_root
check_container
check_os
check_libreswan
check_swan_ver
check_utils_exist
use_defaults=0
assume_yes=0
add_client=0
export_client=0
list_clients=0
revoke_client=0
delete_client=0
remove_ikev2=0
while [ "$#" -gt 0 ]; do
case $1 in
--auto)
use_defaults=1
shift
;;
--addclient)
add_client=1
client_name="$2"
shift
shift
;;
--exportclient)
export_client=1
client_name="$2"
shift
shift
;;
--listclients)
list_clients=1
shift
;;
--revokeclient)
revoke_client=1
client_name="$2"
shift
shift
;;
--deleteclient)
delete_client=1
client_name="$2"
shift
shift
;;
--removeikev2)
remove_ikev2=1
shift
;;
-y|--yes)
assume_yes=1
shift
;;
-h|--help)
show_usage
;;
*)
show_usage "Unknown parameter: $1"
;;
esac
done
CA_NAME="IKEv2 VPN CA"
CERT_DB="sql:/etc/ipsec.d"
CONF_DIR="/etc/ipsec.d"
CONF_FILE="/etc/ipsec.d/.vpnconfig"
IKEV2_CONF="/etc/ipsec.d/ikev2.conf"
IPSEC_CONF="/etc/ipsec.conf"
check_arguments
check_config_password
get_export_dir
if [ "$add_client" = 1 ]; then
check_and_set_client_validity
show_header
show_add_client
create_client_cert
export_client_config
print_client_added
print_client_info
exit 0
fi
if [ "$export_client" = 1 ]; then
show_header
show_export_client
export_client_config
print_client_exported
print_client_info
exit 0
fi
if [ "$list_clients" = 1 ]; then
show_header
list_existing_clients
echo
exit 0
fi
if [ "$revoke_client" = 1 ]; then
show_header
confirm_revoke_cert
create_crl
add_client_cert_to_crl
reload_crls
remove_client_config
print_client_revoked
exit 0
fi
if [ "$delete_client" = 1 ]; then
show_header
confirm_delete_cert
delete_client_cert
remove_client_config
print_client_deleted
exit 0
fi
if [ "$remove_ikev2" = 1 ]; then
check_ipsec_conf
show_header
confirm_remove_ikev2
delete_ikev2_conf
if [ "$os_type" = "alpine" ]; then
ipsec auto --delete ikev2-cp
else
restart_ipsec_service
fi
delete_certificates
print_ikev2_removed
exit 0
fi
if check_ikev2_exists; then
show_header
select_menu_option
case $selected_option in
1)
enter_client_name
enter_client_validity
echo
create_client_cert
export_client_config
print_client_added
print_client_info
exit 0
;;
2)
enter_client_name_for export
echo
export_client_config
print_client_exported
print_client_info
exit 0
;;
3)
echo
list_existing_clients
echo
exit 0
;;
4)
enter_client_name_for revoke
echo
confirm_revoke_cert
create_crl
add_client_cert_to_crl
reload_crls
remove_client_config
print_client_revoked
exit 0
;;
5)
enter_client_name_for delete
echo
confirm_delete_cert
delete_client_cert
remove_client_config
print_client_deleted
exit 0
;;
6)
check_ipsec_conf
echo
confirm_remove_ikev2
delete_ikev2_conf
if [ "$os_type" = "alpine" ]; then
ipsec auto --delete ikev2-cp
else
restart_ipsec_service
fi
delete_certificates
print_ikev2_removed
exit 0
;;
*)
exit 0
;;
esac
fi
check_cert_exists_and_exit "$CA_NAME"
if [ "$use_defaults" = 0 ]; then
show_header
show_welcome
enter_server_address
check_cert_exists_and_exit "$server_addr"
enter_client_name with_defaults
enter_client_validity
enter_custom_dns
check_mobike_support
select_mobike
select_config_password
confirm_setup_options
else
check_server_dns_name
check_custom_dns
check_and_set_client_name
check_and_set_client_validity
show_header
show_start_setup
set_server_address
set_dns_servers
check_mobike_support
mobike_enable="$mobike_support"
fi
create_ca_server_certs
create_client_cert
export_client_config
create_config_readme
add_ikev2_connection
if [ "$os_type" = "alpine" ]; then
ipsec auto --add ikev2-cp >/dev/null
else
restart_ipsec_service
fi
check_ikev2_connection
print_setup_complete
print_client_info
if [ "$in_container" = 0 ]; then
check_swan_update
fi
}
## Defer setup until we have the complete script
ikev2setup "$@"
exit 0
================================================
FILE: extras/update_vpn_users.sh
================================================
#!/bin/bash
#
# Script to update VPN users for both IPsec/L2TP and Cisco IPsec
#
# Copyright (C) 2018-2024 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!
# =====================================================
# Define your own values for these variables
# - List of VPN usernames and passwords, separated by spaces
# - All values MUST be placed inside 'single quotes'
# - DO NOT use these special characters within values: \ " '
YOUR_USERNAMES=''
YOUR_PASSWORDS=''
# Example:
# YOUR_USERNAMES='username1 username2'
# YOUR_PASSWORDS='password1 password2'
# WARNING: *ALL* existing VPN users will be removed
# and replaced with the users listed here.
# =====================================================
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; }
conf_bk() { /bin/cp -f "$1" "$1.old-$SYS_DT" 2>/dev/null; }
onespace() { printf '%s' "$1" | tr -s ' '; }
noquotes() { printf '%s' "$1" | sed -e 's/^"\(.*\)"$/\1/' -e "s/^'\(.*\)'$/\1/"; }
noquotes2() { printf '%s' "$1" | sed -e 's/" "/ /g' -e "s/' '/ /g"; }
update_vpn_users() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo bash $0'"
fi
if ! grep -qs "hwdsl2 VPN script" /etc/sysctl.conf \
|| [ ! -f /etc/ppp/chap-secrets ] || [ ! -f /etc/ipsec.d/passwd ]; then
cat 1>&2 <<'EOF'
Error: Your must first set up the IPsec VPN server before updating VPN users.
See: https://github.com/hwdsl2/setup-ipsec-vpn
EOF
exit 1
fi
command -v openssl >/dev/null 2>&1 || exiterr "'openssl' not found. Abort."
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
cat 1>&2 <<'EOF'
For usage information, visit https://github.com/hwdsl2/setup-ipsec-vpn,
then click on Manage VPN Users.
EOF
exit 1
fi
[ -n "$YOUR_USERNAMES" ] && VPN_USERS="$YOUR_USERNAMES"
[ -n "$YOUR_PASSWORDS" ] && VPN_PASSWORDS="$YOUR_PASSWORDS"
VPN_USERS=$(noquotes "$VPN_USERS")
VPN_USERS=$(onespace "$VPN_USERS")
VPN_USERS=$(noquotes2 "$VPN_USERS")
VPN_PASSWORDS=$(noquotes "$VPN_PASSWORDS")
VPN_PASSWORDS=$(onespace "$VPN_PASSWORDS")
VPN_PASSWORDS=$(noquotes2 "$VPN_PASSWORDS")
if [ -z "$VPN_USERS" ] || [ -z "$VPN_PASSWORDS" ]; then
exiterr "All VPN credentials must be specified. Edit the script and re-enter them."
fi
if printf '%s' "$VPN_USERS $VPN_PASSWORDS" | LC_ALL=C grep -q '[^ -~]\+'; then
exiterr "VPN credentials must not contain non-ASCII characters."
fi
case "$VPN_USERS $VPN_PASSWORDS" in
*[\\\"\']*)
exiterr "VPN credentials must not contain these special characters: \\ \" '"
;;
esac
if printf '%s' "$VPN_USERS" | tr ' ' '\n' | sort | uniq -c | grep -qv '^ *1 '; then
exiterr "VPN usernames must not contain duplicates."
fi
cat <<'EOF'
Welcome! Use this script to update VPN user accounts for both
IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes.
WARNING: *ALL* existing VPN users will be removed and replaced
with the users listed below.
==================================================
Updated list of VPN users (username | password):
EOF
count=1
vpn_user=$(printf '%s' "$VPN_USERS" | cut -d ' ' -f 1)
vpn_password=$(printf '%s' "$VPN_PASSWORDS" | cut -d ' ' -f 1)
while [ -n "$vpn_user" ] && [ -n "$vpn_password" ]; do
cat <> /etc/ppp/chap-secrets <> /etc/ipsec.d/passwd <
#
# 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!
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; }
conf_bk() { /bin/cp -f "$1" "$1.old-$SYS_DT" 2>/dev/null; }
bigecho() { echo "## $1"; }
check_cidr() {
CIDR_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])(/(3[0-2]|[1-2][0-9]|[0-9]))$'
printf '%s' "$1" | tr -d '\n' | grep -Eq "$CIDR_REGEX"
}
check_root() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo bash $0'"
fi
}
check_os() {
rh_file="/etc/redhat-release"
if [ -f "$rh_file" ]; then
os_type=centos
if grep -q "Red Hat" "$rh_file"; then
os_type=rhel
fi
[ -f /etc/oracle-release ] && os_type=ol
grep -qi rocky "$rh_file" && os_type=rocky
grep -qi alma "$rh_file" && os_type=alma
if ! grep -q -E "release (7|8|9|10)" "$rh_file"; then
exiterr "This script only supports CentOS/RHEL 7-10."
fi
elif grep -qs "Amazon Linux release 2 " /etc/system-release; then
os_type=amzn
else
os_type=$(lsb_release -si 2>/dev/null)
[ -z "$os_type" ] && [ -f /etc/os-release ] && os_type=$(. /etc/os-release && printf '%s' "$ID")
case $os_type in
[Uu]buntu)
os_type=ubuntu
;;
[Dd]ebian|[Kk]ali|[Rr]aspbian)
os_type=debian
;;
[Aa]lpine)
os_type=alpine
;;
*)
cat 1>&2 <<'EOF'
Error: This script only supports one of the following OS:
Ubuntu, Debian, CentOS/RHEL, Rocky Linux, AlmaLinux,
Oracle Linux, Amazon Linux 2 or Alpine Linux
EOF
exit 1
;;
esac
fi
}
check_libreswan() {
ipsec_ver=$(ipsec --version 2>/dev/null)
if ! grep -qs "hwdsl2 VPN script" /etc/sysctl.conf \
|| ! printf '%s' "$ipsec_ver" | grep -qi 'libreswan'; then
exiterr "Cannot remove IPsec VPN because it has not been set up on this server."
fi
}
check_iface() {
def_iface=$(route 2>/dev/null | grep -m 1 '^default' | grep -o '[^ ]*$')
if [ "$os_type" != "alpine" ]; then
[ -z "$def_iface" ] && def_iface=$(ip -4 route list 0/0 2>/dev/null | grep -m 1 -Po '(?<=dev )(\S+)')
fi
def_state=$(cat "/sys/class/net/$def_iface/operstate" 2>/dev/null)
if [ -n "$def_state" ] && [ "$def_state" != "down" ]; then
check_wl=0
if [ "$os_type" = "ubuntu" ] || [ "$os_type" = "debian" ]; then
if ! uname -m | grep -qi -e '^arm' -e '^aarch64'; then
check_wl=1
fi
else
check_wl=1
fi
if [ "$check_wl" = 1 ]; then
case $def_iface in
wl*)
exiterr "Wireless interface '$def_iface' detected. DO NOT run this script on your PC or Mac!"
;;
esac
fi
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
}
abort_and_exit() {
echo "Abort. No changes were made." >&2
exit 1
}
confirm_or_abort() {
printf '%s' "$1"
read -r response
case $response in
[yY][eE][sS]|[yY])
echo
;;
*)
abort_and_exit
;;
esac
}
confirm_remove() {
cat <<'EOF'
WARNING: This script will remove IPsec VPN from this server. All VPN configuration
will be *permanently deleted*, and Libreswan and xl2tpd will be removed.
This *cannot* be undone!
EOF
confirm_or_abort "Are you sure you want to remove the VPN? [y/N] "
}
stop_services() {
bigecho "Stopping services..."
service ipsec stop
service xl2tpd stop
}
remove_ipsec() {
bigecho "Removing IPsec..."
/bin/rm -rf /usr/local/sbin/ipsec /usr/local/libexec/ipsec /usr/local/share/doc/libreswan
/bin/rm -f /etc/init/ipsec.conf /lib/systemd/system/ipsec.service /etc/init.d/ipsec \
/usr/lib/systemd/system/ipsec.service /etc/logrotate.d/libreswan \
/usr/lib/tmpfiles.d/libreswan.conf
}
remove_xl2tpd() {
bigecho "Removing xl2tpd..."
if [ "$os_type" = "ubuntu" ] || [ "$os_type" = "debian" ]; then
export DEBIAN_FRONTEND=noninteractive
apt-get -yqq purge xl2tpd >/dev/null
elif [ "$os_type" = "alpine" ]; then
apk del -q xl2tpd
else
yum -y -q remove xl2tpd >/dev/null
fi
}
remove_helper_scripts() {
bigecho "Removing helper scripts..."
for sc in ikev2.sh addvpnuser.sh delvpnuser.sh; do
if [ "$(readlink -f "/usr/bin/$sc" 2>/dev/null)" = "/opt/src/$sc" ]; then
/bin/rm -f "/usr/bin/$sc" "/opt/src/$sc"
fi
done
}
update_sysctl() {
if grep -qs "hwdsl2 VPN script" /etc/sysctl.conf; then
bigecho "Updating sysctl settings..."
conf_bk "/etc/sysctl.conf"
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
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
else
sed --follow-symlinks -i "/# Added by hwdsl2 VPN script/,+${count}d" /etc/sysctl.conf
fi
if [ ! -f /usr/bin/wg-quick ] && [ ! -f /usr/sbin/openvpn ]; then
echo 0 > /proc/sys/net/ipv4/ip_forward
fi
echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
fi
}
update_rclocal() {
if grep -qs "hwdsl2 VPN script" /etc/rc.local; then
bigecho "Updating rc.local..."
conf_bk "/etc/rc.local"
if [ "$os_type" = "alpine" ]; then
sed -i '/# Added by hwdsl2 VPN script/,/)&$/d' /etc/rc.local
else
sed --follow-symlinks -i '/# Added by hwdsl2 VPN script/,/)&$/d' /etc/rc.local
fi
fi
}
get_vpn_subnets() {
L2TP_NET=192.168.42.0/24
XAUTH_NET=192.168.43.0/24
if [ -s /etc/ipsec.conf ]; then
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 '!' | 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
fi
}
update_iptables_rules() {
use_nft=0
if [ "$os_type" = "ubuntu" ] || [ "$os_type" = "debian" ] \
|| [ "$os_type" = "alpine" ]; then
IPT_FILE=/etc/iptables.rules
IPT_FILE2=/etc/iptables/rules.v4
else
IPT_FILE=/etc/sysconfig/iptables
if grep -qs "hwdsl2 VPN script" /etc/sysconfig/nftables.conf; then
use_nft=1
IPT_FILE=/etc/sysconfig/nftables.conf
fi
fi
ipt_flag=0
if grep -qs "hwdsl2 VPN script" "$IPT_FILE"; then
ipt_flag=1
fi
ipi='iptables -D INPUT'
ipf='iptables -D FORWARD'
ipp='iptables -t nat -D POSTROUTING'
res='RELATED,ESTABLISHED'
if [ "$ipt_flag" = 1 ]; then
if [ "$use_nft" = 0 ]; then
bigecho "Updating IPTables rules..."
get_vpn_subnets
iptables-save > "$IPT_FILE.old-$SYS_DT"
$ipi -p udp --dport 1701 -m policy --dir in --pol none -j DROP
$ipi -m conntrack --ctstate INVALID -j DROP
$ipi -m conntrack --ctstate "$res" -j ACCEPT
$ipi -p udp -m multiport --dports 500,4500 -j ACCEPT
$ipi -p udp --dport 1701 -m policy --dir in --pol ipsec -j ACCEPT
$ipi -p udp --dport 1701 -j DROP
$ipf -m conntrack --ctstate INVALID -j DROP
$ipf -i "$NET_IFACE" -o ppp+ -m conntrack --ctstate "$res" -j ACCEPT
$ipf -i ppp+ -o "$NET_IFACE" -j ACCEPT
$ipf -i ppp+ -o ppp+ -j ACCEPT
$ipf -i "$NET_IFACE" -d "$XAUTH_NET" -m conntrack --ctstate "$res" -j ACCEPT
$ipf -s "$XAUTH_NET" -o "$NET_IFACE" -j ACCEPT
$ipf -s "$XAUTH_NET" -o ppp+ -j ACCEPT
iptables -D FORWARD -j DROP
$ipp -s "$XAUTH_NET" -o "$NET_IFACE" -m policy --dir out --pol none -j MASQUERADE
$ipp -s "$L2TP_NET" -o "$NET_IFACE" -j MASQUERADE
iptables-save > "$IPT_FILE"
if [ "$os_type" = "ubuntu" ] || [ "$os_type" = "debian" ]; then
if [ -f "$IPT_FILE2" ]; then
conf_bk "$IPT_FILE2"
/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_count=24
if grep -qs "release 9" /etc/redhat-release; then
diff_count=38
fi
if [ -f "$nft_bk" ] \
&& [ "$(diff -y --suppress-common-lines "$IPT_FILE" "$nft_bk" | wc -l)" = "$diff_count" ]; then
bigecho "Restoring nftables rules..."
conf_bk "$IPT_FILE"
/bin/cp -f "$nft_bk" "$IPT_FILE" && /bin/rm -f "$nft_bk"
nft flush ruleset
systemctl restart nftables
else
cat <<'EOF'
Note: This script cannot automatically remove nftables rules for the VPN.
To manually clean them up, edit /etc/sysconfig/nftables.conf
and remove unneeded rules. Your original rules are backed up as file
/etc/sysconfig/nftables.conf.old-date-time.
EOF
fi
fi
fi
}
update_crontabs() {
if [ "$os_type" = "alpine" ]; then
cron_cmd="rc-service -c ipsec zap start"
if grep -qs "$cron_cmd" /etc/crontabs/root; then
bigecho "Updating crontabs..."
sed -i "/$cron_cmd/d" /etc/crontabs/root
touch /etc/crontabs/cron.update
fi
fi
}
remove_config_files() {
bigecho "Removing VPN configuration..."
/bin/rm -f /etc/ipsec.conf* /etc/ipsec.secrets* /etc/ppp/chap-secrets* /etc/ppp/options.xl2tpd* \
/etc/pam.d/pluto /etc/sysconfig/pluto /etc/default/pluto
/bin/rm -rf /etc/ipsec.d /etc/xl2tpd
}
remove_vpn() {
stop_services
remove_ipsec
remove_xl2tpd
remove_helper_scripts
update_sysctl
update_rclocal
update_iptables_rules
update_crontabs
remove_config_files
}
print_vpn_removed() {
echo
echo "IPsec VPN removed!"
}
vpnuninstall() {
check_root
check_os
check_libreswan
check_iface
confirm_remove
remove_vpn
print_vpn_removed
}
## Defer until we have the complete script
vpnuninstall "$@"
exit 0
================================================
FILE: extras/vpnupgrade.sh
================================================
#!/bin/sh
#
# Script to update Libreswan on Ubuntu, Debian, CentOS/RHEL, Rocky Linux,
# AlmaLinux, Oracle Linux, Amazon Linux 2 and Alpine Linux
#
# The latest version of this script is available at:
# https://github.com/hwdsl2/setup-ipsec-vpn
#
# 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/
#
# Attribution required: please include my name in any derivative and let me
# know how you have improved it!
# (Optional) Specify which Libreswan version to install. See: https://libreswan.org
# If not specified, the latest supported version will be installed.
SWAN_VER=
### 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; }
check_root() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo sh $0'"
fi
}
check_vz() {
if [ -f /proc/user_beancounters ]; then
exiterr "OpenVZ VPS is not supported."
fi
}
check_os() {
rh_file="/etc/redhat-release"
if [ -f "$rh_file" ]; then
os_type=centos
if grep -q "Red Hat" "$rh_file"; then
os_type=rhel
fi
[ -f /etc/oracle-release ] && os_type=ol
grep -qi rocky "$rh_file" && os_type=rocky
grep -qi alma "$rh_file" && os_type=alma
if grep -q "release 7" "$rh_file"; then
os_ver=7
elif grep -q "release 8" "$rh_file"; then
os_ver=8
grep -qi stream "$rh_file" && os_ver=8s
elif grep -q "release 9" "$rh_file"; then
os_ver=9
grep -qi stream "$rh_file" && os_ver=9s
elif grep -q "release 10" "$rh_file"; then
os_ver=10
grep -qi stream "$rh_file" && os_ver=10s
else
exiterr "This script only supports CentOS/RHEL 7-10."
fi
if [ "$os_type" = "centos" ] \
&& { [ "$os_ver" = 7 ] || [ "$os_ver" = 8 ] || [ "$os_ver" = 8s ]; }; then
exiterr "CentOS Linux $os_ver is EOL and not supported."
fi
elif grep -qs "Amazon Linux release 2 " /etc/system-release; then
os_type=amzn
os_ver=2
else
os_type=$(lsb_release -si 2>/dev/null)
[ -z "$os_type" ] && [ -f /etc/os-release ] && os_type=$(. /etc/os-release && printf '%s' "$ID")
case $os_type in
[Uu]buntu)
os_type=ubuntu
;;
[Dd]ebian|[Kk]ali|[Rr]aspbian)
os_type=debian
;;
[Aa]lpine)
os_type=alpine
;;
*)
cat 1>&2 <<'EOF'
Error: This script only supports one of the following OS:
Ubuntu, Debian, CentOS/RHEL, Rocky Linux, AlmaLinux,
Oracle Linux, Amazon Linux 2 or Alpine Linux
EOF
exit 1
;;
esac
if [ "$os_type" != "alpine" ]; then
os_ver=$(sed 's/\..*//' /etc/debian_version | tr -dc 'A-Za-z0-9')
if [ "$os_ver" = 8 ] || [ "$os_ver" = 9 ] || [ "$os_ver" = "stretchsid" ] \
|| [ "$os_ver" = "bustersid" ] || [ -z "$os_ver" ]; then
cat 1>&2 <= 10 or Ubuntu >= 20.04.
This version of Ubuntu/Debian is too old and not supported.
EOF
exit 1
fi
fi
fi
}
check_libreswan() {
ipsec_ver=$(/usr/local/sbin/ipsec --version 2>/dev/null)
if ! printf '%s' "$ipsec_ver" | grep -qi '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
}
install_pkgs() {
if ! command -v wget >/dev/null 2>&1; then
if [ "$os_type" = "ubuntu" ] || [ "$os_type" = "debian" ]; then
export DEBIAN_FRONTEND=noninteractive
(
set -x
apt-get -yqq update || apt-get -yqq update
) || exiterr "'apt-get update' failed."
(
set -x
apt-get -yqq install wget >/dev/null || apt-get -yqq install wget >/dev/null
) || exiterr "'apt-get install wget' failed."
elif [ "$os_type" != "alpine" ]; then
(
set -x
yum -y -q install wget >/dev/null || yum -y -q install wget >/dev/null
) || exiterr "'yum install wget' failed."
fi
fi
if [ "$os_type" = "alpine" ]; then
(
set -x
apk add -U -q bash coreutils grep sed wget
) || exiterr "'apk add' failed."
fi
}
get_setup_url() {
base_url1="https://raw.githubusercontent.com/hwdsl2/setup-ipsec-vpn/master/extras"
base_url2="https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras"
sh_file="vpnupgrade_ubuntu.sh"
if [ "$os_type" = "centos" ] || [ "$os_type" = "rhel" ] || [ "$os_type" = "rocky" ] \
|| [ "$os_type" = "alma" ] || [ "$os_type" = "ol" ]; then
sh_file="vpnupgrade_centos.sh"
elif [ "$os_type" = "amzn" ]; then
sh_file="vpnupgrade_amzn.sh"
elif [ "$os_type" = "alpine" ]; then
sh_file="vpnupgrade_alpine.sh"
fi
setup_url1="$base_url1/$sh_file"
setup_url2="$base_url2/$sh_file"
}
run_setup() {
status=0
if tmpdir=$(mktemp --tmpdir -d vpn.XXXXX 2>/dev/null); then
if ( set -x; wget -t 3 -T 30 -q -O "$tmpdir/vpnup.sh" "$setup_url1" \
|| wget -t 3 -T 30 -q -O "$tmpdir/vpnup.sh" "$setup_url2" \
|| curl -m 30 -fsL "$setup_url1" -o "$tmpdir/vpnup.sh" 2>/dev/null ); then
VPN_UPDATE_SWAN_VER="$SWAN_VER" /bin/bash "$tmpdir/vpnup.sh" || status=1
else
status=1
echo "Error: Could not download update script." >&2
fi
/bin/rm -f "$tmpdir/vpnup.sh"
/bin/rmdir "$tmpdir"
else
exiterr "Could not create temporary directory."
fi
}
vpnupgrade() {
check_root
check_vz
check_os
check_libreswan
install_pkgs
get_setup_url
run_setup
}
## Defer setup until we have the complete script
vpnupgrade "$@"
exit "$status"
================================================
FILE: extras/vpnupgrade_alpine.sh
================================================
#!/bin/bash
#
# Script to update Libreswan on Alpine Linux
#
# The latest version of this script is available at:
# https://github.com/hwdsl2/setup-ipsec-vpn
#
# 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/
#
# Attribution required: please include my name in any derivative and let me
# know how you have improved it!
# (Optional) Specify which Libreswan version to install. See: https://libreswan.org
# If not specified, the latest supported version will be installed.
SWAN_VER=
### DO NOT edit below this line ###
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
SYS_DT=$(date +%F-%T | tr ':' '_')
[ -n "$VPN_UPDATE_SWAN_VER" ] && SWAN_VER="$VPN_UPDATE_SWAN_VER"
exiterr() { echo "Error: $1" >&2; exit 1; }
exiterr2() { exiterr "'apk add' failed."; }
bigecho() { echo "## $1"; }
check_root() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo bash $0'"
fi
}
check_vz() {
if [ -f /proc/user_beancounters ]; then
exiterr "OpenVZ VPS is not supported."
fi
}
check_os() {
os_type=$(lsb_release -si 2>/dev/null)
[ -z "$os_type" ] && [ -f /etc/os-release ] && os_type=$(. /etc/os-release && printf '%s' "$ID")
case $os_type in
[Aa]lpine)
os_type=alpine
;;
*)
exiterr "This script only supports Alpine Linux."
;;
esac
os_ver=$(. /etc/os-release && printf '%s' "$VERSION_ID" | cut -d '.' -f 1,2)
}
check_libreswan() {
ipsec_ver=$(/usr/local/sbin/ipsec --version 2>/dev/null)
swan_ver_old=$(printf '%s' "$ipsec_ver" | sed -e 's/.*Libreswan U\?//' -e 's/\( (\|\/K\).*//')
if ! printf '%s' "$ipsec_ver" | grep -qi '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
}
get_swan_ver() {
swan_ver_cur=5.3
base_url="https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0"
swan_ver_url="$base_url/upg-v1-$os_type-$os_ver-swanver"
swan_ver_latest=$(wget -t 2 -T 10 -qO- "$swan_ver_url" | head -n 1)
if printf '%s' "$swan_ver_latest" | grep -Eq '^([3-9]|[1-9][0-9]{1,2})(\.([0-9]|[1-9][0-9]{1,2})){1,2}$'; then
swan_ver_cur="$swan_ver_latest"
fi
[ -z "$SWAN_VER" ] && SWAN_VER="$swan_ver_cur"
}
check_swan_ver() {
if [ "$SWAN_VER" = "4.8" ] || [ "$SWAN_VER" = "4.13" ]; then
exiterr "Libreswan version $SWAN_VER is not supported."
fi
if ! printf '%s\n%s' "4.5" "$SWAN_VER" | sort -C -V \
|| ! printf '%s\n%s' "$SWAN_VER" "$swan_ver_cur" | sort -C -V; then
cat 1>&2 </dev/null 2>&1
cat > Makefile.inc.local <<'EOF'
WERROR_CFLAGS=-w -s
USE_DNSSEC=false
USE_DH2=true
FINALNSSDIR=/etc/ipsec.d
NSSDIR=/etc/ipsec.d
EOF
if [ "$SWAN_VER" = "4.5" ] || [ "$SWAN_VER" = "4.6" ] \
|| [ "$SWAN_VER" = "4.7" ]; then
echo "USE_GLIBC_KERN_FLIP_HEADERS=true" >> Makefile.inc.local
fi
NPROCS=$(grep -c ^processor /proc/cpuinfo)
[ -z "$NPROCS" ] && NPROCS=1
(
set -x
make "-j$((NPROCS+1))" -s base >/dev/null 2>&1 && make -s install-base >/dev/null 2>&1
)
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
service ipsec start >/dev/null 2>&1
exiterr "Libreswan $SWAN_VER failed to build."
fi
}
update_ikev2_script() {
bigecho "Updating IKEv2 script..."
cd /opt/src || exit 1
ikev2_url="https://raw.githubusercontent.com/hwdsl2/setup-ipsec-vpn/master/extras/ikev2setup.sh"
(
set -x
wget -t 3 -T 30 -q -O ikev2.sh.new "$ikev2_url"
) || /bin/rm -f ikev2.sh.new
if [ -s ikev2.sh.new ]; then
[ -s ikev2.sh ] && /bin/cp -f ikev2.sh "ikev2.sh.old-$SYS_DT"
/bin/cp -f ikev2.sh.new ikev2.sh && chmod +x ikev2.sh \
&& ln -s /opt/src/ikev2.sh /usr/bin 2>/dev/null
/bin/rm -f ikev2.sh.new
fi
}
update_config() {
bigecho "Updating VPN configuration..."
IKE_NEW=" ike=aes256-sha2;modp2048,aes128-sha2;modp2048,aes256-sha1;modp2048,aes128-sha1;modp2048"
PHASE2_NEW=" phase2alg=aes_gcm-null,aes128-sha1,aes256-sha1,aes256-sha2_512,aes128-sha2,aes256-sha2"
if uname -m | grep -qi '^arm'; then
if ! modprobe -q sha512; then
PHASE2_NEW=" phase2alg=aes_gcm-null,aes128-sha1,aes256-sha1,aes128-sha2,aes256-sha2"
fi
fi
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-$SYS_DT" \
-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
sed -i "/ikev2=never/d" /etc/ipsec.conf
sed -i "/conn shared/a \ ikev2=never" /etc/ipsec.conf
if ! grep -qs "ikev1-policy" /etc/ipsec.conf; then
sed -i "/config setup/a \ ikev1-policy=accept" /etc/ipsec.conf
fi
if grep -qs ike-frag /etc/ipsec.d/ikev2.conf; then
sed -i".old-$SYS_DT" 's/^[[:space:]]\+ike-frag=/ fragmentation=/' /etc/ipsec.d/ikev2.conf
fi
}
restart_ipsec() {
bigecho "Restarting IPsec service..."
mkdir -p /run/pluto
sed -i '1c\#!/sbin/openrc-run' /etc/init.d/ipsec
service ipsec restart >/dev/null 2>&1
}
show_setup_complete() {
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!
# (Optional) Specify which Libreswan version to install. See: https://libreswan.org
# If not specified, the latest supported version will be installed.
SWAN_VER=
### DO NOT edit below this line ###
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
SYS_DT=$(date +%F-%T | tr ':' '_')
[ -n "$VPN_UPDATE_SWAN_VER" ] && SWAN_VER="$VPN_UPDATE_SWAN_VER"
exiterr() { echo "Error: $1" >&2; exit 1; }
exiterr2() { exiterr "'yum install' failed."; }
bigecho() { echo "## $1"; }
check_root() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo bash $0'"
fi
}
check_os() {
if ! grep -qs "Amazon Linux release 2 " /etc/system-release; then
exiterr "This script only supports Amazon Linux 2."
fi
}
check_libreswan() {
ipsec_ver=$(/usr/local/sbin/ipsec --version 2>/dev/null)
swan_ver_old=$(printf '%s' "$ipsec_ver" | sed -e 's/.*Libreswan U\?//' -e 's/\( (\|\/K\).*//')
if ! printf '%s' "$ipsec_ver" | grep -qi '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
}
get_swan_ver() {
swan_ver_cur=5.3
base_url="https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0"
swan_ver_url="$base_url/upg-v1-amzn-2-swanver"
swan_ver_latest=$(wget -t 2 -T 10 -qO- "$swan_ver_url" | head -n 1)
if printf '%s' "$swan_ver_latest" | grep -Eq '^([3-9]|[1-9][0-9]{1,2})(\.([0-9]|[1-9][0-9]{1,2})){1,2}$'; then
swan_ver_cur="$swan_ver_latest"
fi
[ -z "$SWAN_VER" ] && SWAN_VER="$swan_ver_cur"
}
check_swan_ver() {
if [ "$SWAN_VER" = "4.8" ] || [ "$SWAN_VER" = "4.13" ]; then
exiterr "Libreswan version $SWAN_VER is not supported."
fi
if [ "$SWAN_VER" != "3.32" ] \
&& { ! printf '%s\n%s' "4.1" "$SWAN_VER" | sort -C -V \
|| ! printf '%s\n%s' "$SWAN_VER" "$swan_ver_cur" | sort -C -V; }; then
cat 1>&2 </dev/null
) || exiterr2
}
get_libreswan() {
bigecho "Downloading Libreswan..."
cd /opt/src || exit 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"
(
set -x
wget -t 3 -T 30 -q -O "$swan_file" "$swan_url1" || wget -t 3 -T 30 -q -O "$swan_file" "$swan_url2"
) || exit 1
/bin/rm -rf "/opt/src/libreswan-$SWAN_VER"
tar xzf "$swan_file" && /bin/rm -f "$swan_file"
}
install_libreswan() {
bigecho "Compiling and installing Libreswan, please wait..."
cd "libreswan-$SWAN_VER" || exit 1
service ipsec stop >/dev/null 2>&1
[ "$SWAN_VER" = "4.1" ] && sed -i 's/ sysv )/ sysvinit )/' programs/setup/setup.in
cat > Makefile.inc.local <<'EOF'
WERROR_CFLAGS=-w -s
USE_DNSSEC=false
USE_DH2=true
EOF
if [ "$SWAN_VER" != "3.32" ]; then
cat >> Makefile.inc.local <<'EOF'
USE_NSS_KDF=false
USE_LINUX_AUDIT=false
USE_SECCOMP=false
FINALNSSDIR=/etc/ipsec.d
NSSDIR=/etc/ipsec.d
EOF
fi
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
(
set -x
make "-j$((NPROCS+1))" -s base >/dev/null 2>&1 && make -s install-base >/dev/null 2>&1
)
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
service ipsec start >/dev/null 2>&1
exiterr "Libreswan $SWAN_VER failed to build."
fi
}
restore_selinux() {
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_ikev2_script() {
bigecho "Updating IKEv2 script..."
cd /opt/src || exit 1
ikev2_url="https://raw.githubusercontent.com/hwdsl2/setup-ipsec-vpn/master/extras/ikev2setup.sh"
(
set -x
wget -t 3 -T 30 -q -O ikev2.sh.new "$ikev2_url"
) || /bin/rm -f ikev2.sh.new
if [ -s ikev2.sh.new ]; then
[ -s ikev2.sh ] && /bin/cp -f ikev2.sh "ikev2.sh.old-$SYS_DT"
/bin/cp -f ikev2.sh.new ikev2.sh && chmod +x ikev2.sh \
&& ln -s /opt/src/ikev2.sh /usr/bin 2>/dev/null
/bin/rm -f ikev2.sh.new
fi
}
update_config() {
bigecho "Updating VPN configuration..."
IKE_NEW=" ike=aes256-sha2;modp2048,aes128-sha2;modp2048,aes256-sha1;modp2048,aes128-sha1;modp2048"
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-$SYS_DT" \
-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
sed -i "/ikev2=never/d" /etc/ipsec.conf
sed -i "/conn shared/a \ ikev2=never" /etc/ipsec.conf
if ! grep -qs "ikev1-policy" /etc/ipsec.conf; then
sed -i "/config setup/a \ ikev1-policy=accept" /etc/ipsec.conf
fi
if grep -qs ike-frag /etc/ipsec.d/ikev2.conf; then
sed -i".old-$SYS_DT" 's/^[[:space:]]\+ike-frag=/ fragmentation=/' /etc/ipsec.d/ikev2.conf
fi
}
restart_ipsec() {
bigecho "Restarting IPsec service..."
mkdir -p /run/pluto
service ipsec restart 2>/dev/null
}
show_setup_complete() {
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!
# (Optional) Specify which Libreswan version to install. See: https://libreswan.org
# If not specified, the latest supported version will be installed.
SWAN_VER=
### DO NOT edit below this line ###
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
SYS_DT=$(date +%F-%T | tr ':' '_')
[ -n "$VPN_UPDATE_SWAN_VER" ] && SWAN_VER="$VPN_UPDATE_SWAN_VER"
exiterr() { echo "Error: $1" >&2; exit 1; }
exiterr2() { exiterr "'yum install' failed."; }
bigecho() { echo "## $1"; }
check_root() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo bash $0'"
fi
}
check_vz() {
if [ -f /proc/user_beancounters ]; then
exiterr "OpenVZ VPS is not supported."
fi
}
check_os() {
rh_file="/etc/redhat-release"
if [ -f "$rh_file" ]; then
os_type=centos
if grep -q "Red Hat" "$rh_file"; then
os_type=rhel
fi
[ -f /etc/oracle-release ] && os_type=ol
grep -qi rocky "$rh_file" && os_type=rocky
grep -qi alma "$rh_file" && os_type=alma
if grep -q "release 7" "$rh_file"; then
os_ver=7
elif grep -q "release 8" "$rh_file"; then
os_ver=8
grep -qi stream "$rh_file" && os_ver=8s
elif grep -q "release 9" "$rh_file"; then
os_ver=9
grep -qi stream "$rh_file" && os_ver=9s
elif grep -q "release 10" "$rh_file"; then
os_ver=10
grep -qi stream "$rh_file" && os_ver=10s
else
exiterr "This script only supports CentOS/RHEL 7-10."
fi
if [ "$os_type" = "centos" ] \
&& { [ "$os_ver" = 7 ] || [ "$os_ver" = 8 ] || [ "$os_ver" = 8s ]; }; then
exiterr "CentOS Linux $os_ver is EOL and not supported."
fi
else
cat 1>&2 <<'EOF'
Error: This script only supports one of the following OS:
CentOS/RHEL, Rocky Linux, AlmaLinux or Oracle Linux
EOF
exit 1
fi
}
check_libreswan() {
ipsec_ver=$(/usr/local/sbin/ipsec --version 2>/dev/null)
swan_ver_old=$(printf '%s' "$ipsec_ver" | sed -e 's/.*Libreswan U\?//' -e 's/\( (\|\/K\).*//')
if ! printf '%s' "$ipsec_ver" | grep -qi '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
}
get_swan_ver() {
swan_ver_cur=5.3
base_url="https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0"
swan_ver_url="$base_url/upg-v1-$os_type-$os_ver-swanver"
swan_ver_latest=$(wget -t 2 -T 10 -qO- "$swan_ver_url" | head -n 1)
if printf '%s' "$swan_ver_latest" | grep -Eq '^([3-9]|[1-9][0-9]{1,2})(\.([0-9]|[1-9][0-9]{1,2})){1,2}$'; then
swan_ver_cur="$swan_ver_latest"
fi
[ -z "$SWAN_VER" ] && SWAN_VER="$swan_ver_cur"
}
check_swan_ver() {
if [ "$SWAN_VER" = "4.8" ] || [ "$SWAN_VER" = "4.13" ]; then
exiterr "Libreswan version $SWAN_VER is not supported."
fi
if [ "$SWAN_VER" != "3.32" ] \
&& { ! printf '%s\n%s' "4.1" "$SWAN_VER" | sort -C -V \
|| ! printf '%s\n%s' "$SWAN_VER" "$swan_ver_cur" | sort -C -V; }; then
cat 1>&2 </dev/null
) || exiterr2
}
install_pkgs_2() {
erp="--enablerepo"
rp1="$erp=*server-*optional*"
rp2="$erp=*releases-optional*"
if [ "$os_type$os_ver" = "ol7" ]; then
rp2="$erp=ol7_optional_latest"
fi
if [ "$os_ver" = 7 ]; then
(
set -x
yum "$rp1" "$rp2" -y -q install systemd-devel libevent-devel fipscheck-devel >/dev/null
) || exiterr2
else
(
set -x
yum -y -q install systemd-devel libevent-devel >/dev/null
) || exiterr2
fi
}
get_libreswan() {
bigecho "Downloading Libreswan..."
cd /opt/src || exit 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"
(
set -x
wget -t 3 -T 30 -q -O "$swan_file" "$swan_url1" || wget -t 3 -T 30 -q -O "$swan_file" "$swan_url2"
) || exit 1
/bin/rm -rf "/opt/src/libreswan-$SWAN_VER"
tar xzf "$swan_file" && /bin/rm -f "$swan_file"
}
install_libreswan() {
bigecho "Compiling and installing Libreswan, please wait..."
cd "libreswan-$SWAN_VER" || exit 1
service ipsec stop >/dev/null 2>&1
[ "$SWAN_VER" = "4.1" ] && sed -i 's/ sysv )/ sysvinit )/' programs/setup/setup.in
cat > Makefile.inc.local <<'EOF'
WERROR_CFLAGS=-w -s
USE_DNSSEC=false
USE_DH2=true
EOF
if [ "$SWAN_VER" != "3.32" ]; then
cat >> Makefile.inc.local <<'EOF'
USE_NSS_KDF=false
USE_LINUX_AUDIT=false
USE_SECCOMP=false
FINALNSSDIR=/etc/ipsec.d
NSSDIR=/etc/ipsec.d
EOF
fi
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
(
set -x
make "-j$((NPROCS+1))" -s base >/dev/null 2>&1 && make -s install-base >/dev/null 2>&1
)
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
service ipsec start >/dev/null 2>&1
exiterr "Libreswan $SWAN_VER failed to build."
fi
}
restore_selinux() {
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_ikev2_script() {
bigecho "Updating IKEv2 script..."
cd /opt/src || exit 1
ikev2_url="https://raw.githubusercontent.com/hwdsl2/setup-ipsec-vpn/master/extras/ikev2setup.sh"
(
set -x
wget -t 3 -T 30 -q -O ikev2.sh.new "$ikev2_url"
) || /bin/rm -f ikev2.sh.new
if [ -s ikev2.sh.new ]; then
[ -s ikev2.sh ] && /bin/cp -f ikev2.sh "ikev2.sh.old-$SYS_DT"
/bin/cp -f ikev2.sh.new ikev2.sh && chmod +x ikev2.sh \
&& ln -s /opt/src/ikev2.sh /usr/bin 2>/dev/null
/bin/rm -f ikev2.sh.new
fi
}
update_config() {
bigecho "Updating VPN configuration..."
IKE_NEW=" ike=aes256-sha2;modp2048,aes128-sha2;modp2048,aes256-sha1;modp2048,aes128-sha1;modp2048"
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-$SYS_DT" \
-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
sed -i "/ikev2=never/d" /etc/ipsec.conf
sed -i "/conn shared/a \ ikev2=never" /etc/ipsec.conf
if ! grep -qs "ikev1-policy" /etc/ipsec.conf; then
sed -i "/config setup/a \ ikev1-policy=accept" /etc/ipsec.conf
fi
if grep -qs ike-frag /etc/ipsec.d/ikev2.conf; then
sed -i".old-$SYS_DT" 's/^[[:space:]]\+ike-frag=/ fragmentation=/' /etc/ipsec.d/ikev2.conf
fi
}
restart_ipsec() {
bigecho "Restarting IPsec service..."
mkdir -p /run/pluto
service ipsec restart 2>/dev/null
}
show_setup_complete() {
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!
# (Optional) Specify which Libreswan version to install. See: https://libreswan.org
# If not specified, the latest supported version will be installed.
SWAN_VER=
### DO NOT edit below this line ###
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
SYS_DT=$(date +%F-%T | tr ':' '_')
[ -n "$VPN_UPDATE_SWAN_VER" ] && SWAN_VER="$VPN_UPDATE_SWAN_VER"
exiterr() { echo "Error: $1" >&2; exit 1; }
exiterr2() { exiterr "'apt-get install' failed."; }
bigecho() { echo "## $1"; }
check_root() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo bash $0'"
fi
}
check_vz() {
if [ -f /proc/user_beancounters ]; then
exiterr "OpenVZ VPS is not supported."
fi
}
check_os() {
os_type=$(lsb_release -si 2>/dev/null)
[ -z "$os_type" ] && [ -f /etc/os-release ] && os_type=$(. /etc/os-release && printf '%s' "$ID")
case $os_type in
[Uu]buntu)
os_type=ubuntu
;;
[Dd]ebian|[Kk]ali)
os_type=debian
;;
[Rr]aspbian)
os_type=raspbian
;;
*)
exiterr "This script only supports Ubuntu and Debian."
;;
esac
os_ver=$(sed 's/\..*//' /etc/debian_version | tr -dc 'A-Za-z0-9')
if [ "$os_ver" = 8 ] || [ "$os_ver" = 9 ] || [ "$os_ver" = "stretchsid" ] \
|| [ "$os_ver" = "bustersid" ] || [ -z "$os_ver" ]; then
cat 1>&2 <= 10 or Ubuntu >= 20.04.
This version of Ubuntu/Debian is too old and not supported.
EOF
exit 1
fi
[ -f /etc/os-release ] && ubuntu_ver=$(. /etc/os-release && printf '%s' "$VERSION_ID")
}
check_libreswan() {
ipsec_ver=$(/usr/local/sbin/ipsec --version 2>/dev/null)
swan_ver_old=$(printf '%s' "$ipsec_ver" | sed -e 's/.*Libreswan U\?//' -e 's/\( (\|\/K\).*//')
if ! printf '%s' "$ipsec_ver" | grep -qi '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
}
get_swan_ver() {
swan_ver_cur=5.3
base_url="https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0"
swan_ver_url="$base_url/upg-v1-$os_type-$os_ver-swanver"
swan_ver_latest=$(wget -t 2 -T 10 -qO- "$swan_ver_url" | head -n 1)
if printf '%s' "$swan_ver_latest" | grep -Eq '^([3-9]|[1-9][0-9]{1,2})(\.([0-9]|[1-9][0-9]{1,2})){1,2}$'; then
swan_ver_cur="$swan_ver_latest"
fi
[ -z "$SWAN_VER" ] && SWAN_VER="$swan_ver_cur"
}
check_swan_ver() {
if [ "$SWAN_VER" = "4.8" ] || [ "$SWAN_VER" = "4.13" ]; then
exiterr "Libreswan version $SWAN_VER is not supported."
fi
if [ "$SWAN_VER" = "3.32" ] && [ "$os_ver" = "11" ]; then
exiterr "Libreswan 3.32 is not supported on Debian 11."
fi
if [ "$SWAN_VER" != "3.32" ] \
&& { ! printf '%s\n%s' "4.1" "$SWAN_VER" | sort -C -V \
|| ! printf '%s\n%s' "$SWAN_VER" "$swan_ver_cur" | sort -C -V; }; then
cat 1>&2 </dev/null
) || exiterr2
if { [ "$os_type" = "ubuntu" ] && [ -n "$ubuntu_ver" ] \
&& printf '%s\n%s' "24.10" "$ubuntu_ver" | sort -C -V; } \
|| [ "$os_ver" = 13 ]; then
(
set -x
apt-get -yqq install systemd-dev >/dev/null
) || exiterr2
fi
}
get_libreswan() {
bigecho "Downloading Libreswan..."
cd /opt/src || exit 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"
(
set -x
wget -t 3 -T 30 -q -O "$swan_file" "$swan_url1" || wget -t 3 -T 30 -q -O "$swan_file" "$swan_url2"
) || exit 1
/bin/rm -rf "/opt/src/libreswan-$SWAN_VER"
tar xzf "$swan_file" && /bin/rm -f "$swan_file"
}
install_libreswan() {
bigecho "Compiling and installing Libreswan, please wait..."
cd "libreswan-$SWAN_VER" || exit 1
service ipsec stop >/dev/null 2>&1
[ "$SWAN_VER" = "4.1" ] && sed -i 's/ sysv )/ sysvinit )/' programs/setup/setup.in
cat > Makefile.inc.local <<'EOF'
WERROR_CFLAGS=-w -s
USE_DNSSEC=false
USE_DH2=true
EOF
if [ "$SWAN_VER" = "3.32" ]; then
cat >> Makefile.inc.local <<'EOF'
USE_DH31=false
USE_NSS_AVA_COPY=true
USE_NSS_IPSEC_PROFILE=false
USE_GLIBC_KERN_FLIP_HEADERS=true
EOF
else
cat >> Makefile.inc.local <<'EOF'
USE_NSS_KDF=false
FINALNSSDIR=/etc/ipsec.d
NSSDIR=/etc/ipsec.d
EOF
fi
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
(
set -x
make "-j$((NPROCS+1))" -s base >/dev/null 2>&1 && make -s install-base >/dev/null 2>&1
)
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
service ipsec start >/dev/null 2>&1
exiterr "Libreswan $SWAN_VER failed to build."
fi
}
update_ikev2_script() {
bigecho "Updating IKEv2 script..."
cd /opt/src || exit 1
ikev2_url="https://raw.githubusercontent.com/hwdsl2/setup-ipsec-vpn/master/extras/ikev2setup.sh"
(
set -x
wget -t 3 -T 30 -q -O ikev2.sh.new "$ikev2_url"
) || /bin/rm -f ikev2.sh.new
if [ -s ikev2.sh.new ]; then
[ -s ikev2.sh ] && /bin/cp -f ikev2.sh "ikev2.sh.old-$SYS_DT"
/bin/cp -f ikev2.sh.new ikev2.sh && chmod +x ikev2.sh \
&& ln -s /opt/src/ikev2.sh /usr/bin 2>/dev/null
/bin/rm -f ikev2.sh.new
fi
}
update_config() {
bigecho "Updating VPN configuration..."
IKE_NEW=" ike=aes256-sha2;modp2048,aes128-sha2;modp2048,aes256-sha1;modp2048,aes128-sha1;modp2048"
PHASE2_NEW=" phase2alg=aes_gcm-null,aes128-sha1,aes256-sha1,aes256-sha2_512,aes128-sha2,aes256-sha2"
if uname -m | grep -qi '^arm'; then
if ! modprobe -q sha512; then
PHASE2_NEW=" phase2alg=aes_gcm-null,aes128-sha1,aes256-sha1,aes128-sha2,aes256-sha2"
fi
fi
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-$SYS_DT" \
-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
sed -i "/ikev2=never/d" /etc/ipsec.conf
sed -i "/conn shared/a \ ikev2=never" /etc/ipsec.conf
if ! grep -qs "ikev1-policy" /etc/ipsec.conf; then
sed -i "/config setup/a \ ikev1-policy=accept" /etc/ipsec.conf
fi
if grep -qs ike-frag /etc/ipsec.d/ikev2.conf; then
sed -i".old-$SYS_DT" 's/^[[:space:]]\+ike-frag=/ fragmentation=/' /etc/ipsec.d/ikev2.conf
fi
}
restart_ipsec() {
bigecho "Restarting IPsec service..."
mkdir -p /run/pluto
service ipsec restart 2>/dev/null
}
show_setup_complete() {
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=''
# =====================================================
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
exiterr() { echo "Error: $1" >&2; exit 1; }
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"
}
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"
}
check_root() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo sh $0'"
fi
}
check_vz() {
if [ -f /proc/user_beancounters ]; then
exiterr "OpenVZ VPS is not supported."
fi
}
check_lxc() {
# shellcheck disable=SC2154
if [ "$container" = "lxc" ] && [ ! -e /dev/ppp ]; then
cat 1>&2 <<'EOF'
Error: /dev/ppp is missing. LXC containers require configuration.
See: https://github.com/hwdsl2/setup-ipsec-vpn/issues/1014
EOF
exit 1
fi
}
check_os() {
rh_file="/etc/redhat-release"
if [ -f "$rh_file" ]; then
os_type=centos
if grep -q "Red Hat" "$rh_file"; then
os_type=rhel
fi
[ -f /etc/oracle-release ] && os_type=ol
grep -qi rocky "$rh_file" && os_type=rocky
grep -qi alma "$rh_file" && os_type=alma
if grep -q "release 7" "$rh_file"; then
os_ver=7
elif grep -q "release 8" "$rh_file"; then
os_ver=8
grep -qi stream "$rh_file" && os_ver=8s
elif grep -q "release 9" "$rh_file"; then
os_ver=9
grep -qi stream "$rh_file" && os_ver=9s
elif grep -q "release 10" "$rh_file"; then
os_ver=10
grep -qi stream "$rh_file" && os_ver=10s
else
exiterr "This script only supports CentOS/RHEL 7-10."
fi
if [ "$os_type" = "centos" ] \
&& { [ "$os_ver" = 7 ] || [ "$os_ver" = 8 ] || [ "$os_ver" = 8s ]; }; then
exiterr "CentOS Linux $os_ver is EOL and not supported."
fi
elif grep -qs "Amazon Linux release 2 " /etc/system-release; then
os_type=amzn
os_ver=2
elif grep -qs "Amazon Linux release 2023" /etc/system-release; then
exiterr "Amazon Linux 2023 is not supported."
else
os_type=$(lsb_release -si 2>/dev/null)
[ -z "$os_type" ] && [ -f /etc/os-release ] && os_type=$(. /etc/os-release && printf '%s' "$ID")
case $os_type in
[Uu]buntu)
os_type=ubuntu
;;
[Dd]ebian|[Kk]ali|[Rr]aspbian)
os_type=debian
;;
[Aa]lpine)
os_type=alpine
;;
*)
cat 1>&2 <<'EOF'
Error: This script only supports one of the following OS:
Ubuntu, Debian, CentOS/RHEL, Rocky Linux, AlmaLinux,
Oracle Linux, Amazon Linux 2 or Alpine Linux
EOF
exit 1
;;
esac
if [ "$os_type" = "alpine" ]; then
os_ver=$(. /etc/os-release && printf '%s' "$VERSION_ID" | cut -d '.' -f 1,2)
if [ "$os_ver" != "3.22" ] && [ "$os_ver" != "3.23" ]; then
exiterr "This script only supports Alpine Linux 3.22/3.23."
fi
else
os_ver=$(sed 's/\..*//' /etc/debian_version | tr -dc 'A-Za-z0-9')
if [ "$os_ver" = 8 ] || [ "$os_ver" = 9 ] || [ "$os_ver" = "stretchsid" ] \
|| [ "$os_ver" = "bustersid" ] || [ -z "$os_ver" ]; then
cat 1>&2 <= 10 or Ubuntu >= 20.04.
This version of Ubuntu/Debian is too old and not supported.
EOF
exit 1
fi
fi
fi
}
check_iface() {
def_iface=$(route 2>/dev/null | grep -m 1 '^default' | grep -o '[^ ]*$')
if [ "$os_type" != "alpine" ]; then
[ -z "$def_iface" ] && def_iface=$(ip -4 route list 0/0 2>/dev/null | grep -m 1 -Po '(?<=dev )(\S+)')
fi
def_state=$(cat "/sys/class/net/$def_iface/operstate" 2>/dev/null)
check_wl=0
if [ -n "$def_state" ] && [ "$def_state" != "down" ]; then
if [ "$os_type" = "ubuntu" ] || [ "$os_type" = "debian" ]; then
if ! uname -m | grep -qi -e '^arm' -e '^aarch64'; then
check_wl=1
fi
else
check_wl=1
fi
fi
if [ "$check_wl" = 1 ]; then
case $def_iface in
wl*)
exiterr "Wireless interface '$def_iface' detected. DO NOT run this script on your PC or Mac!"
;;
esac
fi
}
check_creds() {
[ -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
return 0
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
}
check_dns() {
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
}
check_server_dns() {
if [ -n "$VPN_DNS_NAME" ] && ! check_dns_name "$VPN_DNS_NAME"; then
exiterr "Invalid DNS name. 'VPN_DNS_NAME' must be a fully qualified domain name (FQDN)."
fi
}
check_client_name() {
if [ -n "$VPN_CLIENT_NAME" ]; then
name_len="$(printf '%s' "$VPN_CLIENT_NAME" | wc -m)"
if [ "$name_len" -gt "64" ] || printf '%s' "$VPN_CLIENT_NAME" | LC_ALL=C grep -q '[^A-Za-z0-9_-]\+' \
|| case $VPN_CLIENT_NAME in -*) true ;; *) false ;; esac; then
exiterr "Invalid client name. Use one word only, no special characters except '-' and '_'."
fi
fi
}
wait_for_apt() {
count=0
apt_lk=/var/lib/apt/lists/lock
pkg_lk=/var/lib/dpkg/lock
while fuser "$apt_lk" "$pkg_lk" >/dev/null 2>&1 \
|| lsof "$apt_lk" >/dev/null 2>&1 || lsof "$pkg_lk" >/dev/null 2>&1; do
[ "$count" = 0 ] && echo "## Waiting for apt to be available..."
[ "$count" -ge 200 ] && exiterr "Could not get apt/dpkg lock."
count=$((count+1))
printf '%s' '.'
sleep 3
done
}
install_pkgs() {
if ! command -v wget >/dev/null 2>&1; then
if [ "$os_type" = "ubuntu" ] || [ "$os_type" = "debian" ]; then
wait_for_apt
export DEBIAN_FRONTEND=noninteractive
(
set -x
apt-get -yqq update || apt-get -yqq update
) || exiterr "'apt-get update' failed."
(
set -x
apt-get -yqq install wget >/dev/null || apt-get -yqq install wget >/dev/null
) || exiterr "'apt-get install wget' failed."
elif [ "$os_type" != "alpine" ]; then
(
set -x
yum -y -q install wget >/dev/null || yum -y -q install wget >/dev/null
) || exiterr "'yum install wget' failed."
fi
fi
if [ "$os_type" = "alpine" ]; then
(
set -x
apk add -U -q bash coreutils grep net-tools sed wget
) || exiterr "'apk add' failed."
fi
}
get_setup_url() {
base_url1="https://raw.githubusercontent.com/hwdsl2/setup-ipsec-vpn/master"
base_url2="https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master"
sh_file="vpnsetup_ubuntu.sh"
if [ "$os_type" = "centos" ] || [ "$os_type" = "rhel" ] || [ "$os_type" = "rocky" ] \
|| [ "$os_type" = "alma" ] || [ "$os_type" = "ol" ]; then
sh_file="vpnsetup_centos.sh"
elif [ "$os_type" = "amzn" ]; then
sh_file="vpnsetup_amzn.sh"
elif [ "$os_type" = "alpine" ]; then
sh_file="vpnsetup_alpine.sh"
fi
setup_url1="$base_url1/$sh_file"
setup_url2="$base_url2/$sh_file"
}
run_setup() {
status=0
if tmpdir=$(mktemp --tmpdir -d vpn.XXXXX 2>/dev/null); then
if ( set -x; wget -t 3 -T 30 -q -O "$tmpdir/vpn.sh" "$setup_url1" \
|| wget -t 3 -T 30 -q -O "$tmpdir/vpn.sh" "$setup_url2" \
|| curl -m 30 -fsL "$setup_url1" -o "$tmpdir/vpn.sh" 2>/dev/null ); then
VPN_IPSEC_PSK="$VPN_IPSEC_PSK" VPN_USER="$VPN_USER" \
VPN_PASSWORD="$VPN_PASSWORD" \
VPN_PUBLIC_IP="$VPN_PUBLIC_IP" VPN_L2TP_NET="$VPN_L2TP_NET" \
VPN_L2TP_LOCAL="$VPN_L2TP_LOCAL" VPN_L2TP_POOL="$VPN_L2TP_POOL" \
VPN_XAUTH_NET="$VPN_XAUTH_NET" VPN_XAUTH_POOL="$VPN_XAUTH_POOL" \
VPN_DNS_SRV1="$VPN_DNS_SRV1" VPN_DNS_SRV2="$VPN_DNS_SRV2" \
VPN_DNS_NAME="$VPN_DNS_NAME" VPN_CLIENT_NAME="$VPN_CLIENT_NAME" \
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
echo "Error: Could not download VPN setup script." >&2
fi
/bin/rm -f "$tmpdir/vpn.sh"
/bin/rmdir "$tmpdir"
else
exiterr "Could not create temporary directory."
fi
}
vpnsetup() {
check_root
check_vz
check_lxc
check_os
check_iface
check_creds
check_dns
check_server_dns
check_client_name
install_pkgs
get_setup_url
run_setup
}
## Defer setup until we have the complete script
vpnsetup "$@"
exit "$status"
================================================
FILE: vpnsetup_alpine.sh
================================================
#!/bin/bash
#
# Script for automatic setup of an IPsec VPN server on Alpine Linux
#
# DO NOT RUN THIS SCRIPT ON YOUR PC OR MAC!
#
# The latest version of this script is available at:
# https://github.com/hwdsl2/setup-ipsec-vpn
#
# 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/
#
# 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=''
# =====================================================
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 "'apk add' failed."; }
conf_bk() { /bin/cp -f "$1" "$1.old-$SYS_DT" 2>/dev/null; }
bigecho() { echo "## $1"; }
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"
}
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"
}
check_root() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo bash $0'"
fi
}
check_vz() {
if [ -f /proc/user_beancounters ]; then
exiterr "OpenVZ VPS is not supported."
fi
}
check_os() {
os_type=$(lsb_release -si 2>/dev/null)
[ -z "$os_type" ] && [ -f /etc/os-release ] && os_type=$(. /etc/os-release && printf '%s' "$ID")
case $os_type in
[Aa]lpine)
os_type=alpine
;;
*)
exiterr "This script only supports Alpine Linux."
;;
esac
os_ver=$(. /etc/os-release && printf '%s' "$VERSION_ID" | cut -d '.' -f 1,2)
if [ "$os_ver" != "3.22" ] && [ "$os_ver" != "3.23" ]; then
exiterr "This script only supports Alpine Linux 3.22/3.23."
fi
}
check_iface() {
def_iface=$(route 2>/dev/null | grep -m 1 '^default' | grep -o '[^ ]*$')
def_state=$(cat "/sys/class/net/$def_iface/operstate" 2>/dev/null)
if [ -n "$def_state" ] && [ "$def_state" != "down" ]; then
if ! uname -m | grep -qi -e '^arm' -e '^aarch64'; then
case $def_iface in
wl*)
exiterr "Wireless interface '$def_iface' detected. DO NOT run this script on your PC or Mac!"
;;
esac
fi
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
}
check_creds() {
[ -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/null | head -c 20)
VPN_USER=vpnuser
VPN_PASSWORD=$(LC_CTYPE=C tr -dc 'A-HJ-NPR-Za-km-z2-9' /dev/null | 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
}
check_dns() {
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
}
check_server_dns() {
if [ -n "$VPN_DNS_NAME" ] && ! check_dns_name "$VPN_DNS_NAME"; then
exiterr "Invalid DNS name. 'VPN_DNS_NAME' must be a fully qualified domain name (FQDN)."
fi
}
check_client_name() {
if [ -n "$VPN_CLIENT_NAME" ]; then
name_len="$(printf '%s' "$VPN_CLIENT_NAME" | wc -m)"
if [ "$name_len" -gt "64" ] || printf '%s' "$VPN_CLIENT_NAME" | LC_ALL=C grep -q '[^A-Za-z0-9_-]\+' \
|| case $VPN_CLIENT_NAME in -*) true ;; *) false ;; esac; then
exiterr "Invalid client name. Use one word only, no special characters except '-' and '_'."
fi
fi
}
check_subnets() {
if [ -s /etc/ipsec.conf ] && grep -qs "hwdsl2 VPN script" /etc/sysctl.conf; then
L2TP_NET=${VPN_L2TP_NET:-'192.168.42.0/24'}
XAUTH_NET=${VPN_XAUTH_NET:-'192.168.43.0/24'}
if ! grep -q "$L2TP_NET" /etc/ipsec.conf \
|| ! grep -q "$XAUTH_NET" /etc/ipsec.conf; then
echo "Error: The custom VPN subnets specified do not match initial install." >&2
echo " See Advanced usage -> Customize VPN subnets for more information." >&2
exit 1
fi
fi
}
start_setup() {
bigecho "VPN setup in progress... Please be patient."
mkdir -p /opt/src
cd /opt/src || exit 1
}
install_setup_pkgs() {
bigecho "Installing packages required for setup..."
(
set -x
apk add -U -q bash bind-tools coreutils openssl wget iptables ip6tables iproute2 sed grep
) || exiterr2
}
get_default_ip() {
def_ip=$(ip -4 route get 1 | sed 's/ uid .*//' | awk '{print $NF;exit}' 2>/dev/null)
if check_ip "$def_ip" \
&& ! printf '%s' "$def_ip" | grep -Eq '^(10|127|172\.(1[6-9]|2[0-9]|3[0-1])|192\.168|169\.254)\.'; then
public_ip="$def_ip"
fi
}
detect_ip() {
public_ip=${VPN_PUBLIC_IP:-''}
check_ip "$public_ip" || get_default_ip
check_ip "$public_ip" && return 0
bigecho "Trying to auto discover IP of this server..."
check_ip "$public_ip" || public_ip=$(dig @resolver1.opendns.com -t A -4 myip.opendns.com +short)
check_ip "$public_ip" || public_ip=$(wget -t 2 -T 10 -qO- http://ipv4.icanhazip.com)
check_ip "$public_ip" || public_ip=$(wget -t 2 -T 10 -qO- http://ip1.dynupdate.no-ip.com)
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" || { echo "Warning: Invalid IPv6 address in 'VPN_PUBLIC_IP6'. Detecting IPv6..." >&2; ip6=""; }
fi
[ -z "$ip6" ] && ip6=$(ip -6 addr 2>/dev/null | awk '/inet6 [23]/ {print $2}' | cut -d'/' -f1 | head -n1)
check_ip6 "$ip6" || ip6=""
}
install_vpn_pkgs() {
bigecho "Installing packages required for the VPN..."
(
set -x
apk add -U -q 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 xl2tpd
) || exiterr2
}
install_fail2ban() {
bigecho "Installing Fail2Ban to protect SSH..."
(
set -x
apk add -U -q fail2ban
)
}
link_scripts() {
cd /opt/src || exit 1
/bin/mv -f ikev2setup.sh ikev2.sh
/bin/mv -f add_vpn_user.sh addvpnuser.sh
/bin/mv -f del_vpn_user.sh delvpnuser.sh
echo "+ ikev2.sh addvpnuser.sh delvpnuser.sh"
for sc in ikev2.sh addvpnuser.sh delvpnuser.sh; do
[ -s "$sc" ] && chmod +x "$sc" && ln -s "/opt/src/$sc" /usr/bin 2>/dev/null
done
}
get_helper_scripts() {
bigecho "Downloading helper scripts..."
base1="https://raw.githubusercontent.com/hwdsl2/setup-ipsec-vpn/master/extras"
base2="https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras"
sc1=ikev2setup.sh
sc2=add_vpn_user.sh
sc3=del_vpn_user.sh
cd /opt/src || exit 1
/bin/rm -f "$sc1" "$sc2" "$sc3"
if wget -t 3 -T 30 -q "$base1/$sc1" "$base1/$sc2" "$base1/$sc3"; then
link_scripts
else
/bin/rm -f "$sc1" "$sc2" "$sc3"
if wget -t 3 -T 30 -q "$base2/$sc1" "$base2/$sc2" "$base2/$sc3"; then
link_scripts
else
echo "Warning: Could not download helper scripts." >&2
/bin/rm -f "$sc1" "$sc2" "$sc3"
fi
fi
}
get_swan_ver() {
SWAN_VER=5.3
base_url="https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0"
swan_ver_url="$base_url/v1-$os_type-$os_ver-swanver"
swan_ver_latest=$(wget -t 2 -T 10 -qO- "$swan_ver_url" | head -n 1)
[ -z "$swan_ver_latest" ] && swan_ver_latest=$(curl -m 10 -fsL "$swan_ver_url" 2>/dev/null | head -n 1)
if printf '%s' "$swan_ver_latest" | grep -Eq '^([3-9]|[1-9][0-9]{1,2})(\.([0-9]|[1-9][0-9]{1,2})){1,2}$'; then
SWAN_VER="$swan_ver_latest"
fi
if [ -n "$VPN_SWAN_VER" ]; then
if ! printf '%s\n%s' "4.15" "$VPN_SWAN_VER" | sort -C -V \
|| ! printf '%s\n%s' "$VPN_SWAN_VER" "$SWAN_VER" | sort -C -V; then
cat 1>&2 </dev/null)
swan_ver_old=$(printf '%s' "$ipsec_ver" | sed -e 's/.*Libreswan U\?//' -e 's/\( (\|\/K\).*//')
ipsec_bin="/usr/local/sbin/ipsec"
if [ -n "$swan_ver_old" ] && printf '%s' "$ipsec_ver" | grep -qi 'libreswan' \
&& [ "$(find "$ipsec_bin" -mmin -10080)" ]; then
check_result=1
return 0
fi
get_swan_ver
if [ -s "$ipsec_bin" ] && [ "$swan_ver_old" = "$SWAN_VER" ]; then
touch "$ipsec_bin"
fi
[ "$swan_ver_old" = "$SWAN_VER" ] && check_result=1
}
get_libreswan() {
if [ "$check_result" = 0 ]; then
bigecho "Downloading Libreswan..."
cd /opt/src || exit 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"
(
set -x
wget -t 3 -T 30 -q -O "$swan_file" "$swan_url1" || wget -t 3 -T 30 -q -O "$swan_file" "$swan_url2"
) || exit 1
/bin/rm -rf "/opt/src/libreswan-$SWAN_VER"
tar xzf "$swan_file" && /bin/rm -f "$swan_file"
else
bigecho "Libreswan $swan_ver_old is already installed, skipping..."
fi
}
install_libreswan() {
if [ "$check_result" = 0 ]; then
bigecho "Compiling and installing Libreswan, please wait..."
cd "libreswan-$SWAN_VER" || exit 1
cat > Makefile.inc.local <<'EOF'
WERROR_CFLAGS=-w -s
USE_DNSSEC=false
USE_DH2=true
FINALNSSDIR=/etc/ipsec.d
NSSDIR=/etc/ipsec.d
EOF
NPROCS=$(grep -c ^processor /proc/cpuinfo)
[ -z "$NPROCS" ] && NPROCS=1
(
set -x
make "-j$((NPROCS+1))" -s base >/dev/null 2>&1 && make -s install-base >/dev/null 2>&1
)
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" \
|| [ ! -d /etc/ipsec.d ]; then
exiterr "Libreswan $SWAN_VER failed to build."
fi
fi
}
create_vpn_config() {
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"
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/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 <> /etc/sysctl.conf <<'EOF'
net.ipv6.conf.all.forwarding = 1
EOF
fi
fi
}
update_iptables() {
bigecho "Updating IPTables rules..."
IPT_FILE=/etc/iptables.rules
ipt_flag=0
if ! grep -qs "hwdsl2 VPN script" "$IPT_FILE"; then
ipt_flag=1
fi
ipi='iptables -I INPUT'
ipf='iptables -I FORWARD'
ipp='iptables -t nat -I POSTROUTING'
res='RELATED,ESTABLISHED'
if [ "$ipt_flag" = 1 ]; then
service fail2ban stop >/dev/null 2>&1
iptables-save > "$IPT_FILE.old-$SYS_DT"
$ipi 1 -p udp --dport 1701 -m policy --dir in --pol none -j DROP
$ipi 2 -m conntrack --ctstate INVALID -j DROP
$ipi 3 -m conntrack --ctstate "$res" -j ACCEPT
$ipi 4 -p udp -m multiport --dports 500,4500 -j ACCEPT
$ipi 5 -p udp --dport 1701 -m policy --dir in --pol ipsec -j ACCEPT
$ipi 6 -p udp --dport 1701 -j DROP
$ipf 1 -m conntrack --ctstate INVALID -j DROP
$ipf 2 -i "$NET_IFACE" -o ppp+ -m conntrack --ctstate "$res" -j ACCEPT
$ipf 3 -i ppp+ -o "$NET_IFACE" -j ACCEPT
$ipf 4 -i ppp+ -o ppp+ -j ACCEPT
$ipf 5 -i "$NET_IFACE" -d "$XAUTH_NET" -m conntrack --ctstate "$res" -j ACCEPT
$ipf 6 -s "$XAUTH_NET" -o "$NET_IFACE" -j ACCEPT
$ipf 7 -s "$XAUTH_NET" -o ppp+ -j ACCEPT
iptables -A FORWARD -j DROP
$ipp -s "$XAUTH_NET" -o "$NET_IFACE" -m policy --dir out --pol none -j MASQUERADE
$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
}
enable_on_boot() {
bigecho "Enabling services on boot..."
mkdir -p /etc/network/if-pre-up.d
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
sed -i '1c\#!/sbin/openrc-run' /etc/init.d/ipsec
for svc in fail2ban ipsec xl2tpd; do
rc-update add "$svc" default >/dev/null 2>&1
done
}
start_services() {
bigecho "Starting services..."
sysctl -e -q -p
chmod 600 /etc/ipsec.secrets* /etc/ppp/chap-secrets* /etc/ipsec.d/passwd*
mkdir -p /run/pluto
service fail2ban restart >/dev/null 2>&1
service ipsec restart >/dev/null 2>&1
service xl2tpd restart >/dev/null 2>&1
mkdir -p /etc/crontabs
cron_cmd="rc-service -c ipsec zap start"
if ! grep -qs "$cron_cmd" /etc/crontabs/root; then
cat >> /etc/crontabs/root <
#
# 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=''
# =====================================================
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 "## $1"; }
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"
}
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"
}
check_root() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo bash $0'"
fi
}
check_os() {
if ! grep -qs "Amazon Linux release 2 " /etc/system-release; then
if grep -qs "Amazon Linux release 2023" /etc/system-release; then
exiterr "Amazon Linux 2023 is not supported."
else
exiterr "This script only supports Amazon Linux 2."
fi
fi
}
check_iface() {
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
}
check_creds() {
[ -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/null | head -c 20)
VPN_USER=vpnuser
VPN_PASSWORD=$(LC_CTYPE=C tr -dc 'A-HJ-NPR-Za-km-z2-9' /dev/null | 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
}
check_dns() {
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
}
check_server_dns() {
if [ -n "$VPN_DNS_NAME" ] && ! check_dns_name "$VPN_DNS_NAME"; then
exiterr "Invalid DNS name. 'VPN_DNS_NAME' must be a fully qualified domain name (FQDN)."
fi
}
check_client_name() {
if [ -n "$VPN_CLIENT_NAME" ]; then
name_len="$(printf '%s' "$VPN_CLIENT_NAME" | wc -m)"
if [ "$name_len" -gt "64" ] || printf '%s' "$VPN_CLIENT_NAME" | LC_ALL=C grep -q '[^A-Za-z0-9_-]\+' \
|| case $VPN_CLIENT_NAME in -*) true ;; *) false ;; esac; then
exiterr "Invalid client name. Use one word only, no special characters except '-' and '_'."
fi
fi
}
check_subnets() {
if [ -s /etc/ipsec.conf ] && grep -qs "hwdsl2 VPN script" /etc/sysctl.conf; then
L2TP_NET=${VPN_L2TP_NET:-'192.168.42.0/24'}
XAUTH_NET=${VPN_XAUTH_NET:-'192.168.43.0/24'}
if ! grep -q "$L2TP_NET" /etc/ipsec.conf \
|| ! grep -q "$XAUTH_NET" /etc/ipsec.conf; then
echo "Error: The custom VPN subnets specified do not match initial install." >&2
echo " See Advanced usage -> Customize VPN subnets for more information." >&2
exit 1
fi
fi
}
start_setup() {
bigecho "VPN setup in progress... Please be patient."
mkdir -p /opt/src
cd /opt/src || exit 1
}
install_setup_pkgs() {
bigecho "Installing packages required for setup..."
(
set -x
yum -y -q install wget bind-utils openssl tar \
iptables iproute gawk grep sed net-tools >/dev/null
) || exiterr2
}
get_default_ip() {
def_ip=$(ip -4 route get 1 | sed 's/ uid .*//' | awk '{print $NF;exit}' 2>/dev/null)
if check_ip "$def_ip" \
&& ! printf '%s' "$def_ip" | grep -Eq '^(10|127|172\.(1[6-9]|2[0-9]|3[0-1])|192\.168|169\.254)\.'; then
public_ip="$def_ip"
fi
}
detect_ip() {
public_ip=${VPN_PUBLIC_IP:-''}
check_ip "$public_ip" || get_default_ip
check_ip "$public_ip" && return 0
bigecho "Trying to auto discover IP of this server..."
check_ip "$public_ip" || public_ip=$(dig @resolver1.opendns.com -t A -4 myip.opendns.com +short)
check_ip "$public_ip" || public_ip=$(wget -t 2 -T 10 -qO- http://ipv4.icanhazip.com)
check_ip "$public_ip" || public_ip=$(wget -t 2 -T 10 -qO- http://ip1.dynupdate.no-ip.com)
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" || { echo "Warning: Invalid IPv6 address in 'VPN_PUBLIC_IP6'. Detecting IPv6..." >&2; ip6=""; }
fi
[ -z "$ip6" ] && ip6=$(ip -6 addr 2>/dev/null | awk '/inet6 [23]/ {print $2}' | cut -d'/' -f1 | head -n1)
check_ip6 "$ip6" || ip6=""
}
add_epel_repo() {
bigecho "Adding the EPEL repository..."
(
set -x
amazon-linux-extras install epel -y >/dev/null
) || exiterr2
}
install_vpn_pkgs_1() {
bigecho "Installing packages required for the VPN..."
(
set -x
yum -y -q install nss-devel nspr-devel pkgconfig pam-devel \
libcap-ng-devel libselinux-devel curl-devel nss-tools \
flex bison gcc make util-linux ppp \
systemd-devel iptables-services \
libevent-devel fipscheck-devel >/dev/null
) || exiterr2
}
install_vpn_pkgs_2() {
(
set -x
yum --enablerepo=epel -y -q install xl2tpd >/dev/null 2>&1
) || exiterr2
}
create_f2b_config() {
F2B_FILE=/etc/fail2ban/jail.local
if [ ! -f "$F2B_FILE" ]; then
bigecho "Creating basic Fail2Ban rules..."
cat > "$F2B_FILE" <<'EOF'
[ssh-iptables]
enabled = true
filter = sshd
logpath = /var/log/secure
action = iptables[name=SSH, port=ssh, protocol=tcp]
EOF
fi
}
install_fail2ban() {
bigecho "Installing Fail2Ban to protect SSH..."
(
set -x
yum --enablerepo=epel -y -q install fail2ban >/dev/null
) && create_f2b_config
}
link_scripts() {
cd /opt/src || exit 1
/bin/mv -f ikev2setup.sh ikev2.sh
/bin/mv -f add_vpn_user.sh addvpnuser.sh
/bin/mv -f del_vpn_user.sh delvpnuser.sh
echo "+ ikev2.sh addvpnuser.sh delvpnuser.sh"
for sc in ikev2.sh addvpnuser.sh delvpnuser.sh; do
[ -s "$sc" ] && chmod +x "$sc" && ln -s "/opt/src/$sc" /usr/bin 2>/dev/null
done
}
get_helper_scripts() {
bigecho "Downloading helper scripts..."
base1="https://raw.githubusercontent.com/hwdsl2/setup-ipsec-vpn/master/extras"
base2="https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras"
sc1=ikev2setup.sh
sc2=add_vpn_user.sh
sc3=del_vpn_user.sh
cd /opt/src || exit 1
/bin/rm -f "$sc1" "$sc2" "$sc3"
if wget -t 3 -T 30 -q "$base1/$sc1" "$base1/$sc2" "$base1/$sc3"; then
link_scripts
else
/bin/rm -f "$sc1" "$sc2" "$sc3"
if wget -t 3 -T 30 -q "$base2/$sc1" "$base2/$sc2" "$base2/$sc3"; then
link_scripts
else
echo "Warning: Could not download helper scripts." >&2
/bin/rm -f "$sc1" "$sc2" "$sc3"
fi
fi
}
get_swan_ver() {
SWAN_VER=5.3
base_url="https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0"
swan_ver_url="$base_url/v1-amzn-2-swanver"
swan_ver_latest=$(wget -t 2 -T 10 -qO- "$swan_ver_url" | head -n 1)
[ -z "$swan_ver_latest" ] && swan_ver_latest=$(curl -m 10 -fsL "$swan_ver_url" 2>/dev/null | head -n 1)
if printf '%s' "$swan_ver_latest" | grep -Eq '^([3-9]|[1-9][0-9]{1,2})(\.([0-9]|[1-9][0-9]{1,2})){1,2}$'; then
SWAN_VER="$swan_ver_latest"
fi
if [ -n "$VPN_SWAN_VER" ]; then
if ! printf '%s\n%s' "4.15" "$VPN_SWAN_VER" | sort -C -V \
|| ! printf '%s\n%s' "$VPN_SWAN_VER" "$SWAN_VER" | sort -C -V; then
cat 1>&2 </dev/null)
swan_ver_old=$(printf '%s' "$ipsec_ver" | sed -e 's/.*Libreswan U\?//' -e 's/\( (\|\/K\).*//')
ipsec_bin="/usr/local/sbin/ipsec"
if [ -n "$swan_ver_old" ] && printf '%s' "$ipsec_ver" | grep -qi 'libreswan' \
&& [ "$(find "$ipsec_bin" -mmin -10080)" ]; then
check_result=1
return 0
fi
get_swan_ver
if [ -s "$ipsec_bin" ] && [ "$swan_ver_old" = "$SWAN_VER" ]; then
touch "$ipsec_bin"
fi
[ "$swan_ver_old" = "$SWAN_VER" ] && check_result=1
}
get_libreswan() {
if [ "$check_result" = 0 ]; then
bigecho "Downloading Libreswan..."
cd /opt/src || exit 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"
(
set -x
wget -t 3 -T 30 -q -O "$swan_file" "$swan_url1" || wget -t 3 -T 30 -q -O "$swan_file" "$swan_url2"
) || exit 1
/bin/rm -rf "/opt/src/libreswan-$SWAN_VER"
tar xzf "$swan_file" && /bin/rm -f "$swan_file"
else
bigecho "Libreswan $swan_ver_old is already installed, skipping..."
fi
}
install_libreswan() {
if [ "$check_result" = 0 ]; then
bigecho "Compiling and installing Libreswan, please wait..."
cd "libreswan-$SWAN_VER" || exit 1
cat > Makefile.inc.local <<'EOF'
WERROR_CFLAGS=-w -s
USE_DNSSEC=false
USE_DH2=true
USE_NSS_KDF=false
USE_LINUX_AUDIT=false
USE_SECCOMP=false
FINALNSSDIR=/etc/ipsec.d
NSSDIR=/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
(
set -x
make "-j$((NPROCS+1))" -s base >/dev/null 2>&1 && make -s install-base >/dev/null 2>&1
)
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" \
|| [ ! -d /etc/ipsec.d ]; then
exiterr "Libreswan $SWAN_VER failed to build."
fi
fi
}
create_vpn_config() {
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"
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/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 <> /etc/sysctl.conf <<'EOF'
net.ipv6.conf.all.forwarding = 1
EOF
fi
fi
}
update_iptables() {
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
ipi='iptables -I INPUT'
ipf='iptables -I FORWARD'
ipp='iptables -t nat -I POSTROUTING'
res='RELATED,ESTABLISHED'
if [ "$ipt_flag" = 1 ]; then
service fail2ban stop >/dev/null 2>&1
iptables-save > "$IPT_FILE.old-$SYS_DT"
$ipi 1 -p udp --dport 1701 -m policy --dir in --pol none -j DROP
$ipi 2 -m conntrack --ctstate INVALID -j DROP
$ipi 3 -m conntrack --ctstate "$res" -j ACCEPT
$ipi 4 -p udp -m multiport --dports 500,4500 -j ACCEPT
$ipi 5 -p udp --dport 1701 -m policy --dir in --pol ipsec -j ACCEPT
$ipi 6 -p udp --dport 1701 -j DROP
$ipf 1 -m conntrack --ctstate INVALID -j DROP
$ipf 2 -i "$NET_IFACE" -o ppp+ -m conntrack --ctstate "$res" -j ACCEPT
$ipf 3 -i ppp+ -o "$NET_IFACE" -j ACCEPT
$ipf 4 -i ppp+ -o ppp+ -j ACCEPT
$ipf 5 -i "$NET_IFACE" -d "$XAUTH_NET" -m conntrack --ctstate "$res" -j ACCEPT
$ipf 6 -s "$XAUTH_NET" -o "$NET_IFACE" -j ACCEPT
$ipf 7 -s "$XAUTH_NET" -o ppp+ -j ACCEPT
iptables -A FORWARD -j DROP
$ipp -s "$XAUTH_NET" -o "$NET_IFACE" -m policy --dir out --pol none -j MASQUERADE
$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
}
enable_on_boot() {
bigecho "Enabling services on boot..."
systemctl --now mask firewalld 2>/dev/null
systemctl enable iptables 2>/dev/null
systemctl enable 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
ip6_fwd_rc=""
[ -n "$ip6" ] && ip6_fwd_rc='
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding'
cat >> /etc/rc.local < /proc/sys/net/ipv4/ip_forward${ip6_fwd_rc})&
EOF
fi
}
start_services() {
bigecho "Starting services..."
sysctl -e -q -p
chmod +x /etc/rc.local
chmod 600 /etc/ipsec.secrets* /etc/ppp/chap-secrets* /etc/ipsec.d/passwd*
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
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
}
show_vpn_info() {
cat <
# Based on the work of Thomas Sarlandie (Copyright 2012)
#
# 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=''
# =====================================================
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 "## $1"; }
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"
}
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"
}
check_root() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo bash $0'"
fi
}
check_vz() {
if [ -f /proc/user_beancounters ]; then
exiterr "OpenVZ VPS is not supported."
fi
}
check_lxc() {
# shellcheck disable=SC2154
if [ "$container" = "lxc" ] && [ ! -e /dev/ppp ]; then
cat 1>&2 <<'EOF'
Error: /dev/ppp is missing. LXC containers require configuration.
See: https://github.com/hwdsl2/setup-ipsec-vpn/issues/1014
EOF
exit 1
fi
}
check_os() {
rh_file="/etc/redhat-release"
if [ -f "$rh_file" ]; then
os_type=centos
if grep -q "Red Hat" "$rh_file"; then
os_type=rhel
fi
[ -f /etc/oracle-release ] && os_type=ol
grep -qi rocky "$rh_file" && os_type=rocky
grep -qi alma "$rh_file" && os_type=alma
if grep -q "release 7" "$rh_file"; then
os_ver=7
elif grep -q "release 8" "$rh_file"; then
os_ver=8
grep -qi stream "$rh_file" && os_ver=8s
elif grep -q "release 9" "$rh_file"; then
os_ver=9
grep -qi stream "$rh_file" && os_ver=9s
elif grep -q "release 10" "$rh_file"; then
os_ver=10
grep -qi stream "$rh_file" && os_ver=10s
else
exiterr "This script only supports CentOS/RHEL 7-10."
fi
if [ "$os_type" = "centos" ] \
&& { [ "$os_ver" = 7 ] || [ "$os_ver" = 8 ] || [ "$os_ver" = 8s ]; }; then
exiterr "CentOS Linux $os_ver is EOL and not supported."
fi
else
cat 1>&2 <<'EOF'
Error: This script only supports one of the following OS:
CentOS/RHEL, Rocky Linux, AlmaLinux or Oracle Linux
EOF
exit 1
fi
}
check_iface() {
if ! command -v route >/dev/null 2>&1 && ! command -v ip >/dev/null 2>&1; then
(
set -x
yum -y -q install iproute >/dev/null || yum -y -q install iproute >/dev/null
)
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
}
check_creds() {
[ -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/null | head -c 20)
VPN_USER=vpnuser
VPN_PASSWORD=$(LC_CTYPE=C tr -dc 'A-HJ-NPR-Za-km-z2-9' /dev/null | 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
}
check_dns() {
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
}
check_server_dns() {
if [ -n "$VPN_DNS_NAME" ] && ! check_dns_name "$VPN_DNS_NAME"; then
exiterr "Invalid DNS name. 'VPN_DNS_NAME' must be a fully qualified domain name (FQDN)."
fi
}
check_client_name() {
if [ -n "$VPN_CLIENT_NAME" ]; then
name_len="$(printf '%s' "$VPN_CLIENT_NAME" | wc -m)"
if [ "$name_len" -gt "64" ] || printf '%s' "$VPN_CLIENT_NAME" | LC_ALL=C grep -q '[^A-Za-z0-9_-]\+' \
|| case $VPN_CLIENT_NAME in -*) true ;; *) false ;; esac; then
exiterr "Invalid client name. Use one word only, no special characters except '-' and '_'."
fi
fi
}
check_subnets() {
if [ -s /etc/ipsec.conf ] && grep -qs "hwdsl2 VPN script" /etc/sysctl.conf; then
L2TP_NET=${VPN_L2TP_NET:-'192.168.42.0/24'}
XAUTH_NET=${VPN_XAUTH_NET:-'192.168.43.0/24'}
if ! grep -q "$L2TP_NET" /etc/ipsec.conf \
|| ! grep -q "$XAUTH_NET" /etc/ipsec.conf; then
echo "Error: The custom VPN subnets specified do not match initial install." >&2
echo " See Advanced usage -> Customize VPN subnets for more information." >&2
exit 1
fi
fi
}
start_setup() {
bigecho "VPN setup in progress... Please be patient."
mkdir -p /opt/src
cd /opt/src || exit 1
}
install_setup_pkgs() {
bigecho "Installing packages required for setup..."
(
set -x
yum -y -q install wget bind-utils openssl tar \
iptables iproute gawk grep sed net-tools >/dev/null \
|| yum -y -q install wget bind-utils openssl tar \
iptables iproute gawk grep sed net-tools >/dev/null
) || exiterr2
}
get_default_ip() {
def_ip=$(ip -4 route get 1 | sed 's/ uid .*//' | awk '{print $NF;exit}' 2>/dev/null)
if check_ip "$def_ip" \
&& ! printf '%s' "$def_ip" | grep -Eq '^(10|127|172\.(1[6-9]|2[0-9]|3[0-1])|192\.168|169\.254)\.'; then
public_ip="$def_ip"
fi
}
detect_ip() {
public_ip=${VPN_PUBLIC_IP:-''}
check_ip "$public_ip" || get_default_ip
check_ip "$public_ip" && return 0
bigecho "Trying to auto discover IP of this server..."
check_ip "$public_ip" || public_ip=$(dig @resolver1.opendns.com -t A -4 myip.opendns.com +short)
check_ip "$public_ip" || public_ip=$(wget -t 2 -T 10 -qO- http://ipv4.icanhazip.com)
check_ip "$public_ip" || public_ip=$(wget -t 2 -T 10 -qO- http://ip1.dynupdate.no-ip.com)
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" || { echo "Warning: Invalid IPv6 address in 'VPN_PUBLIC_IP6'. Detecting IPv6..." >&2; ip6=""; }
fi
[ -z "$ip6" ] && ip6=$(ip -6 addr 2>/dev/null | awk '/inet6 [23]/ {print $2}' | cut -d'/' -f1 | head -n1)
check_ip6 "$ip6" || ip6=""
}
add_epel_repo() {
bigecho "Adding the EPEL repository..."
epel_url="https://dl.fedoraproject.org/pub/epel/epel-release-latest-$(rpm -E '%{rhel}').noarch.rpm"
(
set -x
yum -y -q install epel-release >/dev/null 2>&1 || yum -y -q install "$epel_url" >/dev/null
) || exiterr2
}
install_vpn_pkgs_1() {
bigecho "Installing packages required for the VPN..."
erp="--enablerepo"
rp1="$erp=epel"
rp2="$erp=*server-*optional*"
rp3="$erp=*releases-optional*"
if [ "$os_type" = "ol" ]; then
if [ "$os_ver" = 9 ]; then
rp1="$erp=ol9_developer_EPEL"
elif [ "$os_ver" = 8 ]; then
rp1="$erp=ol8_developer_EPEL"
else
rp3="$erp=ol7_optional_latest"
fi
fi
(
set -x
yum -y -q install nss-devel nspr-devel pkgconfig pam-devel \
libcap-ng-devel libselinux-devel curl-devel nss-tools \
flex bison gcc make util-linux ppp >/dev/null
) || exiterr2
}
install_vpn_pkgs_2() {
(
set -x
yum "$rp1" -y -q install xl2tpd >/dev/null 2>&1
) || exiterr2
}
install_vpn_pkgs_3() {
use_nft=0
p1=systemd-devel
p2=libevent-devel
p3=fipscheck-devel
p4=iptables-services
if [ "$os_ver" = 7 ]; then
(
set -x
yum "$rp2" "$rp3" -y -q install $p1 $p2 $p3 $p4 >/dev/null
) || exiterr2
else
(
set -x
yum -y -q install $p1 $p2 >/dev/null
) || exiterr2
if [ "$os_ver" = 9 ] || [ "$os_ver" = 9s ] \
|| [ "$os_ver" = 10 ] || [ "$os_ver" = 10s ] \
|| systemctl is-active --quiet firewalld \
|| systemctl is-active --quiet nftables \
|| grep -qs "hwdsl2 VPN script" /etc/sysconfig/nftables.conf; then
use_nft=1
p4=nftables
fi
(
set -x
yum -y -q install $p4 >/dev/null
) || exiterr2
fi
}
create_f2b_config() {
F2B_FILE=/etc/fail2ban/jail.local
if [ ! -f "$F2B_FILE" ]; then
bigecho "Creating basic Fail2Ban rules..."
cat > "$F2B_FILE" <<'EOF'
[ssh-iptables]
enabled = true
filter = sshd
logpath = /var/log/secure
EOF
if [ "$use_nft" = 1 ]; then
cat >> "$F2B_FILE" <<'EOF'
port = ssh
banaction = nftables-multiport[blocktype=drop]
EOF
else
cat >> "$F2B_FILE" <<'EOF'
action = iptables[name=SSH, port=ssh, protocol=tcp]
EOF
fi
fi
}
install_fail2ban() {
bigecho "Installing Fail2Ban to protect SSH..."
(
set -x
yum "$rp1" -y -q install fail2ban >/dev/null
) && create_f2b_config
}
link_scripts() {
cd /opt/src || exit 1
/bin/mv -f ikev2setup.sh ikev2.sh
/bin/mv -f add_vpn_user.sh addvpnuser.sh
/bin/mv -f del_vpn_user.sh delvpnuser.sh
echo "+ ikev2.sh addvpnuser.sh delvpnuser.sh"
for sc in ikev2.sh addvpnuser.sh delvpnuser.sh; do
[ -s "$sc" ] && chmod +x "$sc" && ln -s "/opt/src/$sc" /usr/bin 2>/dev/null
done
}
get_helper_scripts() {
bigecho "Downloading helper scripts..."
base1="https://raw.githubusercontent.com/hwdsl2/setup-ipsec-vpn/master/extras"
base2="https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras"
sc1=ikev2setup.sh
sc2=add_vpn_user.sh
sc3=del_vpn_user.sh
cd /opt/src || exit 1
/bin/rm -f "$sc1" "$sc2" "$sc3"
if wget -t 3 -T 30 -q "$base1/$sc1" "$base1/$sc2" "$base1/$sc3"; then
link_scripts
else
/bin/rm -f "$sc1" "$sc2" "$sc3"
if wget -t 3 -T 30 -q "$base2/$sc1" "$base2/$sc2" "$base2/$sc3"; then
link_scripts
else
echo "Warning: Could not download helper scripts." >&2
/bin/rm -f "$sc1" "$sc2" "$sc3"
fi
fi
}
get_swan_ver() {
SWAN_VER=5.3
base_url="https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0"
swan_ver_url="$base_url/v1-$os_type-$os_ver-swanver"
swan_ver_latest=$(wget -t 2 -T 10 -qO- "$swan_ver_url" | head -n 1)
[ -z "$swan_ver_latest" ] && swan_ver_latest=$(curl -m 10 -fsL "$swan_ver_url" 2>/dev/null | head -n 1)
if printf '%s' "$swan_ver_latest" | grep -Eq '^([3-9]|[1-9][0-9]{1,2})(\.([0-9]|[1-9][0-9]{1,2})){1,2}$'; then
SWAN_VER="$swan_ver_latest"
fi
if [ -n "$VPN_SWAN_VER" ]; then
if ! printf '%s\n%s' "4.15" "$VPN_SWAN_VER" | sort -C -V \
|| ! printf '%s\n%s' "$VPN_SWAN_VER" "$SWAN_VER" | sort -C -V; then
cat 1>&2 </dev/null)
swan_ver_old=$(printf '%s' "$ipsec_ver" | sed -e 's/.*Libreswan U\?//' -e 's/\( (\|\/K\).*//')
ipsec_bin="/usr/local/sbin/ipsec"
if [ -n "$swan_ver_old" ] && printf '%s' "$ipsec_ver" | grep -qi 'libreswan' \
&& [ "$(find "$ipsec_bin" -mmin -10080)" ]; then
check_result=1
return 0
fi
get_swan_ver
if [ -s "$ipsec_bin" ] && [ "$swan_ver_old" = "$SWAN_VER" ]; then
touch "$ipsec_bin"
fi
[ "$swan_ver_old" = "$SWAN_VER" ] && check_result=1
}
get_libreswan() {
if [ "$check_result" = 0 ]; then
bigecho "Downloading Libreswan..."
cd /opt/src || exit 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"
(
set -x
wget -t 3 -T 30 -q -O "$swan_file" "$swan_url1" || wget -t 3 -T 30 -q -O "$swan_file" "$swan_url2"
) || exit 1
/bin/rm -rf "/opt/src/libreswan-$SWAN_VER"
tar xzf "$swan_file" && /bin/rm -f "$swan_file"
else
bigecho "Libreswan $swan_ver_old is already installed, skipping..."
fi
}
install_libreswan() {
if [ "$check_result" = 0 ]; then
bigecho "Compiling and installing Libreswan, please wait..."
cd "libreswan-$SWAN_VER" || exit 1
cat > Makefile.inc.local <<'EOF'
WERROR_CFLAGS=-w -s
USE_DNSSEC=false
USE_DH2=true
USE_NSS_KDF=false
USE_LINUX_AUDIT=false
USE_SECCOMP=false
FINALNSSDIR=/etc/ipsec.d
NSSDIR=/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
(
set -x
make "-j$((NPROCS+1))" -s base >/dev/null 2>&1 && make -s install-base >/dev/null 2>&1
)
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" \
|| [ ! -d /etc/ipsec.d ]; then
exiterr "Libreswan $SWAN_VER failed to build."
fi
fi
}
create_vpn_config() {
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"
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/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 <> /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
}
update_iptables() {
bigecho "Updating IPTables rules..."
IPT_FILE=/etc/sysconfig/iptables
[ "$use_nft" = 1 ] && IPT_FILE=/etc/sysconfig/nftables.conf
ipt_flag=0
if ! grep -qs "hwdsl2 VPN script" "$IPT_FILE"; then
ipt_flag=1
fi
ipi='iptables -I INPUT'
ipf='iptables -I FORWARD'
ipp='iptables -t nat -I POSTROUTING'
res='RELATED,ESTABLISHED'
nff='nft insert rule inet firewalld'
nfn='nft insert rule inet nftables_svc'
if [ "$ipt_flag" = 1 ]; then
service fail2ban stop >/dev/null 2>&1
if [ "$use_nft" = 1 ]; then
fd_conf=/etc/firewalld/firewalld.conf
if grep -qs '^NftablesTableOwner=yes' "$fd_conf"; then
sed -i '/NftablesTableOwner/s/yes/no/' "$fd_conf"
firewall-cmd --reload >/dev/null 2>&1
fi
nft list ruleset > "$IPT_FILE.old-$SYS_DT"
chmod 600 "$IPT_FILE.old-$SYS_DT"
else
iptables-save > "$IPT_FILE.old-$SYS_DT"
fi
$ipi 1 -p udp --dport 1701 -m policy --dir in --pol none -j DROP
$ipi 2 -m conntrack --ctstate INVALID -j DROP
$ipi 3 -m conntrack --ctstate "$res" -j ACCEPT
$ipi 4 -p udp -m multiport --dports 500,4500 -j ACCEPT
$ipi 5 -p udp --dport 1701 -m policy --dir in --pol ipsec -j ACCEPT
$ipi 6 -p udp --dport 1701 -j DROP
$ipf 1 -m conntrack --ctstate INVALID -j DROP
$ipf 2 -i "$NET_IFACE" -o ppp+ -m conntrack --ctstate "$res" -j ACCEPT
$ipf 3 -i ppp+ -o "$NET_IFACE" -j ACCEPT
$ipf 4 -i ppp+ -o ppp+ -j ACCEPT
$ipf 5 -i "$NET_IFACE" -d "$XAUTH_NET" -m conntrack --ctstate "$res" -j ACCEPT
$ipf 6 -s "$XAUTH_NET" -o "$NET_IFACE" -j ACCEPT
$ipf 7 -s "$XAUTH_NET" -o ppp+ -j ACCEPT
if [ "$use_nft" != 1 ]; then
iptables -A FORWARD -j DROP
fi
if [ "$use_nft" = 1 ]; then
$ipp -s "$XAUTH_NET" -o "$NET_IFACE" ! -d "$XAUTH_NET" -j MASQUERADE
else
$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
$nff filter_INPUT udp dport "$vport" accept 2>/dev/null
$nfn allow udp dport "$vport" accept 2>/dev/null
done
for vnet in "$L2TP_NET" "$XAUTH_NET"; do
for vdir in saddr daddr; do
$nff filter_FORWARD ip "$vdir" "$vnet" accept 2>/dev/null
$nfn FORWARD ip "$vdir" "$vnet" accept 2>/dev/null
done
done
echo "flush ruleset" >> "$IPT_FILE"
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
}
fix_nss_config() {
nss_conf="/etc/crypto-policies/back-ends/nss.config"
if [ -s "$nss_conf" ]; then
if ! grep -q ":SHA1:" "$nss_conf" \
&& ! grep -q " allow=SHA1:" "$nss_conf"; then
sed -i "/ALL allow=/s/ allow=/ allow=SHA1:/" "$nss_conf"
fi
fi
}
apply_gcp_mtu_fix() {
if dmidecode -s system-product-name 2>/dev/null | grep -qi 'Google Compute Engine' \
&& ifconfig 2>/dev/null | grep "$NET_IFACE" | head -n 1 | grep -qi 'mtu 1460'; then
bigecho "Applying fix for MTU size..."
ifconfig "$NET_IFACE" mtu 1500
dh_file="/etc/dhcp/dhclient.conf"
if grep -qs "send host-name" "$dh_file" \
&& ! grep -qs "interface-mtu 1500" "$dh_file"; then
sed -i".old-$SYS_DT" \
"/send host-name/a \interface \"$NET_IFACE\" {\ndefault interface-mtu 1500;\nsupersede interface-mtu 1500;\n}" \
"$dh_file"
fi
fi
}
enable_on_boot() {
bigecho "Enabling services on boot..."
systemctl --now mask firewalld 2>/dev/null
if [ "$use_nft" = 1 ]; then
systemctl enable nftables 2>/dev/null
systemctl enable fail2ban 2>/dev/null
else
systemctl enable iptables 2>/dev/null
systemctl enable fail2ban 2>/dev/null
fi
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
ip6_fwd_rc=""
[ -n "$ip6" ] && ip6_fwd_rc='
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding'
cat >> /etc/rc.local < /proc/sys/net/ipv4/ip_forward${ip6_fwd_rc})&
EOF
fi
}
start_services() {
bigecho "Starting services..."
sysctl -e -q -p
chmod +x /etc/rc.local
chmod 600 /etc/ipsec.secrets* /etc/ppp/chap-secrets* /etc/ipsec.d/passwd*
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
if [ "$use_nft" = 1 ]; then
if ! nft -c -f "$IPT_FILE" >/dev/null 2>&1; then
sed -i '/ip6 saddr fddd:\(2c4\|1194\):/s/xt target "MASQUERADE"/masquerade/' "$IPT_FILE"
fi
nft -f "$IPT_FILE"
else
iptables-restore < "$IPT_FILE"
fi
# 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
}
show_vpn_info() {
cat <
# Based on the work of Thomas Sarlandie (Copyright 2012)
#
# 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=''
# =====================================================
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 "'apt-get install' failed."; }
conf_bk() { /bin/cp -f "$1" "$1.old-$SYS_DT" 2>/dev/null; }
bigecho() { echo "## $1"; }
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"
}
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"
}
check_root() {
if [ "$(id -u)" != 0 ]; then
exiterr "Script must be run as root. Try 'sudo bash $0'"
fi
}
check_vz() {
if [ -f /proc/user_beancounters ]; then
exiterr "OpenVZ VPS is not supported."
fi
}
check_lxc() {
# shellcheck disable=SC2154
if [ "$container" = "lxc" ] && [ ! -e /dev/ppp ]; then
cat 1>&2 <<'EOF'
Error: /dev/ppp is missing. LXC containers require configuration.
See: https://github.com/hwdsl2/setup-ipsec-vpn/issues/1014
EOF
exit 1
fi
}
check_os() {
os_type=$(lsb_release -si 2>/dev/null)
[ -z "$os_type" ] && [ -f /etc/os-release ] && os_type=$(. /etc/os-release && printf '%s' "$ID")
case $os_type in
[Uu]buntu)
os_type=ubuntu
;;
[Dd]ebian|[Kk]ali)
os_type=debian
;;
[Rr]aspbian)
os_type=raspbian
;;
*)
exiterr "This script only supports Ubuntu and Debian."
;;
esac
os_ver=$(sed 's/\..*//' /etc/debian_version | tr -dc 'A-Za-z0-9')
if [ "$os_ver" = 8 ] || [ "$os_ver" = 9 ] || [ "$os_ver" = "stretchsid" ] \
|| [ "$os_ver" = "bustersid" ] || [ -z "$os_ver" ]; then
cat 1>&2 <= 10 or Ubuntu >= 20.04.
This version of Ubuntu/Debian is too old and not supported.
EOF
exit 1
fi
[ -f /etc/os-release ] && ubuntu_ver=$(. /etc/os-release && printf '%s' "$VERSION_ID")
}
check_iface() {
if ! command -v route >/dev/null 2>&1 && ! command -v ip >/dev/null 2>&1; then
wait_for_apt
export DEBIAN_FRONTEND=noninteractive
(
set -x
apt-get -yqq update || apt-get -yqq update
apt-get -yqq install iproute2 >/dev/null
)
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
if ! uname -m | grep -qi -e '^arm' -e '^aarch64'; then
case $def_iface in
wl*)
exiterr "Wireless interface '$def_iface' detected. DO NOT run this script on your PC or Mac!"
;;
esac
fi
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
}
check_creds() {
[ -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/null | head -c 20)
VPN_USER=vpnuser
VPN_PASSWORD=$(LC_CTYPE=C tr -dc 'A-HJ-NPR-Za-km-z2-9' /dev/null | 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
}
check_dns() {
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
}
check_server_dns() {
if [ -n "$VPN_DNS_NAME" ] && ! check_dns_name "$VPN_DNS_NAME"; then
exiterr "Invalid DNS name. 'VPN_DNS_NAME' must be a fully qualified domain name (FQDN)."
fi
}
check_client_name() {
if [ -n "$VPN_CLIENT_NAME" ]; then
name_len="$(printf '%s' "$VPN_CLIENT_NAME" | wc -m)"
if [ "$name_len" -gt "64" ] || printf '%s' "$VPN_CLIENT_NAME" | LC_ALL=C grep -q '[^A-Za-z0-9_-]\+' \
|| case $VPN_CLIENT_NAME in -*) true ;; *) false ;; esac; then
exiterr "Invalid client name. Use one word only, no special characters except '-' and '_'."
fi
fi
}
check_subnets() {
if [ -s /etc/ipsec.conf ] && grep -qs "hwdsl2 VPN script" /etc/sysctl.conf; then
L2TP_NET=${VPN_L2TP_NET:-'192.168.42.0/24'}
XAUTH_NET=${VPN_XAUTH_NET:-'192.168.43.0/24'}
if ! grep -q "$L2TP_NET" /etc/ipsec.conf \
|| ! grep -q "$XAUTH_NET" /etc/ipsec.conf; then
echo "Error: The custom VPN subnets specified do not match initial install." >&2
echo " See Advanced usage -> Customize VPN subnets for more information." >&2
exit 1
fi
fi
}
check_iptables() {
if [ -x /sbin/iptables ] && ! iptables -nL INPUT >/dev/null 2>&1; then
exiterr "IPTables check failed. Reboot and re-run this script."
fi
}
start_setup() {
bigecho "VPN setup in progress... Please be patient."
mkdir -p /opt/src
cd /opt/src || exit 1
}
wait_for_apt() {
count=0
apt_lk=/var/lib/apt/lists/lock
pkg_lk=/var/lib/dpkg/lock
while fuser "$apt_lk" "$pkg_lk" >/dev/null 2>&1 \
|| lsof "$apt_lk" >/dev/null 2>&1 || lsof "$pkg_lk" >/dev/null 2>&1; do
[ "$count" = 0 ] && echo "## Waiting for apt to be available..."
[ "$count" -ge 200 ] && exiterr "Could not get apt/dpkg lock."
count=$((count+1))
printf '%s' '.'
sleep 3
done
}
update_apt_cache() {
bigecho "Installing packages required for setup..."
export DEBIAN_FRONTEND=noninteractive
(
set -x
apt-get -yqq update || apt-get -yqq update
) || exiterr "'apt-get update' failed."
}
install_setup_pkgs() {
(
set -x
apt-get -yqq install wget dnsutils openssl \
iptables iproute2 gawk grep sed net-tools >/dev/null \
|| apt-get -yqq install wget dnsutils openssl \
iptables iproute2 gawk grep sed net-tools >/dev/null
) || exiterr2
}
get_default_ip() {
def_ip=$(ip -4 route get 1 | sed 's/ uid .*//' | awk '{print $NF;exit}' 2>/dev/null)
if check_ip "$def_ip" \
&& ! printf '%s' "$def_ip" | grep -Eq '^(10|127|172\.(1[6-9]|2[0-9]|3[0-1])|192\.168|169\.254)\.'; then
public_ip="$def_ip"
fi
}
detect_ip() {
public_ip=${VPN_PUBLIC_IP:-''}
check_ip "$public_ip" || get_default_ip
check_ip "$public_ip" && return 0
bigecho "Trying to auto discover IP of this server..."
check_ip "$public_ip" || public_ip=$(dig @resolver1.opendns.com -t A -4 myip.opendns.com +short)
check_ip "$public_ip" || public_ip=$(wget -t 2 -T 10 -qO- http://ipv4.icanhazip.com)
check_ip "$public_ip" || public_ip=$(wget -t 2 -T 10 -qO- http://ip1.dynupdate.no-ip.com)
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" || { echo "Warning: Invalid IPv6 address in 'VPN_PUBLIC_IP6'. Detecting IPv6..." >&2; ip6=""; }
fi
[ -z "$ip6" ] && ip6=$(ip -6 addr 2>/dev/null | awk '/inet6 [23]/ {print $2}' | cut -d'/' -f1 | head -n1)
check_ip6 "$ip6" || ip6=""
}
install_vpn_pkgs() {
bigecho "Installing packages required for the VPN..."
p1=libcurl4-nss-dev
if [ "$os_ver" = "trixiesid" ] || [ "$os_ver" = 13 ]; then
p1=libcurl4-gnutls-dev
fi
(
set -x
apt-get -yqq install libnss3-dev libnspr4-dev pkg-config \
libpam0g-dev libcap-ng-dev libcap-ng-utils libselinux1-dev \
$p1 flex bison gcc make libnss3-tools \
libevent-dev libsystemd-dev uuid-runtime ppp xl2tpd >/dev/null
) || exiterr2
if { [ "$os_type" = "ubuntu" ] && [ -n "$ubuntu_ver" ] \
&& printf '%s\n%s' "24.10" "$ubuntu_ver" | sort -C -V; } \
|| [ "$os_ver" = 13 ]; then
(
set -x
apt-get -yqq install systemd-dev >/dev/null
) || exiterr2
fi
if [ "$os_type" = "debian" ] && printf '%s\n%s' "12" "$os_ver" | sort -C -V; then
(
set -x
apt-get -yqq install rsyslog >/dev/null
) || exiterr2
fi
}
install_fail2ban() {
bigecho "Installing Fail2Ban to protect SSH..."
(
set -x
apt-get -yqq install fail2ban >/dev/null
)
}
link_scripts() {
cd /opt/src || exit 1
/bin/mv -f ikev2setup.sh ikev2.sh
/bin/mv -f add_vpn_user.sh addvpnuser.sh
/bin/mv -f del_vpn_user.sh delvpnuser.sh
echo "+ ikev2.sh addvpnuser.sh delvpnuser.sh"
for sc in ikev2.sh addvpnuser.sh delvpnuser.sh; do
[ -s "$sc" ] && chmod +x "$sc" && ln -s "/opt/src/$sc" /usr/bin 2>/dev/null
done
}
get_helper_scripts() {
bigecho "Downloading helper scripts..."
base1="https://raw.githubusercontent.com/hwdsl2/setup-ipsec-vpn/master/extras"
base2="https://gitlab.com/hwdsl2/setup-ipsec-vpn/-/raw/master/extras"
sc1=ikev2setup.sh
sc2=add_vpn_user.sh
sc3=del_vpn_user.sh
cd /opt/src || exit 1
/bin/rm -f "$sc1" "$sc2" "$sc3"
if wget -t 3 -T 30 -q "$base1/$sc1" "$base1/$sc2" "$base1/$sc3"; then
link_scripts
else
/bin/rm -f "$sc1" "$sc2" "$sc3"
if wget -t 3 -T 30 -q "$base2/$sc1" "$base2/$sc2" "$base2/$sc3"; then
link_scripts
else
echo "Warning: Could not download helper scripts." >&2
/bin/rm -f "$sc1" "$sc2" "$sc3"
fi
fi
}
get_swan_ver() {
SWAN_VER=5.3
base_url="https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0"
swan_ver_url="$base_url/v1-$os_type-$os_ver-swanver"
swan_ver_latest=$(wget -t 2 -T 10 -qO- "$swan_ver_url" | head -n 1)
[ -z "$swan_ver_latest" ] && swan_ver_latest=$(curl -m 10 -fsL "$swan_ver_url" 2>/dev/null | head -n 1)
if printf '%s' "$swan_ver_latest" | grep -Eq '^([3-9]|[1-9][0-9]{1,2})(\.([0-9]|[1-9][0-9]{1,2})){1,2}$'; then
SWAN_VER="$swan_ver_latest"
fi
if [ -n "$VPN_SWAN_VER" ]; then
if ! printf '%s\n%s' "4.15" "$VPN_SWAN_VER" | sort -C -V \
|| ! printf '%s\n%s' "$VPN_SWAN_VER" "$SWAN_VER" | sort -C -V; then
cat 1>&2 </dev/null)
swan_ver_old=$(printf '%s' "$ipsec_ver" | sed -e 's/.*Libreswan U\?//' -e 's/\( (\|\/K\).*//')
ipsec_bin="/usr/local/sbin/ipsec"
if [ -n "$swan_ver_old" ] && printf '%s' "$ipsec_ver" | grep -qi 'libreswan' \
&& [ "$(find "$ipsec_bin" -mmin -10080)" ]; then
check_result=1
return 0
fi
get_swan_ver
if [ -s "$ipsec_bin" ] && [ "$swan_ver_old" = "$SWAN_VER" ]; then
touch "$ipsec_bin"
fi
[ "$swan_ver_old" = "$SWAN_VER" ] && check_result=1
}
get_libreswan() {
if [ "$check_result" = 0 ]; then
bigecho "Downloading Libreswan..."
cd /opt/src || exit 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"
(
set -x
wget -t 3 -T 30 -q -O "$swan_file" "$swan_url1" || wget -t 3 -T 30 -q -O "$swan_file" "$swan_url2"
) || exit 1
/bin/rm -rf "/opt/src/libreswan-$SWAN_VER"
tar xzf "$swan_file" && /bin/rm -f "$swan_file"
else
bigecho "Libreswan $swan_ver_old is already installed, skipping..."
fi
}
install_libreswan() {
if [ "$check_result" = 0 ]; then
bigecho "Compiling and installing Libreswan, please wait..."
cd "libreswan-$SWAN_VER" || exit 1
cat > Makefile.inc.local <<'EOF'
WERROR_CFLAGS=-w -s
USE_DNSSEC=false
USE_DH2=true
USE_NSS_KDF=false
FINALNSSDIR=/etc/ipsec.d
NSSDIR=/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
(
set -x
make "-j$((NPROCS+1))" -s base >/dev/null 2>&1 && make -s install-base >/dev/null 2>&1
)
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" \
|| [ ! -d /etc/ipsec.d ]; then
exiterr "Libreswan $SWAN_VER failed to build."
fi
fi
}
create_vpn_config() {
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"
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/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 <> /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
}
update_iptables() {
bigecho "Updating IPTables rules..."
IPT_FILE=/etc/iptables.rules
IPT_FILE2=/etc/iptables/rules.v4
ipt_flag=0
if ! grep -qs "hwdsl2 VPN script" "$IPT_FILE"; then
ipt_flag=1
fi
ipi='iptables -I INPUT'
ipf='iptables -I FORWARD'
ipp='iptables -t nat -I POSTROUTING'
res='RELATED,ESTABLISHED'
if [ "$ipt_flag" = 1 ]; then
service fail2ban stop >/dev/null 2>&1
iptables-save > "$IPT_FILE.old-$SYS_DT"
$ipi 1 -p udp --dport 1701 -m policy --dir in --pol none -j DROP
$ipi 2 -m conntrack --ctstate INVALID -j DROP
$ipi 3 -m conntrack --ctstate "$res" -j ACCEPT
$ipi 4 -p udp -m multiport --dports 500,4500 -j ACCEPT
$ipi 5 -p udp --dport 1701 -m policy --dir in --pol ipsec -j ACCEPT
$ipi 6 -p udp --dport 1701 -j DROP
$ipf 1 -m conntrack --ctstate INVALID -j DROP
$ipf 2 -i "$NET_IFACE" -o ppp+ -m conntrack --ctstate "$res" -j ACCEPT
$ipf 3 -i ppp+ -o "$NET_IFACE" -j ACCEPT
$ipf 4 -i ppp+ -o ppp+ -j ACCEPT
$ipf 5 -i "$NET_IFACE" -d "$XAUTH_NET" -m conntrack --ctstate "$res" -j ACCEPT
$ipf 6 -s "$XAUTH_NET" -o "$NET_IFACE" -j ACCEPT
$ipf 7 -s "$XAUTH_NET" -o ppp+ -j ACCEPT
iptables -A FORWARD -j DROP
$ipp -s "$XAUTH_NET" -o "$NET_IFACE" -m policy --dir out --pol none -j MASQUERADE
$ipp -s "$L2TP_NET" -o "$NET_IFACE" -j MASQUERADE
echo "# Modified by hwdsl2 VPN script" > "$IPT_FILE"
iptables-save >> "$IPT_FILE"
if [ -f "$IPT_FILE2" ]; then
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
}
apply_gcp_mtu_fix() {
if dmidecode -s system-product-name 2>/dev/null | grep -qi 'Google Compute Engine' \
&& ifconfig 2>/dev/null | grep "$NET_IFACE" | head -n 1 | grep -qi 'mtu 1460'; then
bigecho "Applying fix for MTU size..."
ifconfig "$NET_IFACE" mtu 1500
dh_file="/etc/dhcp/dhclient.conf"
if grep -qs "send host-name" "$dh_file" \
&& ! grep -qs "interface-mtu 1500" "$dh_file"; then
sed -i".old-$SYS_DT" \
"/send host-name/a \interface \"$NET_IFACE\" {\ndefault interface-mtu 1500;\nsupersede interface-mtu 1500;\n}" \
"$dh_file"
fi
fi
}
enable_on_boot() {
bigecho "Enabling services on boot..."
IPT_PST=/etc/init.d/iptables-persistent
IPT_PST2=/usr/share/netfilter-persistent/plugins.d/15-ip4tables
ipt_load=1
if [ -f "$IPT_FILE2" ] && { [ -f "$IPT_PST" ] || [ -f "$IPT_PST2" ]; }; then
ipt_load=0
fi
if [ "$ipt_load" = 1 ]; then
mkdir -p /etc/network/if-pre-up.d
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
if [ -f /usr/sbin/netplan ]; then
mkdir -p /etc/systemd/system
cat > /etc/systemd/system/load-iptables-rules.service <<'EOF'
[Unit]
Description = Load /etc/iptables.rules
DefaultDependencies=no
Before=network-pre.target
Wants=network-pre.target
Wants=systemd-modules-load.service local-fs.target
After=systemd-modules-load.service local-fs.target
[Service]
Type=oneshot
ExecStart=/etc/network/if-pre-up.d/iptablesload
[Install]
WantedBy=multi-user.target
EOF
systemctl enable load-iptables-rules 2>/dev/null
fi
fi
for svc in fail2ban ipsec xl2tpd; do
update-rc.d "$svc" enable >/dev/null 2>&1
systemctl enable "$svc" 2>/dev/null
done
if ! grep -qs "hwdsl2 VPN script" /etc/rc.local; then
if [ -f /etc/rc.local ]; then
conf_bk "/etc/rc.local"
sed --follow-symlinks -i '/^exit 0/d' /etc/rc.local
else
echo '#!/bin/sh' > /etc/rc.local
fi
rc_delay=15
if uname -m | grep -qi '^arm'; then
rc_delay=60
fi
ip6_fwd_rc=""
[ -n "$ip6" ] && ip6_fwd_rc='
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding'
cat >> /etc/rc.local < /proc/sys/net/ipv4/ip_forward${ip6_fwd_rc})&
exit 0
EOF
fi
}
start_services() {
bigecho "Starting services..."
sysctl -e -q -p
chmod +x /etc/rc.local
chmod 600 /etc/ipsec.secrets* /etc/ppp/chap-secrets* /etc/ipsec.d/passwd*
mkdir -p /run/pluto
service fail2ban restart 2>/dev/null
service ipsec restart 2>/dev/null
service xl2tpd restart 2>/dev/null
}
show_vpn_info() {
cat <