允许Docker容器连接到主机隧道接口上的OpenVPN客户端

我有以下设置:

>运行docker服务的CentOS主机
>用户定义的docker bridge网络
> 2个Docker容器连接到该用户定义的桥接网络
> OpenVPN安装(当前在主机上运行.也可以在docker容器中运行)
>一些客户端连接到OpenVPN

如何允许docker bridge网络上的docker容器与tun0网络上的openvpn客户端通信?

我希望能够以透明的方式在docker1(10.10.0.3)和连接到vpn(172.19.0.x范围)的客户端之间进行基于tcp的通信.

我需要在docker(networking / iptables / …)端和主机上设置什么(iptables?)

最佳答案
上下文

我一直在使用来自Kyle Manna(https://github.com/kylemanna/docker-openvpn)的非常好的Docker容器.我正在使用所谓的“偏执”文档来设置我的OpenVPN服务器,但在我看来,这应该是标准的方式,而不是偏执的方式.

组态

为了允许所选Docker容器和VPN客户端之间的双向连接,您需要创建一个Docker网络,您将在其上附加容器,VPN容器应允许该容器访问该容器. VPN服务器将成为其中一个容器.

VPN服务器应具有客户端到客户端,拓扑子网,dev tun0(或其他tun设备)并推送“route< docker net IP>< docker net mask>”配置.

VPN服务器的主机应配置为支持从一个子网到另一个子网的IP数据包转发.这意味着将sysctl ip_forward设置为1(如果安装了Docker,则应该是这种情况),允许来自tun设备的数据包通过iptables FORWARD链并设置正确的路由.这可以使用以下命令进行总结:

$sudo sysctl -w net.ipv4.ip_forward=1
$sudo iptables -A FORWARD -i tun+ -j ACCEPT
$sudo ip route add 192.168.255.0/24 via <IP address of OpenVPN server container>

无论如何,这里是我用来设置服务器的选项:

$docker run --rm --net=none -it -v $PWD/files/openvpn:/etc/openvpn kylemanna/openvpn:2.4 ovpn_genconfig -u udp://<FQDN> -N -d -c -p "route <docker net IP> <docker net range>" -e "topology subnet"

这应该生成一个类似于的服务器配置文件:

server 192.168.255.0 255.255.255.0
verb 3
key /etc/openvpn/pki/private/vpn.example.com.key
ca /etc/openvpn/pki/ca.crt
cert /etc/openvpn/pki/issued/vpn.example.com.crt
dh /etc/openvpn/pki/dh.pem
tls-auth /etc/openvpn/pki/ta.key
key-direction 0
keepalive 10 60
persist-key
persist-tun

proto udp
# Rely on Docker to do port mapping, internally always 1194
port 1194
dev tun0
status /tmp/openvpn-status.log

user nobody
group nogroup
client-to-client

### Push Configurations Below
push "dhcp-option DNS 8.8.8.8"
push "route 172.20.20.0 255.255.255.0"

### Extra Configurations Below
topology subnet

具体例子

我现在举一个具体的例子.在这个例子中,我将在主机vpn.example.com上的Docker中运行上面提到的OpenVPN服务器.此容器已连接到Docker网络docker-net-vpn.以下是命令(在此示例中,我直接在服务器上生成服务器配置,并且我跳过CA生成,请遵循上面提到的项目的偏执文档):

$docker network create --attachable=true --driver=bridge --subnet=172.20.20.0/24 --gateway=172.20.20.1 docker-net-vpn
$docker run --rm --net=none -it -v $PWD/files/openvpn:/etc/openvpn kylemanna/openvpn:2.4 ovpn_genconfig -u udp://vpn.example.com -N -d -c -p "route 172.20.20.0 255.255.255.0" -e "topology subnet"
$docker run --detach --name openvpn -v $PWD/files/openvpn:/etc/openvpn --net=docker-net-vpn --ip=172.20.20.2 -p 1194:1194/udp --cap-add=NET_ADMIN kylemanna/openvpn:2.4
$sudo sysctl -w net.ipv4.ip_forward=1
$sudo iptables -A FORWARD -i tun+ -j ACCEPT
$sudo ip route add 192.168.255.0/24 via 172.20.20.2

第一个命令创建一个专用的新Docker网络,用于定义新的子网.我们将OpenVPN服务器连接到此网络.

第二个使用第一个命令中定义的相同子网创建OpenVPN配置.

第三个创建OpenVPN服务器.它附加到新创建的Docker网络并使用修复IP.

第四和第五个命令配置IP转发.

最后一个命令通过OpenVPN容器固定IP向VPN客户端配置添加新路由.

注意

我没有尝试过,但应该可以限制iptables的FORWARD规则. Docker网络创建创建了一个新的桥接设备.该桥名为br-< ID> ID是Docker网络ID的前12个字符.这个ID可以通过docker network inspect -f'{{.Id}}’docker-net-vpn |获得.切-b-12.因此,以下命令可能更具限制性(因此安全性更好),但仍应允许我们的流量路由:

$NET_VPN_BRIDGE="br-$(docker network inspect -f '{{.Id}}' docker-net-vpn | cut -b-12)"
$sudo iptables -A FORWARD -i tun+ -o ${NET_VPN_BRIDGE} -j ACCEPT

转载注明原文:允许Docker容器连接到主机隧道接口上的OpenVPN客户端 - 代码日志