openvpn自建记录

用docker自建VPN,在此记录下过程:

提前配置好docker镜像源,多配置几个以便成功拉取镜像

# 创建数据目录
OVPN_DATA="ovpn-data"
sudo mkdir -p $OVPN_DATA

# 拉取镜像
sudo docker pull kylemanna/openvpn

# 初始化配置。将 `vpn.example.com` 替换为你的公网服务器IP或域名。
sudo docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://vpn.example.com

# 生成证书和密钥。此命令会交互式地要求你设置CA密码和服务器端证书信息。
sudo docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki
挂载数据卷
OVPN_DATA="ovpn-data"
docker volume create --name $OVPN_DATA
列出数据卷
docker volume ls
查看数据卷存储文职
docker volume inspect <卷名>

在执行 ovpn_initpki 时,请务必记住设置的 CA 密码,并为服务器证书使用一个易识别的通用名(如 server)。

sudo docker run -d \
  --name openvpn-server \
  --restart unless-stopped \
  -v $OVPN_DATA:/etc/openvpn \
  -p 1194:1194/udp \
  --cap-add=NET_ADMIN \
  kylemanna/openvpn
# 生成客户端证书密钥对。将 `client-internal` 替换为你为内网服务器起的名字。
sudo docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full client-internal nopass

# 将客户端配置导出为一个独立的 .ovpn 文件
sudo docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_getclient client-internal > client-internal.ovpn

内网服务器直接使用old-pc-client.ovpn加载到客户端配置文件来启动容器

docker run -d \
  --name openvpn-client \
  --network=host \
  --restart unless-stopped \
  --cap-add=NET_ADMIN \
  --device /dev/net/tun \
  -v /home/vpn/old-pc-client.ovpn:/client.ovpn:ro \
  kylemanna/openvpn \
  openvpn --config /client.ovpn

关键修改说明‌:

  • 挂载路径与文件名‌:将配置文件挂载到一个任意的容器内路径(如 /client.ovpn),而不是服务端默认的 /etc/openvpn/ 目录下,以避免触发服务端的初始化脚本。
  • 启动命令‌:在镜像名 kylemanna/openvpn 之后,显式指定了容器的启动命令为 openvpn --config /client.ovpn。这直接调用 openvpn 二进制程序,并告诉它使用您挂载的配置文件,从而绕过了会报错的 ovpn_run 脚本。

启动后,查看容器日志以确认连接成功

docker logs openvpn-client

如果连接成功,将在日志末尾看到 Initialization Sequence Completed 的提示。

服务器为公网客户端生成配置文件

在公网VPN服务器上,需要为每一个独立的客户端设备生成专属的配置文件。

  1. 为特定客户端创建证书和密钥
    在服务器上,使用Docker命令为新的客户端(例如名为user-laptop)生成证书和密钥
# 为客户端生成证书和密钥对
docker run -v ovpn-data:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full user-laptop nopass

# 将客户端配置导出为独立的 .ovpn 文件
docker run -v ovpn-data:/etc/openvpn --rm kylemanna/openvpn ovpn_getclient user-laptop > user-laptop.ovpn

  • user-laptop:客户端的名称,可自定义,用于标识设备。
  • nopass:可选参数,表示不为客户端密钥设置密码,方便自动连接。

CCD配置文件详解

启用CCD功能
client-config-dir /etc/openvpn/ccd
client-to-client  # 如果需要客户端间通信

文件配置示例:
# /etc/openvpn/ccd/client1    分配固定IP
ifconfig-push 10.8.0.100 10.8.0.101

# /etc/openvpn/ccd/client2    分配固定IP+路由
ifconfig-push 10.8.0.200 10.8.0.201
iroute 192.168.1.0 255.255.255.0
push "route 192.168.1.0 255.255.255.0"

# /etc/openvpn/ccd/client3    复杂配置
ifconfig-push 10.8.0.50 10.8.0.51
# 推送特定路由
push "route 10.0.0.0 255.255.255.0"
push "route 172.16.0.0 255.255.0.0"
# DNS 设置
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
# 重定向网关(仅限此客户端)
push "redirect-gateway def1"
# 允许访问的客户端
client-to-client

# 连接数量限制
max-clients 2  # 此客户端最多同时2个连接

# 连接时间控制
push "inactive 7200"    # 2小时无活动断开
push "ping 15"          # 15秒心跳
push "ping-restart 45"  # 45秒无响应重连

# 带宽限制(间接控制连接质量)
push "shaper 1000000"   # 限制为1Mbps
# ============================================
# OpenVPN CCD配置文件示例
# 文件名:/etc/openvpn/ccd/client1
# 对应客户端证书CN:client1
# ============================================

# 1. 固定IP地址分配
# 格式:ifconfig-push <客户端IP> <服务器端对端IP>
ifconfig-push 10.8.0.100 10.8.0.101

# 2. 内部路由配置(用于站点到站点VPN)
# 允许客户端访问其本地网络
iroute 192.168.1.0 255.255.255.0
iroute 172.16.0.0 255.255.255.0

# 3. 推送路由到客户端
# 让客户端可以访问服务器端网络
push "route 10.0.0.0 255.255.255.0"
push "route 172.16.1.0 255.255.255.0"

# 4. DNS配置(清除并设置新DNS)
push "dhcp-option DNS 0.0.0.0"      # 清除现有DNS
push "dhcp-option DNS 8.8.8.8"      # 首选DNS
push "dhcp-option DNS 8.8.4.4"      # 备用DNS
push "dhcp-option DNS 1.1.1.1"      # 备用DNS2

# 5. 域名后缀
push "dhcp-option DOMAIN example.com"
push "dhcp-option DOMAIN-SEARCH corp.example.com"

# 6. 重定向所有流量(强制所有流量走VPN)
push "redirect-gateway def1 bypass-dhcp"

# 7. 客户端间通信控制
client-to-client                    # 允许客户端间通信

# 8. 推送WINS服务器(Windows网络)
push "dhcp-option WINS 10.8.0.1"

# 9. 推送NTP服务器
push "dhcp-option NTP 10.8.0.1"

# 10. 推送代理自动配置(PAC)
push "dhcp-option PROXY_AUTO_CONFIG_URL http://10.8.0.1/proxy.pac"

# 11. 连接保持设置
keepalive 10 60

# 12. 最大连接数限制
max-clients 5

# 13. 推送自定义路由指标(Windows)
push "route-metric 100"

# 14. 推送MTU设置
push "tun-mtu 1500"
push "fragment 1300"
push "mssfix 1200"

# 15. 压缩设置(根据服务器配置选择)
push "comp-lzo yes"                 # LZO压缩
# 或
push "compress lz4-v2"              # LZ4压缩

# 16. 推送自定义环境变量
setenv UV_XYZ "custom_value"

# 17. 推送自定义脚本
push "setenv PATH /custom/path:$PATH"

# 18. 推送自定义安全设置
push "cipher AES-256-GCM"
push "auth SHA256"

# 19. 推送连接超时设置
push "ping 10"
push "ping-restart 120"

# 20. 推送自定义日志级别
push "verb 3"

# 21. 推送重新协商时间
push "reneg-sec 3600"

# 22. 推送TLS版本控制
push "tls-version-min 1.2"

# 23. 推送数据通道卸载
push "data-ciphers AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305"

# 24. 推送TLS密码套件
push "tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384"

# 25. 推送自定义路由表
push "route-nopull"                 # 禁止自动路由
push "route 192.168.100.0 255.255.255.0 vpn_gateway 100"

# 26. 推送DNS回退设置
push "block-outside-dns"            # 阻止非VPN DNS查询(Windows)

# 27. 推送自定义网关
push "route-gateway 10.8.0.1"

# 28. 推送拓扑设置
push "topology subnet"

# 29. 推送自定义DHCP选项
push "dhcp-option ADAPTER_DOMAIN_SUFFIX example.org"

# 30. 推送连接脚本
push "setenv FORWARD_COMPATIBLE 1"
push "script-security 2"
push "setenv PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

路由注意事项

  • 使用 iroute 时,需要在服务器配置中添加对应的路由(route)
  • 对于需要访问客户端背后网络的情况,需要额外配置