简单的WireGuard Docker网络设置

2020-09-25 05:32:35

我最近重新组织了我的自托管内容,以使用Docker。虽然Docker并不真正符合我的理念,但几乎所有软件的广泛可用性和低维护成本说服了我切换,到目前为止,我很高兴,这比以前的工作要少得多,我可以将Docker合成文件签入到版本控制中,并且使用Docker卷中的所有内容备份都很容易。

无论如何,这里是我想要讨论的场景:您有一个或多个Docker容器,并且您希望通过WireGuard VPN路由其所有流量,而不是其他容器的流量或主机的流量。您拥有对主机的root访问权限。

使用WireGuard最直接的方式是WG-QUICK。您只需要一个大约10行长的配置文件(看一看OpenVPN配置文件,您就会喜欢这个简短的文件),运行sudo wg-ick up{config file},您的VPN就启动并运行了。这些文件也适用于Android/iOS/MacOS/Windows应用程序。

例如,我可以100%推荐的VPN提供商Mullvad可以让您下载WG-QUICK文件,以便于安装。

WG-QUICK很简单,但它通过VPN路由所有流量,这是您大多数时候想要的,但在我们的用例中不是这样。注意,允许的IP范围并不像您想象的那样有帮助:您可以告诉WireGuard,只有到特定IP的流量才应该通过VPN路由,这对于员工的VPN来说是有意义的:只有到公司网络的流量才应该通过VPN。但是,我们需要按来源进行过滤。WG-QUICK做不到这一点。

经过相当多的搜索,我终于找到了一篇很棒的博客文章,详细介绍了直接使用WG和IP工具(以及在另一个容器中使用WireGuard客户端)解决我们的确切问题的方案。这篇文章主要是基于这一点。

该方法的要点是:手动设置WireGuard接口,与WG-QUICK在内部操作的方式相同,但还没有到它的任何路由。然后通过IP添加路由规则,将特定子网的所有流量发送到VPN。最后,使用Docker Compose或Docker网络将所需的Docker容器配置为恰好使用该子网。

虽然这是一个漂亮而优雅的解决方案,但我认为它的配置有点麻烦,所以我试图找到一种更舒适的方式来设置它。

虽然我同意针对systemd及其策略的一些批评,但systemd-networkd确实是Linux上网络配置方面发生过的最好的事情。您可以使用简短、少量且文档齐全的纯文本配置文件来设置网络,而不是摆弄极其复杂的工具(如IP或奇怪的网络管理器)。我爱死它了。事实证明,它也有我们需要的一切隧道我们的码头集装箱,并以一种很好和简单的方式。这是我选择的解决方案,我想向您展示。

要在给定来自VPN提供商的WG-QUICK配置文件的情况下通过WireGuard VPN隧道传输容器,请将这些文件添加到/etc/systemd/network/:

[NetDev]name=wg0 Kind=wireguard description=WireGuard VPN[WireGuard]PrivateKey={Private Key,与WG-QUICK CONFIG中相同}[WireGuardPeer]PublicKey={PUBLIC KEY,与WG-QUICK CONFIG中相同}AllowweIP=0。0。0.0/0,::0/0端点={端点,与WG-QUICK配置中相同}。

[Match]name=wg0[Network]#如果需要多个地址,例如IPv4和6,请使用多个地址线。地址={要绑定到VPN内部的地址,与WG-QUICK CONFIG中的地址相同}[RoutingPolicyRule]from=10。123.。0.0/16表=242[路由]网关={接口地址,同上[网络]地址}表=242[路由]目的地=0。0。0.0/0类型=黑洞度量=1表=242。

然后运行sudo docker network create tuneled0--subnet10.123.0.0。现在,您可以使用--net=thuneled0运行停靠容器来对它们进行隧道操作。

版本:";3.7";服务:应用程序:映像:{image}DNS:";{要使用的DNS服务器}";网络:隧道0:{}网络:隧道0:IPAM:配置:-子网:10.123.0.0/16。

工作正常的网络连接。我认为它不需要使用systemd-networkd进行配置,尽管我还没有测试过。如果可能的话,我建议使用networkd。

首先,我们必须运行WireGuard接口。我们不能使用WG-QUICK做到这一点,因为它会自动通过它路由所有流量,而且使用WG很麻烦,所以我们使用systemd-networkd。我们只需在/etc/systemd/network/中添加两个文件:

[NetDev]#或任何其他名称name=wg0 Kind=wireguard#或您自己的描述Description=WireGuard VPN[WireGuard]PrivateKey={Private Key,与WG-QUICK CONFIG}[WireGuardPeer]PublicKey={PUBLIC KEY,与WG-QUICK CONFIG}#提醒,这些是允许的目标IP,而不是源IP,因此我们允许所有AllowweIP=0。0。0.0/0,::0/0端点={端点,与WG-QUICK配置中相同}。

[Match]#与.netdev file name=wg0[Network]#相同。如果需要多个地址,例如对于IPv4和6,请使用多个地址行。地址={要绑定到VPN内部的地址,与WG-QUICK配置中相同}。

正如您所看到的,它非常类似于WG-Quick配置文件,并且大多数值都可以直接从该文件中获取。有关更多信息,请查看netdev和网络文件的手册页。

文件的名称可以根据您的喜好进行调整。请注意,systemd-networkd按字母顺序读取配置文件,因此如果需要,请调整名称中的前缀数字。

使用#systemctl reart systemd-networkd(或确保使用reboot)应用配置。现在您可以验证接口是否正在实际工作:

两个cURL调用的结果应该不同,第一个显示您的正常IP,第二个显示VPN IP地址。请注意,对我来说,第二个cURL只能作为root使用(可能由于某些原因,curl只能作为root绑定到接口)。使用sudo wg和networkctl status wg0,您可以获得有关接口的更多信息。

现在我们已经启动并运行了WireGuard接口,我们必须安排我们的Docker容器的流量实际通过它。原来我们所要做的就是向85-wg0.network添加四行。它应该是这样的:

[Match]name=wg0[Network]#如果需要多个地址,例如IPv4和6,请使用多个地址线。地址={要绑定到VPN内部的地址,与wg-ick config}[RoutingPolicyRule]#或=10中的任何其他未使用的专用子网中的地址相同。123.。0.0/16#或任何其他未使用的表号Table=242[Route]Gateway={接口地址,同上}#与上表相同的表号=242[Route]Destination=0。0。0.0/0类型=黑洞度量=1#与上表相同的表号=242

[RoutingPolicyRule]部分所做的是从指定子网获取所有流量,并在路由表242中查找该流量的路由。我们使用[Route]部分将一个路由添加到表242(希望以前是空的),该路由将流量发送到我们的WireGuard接口,因为我们将接口的地址设置为网关。

第二个[Route]部分在同一个表中设置度量为1的黑洞路由,这意味着优先级低于默认度量0。如果VPN网关关闭,这应该会丢弃所有流量(而不是通过没有任何VPN的默认网络路由),从而防止泄漏。

要让Docker实际使用带有特定容器的接口,我们有两种可能性。

请注意,对于这两种方法,发布的端口在主机上的localhost上将不可用,因为所有容器通信都通过VPN(当然,这是我们想要的)。因此,如果您添加一个暴露的端口,则必须通过VPN的外部地址访问该端口。

在我们在systemd-networkd配置文件中使用sudo docker network create tuneled0--subnet10.123.0.0(或使用隧道0以外的任何名称)的子网中创建Docker网络,然后使用--net=tuneled0选项在该网络中运行容器。使用--dns选项,您可以设置自定义DNS,这样就不会泄露DNS流量。

例如,您可以使用sudo docker run-t--net=Tuneneled0 curlimages/curl icanhazip.com检查返回的IP是否真的是VPN的IP。

这是更舒适的方法。您可以将其用作您自己的合成文件的基础:

版本:";3.7";服务:应用程序:映像:{image}DNS:";{要使用的DNS服务器}";网络:#或您自己的名称隧道0:网络:#与上述隧道同名0:IPAM:CONFIG:-子网:10.123.0.0/16

您可以使用Docker的普通端口发布选项使端口可以通过VPN使用。因此,例如,如果您的VPN提供商为您提供了端口1234,而您希望容器内的端口80可通过VPN使用,则使用-p1234:80调用docker(不要忘记上面解释的其他必需选项)或添加。

请注意,隧道容器的发布端口不能在本地主机上访问,只能通过VPN访问。遗憾的是,我还没有找到解决这个问题的可能性。

我们在WireGuard VPN上运行Docker Containers,只有两个简短的配置文件。如果您有任何问题或意见,请发布到论坛或与我联系。

非常感谢尼克·巴布科克(Nick Babcock)发表了这篇精彩的文章!

更新1:新增黑洞路由,防止VPN网关关闭时泄漏。感谢tChamb的建议!