docker-ipsec-vpn-server Documentation

Docker image to run an IPsec VPN server, with IPsec/L2TP, Cisco IPsec and IKEv2. Auto-generates server config and supports VPN client setup on Linux,...

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy docker-ipsec-vpn-server on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name docker-ipsec-vpn-server -p 500:500 --restart always hwdsl2/ipsec-vpn-server
Configured Services & Ports
⚙️ vpn
image: hwdsl2/ipsec-vpn-server
🔌 Ports: 500:500/udp, 4500:4500/udp
docker-compose.yml
yaml (docker-compose.yml)
volumes:
  ikev2-vpn-data:

services:
  vpn:
    image: hwdsl2/ipsec-vpn-server
    restart: always
    env_file:
      - ./vpn.env
    ports:
      - "500:500/udp"
      - "4500:4500/udp"
    privileged: true
    hostname: ipsec-vpn-server
    container_name: ipsec-vpn-server
    volumes:
      - ikev2-vpn-data:/etc/ipsec.d
      - /lib/modules:/lib/modules:ro
    # To enable IPv6 support for IKEv2 clients, the Docker host must have a
    # public IPv6 address. Uncomment the network section below and configure
    # IPv6 in your Docker daemon (set "ipv6": true and "fixed-cidr-v6" in
    # /etc/docker/daemon.json), then re-create this container.
    # networks:
    #   vpnnet:

# networks:
#   vpnnet:
#     enable_ipv6: true
#     ipam:
#       config:
#         - subnet: fddd:1::/64

File: README.md

English | 简体中文 | 繁體中文 | Русский

IPsec VPN Server on Docker

Docker image to run an IPsec VPN server, with IPsec/L2TP, Cisco IPsec and IKEv2.

Based on Alpine 3.23 or Debian 12 with Libreswan (IPsec VPN software) and xl2tpd (L2TP daemon).

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.

Features:

  • Automatically generates VPN credentials and IKEv2 configuration on first start
  • 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 a helper script to manage IKEv2 users and certificates
  • Automatically built and published via GitHub Actions
  • Persistent data via a Docker volume
  • Multi-arch: linux/amd64, linux/arm64, linux/arm/v7

Also available:

Quick start

Use this command to set up an IPsec VPN server on Docker:

bash
docker run \
    --name ipsec-vpn-server \
    --restart=always \
    -v ikev2-vpn-data:/etc/ipsec.d \
    -v /lib/modules:/lib/modules:ro \
    -p 500:500/udp \
    -p 4500:4500/udp \
    -d --privileged \
    hwdsl2/ipsec-vpn-server

Your VPN login details will be randomly generated. See Retrieve VPN login details.

Alternatively, you may set up IPsec VPN without Docker. To learn more about how to use this image, read the sections below.

Community

  • 📬 Subscribe for project updates (1–2 emails/month) — get free VPN and AI deployment guides (PDF)
  • 💬 Join the r/selfhostedstack community for discussions
  • ⭐ Star the repository if you find it useful — it helps others discover it

Requirements

  • A Linux server with a public IP address or DNS name
  • Docker installed
  • VPN ports open in your firewall (UDP 500 and 4500)
  • You may also use Podman to run this image, after creating an alias for docker

Note: Advanced users can use this image on macOS with Docker for Mac. Before using IPsec/L2TP mode, you may need to restart the container once with docker restart ipsec-vpn-server. This image does not support Docker for Windows.

Download

Get the trusted build from the Docker Hub registry:

bash
docker pull hwdsl2/ipsec-vpn-server

Alternatively, you may download from Quay.io:

bash
docker pull quay.io/hwdsl2/ipsec-vpn-server
docker image tag quay.io/hwdsl2/ipsec-vpn-server hwdsl2/ipsec-vpn-server

Supported platforms: linux/amd64, linux/arm64 and linux/arm/v7.

Advanced users can build from source code on GitHub.

Image comparison

Two pre-built images are available. The default Alpine-based image is only ~19 MB.

Alpine-based Debian-based
Image name hwdsl2/ipsec-vpn-server hwdsl2/ipsec-vpn-server:debian
Compressed size ~ 19 MB ~ 62 MB
Base image Alpine Linux 3.23 Debian Linux 12
Platforms amd64, arm64, arm/v7 amd64, arm64, arm/v7
Libreswan version 5.3.2 5.3.2
IPsec/L2TP ✅ ✅
Cisco IPsec ✅ ✅
IKEv2 ✅ ✅

Note: To use the Debian-based image, replace every hwdsl2/ipsec-vpn-server with hwdsl2/ipsec-vpn-server:debian in this README. These images are not currently compatible with Synology NAS systems.

I want to use the older Libreswan version 4.

It is generally recommended to use the latest Libreswan version 5, which is the default version in this project. However, if you want to use the older Libreswan version 4, you can build the Docker image from source code:

bash
git clone https://github.com/hwdsl2/docker-ipsec-vpn-server
cd docker-ipsec-vpn-server
# Specify Libreswan version 4
sed -i 's/SWAN_VER=5\..*/SWAN_VER=4.15/' Dockerfile Dockerfile.debian
# To build Alpine-based image
docker build -t hwdsl2/ipsec-vpn-server .
# To build Debian-based image
docker build -f Dockerfile.debian -t hwdsl2/ipsec-vpn-server:debian .

How to use this image

Environment variables

Note: All the variables to this image are optional, which means you don't have to type in any variable, and you can have an IPsec VPN server out of the box! To do that, create an empty env file using touch vpn.env, and skip to the next section.

This Docker image uses the following variables, that can be declared in an env file (see example):

text
VPN_IPSEC_PSK=your_ipsec_pre_shared_key
VPN_USER=your_vpn_username
VPN_PASSWORD=your_vpn_password

This will create a user account for VPN login, which can be used by your multiple devices*. The IPsec PSK (pre-shared key) is specified by the VPN_IPSEC_PSK environment variable. The VPN username is defined in VPN_USER, and VPN password is specified by VPN_PASSWORD.

Additional VPN users are supported, and can be optionally declared in your env file like this. Usernames and passwords must be separated by spaces, and usernames cannot contain duplicates. All VPN users will share the same IPsec PSK.

text
VPN_ADDL_USERS=additional_username_1 additional_username_2
VPN_ADDL_PASSWORDS=additional_password_1 additional_password_2

The variables above are only for IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes. For IKEv2, see Configure and use IKEv2 VPN.

Note: In your env file, DO NOT put "" or '' around values, or add space around =. DO NOT use these special characters within values: \ " '. A secure IPsec PSK should consist of at least 20 random characters.

Note: If you modify the env file after the Docker container is already created, you must remove and re-create the container for the changes to take effect. Refer to Update Docker image.

Additional environment variables

Advanced users can optionally specify a DNS name, client name and/or custom DNS servers.

Learn how to specify a DNS name, client name and/or custom DNS servers.

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:

text
VPN_DNS_NAME=vpn.example.com

You may specify a name for the first IKEv2 client. Use one word only, no special characters except - and _. The default is vpnclient if not specified.

text
VPN_CLIENT_NAME=your_client_name

By default, clients are set to use Google Public DNS when the VPN is active. You may specify custom DNS server(s) for all VPN modes. Example:

text
VPN_DNS_SRV1=1.1.1.1
VPN_DNS_SRV2=1.0.0.1

For more details and a list of some popular public DNS providers, see Use alternative DNS servers.

By default, no password is required when importing IKEv2 client configuration. You can choose to protect client config files using a random password.

text
VPN_PROTECT_CONFIG=yes

Note: The variables above have no effect for IKEv2 mode, if IKEv2 is already set up in the Docker container. In this case, you may remove IKEv2 and set it up again using custom options. Refer to Configure and use IKEv2 VPN.

Start the IPsec VPN server

Create a new Docker container from this image (replace ./vpn.env with your own env file):

bash
docker run \
    --name ipsec-vpn-server \
    --env-file ./vpn.env \
    --restart=always \
    -v ikev2-vpn-data:/etc/ipsec.d \
    -v /lib/modules:/lib/modules:ro \
    -p 500:500/udp \
    -p 4500:4500/udp \
    -d --privileged \
    hwdsl2/ipsec-vpn-server

In this command, we use the -v option of docker run to create a new Docker volume named ikev2-vpn-data, and mount it into /etc/ipsec.d in the container. IKEv2 related data such as certificates and keys will persist in the volume, and later when you need to re-create the Docker container, just specify the same volume again.

It is recommended to enable IKEv2 when using this image. However, if you prefer not to enable IKEv2 and use only the IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes to connect to the VPN, remove the first -v option from the docker run command above.

Note: Advanced users can also run without privileged mode.

Retrieve VPN login details

If you did not specify an env file in the docker run command above, VPN_USER will default to vpnuser and both VPN_IPSEC_PSK and VPN_PASSWORD will be randomly generated. To retrieve them, view the container logs:

bash
docker logs ipsec-vpn-server

Search for these lines in the output:

text
Connect to your new VPN with these details:

Server IP: your_vpn_server_ip
IPsec PSK: your_ipsec_pre_shared_key
Username: your_vpn_username
Password: your_vpn_password

The output will also include details for IKEv2 mode, if enabled.

(Optional) Backup the generated VPN login details (if any) to the current directory:

bash
docker cp ipsec-vpn-server:/etc/ipsec.d/vpn-gen.env ./

Using docker-compose

bash
cp vpn.env.example vpn.env
# Edit vpn.env if needed, then:
docker compose up -d
docker logs ipsec-vpn-server

Example docker-compose.yml (already included):

yaml
volumes:
  ikev2-vpn-data:

services:
  vpn:
    image: hwdsl2/ipsec-vpn-server
    restart: always
    env_file:
      - ./vpn.env
    ports:
      - "500:500/udp"
      - "4500:4500/udp"
    privileged: true
    hostname: ipsec-vpn-server
    container_name: ipsec-vpn-server
    volumes:
      - ikev2-vpn-data:/etc/ipsec.d
      - /lib/modules:/lib/modules:ro

Next steps

Read this in other languages: English, 简体中文, 繁體中文, Русский.

Get your computer or device to use the VPN. Please refer to:

Configure and use IKEv2 VPN (recommended)

Configure IPsec/L2TP VPN Clients

Configure IPsec/XAuth ("Cisco IPsec") VPN Clients

Read :book: VPN book to access extra content.

Enjoy your very own VPN! :sparkles::tada::rocket::sparkles:

Important notes

Windows users: For IPsec/L2TP mode, a one-time registry change is required if the VPN server or client is behind NAT (e.g. home router).

The same VPN account can be used by your multiple devices. However, due to an IPsec/L2TP limitation, if you wish to connect multiple devices from behind the same NAT (e.g. home router), you must use IKEv2 or IPsec/XAuth mode.

If you wish to add, edit or remove VPN user accounts, first update your env file, then you must remove and re-create the Docker container using instructions from the next section. Advanced users can bind mount the env file.

For servers with an external firewall (e.g. EC2/GCE), open UDP ports 500 and 4500 for the VPN. Aliyun users, see #433.

Clients are set to use Google Public DNS when the VPN is active. If another DNS provider is preferred, read this section.

Update Docker image

To update the Docker image and container, first download the latest version:

bash
docker pull hwdsl2/ipsec-vpn-server

If the Docker image is already up to date, you should see:

text
Status: Image is up to date for hwdsl2/ipsec-vpn-server:latest

Otherwise, it will download the latest version. To update your Docker container, first note your VPN login details. Then remove the Docker container with docker rm -f ipsec-vpn-server. Finally, re-create it using instructions from How to use this image.

Configure and use IKEv2 VPN

IKEv2 mode has improvements over IPsec/L2TP and IPsec/XAuth ("Cisco IPsec"), and does not require an IPsec PSK, username or password. Read more here.

First, check container logs to view details for IKEv2:

bash
docker logs ipsec-vpn-server

Note: If you cannot find IKEv2 details, IKEv2 may not be enabled in the container. Try updating the Docker image and container using instructions from the Update Docker image section.

During IKEv2 setup, an IKEv2 client (with default name vpnclient) is created, with its configuration exported to /etc/ipsec.d inside the container. To copy config file(s) to the Docker host:

bash
# Check contents of /etc/ipsec.d in the container
docker exec -it ipsec-vpn-server ls -l /etc/ipsec.d
# Example: Copy a client config file from the container
# to the current directory on the Docker host
docker cp ipsec-vpn-server:/etc/ipsec.d/vpnclient.p12 ./

Next steps: Configure your devices to use the IKEv2 VPN.

Learn how to manage IKEv2 clients.

You can manage IKEv2 clients using the helper script. See examples below. To customize client options, run the script without arguments.

bash
# Add a new client (using default options)
docker exec -it ipsec-vpn-server ikev2.sh --addclient [client name]
# Export configuration for an existing client
docker exec -it ipsec-vpn-server ikev2.sh --exportclient [client name]
# List existing clients
docker exec -it ipsec-vpn-server ikev2.sh --listclients
# Show usage
docker exec -it ipsec-vpn-server ikev2.sh -h

Note: If you encounter error "executable file not found", replace ikev2.sh above with /opt/src/ikev2.sh.

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. To change the IKEv2 server address, first open a bash shell inside the container, then follow these instructions. Note that the container logs will not show the new IKEv2 server address until you restart the Docker container.

Remove IKEv2 and set it up again using custom options.

In certain circumstances, you may need to remove IKEv2 and set it up again using custom options.

Warning: All IKEv2 configuration including certificates and keys will be permanently deleted. This cannot be undone!

Option 1: Remove IKEv2 and set it up again using the helper script.

Note that this will override variables you specified in the env file, such as VPN_DNS_NAME and VPN_CLIENT_NAME, and the container logs will no longer show up-to-date information for IKEv2.

bash
# Remove IKEv2 and delete all IKEv2 configuration
docker exec -it ipsec-vpn-server ikev2.sh --removeikev2
# Set up IKEv2 again using custom options
docker exec -it ipsec-vpn-server ikev2.sh

Option 2: Remove ikev2-vpn-data and re-create the container.

  1. Write down all your VPN login details.
  2. Remove the Docker container: docker rm -f ipsec-vpn-server.
  3. Remove the ikev2-vpn-data volume: docker volume rm ikev2-vpn-data.
  4. Update your env file and add custom IKEv2 options such as VPN_DNS_NAME and VPN_CLIENT_NAME, then re-create the container. Refer to How to use this image.

Advanced usage

See Advanced usage.

Technical details

There are two services running: Libreswan (pluto) for the IPsec VPN, and xl2tpd for L2TP support.

The default IPsec configuration supports:

  • IPsec/L2TP with PSK
  • IKEv1 with PSK and XAuth ("Cisco IPsec")
  • IKEv2

Ports required: 500/udp and 4500/udp (IPsec)

License

Note: The software components inside the pre-built image (such as Libreswan and xl2tpd) are under the respective licenses chosen by their respective copyright holders. As for any pre-built image usage, it is the image user's responsibility to ensure that any use of this image complies with any relevant licenses for all software contained within.

Copyright (C) 2016-2026 Lin Song
Based on the work of Thomas Sarlandie (Copyright 2012)


This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License
Attribution required: please include my name in any derivative and let me know how you have improved it!


File: docs/advanced-usage.md

English | 中文

Advanced Usage

Use alternative DNS servers

By default, clients are set to use Google Public DNS when the VPN is active. If another DNS provider is preferred, define VPN_DNS_SRV1 and optionally VPN_DNS_SRV2 in your env file, then follow instructions to re-create the Docker container. Example:

text
VPN_DNS_SRV1=1.1.1.1
VPN_DNS_SRV2=1.0.0.1

Use VPN_DNS_SRV1 to specify the primary DNS server, and VPN_DNS_SRV2 to specify the secondary DNS server (optional).

Note that if IKEv2 is already set up in the Docker container, you will also need to edit /etc/ipsec.d/ikev2.conf inside the Docker container and replace 8.8.8.8 and 8.8.4.4 with your alternative DNS server(s), then restart the Docker container.

Below is a list of some popular public DNS providers for your reference.

Provider Primary DNS Secondary DNS Notes
Google Public DNS 8.8.8.8 8.8.4.4 Default in this project
Cloudflare 1.1.1.1 1.0.0.1 See also: Cloudflare for families
Quad9 9.9.9.9 149.112.112.112 Blocks malicious domains
OpenDNS 208.67.222.222 208.67.220.220 Blocks phishing domains, configurable.
CleanBrowsing 185.228.168.9 185.228.169.9 Domain filters available
NextDNS Varies Varies Ad blocking, free tier available. Learn more.
Control D Varies Varies Ad blocking, configurable. Learn more.

Run without privileged mode

Advanced users can create a Docker container from this image without using privileged mode (replace ./vpn.env in the command below with your own env file).

Note: If your Docker host runs CentOS Stream, Oracle Linux 8+, Rocky Linux or AlmaLinux, it is recommended to use privileged mode. If you want to run without privileged mode, you must run modprobe ip_tables ip6_tables before creating the Docker container and also on boot.

text
docker run \
    --name ipsec-vpn-server \
    --env-file ./vpn.env \
    --restart=always \
    -v ikev2-vpn-data:/etc/ipsec.d \
    -p 500:500/udp \
    -p 4500:4500/udp \
    -d --cap-add=NET_ADMIN \
    --device=/dev/ppp \
    --sysctl net.ipv4.ip_forward=1 \
    --sysctl net.ipv4.conf.all.accept_redirects=0 \
    --sysctl net.ipv4.conf.all.send_redirects=0 \
    --sysctl net.ipv4.conf.all.rp_filter=0 \
    --sysctl net.ipv4.conf.default.accept_redirects=0 \
    --sysctl net.ipv4.conf.default.send_redirects=0 \
    --sysctl net.ipv4.conf.default.rp_filter=0 \
    --sysctl net.ipv6.conf.all.forwarding=1 \
    hwdsl2/ipsec-vpn-server

When running without privileged mode, the container is unable to change sysctl settings. This could affect certain features of this image. A known issue is that the Android/Linux MTU/MSS fix also requires adding --sysctl net.ipv4.ip_no_pmtu_disc=1 to the docker run command. If you encounter any issues, try re-creating the container using privileged mode.

After creating the Docker container, see Retrieve VPN login details.

Similarly, if using Docker compose, you may replace privileged: true in docker-compose.yml with:

text
cap_add:
    - NET_ADMIN
  devices:
    - "/dev/ppp:/dev/ppp"
  sysctls:
    - net.ipv4.ip_forward=1
    - net.ipv4.conf.all.accept_redirects=0
    - net.ipv4.conf.all.send_redirects=0
    - net.ipv4.conf.all.rp_filter=0
    - net.ipv4.conf.default.accept_redirects=0
    - net.ipv4.conf.default.send_redirects=0
    - net.ipv4.conf.default.rp_filter=0
    - net.ipv6.conf.all.forwarding=1

For more information, see compose file reference.

Select VPN modes

Using this Docker image, the IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes are enabled by default. In addition, IKEv2 mode will be enabled if the -v ikev2-vpn-data:/etc/ipsec.d option is specified in the docker run command when creating the Docker container.

Advanced users can selectively disable VPN modes by setting the following variable(s) in the env file, then re-create the Docker container.

Disable IPsec/L2TP mode: VPN_DISABLE_IPSEC_L2TP=yes
Disable IPsec/XAuth ("Cisco IPsec") mode: VPN_DISABLE_IPSEC_XAUTH=yes
Disable both IPsec/L2TP and IPsec/XAuth modes: VPN_IKEV2_ONLY=yes

Enable IKEv2 perfect forward secrecy

By default, IKEv2 Child SAs derive keying material from the existing IKE SA without a new Diffie-Hellman exchange (pfs=no). Enabling perfect forward secrecy (PFS) causes each Child SA rekey to perform a fresh DH exchange, so that a future compromise of the server's private key cannot decrypt previously recorded sessions.

Note: The IKE SA already proposes ECP-256 as its first preference (aes_gcm_c_256-hmac_sha2_256-ecp_256), and all modern clients negotiate it, so session keys are already independent of the server's long-term private key for those clients. Enabling PFS for Child SAs is an incremental hardening step, not a critical gap.

Client compatibility: All modern clients support PFS. However, macOS and iOS clients require re-export and re-import of the .mobileconfig profile with EnablePFS set to 1 (see below). Windows clients require a connection update. RouterOS users must change pfs-group=none to pfs-group=ecp256 in their IKEv2 profile. Android and Linux strongSwan clients require no changes. Windows 7 IKEv2 clients do not support ECP PFS groups and will fail to connect if PFS is enabled on the server.

To enable PFS, first open a Bash shell inside the container, then run:

bash
sed -i 's/pfs=no/pfs=yes/' /etc/ipsec.d/ikev2.conf

When finished, exit the container and restart it:

text
docker restart ipsec-vpn-server

After enabling PFS, the following client configurations must be updated:

  • macOS / iOS: Re-export the client .mobileconfig by running docker exec -it ipsec-vpn-server ikev2.sh --exportclient <name> and copying it to your Docker host, then edit the exported file to enable PFS:
    bash
    sed -i '/EnablePFS/{n;s/0/1/;}' <name>.mobileconfig
    Re-import the updated file on your device.
  • Windows: In an elevated PowerShell window, run Set-VpnConnection -Name "Your VPN Name" -PfsGroup ECP256 (replace with your actual VPN connection name), then reconnect the VPN.
  • RouterOS (MikroTik): In the IKEv2 peer profile, change pfs-group=none to pfs-group=ecp256.

Android and Linux strongSwan clients require no changes; PFS is auto-negotiated.

To revert to the default (PFS disabled), repeat the steps above but replace pfs=yes with pfs=no in the sed command.

Access other containers on the Docker host

After connecting to the VPN, VPN clients can generally access services running in other containers on the same Docker host, without additional configuration.

For example, if the IPsec VPN server container has IP 172.17.0.2, and an Nginx container with IP 172.17.0.3 is running on the same Docker host, VPN clients can use IP 172.17.0.3 to access services on the Nginx container. To find out which IP is assigned to a container, run docker inspect <container name>.

Specify VPN server's public IP

On Docker hosts with multiple public IP addresses, advanced users can specify a public IP for the VPN server using variable VPN_PUBLIC_IP in the env file, then re-create the Docker container. For example, if the Docker host has IPs 192.0.2.1 and 192.0.2.2, and you want the VPN server to use 192.0.2.2:

text
VPN_PUBLIC_IP=192.0.2.2

Note that this variable has no effect for IKEv2 mode, if IKEv2 is already set up in the Docker container. In this case, you may remove IKEv2 and set it up again using custom options. Refer to Configure and use IKEv2 VPN.

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 Docker host. In this case, you can try adding an IPTables SNAT rule on the Docker host. To persist after reboot, you may add the command to /etc/rc.local.

Continuing with the example above, if the Docker container has internal IP 172.17.0.2 (check using docker inspect ipsec-vpn-server), Docker's network interface name is docker0 (check using iptables -nvL -t nat), and you want the "outgoing IP" to be 192.0.2.2:

text
iptables -t nat -I POSTROUTING -s 172.17.0.2 ! -o docker0 -j SNAT --to 192.0.2.2

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.

Assign static IPs to VPN clients

When connecting using IPsec/L2TP mode, the VPN server (Docker container) 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") or IKEv2 mode, the VPN server (Docker container) 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.

Advanced users may optionally assign static IPs to VPN clients. For IKEv2 mode, first open a Bash shell inside the container, then follow the steps in section "IKEv2 mode: Assign static IPs to VPN clients" of Internal VPN IPs and traffic. Note that you should skip steps 2, 3 and 5, and restart the Docker container when finished. This is because changes to /etc/ipsec.conf may be overwritten on container restart.

Instructions below ONLY apply to IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes.

To assign static IPs, declare the VPN_ADDL_IP_ADDRS variable in your env file, then re-create the Docker container. Example:

text
VPN_ADDL_USERS=user1 user2 user3 user4 user5
VPN_ADDL_PASSWORDS=pass1 pass2 pass3 pass4 pass5
VPN_ADDL_IP_ADDRS=* * 192.168.42.2 192.168.43.2

In this example, we assign static IP 192.168.42.2 for user3 for IPsec/L2TP mode, and assign static IP 192.168.43.2 for user4 for IPsec/XAuth ("Cisco IPsec") mode. Internal IPs for user1, user2 and user5 will be auto-assigned. The internal IP for user3 for IPsec/XAuth mode and the internal IP for user4 for IPsec/L2TP mode will also be auto-assigned. You may use * to specify auto-assigned IPs, or put those user(s) at the end of the list.

Static IPs that you specify for IPsec/L2TP mode must be within the range from 192.168.42.2 to 192.168.42.9. Static IPs that you specify for IPsec/XAuth ("Cisco IPsec") mode must be within the range from 192.168.43.2 to 192.168.43.9.

If you need to assign more static IPs, you must shrink the pool of auto-assigned IP addresses. Example:

text
VPN_L2TP_POOL=192.168.42.100-192.168.42.250
VPN_XAUTH_POOL=192.168.43.100-192.168.43.250

This will allow you to assign static IPs within the range from 192.168.42.2 to 192.168.42.99 for IPsec/L2TP mode, and within the range from 192.168.43.2 to 192.168.43.99 for IPsec/XAuth ("Cisco IPsec") mode.

Note that if you specify VPN_XAUTH_POOL in the env file, and IKEv2 is already set up in the Docker container, you must manually edit /etc/ipsec.d/ikev2.conf inside the container and replace rightaddresspool=192.168.43.10-192.168.43.250 with the same value as VPN_XAUTH_POOL, before re-creating the Docker container. Otherwise, IKEv2 may stop working.

Note: In your env file, DO NOT put "" or '' around values, or add space around =. DO NOT use these special characters within values: \ " '.

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, read the previous section.

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) in your env file, then you must re-create the Docker container.

text
# Example: Specify custom VPN subnet for IPsec/L2TP mode
# Note: All three variables must be specified.
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
text
# Example: Specify custom VPN subnet for IPsec/XAuth and IKEv2 modes
# Note: Both variables must be specified.
VPN_XAUTH_NET=10.2.0.0/16
VPN_XAUTH_POOL=10.2.0.10-10.2.254.254

Note: In your env file, DO NOT put "" or '' around values, or add space around =.

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.

Note that if you specify VPN_XAUTH_POOL in the env file, and IKEv2 is already set up in the Docker container, you must manually edit /etc/ipsec.d/ikev2.conf inside the container and replace rightaddresspool=192.168.43.10-192.168.43.250 with the same value as VPN_XAUTH_POOL, before re-creating the Docker container. Otherwise, IKEv2 may stop working.

IPv6 support

If the Docker host has a public (global unicast) IPv6 address and the requirements below are met, IPv6 support for IKEv2 clients is automatically enabled when the container starts. No manual configuration is needed.

Note: IPv6 works without additional configuration when using the strongSwan VPN client on Android. For Windows and macOS clients, follow the platform-specific steps below. iOS clients do not currently support routing IPv6 traffic through the IKEv2 VPN; you may instead use OpenVPN or WireGuard.

Windows: Route IPv6 traffic through the VPN

If you used the ikev2_config_import.cmd script to import IKEv2 configuration, you can answer y when prompted to automatically add IPv6 routes. Otherwise, run the following commands once in a PowerShell window to route IPv6 traffic through the VPN. Replace IKEv2 VPN X.X.X.X with the actual name of your VPN connection. When finished, reconnect to the IKEv2 VPN.

powershell
Add-VpnConnectionRoute -ConnectionName "IKEv2 VPN X.X.X.X" -DestinationPrefix ::/1
Add-VpnConnectionRoute -ConnectionName "IKEv2 VPN X.X.X.X" -DestinationPrefix 8000::/1

macOS: Route IPv6 traffic through the VPN

After connecting to the IKEv2 VPN, run the following command in Terminal to route IPv6 traffic through the VPN. This command must be run each time you connect. The route is automatically removed when you disconnect from the VPN. The interface is usually ipsec0; if you have multiple VPN connections active it may be ipsec1, etc. Run ifconfig | grep ipsec to confirm.

text
sudo route -n add -inet6 default -interface ipsec0

When IPv6 is enabled, IKEv2 VPN clients receive both an IPv4 address from the 192.168.43.0/24 pool and an IPv6 address from the fddd:500:500:500::/64 pool. The container masquerades IPv6 traffic from VPN clients through the host's IPv6 address, giving clients full IPv6 internet access through the tunnel.

Requirements:

  • The Docker host must have a routable global unicast IPv6 address (starting with 2 or 3). Link-local (fe80::/10) addresses are not sufficient.
  • IPv6 must be enabled for the Docker container. See Enable IPv6 support in Docker.
  • Libreswan 5.0 or newer (the Docker image includes 5.x by default).
  • IPv6 is only supported for IKEv2 mode. IPsec/L2TP and IPsec/XAuth ("Cisco IPsec") modes do not support IPv6.

To enable IPv6 for the Docker container, first enable IPv6 in the Docker daemon by adding the following to /etc/docker/daemon.json on the Docker host, then restart Docker:

json
{
  "ipv6": true,
  "fixed-cidr-v6": "fddd:1::/64"
}

After that, re-create the Docker container. The run.sh script will detect the container's public IPv6 address and automatically configure IPv6 support.

To verify that IPv6 is working, connect to the VPN using IKEv2 and check your IPv6 address, e.g. using test-ipv6.com.

Note for existing containers: If IKEv2 is already set up in your container (i.e. ikev2.conf already exists in the ikev2-vpn-data volume), IPv6 will not be automatically added to the existing IKEv2 configuration when the container restarts or is recreated. To enable full IPv6 support for IKEv2, you must remove IKEv2 and set it up again. Refer to "remove IKEv2" in Configure and use IKEv2 VPN.

You may optionally customize the IPv6 pool subnet by setting VPN_IP6_NET in your env file before re-creating the container:

text
# Example: Specify custom IPv6 pool subnet for IKEv2 mode
# Must be a /64 subnet in the ULA range
VPN_IP6_NET=fddd:1234:5678:9012::/64

Split tunneling

With split tunneling, VPN clients will only send traffic for a specific destination subnet 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 IKEv2 mode. Add the variable VPN_SPLIT_IKEV2 to your env file, then re-create the Docker container. For example, if the destination subnet is 10.123.123.0/24:

text
VPN_SPLIT_IKEV2=10.123.123.0/24

Note that this variable has no effect if IKEv2 is already set up in the Docker container. In this case, you have two options:

Option 1: First start a Bash shell inside the container, then edit /etc/ipsec.d/ikev2.conf and replace leftsubnet=0.0.0.0/0 with your desired subnet. When finished, exit the container and run docker restart ipsec-vpn-server.

Option 2: Remove both the Docker container and the ikev2-vpn-data volume, then re-create the Docker container. All VPN configuration will be permanently deleted. Refer to "remove IKEv2" in Configure and use IKEv2 VPN.

Alternatively, Windows users can enable split tunneling by manually adding routes. For more details, see Split tunneling.

About host network mode

Advanced users can run this image in host network mode, by adding --network=host to the docker run command.

Host network mode is NOT recommended for this image, unless your use case requires it. In this mode, the container's network stack is not isolated from the Docker host, and VPN clients may be able to access ports or services on the Docker host using its internal VPN IP 192.168.42.1 after connecting using IPsec/L2TP mode. Note that you will need to manually clean up the changes to IPTables rules and sysctl settings by run.sh or reboot the server when you no longer use this image.

Some Docker host OS, such as Debian 10, cannot run this image in host network mode due to the use of nftables.

Enable Libreswan logs

To keep the Docker image small, Libreswan (IPsec) logs are not enabled by default. If you need to enable it for troubleshooting purposes, first start a Bash session in the running container:

text
docker exec -it ipsec-vpn-server env TERM=xterm bash -l

Then run the following commands:

text
# For Alpine-based image
apk add --no-cache rsyslog
rsyslogd
rc-service ipsec stop; rc-service -D ipsec start >/dev/null 2>&1
sed -i '\|pluto\.pid|a rm -f /var/run/rsyslogd.pid; rsyslogd' /opt/src/run.sh
exit
# For Debian-based image
apt-get update && apt-get -y install rsyslog
rsyslogd
service ipsec restart
sed -i '\|pluto\.pid|a rm -f /var/run/rsyslogd.pid; rsyslogd' /opt/src/run.sh
exit

Note: The error rsyslogd: imklog: cannot open kernel log is normal if you use this Docker image without privileged mode.

When finished, you may check Libreswan logs with:

text
docker exec -it ipsec-vpn-server grep pluto /var/log/auth.log

To check xl2tpd logs, run docker logs ipsec-vpn-server.

Check server status

Check the status of the IPsec VPN server:

text
docker exec -it ipsec-vpn-server ipsec status

Show currently established VPN connections:

text
docker exec -it ipsec-vpn-server ipsec trafficstatus

Build from source code

Advanced users can download and compile the source code from GitHub:

text
git clone https://github.com/hwdsl2/docker-ipsec-vpn-server
cd docker-ipsec-vpn-server
# To build Alpine-based image
docker build -t hwdsl2/ipsec-vpn-server .
# To build Debian-based image
docker build -f Dockerfile.debian -t hwdsl2/ipsec-vpn-server:debian .

Or use this if not modifying the source code:

text
# To build Alpine-based image
docker build -t hwdsl2/ipsec-vpn-server github.com/hwdsl2/docker-ipsec-vpn-server
# To build Debian-based image
docker build -f Dockerfile.debian -t hwdsl2/ipsec-vpn-server:debian \
  github.com/hwdsl2/docker-ipsec-vpn-server

Bash shell inside container

To start a Bash session in the running container:

text
docker exec -it ipsec-vpn-server env TERM=xterm bash -l

(Optional) Install the nano editor:

text
# For Alpine-based image
apk add --no-cache nano
# For Debian-based image
apt-get update && apt-get -y install nano

Then run your commands inside the container. When finished, exit the container and restart if needed:

text
exit
docker restart ipsec-vpn-server

Bind mount the env file

As an alternative to the --env-file option, advanced users can bind mount the env file. The advantage of this method is that after updating the env file, you can restart the Docker container to take effect instead of re-creating it. To use this method, you must first edit your env file and use single quotes '' to enclose the values of all variables. Then (re-)create the Docker container (replace the first vpn.env with your own env file):

text
docker run \
    --name ipsec-vpn-server \
    --restart=always \
    -v "$(pwd)/vpn.env:/opt/src/env/vpn.env:ro" \
    -v ikev2-vpn-data:/etc/ipsec.d \
    -v /lib/modules:/lib/modules:ro \
    -p 500:500/udp \
    -p 4500:4500/udp \
    -d --privileged \
    hwdsl2/ipsec-vpn-server

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 on your Docker host.

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. When finished, restart the Docker container:

text
docker restart ipsec-vpn-server

License

Note: The software components inside the pre-built image (such as Libreswan and xl2tpd) are under the respective licenses chosen by their respective copyright holders. As for any pre-built image usage, it is the image user's responsibility to ensure that any use of this image complies with any relevant licenses for all software contained within.

Copyright (C) 2016-2026 Lin Song


This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License
Attribution required: please include my name in any derivative and let me know how you have improved it!


File: docs/advanced-usage-zh.md

English | 中文

高级用法

使用其他的 DNS 服务器

在 VPN 已连接时,客户端默认配置为使用 Google Public DNS。如果偏好其它的域名解析服务,你可以在 env 文件中定义 VPN_DNS_SRV1 和 VPN_DNS_SRV2(可选),然后按照说明重新创建 Docker 容器。示例如下:

text
VPN_DNS_SRV1=1.1.1.1
VPN_DNS_SRV2=1.0.0.1

使用 VPN_DNS_SRV1 指定主 DNS 服务器,使用 VPN_DNS_SRV2 指定辅助 DNS 服务器(可选)。

请注意,如果 Docker 容器中已经配置了 IKEv2,你还需要编辑 Docker 容器内的 /etc/ipsec.d/ikev2.conf 并将 8.8.8.8 和 8.8.4.4 替换为你的其他的 DNS 服务器,然后重新启动 Docker 容器。

以下是一些流行的公共 DNS 提供商的列表,供你参考。

提供商 主 DNS 辅助 DNS 注释
Google Public DNS 8.8.8.8 8.8.4.4 本项目默认
Cloudflare 1.1.1.1 1.0.0.1 另见:Cloudflare for families
Quad9 9.9.9.9 149.112.112.112 阻止恶意域
OpenDNS 208.67.222.222 208.67.220.220 阻止网络钓鱼域,可配置。
CleanBrowsing 185.228.168.9 185.228.169.9 域过滤器可用
NextDNS 按需选择 按需选择 广告拦截,免费套餐可用。了解更多。
Control D 按需选择 按需选择 广告拦截,可配置。了解更多。

不启用 privileged 模式运行

高级用户可以在不启用 privileged 模式的情况下使用本镜像创建一个 Docker 容器(将以下命令中的 ./vpn.env 替换为你自己的 env 文件)。

注: 如果你的 Docker 主机运行 CentOS Stream, Oracle Linux 8+, Rocky Linux 或者 AlmaLinux,推荐使用 privileged 模式。如果你想要不启用 privileged 模式运行,则 必须 在创建 Docker 容器之前以及系统启动时运行 modprobe ip_tables ip6_tables。

text
docker run \
    --name ipsec-vpn-server \
    --env-file ./vpn.env \
    --restart=always \
    -v ikev2-vpn-data:/etc/ipsec.d \
    -p 500:500/udp \
    -p 4500:4500/udp \
    -d --cap-add=NET_ADMIN \
    --device=/dev/ppp \
    --sysctl net.ipv4.ip_forward=1 \
    --sysctl net.ipv4.conf.all.accept_redirects=0 \
    --sysctl net.ipv4.conf.all.send_redirects=0 \
    --sysctl net.ipv4.conf.all.rp_filter=0 \
    --sysctl net.ipv4.conf.default.accept_redirects=0 \
    --sysctl net.ipv4.conf.default.send_redirects=0 \
    --sysctl net.ipv4.conf.default.rp_filter=0 \
    --sysctl net.ipv6.conf.all.forwarding=1 \
    hwdsl2/ipsec-vpn-server

在不启用 privileged 模式运行时,容器不能更改 sysctl 设置。这可能会影响本镜像的某些功能。一个已知问题是 Android/Linux MTU/MSS fix 需要另外在 docker run 命令添加 --sysctl net.ipv4.ip_no_pmtu_disc=1 才有效。如果你遇到任何问题,可以尝试换用 privileged 模式重新创建容器。

在创建 Docker 容器之后,请转到获取 VPN 登录信息。

类似地,如果你使用 Docker compose,可以将 docker-compose.yml 中的 privileged: true 替换为:

text
cap_add:
    - NET_ADMIN
  devices:
    - "/dev/ppp:/dev/ppp"
  sysctls:
    - net.ipv4.ip_forward=1
    - net.ipv4.conf.all.accept_redirects=0
    - net.ipv4.conf.all.send_redirects=0
    - net.ipv4.conf.all.rp_filter=0
    - net.ipv4.conf.default.accept_redirects=0
    - net.ipv4.conf.default.send_redirects=0
    - net.ipv4.conf.default.rp_filter=0
    - net.ipv6.conf.all.forwarding=1

更多信息请参见 compose file reference。

选择 VPN 模式

在使用此 Docker 镜像时,默认启用 IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式。此外,如果在创建 Docker 容器时在 docker run 命令中指定了 -v ikev2-vpn-data:/etc/ipsec.d 选项,则会启用 IKEv2 模式。

高级用户可以有选择性地禁用 VPN 模式,通过在 env 文件中设置以下变量并重新创建 Docker 容器来实现。

禁用 IPsec/L2TP 模式:VPN_DISABLE_IPSEC_L2TP=yes
禁用 IPsec/XAuth ("Cisco IPsec") 模式:VPN_DISABLE_IPSEC_XAUTH=yes
禁用 IPsec/L2TP 和 IPsec/XAuth 模式:VPN_IKEV2_ONLY=yes

启用 IKEv2 前向保密

默认情况下,IKEv2 子安全关联(Child SA)从现有 IKE SA 派生密钥材料,不进行新的 Diffie-Hellman 交换(pfs=no)。启用前向保密(PFS)后,每次子 SA 重新生成密钥时都会执行新的 DH 交换,从而确保即使服务器私钥在将来遭到泄露,攻击者也无法解密之前录制的会话。

注: IKE SA 已将 ECP-256(aes_gcm_c_256-hmac_sha2_256-ecp_256)作为首选提案,所有现代客户端均会协商使用,因此这些客户端的会话密钥已与长期密钥材料独立。为子 SA 启用 PFS 是一项渐进式安全加固措施,而非关键漏洞修复。

客户端兼容性: 所有现代客户端均支持 PFS。但是,macOS 和 iOS 客户端需要重新导出并导入已将 EnablePFS 设为 1 的 .mobileconfig 配置文件(详见下文)。Windows 客户端需要更新连接配置。RouterOS 用户需将 IKEv2 配置文件中的 pfs-group=none 改为 pfs-group=ecp256。Android 和 Linux strongSwan 客户端无需更改。Windows 7 IKEv2 客户端不支持 ECP PFS 组,若服务器启用 PFS,将无法连接。

要启用 PFS,请先在容器内打开 Bash shell,然后运行:

bash
sed -i 's/pfs=no/pfs=yes/' /etc/ipsec.d/ikev2.conf

完成后,exit 容器并重启:

text
docker restart ipsec-vpn-server

启用 PFS 后,需要更新以下客户端配置:

  • macOS / iOS: 运行 docker exec -it ipsec-vpn-server ikev2.sh --exportclient <名称> 重新导出客户端 .mobileconfig 文件并复制到 Docker 主机,然后编辑导出的文件以启用 PFS:
    bash
    sed -i '/EnablePFS/{n;s/0/1/;}' <名称>.mobileconfig
    在设备上重新导入更新后的文件。
  • Windows: 在提升权限的 PowerShell 窗口中运行 Set-VpnConnection -Name "你的VPN名称" -PfsGroup ECP256(替换为实际的 VPN 连接名称),然后重新连接 VPN。
  • RouterOS (MikroTik): 在 IKEv2 对等配置文件中,将 pfs-group=none 改为 pfs-group=ecp256。

Android 和 Linux strongSwan 客户端无需更改,PFS 会自动协商。

要恢复默认设置(禁用 PFS),请重复上述步骤,但在 sed 命令中将 pfs=yes 替换为 pfs=no。

访问 Docker 主机上的其它容器

连接到 VPN 后,VPN 客户端通常可以访问在同一 Docker 主机上其他容器中运行的服务,而无需进行其他配置。

例如,如果 IPsec VPN 服务器容器的 IP 为 172.17.0.2,并且一个 IP 为 172.17.0.3 的 Nginx 容器在同一 Docker 主机上运行,则 VPN 客户端可以使用 IP 172.17.0.3 来访问 Nginx 容器上的服务。要找出分配给容器的 IP ,可以运行 docker inspect <container name>。

指定 VPN 服务器的公有 IP

在具有多个公有 IP 地址的 Docker 主机上,高级用户可以使用 env 文件中的变量 VPN_PUBLIC_IP 为 VPN 服务器指定一个公有 IP,然后重新创建 Docker 容器。例如,如果 Docker 主机的 IP 为 192.0.2.1 和 192.0.2.2,并且你想要 VPN 服务器使用 192.0.2.2:

text
VPN_PUBLIC_IP=192.0.2.2

请注意,如果在 Docker 容器中已经配置了 IKEv2,则此变量对 IKEv2 模式无效。在这种情况下,你可以移除 IKEv2 并使用自定义选项重新配置它。参见配置并使用 IKEv2 VPN。

如果你想要 VPN 客户端在 VPN 连接处于活动状态时使用指定的公有 IP 作为其 "出站 IP",并且指定的 IP 不是 Docker 主机上的主 IP(或默认路由),则可能需要额外的配置。在这种情况下,你可以尝试在 Docker 主机上添加一个 IPTables SNAT 规则。如果要在重启后继续有效,你可以将命令添加到 /etc/rc.local。

继续上面的例子,如果 Docker 容器具有内部 IP 172.17.0.2(使用 docker inspect ipsec-vpn-server 查看),Docker 的网络接口名称为 docker0(使用 iptables -nvL -t nat 查看),并且你希望 "出站 IP" 为 192.0.2.2:

text
iptables -t nat -I POSTROUTING -s 172.17.0.2 ! -o docker0 -j SNAT --to 192.0.2.2

要检查一个已连接的 VPN 客户端的 "出站 IP",你可以在该客户端上打开浏览器并到这里检测 IP 地址。

为 VPN 客户端指定静态 IP

在使用 IPsec/L2TP 模式连接时,VPN 服务器(Docker 容器)在虚拟网络 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") 或 IKEv2 模式连接时,VPN 服务器(Docker 容器)在虚拟网络 192.168.43.0/24 内 没有 内网 IP。为客户端分配的内网 IP 在这个范围内:192.168.43.10 到 192.168.43.250。

高级用户可以将静态 IP 分配给 VPN 客户端。这是可选的。对于 IKEv2 模式,首先在容器中运行 Bash shell,然后按照VPN 内网 IP 和流量中的 "IKEv2 模式:为 VPN 客户端分配静态 IP" 小节中的步骤操作。请注意,你需要跳过第 2, 3 和 5 步,并且在完成后重启 Docker 容器。这是因为对 /etc/ipsec.conf 的修改可能会在重启容器时被覆盖。

以下说明 仅适用于 IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式。

要分配静态 IP,在你的 env 文件中定义 VPN_ADDL_IP_ADDRS 变量,然后重新创建 Docker 容器。例如:

text
VPN_ADDL_USERS=user1 user2 user3 user4 user5
VPN_ADDL_PASSWORDS=pass1 pass2 pass3 pass4 pass5
VPN_ADDL_IP_ADDRS=* * 192.168.42.2 192.168.43.2

在此示例中,我们为 IPsec/L2TP 模式的 user3 分配静态 IP 192.168.42.2,并为 IPsec/XAuth ("Cisco IPsec") 模式的 user4 分配静态 IP 192.168.43.2。user1, user2 和 user5 的内网 IP 将被自动分配。user3 在 IPsec/XAuth 模式下的内网 IP 和 user4 在 IPsec/L2TP 模式下的内网 IP 也将被自动分配。你可以使用 * 来指定自动分配的 IP,或者将这些用户放在列表的末尾。

你为 IPsec/L2TP 模式指定的静态 IP 必须在 192.168.42.2 到 192.168.42.9 范围内。你为 IPsec/XAuth ("Cisco IPsec") 模式指定的静态 IP 必须在 192.168.43.2 到 192.168.43.9 范围内。

如果你需要分配更多静态 IP,则必须缩小自动分配的 IP 地址池。示例如下:

text
VPN_L2TP_POOL=192.168.42.100-192.168.42.250
VPN_XAUTH_POOL=192.168.43.100-192.168.43.250

这将允许你为 IPsec/L2TP 模式在 192.168.42.2 到 192.168.42.99 范围内分配静态 IP,并且为 IPsec/XAuth ("Cisco IPsec") 模式在 192.168.43.2 到 192.168.43.99 范围内分配静态 IP。

请注意,如果你在 env 文件中指定了 VPN_XAUTH_POOL,并且在 Docker 容器中已经配置了 IKEv2,你 必须 在重新创建 Docker 容器之前手动编辑容器内的 /etc/ipsec.d/ikev2.conf 并将 rightaddresspool=192.168.43.10-192.168.43.250 替换为与 VPN_XAUTH_POOL 相同的值。否则 IKEv2 可能会停止工作。

注: 在你的 env 文件中,不要为变量值添加 "" 或者 '',或在 = 两边添加空格。不要在值中使用这些字符: \ " '。

自定义 VPN 子网

默认情况下,IPsec/L2TP VPN 客户端将使用内部 VPN 子网 192.168.42.0/24,而 IPsec/XAuth ("Cisco IPsec") 和 IKEv2 VPN 客户端将使用内部 VPN 子网 192.168.43.0/24。有关更多详细信息,请阅读上一节。

对于大多数用例,没有必要也 不建议 自定义这些子网。但是,如果你的用例需要它,你可以在 env 文件中指定自定义子网,然后你必须重新创建 Docker 容器。

text
# 示例:为 IPsec/L2TP 模式指定自定义 VPN 子网
# 注:必须指定所有三个变量。
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
text
# 示例:为 IPsec/XAuth 和 IKEv2 模式指定自定义 VPN 子网
# 注:必须指定以下两个变量。
VPN_XAUTH_NET=10.2.0.0/16
VPN_XAUTH_POOL=10.2.0.10-10.2.254.254

注: 在你的 env 文件中,不要为变量值添加 "" 或者 '',或在 = 两边添加空格。

在上面的例子中,VPN_L2TP_LOCAL 是在 IPsec/L2TP 模式下的 VPN 服务器的内网 IP。VPN_L2TP_POOL 和 VPN_XAUTH_POOL 是为 VPN 客户端自动分配的 IP 地址池。

请注意,如果你在 env 文件中指定了 VPN_XAUTH_POOL,并且在 Docker 容器中已经配置了 IKEv2,你 必须 在重新创建 Docker 容器之前手动编辑容器内的 /etc/ipsec.d/ikev2.conf 并将 rightaddresspool=192.168.43.10-192.168.43.250 替换为与 VPN_XAUTH_POOL 相同的值。否则 IKEv2 可能会停止工作。

IPv6 支持

如果 Docker 宿主机拥有公共(全局单播)IPv6 地址并且满足以下要求,IKEv2 客户端的 IPv6 支持将在容器启动时自动启用,无需手动配置。

注: 在 Android 上使用 strongSwan VPN 客户端时,IPv6 无需额外配置即可正常工作。对于 Windows 和 macOS 客户端,请按照以下平台特定步骤进行配置。iOS 客户端目前不支持通过 IKEv2 VPN 路由 IPv6 流量;你可以改用 OpenVPN 或 WireGuard。

Windows:通过 VPN 路由 IPv6 流量

如果你使用了 ikev2_config_import.cmd 脚本导入 IKEv2 配置,可以在提示时输入 y 以自动添加 IPv6 路由。否则,你需要在 PowerShell 窗口中运行以下命令一次,以通过 VPN 路由 IPv6 流量。将 IKEv2 VPN X.X.X.X 替换为你的 VPN 连接的实际名称。完成后,重新连接到 IKEv2 VPN。

powershell
Add-VpnConnectionRoute -ConnectionName "IKEv2 VPN X.X.X.X" -DestinationPrefix ::/1
Add-VpnConnectionRoute -ConnectionName "IKEv2 VPN X.X.X.X" -DestinationPrefix 8000::/1

macOS:通过 VPN 路由 IPv6 流量

连接到 IKEv2 VPN 后,需要在终端中运行以下命令以通过 VPN 路由 IPv6 流量。每次连接后都需要运行此命令。断开 VPN 时,该路由将自动删除。接口通常为 ipsec0;如果同时有多个 VPN 连接处于活动状态,可能为 ipsec1 等,运行 ifconfig | grep ipsec 确认。

text
sudo route -n add -inet6 default -interface ipsec0

启用 IPv6 后,IKEv2 VPN 客户端将同时获得来自 192.168.43.0/24 地址池的 IPv4 地址和来自 fddd:500:500:500::/64 地址池的 IPv6 地址。容器会将来自 VPN 客户端的 IPv6 流量通过宿主机的 IPv6 地址进行伪装(NAT),使 VPN 客户端通过隧道获得完整的 IPv6 互联网访问。

要求:

  • Docker 宿主机必须拥有可路由的全局单播 IPv6 地址(以 2 或 3 开头)。链路本地地址 (fe80::/10) 不满足要求。
  • 必须为 Docker 容器启用 IPv6。参见在 Docker 中启用 IPv6 支持。
  • Libreswan 5.0 或更新版本(Docker 镜像默认包含 5.x)。
  • IPv6 仅支持 IKEv2 模式。IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式不支持 IPv6。

要为 Docker 容器启用 IPv6,首先在 Docker 宿主机上将以下内容添加到 /etc/docker/daemon.json,然后重启 Docker:

json
{
  "ipv6": true,
  "fixed-cidr-v6": "fddd:1::/64"
}

然后重新创建容器。run.sh 脚本将检测容器的公共 IPv6 地址并自动配置 IPv6 支持。

要验证 IPv6 是否正常工作,请使用 IKEv2 连接到 VPN,然后检查你的 IPv6 地址,例如使用 test-ipv6.com。

现有容器注意事项: 如果你的容器中已经配置了 IKEv2(即 ikev2-vpn-data 卷中已存在 ikev2.conf),在容器重启或重新创建时 IPv6 不会自动添加到现有的 IKEv2 配置中。要为 IKEv2 启用完整的 IPv6 支持,必须移除 IKEv2 并重新配置。参见配置并使用 IKEv2 VPN 中的"移除 IKEv2"部分。

你也可以在 env 文件中设置 VPN_IP6_NET,在重新创建容器之前自定义 IPv6 地址池子网:

text
# 示例:为 IKEv2 模式指定自定义 IPv6 地址池子网
# 必须是 ULA 范围内的 /64 子网
VPN_IP6_NET=fddd:1234:5678:9012::/64

VPN 分流

在启用 VPN 分流 (split tunneling) 时,VPN 客户端将仅通过 VPN 隧道发送特定目标子网的流量。其他流量 不会 通过 VPN 隧道。这允许你通过 VPN 安全访问指定的网络,而无需通过 VPN 发送所有客户端的流量。VPN 分流有一些局限性,而且并非所有的 VPN 客户端都支持。

高级用户可以为 IKEv2 模式启用 VPN 分流。这是可选的。将变量 VPN_SPLIT_IKEV2 添加到你的 env 文件,然后重新创建 Docker 容器。例如,如果目标子网是 10.123.123.0/24:

text
VPN_SPLIT_IKEV2=10.123.123.0/24

请注意,如果在 Docker 容器中已经配置了 IKEv2,则此变量无效。在这种情况下,有两个选项:

选项 1: 首先在容器中运行 Bash shell,然后编辑 /etc/ipsec.d/ikev2.conf 并将 leftsubnet=0.0.0.0/0 替换为你想要的子网。在完成后,退出容器并运行 docker restart ipsec-vpn-server。

选项 2: 删除 Docker 容器以及 ikev2-vpn-data 卷,然后重新创建容器。这将永久删除所有的 VPN 配置。参见配置并使用 IKEv2 VPN 中的"移除 IKEv2"部分。

另外,Windows 用户也可以通过手动添加路由的方式启用 VPN 分流。有关详细信息,请参阅 VPN 分流。

关于 host network 模式

高级用户可以使用 host network 模式运行本镜像,通过为 docker run 命令添加 --network=host 参数来实现。

在非必要的情况下,不推荐使用 host network 模式运行本镜像。在该模式下,容器的网络栈未与 Docker 主机隔离,从而在使用 IPsec/L2TP 模式连接之后,VPN 客户端可以使用 Docker 主机的 VPN 内网 IP 192.168.42.1 访问主机上的端口或服务。请注意,当你不再使用本镜像时,你需要手动清理 run.sh 所更改的 IPTables 规则和 sysctl 设置,或者重启服务器。

某些 Docker 主机操作系统,比如 Debian 10,不能使用 host network 模式运行本镜像,因为它们使用 nftables。

启用 Libreswan 日志

为了保持较小的 Docker 镜像,Libreswan (IPsec) 日志默认未开启。如果你需要启用它以进行故障排除,首先在正在运行的 Docker 容器中开始一个 Bash 会话:

text
docker exec -it ipsec-vpn-server env TERM=xterm bash -l

然后运行以下命令:

text
# For Alpine-based image
apk add --no-cache rsyslog
rsyslogd
rc-service ipsec stop; rc-service -D ipsec start >/dev/null 2>&1
sed -i '\|pluto\.pid|a rm -f /var/run/rsyslogd.pid; rsyslogd' /opt/src/run.sh
exit
# For Debian-based image
apt-get update && apt-get -y install rsyslog
rsyslogd
service ipsec restart
sed -i '\|pluto\.pid|a rm -f /var/run/rsyslogd.pid; rsyslogd' /opt/src/run.sh
exit

注: 如果你在不启用 privileged 模式的情况下使用本镜像,则错误 rsyslogd: imklog: cannot open kernel log 是正常的。

完成后你可以这样查看 Libreswan 日志:

text
docker exec -it ipsec-vpn-server grep pluto /var/log/auth.log

如需查看 xl2tpd 日志,请运行 docker logs ipsec-vpn-server。

查看服务器状态

检查 IPsec VPN 服务器状态:

text
docker exec -it ipsec-vpn-server ipsec status

查看当前已建立的 VPN 连接:

text
docker exec -it ipsec-vpn-server ipsec trafficstatus

从源代码构建

高级用户可以从 GitHub 下载并自行编译源代码:

text
git clone https://github.com/hwdsl2/docker-ipsec-vpn-server
cd docker-ipsec-vpn-server
# To build Alpine-based image
docker build -t hwdsl2/ipsec-vpn-server .
# To build Debian-based image
docker build -f Dockerfile.debian -t hwdsl2/ipsec-vpn-server:debian .

若不需要改动源码,也可以这样:

text
# To build Alpine-based image
docker build -t hwdsl2/ipsec-vpn-server github.com/hwdsl2/docker-ipsec-vpn-server
# To build Debian-based image
docker build -f Dockerfile.debian -t hwdsl2/ipsec-vpn-server:debian \
  github.com/hwdsl2/docker-ipsec-vpn-server

在容器中运行 Bash shell

在正在运行的 Docker 容器中开始一个 Bash 会话:

text
docker exec -it ipsec-vpn-server env TERM=xterm bash -l

(可选步骤)安装 nano 编辑器:

text
# For Alpine-based image
apk add --no-cache nano
# For Debian-based image
apt-get update && apt-get -y install nano

然后在容器中运行你的命令。完成后退出并重启 Docker 容器(如果需要):

text
exit
docker restart ipsec-vpn-server

绑定挂载 env 文件

作为 --env-file 选项的替代方案,高级用户可以绑定挂载 env 文件。该方法的好处是你在更新 env 文件之后可以重启 Docker 容器以生效,而不需要重新创建它。要使用这个方法,你必须首先编辑你的 env 文件并将所有的变量值用单引号 '' 括起来。然后(重新)创建 Docker 容器(将第一个 vpn.env 替换为你自己的 env 文件):

text
docker run \
    --name ipsec-vpn-server \
    --restart=always \
    -v "$(pwd)/vpn.env:/opt/src/env/vpn.env:ro" \
    -v ikev2-vpn-data:/etc/ipsec.d \
    -v /lib/modules:/lib/modules:ro \
    -p 500:500/udp \
    -p 4500:4500/udp \
    -d --privileged \
    hwdsl2/ipsec-vpn-server

部署 Google BBR 拥塞控制

VPN 服务器搭建完成后,可以通过在 Docker 主机上部署 Google BBR 拥塞控制算法提升性能。

这通常只需要在配置文件 /etc/sysctl.conf 中插入设定即可完成。但是部分 Linux 发行版可能需要额外更新 Linux 内核。

详细的部署方法,可以参考这篇文档。在完成后重启 Docker 容器:

text
docker restart ipsec-vpn-server

授权协议

注: 预构建镜像中的软件组件(例如 Libreswan 和 xl2tpd)在其各自版权所有者选择的相应许可下。对于任何预构建的镜像的使用,用户有责任确保对该镜像的任何使用符合其中包含的所有软件的任何相关许可。

版权所有 (C) 2016-2026 Lin Song


这个项目是以知识共享署名-相同方式共享3.0 许可协议授权。
必须署名: 请包括我的名字在任何衍生产品,并且让我知道你是如何改善它的!


File: docs/vpn-book.md

« Back to home page | English | 简体中文 | 繁體中文

New: Privacy Tools in the Age of AI

Learn how to build next-level privacy protection in the age of AI. This book is available in eBook, print and audiobook formats on:

» Amazon
» Google Play
» Apple Books
» Hoopla
» Other Platforms

Other language versions: Español, Deutsch, Français, Italiano.

Build Your Own VPN Server: A Step by Step Guide

This book is a step-by-step guide to building your own IPsec VPN, OpenVPN and WireGuard server. Available in eBook, print and audiobook formats on:

» Amazon
» Google Play
» Apple Books
» Hoopla
» Other Platforms

Other language versions: 简体中文, 繁體中文, Español, Deutsch, Français, Italiano, Nederlands, Português, 日本語.

Set Up Your Own IPsec VPN, OpenVPN and WireGuard Server

This book is a comprehensive guide to building your own IPsec VPN, OpenVPN and WireGuard server. Available in eBook, print and audiobook formats on:

» Amazon
» Google Play
» Apple Books
» Hoopla
» Other Platforms

Other language versions: 简体中文, 繁體中文, Español, Deutsch, Français, Italiano, 日本語.

Author page: amazon.com/author/linsong


File: docs/vpn-book-zh.md

« 返回主页 | English | 简体中文 | 繁體中文

新:Privacy Tools in the Age of AI

了解如何在人工智能时代构建更高级别的隐私保护。本书提供电子书、精装本、平装本和有声读物格式。

» Amazon
» Google Play
» Apple Books
» Hoopla
» 其他平台

其他语言版本:Español、Deutsch、Français、Italiano。

搭建自己的 VPN 服务器:IPsec VPN、OpenVPN 与 WireGuard 实战指南

本书是搭建你自己的 IPsec VPN、OpenVPN 和 WireGuard 服务器的实战指南。提供电子书和平装本格式。

» Google Play
» Apple Books
» Amazon
» Amazon 平装本
» 其他平台

其他语言版本:繁體中文、English、Español、Deutsch、Français、Italiano、Nederlands、Português、日本語。

搭建自己的 VPN 服务器:IPsec VPN、OpenVPN 与 WireGuard 完整指南

本书是搭建你自己的 IPsec VPN、OpenVPN 和 WireGuard 服务器的完整指南。提供电子书和平装本格式。

» Google Play
» Apple Books
» Amazon
» Amazon 平装本
» 其他平台

其他语言版本:繁體中文、English、Español、Deutsch、Français、Italiano、日本語。

作者页面:amazon.com/author/linsong


File: README-zh.md

English | 简体中文 | 繁體中文 | Русский

Docker 上的 IPsec VPN 服务器

使用这个 Docker 镜像快速搭建 IPsec VPN 服务器。支持 IPsec/L2TP,Cisco IPsec 和 IKEv2 协议。

本镜像以 Alpine 3.23 或 Debian 12 为基础,并使用 Libreswan (IPsec VPN 软件) 和 xl2tpd (L2TP 服务进程)。

IPsec VPN 可以加密你的网络流量,以防止在通过因特网传送时,你和 VPN 服务器之间的任何人对你的数据的未经授权的访问。在使用不安全的网络时,这是特别有用的,例如在咖啡厅,机场或旅馆房间。

功能特性:

  • 首次启动时自动生成 VPN 凭证和 IKEv2 配置
  • 支持具有强大和快速加密算法(例如 AES-GCM)的 IKEv2 模式
  • 生成 VPN 配置文件以自动配置 iOS, macOS 和 Android 设备
  • 支持 Windows, macOS, iOS, Android, Chrome OS 和 Linux 客户端
  • 包括辅助脚本以管理 IKEv2 用户和证书
  • 通过 GitHub Actions 自动构建和发布
  • 使用 Docker 卷实现数据持久化
  • 多架构支持:linux/amd64、linux/arm64、linux/arm/v7

另提供:

快速开始

使用以下命令在 Docker 上快速搭建 IPsec VPN 服务器:

bash
docker run \
    --name ipsec-vpn-server \
    --restart=always \
    -v ikev2-vpn-data:/etc/ipsec.d \
    -v /lib/modules:/lib/modules:ro \
    -p 500:500/udp \
    -p 4500:4500/udp \
    -d --privileged \
    hwdsl2/ipsec-vpn-server

你的 VPN 登录凭证将会被自动随机生成。请参见获取 VPN 登录信息。

另外,你也可以在不使用 Docker 的情况下安装 IPsec VPN。要了解更多有关如何使用本镜像的信息,请继续阅读以下部分。

社区

  • 📬 订阅项目更新(每月 1–2 封邮件)——获取免费的 VPN 和 AI 部署指南(PDF,英文)
  • 💬 加入 r/selfhostedstack 社区参与讨论
  • ⭐ 如果你觉得本项目有用,请为仓库加星——这有助于让更多人发现它。

系统要求

  • 具有公网 IP 地址或 DNS 名称的 Linux 服务器
  • 已安装 Docker
  • 在防火墙中开放 VPN 端口(UDP 500 和 4500)
  • 你也可以使用 Podman 运行本镜像,需要首先为 docker 命令创建一个别名

注: 高级用户可以在 macOS 上通过安装 Docker for Mac 使用本镜像。在使用 IPsec/L2TP 模式之前,你可能需要运行 docker restart ipsec-vpn-server 重启一次容器。本镜像不支持 Docker for Windows。

下载

预构建的可信任镜像可在 Docker Hub registry 下载:

bash
docker pull hwdsl2/ipsec-vpn-server

或者,你也可以从 Quay.io 下载:

bash
docker pull quay.io/hwdsl2/ipsec-vpn-server
docker image tag quay.io/hwdsl2/ipsec-vpn-server hwdsl2/ipsec-vpn-server

支持的平台:linux/amd64、linux/arm64 和 linux/arm/v7。

高级用户可以自己从 GitHub 编译源代码。

镜像对照表

有两个预构建的镜像可用。默认的基于 Alpine 的镜像大小仅 ~19 MB。

基于 Alpine 基于 Debian
镜像名称 hwdsl2/ipsec-vpn-server hwdsl2/ipsec-vpn-server:debian
压缩后大小 ~ 19 MB ~ 62 MB
基础镜像 Alpine Linux 3.23 Debian Linux 12
系统架构 amd64, arm64, arm/v7 amd64, arm64, arm/v7
Libreswan 版本 5.3.2 5.3.2
IPsec/L2TP ✅ ✅
Cisco IPsec ✅ ✅
IKEv2 ✅ ✅

注: 要使用基于 Debian 的镜像,请将本自述文件中所有的 hwdsl2/ipsec-vpn-server 替换为 hwdsl2/ipsec-vpn-server:debian。这些镜像当前与 Synology NAS 系统不兼容。

我需要使用较旧版本的 Libreswan 版本 4。

一般建议使用最新的 Libreswan 版本 5,它是本项目的默认版本。但是,如果你想要使用较旧版本的 Libreswan 版本 4,你可以从源代码构建 Docker 镜像:

bash
git clone https://github.com/hwdsl2/docker-ipsec-vpn-server
cd docker-ipsec-vpn-server
# Specify Libreswan version 4
sed -i 's/SWAN_VER=5\..*/SWAN_VER=4.15/' Dockerfile Dockerfile.debian
# To build Alpine-based image
docker build -t hwdsl2/ipsec-vpn-server .
# To build Debian-based image
docker build -f Dockerfile.debian -t hwdsl2/ipsec-vpn-server:debian .

如何使用本镜像

环境变量

注: 所有这些变量对于本镜像都是可选的,也就是说无需定义它们就可以搭建 IPsec VPN 服务器。你可以运行 touch vpn.env 创建一个空的 env 文件,然后跳到下一节。

这个 Docker 镜像使用以下几个变量,可以在一个 env 文件中定义(参见示例):

text
VPN_IPSEC_PSK=your_ipsec_pre_shared_key
VPN_USER=your_vpn_username
VPN_PASSWORD=your_vpn_password

这将创建一个用于 VPN 登录的用户账户,它可以在你的多个设备上使用*。 IPsec PSK (预共享密钥) 由 VPN_IPSEC_PSK 环境变量指定。 VPN 用户名和密码分别在 VPN_USER 和 VPN_PASSWORD 中定义。

支持创建额外的 VPN 用户,如果需要,可以像下面这样在你的 env 文件中定义。用户名和密码必须分别使用空格进行分隔,并且用户名不能有重复。所有的 VPN 用户将共享同一个 IPsec PSK。

text
VPN_ADDL_USERS=additional_username_1 additional_username_2
VPN_ADDL_PASSWORDS=additional_password_1 additional_password_2

以上变量仅适用于 IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式。对于 IKEv2,参见配置并使用 IKEv2 VPN。

注: 在你的 env 文件中,不要为变量值添加 "" 或者 '',或在 = 两边添加空格。不要在值中使用这些字符: \ " '。一个安全的 IPsec PSK 应该至少包含 20 个随机字符。

注: 如果在创建 Docker 容器后修改 env 文件,则必须删除并重新创建容器才能使更改生效。参见更新 Docker 镜像。

其他环境变量

高级用户可以指定一个域名,客户端名称和/或另外的 DNS 服务器。这是可选的。

了解如何指定一个域名,客户端名称和/或另外的 DNS 服务器。

高级用户可以指定一个域名作为 IKEv2 服务器地址。这是可选的。该域名必须是一个全称域名 (FQDN)。示例如下:

text
VPN_DNS_NAME=vpn.example.com

你可以指定第一个 IKEv2 客户端的名称。该名称不能包含空格或者除 - _ 之外的任何特殊字符。如果未指定,则使用默认值 vpnclient。

text
VPN_CLIENT_NAME=your_client_name

在 VPN 已连接时,客户端默认配置为使用 Google Public DNS。你可以为所有的 VPN 模式指定另外的 DNS 服务器。示例如下:

text
VPN_DNS_SRV1=1.1.1.1
VPN_DNS_SRV2=1.0.0.1

有关详细信息以及一些流行的公共 DNS 提供商的列表,参见使用其他的 DNS 服务器。

默认情况下,导入 IKEv2 客户端配置时不需要密码。你可以选择使用随机密码保护客户端配置文件。

text
VPN_PROTECT_CONFIG=yes

注: 如果在 Docker 容器中已经配置了 IKEv2,则以上变量对 IKEv2 模式无效。在这种情况下,你可以移除 IKEv2 并使用自定义选项重新配置它。参见配置并使用 IKEv2 VPN。

运行 IPsec VPN 服务器

使用本镜像创建一个新的 Docker 容器(将 ./vpn.env 替换为你自己的 env 文件):

bash
docker run \
    --name ipsec-vpn-server \
    --env-file ./vpn.env \
    --restart=always \
    -v ikev2-vpn-data:/etc/ipsec.d \
    -v /lib/modules:/lib/modules:ro \
    -p 500:500/udp \
    -p 4500:4500/udp \
    -d --privileged \
    hwdsl2/ipsec-vpn-server

在该命令中,我们使用 docker run 的 -v 选项来创建一个名为 ikev2-vpn-data 的新 Docker 卷,并且将它挂载到容器内的 /etc/ipsec.d 目录下。IKEv2 的相关数据(比如证书和密钥)在该卷中保存,之后当你需要重新创建 Docker 容器的时候,只需指定同一个卷。

推荐在使用本镜像时启用 IKEv2。如果你不想启用 IKEv2 而仅使用 IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 模式连接到 VPN,可以去掉上面 docker run 命令中的第一个 -v 选项。

注: 高级用户也可以不启用 privileged 模式运行。

获取 VPN 登录信息

如果你在上述 docker run 命令中没有指定 env 文件,VPN_USER 会默认为 vpnuser,并且 VPN_IPSEC_PSK 和 VPN_PASSWORD 会被自动随机生成。要获取这些登录信息,可以查看容器的日志:

bash
docker logs ipsec-vpn-server

在命令输出中查找这些行:

text
Connect to your new VPN with these details:

Server IP: 你的VPN服务器IP
IPsec PSK: 你的IPsec预共享密钥
Username: 你的VPN用户名
Password: 你的VPN密码

在命令输出中也会包含 IKEv2 配置信息(如果已启用)。

(可选步骤)备份自动生成的 VPN 登录信息(如果有)到当前目录:

bash
docker cp ipsec-vpn-server:/etc/ipsec.d/vpn-gen.env ./

使用 docker-compose

bash
cp vpn.env.example vpn.env
# 如果需要,编辑 vpn.env,然后:
docker compose up -d
docker logs ipsec-vpn-server

示例 docker-compose.yml(已包含在内):

yaml
volumes:
  ikev2-vpn-data:

services:
  vpn:
    image: hwdsl2/ipsec-vpn-server
    restart: always
    env_file:
      - ./vpn.env
    ports:
      - "500:500/udp"
      - "4500:4500/udp"
    privileged: true
    hostname: ipsec-vpn-server
    container_name: ipsec-vpn-server
    volumes:
      - ikev2-vpn-data:/etc/ipsec.d
      - /lib/modules:/lib/modules:ro

下一步

其他语言版本: English, 简体中文, 繁體中文, Русский。

配置你的计算机或其它设备使用 VPN。请参见:

配置并使用 IKEv2 VPN(推荐)

配置 IPsec/L2TP VPN 客户端

配置 IPsec/XAuth ("Cisco IPsec") VPN 客户端

阅读 :book: VPN book 以访问额外内容。

开始使用自己的专属 VPN! :sparkles::tada::rocket::sparkles:

重要提示

Windows 用户 对于 IPsec/L2TP 模式,在首次连接之前需要修改注册表,以解决 VPN 服务器或客户端与 NAT(比如家用路由器)的兼容问题。

同一个 VPN 账户可以在你的多个设备上使用。但是由于 IPsec/L2TP 的局限性,如果需要连接在同一个 NAT(比如家用路由器)后面的多个设备,你必须使用 IKEv2 或者 IPsec/XAuth 模式。

如需添加,修改或者删除 VPN 用户账户,首先更新你的 env 文件,然后你必须按照下一节的说明来删除并重新创建 Docker 容器。高级用户可以绑定挂载 env 文件。

对于有外部防火墙的服务器(比如 EC2/GCE),请为 VPN 打开 UDP 端口 500 和 4500。阿里云用户请参见 #433。

在 VPN 已连接时,客户端配置为使用 Google Public DNS。如果偏好其它的域名解析服务,请看这里。

更新 Docker 镜像

要更新 Docker 镜像和容器,首先下载最新版本:

bash
docker pull hwdsl2/ipsec-vpn-server

如果 Docker 镜像已经是最新的,你会看到提示:

text
Status: Image is up to date for hwdsl2/ipsec-vpn-server:latest

否则将会下载最新版本。要更新你的 Docker 容器,首先记下你所有的 VPN 登录信息。然后删除 Docker 容器: docker rm -f ipsec-vpn-server。最后按照如何使用本镜像的说明来重新创建它。

配置并使用 IKEv2 VPN

IKEv2 模式是比 IPsec/L2TP 和 IPsec/XAuth ("Cisco IPsec") 更佳的连接模式,该模式无需 IPsec PSK, 用户名或密码。更多信息请看这里。

首先,查看容器的日志以获取 IKEv2 配置信息:

bash
docker logs ipsec-vpn-server

注: 如果你无法找到 IKEv2 配置信息,IKEv2 可能没有在容器中启用。尝试按照更新 Docker 镜像一节的说明更新 Docker 镜像和容器。

在 IKEv2 安装过程中会创建一个 IKEv2 客户端(默认名称为 vpnclient),并且导出它的配置到 容器内 的 /etc/ipsec.d 目录下。你可以将配置文件复制到 Docker 主机:

bash
# 查看容器内的 /etc/ipsec.d 目录的文件
docker exec -it ipsec-vpn-server ls -l /etc/ipsec.d
# 示例:将一个客户端配置文件从容器复制到 Docker 主机当前目录
docker cp ipsec-vpn-server:/etc/ipsec.d/vpnclient.p12 ./

下一步: 配置你的设备以使用 IKEv2 VPN。

了解如何管理 IKEv2 客户端。

你可以使用辅助脚本管理 IKEv2 客户端。示例如下。如需自定义客户端选项,可以在不添加参数的情况下运行脚本。

bash
# 添加一个客户端(使用默认选项)
docker exec -it ipsec-vpn-server ikev2.sh --addclient [client name]
# 导出一个已有的客户端的配置
docker exec -it ipsec-vpn-server ikev2.sh --exportclient [client name]
# 列出已有的客户端
docker exec -it ipsec-vpn-server ikev2.sh --listclients
# 显示使用信息
docker exec -it ipsec-vpn-server ikev2.sh -h

注: 如果你遇到错误 "executable file not found",将上面的 ikev2.sh 换成 /opt/src/ikev2.sh。

了解如何更改 IKEv2 服务器地址。

在某些情况下,你可能需要更改 IKEv2 服务器地址。例如切换为使用域名,或者在服务器的 IP 更改之后。要更改 IKEv2 服务器地址,首先在容器中运行 Bash shell,然后按照这里的说明操作。请注意,容器的日志在你重启 Docker 容器之前将不显示新的 IKEv2 服务器地址。

移除 IKEv2 并使用自定义选项重新配置。

在某些情况下,你可能需要移除 IKEv2 并使用自定义选项重新配置它。

警告: 这将永久删除所有的 IKEv2 配置(包括证书和密钥),并且不可撤销!

选项 1: 使用辅助脚本移除 IKEv2 并重新配置。

请注意,这将覆盖你在 env 文件中指定的变量,例如 VPN_DNS_NAME 和 VPN_CLIENT_NAME,并且容器的日志将不再显示 IKEv2 的最新信息。

bash
# 移除 IKEv2 并删除所有的 IKEv2 配置
docker exec -it ipsec-vpn-server ikev2.sh --removeikev2
# 使用自定义选项重新配置 IKEv2
docker exec -it ipsec-vpn-server ikev2.sh

选项 2: 移除 ikev2-vpn-data 并重新创建容器。

  1. 在纸上记下你所有的 VPN 登录信息。
  2. 删除 Docker 容器:docker rm -f ipsec-vpn-server。
  3. 删除 ikev2-vpn-data 卷:docker volume rm ikev2-vpn-data。
  4. 更新你的 env 文件并添加自定义 IKEv2 选项,例如 VPN_DNS_NAME 和 VPN_CLIENT_NAME,然后重新创建容器。参见如何使用本镜像。

高级用法

请参见高级用法。

技术细节

需要运行以下两个服务:Libreswan (pluto) 提供 IPsec VPN,xl2tpd 提供 L2TP 支持。

默认的 IPsec 配置支持以下协议:

  • IPsec/L2TP with PSK
  • IKEv1 with PSK and XAuth ("Cisco IPsec")
  • IKEv2

所需端口:500/udp 和 4500/udp(IPsec)

授权协议

注: 预构建镜像中的软件组件(例如 Libreswan 和 xl2tpd)在其各自版权所有者选择的相应许可下。对于任何预构建的镜像的使用,用户有责任确保对该镜像的任何使用符合其中包含的所有软件的任何相关许可。

版权所有 (C) 2016-2026 Lin Song
基于 Thomas Sarlandie 的工作 (版权所有 2012)


这个项目是以知识共享署名-相同方式共享3.0 许可协议授权。
必须署名: 请包括我的名字在任何衍生产品,并且让我知道你是如何改善它的!