介绍
在本教程中,我们将演示如何使用配置管理工具 Ansible 来设置带有 Tinc 的网状 VPN,以保护 Ubuntu 和 CentOS 服务器之间的网络通信。
如果您的服务器使用共享网络,则网状 VPN 特别有用,因为它使您的服务器能够像在真正的专用网络上隔离一样进行通信。 VPN 的身份验证和加密功能提供的额外安全层将保护您的私有服务(数据库、Elasticsearch 集群等)的网络通信免受未经授权的访问或攻击。 如果您使用的是 DigitalOcean 的 私有网络功能 ,那么在同一区域内的同一团队或帐户上的服务器上已经启用了此安全功能。
跨多个服务器手动配置和维护 VPN 既困难又容易出错,因为需要在所有 VPN 成员之间分发多个配置和密钥文件。 出于这个原因,配置管理工具应该用于任何成员可能在某些时候发生变化的实际网状 VPN 设置。 可以使用任何配置管理工具,但本教程使用 Ansible 是因为它流行且易于使用。 本教程使用的 Ansible Playbook,ansible-tinc,已经在 Ubuntu 14.04 和 CentOS 7 服务器上进行了测试。
背景阅读
您应该能够按照本教程设置网状 VPN,而无需过多了解 Ansible 或 Tinc,因为随附的 Playbook 将为您完成大部分工作。 但是,您可能想在某些时候阅读它们的工作原理,以便了解您正在设置的细节。
本 Tinc VPN 教程 介绍了如何手动安装和配置 Tinc VPN。 使用 Ansible 来自动化该过程使其更易于管理。
如何安装和配置 Ansible 对 Ansible 的工作原理进行了非常高级的介绍。 如果您想开始编写 Ansible Playbook 来自动执行系统管理员任务,请查看 本教程 。
先决条件
本地机器
本地机器是执行 Ansible Playbook 的地方。 这可能是您的本地机器(例如 笔记本电脑)或您用来管理服务器的其他服务器。 如前所述,它需要能够以 root
的身份连接到每个远程服务器。
您的本地计算机需要安装 Ansible 2.0+。 如需安装请参考官方Ansible安装文档,安装过程因操作系统或发行版而异。
您的本地计算机也需要安装 Git,因此您可以轻松下载 ansible-tinc Playbook 的副本。 再次,因为安装说明依赖于你的本地机器,请参考【X88X】官方Git安装指南【X123X】。
远程服务器
远程服务器是您要配置为使用 Tinc VPN 的主机。 你应该从至少两个开始。 要使用 Ansible Playbook,它们必须是:
- 运行 Ubuntu 14.04 或 CentOS 7
- 可通过
root
用户、 使用公钥身份验证 访问本地机器(安装了 Ansible)
注意: 由于 Playbook 使用的 Ansible 同步模块 存在 错误,目前无法使用其他远程用户。
如果您尚未禁用 root
的密码验证,可以通过将 PermitRootLogin without-password
添加到 /etc/ssh/sshd_config
文件,然后重新启动 SSH 来执行此操作。
如果您使用的是同一数据中心内的 DigitalOcean Droplets,您应该在所有这些上启用专用网络。 这将允许您使用专用网络接口 eth1
进行加密的 VPN 通信。 提供的 Playbook 假定每个 VPN 节点都将使用相同的网络设备名称。
下载 Ansible-Tinc 手册
准备好开始后,使用 git clone
下载 Playbook 的副本。 我们将它克隆到我们的主目录:
cd ~ git clone https://github.com/thisismitch/ansible-tinc
现在切换到新下载的ansible-tinc
目录:
cd ansible-tinc
注意: 本教程的其余部分假定您位于本地计算机上的 ansible-tinc
目录中。 所有 Ansible 命令都必须从此目录执行。 此外,所有引用的文件,除了 /etc/hosts
,都是相对于这个路径的——例如 hosts
是指 ~/ansible-tinc/hosts
。
接下来,我们将向您展示如何使用 Playbook 创建您的网状 VPN。 如果您熟悉 Ansible,您可能需要花一些时间浏览 Playbook 的内容。 本质上,它使用 Tinc 安装和配置一个网状 VPN,它还在每个服务器的 /etc/hosts
中添加了便利条目。
创建主机清单文件
在运行 Playbook 之前,您必须创建一个 hosts
文件,其中包含有关您要包含在 Tinc VPN 中的服务器的信息。 我们现在将查看 hosts 文件的内容。
~/ansible-tinc/hosts 示例
[vpn] node01 vpn_ip=10.0.0.1 ansible_host=192.0.2.55 node02 vpn_ip=10.0.0.2 ansible_host=192.0.2.240 node03 vpn_ip=10.0.0.3 ansible_host=198.51.100.4 node04 vpn_ip=10.0.0.4 ansible_host=198.51.100.36 [removevpn]
第一行 [vpn]
指定其正下方的主机条目是“vpn”组的一部分。 该组的成员将在其上配置 Tinc 网状 VPN。
- 第一列是您设置主机清单名称的位置,示例第一行中的“node01”,Ansible 将如何引用主机。 该值用于配置 Tinc 连接,并生成
/etc/hosts
条目。 不要在此处使用连字符,因为 Tinc 不支持在主机名中使用连字符 vpn_ip
是节点将用于 VPN 的 IP 地址。 将此分配给您希望服务器用于其 VPN 连接的 IP 地址ansible_host
必须设置为本地机器可以到达节点的值(即 真实的 IP 地址或主机名)
因此,在示例中,我们有四台主机要在网状 VPN 中配置,如下所示:
一旦您的 hosts
文件包含您想要包含在 VPN 中的所有服务器,请保存您的更改。 确保它不包含重复的条目(主机名、vpn_ip
地址或 ansible_host
值)。
此时,您应该测试 Ansible 是否可以连接到清单文件中的所有主机:
ansible all -m ping
他们都应该以绿色的“SUCCESS”消息响应。 如果任何连接失败,请检查您的主机文件是否有错误,并确保所有有问题的服务器都满足 先决条件部分 中列出的要求,然后再继续。
查看组变量
在运行 Playbook 之前,您可能需要查看 /group_vars/all
文件的内容:
/group_vars/全部
--- netname: nyc3 physical_ip: "{{ ansible_eth1.ipv4.address }}" vpn_interface: tun0 vpn_netmask: 255.255.255.0 vpn_subnet_cidr_netmask: 32
两个最重要的变量是 physical_ip
和 vpn_netmask
:
physical_ip
指定您希望 tinc 绑定到哪个 IP 地址。 在这里,我们利用 Ansible Fact 将其设置为eth1
网络设备的 IP 地址。 在 DigitalOcean 上,eth1
是专用网络接口,因此必须启用 Private Networking,除非您更愿意使用公共网络接口eth0
,将其值更改为 [ X202X]vpn_netmask
指定将应用于 VPN 接口的网络掩码。 默认设置为255.255.255.0
,即每个vpn_ip
都是一个C类地址,只能与同一子网内的其他主机通信。 例如,除非通过将vpn_netmask
更改为255.255.0.0
来扩大子网,否则10.0.0.x
将无法与10.0.1.x
主机通信。
注意: VPN 的安全优势可以通过公共 Internet 扩展到您的服务器,但请记住,通信仍将具有与非 VPN 连接相同的延迟和带宽限制。
以下是其他设置的说明:
netname
指定 tinc 网络名称。 默认设置为nyc3
。vpn_interface
是 tinc 将使用的虚拟网络接口的名称。 默认为tun0
。vpn_subnet_cidr_netmask
设置为 32,表示单主机子网(点对点),因为我们正在配置网状 VPN。 不要更改此值。
完成对组变量的审查后,您应该准备好继续下一步。
部署 Tinc VPN
现在已经创建了一个清单 hosts 文件并查看了组变量,您可以通过运行 Playbook 来部署 Tinc 并在您的服务器上设置 VPN。
在 ansible-tinc
目录中,运行以下命令来运行 Playbook:
ansible-playbook site.yml
当 Playbook 运行时,它应该提供每个执行任务的输出。 如果一切配置正确,您应该会看到几个 ok
和 changed
状态,以及零个 failed
状态:
PLAY RECAP *********************************************************************node01 : ok=18 changed=15 unreachable=0 failed=0 node02 : ok=18 changed=15 unreachable=0 failed=0 node03 : ok=21 changed=19 unreachable=0 failed=0 node04 : ok=21 changed=19 unreachable=0 failed=0
如果没有失败的任务,清单文件中的所有主机都应该能够通过 VPN 网络相互通信。
测试 VPN
登录到您的第一台主机并 ping 第二台主机:
ping 10.0.0.2
因为 Playbook 会自动创建 /etc/hosts
条目,将清单主机名指向每个成员的 VPN IP 地址,所以您也可以执行类似的操作(假设您的一个主机在 Ansible 中名为 node02
hosts
文件):
ping node02
无论哪种方式,您都应该看到有效的 ping 响应:
[secondary_label Output: PING node02 (10.0.0.2) 56(84) bytes of data. 64 bytes from node02 (10.0.0.2): icmp_seq=1 ttl=64 time=1.42 ms 64 bytes from node02 (10.0.0.2): icmp_seq=2 ttl=64 time=1.03 ms ...
随意测试其他节点之间的 VPN 连接。
注: Tinc 使用端口 655
。 如果您的 ping 测试不起作用,请确保每个节点的防火墙允许通过 VPN 正在使用的真实网络设备上的适当流量。
完成测试后,您的网状 VPN 就可以使用了!
配置服务和应用程序
现在您的网状 VPN 已设置完毕,您需要确保配置后端服务和应用程序以使用它(在适当的情况下)。 这意味着任何应该通过 VPN 进行通信的服务都需要使用适当的 VPN IP 地址 (vpn_ip
) 而不是普通的私有 IP 地址。
例如,假设您在 node01 上运行带有 Nginx 的 LEMP 堆栈,在 node02 上运行 MySQL 数据库。 MySQL 应配置为绑定到 VPN IP 地址 10.0.0.2
,PHP 应用程序应连接到 10.0.0.2
的数据库,Nginx 应侦听 192.0.2.55
(node01 的公共 IP 地址)。
再举一个例子,如果 node01、node02 和 node03 是 Elasticsearch 集群中的节点,则应将 Elasticsearch 配置为使用 10.0.0.1
、[ X170X] 和 10.0.0.3
作为节点 IP 地址。 同样,任何连接到集群的客户端也应该使用 VPN 地址。
防火墙注意事项
您可能需要更新防火墙规则以允许 VPN 网络设备“tun0”或 VPN IP 地址上的流量。
如何添加或删除服务器
添加新服务器
hosts
文件中 [vpn]
组中列出的所有服务器都将成为 VPN 的一部分。 要添加新的 VPN 成员,只需将新服务器添加到 [vpn]
组,然后重新运行 Playbook:
ansible-playbook site.yml
删除服务器
要删除 VPN 成员,请将要删除的服务器的 hosts
条目移到文件底部的 [removevpn]
组下。
例如,如果我们要删除 node04,则 hosts
文件将如下所示:
hosts — 从 VPN 中删除 node04
[vpn] node01 vpn_ip=10.0.0.1 ansible_host=192.0.2.55 node02 vpn_ip=10.0.0.2 ansible_host=192.0.2.240 node03 vpn_ip=10.0.0.3 ansible_host=198.51.100.4 [removevpn] node04 vpn_ip=10.0.0.4 ansible_host=198.51.100.36
保存主机文件。 请注意,vpn_ip
是可选的,未用于 [removevpn]
组成员。
然后重新运行剧本:
ansible-playbook site.yml
这将停止 Tinc 并从 [removevpn]
组的成员中删除 Tinc 配置和主机密钥文件,从而将它们从 VPN 中删除。
请注意,从 VPN 中删除主机将导致剩余 VPN 成员上的孤立 tinc 主机文件和 /etc/hosts 条目。 除非您稍后将新服务器添加到 VPN 但重用已停用的名称,否则这不会影响任何事情。 如果这对您来说是个问题,请删除每台服务器上相应的 /etc/hosts
条目。
结论
您的服务器基础设施现在应该通过使用 Tinc 和 Ansible 的网状 VPN 来保护! 如果您需要修改 playbook 以满足您的特定需求,请随时在 GitHub 上 fork 它。
祝你好运!