我想让 OpenVPN 用户可以访问所有属于 Overlay 网络的 Docker 容器,就像它们位于同一个 LAN 中一样。最简单的示例是 3 个容器分布在 2 个主机上,主机通过覆盖网络连接,所有 3 个容器都是该覆盖网络的一部分。
为此,我准备了一个 OpenVPN 容器(带有 TAP 适配器的桥接模式的 OpenVPN),并且在该容器中我创建了一个桥接 br0,并将 eth0 和 tap0 接口桥接到 br0。通过这种方式,我可以说我将我的 TAP 和所有 OpenVPN 客户端桥接到了覆盖网络(我不确定这种说法是否正确)。
到目前为止,当我的 OpenVPN 用户连接到 OpenVPN 并尝试 ping 虚拟容器 1(与 OpenVPN 容器位于同一主机上)时,用户能够 ping 虚拟容器 1(当然也能够 ping OpenVPN 容器)。到目前为止一切顺利!
然而,用户无法 ping 虚拟容器 2,因为它位于不同的主机(但与上面提到的 OpenVPN 容器属于同一覆盖层的一部分)。
简而言之,连接到 OpenVPN 容器(桥接至 Docker 覆盖网络)并尝试 ping 其他容器的 VPN 用户只能 ping 同一主机上的容器,而不能 ping 其他主机上的容器,就好像桥接仅在本地桥接上工作而不在覆盖网络上工作。
还需要说明的是,从 OpenVPN 容器内部我可以 ping 虚拟容器 2(当然也可以 ping 虚拟容器 1)。
此图概括了我上面讲述的整个故事。请注意红色箭头,它代表我想要实现但目前无法实现的连接(VPN 用户通过 OpenVPN 连接到主机 1,然后尝试 ping 虚拟容器 2)。
一些详细的技术信息
OpenVPN 容器
/etc/openvpn # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: tap0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
link/ether 06:9b:33:89:85:81 brd ff:ff:ff:ff:ff:ff
3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default qlen 1000
link/ether 02:42:0a:08:00:04 brd ff:ff:ff:ff:ff:ff
inet 10.8.0.4/24 scope global br0
valid_lft forever preferred_lft forever
74: eth0@if75: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master br0 state UP group default
link/ether 02:42:0a:08:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
76: eth1@if77: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:12:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet 172.18.0.4/16 brd 172.18.255.255 scope global eth1
valid_lft forever preferred_lft forever
/etc/openvpn # ip route
default via 172.18.0.1 dev eth1
10.8.0.0/24 dev br0 proto kernel scope link src 10.8.0.4
172.18.0.0/16 dev eth1 proto kernel scope link src 172.18.0.4
OpenVPN 服务器配置:
port 1194
proto udp
dev tap0
ca ca.crt
cert server.crt
key server.key # This file should be kept secret
dh dh.pem
ifconfig-pool-persist ipp.txt
client-to-client
keepalive 10 120
cipher AES-256-GCM
compress lz4-v2
push "compress lz4-v2"
persist-key
persist-tun
status /var/log/openvpn-status.log
verb 3
explicit-exit-notify 1
##### Authentication #####
# A client certificate is not required. The client need to authenticate using username/password only.
verify-client-cert none
# Disables keys renegotiation. The default value is one hour, which disconnects the user every hour and causes the end user to be challenged to reauthorize using a new OTP.
reneg-sec 0
# Loads and uses LDAP plugin config.
plugin /usr/lib/openvpn/plugins/openvpn-auth-ldap.so /etc/openvpn/auth-ldap.conf
# Loads and uses PAM-auth plugin (mainly for 2FA).
plugin /usr/lib/openvpn/plugins/openvpn-plugin-auth-pam.so "openvpn login USERNAME password PASSWORD pin OTP"
新娘的嫁接如下:
openvpn --mktun --dev tap0
ip link set tap0 promisc on up
ip link add name br0 type bridge
ip link set dev br0 up
ip link set dev tap0 master br0
ip link set dev eth0 master br0
ip addr flush dev eth0
ip addr add 10.8.0.4/24 dev br0
OpenVPN 使用命令启动
VPN_SERVER_HOST_IP_ADDRESS=10.8.0.254
VPN_NETMASK=255.255.255.0
VPN_POOL_START_IP_ADDRESS=10.8.0.50
VPN_POOL_END_IP_ADDRESS=10.8.0.100
openvpn \
--config server.conf \
--server-bridge $VPN_SERVER_HOST_IP_ADDRESS $VPN_NETMASK $VPN_POOL_START_IP_ADDRESS $VPN_POOL_END_IP_ADDRESS
我的虚拟容器 2(与虚拟容器 1 非常相似,但 IP 不同):
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
35: eth0@if36: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue state UP
link/ether 02:42:0a:08:00:05 brd ff:ff:ff:ff:ff:ff
inet 10.8.0.5/24 brd 10.8.0.255 scope global eth0
valid_lft forever preferred_lft forever
37: eth1@if38: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.3/16 brd 172.18.255.255 scope global eth1
valid_lft forever preferred_lft forever
/ # ip route
default via 172.18.0.1 dev eth1
10.8.0.0/24 dev eth0 scope link src 10.8.0.5
172.18.0.0/16 dev eth1 scope link src 172.18.0.3