Docker 部署 OpenVPN

环境信息

  • Centos 7 3.10.0-1160
  • Docker 20.10.9
  • iptables

前提条件

宿主机操作系统内核配置允许数据转发,开启系统 IPv4 转发功能

Docker 部署 OpenVPN 服务端步骤

创建本地配置目录

用了在启动容器时挂载以持久化 OpenVPN 配置

mkdir /opt/openvpn1/

初始化配置文件

执行以下命令初始化 OpenVPN 服务端配置

docker run --rm \
-v /opt/openvpn1/:/etc/openvpn \
kylemanna/openvpn:2.4 ovpn_genconfig -u udp://${PUB_IP}:1194

参数说明:

  • udp://${PUB_IP}:1194 - 指定 VPN 服务器配置,使用 1194/udp 端口。${PUB_IP} 为服务器公网 IP。

生成密钥(证书)文件

docker run --rm -it \
-v /opt/openvpn1/:/etc/openvpn \
kylemanna/openvpn:2.4 ovpn_initpki

根据提示,输入 CA 根证书密码及名称

创建带有密码的客户端证书

执行以下命令,根据提示输入客户端证书密码及 CA 密码,生成客户端证书。如果客户端证书无需密码,最后加选项 nopass

docker run --rm -it \
-v /opt/openvpn1/:/etc/openvpn \
kylemanna/openvpn:2.4 easyrsa build-client-full vpn1

导出客户端证书

docker run --rm -it \
-v /opt/openvpn1/:/etc/openvpn \
kylemanna/openvpn:2.4 ovpn_getclient vpn1 > /opt/openvpn/client/vpn1.ovpn

启动 OpenVPN

docker run -it --name OpenVPN1 \
-v /opt/openvpn1/:/etc/openvpn \
-d -p 1194:1194/udp --cap-add=NET_ADMIN \
kylemanna/openvpn:2.4

防火墙放通 1194/udp 端口

/etc/sysconfig/iptables
-A INPUT -p udp --dport 1194 -j ACCEPT -m comment --comment "openvpn"

OpenVPN 启动后,docker 会在宿主机操作系统的 iptables 中添加对应的 MASQUERADE 规则,负责转发和 NAT 数据,具体规则可通过以下方法查看

查看 NAT 表添加的规则

$ iptables -t nat -L -v -n --line-numbers | more
Chain PREROUTING (policy ACCEPT 127 packets, 9255 bytes)
num pkts bytes target prot opt in out source destination
1 54 2490 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT 1 packets, 70 bytes)
num pkts bytes target prot opt in out source destination
1 75 6875 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
2 610 36387 MASQUERADE all -- * * 10.8.0.0/24 0.0.0.0/0
3 0 0 MASQUERADE udp -- * * 172.17.0.2 172.17.0.2 udp dpt:1194

Chain DOCKER (2 references)
num pkts bytes target prot opt in out source destination
1 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
2 1 70 DNAT udp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:1194 to:172.17.0.2:1194

查看 FILTER 表添加的规则

$ iptables -L -v -n --line-numbers | more
Chain INPUT (policy DROP 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 641 51489 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
2 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
3 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:1194 /* openvpn */
...
13 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8
14 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 0
15 230 14788 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited

Chain FORWARD (policy DROP 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 16891 4860K DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0
2 16891 4860K DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0
3 8465 2439K ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
4 1 70 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0
5 8425 2421K ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
6 0 0 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0
7 4177 1774K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
8 202 13030 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 343 packets, 61383 bytes)
num pkts bytes target prot opt in out source destination

Chain DOCKER (1 references)
num pkts bytes target prot opt in out source destination
1 1 70 ACCEPT udp -- !docker0 docker0 0.0.0.0/0 172.17.0.2 udp dpt:1194

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
num pkts bytes target prot opt in out source destination
1 8425 2421K DOCKER-ISOLATION-STAGE-2 all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
2 16891 4860K RETURN all -- * * 0.0.0.0/0 0.0.0.0/0

Chain DOCKER-ISOLATION-STAGE-2 (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DROP all -- * docker0 0.0.0.0/0 0.0.0.0/0
2 8425 2421K RETURN all -- * * 0.0.0.0/0 0.0.0.0/0

Chain DOCKER-USER (1 references)
num pkts bytes target prot opt in out source destination
1 16891 4860K RETURN all -- * * 0.0.0.0/0 0.0.0.0/0

客户端连接

导出客户端证书 中生成的客户端证书发送到客户端,测试连接。

客户端连接失败,可以检查以下内容:

  • 客户端日志及服务端日志,服务端日志可以通过以下方法查看

    docker logs -f OpenVPN
  • 检查是否是因为 iptables 防火墙规则 问题导致无法连接,如果防火墙相关规则丢失,可以通过重启 docker 和 OpenVPN 容器的方式恢复。

  • 检查容器中启动的端口和 docker 映射的端口是否一致。