diff --git a/.github/ISSUE_TEMPLATE/00-bug-report.md b/.github/ISSUE_TEMPLATE/00-bug-report.md new file mode 100644 index 0000000000..33a084b365 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/00-bug-report.md @@ -0,0 +1,48 @@ +--- +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. diff --git a/.github/ISSUE_TEMPLATE/10-bug-report-zh.md b/.github/ISSUE_TEMPLATE/10-bug-report-zh.md new file mode 100644 index 0000000000..735254c52b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/10-bug-report-zh.md @@ -0,0 +1,48 @@ +--- +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 的其它信息。 diff --git a/.github/ISSUE_TEMPLATE/20-enhancement-request.md b/.github/ISSUE_TEMPLATE/20-enhancement-request.md new file mode 100644 index 0000000000..6baa7bdb58 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/20-enhancement-request.md @@ -0,0 +1,26 @@ +--- +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. diff --git a/.github/ISSUE_TEMPLATE/30-enhancement-request-zh.md b/.github/ISSUE_TEMPLATE/30-enhancement-request-zh.md new file mode 100644 index 0000000000..b8ebc7a191 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/30-enhancement-request-zh.md @@ -0,0 +1,26 @@ +--- +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-状态) + +**描述改进建议** +使用清楚简明的语言描述你的改进建议。 + +**你的改进建议与遇到的问题有关吗?请描述。** +(如果适用)清楚,简洁地说明问题所在。 + +**其它信息** +添加关于该改进建议的其它信息。 diff --git a/.github/workflows/check_urls.yml b/.github/workflows/check_urls.yml new file mode 100644 index 0000000000..bc12bc4cb1 --- /dev/null +++ b/.github/workflows/check_urls.yml @@ -0,0 +1,108 @@ +# +# Copyright (C) 2020-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! + +name: check_urls + +on: workflow_call + +jobs: + check_urls: + runs-on: ubuntu-22.04 + if: github.repository_owner == 'hwdsl2' + steps: + - uses: actions/checkout@v4 + 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 diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml new file mode 100644 index 0000000000..a3dd978a63 --- /dev/null +++ b/.github/workflows/cron.yml @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020-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! + +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_2: + needs: check_urls + uses: ./.github/workflows/test_set_2.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000000..4fce05b297 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,28 @@ +# +# Copyright (C) 2020-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! + +name: build + +on: + push: + branches: [master] + paths: + - '**.sh' + - '.github/workflows/main.yml' + - '.github/workflows/shellcheck.yml' + - '.github/workflows/test_set_2.yml' + +jobs: + shellcheck: + if: github.repository_owner == 'hwdsl2' + uses: ./.github/workflows/shellcheck.yml + + test_set_2: + needs: shellcheck + uses: ./.github/workflows/test_set_2.yml diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml new file mode 100644 index 0000000000..ddcb1e0d98 --- /dev/null +++ b/.github/workflows/shellcheck.yml @@ -0,0 +1,38 @@ +# +# Copyright (C) 2020-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! + +name: shellcheck + +on: workflow_call + +jobs: + shellcheck: + runs-on: ubuntu-22.04 + if: github.repository_owner == 'hwdsl2' + steps: + - uses: actions/checkout@v4 + 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 diff --git a/.github/workflows/test_set_1.yml b/.github/workflows/test_set_1.yml new file mode 100644 index 0000000000..b94d1ce8a6 --- /dev/null +++ b/.github/workflows/test_set_1.yml @@ -0,0 +1,622 @@ +# +# Copyright (C) 2020-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! + +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:9s", "rockylinux:8", "almalinux:9", "almalinux:8", "amazonlinux:2", "oraclelinux:9", "oraclelinux:8", "oraclelinux:7"] + fail-fast: false + env: + OS_VERSION: ${{ matrix.os_version }} + steps: + - uses: actions/checkout@v4 + 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 + if ! command -v amazon-linux-extras; then + systemctl restart ipsec + fi + if grep -qs -i stream /etc/redhat-release \ + && grep -qs 'release 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 + yum -y -q update + yum -y -q install wget rsyslog + if grep -qs 'release 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 -qs 'release 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 -qs 'release 9' /etc/oracle-release; then + if ! grep -qs -i stream /etc/redhat-release \ + || ! grep -qs 'release 9' /etc/redhat-release; then + restart_fail2ban + cat /var/log/fail2ban.log + fi + fi + + netstat -anpu | grep pluto + netstat -anpu | grep xl2tpd + if grep -qs 'release 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 -qs 'release 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 + else + echo "FROM $OS_VERSION" > Dockerfile + fi + + cat >> Dockerfile <<'EOF' + + ENV container docker + WORKDIR /opt/src + + RUN if command -v amazon-linux-extras; then amazon-linux-extras install -y kernel-ng; fi + EOF + + if [ "$OS_VERSION" = "centos:9s" ]; 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:ro \ + --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 diff --git a/.github/workflows/test_set_2.yml b/.github/workflows/test_set_2.yml new file mode 100644 index 0000000000..d7bb217fa6 --- /dev/null +++ b/.github/workflows/test_set_2.yml @@ -0,0 +1,547 @@ +# +# Copyright (C) 2020-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! + +name: test_set_2 + +on: workflow_call + +jobs: + test_set_2: + runs-on: ubuntu-22.04 + if: github.repository_owner == 'hwdsl2' + strategy: + matrix: + os_version: ["ubuntu:24.04", "ubuntu:22.04", "ubuntu:20.04", "debian:12", "debian:11", "alpine:3.20", "alpine:3.19"] + fail-fast: false + container: + image: ${{ matrix.os_version }} + options: --cap-add=NET_ADMIN --device=/dev/ppp + steps: + - uses: actions/checkout@v4 + 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 + + 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" ] \ + || grep -qs trixie /etc/debian_version; 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 dist-upgrade + apt-get -yqq install wget rsyslog + if grep -qs -e bookworm -e trixie /etc/debian_version \ + || [ "$(sed 's/\..*//' /etc/debian_version 2>/dev/null)" = "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 + if ! grep -qs trixie /etc/debian_version; then + restart_fail2ban + cat /var/log/fail2ban.log + fi + 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 diff --git a/README-zh.md b/README-zh.md index 127e951cd4..16ca245b19 100644 --- a/README-zh.md +++ b/README-zh.md @@ -1,156 +1,437 @@ -# IPsec VPN 服务器一键安装脚本  [![Build Status](https://static.ls20.com/travis-ci/setup-ipsec-vpn.svg)](https://travis-ci.org/hwdsl2/setup-ipsec-vpn) +[English](README.md) | [中文](README-zh.md) -*其他语言版本: [English](README.md), [简体中文](README-zh.md).* +# IPsec VPN 服务器一键安装脚本 -使用 Linux Shell 脚本一键快速搭建 IPsec VPN 服务器。同时支持 IPsec/L2TP 和 Cisco IPsec 协议,可用于 Ubuntu,Debian 和 CentOS 系统。你只需提供自己的 VPN 登录凭证,然后运行脚本自动完成安装。 +[![Build Status](https://github.com/hwdsl2/setup-ipsec-vpn/actions/workflows/main.yml/badge.svg)](https://github.com/hwdsl2/setup-ipsec-vpn/actions/workflows/main.yml) [![GitHub Stars](docs/images/badges/github-stars.svg)](https://github.com/hwdsl2/setup-ipsec-vpn/stargazers) [![Docker Stars](docs/images/badges/docker-stars.svg)](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh.md) [![Docker Pulls](docs/images/badges/docker-pulls.svg)](https://github.com/hwdsl2/docker-ipsec-vpn-server/blob/master/README-zh.md) -我们将使用 Libreswan 作为 IPsec 服务器,以及 xl2tpd 作为 L2TP 提供者。 +使用 Linux 脚本一键快速搭建自己的 IPsec VPN 服务器。支持 IPsec/L2TP, Cisco IPsec 和 IKEv2 协议。 -**» 相关教程: IPsec VPN Server Auto Setup with Libreswan** +IPsec VPN 可以加密你的网络流量,以防止在通过因特网传送时,你和 VPN 服务器之间的任何人对你的数据的未经授权的访问。在使用不安全的网络时,这是特别有用的,例如在咖啡厅,机场或旅馆房间。 -#### 目录 +我们将使用 [Libreswan](https://libreswan.org/) 作为 IPsec 服务器,以及 [xl2tpd](https://github.com/xelerance/xl2tpd) 作为 L2TP 提供者。 -- [功能特性](#功能特性) -- [系统要求](#系统要求) -- [安装说明](#安装说明) - - [Ubuntu & Debian](#ubuntu--debian) - - [CentOS & RHEL](#centos--rhel) -- [下一步](#下一步) -- [重要提示](#重要提示) -- [升级Libreswan](#升级libreswan) -- [问题和反馈](#问题和反馈) -- [卸载说明](#卸载说明) -- [另见](#另见) -- [作者](#作者) -- [授权协议](#授权协议) +**[» :book: Book: 搭建自己的 VPN 服务器分步指南](https://books2read.com/vpnguidezh)** [[中文](https://books2read.com/vpnguidezh) | [English](https://books2read.com/vpnguide?store=amazon) | [Español](https://books2read.com/vpnguidees?store=amazon) | [Deutsch](https://books2read.com/vpnguidede?store=amazon) | [Français](https://books2read.com/vpnguidefr?store=amazon) | [Italiano](https://books2read.com/vpnguideit?store=amazon) | [PT](https://books2read.com/vpnguidept?store=amazon) | [日本語](https://books2read.com/vpnguideja?store=amazon)] + +## 快速开始 + +首先,在你的 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/XAuth ("Cisco IPsec")` 模式 -- **新:** 现在可以下载 VPN 服务器的预构建 [Docker 镜像](#另见) - 全自动的 IPsec VPN 服务器配置,无需用户输入 -- 封装所有的 VPN 流量在 UDP 协议,不需要 ESP 协议支持 -- 可直接作为 Amazon EC2 实例创建时的用户数据使用 -- 自动确定服务器的公网 IP 以及私有 IP 地址 -- 包括基本的 IPTables 防火墙规则和 `sysctl.conf` 优化设置 -- 测试通过: Ubuntu 16.04/14.04/12.04, Debian 8 和 CentOS 6/7 +- 支持具有强大和快速加密算法(例如 AES-GCM)的 IKEv2 模式 +- 生成 VPN 配置文件以自动配置 iOS, macOS 和 Android 设备 +- 支持 Windows, macOS, iOS, Android, Chrome OS 和 Linux 客户端 +- 包括辅助脚本以管理 VPN 用户和证书 ## 系统要求 -一个新创建的 Amazon EC2 实例,使用这些 AMI: (详细步骤 看这里) -- Ubuntu 16.04 (Xenial), 14.04 (Trusty) or 12.04 (Precise) -- Debian 8 (Jessie) EC2 Images -- CentOS 7 (x86_64) with Updates -- CentOS 6 (x86_64) with Updates +一个云服务器,虚拟专用服务器 (VPS) 或者专用服务器,安装以下操作系统之一: + +- Ubuntu 24.04, 22.04 或者 20.04 +- Debian 12 或者 11 +- CentOS Stream 9 +- Rocky Linux 或者 AlmaLinux +- Oracle Linux +- Amazon Linux 2 -**-或者-** +
+ +其他受支持的 Linux 发行版。 + -一个专用服务器,或者任何基于 KVM/Xen 的虚拟专用服务器 (VPS),全新安装以上操作系统之一。另外也可以使用 Debian 7 (Wheezy),但是必须首先运行另一个脚本。 OpenVZ VPS 用户可尝试 Shadowsocks ( libev | rss ) 或者 OpenVPN。 +- Raspberry Pi OS (Raspbian) +- Kali Linux +- Alpine Linux +- Red Hat Enterprise Linux (RHEL) +
-**» 我想建立并使用自己的 VPN ,但是没有可用的服务器** +这也包括公共云服务中的 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)部署。 + +使用以下按钮快速部署: + +[![Deploy to DigitalOcean](docs/images/do-install-button.png)](http://dovpn.carlfriess.com)  [![Deploy to Linode](docs/images/linode-deploy-button.png)](https://cloud.linode.com/stackscripts/37239)  [![Deploy to AWS](docs/images/aws-deploy-button.png)](aws/README-zh.md)  [![Deploy to Azure](docs/images/azure-deploy-button.png)](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 上运行这些脚本!它们只能用在服务器上! ## 安装说明 -### Ubuntu & Debian - -首先,更新你的系统: 运行 `apt-get update && apt-get dist-upgrade` 并重启。这一步是可选的,但推荐。 +首先,更新你的服务器:运行 `sudo apt-get update && sudo apt-get dist-upgrade` (Ubuntu/Debian) 或者 `sudo yum update` 并重启。这一步是可选的,但推荐。 要安装 VPN,请从以下选项中选择一个: -**选项 1:** 使用脚本随机生成的 VPN 登录凭证 (完成后会在屏幕上显示): +**选项 1:** 使用脚本随机生成的 VPN 登录凭证(完成后会显示)。 ```bash -wget https://git.io/vpnsetup -O vpnsetup.sh && sudo sh vpnsetup.sh +wget https://get.vpnsetup.net -O vpn.sh && sudo sh vpn.sh ``` -**选项 2:** 编辑脚本并提供你自己的 VPN 登录凭证: +**选项 2:** 编辑脚本并提供你自己的 VPN 登录凭证。 ```bash -wget https://git.io/vpnsetup -O vpnsetup.sh -nano -w vpnsetup.sh +wget https://get.vpnsetup.net -O vpn.sh +nano -w vpn.sh [替换为你自己的值: YOUR_IPSEC_PSK, YOUR_USERNAME 和 YOUR_PASSWORD] -sudo sh vpnsetup.sh +sudo sh vpn.sh ``` -**选项 3:** 将你自己的 VPN 登录凭证定义为环境变量: +**注:** 一个安全的 IPsec PSK 应该至少包含 20 个随机字符。 + +**选项 3:** 将你自己的 VPN 登录凭证定义为环境变量。 ```bash # 所有变量值必须用 '单引号' 括起来 # *不要* 在值中使用这些字符: \ " ' -wget https://git.io/vpnsetup -O vpnsetup.sh && sudo \ -VPN_IPSEC_PSK='你的IPsec预共享密钥' \ +wget https://get.vpnsetup.net -O vpn.sh +sudo VPN_IPSEC_PSK='你的IPsec预共享密钥' \ VPN_USER='你的VPN用户名' \ -VPN_PASSWORD='你的VPN密码' sh vpnsetup.sh +VPN_PASSWORD='你的VPN密码' \ +sh vpn.sh ``` -**注:** 如果无法通过 `wget` 下载,你也可以打开 vpnsetup.sh (或者 vpnsetup_centos.sh),然后点击右方的 **`Raw`** 按钮。按快捷键 `Ctrl-A` 全选, `Ctrl-C` 复制,然后粘贴到你喜欢的编辑器。 +你可以选择在同一台服务器上安装 [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。 -### CentOS & RHEL +
+ +如果无法下载,请点这里。 + -首先,更新你的系统: 运行 `yum update` 并重启。这一步是可选的,但推荐。 +你也可以使用 `curl` 下载。例如: -按照与上面相同的步骤,但是将 `https://git.io/vpnsetup` 换成 `https://git.io/vpnsetup-centos`。 +```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-子网)。 +
## 下一步 -配置你的计算机或其它设备使用 VPN 。请参见: +*其他语言版本: [English](README.md#next-steps), [中文](README-zh.md#下一步)。* -配置 IPsec/L2TP VPN 客户端 -配置 IPsec/XAuth ("Cisco IPsec") VPN 客户端 +配置你的计算机或其它设备使用 VPN。请参见: -开始使用自己的专属 VPN ! :sparkles::tada::rocket::sparkles: +**[配置 IKEv2 VPN 客户端(推荐)](docs/ikev2-howto-zh.md)** -## 重要提示 +**[配置 IPsec/L2TP VPN 客户端](docs/clients-zh.md)** + +**[配置 IPsec/XAuth ("Cisco IPsec") VPN 客户端](docs/clients-xauth-zh.md)** -**Windows 用户** 在首次连接之前需要修改一次注册表,以解决 VPN 服务器 和/或 客户端与 NAT (比如家用路由器)的兼容问题。如果在连接过程中遇到错误,请参见 故障排除。 +**阅读 [:book: VPN book](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-X8X5FVFZC) 以访问 [额外内容](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-X8X5FVFZC)。** -**Android 6 (Marshmallow) 用户** 请参考此文档中的注释: 配置 IPsec/L2TP VPN 客户端。 +开始使用自己的专属 VPN! :sparkles::tada::rocket::sparkles: + +## 重要提示 -如果需要添加,修改或者删除 VPN 用户账户,请参见 管理 VPN 用户。 +**Windows 用户** 对于 IPsec/L2TP 模式,在首次连接之前需要 [修改注册表](docs/clients-zh.md#windows-错误-809),以解决 VPN 服务器或客户端与 NAT(比如家用路由器)的兼容问题。 -在 VPN 已连接时,客户端配置为使用 Google Public DNS。如果偏好其它的域名解析服务,请编辑 `/etc/ppp/options.xl2tpd` 和 `/etc/ipsec.conf` 并替换 `8.8.8.8` 和 `8.8.4.4`。然后重启服务器。 +同一个 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/GCE),请打开 UDP 端口 500 和 4500,以及 TCP 端口 22 (用于 SSH)。 +对于有外部防火墙的服务器(比如 [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)。 -如果需要打开服务器上的其它端口,请编辑 IPTables 防火墙规则: `/etc/iptables.rules` 和/或 `/etc/iptables/rules.v4` (Ubuntu/Debian),或者 `/etc/sysconfig/iptables` (CentOS)。然后重启服务器。 +在 VPN 已连接时,客户端配置为使用 [Google Public DNS](https://developers.google.com/speed/public-dns/)。如果偏好其它的域名解析服务,请参见 [高级用法](docs/advanced-usage-zh.md)。 -在使用 `IPsec/L2TP` 连接时,VPN 服务器在虚拟网络 `192.168.42.0/24` 内具有 IP `192.168.42.1`。 +使用内核支持有助于提高 IPsec/L2TP 性能。它在所有 [受支持的系统](#系统要求) 上可用。Ubuntu 系统需要安装 `linux-modules-extra-$(uname -r)` 软件包并运行 `service xl2tpd restart`。 这些脚本在更改现有的配置文件之前会先做备份,使用 `.old-日期-时间` 为文件名后缀。 ## 升级Libreswan -提供两个额外的脚本 vpnupgrade.shvpnupgrade_centos.sh,可用于升级 Libreswan (网站 | 通知列表)。请在运行前根据需要修改 `swan_ver` 变量。检查已安装版本: `ipsec --version` +使用以下命令更新你的 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 +``` -- 有问题需要提问?请先搜索已有的留言,在这个 Gist 以及我的博客。 -- Libreswan (IPsec) 的相关问题可在邮件列表提问。也可以参见这些文章:[1] [2] [3] [4] [5]。 -- 如果你发现了一个可重复的程序漏洞,请提交一个 GitHub Issue。 +
+ +如果无法下载,请点这里。 + -## 卸载说明 +你也可以使用 `curl` 下载: -请参见 卸载 VPN。 +```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.1`。查看已安装版本:`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-子网) +- [转发端口到 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 -- 在 Docker 上搭建 IPsec VPN +要卸载 IPsec VPN,运行[辅助脚本](extras/vpnuninstall.sh): -## 作者 +**警告:** 此辅助脚本将从你的服务器中删除 IPsec VPN。所有的 VPN 配置将被**永久删除**,并且 Libreswan 和 xl2tpd 将被移除。此操作**不可撤销**! -**Lin Song** (linsongui@gmail.com) -- 最后一年的美国在读博士生,专业是电子与计算机工程 (ECE) -- 现在正在积极寻找新的工作机会,比如软件或系统工程师 -- 在 LinkedIn 上与我联系: https://www.linkedin.com/in/linsongui +```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/mailman/listinfo/swan) 或 [strongSwan](https://lists.strongswan.org/mailman/listinfo/users) 邮件列表提问,或者参考这些网站:[[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-2016 Lin Song   View my profile on LinkedIn -基于 Thomas Sarlandie 的工作 (版权所有 2012) +版权所有 (C) 2014-2024 [Lin Song](https://github.com/hwdsl2) [![View my profile on LinkedIn](https://static.licdn.com/scds/common/u/img/webpromo/btn_viewmy_160x25.png)](https://www.linkedin.com/in/linsongui) +基于 [Thomas Sarlandie 的工作](https://github.com/sarfata/voodooprivacy) (版权所有 2012) -这个项目是以 知识共享署名-相同方式共享3.0 许可协议授权。 +[![Creative Commons License](https://i.creativecommons.org/l/by-sa/3.0/88x31.png)](http://creativecommons.org/licenses/by-sa/3.0/) +这个项目是以 [知识共享署名-相同方式共享3.0](http://creativecommons.org/licenses/by-sa/3.0/) 许可协议授权。 必须署名: 请包括我的名字在任何衍生产品,并且让我知道你是如何改善它的! diff --git a/README.md b/README.md index bca3446cf3..0259a3056e 100644 --- a/README.md +++ b/README.md @@ -1,156 +1,437 @@ -# IPsec VPN Server Auto Setup Scripts  [![Build Status](https://static.ls20.com/travis-ci/setup-ipsec-vpn.svg)](https://travis-ci.org/hwdsl2/setup-ipsec-vpn) +[English](README.md) | [中文](README-zh.md) -*Read this in other languages: [English](README.md), [简体中文](README-zh.md).* +# IPsec VPN Server Auto Setup Scripts -Set up your own IPsec VPN server in just a few minutes, with both IPsec/L2TP and Cisco IPsec on Ubuntu, Debian and CentOS. All you need to do is provide your own VPN credentials, and let the scripts handle the rest. +[![Build Status](https://github.com/hwdsl2/setup-ipsec-vpn/actions/workflows/main.yml/badge.svg)](https://github.com/hwdsl2/setup-ipsec-vpn/actions/workflows/main.yml) [![GitHub Stars](docs/images/badges/github-stars.svg)](https://github.com/hwdsl2/setup-ipsec-vpn/stargazers) [![Docker Stars](docs/images/badges/docker-stars.svg)](https://github.com/hwdsl2/docker-ipsec-vpn-server) [![Docker Pulls](docs/images/badges/docker-pulls.svg)](https://github.com/hwdsl2/docker-ipsec-vpn-server) -We will use Libreswan as the IPsec server, and xl2tpd as the L2TP provider. +Set up your own IPsec VPN server in just a few minutes, with IPsec/L2TP, Cisco IPsec and IKEv2. -**» Related tutorial: IPsec VPN Server Auto Setup with Libreswan** +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. -#### Table of Contents +We will use [Libreswan](https://libreswan.org/) as the IPsec server, and [xl2tpd](https://github.com/xelerance/xl2tpd) as the L2TP provider. -- [Features](#features) -- [Requirements](#requirements) -- [Installation](#installation) - - [Ubuntu & Debian](#ubuntu--debian) - - [CentOS & RHEL](#centos--rhel) -- [Next Steps](#next-steps) -- [Important Notes](#important-notes) -- [Upgrade Libreswan](#upgrade-libreswan) -- [Bugs & Questions](#bugs--questions) -- [Uninstallation](#uninstallation) -- [See Also](#see-also) -- [Author](#author) -- [License](#license) +**[» :book: Book: Build Your Own VPN Server](https://books2read.com/vpnguide?store=amazon)** [[English](https://books2read.com/vpnguide?store=amazon) | [中文](https://books2read.com/vpnguidezh) | [Español](https://books2read.com/vpnguidees?store=amazon) | [Deutsch](https://books2read.com/vpnguidede?store=amazon) | [Français](https://books2read.com/vpnguidefr?store=amazon) | [Italiano](https://books2read.com/vpnguideit?store=amazon) | [PT](https://books2read.com/vpnguidept?store=amazon) | [日本語](https://books2read.com/vpnguideja?store=amazon)] + +## 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 -- **New:** The faster `IPsec/XAuth ("Cisco IPsec")` mode is supported -- **New:** A pre-built [Docker image](#see-also) of the VPN server is now available - Fully automated IPsec VPN server setup, no user input needed -- Encapsulates all VPN traffic in UDP - does not need ESP protocol -- Can be directly used as "user-data" for a new Amazon EC2 instance -- Automatically determines public IP and private IP of server -- Includes basic IPTables rules and `sysctl.conf` settings -- Tested with Ubuntu 16.04/14.04/12.04, Debian 8 and CentOS 6 & 7 +- 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 newly created Amazon EC2 instance, using these AMIs: (See instructions) -- Ubuntu 16.04 (Xenial), 14.04 (Trusty) or 12.04 (Precise) -- Debian 8 (Jessie) EC2 Images -- CentOS 7 (x86_64) with Updates -- CentOS 6 (x86_64) with Updates +A cloud server, virtual private server (VPS) or dedicated server, with an install of: -**-OR-** +- Ubuntu 24.04, 22.04 or 20.04 +- Debian 12 or 11 +- CentOS Stream 9 +- Rocky Linux or AlmaLinux +- Oracle Linux +- Amazon Linux 2 -A dedicated server or any KVM- or Xen-based Virtual Private Server (VPS), freshly installed with one of the above systems. Besides those, Debian 7 (Wheezy) can also be used with this workaround. OpenVZ VPS users should instead try OpenVPN. +
+ +Other supported Linux distributions. + -**» I want to run my own VPN but don't have a server for that** +- 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: + +[![Deploy to DigitalOcean](docs/images/do-install-button.png)](http://dovpn.carlfriess.com)  [![Deploy to Linode](docs/images/linode-deploy-button.png)](https://cloud.linode.com/stackscripts/37239)  [![Deploy to AWS](docs/images/aws-deploy-button.png)](aws/README.md)  [![Deploy to Azure](docs/images/azure-deploy-button.png)](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 -### Ubuntu & Debian - -First, update your system with `apt-get update && apt-get dist-upgrade` and reboot. This is optional, but recommended. +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): +**Option 1:** Have the script generate random VPN credentials for you (will be displayed when finished). ```bash -wget https://git.io/vpnsetup -O vpnsetup.sh && sudo sh vpnsetup.sh +wget https://get.vpnsetup.net -O vpn.sh && sudo sh vpn.sh ``` -**Option 2:** Edit the script and provide your own VPN credentials: +**Option 2:** Edit the script and provide your own VPN credentials. ```bash -wget https://git.io/vpnsetup -O vpnsetup.sh -nano -w vpnsetup.sh +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 vpnsetup.sh +sudo sh vpn.sh ``` -**Option 3:** Define your VPN credentials as environment variables: +**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 characters within values: \ " ' -wget https://git.io/vpnsetup -O vpnsetup.sh && sudo \ -VPN_IPSEC_PSK='your_ipsec_pre_shared_key' \ +# 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 vpnsetup.sh +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 ``` -**Note:** If unable to download via `wget`, you may also open vpnsetup.sh (or vpnsetup_centos.sh) and click the **`Raw`** button. Press `Ctrl-A` to select all, `Ctrl-C` to copy, then paste into your favorite editor. +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 +``` -### CentOS & RHEL +**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. +
-First, update your system with `yum update` and reboot. This is optional, but recommended. +## Customize VPN options -Follow the same steps as above, but replace `https://git.io/vpnsetup` with `https://git.io/vpnsetup-centos`. +### Use alternative DNS servers -## Next Steps +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#下一步).* Get your computer or device to use the VPN. Please refer to: -Configure IPsec/L2TP VPN Clients -Configure IPsec/XAuth ("Cisco IPsec") VPN Clients +**[Configure IKEv2 VPN Clients (recommended)](docs/ikev2-howto.md)** -Enjoy your very own VPN! :sparkles::tada::rocket::sparkles: +**[Configure IPsec/L2TP VPN Clients](docs/clients.md)** -## Important Notes +**[Configure IPsec/XAuth ("Cisco IPsec") VPN Clients](docs/clients-xauth.md)** -For **Windows users**, this one-time registry change is required if the VPN server and/or client is behind NAT (e.g. home router). If you get an error when trying to connect, see Troubleshooting. +**Read [:book: VPN book](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-O5O7FVF8J) to access [extra content](https://ko-fi.com/post/Support-this-project-and-get-access-to-supporter-o-O5O7FVF8J).** -**Android 6 (Marshmallow) users**: Please see notes in Configure IPsec/L2TP VPN Clients. +Enjoy your very own VPN! :sparkles::tada::rocket::sparkles: -If you wish to add, edit or remove VPN user accounts, refer to Manage VPN Users. +## Important notes -Clients are set to use Google Public DNS when the VPN is active. If another DNS provider is preferred, replace `8.8.8.8` and `8.8.4.4` in both `/etc/ppp/options.xl2tpd` and `/etc/ipsec.conf`. Then reboot your server. +**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). -For servers with an external firewall (e.g. EC2/GCE), open UDP ports 500 & 4500, and TCP port 22 (for SSH). +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). -To open additional ports on the server, edit the IPTables rules in `/etc/iptables.rules` and/or `/etc/iptables/rules.v4` (Ubuntu/Debian), or `/etc/sysconfig/iptables` (CentOS). Then reboot your server. +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). -When connecting via `IPsec/L2TP`, the VPN server has IP `192.168.42.1` within the VPN subnet `192.168.42.0/24`. +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 -The additional scripts vpnupgrade.sh and vpnupgrade_centos.sh can be used to upgrade Libreswan (website | mailing list). Update the `swan_ver` variable as necessary. Check installed version: `ipsec --version` +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. -## Bugs & Questions +```bash +wget https://get.vpnsetup.net/upg -O vpnup.sh && sudo sh vpnup.sh +``` -- Got a question? Please first search other people's comments in this Gist and on my blog. -- Ask Libreswan (IPsec) related questions on the mailing list, or read these articles: [1] [2] [3] [4] [5]. -- If you found a reproducible bug, open a GitHub Issue to submit a bug report. +
+ +Click here if you are unable to download. + -## Uninstallation +You may also use `curl` to download: -Please refer to Uninstall the VPN. +```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.1`. 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). -## See Also +- [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) +- [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) -- IPsec VPN Server on Docker +## 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 +``` +
-## Author +For more information, see [Uninstall the VPN](docs/uninstall.md). -**Lin Song** (linsongui@gmail.com) -- Final year U.S. PhD candidate, majoring in Electrical and Computer Engineering (ECE) -- Actively seeking opportunities in areas such as Software or Systems Engineering -- Contact me on LinkedIn: https://www.linkedin.com/in/linsongui +## Feedback & Questions -Thanks to all contributors to this project! +- 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/mailman/listinfo/swan) or [strongSwan](https://lists.strongswan.org/mailman/listinfo/users) 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-2016 Lin Song   View my profile on LinkedIn -Based on the work of Thomas Sarlandie (Copyright 2012) +Copyright (C) 2014-2024 [Lin Song](https://github.com/hwdsl2) [![View my profile on LinkedIn](https://static.licdn.com/scds/common/u/img/webpromo/btn_viewmy_160x25.png)](https://www.linkedin.com/in/linsongui) +Based on [the work of Thomas Sarlandie](https://github.com/sarfata/voodooprivacy) (Copyright 2012) -This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License +[![Creative Commons License](https://i.creativecommons.org/l/by-sa/3.0/88x31.png)](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! diff --git a/aws/README-zh.md b/aws/README-zh.md new file mode 100644 index 0000000000..6a30471e4d --- /dev/null +++ b/aws/README-zh.md @@ -0,0 +1,125 @@ +[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**/20.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#下一步)。 + +点击下面的图标开始: + +[![Launch stack](images/cloudformation-launch-stack-button.png)](https://console.aws.amazon.com/cloudformation/home#/stacks/new) + +## 屏幕截图 + +
+ +点这里查看屏幕截图。 + + +![上传模板](images/upload-the-template.png) +![指定参数](images/specify-parameters.png) +![确认 IAM](images/confirm-iam.png) +![显示密钥](images/show-key.png) +
+ +## 常见问题 + +
+ +如何在部署结束后提取 IKEv2 连接配置文件? + + +部署完成之后,生成的 IKEv2 配置文件已经被上传到了一个新创建的 AWS Simple Storage Service (S3) 储存桶。下载配置文件的链接可以在 **Outputs** 页面下找到。 + +点击下载链接下载名为 `profiles.zip` 的压缩包文件。解压密码为**你在创建堆栈时输入的 VPN 连接密码**。 + +值得注意的是,IKEv2 配置文件的下载链接将会在**1天后过期**,从堆栈部署完成时算起。如果你将堆栈删除,存放 IKEv2 配置文件的储存桶不会被自动删除。 + +关于如何在 IKEv2 模式下配置你的客户端,请参见: [IKEv2 VPN 配置和使用指南](../docs/ikev2-howto-zh.md)。 + +![IKEv2 配置文件](images/credentials.png) + +
+ +
+ +部署后如何通过 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 + ``` + + ![显示密钥 ID](images/show-key-id.png) + +2. 直接从 **Outputs** 页面拷贝私钥对内容 ,然后将其保存入一个证书文件。请注意在保存到你的计算机之前,你可能需要修改私钥的格式,比如用换行符替换所有的空格。在保存后,需要为该私钥文件设置[适当的权限](https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/connection-prereqs.html#connection-prereqs-private-key)才能使用。 + + ![显示密钥内容](images/show-key-id.png) + +要为私钥文件设置适当的权限,请在该文件所在的目录下运行以下命令: + +```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-2024 [Scott X. L.](https://github.com/scottpedia) <[wtanglef@pm.me](mailto:wtanglef@pm.me)> diff --git a/aws/README.md b/aws/README.md new file mode 100644 index 0000000000..6b65319d3e --- /dev/null +++ b/aws/README.md @@ -0,0 +1,125 @@ +[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**/20.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: + +[![Launch stack](images/cloudformation-launch-stack-button.png)](https://console.aws.amazon.com/cloudformation/home#/stacks/new) + +## Screenshots + +
+ +Click here to view screenshots. + + +![Upload the template](images/upload-the-template.png) +![Specify parameters](images/specify-parameters.png) +![Confirm IAM](images/confirm-iam.png) +![Show key](images/show-key.png) +
+ +## 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). + +![Credentials](images/credentials.png) + +
+ +
+ +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 + ``` + + ![Show key ID](images/show-key-id.png) + +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. + + ![Show key material](images/show-key.png) + +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-2024 [Scott X. L.](https://github.com/scottpedia) <[wtanglef@pm.me](mailto:wtanglef@pm.me)> diff --git a/aws/cloudformation-template-ipsec.json b/aws/cloudformation-template-ipsec.json new file mode 100644 index 0000000000..8f2f758923 --- /dev/null +++ b/aws/cloudformation-template-ipsec.json @@ -0,0 +1,731 @@ +{ + "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-2024 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": { + "Ubuntu2004": { + "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" + }, + "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\nadd-apt-repository ppa:deadsnakes/ppa\napt-get -yq update\napt-get -yq install python3.11 python3-pip zip\npython3 -m pip install awscli\npython3.11 -m pip install -U pip setuptools\npython3.11 -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 = {", + " 'Ubuntu2004': 'ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*',", + " '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 22.04", + "Default": "Ubuntu2204", + "AllowedValues": [ + "Ubuntu2404", + "Ubuntu2204", + "Ubuntu2004", + "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" + ] + ] + } + } + } +} diff --git a/aws/images/cloudformation-launch-stack-button.png b/aws/images/cloudformation-launch-stack-button.png new file mode 100644 index 0000000000..0033c8e4d6 Binary files /dev/null and b/aws/images/cloudformation-launch-stack-button.png differ diff --git a/aws/images/confirm-iam.png b/aws/images/confirm-iam.png new file mode 100644 index 0000000000..dd1a448aa1 Binary files /dev/null and b/aws/images/confirm-iam.png differ diff --git a/aws/images/credentials.png b/aws/images/credentials.png new file mode 100644 index 0000000000..e6dd37203d Binary files /dev/null and b/aws/images/credentials.png differ diff --git a/aws/images/show-key-id.png b/aws/images/show-key-id.png new file mode 100644 index 0000000000..0d0abed1c5 Binary files /dev/null and b/aws/images/show-key-id.png differ diff --git a/aws/images/show-key.png b/aws/images/show-key.png new file mode 100644 index 0000000000..e9fc8e50e1 Binary files /dev/null and b/aws/images/show-key.png differ diff --git a/aws/images/specify-parameters.png b/aws/images/specify-parameters.png new file mode 100644 index 0000000000..cf2dda6982 Binary files /dev/null and b/aws/images/specify-parameters.png differ diff --git a/aws/images/upload-the-template.png b/aws/images/upload-the-template.png new file mode 100644 index 0000000000..1949a80fb5 Binary files /dev/null and b/aws/images/upload-the-template.png differ diff --git a/azure/README-zh.md b/azure/README-zh.md new file mode 100644 index 0000000000..639d8c6730 --- /dev/null +++ b/azure/README-zh.md @@ -0,0 +1,38 @@ +[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 (用户名) + - Password for VPN **and** SSH (密码) + - IPsec Pre-Shared Key for VPN (IPsec 预共享密钥) + - Operating System Image (操作系统镜像,Ubuntu 22.04 或 20.04) + - Virtual Machine Size (虚拟机大小,默认值: Standard_B1s) + +**注:** \*不要\* 在值中使用这些字符: `\ " '` + +请单击以下按钮开始: + +[![Deploy to Azure](../docs/images/azure-deploy-button.png)](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://docs.microsoft.com/zh-cn/troubleshoot/azure/virtual-machines/troubleshoot-ssh-connection) 和/或 [无法 SSH 到 Azure Linux VM,因为权限太开放](https://docs.microsoft.com/zh-cn/troubleshoot/azure/virtual-machines/troubleshoot-ssh-permissions-too-open)。 + +## 作者 + +版权所有 (C) 2016 [Daniel Falkner](https://github.com/derdanu) +版权所有 (C) 2017-2024 [Lin Song](https://github.com/hwdsl2) + +## 屏幕截图 + +
+ +单击查看屏幕截图。 + + +![Azure Custom Deployment](custom_deployment_screenshot.png) +
diff --git a/azure/README.md b/azure/README.md new file mode 100644 index 0000000000..23b7ab0f2a --- /dev/null +++ b/azure/README.md @@ -0,0 +1,38 @@ +[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 22.04 or 20.04) + - Virtual Machine Size (Default: Standard_B1s) + +**Note:** DO NOT use these special characters within values: `\ " '` + +Press this button to start: + +[![Deploy to Azure](../docs/images/azure-deploy-button.png)](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://docs.microsoft.com/en-us/troubleshoot/azure/virtual-machines/troubleshoot-ssh-connection) and/or [Can't SSH to Azure Linux VM because permissions are too open](https://docs.microsoft.com/en-us/troubleshoot/azure/virtual-machines/troubleshoot-ssh-permissions-too-open). + +## Authors + +Copyright (C) 2016 [Daniel Falkner](https://github.com/derdanu) +Copyright (C) 2017-2024 [Lin Song](https://github.com/hwdsl2) + +## Screenshot + +
+ +Click to see screenshot. + + +![Azure Custom Deployment](custom_deployment_screenshot.png) +
diff --git a/azure/azuredeploy.json b/azure/azuredeploy.json new file mode 100644 index 0000000000..9e3660b362 --- /dev/null +++ b/azure/azuredeploy.json @@ -0,0 +1,283 @@ +{ + "$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": [ + "ubuntu22.04", + "ubuntu20.04" + ], + "defaultValue": "ubuntu22.04", + "metadata": { + "description": "OS to use. Ubuntu 22.04 or 20.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'))]", + "ubuntu22.04": { + "publisher": "Canonical", + "offer": "0001-com-ubuntu-server-jammy", + "sku": "22_04-lts", + "version": "latest" + }, + "ubuntu20.04": { + "publisher": "Canonical", + "offer": "0001-com-ubuntu-server-focal", + "sku": "20_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]" + } + } +} diff --git a/azure/azuredeploy.parameters.json b/azure/azuredeploy.parameters.json new file mode 100644 index 0000000000..1dbe22b64d --- /dev/null +++ b/azure/azuredeploy.parameters.json @@ -0,0 +1,15 @@ +{ + "$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" + } + } +} \ No newline at end of file diff --git a/azure/custom_deployment_screenshot.png b/azure/custom_deployment_screenshot.png new file mode 100644 index 0000000000..6e7c30cefe Binary files /dev/null and b/azure/custom_deployment_screenshot.png differ diff --git a/azure/install.sh b/azure/install.sh new file mode 100755 index 0000000000..0731f9e397 --- /dev/null +++ b/azure/install.sh @@ -0,0 +1,7 @@ +#!/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 diff --git a/docs/advanced-usage-zh.md b/docs/advanced-usage-zh.md new file mode 100644 index 0000000000..20e3d8ca6e --- /dev/null +++ b/docs/advanced-usage-zh.md @@ -0,0 +1,419 @@ +[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-子网) +* [转发端口到 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 地址池。 + +## 转发端口到 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)。然后重启服务器。 + +**注:** 如果你的服务器运行 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-2024 [Lin Song](https://github.com/hwdsl2) [![View my profile on LinkedIn](https://static.licdn.com/scds/common/u/img/webpromo/btn_viewmy_160x25.png)](https://www.linkedin.com/in/linsongui) + +[![Creative Commons License](https://i.creativecommons.org/l/by-sa/3.0/88x31.png)](http://creativecommons.org/licenses/by-sa/3.0/) +这个项目是以 [知识共享署名-相同方式共享3.0](http://creativecommons.org/licenses/by-sa/3.0/) 许可协议授权。 +必须署名: 请包括我的名字在任何衍生产品,并且让我知道你是如何改善它的! diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md new file mode 100644 index 0000000000..3dbe2f5692 --- /dev/null +++ b/docs/advanced-usage.md @@ -0,0 +1,420 @@ +[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) +* [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. + +## 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. + +**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-2024 [Lin Song](https://github.com/hwdsl2) [![View my profile on LinkedIn](https://static.licdn.com/scds/common/u/img/webpromo/btn_viewmy_160x25.png)](https://www.linkedin.com/in/linsongui) + +[![Creative Commons License](https://i.creativecommons.org/l/by-sa/3.0/88x31.png)](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! diff --git a/docs/bbr-zh.md b/docs/bbr-zh.md new file mode 100644 index 0000000000..caea7f347b --- /dev/null +++ b/docs/bbr-zh.md @@ -0,0 +1,77 @@ +[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) diff --git a/docs/bbr.md b/docs/bbr.md new file mode 100644 index 0000000000..7fec2ca3cb --- /dev/null +++ b/docs/bbr.md @@ -0,0 +1,78 @@ +[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) diff --git a/docs/clients-xauth-zh.md b/docs/clients-xauth-zh.md index 2630875bf3..a1e479ddec 100644 --- a/docs/clients-xauth-zh.md +++ b/docs/clients-xauth-zh.md @@ -1,54 +1,70 @@ -## 配置 IPsec/XAuth VPN 客户端 +[English](clients-xauth.md) | [中文](clients-xauth-zh.md) -*其他语言版本: [English](clients-xauth.md), [简体中文](clients-xauth-zh.md).* +# 配置 IPsec/XAuth VPN 客户端 -*如需使用 IPsec/L2TP 模式连接,请参见: [配置 IPsec/L2TP VPN 客户端](clients-zh.md)* +在成功 [搭建自己的 VPN 服务器](../README-zh.md) 之后,按照下面的步骤来配置你的设备。IPsec/XAuth ("Cisco IPsec") 在 Android, iOS 和 OS X 上均受支持,无需安装额外的软件。Windows 用户可以使用免费的 [Shrew Soft 客户端](https://www.shrew.net/download/vpn)。如果无法连接,请首先检查是否输入了正确的 VPN 登录凭证。 -在成功搭建自己的 VPN 服务器之后,你可以按照下面的步骤来配置你的设备。IPsec/XAuth ("Cisco IPsec") 在 Android, iOS 和 OS X 上均受支持,无需安装额外的软件。Windows 用户可以使用免费的 Shrew Soft 客户端。如果无法连接,请首先检查是否输入了正确的 VPN 登录凭证。 - -`IPsec/XAuth` 模式也称为 "Cisco IPsec"。和 `IPsec/L2TP` 相比较,它通常能够更高效地传输数据。 +IPsec/XAuth 模式也称为 "Cisco IPsec"。该模式通常能够比 IPsec/L2TP **更高效**地传输数据(较低的额外开销)。 --- * 平台名称 * [Windows](#windows) - * [OS X](#os-x) + * [OS X (macOS)](#os-x-macos) * [Android](#android) - * [iOS](#ios) + * [iOS (iPhone/iPad)](#ios) + * [Linux](#linux) -### Windows ### +## Windows -**注:** 你也可以使用 [IPsec/L2TP 模式](clients-zh.md) 连接,无需安装额外的软件。 +> 你也可以使用 [IKEv2](ikev2-howto-zh.md)(推荐)或者 [IPsec/L2TP](clients-zh.md) 模式连接。无需安装额外的软件。 -1. 下载并安装免费的 Shrew Soft VPN 客户端。 +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 连接成功后,会在 VPN Connect 状态窗口中显示 **tunnel enabled** 字样。最后你可以到这里检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 +连接成功后,你会在 VPN Connect 状态窗口中看到 **tunnel enabled** 字样。单击 "Network" 选项卡,并确认 **Established - 1** 显示在 "Security Associations" 下面。最后你可以到 [这里](https://www.ipchicken.com) 检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 + +如果在连接过程中遇到错误,请参见 [故障排除](clients-zh.md#ikev1-故障排除)。 - -如果在连接过程中遇到错误,请参见 故障排除。 +## OS X (macOS) -**注:** 在首次连接之前需要修改一次注册表,以解决 VPN 服务器 和/或 客户端与 NAT (比如家用路由器)的兼容问题。请参照链接网页中的说明,或者打开提升权限命令提示符并运行以下命令。完成后必须重启计算机。 -- 适用于 Windows Vista, 7, 8 和 10 - ```console - REG ADD HKLM\SYSTEM\CurrentControlSet\Services\PolicyAgent /v AssumeUDPEncapsulationContextOnSendRule /t REG_DWORD /d 0x2 /f - ``` +### macOS 13 (Ventura) 及以上 -- 仅适用于 Windows XP - ```console - REG ADD HKLM\SYSTEM\CurrentControlSet\Services\IPSec /v AssumeUDPEncapsulationContextOnSendRule /t REG_DWORD /d 0x2 /f - ``` +> 你也可以使用 [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) 模式连接。 -### OS X ### 1. 打开系统偏好设置并转到网络部分。 1. 在窗口左下角单击 **+** 按钮。 1. 从 **接口** 下拉菜单选择 **VPN**。 @@ -58,18 +74,29 @@ VPN 连接成功后,会在 VPN Connect 状态窗口中显示 **tunnel enabled* 1. 在 **服务器地址** 字段中输入`你的 VPN 服务器 IP`。 1. 在 **帐户名称** 字段中输入`你的 VPN 用户名`。 1. 在 **密码** 字段中输入`你的 VPN 密码`。 -1. 单击 **鉴定设置** 按钮。 -1. 在 **机器鉴定** 部分,选择 **共享的密钥** 单选按钮,然后输入`你的 VPN IPsec PSK`。 +1. 单击 **认证设置** 按钮。 +1. 在 **机器认证** 部分,选择 **共享的密钥** 单选按钮,然后输入`你的 VPN IPsec PSK`。 1. 保持 **群组名称** 字段空白。 1. 单击 **好**。 1. 选中 **在菜单栏中显示 VPN 状态** 复选框。 -1. 单击 **应用** 保存VPN连接信息。 +1. 单击 **应用** 保存 VPN 连接信息。 + +要连接到 VPN:使用菜单栏中的图标,或者打开系统偏好设置的网络部分,选择 VPN 并单击 **连接**。最后你可以到 [这里](https://www.ipchicken.com) 检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 + +如果在连接过程中遇到错误,请参见 [故障排除](clients-zh.md#ikev1-故障排除)。 -要连接到 VPN,你可以使用菜单栏中的 VPN 图标,或者在系统偏好设置的网络部分选择 VPN,并单击 **连接**。最后你可以到这里检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 +## 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 设备上进行以下步骤: -### Android ### 1. 启动 **设置** 应用程序。 -1. 在 **无线和网络** 部分单击 **更多...**。 +1. 单击 **网络和互联网**。或者,如果你使用 Android 7 或更早版本,在 **无线和网络** 部分单击 **更多...**。 1. 单击 **VPN**。 1. 单击 **添加VPN配置文件** 或窗口右上角的 **+**。 1. 在 **名称** 字段中输入任意内容。 @@ -84,11 +111,14 @@ VPN 连接成功后,会在 VPN Connect 状态窗口中显示 **tunnel enabled* 1. 选中 **保存帐户信息** 复选框。 1. 单击 **连接**。 -**注:** Android 6 (Marshmallow) 用户需要编辑 VPN 服务器上的 `/etc/ipsec.conf`,并在 `ike=` 和 `phase2alg=` 两行结尾添加 `,aes256-sha2_256` 字样。然后在它们下面添加一行 `sha2-truncbug=yes`。每行开头必须空两格。保存修改并运行 `service ipsec restart`。(更多信息) +连接成功后,会在通知栏显示图标。最后你可以到 [这里](https://www.ipchicken.com) 检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 + +如果在连接过程中遇到错误,请参见 [故障排除](clients-zh.md#ikev1-故障排除)。 + +## iOS -VPN 连接成功后,会在通知栏显示图标。最后你可以到这里检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 +> 你也可以使用 [IKEv2](ikev2-howto-zh.md)(推荐)或者 [IPsec/L2TP](clients-zh.md) 模式连接。 -### iOS ### 1. 进入设置 -> 通用 -> VPN。 1. 单击 **添加VPN配置...**。 1. 单击 **类型** 。选择 **IPSec** 并返回。 @@ -98,46 +128,49 @@ VPN 连接成功后,会在通知栏显示图标。最后你可以到这里检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 +连接成功后,会在通知栏显示图标。最后你可以到 [这里](https://www.ipchicken.com) 检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 -## 故障排除 +如果在连接过程中遇到错误,请参见 [故障排除](clients-zh.md#ikev1-故障排除)。 -### Windows 错误 809 +## Linux -> 无法建立计算机与 VPN 服务器之间的网络连接,因为远程服务器未响应。 +> 你也可以使用 [IKEv2](ikev2-howto-zh.md) 模式连接(推荐)。 -要解决此错误,请按照上面的步骤添加注册表键并重启计算机。 +### Fedora 和 CentOS -### Windows 错误 628 +Fedora 28 (和更新版本)和 CentOS 8/7 用户可以使用 `yum` 安装 `NetworkManager-libreswan-gnome` 软件包,然后通过 GUI 配置 IPsec/XAuth VPN 客户端。 -> 在连接完成前,连接被远程计算机终止。 - -要解决此错误,请按以下步骤操作: - -1. 右键单击系统托盘中的无线/网络图标,选择 **打开网络与共享中心**。 -1. 单击左侧的 **更改适配器设置**。右键单击新的 VPN 连接,并选择 **属性**。 -1. 单击 **安全** 选项卡,从 **VPN 类型** 下拉菜单中选择 "使用 IPsec 的第 2 层隧道协议 (L2TP/IPSec)"。 -1. 单击 **允许使用这些协议**。选中 "质询握手身份验证协议 (CHAP)" 复选框,并且取消选中所有其它项。 -1. 单击 **确定** 保存 VPN 连接的详细信息。 - -![Select only CHAP in VPN connection properties-2](https://cloud.githubusercontent.com/assets/5104323/16026263/cbda945a-3192-11e6-96a6-ff18c5dd9a48.png) - -### 其它错误 +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 -本文档是在 Streisand 项目文档基础上翻译和修改。该项目由 Joshua Lund 和其他开发者维护。 +其它 Linux 版本用户可以使用 [IPsec/L2TP](clients-zh.md#linux) 模式连接。 ## 授权协议 -版权所有 (C) 2016 Lin Song -基于 Joshua Lund 的工作 (版权所有 2014-2016) +注: 这个协议仅适用于本文档。 + +版权所有 (C) 2016-2024 [Lin Song](https://github.com/hwdsl2) [![View my profile on LinkedIn](https://static.licdn.com/scds/common/u/img/webpromo/btn_viewmy_160x25.png)](https://www.linkedin.com/in/linsongui) +受到 [Joshua Lund 的工作](https://github.com/StreisandEffect/streisand/blob/6aa6b6b2735dd829ca8c417d72eb2768a89b6639/playbooks/roles/l2tp-ipsec/templates/instructions.md.j2) 的启发 -本程序为自由软件,在自由软件联盟发布的 GNU 通用公共许可协议的约束下,你可以对其进行再发布及修改。协议版本为第三版或(随你)更新的版本。 +本程序为自由软件,在自由软件联盟发布的[ GNU 通用公共许可协议](https://www.gnu.org/licenses/gpl.html)的约束下,你可以对其进行再发布及修改。协议版本为第三版或(随你)更新的版本。 我们希望发布的这款程序有用,但不保证,甚至不保证它有经济价值和适合特定用途。详情参见GNU通用公共许可协议。 diff --git a/docs/clients-xauth.md b/docs/clients-xauth.md index 595d2daec4..a374b535e5 100644 --- a/docs/clients-xauth.md +++ b/docs/clients-xauth.md @@ -1,54 +1,70 @@ -## Configure IPsec/XAuth VPN Clients +[English](clients-xauth.md) | [中文](clients-xauth-zh.md) -*Read this in other languages: [English](clients-xauth.md), [简体中文](clients-xauth-zh.md).* +# Configure IPsec/XAuth VPN Clients -*To connect using IPsec/L2TP mode, see: [Configure IPsec/L2TP VPN Clients](clients.md)* +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. -After setting up your own VPN server, 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. 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". Compared to `IPsec/L2TP`, it is generally faster with less overhead. +IPsec/XAuth mode is also called "Cisco IPsec". This mode is generally **faster than** IPsec/L2TP with less overhead. --- * Platforms * [Windows](#windows) - * [OS X](#os-x) + * [OS X (macOS)](#os-x-macos) * [Android](#android) - * [iOS](#ios) + * [iOS (iPhone/iPad)](#ios) + * [Linux](#linux) -### Windows ### +## Windows -**Note:** You can also connect using [IPsec/L2TP mode](clients.md). No additional software is required. +> 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. +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. Click the **Credentials** tab below. Enter `Your VPN IPsec PSK` in the **Pre Shared Key** field. +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. You can verify that your traffic is being routed properly by looking up your IP address on Google. It should say "Your public IP address is `Your VPN Server IP`". +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) - -If you get an error when trying to connect, see Troubleshooting. +### 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. -**Note:** This one-time registry change is required if the VPN server and/or client is behind NAT (e.g. home router). Refer to the linked web page, or run the following from an elevated command prompt. You must reboot your computer when finished. -- For Windows Vista, 7, 8 and 10 - ```console - REG ADD HKLM\SYSTEM\CurrentControlSet\Services\PolicyAgent /v AssumeUDPEncapsulationContextOnSendRule /t REG_DWORD /d 0x2 /f - ``` +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`". -- For Windows XP ONLY - ```console - REG ADD HKLM\SYSTEM\CurrentControlSet\Services\IPSec /v AssumeUDPEncapsulationContextOnSendRule /t REG_DWORD /d 0x2 /f - ``` +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. -### OS X ### 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. @@ -65,11 +81,22 @@ If you get an error when trying to connect, see Troub 1. Check the **Show VPN status in menu bar** checkbox. 1. Click **Apply** to save the VPN connection information. -You can connect to the VPN using the VPN icon in the menu bar, or by selecting the VPN in the Network section of System Preferences and choosing **Connect**. You can verify that your traffic is being routed properly by looking up your IP address on Google. It should say "Your public IP address is `Your VPN Server IP`". +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: -### Android ### 1. Launch the **Settings** application. -1. Tap **More...** in the **Wireless & Networks** section. +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. @@ -84,11 +111,14 @@ You can connect to the VPN using the VPN icon in the menu bar, or by selecting t 1. Check the **Save account information** checkbox. 1. Tap **Connect**. -**Note:** Android 6 (Marshmallow) users should edit `/etc/ipsec.conf` on the VPN server and append `,aes256-sha2_256` to both `ike=` and `phase2alg=` lines. Then add a new line `sha2-truncbug=yes` immediately after those. Indent lines with two spaces. When finished, run `service ipsec restart`. (Reference) +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`". -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. 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. -### iOS ### 1. Go to Settings -> General -> VPN. 1. Tap **Add VPN Configuration...**. 1. Tap **Type**. Select **IPSec** and go back. @@ -101,43 +131,46 @@ Once connected, you will see a VPN icon in the notification bar. You can verify 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. It should say "Your public IP address is `Your VPN Server IP`". - -## Troubleshooting +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`". -### Windows Error 809 +If you get an error when trying to connect, see [Troubleshooting](clients.md#ikev1-troubleshooting). -> The network connection between your computer and the VPN server could not be established because the remote server is not responding. +## Linux -To fix this error, follow the steps above to add a registry key and reboot your computer. +> You may also connect using [IKEv2](ikev2-howto.md) mode (recommended). -### Windows Error 628 +### Fedora and CentOS -> The connection was terminated by the remote computer before it could be completed. +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. -To fix this error, please follow these steps: - -1. Right-click on the wireless/network icon in system tray, select **Open Network and Sharing Center**. -1. On the left, click **Change adapter settings**. Right-click on the new VPN 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**. Select the "Challenge Handshake Authentication Protocol (CHAP)" checkbox, and deselect all others. -1. Click **OK** to save the VPN connection details. - -![Select only CHAP in VPN connection properties](https://cloud.githubusercontent.com/assets/5104323/16024310/b113e9b6-3186-11e6-9e03-12f5455487ba.png) - -### Other Errors +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. -Please refer to this document for more troubleshooting tips. +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`". -## Credits +### Other Linux -This document was adapted from the Streisand project by Joshua Lund and contributors. +Other Linux users can connect using [IPsec/L2TP](clients.md#linux) mode. ## License -Copyright (C) 2016 Lin Song -Based on the work of Joshua Lund (Copyright 2014-2016) +Note: This license applies to this document only. + +Copyright (C) 2016-2024 [Lin Song](https://github.com/hwdsl2) [![View my profile on LinkedIn](https://static.licdn.com/scds/common/u/img/webpromo/btn_viewmy_160x25.png)](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 as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +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. diff --git a/docs/clients-zh.md b/docs/clients-zh.md index 119ef9618e..23eadb6cf3 100644 --- a/docs/clients-zh.md +++ b/docs/clients-zh.md @@ -1,46 +1,85 @@ -## 配置 IPsec/L2TP VPN 客户端 +[English](clients.md) | [中文](clients-zh.md) -*其他语言版本: [English](clients.md), [简体中文](clients-zh.md).* +# 配置 IPsec/L2TP VPN 客户端 -*如需使用 IPsec/XAuth ("Cisco IPsec") 模式连接,请参见: [配置 IPsec/XAuth VPN 客户端](clients-xauth-zh.md)* - -在成功搭建自己的 VPN 服务器之后,你可以按照下面的步骤来配置你的设备。IPsec/L2TP 在 Android, iOS, OS X 和 Windows 上均受支持,无需安装额外的软件。设置过程通常只需要几分钟。如果无法连接,请首先检查是否输入了正确的 VPN 登录凭证。 +在成功 [搭建自己的 VPN 服务器](../README-zh.md) 之后,按照下面的步骤来配置你的设备。IPsec/L2TP 在 Android, iOS, OS X 和 Windows 上均受支持,无需安装额外的软件。设置过程通常只需要几分钟。如果无法连接,请首先检查是否输入了正确的 VPN 登录凭证。 --- * 平台名称 * [Windows](#windows) - * [OS X](#os-x) + * [OS X (macOS)](#os-x-macos) * [Android](#android) - * [iOS](#ios) - * [Chromebook](#chromebook) + * [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 ### +**注:** 在首次连接之前需要[修改一次注册表](#windows-错误-809),以解决 VPN 服务器 和/或 客户端与 NAT (比如家用路由器)的兼容问题。 -**Windows 10 and 8.x:** +要连接到 VPN:单击 **连接** 按钮,或者单击系统托盘中的无线/网络图标,单击 **VPN**,然后选择新的 VPN 连接并单击 **连接**。如果出现提示,在登录窗口中输入 `你的 VPN 用户名` 和 `密码` ,并单击 **确定**。最后你可以到 [这里](https://www.ipchicken.com) 检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 + +如果在连接过程中遇到错误,请参见 [故障排除](#ikev1-故障排除)。 + +### Windows 10 and 8 1. 右键单击系统托盘中的无线/网络图标。 -1. 选择 **打开网络与共享中心**。 +1. 选择 **打开"网络和 Internet"设置**,然后在打开的页面中单击 **网络和共享中心**。 1. 单击 **设置新的连接或网络**。 1. 选择 **连接到工作区**,然后单击 **下一步**。 1. 单击 **使用我的Internet连接 (VPN)**。 1. 在 **Internet地址** 字段中输入`你的 VPN 服务器 IP`。 1. 在 **目标名称** 字段中输入任意内容。单击 **创建**。 -1. 右键单击系统托盘中的无线/网络图标,选择 **打开网络与共享中心**。 -1. 单击左侧的 **更改适配器设置**。右键单击新的 VPN 连接,并选择 **属性**。 +1. 返回 **网络和共享中心**。单击左侧的 **更改适配器设置**。 +1. 右键单击新创建的 VPN 连接,并选择 **属性**。 1. 单击 **安全** 选项卡,从 **VPN 类型** 下拉菜单中选择 "使用 IPsec 的第 2 层隧道协议 (L2TP/IPSec)"。 -1. 单击 **允许使用这些协议**。选中 "质询握手身份验证协议 (CHAP)" 复选框,并且取消选中所有其它项。 +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`。 -**Windows 7, Vista and XP:** +如果在连接过程中遇到错误,请参见 [故障排除](#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. 选择 **连接到工作区**,然后单击 **下一步**。 1. 单击 **使用我的Internet连接 (VPN)**。 @@ -52,33 +91,53 @@ 1. 在 **密码** 字段中输入`你的 VPN 密码`。 1. 选中 **记住此密码** 复选框。 1. 单击 **创建**,然后单击 **关闭** 按钮。 -1. 重复上面的第 1-3 步,打开 **网络与共享中心**。 -1. 单击左侧的 **更改适配器设置**。右键单击新的 VPN 连接,并选择 **属性**。 -1. 单击 **选项** 选项卡,取消选中 **包含Windows登录域** 复选框。 +1. 返回 **网络和共享中心**。单击左侧的 **更改适配器设置**。 +1. 右键单击新创建的 VPN 连接,并选择 **属性**。 +1. 单击 **选项** 选项卡,取消选中 **包括Windows登录域** 复选框。 1. 单击 **安全** 选项卡,从 **VPN 类型** 下拉菜单中选择 "使用 IPsec 的第 2 层隧道协议 (L2TP/IPSec)"。 -1. 单击 **允许使用这些协议**。选中 "质询握手身份验证协议 (CHAP)" 复选框,并且取消选中所有其它项。 +1. 单击 **允许使用这些协议**。选中 "质询握手身份验证协议 (CHAP)" 和 "Microsoft CHAP 版本 2 (MS-CHAP v2)" 复选框。 1. 单击 **高级设置** 按钮。 1. 单击 **使用预共享密钥作身份验证** 并在 **密钥** 字段中输入`你的 VPN IPsec PSK`。 1. 单击 **确定** 关闭 **高级设置**。 1. 单击 **确定** 保存 VPN 连接的详细信息。 -要连接到 VPN: 单击系统托盘中的无线/网络图标,选择新的 VPN 连接,然后单击 **连接**。如果出现提示,在登录窗口中输入 `你的 VPN 用户名` 和 `密码` ,并单击 **确定**。最后你可以到这里检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 +**注:** 在首次连接之前需要[修改一次注册表](#windows-错误-809),以解决 VPN 服务器 和/或 客户端与 NAT (比如家用路由器)的兼容问题。 - -如果在连接过程中遇到错误,请参见 故障排除。 +要连接到 VPN:单击系统托盘中的无线/网络图标,选择新的 VPN 连接,然后单击 **连接**。如果出现提示,在登录窗口中输入 `你的 VPN 用户名` 和 `密码` ,并单击 **确定**。最后你可以到 [这里](https://www.ipchicken.com) 检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 -**注:** 在首次连接之前需要修改一次注册表,以解决 VPN 服务器 和/或 客户端与 NAT (比如家用路由器)的兼容问题。请参照链接网页中的说明,或者打开提升权限命令提示符并运行以下命令。完成后必须重启计算机。 -- 适用于 Windows Vista, 7, 8 和 10 - ```console - REG ADD HKLM\SYSTEM\CurrentControlSet\Services\PolicyAgent /v AssumeUDPEncapsulationContextOnSendRule /t REG_DWORD /d 0x2 /f - ``` +如果在连接过程中遇到错误,请参见 [故障排除](#ikev1-故障排除)。 -- 仅适用于 Windows XP - ```console - REG ADD HKLM\SYSTEM\CurrentControlSet\Services\IPSec /v AssumeUDPEncapsulationContextOnSendRule /t REG_DWORD /d 0x2 /f - ``` +## 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) 模式连接。 -### OS X ### 1. 打开系统偏好设置并转到网络部分。 1. 在窗口左下角单击 **+** 按钮。 1. 从 **接口** 下拉菜单选择 **VPN**。 @@ -87,25 +146,39 @@ 1. 单击 **创建**。 1. 在 **服务器地址** 字段中输入`你的 VPN 服务器 IP`。 1. 在 **帐户名称** 字段中输入`你的 VPN 用户名`。 -1. 单击 **鉴定设置** 按钮。 -1. 在 **用户鉴定** 部分,选择 **密码** 单选按钮,然后输入`你的 VPN 密码`。 -1. 在 **机器鉴定** 部分,选择 **共享的密钥** 单选按钮,然后输入`你的 VPN IPsec PSK`。 +1. 单击 **认证设置** 按钮。 +1. 在 **用户认证** 部分,选择 **密码** 单选按钮,然后输入`你的 VPN 密码`。 +1. 在 **机器认证** 部分,选择 **共享的密钥** 单选按钮,然后输入`你的 VPN IPsec PSK`。 +1. 保持 **群组名称** 字段空白。 1. 单击 **好**。 1. 选中 **在菜单栏中显示 VPN 状态** 复选框。 -1. 单击 **高级** 按钮,并选中 **通过VPN连接发送所有通信** 复选框。 -1. 单击 **TCP/IP** 选项卡,并在 **配置IPv6** 部分中选择 **仅本地链接**。 -1. 单击 **好** 关闭高级设置,然后单击 **应用** 保存VPN连接信息。 +1. **(重要)** 单击 **高级** 按钮,并选中 **通过VPN连接发送所有通信** 复选框。 +1. **(重要)** 单击 **TCP/IP** 选项卡,并在 **配置IPv6** 部分中选择 **仅本地链接**。 +1. 单击 **好** 关闭高级设置,然后单击 **应用** 保存 VPN 连接信息。 + +要连接到 VPN:使用菜单栏中的图标,或者打开系统偏好设置的网络部分,选择 VPN 并单击 **连接**。最后你可以到 [这里](https://www.ipchicken.com) 检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 -要连接到 VPN,你可以使用菜单栏中的 VPN 图标,或者在系统偏好设置的网络部分选择 VPN,并单击 **连接**。最后你可以到这里检测你的 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 设备上进行以下步骤: -### Android ### 1. 启动 **设置** 应用程序。 -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连接。 @@ -114,11 +187,14 @@ 1. 选中 **保存帐户信息** 复选框。 1. 单击 **连接**。 -**注:** Android 6 (Marshmallow) 用户需要编辑 VPN 服务器上的 `/etc/ipsec.conf`,并在 `ike=` 和 `phase2alg=` 两行结尾添加 `,aes256-sha2_256` 字样。然后在它们下面添加一行 `sha2-truncbug=yes`。每行开头必须空两格。保存修改并运行 `service ipsec restart`。(更多信息) +连接成功后,会在通知栏显示图标。最后你可以到 [这里](https://www.ipchicken.com) 检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 + +如果在连接过程中遇到错误,请参见 [故障排除](#ikev1-故障排除)。 -VPN 连接成功后,会在通知栏显示图标。最后你可以到这里检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 +## iOS + +> 你也可以使用 [IKEv2](ikev2-howto-zh.md)(推荐)或者 [IPsec/XAuth](clients-xauth-zh.md) 模式连接。 -### iOS ### 1. 进入设置 -> 通用 -> VPN。 1. 单击 **添加VPN配置...**。 1. 单击 **类型** 。选择 **L2TP** 并返回。 @@ -128,62 +204,450 @@ VPN 连接成功后,会在通知栏显示图标。最后你可以到这里检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 +连接成功后,会在通知栏显示图标。最后你可以到 [这里](https://www.ipchicken.com) 检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 -### Chromebook ### -1. 如果你尚未登录 Chromebook,请先登录。 -1. 单击状态区(其中显示你的帐户头像)。 -1. 单击 **设置**。 -1. 在 **互联网连接** 部分,单击 **添加连接**。 -1. 单击 **添加 OpenVPN / L2TP**。 -1. 在 **服务器主机名** 字段中输入`你的 VPN 服务器 IP`。 +如果在连接过程中遇到错误,请参见 [故障排除](#ikev1-故障排除)。 + +## Chrome OS + +> 你也可以使用 [IKEv2](ikev2-howto-zh.md) 模式连接(推荐)。 + +1. 进入设置 -> 网络。 +1. 单击 **添加连接**,然后单击 **添加内置 VPN**。 1. 在 **服务名称** 字段中输入任意内容。 -1. 在 **供应商类型** 下拉菜单选择 **L2TP/IPsec + 预共享密钥**。 -1. 在 **预共享密钥** 字段中输入`你的 VPN IPsec PSK`。 +1. 在 **提供商类型** 下拉菜单选择 **L2TP/IPsec**。 +1. 在 **服务器主机名** 字段中输入`你的 VPN 服务器 IP`。 +1. 在 **身份验证类型** 下拉菜单选择 **预共享密钥**。 1. 在 **用户名** 字段中输入`你的 VPN 用户名`。 1. 在 **密码** 字段中输入`你的 VPN 密码`。 +1. 在 **预共享密钥** 字段中输入`你的 VPN IPsec PSK`。 +1. 保持其他字段空白。 +1. 启用 **保存身份信息和密码**。 1. 单击 **连接**。 -VPN 连接成功后,网络状态图标上会出现 VPN 指示。最后你可以到这里检测你的 IP 地址,应该显示为`你的 VPN 服务器 IP`。 +连接成功后,网络状态图标上会出现 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 -> 无法建立计算机与 VPN 服务器之间的网络连接,因为远程服务器未响应。 +> 错误 809:无法建立计算机与 VPN 服务器之间的网络连接,因为远程服务器未响应。这可能是因为未将计算机与远程服务器之间的某种网络设备(如防火墙、NAT、路由器等)配置为允许 VPN 连接。请与管理员或服务提供商联系以确定哪种设备可能产生此问题。 -要解决此错误,请按照上面的步骤添加注册表键并重启计算机。 +**注:** 仅当你使用 IPsec/L2TP 模式连接到 VPN 时,才需要进行下面的注册表更改。对于 [IKEv2](ikev2-howto-zh.md) 和 [IPsec/XAuth](clients-xauth-zh.md) 模式,**不需要** 进行此更改。 -### Windows 错误 628 +要解决此错误,在首次连接之前需要修改一次注册表,以解决 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 + ``` -1. 右键单击系统托盘中的无线/网络图标,选择 **打开网络与共享中心**。 -1. 单击左侧的 **更改适配器设置**。右键单击新的 VPN 连接,并选择 **属性**。 +另外,某些个别的 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)" 复选框,并且取消选中所有其它项。 +1. 单击 **允许使用这些协议**。选中 "质询握手身份验证协议 (CHAP)" 和 "Microsoft CHAP 版本 2 (MS-CHAP v2)" 复选框。 +1. 单击 **高级设置** 按钮。 +1. 单击 **使用预共享密钥作身份验证** 并在 **密钥** 字段中输入`你的 VPN IPsec PSK`。 +1. 单击 **确定** 关闭 **高级设置**。 1. 单击 **确定** 保存 VPN 连接的详细信息。 -![Select only CHAP in VPN connection properties-2](https://cloud.githubusercontent.com/assets/5104323/16026263/cbda945a-3192-11e6-96a6-ff18c5dd9a48.png) +### 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,可以另外尝试 [OpenVPN](https://github.com/hwdsl2/openvpn-install/blob/master/README-zh.md) 或 [WireGuard](https://github.com/hwdsl2/wireguard-install/blob/master/README-zh.md)。 -本文档是在 Streisand 项目文档基础上翻译和修改。该项目由 Joshua Lund 和其他开发者维护。 +### 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 Lin Song -基于 Joshua Lund 的工作 (版权所有 2014-2016) +注: 这个协议仅适用于本文档。 + +版权所有 (C) 2016-2024 [Lin Song](https://github.com/hwdsl2) [![View my profile on LinkedIn](https://static.licdn.com/scds/common/u/img/webpromo/btn_viewmy_160x25.png)](https://www.linkedin.com/in/linsongui) +受到 [Joshua Lund 的工作](https://github.com/StreisandEffect/streisand/blob/6aa6b6b2735dd829ca8c417d72eb2768a89b6639/playbooks/roles/l2tp-ipsec/templates/instructions.md.j2) 的启发 -本程序为自由软件,在自由软件联盟发布的 GNU 通用公共许可协议的约束下,你可以对其进行再发布及修改。协议版本为第三版或(随你)更新的版本。 +本程序为自由软件,在自由软件联盟发布的[ GNU 通用公共许可协议](https://www.gnu.org/licenses/gpl.html)的约束下,你可以对其进行再发布及修改。协议版本为第三版或(随你)更新的版本。 我们希望发布的这款程序有用,但不保证,甚至不保证它有经济价值和适合特定用途。详情参见GNU通用公共许可协议。 diff --git a/docs/clients.md b/docs/clients.md index 0fb5baf2f1..47e30b6f9b 100644 --- a/docs/clients.md +++ b/docs/clients.md @@ -1,42 +1,81 @@ -## Configure IPsec/L2TP VPN Clients +[English](clients.md) | [中文](clients-zh.md) -*Read this in other languages: [English](clients.md), [简体中文](clients-zh.md).* +# Configure IPsec/L2TP VPN Clients -*To connect using IPsec/XAuth ("Cisco IPsec") mode, see: [Configure IPsec/XAuth VPN Clients](clients-xauth.md)* - -After setting up your own VPN server, 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. +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](#os-x) + * [OS X (macOS)](#os-x-macos) * [Android](#android) - * [iOS](#ios) - * [Chromebook](#chromebook) + * [iOS (iPhone/iPad)](#ios) + * [Chrome OS (Chromebook)](#chrome-os) + * [Linux](#linux) +* [IKEv1 troubleshooting](#ikev1-troubleshooting) + +## Windows -### Windows ### +> You may also connect using [IKEv2](ikev2-howto.md) mode (recommended). -**Windows 10 and 8.x:** +### Windows 11 1. Right-click on the wireless/network icon in your system tray. -1. Select **Open Network and Sharing Center**. +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. Right-click on the wireless/network icon in your system tray, select **Open Network and Sharing Center**. -1. On the left, click **Change adapter settings**. Right-click on the new VPN entry and choose **Properties**. +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**. Select "Challenge Handshake Authentication Protocol (CHAP)" and deselect all others. +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:** A one-time registry change is required before connecting. See notes below. +**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`". -**Windows 7, Vista and XP:** +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. @@ -52,33 +91,53 @@ After settin 1. Enter `Your VPN Password` in the **Password** field. 1. Check the **Remember this password** checkbox. 1. Click **Create**, and then **Close**. -1. Repeat steps 1-3 above to open **Network and Sharing Center**. -1. On the left, click **Change adapter settings**. Right-click on the new VPN entry and choose **Properties**. +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**. Select "Challenge Handshake Authentication Protocol (CHAP)" and deselect all others. +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. -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. It should say "Your public IP address is `Your VPN Server IP`". +**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). - -If you get an error when trying to connect, see Troubleshooting. +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`". -**Note:** This one-time registry change is required if the VPN server and/or client is behind NAT (e.g. home router). Refer to the linked web page, or run the following from an elevated command prompt. You must reboot your computer when finished. -- For Windows Vista, 7, 8 and 10 - ```console - REG ADD HKLM\SYSTEM\CurrentControlSet\Services\PolicyAgent /v AssumeUDPEncapsulationContextOnSendRule /t REG_DWORD /d 0x2 /f - ``` +If you get an error when trying to connect, see [Troubleshooting](#ikev1-troubleshooting). -- For Windows XP ONLY - ```console - REG ADD HKLM\SYSTEM\CurrentControlSet\Services\IPSec /v AssumeUDPEncapsulationContextOnSendRule /t REG_DWORD /d 0x2 /f - ``` +## 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. -### OS X ### 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. @@ -92,20 +151,33 @@ If you get an error when trying to connect, see Troub 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. Click the **Advanced** button and make sure the **Send all traffic over VPN connection** checkbox is selected. -1. Click the **TCP/IP** tab, and make sure **Link-local only** is selected in the **Configure IPv6** section. +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. -You can connect to the VPN using the VPN icon in the menu bar, or by selecting the VPN in the Network section of System Preferences and choosing **Connect**. You can verify that your traffic is being routed properly by looking up your IP address on Google. It should say "Your public IP address is `Your VPN Server IP`". +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: -### Android ### 1. Launch the **Settings** application. -1. Tap **More...** in the **Wireless & Networks** section. +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. @@ -114,11 +186,14 @@ You can connect to the VPN using the VPN icon in the menu bar, or by selecting t 1. Check the **Save account information** checkbox. 1. Tap **Connect**. -**Note:** Android 6 (Marshmallow) users should edit `/etc/ipsec.conf` on the VPN server and append `,aes256-sha2_256` to both `ike=` and `phase2alg=` lines. Then add a new line `sha2-truncbug=yes` immediately after those. Indent lines with two spaces. When finished, run `service ipsec restart`. (Reference) +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 -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. It should say "Your public IP address is `Your VPN Server IP`". +> You may also connect using [IKEv2](ikev2-howto.md) (recommended) or [IPsec/XAuth](clients-xauth.md) mode. -### iOS ### 1. Go to Settings -> General -> VPN. 1. Tap **Add VPN Configuration...**. 1. Tap **Type**. Select **L2TP** and go back. @@ -131,59 +206,446 @@ Once connected, you will see a VPN icon in the notification bar. You can verify 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. It should say "Your public IP address is `Your VPN Server IP`". +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`". -### Chromebook ### -1. If you haven't already, sign in to your Chromebook. -1. Click the status area, where your account picture appears. -1. Click **Settings**. -1. In the **Internet connection** section, click **Add connection**. -1. Click **Add OpenVPN / L2TP**. -1. Enter `Your VPN Server IP` for the **Server hostname**. +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. Make sure **Provider type** is **L2TP/IPSec + pre-shared key**. -1. Enter `Your VPN IPsec PSK` for the **Pre-shared key**. +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. It should say "Your public IP address is `Your VPN Server IP`". +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 +``` -## Troubleshooting +Find this line in the output: `default via X.X.X.X ...`. Write down this gateway IP for use in the two commands below. -### Windows Error 809 +Exclude your VPN server's public IP from the new default route (replace with actual value): -> The network connection between your computer and the VPN server could not be established because the remote server is not responding. +```bash +route add YOUR_VPN_SERVER_PUBLIC_IP gw X.X.X.X +``` -To fix this error, follow the steps above to add a registry key and reboot your computer. +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)): -### Windows Error 628 +```bash +route add YOUR_LOCAL_PC_PUBLIC_IP gw X.X.X.X +``` -> The connection was terminated by the remote computer before it could be completed. +Add a new default route to start routing traffic via the VPN server: -To fix this error, please follow these steps: +```bash +route add default dev ppp0 +``` -1. Right-click on the wireless/network icon in system tray, select **Open Network and Sharing Center**. -1. On the left, click **Change adapter settings**. Right-click on the new VPN and choose **Properties**. +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**. Select the "Challenge Handshake Authentication Protocol (CHAP)" checkbox, and deselect all others. +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. -![Select only CHAP in VPN connection properties](https://cloud.githubusercontent.com/assets/5104323/16024310/b113e9b6-3186-11e6-9e03-12f5455487ba.png) +### 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. -### Other Errors +### Windows DNS leaks and IPv6 -Please refer to this document for more troubleshooting tips. +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. -## Credits +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 a VPN with IPv6 support, you could instead try [OpenVPN](https://github.com/hwdsl2/openvpn-install) or [WireGuard](https://github.com/hwdsl2/wireguard-install). -This document was adapted from the Streisand project by Joshua Lund and contributors. +### 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 -Copyright (C) 2016 Lin Song -Based on the work of Joshua Lund (Copyright 2014-2016) +Note: This license applies to this document only. + +Copyright (C) 2016-2024 [Lin Song](https://github.com/hwdsl2) [![View my profile on LinkedIn](https://static.licdn.com/scds/common/u/img/webpromo/btn_viewmy_160x25.png)](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 as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +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. diff --git a/docs/ikev2-howto-zh.md b/docs/ikev2-howto-zh.md new file mode 100644 index 0000000000..820147cc7b --- /dev/null +++ b/docs/ikev2-howto-zh.md @@ -0,0 +1,1285 @@ +[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-故障排除)。 + +#### 手动导入配置 + +[[支持者] **屏幕录影:** 在 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. 按 Win+R 或在开始菜单中搜索 `mmc` 打开 *Microsoft Management Console*。 + + 1. 在 `File - Add/Remove Snap-In` 的窗口中,选择添加 `Certificates` 并在弹出的窗口中选择 `Computer account -> Local Computer`。点击 `Finish -> OK` 以保存设置。 + + 1. 在 `Certificates - Personal - Certificates` 中删除 IKEv2 客户端证书。该证书的名称与你指定的 IKEv2 客户端名称一致,默认为 `vpnclient`,该证书由 `IKEv2 VPN CA` 颁发。 + + 1. 在 `Certificates - Trusted Root Certification Authorities - Certificates` 中删除 IKEv2 VPN CA 证书。该证书是由 `IKEv2 VPN CA` 颁发的,颁发给 `IKEv2 VPN CA` 的证书。需要注意,删除这一步的证书时,`Certificates - Personal - Certificates` 中应不存在其他由 `IKEv2 VPN CA` 颁发的证书。 + +1. (可选,适用于手动创建了 VPN 连接的用户)还原注册表配置。注意,在编辑注册表前应备份。 + + 1. 按 Win+R 或在开始菜单中搜索 `regedit` 打开 *Registry Editor*。 + + 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: 搭建自己的 IPsec VPN, OpenVPN 和 WireGuard 服务器](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: 搭建自己的 IPsec VPN, OpenVPN 和 WireGuard 服务器](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 标识符** 字段中输入任意内容(例如 `empty`)。 + **注:** 该字段不应该为必填。它是 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)。如果你遇到错误 `Could not find source connection`,编辑 `/etc/netplan/01-netcfg.yaml` 并将 `renderer: networkd` 替换为 `renderer: NetworkManager`,然后运行 `sudo netplan apply`。要连接到 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` 文件安全地传送到你的计算机。 + +
+ + 单击查看屏幕录影。 + + + ![routeros get certificate](images/routeros-get-cert.gif) +
+ +2. 在 WinBox 中,转到 System > certificates > import. 将 `.p12` 证书文件导入两次(是的,导入同一个文件两次)。检查你的 certificates panel。你应该看到 2 个文件,其中标注 KT 的是密钥。 + +
+ + 单击查看屏幕录影。 + + + ![routeros import certificate](images/routeros-import-cert.gif) +
+ + 或者,你也可以使用终端命令 (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-2024 [Lin Song](https://github.com/hwdsl2) [![View my profile on LinkedIn](https://static.licdn.com/scds/common/u/img/webpromo/btn_viewmy_160x25.png)](https://www.linkedin.com/in/linsongui) + +[![Creative Commons License](https://i.creativecommons.org/l/by-sa/3.0/88x31.png)](http://creativecommons.org/licenses/by-sa/3.0/) +这个项目是以 [知识共享署名-相同方式共享3.0](http://creativecommons.org/licenses/by-sa/3.0/) 许可协议授权。 +必须署名: 请包括我的名字在任何衍生产品,并且让我知道你是如何改善它的! diff --git a/docs/ikev2-howto.md b/docs/ikev2-howto.md new file mode 100644 index 0000000000..c93fc68650 --- /dev/null +++ b/docs/ikev2-howto.md @@ -0,0 +1,1287 @@ +[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). + +#### 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. Press Win+R, or search for `mmc` in the Start Menu. Open *Microsoft Management Console*. + + 1. 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 (e.g. `empty`) in the **IPSec identifier** field. + **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: + +```bash +# Ubuntu and Debian +sudo apt-get update +sudo apt-get install network-manager-strongswan + +# Arch Linux +sudo pacman -Syu # upgrade all packages +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 +``` + +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 +``` + +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. + +Alternatively, you may connect using the command line. See [#1399](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1399) and [#1007](https://github.com/hwdsl2/setup-ipsec-vpn/issues/1007) 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`. 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. + + + ![routeros get certificate](images/routeros-get-cert.gif) +
+ +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. + + + ![routeros import certificate](images/routeros-import-cert.gif) +
+ + 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-2024 [Lin Song](https://github.com/hwdsl2) [![View my profile on LinkedIn](https://static.licdn.com/scds/common/u/img/webpromo/btn_viewmy_160x25.png)](https://www.linkedin.com/in/linsongui) + +[![Creative Commons License](https://i.creativecommons.org/l/by-sa/3.0/88x31.png)](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! diff --git a/docs/images/aws-deploy-button.png b/docs/images/aws-deploy-button.png new file mode 100644 index 0000000000..f945c85764 Binary files /dev/null and b/docs/images/aws-deploy-button.png differ diff --git a/docs/images/azure-deploy-button.png b/docs/images/azure-deploy-button.png new file mode 100644 index 0000000000..e72828991e Binary files /dev/null and b/docs/images/azure-deploy-button.png differ diff --git a/docs/images/badges/docker-pulls.svg b/docs/images/badges/docker-pulls.svg new file mode 100644 index 0000000000..af15b7784d --- /dev/null +++ b/docs/images/badges/docker-pulls.svg @@ -0,0 +1 @@ +docker pulls: 32Mdocker pulls32M diff --git a/docs/images/badges/docker-stars.svg b/docs/images/badges/docker-stars.svg new file mode 100644 index 0000000000..dc47ec1115 --- /dev/null +++ b/docs/images/badges/docker-stars.svg @@ -0,0 +1 @@ +docker stars: 495docker stars495 diff --git a/docs/images/badges/github-stars.svg b/docs/images/badges/github-stars.svg new file mode 100644 index 0000000000..987e24e4c3 --- /dev/null +++ b/docs/images/badges/github-stars.svg @@ -0,0 +1 @@ +stars25k diff --git a/docs/images/do-install-button.png b/docs/images/do-install-button.png new file mode 100644 index 0000000000..34206e00dc Binary files /dev/null and b/docs/images/do-install-button.png differ diff --git a/docs/images/linode-deploy-button.png b/docs/images/linode-deploy-button.png new file mode 100644 index 0000000000..aa6f059b17 Binary files /dev/null and b/docs/images/linode-deploy-button.png differ diff --git a/docs/images/routeros-get-cert.gif b/docs/images/routeros-get-cert.gif new file mode 100644 index 0000000000..dcdc0dc727 Binary files /dev/null and b/docs/images/routeros-get-cert.gif differ diff --git a/docs/images/routeros-import-cert.gif b/docs/images/routeros-import-cert.gif new file mode 100644 index 0000000000..4dc12559d0 Binary files /dev/null and b/docs/images/routeros-import-cert.gif differ diff --git a/docs/images/script-demo.svg b/docs/images/script-demo.svg new file mode 100644 index 0000000000..9569b815a8 --- /dev/null +++ b/docs/images/script-demo.svg @@ -0,0 +1 @@ +##VPNcredentialsnotsetbyuser.GeneratingrandomPSKandpassword...##VPNsetupinprogress...Pleasebepatient.##Installingpackagesrequiredforsetup...+apt-get-yqqupdate+apt-get-yqqinstallwgetdnsutilsopenssliptablesiproute2gawkgrepsednet-tools##InstallingpackagesrequiredfortheVPN...+apt-get-yqqinstalllibnss3-devlibnspr4-devpkg-configlibpam0g-devlibcap-ng-devlibcap-ng-utilslibselinux1-devlibcurl4-nss-devflexbisongccmakelibnss3-toolslibevent-devlibsystemd-devuuid-runtimepppxl2tpd##InstallingFail2BantoprotectSSH...+apt-get-yqqinstallfail2ban##Downloadinghelperscripts...+ikev2.shaddvpnuser.shdelvpnuser.sh##DownloadingLibreswan...+wget-t3-T30-q-Olibreswan-4.7.tar.gzhttps://github.com/libreswan/libreswan/archive/v4.7.tar.gz##CompilingandinstallingLibreswan,pleasewait...+make-j2-sbase+make-sinstall-base##CreatingVPNconfiguration...##Updatingsysctlsettings...##UpdatingIPTablesrules...##Enablingservicesonboot...##Startingservices...================================================IPsecVPNserverisnowreadyforuse!ConnecttoyournewVPNwiththesedetails:ServerIP:192.0.2.1IPsecPSK:DEMO_ONLY_DO_NOT_USEUsername:vpnuserPassword:DEMO_ONLY_DO_NOT_USEWritethesedown.You'llneedthemtoconnect!VPNclientsetup:https://vpnsetup.net/clients##StartingIKEv2setupinautomode,usingdefaultoptions.IKEv2setupsuccessful.DetailsforIKEv2mode:VPNserveraddress:192.0.2.1VPNclientname:vpnclientClientconfigurationisavailableat:/root/vpnclient.p12(forWindows&Linux)/root/vpnclient.sswan(forAndroid)/root/vpnclient.mobileconfig(foriOS&macOS)Nextsteps:ConfigureIKEv2clients.See:https://vpnsetup.net/clients++ikev2.sh+ikev2.shaddvpnuser.sh##CheckingforMOBIKEsupport...notavailable##GeneratingCAandservercertificates...##Generatingclientcertificate...##Creatingclientconfiguration...##AddinganewIKEv2connection...##RestartingIPsecservice... diff --git a/docs/manage-users-zh.md b/docs/manage-users-zh.md index 0f80c0554b..d8451b2789 100644 --- a/docs/manage-users-zh.md +++ b/docs/manage-users-zh.md @@ -1,43 +1,185 @@ -## 管理 VPN 用户 +[English](manage-users.md) | [中文](manage-users-zh.md) -*其他语言版本: [English](manage-users.md), [简体中文](manage-users-zh.md).* +# 管理 VPN 用户 -在默认情况下,将只创建一个用于 VPN 登录的用户账户。如果你需要添加,编辑或者删除用户,请阅读本文档。 +在默认情况下,将只创建一个用于 VPN 登录的用户账户。如果你需要查看或管理 IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式的用户,请阅读本文档。对于 IKEv2,参见 [管理 IKEv2 客户端](ikev2-howto-zh.md#管理-ikev2-客户端)。 -首先,IPsec PSK (预共享密钥) 保存在文件 `/etc/ipsec.secrets`。如果要更换一个新的 PSK,可以编辑此文件。 +* [使用辅助脚本管理 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 - %any : PSK "" +sudo addvpnuser.sh ``` -对于 `IPsec/L2TP`,VPN 用户账户信息保存在文件 `/etc/ppp/chap-secrets`。该文件的格式如下: +
+ +错误:"sudo: addvpnuser.sh: command not found". + + +如果你使用了较早版本的 VPN 安装脚本,这是正常的。首先下载辅助脚本: ```bash -"" l2tpd "" * -"" l2tpd "" * -... ... +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 ``` -你可以添加更多用户,每个用户对应文件中的一行。**不要**在用户名,密码或 PSK 中使用这些字符:`\ " '` +**重要:** 这个脚本会将你当前 **所有的 VPN 用户** 移除并替换为你指定的列表中的用户。如果你需要保留已有的 VPN 用户,则必须将它们包含在下面的变量中。 + +要使用这个脚本,从以下选项中选择一个: -对于 `IPsec/XAuth ("Cisco IPsec")`, VPN 用户账户信息保存在文件 `/etc/ipsec.d/passwd`。该文件的格式如下: +**选项 1:** 编辑脚本并输入 VPN 用户信息: ```bash -::xauth-psk -::xauth-psk +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" * ... ... ``` -这个文件中的密码以 salted and hashed 的形式保存。该步骤可以借助比如 `openssl` 工具来完成: +对于 IPsec/XAuth ("Cisco IPsec"),VPN 用户信息保存在文件 `/etc/ipsec.d/passwd`。这个文件中的密码以加盐哈希值的形式保存。更多详情请见 [手动管理 VPN 用户](#手动管理-vpn-用户)。 + +## 查看或更改 IPsec PSK + +IPsec PSK(预共享密钥)保存在文件 `/etc/ipsec.secrets`。所有的 VPN 用户将共享同一个 IPsec PSK。该文件的格式如下: ```bash -# 以下命令的输出为 -openssl passwd -1 "" +%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-2024 [Lin Song](https://github.com/hwdsl2) [![View my profile on LinkedIn](https://static.licdn.com/scds/common/u/img/webpromo/btn_viewmy_160x25.png)](https://www.linkedin.com/in/linsongui) + +[![Creative Commons License](https://i.creativecommons.org/l/by-sa/3.0/88x31.png)](http://creativecommons.org/licenses/by-sa/3.0/) +这个项目是以 [知识共享署名-相同方式共享3.0](http://creativecommons.org/licenses/by-sa/3.0/) 许可协议授权。 +必须署名: 请包括我的名字在任何衍生产品,并且让我知道你是如何改善它的! diff --git a/docs/manage-users.md b/docs/manage-users.md index 55d7fba42f..9aca41a78c 100644 --- a/docs/manage-users.md +++ b/docs/manage-users.md @@ -1,43 +1,185 @@ -## Manage VPN Users +[English](manage-users.md) | [中文](manage-users-zh.md) -*Read this in other languages: [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 add, edit or remove users, read this document. +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). -First, the IPsec PSK (pre-shared key) is stored in `/etc/ipsec.secrets`. To change to a new PSK, just edit this file. +* [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 - %any : PSK "" +sudo addvpnuser.sh ``` -For `IPsec/L2TP`, VPN users are specified in `/etc/ppp/chap-secrets`. The format of this file is: +
+ +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 -"" l2tpd "" * -"" l2tpd "" * -... ... +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 ``` -You can add more users, use one line for each user. DO NOT use these characters within values: `\ " '` +**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. -For `IPsec/XAuth ("Cisco IPsec")`, VPN users are specified in `/etc/ipsec.d/passwd`. The format of this file is: +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 -::xauth-psk -::xauth-psk +"username1" l2tpd "password1" * +"username2" l2tpd "password2" * ... ... ``` -Passwords in this file are salted and hashed. This step can be done using e.g. the `openssl` utility: +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 -# The output will be -openssl passwd -1 "" +%any %any : PSK "your_ipsec_pre_shared_key" ``` -When finished making changes, run these commands or reboot your server. +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-2024 [Lin Song](https://github.com/hwdsl2) [![View my profile on LinkedIn](https://static.licdn.com/scds/common/u/img/webpromo/btn_viewmy_160x25.png)](https://www.linkedin.com/in/linsongui) + +[![Creative Commons License](https://i.creativecommons.org/l/by-sa/3.0/88x31.png)](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! diff --git a/docs/uninstall-zh.md b/docs/uninstall-zh.md index 05788c5aa8..dc711ae775 100644 --- a/docs/uninstall-zh.md +++ b/docs/uninstall-zh.md @@ -1,10 +1,46 @@ -# 卸载 VPN +[English](uninstall.md) | [中文](uninstall-zh.md) -*其他语言版本: [English](uninstall.md), [简体中文](uninstall-zh.md).* +# 卸载 VPN -按照以下步骤移除 VPN。这些命令需要用 `root` 账户运行,或者使用 `sudo`。 +* [使用辅助脚本卸载 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 将被移除。此操作**不可撤销**! + +### 步骤 * [第一步](#第一步) * [第二步](#第二步) @@ -13,47 +49,51 @@ * [可选步骤](#可选步骤) * [完成后](#完成后) -## 第一步 +### 第一步 -``` +```bash service ipsec stop service xl2tpd stop -rm -rf /usr/local/sbin/ipsec /usr/local/libexec/ipsec -rm -f /etc/init/ipsec.conf /lib/systemd/system/ipsec.service \ - /etc/init.d/ipsec /usr/lib/systemd/system/ipsec.service +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 +#### Ubuntu & Debian `apt-get purge xl2tpd` -### CentOS/RHEL +#### CentOS/RHEL, Rocky Linux, AlmaLinux, Oracle Linux & Amazon Linux 2 `yum remove xl2tpd` -## 第三步 +#### Alpine Linux + +`apk del xl2tpd` + +### 第三步 + +#### Ubuntu, Debian & Alpine Linux -### Ubuntu/Debian +编辑 `/etc/iptables.rules` 并删除不需要的规则。你之前的防火墙规则(如果有)备份在 `/etc/iptables.rules.old-日期-时间`。另外如果文件 `/etc/iptables/rules.v4` 存在,请编辑它。 -编辑 `/etc/iptables.rules` 并删除不需要的规则。 -你以前的防火墙规则(如果有)会备份在 `/etc/iptables.rules.old-日期-时间`。 -另外如果文件 `/etc/iptables/rules.v4` 存在,请编辑它。 +#### CentOS/RHEL, Rocky Linux, AlmaLinux, Oracle Linux & Amazon Linux 2 -### CentOS/RHEL +编辑 `/etc/sysconfig/iptables` 并删除不需要的规则。你之前的防火墙规则(如果有)备份在 `/etc/sysconfig/iptables.old-日期-时间`。 -编辑 `/etc/sysconfig/iptables` 并删除不需要的规则。 -你以前的防火墙规则(如果有)会备份在 `/etc/sysconfig/iptables.old-日期-时间`。 +**注:** 如果使用 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` (如果有)。 -## 可选步骤 +### 可选步骤 -注: 这一步是可选的。 +**注:** 这一步是可选的。 删除这些配置文件: @@ -69,12 +109,42 @@ rm -f /etc/init/ipsec.conf /lib/systemd/system/ipsec.service \ 要快速删除,可以复制并粘贴以下命令: -``` +```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-2024 [Lin Song](https://github.com/hwdsl2) [![View my profile on LinkedIn](https://static.licdn.com/scds/common/u/img/webpromo/btn_viewmy_160x25.png)](https://www.linkedin.com/in/linsongui) + +[![Creative Commons License](https://i.creativecommons.org/l/by-sa/3.0/88x31.png)](http://creativecommons.org/licenses/by-sa/3.0/) +这个项目是以 [知识共享署名-相同方式共享3.0](http://creativecommons.org/licenses/by-sa/3.0/) 许可协议授权。 +必须署名: 请包括我的名字在任何衍生产品,并且让我知道你是如何改善它的! diff --git a/docs/uninstall.md b/docs/uninstall.md index 9da7f2990f..aa713b1bfe 100644 --- a/docs/uninstall.md +++ b/docs/uninstall.md @@ -1,10 +1,46 @@ -# Uninstall the VPN +[English](uninstall.md) | [中文](uninstall-zh.md) -*Read this in other languages: [English](uninstall.md), [简体中文](uninstall-zh.md).* +# Uninstall the VPN -Follow these steps to remove the VPN. Commands must be run as `root`, or with `sudo`. +* [Uninstall using helper script](#uninstall-using-helper-script) +* [Manually uninstall the VPN](#manually-uninstall-the-vpn) -## Steps +## 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) @@ -13,47 +49,51 @@ Follow these steps to remove the VPN. Commands must be run as `root`, or with `s * [Optional](#optional) * [When finished](#when-finished) -## First step +### First step -``` +```bash service ipsec stop service xl2tpd stop -rm -rf /usr/local/sbin/ipsec /usr/local/libexec/ipsec -rm -f /etc/init/ipsec.conf /lib/systemd/system/ipsec.service \ - /etc/init.d/ipsec /usr/lib/systemd/system/ipsec.service +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 +### Second step -### Ubuntu/Debian +#### Ubuntu & Debian `apt-get purge xl2tpd` -### CentOS/RHEL +#### CentOS/RHEL, Rocky Linux, AlmaLinux, Oracle Linux & Amazon Linux 2 `yum remove xl2tpd` -## Third step +#### Alpine Linux + +`apk del xl2tpd` + +### Third step + +#### Ubuntu, Debian & Alpine Linux -### Ubuntu/Debian +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. -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. +#### CentOS/RHEL, Rocky Linux, AlmaLinux, Oracle Linux & Amazon Linux 2 -### CentOS/RHEL +Edit `/etc/sysconfig/iptables` and remove unneeded rules. Your original rules (if any) are backed up as `/etc/sysconfig/iptables.old-date-time`. -Edit `/etc/sysconfig/iptables` and remove unneeded rules. -Your original rules (if any) are backed up as `/etc/sysconfig/iptables.old-date-time`. +**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 +### 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 +### Optional -Note: This step is optional. +**Note:** This step is optional. Remove these config files: @@ -69,12 +109,42 @@ Remove these config files: 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 ``` -## When finished +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-2024 [Lin Song](https://github.com/hwdsl2) [![View my profile on LinkedIn](https://static.licdn.com/scds/common/u/img/webpromo/btn_viewmy_160x25.png)](https://www.linkedin.com/in/linsongui) + +[![Creative Commons License](https://i.creativecommons.org/l/by-sa/3.0/88x31.png)](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! diff --git a/extras/add_vpn_user.sh b/extras/add_vpn_user.sh new file mode 100755 index 0000000000..ec27b31500 --- /dev/null +++ b/extras/add_vpn_user.sh @@ -0,0 +1,139 @@ +#!/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 +} + +confirm_or_abort() { + printf '%s' "$1" + read -r response + case $response in + [yY][eE][sS]|[yY]) + echo + ;; + *) + abort_and_exit + ;; + esac +} + +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=) + 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 diff --git a/extras/ikev2onlymode.sh b/extras/ikev2onlymode.sh new file mode 100755 index 0000000000..7e5ce8bcf8 --- /dev/null +++ b/extras/ikev2onlymode.sh @@ -0,0 +1,179 @@ +#!/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 + else + exiterr "This script only supports CentOS/RHEL 7-9." + 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) + if [ "$os_ver" != "3.19" ] && [ "$os_ver" != "3.20" ]; then + exiterr "This script only supports Alpine Linux 3.19/3.20." + fi + else + os_ver=$(sed 's/\..*//' /etc/debian_version | tr -dc 'A-Za-z0-9') + if [ "$os_ver" = 8 ] || [ "$os_ver" = 9 ] || [ "$os_ver" = "jessiesid" ] \ + || [ "$os_ver" = "bustersid" ]; 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-2024 Lin Song 28 Jul 2024 + +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=) + [ -z "$server_addr" ] && server_addr=$(grep -s "leftcert=" "$IPSEC_CONF" | cut -f2 -d=) + 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'} + 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 diff --git a/extras/update_vpn_users.sh b/extras/update_vpn_users.sh new file mode 100755 index 0000000000..02592e4b9f --- /dev/null +++ b/extras/update_vpn_users.sh @@ -0,0 +1,163 @@ +#!/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 <= 3.16) for Libreswan. -# This script provides a workaround by installing unofficial packages from download.libreswan.org. -# Debian 7 users: Run this script first, before using the VPN setup script. -# -# IMPORTANT: These unofficial packages do not receive the latest security updates compared to -# official Debian packages. They could contain unpatched vulnerabilities. Use at your own risk! -# -# Copyright (C) 2015-2016 Lin Song -# -# This program is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License 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. -# -# You should have received a copy of the GNU General Public License along with -# this program. If not, see http://www.gnu.org/licenses/. - -export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - -exiterr() { echo "Error: ${1}" >&2; exit 1; } - -if [ "$(sed 's/\..*//' /etc/debian_version 2>/dev/null)" != "7" ]; then - exiterr "This script only supports Debian 7 (Wheezy)." -fi - -if [ "$(uname -m)" != "x86_64" ]; then - exiterr "This script only supports 64-bit Debian 7." -fi - -if [ "$(id -u)" != 0 ]; then - exiterr "Script must be run as root. Try 'sudo sh $0'" -fi - -# Create and change to working dir -mkdir -p /opt/src -cd /opt/src || exiterr "Cannot enter /opt/src." - -# Update package index and install wget -export DEBIAN_FRONTEND=noninteractive -apt-get -yq update || exiterr "'apt-get update' failed." -apt-get -yq install wget || exiterr "Failed to install 'wget'." - -# Install libnss/libnspr packages from download.libreswan.org. -# Ref: https://libreswan.org/wiki/3.14_on_Debian_Wheezy -base_url=https://download.libreswan.org/binaries/debian/wheezy - -deb1=libnspr4_4.10.7-1_amd64.deb -deb2=libnspr4-dev_4.10.7-1_amd64.deb -deb3=libnss3_3.17.2-1.1_amd64.deb -deb4=libnss3-dev_3.17.2-1.1_amd64.deb -deb5=libnss3-tools_3.17.2-1.1_amd64.deb - -wget -t 3 -T 30 -nv -O "$deb1" "$base_url/$deb1" -wget -t 3 -T 30 -nv -O "$deb2" "$base_url/$deb2" -wget -t 3 -T 30 -nv -O "$deb3" "$base_url/$deb3" -wget -t 3 -T 30 -nv -O "$deb4" "$base_url/$deb4" -wget -t 3 -T 30 -nv -O "$deb5" "$base_url/$deb5" - -if [ -s "$deb1" ] && [ -s "$deb2" ] && [ -s "$deb3" ] && [ -s "$deb4" ] && [ -s "$deb5" ]; then - dpkg -i "$deb1" "$deb2" "$deb3" "$deb4" "$deb5" && /bin/rm -f "$deb1" "$deb2" "$deb3" "$deb4" "$deb5" - apt-get install -f - echo - echo 'Completed! If no error, you may now proceed to run the VPN setup script.' - exit 0 -else - /bin/rm -f "$deb1" "$deb2" "$deb3" "$deb4" "$deb5" - exiterr 'Could not download libnss/libnspr package(s).' -fi diff --git a/extras/vpnuninstall.sh b/extras/vpnuninstall.sh new file mode 100755 index 0000000000..6492c398ee --- /dev/null +++ b/extras/vpnuninstall.sh @@ -0,0 +1,358 @@ +#!/bin/bash +# +# Script to uninstall IPsec VPN +# +# 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-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; } +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)" "$rh_file"; then + exiterr "This script only supports CentOS/RHEL 7-9." + 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) + 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 + 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" ] || [ "$os_type" = "raspbian" ]; 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" ] || [ "$os_type" = "raspbian" ]; 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) + if [ "$line1" = "net.core.default_qdisc = fq" ] \ + && [ "$line2" = "net.ipv4.tcp_congestion_control = bbr" ]; then + count=19 + 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/,+4d' /etc/rc.local + else + sed --follow-symlinks -i '/# Added by hwdsl2 VPN script/,+4d' /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 '!' | sed 's/,%v4://') + xauthnet=$(printf '%s' "$vipr" | cut -f3 -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" = "raspbian" ] \ + || [ "$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" ] || [ "$os_type" = "raspbian" ]; then + if [ -f "$IPT_FILE2" ]; then + conf_bk "$IPT_FILE2" + /bin/cp -f "$IPT_FILE" "$IPT_FILE2" + fi + 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 diff --git a/extras/vpnupgrade.sh b/extras/vpnupgrade.sh old mode 100644 new mode 100755 index bbe5f0cd86..179dfa0527 --- a/extras/vpnupgrade.sh +++ b/extras/vpnupgrade.sh @@ -1,8 +1,12 @@ #!/bin/sh # -# Script to upgrade Libreswan on Ubuntu and Debian +# Script to update Libreswan on Ubuntu, Debian, CentOS/RHEL, Rocky Linux, +# AlmaLinux, Oracle Linux, Amazon Linux 2 and Alpine Linux # -# Copyright (C) 2016 Lin Song +# The latest version of this script is available at: +# https://github.com/hwdsl2/setup-ipsec-vpn +# +# Copyright (C) 2021-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/ @@ -10,132 +14,183 @@ # Attribution required: please include my name in any derivative and let me # know how you have improved it! -# Check for the latest version at https://libreswan.org and update as necessary -swan_ver=3.17 +# (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 +### DO NOT edit below this line ### export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" -exiterr() { echo "Error: ${1}" >&2; exit 1; } -exiterr2() { echo "Error: 'apt-get install' failed." >&2; exit 1; } - -os_type="$(lsb_release -si 2>/dev/null)" -if [ "$os_type" != "Ubuntu" ] && [ "$os_type" != "Debian" ]; then - exiterr "This script only supports Ubuntu/Debian." -fi - -if [ -f /proc/user_beancounters ]; then - exiterr "This script does not support OpenVZ VPS." -fi - -if [ "$(id -u)" != 0 ]; then - exiterr "Script must be run as root. Try 'sudo sh $0'" -fi - -if [ -z "$swan_ver" ]; then - exiterr "Libreswan version 'swan_ver' not specified." -fi - -/usr/local/sbin/ipsec --version 2>/dev/null | grep -qs "Libreswan" -if [ "$?" != "0" ]; then - exiterr "This script requires Libreswan already installed." -fi - -/usr/local/sbin/ipsec --version 2>/dev/null | grep -qs "Libreswan $swan_ver" -if [ "$?" = "0" ]; then - echo "You already have Libreswan version $swan_ver installed! " - echo "If you continue, the same version will be re-installed." - echo - printf "Do you wish to continue anyway? [y/N] " - read -r response - case $response in - [yY][eE][sS]|[yY]) - echo - ;; - *) - echo "Aborting." - exit 1 - ;; - esac -fi - -clear - -cat <&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 + else + exiterr "This script only supports CentOS/RHEL 7-9." + 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 - -if [ "$(sed 's/\..*//' /etc/debian_version 2>/dev/null)" = "7" ]; then -cat <<'EOF' -IMPORTANT: Workaround required for Debian 7 (Wheezy). -You must first run the script at: https://git.io/vpndeb7 -Continue only after completing this workaround. - + 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.19" ] && [ "$os_ver" != "3.20" ]; then + exiterr "This script only supports Alpine Linux 3.19/3.20." + fi + else + os_ver=$(sed 's/\..*//' /etc/debian_version | tr -dc 'A-Za-z0-9') + if [ "$os_ver" = 8 ] || [ "$os_ver" = 9 ] || [ "$os_ver" = "jessiesid" ] \ + || [ "$os_ver" = "bustersid" ]; 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 -fi - -printf "Do you wish to continue? [y/N] " -read -r response -case $response in - [yY][eE][sS]|[yY]) - echo - echo "Please be patient. Setup is continuing..." - echo - ;; - *) - echo "Aborting." exit 1 - ;; -esac - -# Create and change to working dir -mkdir -p /opt/src -cd /opt/src || exiterr "Cannot enter /opt/src." - -# Update package index and install Wget -export DEBIAN_FRONTEND=noninteractive -apt-get -yq update || exiterr "'apt-get update' failed." -apt-get -yq install wget || exiterr2 - -# Install necessary packages -apt-get -yq install libnss3-dev libnspr4-dev pkg-config libpam0g-dev \ - libcap-ng-dev libcap-ng-utils libselinux1-dev \ - libcurl4-nss-dev flex bison gcc make \ - libunbound-dev libnss3-tools libevent-dev || exiterr2 -apt-get -yq --no-install-recommends install xmlto || exiterr2 - -# Compile and install Libreswan -swan_file="libreswan-$swan_ver.tar.gz" -swan_url1="https://download.libreswan.org/$swan_file" -swan_url2="https://github.com/libreswan/libreswan/archive/v$swan_ver.tar.gz" -wget -t 3 -T 30 -nv -O "$swan_file" "$swan_url1" || wget -t 3 -T 30 -nv -O "$swan_file" "$swan_url2" -[ "$?" != "0" ] && exiterr "Cannot download Libreswan source." -/bin/rm -rf "/opt/src/libreswan-$swan_ver" -tar xzf "$swan_file" && /bin/rm -f "$swan_file" -cd "libreswan-$swan_ver" || exiterr "Cannot enter Libreswan source dir." -echo "WERROR_CFLAGS =" > Makefile.inc.local -if [ "$(packaging/utils/lswan_detect.sh init)" = "systemd" ]; then - apt-get -yq install libsystemd-dev || exiterr2 -fi -make -s programs && make -s install - -# Verify the install and clean up -cd /opt/src || exiterr "Cannot enter /opt/src." -/bin/rm -rf "/opt/src/libreswan-$swan_ver" -/usr/local/sbin/ipsec --version 2>/dev/null | grep -qs "$swan_ver" -[ "$?" != "0" ] && exiterr "Libreswan $swan_ver failed to build." - -# Restart IPsec service -service ipsec restart - -echo -echo "Libreswan $swan_ver was installed successfully! " -echo - -exit 0 + fi +} + +install_pkgs() { + if ! command -v wget >/dev/null 2>&1; then + if [ "$os_type" = "ubuntu" ] || [ "$os_type" = "debian" ] || [ "$os_type" = "raspbian" ]; 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" diff --git a/extras/vpnupgrade_alpine.sh b/extras/vpnupgrade_alpine.sh new file mode 100755 index 0000000000..c6d88b9375 --- /dev/null +++ b/extras/vpnupgrade_alpine.sh @@ -0,0 +1,307 @@ +#!/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-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! + +# (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) + if [ "$os_ver" != "3.19" ] && [ "$os_ver" != "3.20" ]; then + exiterr "This script only supports Alpine Linux 3.19/3.20." + 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.1 + 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.1 + 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 < +# The latest version of this script is available at: +# https://github.com/hwdsl2/setup-ipsec-vpn +# +# Copyright (C) 2016-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/ @@ -10,136 +13,340 @@ # Attribution required: please include my name in any derivative and let me # know how you have improved it! -# Check for the latest version at https://libreswan.org and update as necessary -swan_ver=3.17 +# (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 +### 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() { echo "Error: 'yum install' failed." >&2; exit 1; } +exiterr() { echo "Error: $1" >&2; exit 1; } +exiterr2() { exiterr "'yum install' failed."; } +bigecho() { echo "## $1"; } -if [ ! -f /etc/redhat-release ]; then - exiterr "This script only supports CentOS/RHEL." -fi +check_root() { + if [ "$(id -u)" != 0 ]; then + exiterr "Script must be run as root. Try 'sudo bash $0'" + fi +} -if ! grep -qs -e "release 6" -e "release 7" /etc/redhat-release; then - exiterr "This script only supports CentOS/RHEL 6 and 7." -fi +check_vz() { + if [ -f /proc/user_beancounters ]; then + exiterr "OpenVZ VPS is not supported." + fi +} -if [ -f /proc/user_beancounters ]; then - exiterr "This script does not support OpenVZ VPS." -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 + else + exiterr "This script only supports CentOS/RHEL 7-9." + 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 +} -if [ "$(id -u)" != 0 ]; then - exiterr "Script must be run as root. Try 'sudo sh $0'" -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 +} -if [ -z "$swan_ver" ]; then - exiterr "Libreswan version 'swan_ver' not specified." -fi +get_swan_ver() { + swan_ver_cur=5.1 + 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" +} -/usr/local/sbin/ipsec --version 2>/dev/null | grep -qs "Libreswan" -if [ "$?" != "0" ]; then - exiterr "This script requires Libreswan already installed." -fi +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 | grep -qs "Libreswan $swan_ver" -if [ "$?" = "0" ]; then - echo "You already have Libreswan version $swan_ver installed! " - echo "If you continue, the same version will be re-installed." - echo - printf "Do you wish to continue anyway? [y/N] " +EOF + fi + printf "Do you want to continue? [Y/n] " read -r response case $response in - [yY][eE][sS]|[yY]) + [yY][eE][sS]|[yY]|'') echo ;; *) - echo "Aborting." + echo "Abort. No changes were made." exit 1 ;; esac -fi +} + +start_setup() { + mkdir -p /opt/src + cd /opt/src || exit 1 +} + +install_pkgs_1() { + bigecho "Installing required packages..." + ( + 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 wget sed tar >/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 +} -clear +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 </dev/null | grep -qs "$swan_ver" -[ "$?" != "0" ] && exiterr "Libreswan $swan_ver failed to build." - -# Restore SELinux contexts -restorecon /etc/ipsec.d/*db 2>/dev/null -restorecon /usr/local/sbin -Rv 2>/dev/null -restorecon /usr/local/libexec/ipsec -Rv 2>/dev/null - -# Restart IPsec service -service ipsec restart - -echo -echo "Libreswan $swan_ver was installed successfully! " -echo +EOF + fi +} + +vpnupgrade() { + check_root + check_vz + check_os + check_libreswan + get_swan_ver + check_swan_ver + show_setup_info + start_setup + install_pkgs_1 + install_pkgs_2 + get_libreswan + install_libreswan + restore_selinux + update_ikev2_script + update_config + restart_ipsec + show_setup_complete +} + +## Defer setup until we have the complete script +vpnupgrade "$@" exit 0 diff --git a/extras/vpnupgrade_ubuntu.sh b/extras/vpnupgrade_ubuntu.sh new file mode 100755 index 0000000000..90cff3c872 --- /dev/null +++ b/extras/vpnupgrade_ubuntu.sh @@ -0,0 +1,343 @@ +#!/bin/bash +# +# Script to update Libreswan on Ubuntu and Debian +# +# The latest version of this script is available at: +# https://github.com/hwdsl2/setup-ipsec-vpn +# +# Copyright (C) 2016-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! + +# (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" = "jessiesid" ] \ + || [ "$os_ver" = "bustersid" ]; then +cat 1>&2 <= 10 or Ubuntu >= 20.04. + This version of Ubuntu/Debian is too old and not supported. +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.1 + 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 +} + +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 < -# Based on the work of Thomas Sarlandie (Copyright 2012) +# The latest version of this script is available at: +# https://github.com/hwdsl2/setup-ipsec-vpn +# +# Copyright (C) 2021-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/ @@ -20,437 +21,295 @@ # 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 characters within values: \ " ' +# - DO NOT use these special characters within values: \ " ' YOUR_IPSEC_PSK='' YOUR_USERNAME='' YOUR_PASSWORD='' -# Important Notes: https://git.io/vpnnotes -# Setup VPN Clients: https://git.io/vpnclients - # ===================================================== export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" -exiterr() { echo "Error: ${1}" >&2; exit 1; } -exiterr2() { echo "Error: 'apt-get install' failed." >&2; exit 1; } +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" +} -os_type="$(lsb_release -si 2>/dev/null)" -if [ "$os_type" != "Ubuntu" ] && [ "$os_type" != "Debian" ]; then - exiterr "This script only supports Ubuntu/Debian." -fi +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" +} -if [ -f /proc/user_beancounters ]; then - exiterr "This script does not support OpenVZ VPS." -fi +check_root() { + if [ "$(id -u)" != 0 ]; then + exiterr "Script must be run as root. Try 'sudo sh $0'" + fi +} -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 +} -eth0_state=$(cat /sys/class/net/eth0/operstate 2>/dev/null) -if [ -z "$eth0_state" ] || [ "$eth0_state" = "down" ]; then +check_lxc() { + # shellcheck disable=SC2154 + if [ "$container" = "lxc" ] && [ ! -e /dev/ppp ]; then cat 1>&2 <<'EOF' -Error: Network interface 'eth0' is not available. - -Please DO NOT run this script on your PC or Mac! -Run 'cat /proc/net/dev' to find the active network interface, -then use it to replace ALL 'eth0' and 'eth+' in this script. +Error: /dev/ppp is missing. LXC containers require configuration. + See: https://github.com/hwdsl2/setup-ipsec-vpn/issues/1014 EOF exit 1 -fi - -[ -n "$YOUR_IPSEC_PSK" ] && VPN_IPSEC_PSK="$YOUR_IPSEC_PSK" -[ -n "$YOUR_USERNAME" ] && VPN_USER="$YOUR_USERNAME" -[ -n "$YOUR_PASSWORD" ] && VPN_PASSWORD="$YOUR_PASSWORD" - -if [ -z "$VPN_IPSEC_PSK" ] && [ -z "$VPN_USER" ] && [ -z "$VPN_PASSWORD" ]; then - echo "VPN credentials not set by user. Generating random PSK and password..." - echo - VPN_IPSEC_PSK="$(LC_CTYPE=C tr -dc 'A-HJ-NPR-Za-km-z2-9' < /dev/urandom | head -c 16)" - VPN_USER=vpnuser - VPN_PASSWORD="$(LC_CTYPE=C tr -dc 'A-HJ-NPR-Za-km-z2-9' < /dev/urandom | head -c 16)" -fi - -if [ -z "$VPN_IPSEC_PSK" ] || [ -z "$VPN_USER" ] || [ -z "$VPN_PASSWORD" ]; then - exiterr "All VPN credentials must be specified. Edit the script and re-enter them." -fi - -if [ "$(sed 's/\..*//' /etc/debian_version 2>/dev/null)" = "7" ]; then -cat <<'EOF' -IMPORTANT: Workaround required for Debian 7 (Wheezy). -You must first run the script at: https://git.io/vpndeb7 -If not already done so, press Ctrl-C to interrupt now. - -Continuing in 30 seconds ... - -EOF - sleep 30 -fi - -echo "VPN setup in progress... Please be patient." -echo - -# Create and change to working dir -mkdir -p /opt/src -cd /opt/src || exiterr "Cannot enter /opt/src." - -# Update package index -export DEBIAN_FRONTEND=noninteractive -apt-get -yq update || exiterr "'apt-get update' failed." - -# Make sure basic commands exist -apt-get -yq install wget dnsutils openssl || exiterr2 -apt-get -yq install iproute gawk grep sed net-tools || exiterr2 - -cat <<'EOF' - -Trying to auto discover IPs of this server... - -In case the script hangs here for more than a few minutes, -use Ctrl-C to interrupt. Then edit it and manually enter IPs. - -EOF - -# In case auto IP discovery fails, you may manually enter server IPs here. -# If your server only has a public IP, put that public IP on both lines. -PUBLIC_IP=${VPN_PUBLIC_IP:-''} -PRIVATE_IP=${VPN_PRIVATE_IP:-''} - -# In Amazon EC2, these two variables will be retrieved from metadata -[ -z "$PUBLIC_IP" ] && PUBLIC_IP=$(wget -t 3 -T 15 -qO- 'http://169.254.169.254/latest/meta-data/public-ipv4') -[ -z "$PRIVATE_IP" ] && PRIVATE_IP=$(wget -t 3 -T 15 -qO- 'http://169.254.169.254/latest/meta-data/local-ipv4') - -# Try to find IPs for non-EC2 servers -[ -z "$PUBLIC_IP" ] && PUBLIC_IP=$(dig @resolver1.opendns.com -t A -4 myip.opendns.com +short) -[ -z "$PUBLIC_IP" ] && PUBLIC_IP=$(wget -t 3 -T 15 -qO- http://whatismyip.akamai.com) -[ -z "$PUBLIC_IP" ] && PUBLIC_IP=$(wget -t 3 -T 15 -qO- http://ipv4.icanhazip.com) -[ -z "$PRIVATE_IP" ] && PRIVATE_IP=$(ip -4 route get 1 | awk '{print $NF;exit}') -[ -z "$PRIVATE_IP" ] && PRIVATE_IP=$(ifconfig eth0 | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*') - -# Check IPs for correct format -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])$" -if ! printf %s "$PUBLIC_IP" | grep -Eq "$IP_REGEX"; then - exiterr "Cannot find valid public IP. Edit the script and manually enter IPs." -fi -if ! printf %s "$PRIVATE_IP" | grep -Eq "$IP_REGEX"; then - exiterr "Cannot find valid private IP. Edit the script and manually enter IPs." -fi - -# Install necessary packages -apt-get -yq install libnss3-dev libnspr4-dev pkg-config libpam0g-dev \ - libcap-ng-dev libcap-ng-utils libselinux1-dev \ - libcurl4-nss-dev flex bison gcc make \ - libunbound-dev libnss3-tools libevent-dev || exiterr2 -apt-get -yq --no-install-recommends install xmlto || exiterr2 -apt-get -yq install ppp xl2tpd || exiterr2 - -# Install Fail2Ban to protect SSH -apt-get -yq install fail2ban || exiterr2 - -# Compile and install Libreswan -swan_ver=3.17 -swan_file="libreswan-$swan_ver.tar.gz" -swan_url1="https://download.libreswan.org/$swan_file" -swan_url2="https://github.com/libreswan/libreswan/archive/v$swan_ver.tar.gz" -wget -t 3 -T 30 -nv -O "$swan_file" "$swan_url1" || wget -t 3 -T 30 -nv -O "$swan_file" "$swan_url2" -[ "$?" != "0" ] && exiterr "Cannot download Libreswan source." -/bin/rm -rf "/opt/src/libreswan-$swan_ver" -tar xzf "$swan_file" && /bin/rm -f "$swan_file" -cd "libreswan-$swan_ver" || exiterr "Cannot enter Libreswan source dir." -echo "WERROR_CFLAGS =" > Makefile.inc.local -if [ "$(packaging/utils/lswan_detect.sh init)" = "systemd" ]; then - apt-get -yq install libsystemd-dev || exiterr2 -fi -make -s programs && make -s install - -# Verify the install and clean up -cd /opt/src || exiterr "Cannot enter /opt/src." -/bin/rm -rf "/opt/src/libreswan-$swan_ver" -/usr/local/sbin/ipsec --version 2>/dev/null | grep -qs "$swan_ver" -[ "$?" != "0" ] && exiterr "Libreswan $swan_ver failed to build." - -# Create IPsec (Libreswan) config -sys_dt="$(date +%Y-%m-%d-%H:%M:%S)" -/bin/cp -f /etc/ipsec.conf "/etc/ipsec.conf.old-$sys_dt" 2>/dev/null -cat > /etc/ipsec.conf </dev/null -cat > /etc/ipsec.secrets </dev/null -cat > /etc/xl2tpd/xl2tpd.conf <<'EOF' -[global] -port = 1701 - -[lns default] -ip range = 192.168.42.10-192.168.42.250 -local ip = 192.168.42.1 -require chap = yes -refuse pap = yes -require authentication = yes -name = l2tpd -pppoptfile = /etc/ppp/options.xl2tpd -length bit = yes -EOF - -# Set xl2tpd options -/bin/cp -f /etc/ppp/options.xl2tpd "/etc/ppp/options.xl2tpd.old-$sys_dt" 2>/dev/null -cat > /etc/ppp/options.xl2tpd <<'EOF' -ipcp-accept-local -ipcp-accept-remote -ms-dns 8.8.8.8 -ms-dns 8.8.4.4 -noccp -auth -crtscts -mtu 1280 -mru 1280 -lock -proxyarp -lcp-echo-failure 4 -lcp-echo-interval 30 -connect-delay 5000 -EOF - -# Create VPN credentials -/bin/cp -f /etc/ppp/chap-secrets "/etc/ppp/chap-secrets.old-$sys_dt" 2>/dev/null -cat > /etc/ppp/chap-secrets </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 - -/bin/cp -f /etc/ipsec.d/passwd "/etc/ipsec.d/passwd.old-$sys_dt" 2>/dev/null -VPN_PASSWORD_ENC=$(openssl passwd -1 "$VPN_PASSWORD") -cat > /etc/ipsec.d/passwd <&2 <= 10 or Ubuntu >= 20.04. + This version of Ubuntu/Debian is too old and not supported. EOF + exit 1 + fi + fi + fi +} -# Update sysctl settings -if ! grep -qs "hwdsl2 VPN script" /etc/sysctl.conf; then - /bin/cp -f /etc/sysctl.conf "/etc/sysctl.conf.old-$sys_dt" 2>/dev/null -cat >> /etc/sysctl.conf <<'EOF' - -# Added by hwdsl2 VPN script -kernel.msgmnb = 65536 -kernel.msgmax = 65536 -kernel.shmmax = 68719476736 -kernel.shmall = 4294967296 - -net.ipv4.ip_forward = 1 -net.ipv4.tcp_syncookies = 1 -net.ipv4.conf.all.accept_source_route = 0 -net.ipv4.conf.default.accept_source_route = 0 -net.ipv4.conf.all.accept_redirects = 0 -net.ipv4.conf.default.accept_redirects = 0 -net.ipv4.conf.all.send_redirects = 0 -net.ipv4.conf.default.send_redirects = 0 -net.ipv4.conf.lo.send_redirects = 0 -net.ipv4.conf.eth0.send_redirects = 0 -net.ipv4.conf.all.rp_filter = 0 -net.ipv4.conf.default.rp_filter = 0 -net.ipv4.conf.lo.rp_filter = 0 -net.ipv4.conf.eth0.rp_filter = 0 -net.ipv4.icmp_echo_ignore_broadcasts = 1 -net.ipv4.icmp_ignore_bogus_error_responses = 1 - -net.core.wmem_max = 12582912 -net.core.rmem_max = 12582912 -net.ipv4.tcp_rmem = 10240 87380 12582912 -net.ipv4.tcp_wmem = 10240 87380 12582912 -EOF -fi - -# Create basic IPTables rules. First check for existing rules. -# - If IPTables is "empty", simply write out the new rules. -# - If *not* empty, insert new rules and save them with existing ones. -if ! grep -qs "hwdsl2 VPN script" /etc/iptables.rules; then - service fail2ban stop >/dev/null 2>&1 - iptables-save > "/etc/iptables.rules.old-$sys_dt" - sshd_port="$(ss -nlput | grep sshd | awk '{print $5}' | head -n 1 | grep -Eo '[0-9]{1,5}$')" - if [ "$(iptables-save | grep -c '^\-')" = "0" ] && [ "$sshd_port" = "22" ]; then -cat > /etc/iptables.rules < /etc/iptables.rules - iptables-save >> /etc/iptables.rules +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 - # Update rules for iptables-persistent - if [ -f /etc/iptables/rules.v4 ]; then - /bin/cp -f /etc/iptables/rules.v4 "/etc/iptables/rules.v4.old-$sys_dt" - /bin/cp -f /etc/iptables.rules /etc/iptables/rules.v4 + 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" ] || [ "$os_type" = "raspbian" ]; then + if ! uname -m | grep -qi -e '^arm' -e '^aarch64'; then + check_wl=1 + fi + else + check_wl=1 + fi fi -fi - -# Load IPTables rules at system 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 -exit 0 -EOF - -# Start services at boot -if ! grep -qs "hwdsl2 VPN script" /etc/rc.local; then - /bin/cp -f /etc/rc.local "/etc/rc.local.old-$sys_dt" 2>/dev/null - sed --follow-symlinks -i -e '/^exit 0/d' /etc/rc.local -cat >> /etc/rc.local <<'EOF' - -# Added by hwdsl2 VPN script -service fail2ban restart || /bin/true -service ipsec start -service xl2tpd start -echo 1 > /proc/sys/net/ipv4/ip_forward -exit 0 -EOF -fi - -# Reload sysctl.conf -sysctl -e -q -p - -# Update file attributes -chmod +x /etc/rc.local -chmod +x /etc/network/if-pre-up.d/iptablesload -chmod 600 /etc/ipsec.secrets* /etc/ppp/chap-secrets* /etc/ipsec.d/passwd* - -# Apply new IPTables rules -iptables-restore < /etc/iptables.rules - -# Restart services -service fail2ban stop >/dev/null 2>&1 -service ipsec stop >/dev/null 2>&1 -service xl2tpd stop >/dev/null 2>&1 -service fail2ban start -service ipsec start -service xl2tpd start - -cat </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 100 ] && 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" ] || [ "$os_type" = "raspbian" ]; 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" \ + /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" diff --git a/vpnsetup_alpine.sh b/vpnsetup_alpine.sh new file mode 100755 index 0000000000..edba7ecd2e --- /dev/null +++ b/vpnsetup_alpine.sh @@ -0,0 +1,634 @@ +#!/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-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 +# - 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_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.19" ] && [ "$os_ver" != "3.20" ]; then + exiterr "This script only supports Alpine Linux 3.19/3.20." + 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 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." +} + +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.1 + 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"; 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" + # 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 </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" + 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 +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_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." +} + +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.1 + 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"; 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" + # 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 </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" + 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 +cat >> /etc/rc.local <<'EOF' + +# Added by hwdsl2 VPN script +(sleep 15 +service ipsec restart +service xl2tpd restart +echo 1 > /proc/sys/net/ipv4/ip_forward)& +EOF + fi +} + +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 < +# The latest version of this script is available at: +# https://github.com/hwdsl2/setup-ipsec-vpn +# +# Copyright (C) 2015-2024 Lin Song # Based on the work of Thomas Sarlandie (Copyright 2012) # # This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 @@ -20,222 +22,509 @@ # 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 characters within values: \ " ' +# - DO NOT use these special characters within values: \ " ' YOUR_IPSEC_PSK='' YOUR_USERNAME='' YOUR_PASSWORD='' -# Important Notes: https://git.io/vpnnotes -# Setup VPN Clients: https://git.io/vpnclients - # ===================================================== 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_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 +} -exiterr() { echo "Error: ${1}" >&2; exit 1; } -exiterr2() { echo "Error: 'yum install' failed." >&2; exit 1; } - -if [ ! -f /etc/redhat-release ]; then - exiterr "This script only supports CentOS/RHEL." -fi - -if ! grep -qs -e "release 6" -e "release 7" /etc/redhat-release; then - exiterr "This script only supports CentOS/RHEL 6 and 7." -fi - -if [ -f /proc/user_beancounters ]; then - exiterr "This script does not support OpenVZ VPS." -fi - -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 +} -eth0_state=$(cat /sys/class/net/eth0/operstate 2>/dev/null) -if [ -z "$eth0_state" ] || [ "$eth0_state" = "down" ]; then +check_lxc() { + # shellcheck disable=SC2154 + if [ "$container" = "lxc" ] && [ ! -e /dev/ppp ]; then cat 1>&2 <<'EOF' -Error: Network interface 'eth0' is not available. - -Please DO NOT run this script on your PC or Mac! -Run 'cat /proc/net/dev' to find the active network interface, -then use it to replace ALL 'eth0' and 'eth+' in this script. +Error: /dev/ppp is missing. LXC containers require configuration. + See: https://github.com/hwdsl2/setup-ipsec-vpn/issues/1014 EOF exit 1 -fi - -[ -n "$YOUR_IPSEC_PSK" ] && VPN_IPSEC_PSK="$YOUR_IPSEC_PSK" -[ -n "$YOUR_USERNAME" ] && VPN_USER="$YOUR_USERNAME" -[ -n "$YOUR_PASSWORD" ] && VPN_PASSWORD="$YOUR_PASSWORD" - -if [ -z "$VPN_IPSEC_PSK" ] && [ -z "$VPN_USER" ] && [ -z "$VPN_PASSWORD" ]; then - echo "VPN credentials not set by user. Generating random PSK and password..." - echo - VPN_IPSEC_PSK="$(LC_CTYPE=C tr -dc 'A-HJ-NPR-Za-km-z2-9' < /dev/urandom | head -c 16)" - VPN_USER=vpnuser - VPN_PASSWORD="$(LC_CTYPE=C tr -dc 'A-HJ-NPR-Za-km-z2-9' < /dev/urandom | head -c 16)" -fi - -if [ -z "$VPN_IPSEC_PSK" ] || [ -z "$VPN_USER" ] || [ -z "$VPN_PASSWORD" ]; then - exiterr "All VPN credentials must be specified. Edit the script and re-enter them." -fi - -echo "VPN setup in progress... Please be patient." -echo - -# Create and change to working dir -mkdir -p /opt/src -cd /opt/src || exiterr "Cannot enter /opt/src." - -# Make sure basic commands exist -yum -y install wget bind-utils openssl || exiterr2 -yum -y install iproute gawk grep sed net-tools || exiterr2 - -cat <<'EOF' - -Trying to auto discover IPs of this server... + 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 + else + exiterr "This script only supports CentOS/RHEL 7-9." + 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 +} -In case the script hangs here for more than a few minutes, -use Ctrl-C to interrupt. Then edit it and manually enter IPs. +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." +} + +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 ] \ + || 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 -# In case auto IP discovery fails, you may manually enter server IPs here. -# If your server only has a public IP, put that public IP on both lines. -PUBLIC_IP=${VPN_PUBLIC_IP:-''} -PRIVATE_IP=${VPN_PRIVATE_IP:-''} - -# In Amazon EC2, these two variables will be retrieved from metadata -[ -z "$PUBLIC_IP" ] && PUBLIC_IP=$(wget -t 3 -T 15 -qO- 'http://169.254.169.254/latest/meta-data/public-ipv4') -[ -z "$PRIVATE_IP" ] && PRIVATE_IP=$(wget -t 3 -T 15 -qO- 'http://169.254.169.254/latest/meta-data/local-ipv4') - -# Try to find IPs for non-EC2 servers -[ -z "$PUBLIC_IP" ] && PUBLIC_IP=$(dig @resolver1.opendns.com -t A -4 myip.opendns.com +short) -[ -z "$PUBLIC_IP" ] && PUBLIC_IP=$(wget -t 3 -T 15 -qO- http://whatismyip.akamai.com) -[ -z "$PUBLIC_IP" ] && PUBLIC_IP=$(wget -t 3 -T 15 -qO- http://ipv4.icanhazip.com) -[ -z "$PRIVATE_IP" ] && PRIVATE_IP=$(ip -4 route get 1 | awk '{print $NF;exit}') -[ -z "$PRIVATE_IP" ] && PRIVATE_IP=$(ifconfig eth0 | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*') - -# Check IPs for correct format -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])$" -if ! printf %s "$PUBLIC_IP" | grep -Eq "$IP_REGEX"; then - exiterr "Cannot find valid public IP. Edit the script and manually enter IPs." -fi -if ! printf %s "$PRIVATE_IP" | grep -Eq "$IP_REGEX"; then - exiterr "Cannot find valid private IP. Edit the script and manually enter IPs." -fi - -# Add the EPEL repository -yum -y install epel-release || exiterr2 - -# Install necessary packages -yum -y install nss-devel nspr-devel pkgconfig pam-devel \ - libcap-ng-devel libselinux-devel \ - curl-devel flex bison gcc make \ - fipscheck-devel unbound-devel xmlto || exiterr2 -yum -y install ppp xl2tpd || exiterr2 - -# Install Fail2Ban to protect SSH -yum -y install fail2ban || exiterr2 - -# Install libevent2 and systemd-devel (CentOS 7) -if grep -qs "release 6" /etc/redhat-release; then - yum -y remove libevent-devel - yum -y install libevent2-devel || exiterr2 -elif grep -qs "release 7" /etc/redhat-release; then - yum -y install libevent-devel systemd-devel || exiterr2 -fi - -# Compile and install Libreswan -swan_ver=3.17 -swan_file="libreswan-$swan_ver.tar.gz" -swan_url1="https://download.libreswan.org/$swan_file" -swan_url2="https://github.com/libreswan/libreswan/archive/v$swan_ver.tar.gz" -wget -t 3 -T 30 -nv -O "$swan_file" "$swan_url1" || wget -t 3 -T 30 -nv -O "$swan_file" "$swan_url2" -[ "$?" != "0" ] && exiterr "Cannot download Libreswan source." -/bin/rm -rf "/opt/src/libreswan-$swan_ver" -tar xzf "$swan_file" && /bin/rm -f "$swan_file" -cd "libreswan-$swan_ver" || exiterr "Cannot enter Libreswan source dir." -echo "WERROR_CFLAGS =" > Makefile.inc.local -make -s programs && make -s install - -# Verify the install and clean up -cd /opt/src || exiterr "Cannot enter /opt/src." -/bin/rm -rf "/opt/src/libreswan-$swan_ver" -/usr/local/sbin/ipsec --version 2>/dev/null | grep -qs "$swan_ver" -[ "$?" != "0" ] && exiterr "Libreswan $swan_ver failed to build." - -# Create IPsec (Libreswan) config -sys_dt="$(date +%Y-%m-%d-%H:%M:%S)" -/bin/cp -f /etc/ipsec.conf "/etc/ipsec.conf.old-$sys_dt" 2>/dev/null + 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.1 + 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"; 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" + # Create IPsec config + conf_bk "/etc/ipsec.conf" cat > /etc/ipsec.conf </dev/null +include /etc/ipsec.d/*.conf +EOF + # Specify IPsec PSK + conf_bk "/etc/ipsec.secrets" cat > /etc/ipsec.secrets </dev/null -cat > /etc/xl2tpd/xl2tpd.conf <<'EOF' + # Create xl2tpd config + conf_bk "/etc/xl2tpd/xl2tpd.conf" +cat > /etc/xl2tpd/xl2tpd.conf </dev/null -cat > /etc/ppp/options.xl2tpd <<'EOF' + # Set xl2tpd options + conf_bk "/etc/ppp/options.xl2tpd" +cat > /etc/ppp/options.xl2tpd </dev/null + if [ -z "$VPN_DNS_SRV1" ] || [ -n "$VPN_DNS_SRV2" ]; then +cat >> /etc/ppp/options.xl2tpd < /etc/ppp/chap-secrets </dev/null -VPN_PASSWORD_ENC=$(openssl passwd -1 "$VPN_PASSWORD") + conf_bk "/etc/ipsec.d/passwd" + VPN_PASSWORD_ENC=$(openssl passwd -1 "$VPN_PASSWORD") cat > /etc/ipsec.d/passwd </dev/null -cat >> /etc/sysctl.conf <<'EOF' +update_sysctl() { + bigecho "Updating sysctl settings..." + if ! grep -qs "hwdsl2 VPN script" /etc/sysctl.conf; then + conf_bk "/etc/sysctl.conf" +cat >> /etc/sysctl.conf </dev/null 2>&1 - iptables-save > "/etc/sysconfig/iptables.old-$sys_dt" - sshd_port="$(ss -nlput | grep sshd | awk '{print $5}' | head -n 1 | grep -Eo '[0-9]{1,5}$')" - if [ "$(iptables-save | grep -c '^\-')" = "0" ] && [ "$sshd_port" = "22" ]; then -cat > /etc/sysconfig/iptables <> /etc/sysctl.conf <<'EOF' +net.core.default_qdisc = fq +net.ipv4.tcp_congestion_control = bbr 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 + 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 + 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" + 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 - iptables -I INPUT 1 -p udp -m multiport --dports 500,4500 -j ACCEPT - iptables -I INPUT 2 -p udp --dport 1701 -m policy --dir in --pol ipsec -j ACCEPT - iptables -I INPUT 3 -p udp --dport 1701 -j DROP - iptables -I FORWARD 1 -m conntrack --ctstate INVALID -j DROP - iptables -I FORWARD 2 -i eth+ -o ppp+ -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT - iptables -I FORWARD 3 -i ppp+ -o eth+ -j ACCEPT - iptables -I FORWARD 4 -i ppp+ -o ppp+ -s 192.168.42.0/24 -d 192.168.42.0/24 -j ACCEPT - iptables -I FORWARD 5 -i eth+ -d 192.168.43.0/24 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT - iptables -I FORWARD 6 -s 192.168.43.0/24 -o eth+ -j ACCEPT - # Uncomment to DROP traffic between VPN clients themselves - # 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 -A FORWARD -j DROP - iptables -t nat -I POSTROUTING -s 192.168.43.0/24 -o eth+ -m policy --dir out --pol none -j SNAT --to-source "$PRIVATE_IP" - iptables -t nat -I POSTROUTING -s 192.168.42.0/24 -o eth+ -j SNAT --to-source "$PRIVATE_IP" - echo "# Modified by hwdsl2 VPN script" > /etc/sysconfig/iptables - iptables-save >> /etc/sysconfig/iptables - fi -fi - -# Create basic Fail2Ban rules -if [ ! -f /etc/fail2ban/jail.local ] ; then -cat > /etc/fail2ban/jail.local <<'EOF' -[DEFAULT] -ignoreip = 127.0.0.1/8 -bantime = 600 -findtime = 600 -maxretry = 5 -backend = auto - -[ssh-iptables] -enabled = true -filter = sshd -action = iptables[name=SSH, port=ssh, protocol=tcp] -logpath = /var/log/secure -EOF -fi - -# Start services at boot -if ! grep -qs "hwdsl2 VPN script" /etc/rc.local; then - /bin/cp -f /etc/rc.local "/etc/rc.local.old-$sys_dt" 2>/dev/null + 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 cat >> /etc/rc.local <<'EOF' # Added by hwdsl2 VPN script -iptables-restore < /etc/sysconfig/iptables -service fail2ban restart -service ipsec start -service xl2tpd start -echo 1 > /proc/sys/net/ipv4/ip_forward +(sleep 15 +service ipsec restart +service xl2tpd restart +echo 1 > /proc/sys/net/ipv4/ip_forward)& EOF -fi - -# Restore SELinux contexts -restorecon /etc/ipsec.d/*db 2>/dev/null -restorecon /usr/local/sbin -Rv 2>/dev/null -restorecon /usr/local/libexec/ipsec -Rv 2>/dev/null - -# Reload sysctl.conf -sysctl -e -q -p - -# Update file attributes -chmod +x /etc/rc.local -chmod 600 /etc/ipsec.secrets* /etc/ppp/chap-secrets* /etc/ipsec.d/passwd* - -# Apply new IPTables rules -iptables-restore < /etc/sysconfig/iptables - -# Restart services -service fail2ban stop >/dev/null 2>&1 -service ipsec stop >/dev/null 2>&1 -service xl2tpd stop >/dev/null 2>&1 -service fail2ban start -service ipsec start -service xl2tpd start + 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_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" = "jessiesid" ] \ + || [ "$os_ver" = "bustersid" ]; then +cat 1>&2 <= 10 or Ubuntu >= 20.04. + This version of Ubuntu/Debian is too old and not supported. +EOF + exit 1 + fi +} + +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 100 ] && 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." +} + +install_vpn_pkgs() { + bigecho "Installing packages required for the VPN..." + p1=libcurl4-nss-dev + [ "$os_ver" = "trixiesid" ] && p1=libcurl4-gnutls-dev + ( + 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" = "debian" ] && [ "$os_ver" = 12 ]; 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.1 + 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"; 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" + # 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 + 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 + 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 +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 +cat >> /etc/rc.local < /proc/sys/net/ipv4/ip_forward)& +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 <