Paranoid Penguin - Linux VPNs with OpenVPN,第五部分
在我之前的四篇专栏文章中,我详细地展示了如何设置 OpenVPN,以允许远程用户创建安全的远程访问连接——虚拟专用网络 (VPN) 隧道——通过互联网回到您的个人或公司网络。到现在,您应该理解 VPN 技术的基本原理,特别是基于 TLS/SSL 的 VPN 的工作方式,以及如何为 OpenVPN 创建可用的服务器和客户端配置。
本月,我将总结本系列,并对之前专栏文章中的客户端-服务器场景进行一些其他但重要的说明,包括关于启用 IP 转发的说明,一些关于使用 Web 代理和通过隧道强制 DNS 使用的技巧,以及关于“隐藏”所有 VPN 客户端 IP 地址在您的 OpenVPN 服务器 IP 地址之后的方法。
在本系列文章中,我一直在实现清单 1 中所示的 OpenVPN 服务器配置,该配置使 OpenVPN 以服务器模式运行。在我的示例场景中,只有一个远程用户连接到此 OpenVPN 服务器,但如果您有更多用户,则应编辑max-clients参数。请记住,因为我还设置了相当宽松的隧道超时时间,以尽量减少由于网络问题导致隧道中断的可能性,所以您应该在您期望的最大并发客户端连接数的实际数量上加 1 或 2。
清单 1. 服务器的 server.ovpn 文件
port 1194 proto udp dev tun ca 2.0/keys/ca.crt cert 2.0/keys/server.crt key 2.0/keys/server.key # This file should be kept secret dh 2.0/keys/dh1024.pem tls-auth 2.0/keys/ta.key 0 server 10.31.33.0 255.255.255.0 ifconfig-pool-persist ipp.txt push "redirect-gateway def1 bypass-dhcp" keepalive 10 120 cipher BF-CBC # Blowfish (default) comp-lzo max-clients 2 user nobody group nogroup persist-key persist-tun status openvpn-status.log verb 3 mute 20
清单 1 中我需要回顾的另一个设置是push "redirect-gateway def1 bypass-dhcp",它将 OpenVPN 的本地默认网关设置推送给所有客户端。这具有使 VPN 客户端将所有 Internet 流量通过 VPN 隧道路由的效果,这(正如我稍后将讨论的)具有重要的安全优势。
与清单 1 对应的客户端配置文件如清单 2 所示。此文件在 Linux 和 Windows 客户端系统上同样适用。请记住,参数remote指定您的 OpenVPN 服务器的 IP 地址或主机名以及它正在接受连接的端口。
另请记住,由参数指定的 ca.crt、minion.crt、minion.key 和 ta.key 文件ca, cert, key和tls-auth需要预先生成,并与配置文件本身一起放置在 /etc/openvpn 中。由ca和cert指定的证书和密钥对于每个客户端系统应该是唯一的!
清单 2. 客户端的 client.ovpn 文件
client proto udp dev tun remote 1.2.3.4 1194 nobind ca ca.crt cert minion.crt key minion.key ns-cert-type server tls-auth ta.key 1 cipher BF-CBC comp-lzo user nobody group nogroup persist-key persist-tun mute-replay-warnings verb 3 mute 20
再次强调,清单 1 中的服务器配置和清单 2 中的客户端配置的目的是允许远程用户通过互联网连接回到 OpenVPN 服务器所在的“家庭”网络。(这可能是也可能不是您的住所。我所说的家庭网络是指“受信任的公司或个人网络”,而不是您尝试连接的远程网络。)然而,上个月,我忘记提及一个关键步骤,如果您希望远程客户端能够与服务器本身以外的任何东西通信,则必须在您的 OpenVPN 服务器上执行此步骤:启用 IP 转发。
默认情况下,几乎任何 Linux 系统都配置为不允许将进入一个网络接口的网络数据包转发到另一个网络接口并从该接口发送出去。这是 Linux 的一项安全功能。它有助于降低您的 Linux 系统以不良或意外方式将不同网络连接在一起的可能性。
但是,通常您希望 OpenVPN 服务器连接不同的网络。以下情况是例外:
您的远程用户需要的所有服务和资源都托管在 OpenVPN 服务器本身上。
可以在 OpenVPN 服务器上运行代理应用程序,这些应用程序可以代理到未托管在其上的服务的连接。
在第一种情况下,一旦远程用户成功连接到 OpenVPN 服务器,他们就可以通过定位服务器的真实/本地 IP 地址而不是其面向互联网的地址来连接到托管在该服务器上的其他服务。例如,清单 2 中的客户端配置的目标服务器地址为 1.2.3.4,该地址是可互联网路由的。假设这实际上是一个路由器或防火墙地址,它被转换为您的 OpenVPN 服务器的地址 10.0.0.4。
要ssh到 OpenVPN 服务器,在您建立到它的隧道之后,您将定位 10.0.0.4,而不是 1.2.3.4。这同样适用于 Samba、NFS、HTTP/S 或在 OpenVPN 服务器上运行的任何其他服务。
在第二种情况下,要访问远程网络上的其他资源,您需要配置客户端系统上运行的应用程序,以使用 OpenVPN 服务器的真实/内部地址 (10.0.0.4) 作为其代理地址。最好的例子是 Squid。如果您想要访问的远程网络上的所有资源都涉及 Web 服务,您可以在 OpenVPN 服务器上运行 Squid,并将客户端的 Web 浏览器配置为使用 10.0.0.4 作为其代理地址(尽管这仅在隧道建立后才有效)。
在上述任何一种情况下,您都无需在 OpenVPN 服务器上启用 IP 转发,因为 VPN 客户端与您的家庭网络之间的所有直接通信都在 OpenVPN 服务器上终止。但是,如果您的客户端需要访问家庭网络上或更远的其他内容,而不使用 OpenVPN 服务器作为代理,则您确实需要启用 IP 转发。
这非常简单。要在不重启的情况下打开 IP 转发,只需执行此命令
bash-$ sudo sysctl -w net.ipv4.ip_forward=1
要使此更改在重启后保持持久,请取消注释 /etc/sysctl.conf 中的以下行(您需要su到 root 用户或使用 sudo 编辑此文件)
net.ipv4.ip_forward=1
在谈到使用 VPN 软件在使用不受信任的网络(如 WLAN 热点)时的价值时,我已经描述了使用您家庭网络的 Web 代理而不是直接通过不受信任的网络浏览 Web 的好处。从策略执行的角度来看,这允许您执行您家庭网络的代理配置的任何 URL 或内容过滤;从端点安全的角度来看,它使网络钓鱼和中间人攻击更加困难。
不利的一面是,它还会导致 Web 浏览体验稍慢一些,因为每个用户的 Web 流量都必须遍历比没有 VPN 隧道时更长、更慢的路径。此外,在没有同时配置远程用户使用您的公司 DNS 服务器的情况下,让他们使用您的公司 Web 代理可能无法阻止中间人攻击(其中 DNS 重定向是一种常用技术),从而给人一种虚假的安全感。
我稍后会回到 DNS 问题,但是如何在 OpenVPN 中使用 Web 代理?这很简单。在 Web 代理本身上,您只需确保有一个访问控制列表 (ACL) 允许来自隧道 IP 的客户端连接。如果您的 Squid 服务器在与 OpenVPN 服务器不同的机器上运行,并且 OpenVPN 服务器正在使用网络地址转换 (NAT) 来“隐藏”所有隧道发起的数据包在其自身的 IP 地址之后(我稍后将讨论 NAT),那么这是一个无关紧要的问题。
但是,如果您在 OpenVPN 服务器本身上运行 Web 代理,则需要一个 ACL。对于 Squid,您需要在 /etc/squid/squid.conf 中添加类似这样的内容
acl openvpn_tunnels src 10.31.33.0/24 http_access allow openvpn_tunnels
的acl行定义了一个名为openvpn_tunnels的对象,表示源 IP 地址介于 10.31.33.1 和 10.31.33.254 之间的事务。http_access行允许从这个 IP 范围发起的事务。与您对此文件所做的任何其他更改一样,您需要重启 Squid 才能使此 ACL 生效 (sudo /etc/init.d/squid restart).
您的客户端当然需要配置为使用您的 Web 代理,但无论他们是通过 OpenVPN 从远处连接还是直接连接到您的 LAN,他们都定位相同的 IP 地址。也就是说,如果您已经让您的用户代理所有 Web 流量,那么他们通过 OpenVPN 使用相同的代理应该不需要更改他们的 Web 浏览器设置。
如果您要求所有远程用户将所有 Internet 流量通过 VPN 隧道路由,那么仅仅强制他们使用远程网络的默认网关是不够的。您还需要强制他们使用远程网络的 DNS 服务器。否则,隧道客户端侧涉及 DNS 欺骗的中间人攻击将会成功。一旦远程用户的浏览器被告知某个给定 URL 的网络钓鱼站点的 IP 地址,那么它连接到该 IP 是直接连接还是通过 VPN 隧道连接都无关紧要(除非,也许,网络钓鱼站点的 IP 地址在您的公司 Web 代理或防火墙强制执行的黑名单上)。
如果您的远程客户端都运行 Windows,则很容易强制执行服务器端 DNS 设置。只需将以下行添加到您的 OpenVPN 服务器的 OpenVPN 配置文件中
push "dhcp-option DNS 10.0.0.100" push "dhcp-option DNS 10.0.0.120"
当然,您应该将 10.0.0.100 和 10.0.0.120 替换为您希望客户端使用的 DNS 服务器的地址。
不幸的是,这不适用于非 Windows 客户端。对于 Linux 和其他 UNIX 客户端,您需要手动或动态地编辑这些客户端系统的 /etc/resolv.conf 文件。服务器端配置参数foreign_option_<I>n<I>允许您将数据传递给隧道启动脚本 (--up脚本);例如,行foreign_option_1='dhcp-option DNS 10.0.0.100'发送行dhcp-option DNS 10.0.0.100到任何已定义的“up”脚本,然后这些脚本可以对该数据进行操作。
所有这些工作的细节超出了本文的范围。只需说 OpenVPN 手册页描述了“up”脚本的工作方式,并且本文的“资源”中的 update-resolv-conf 脚本的链接提供了一个您可以更改的脚本,以重写 /etc/resolv.conf 以优先考虑您的“家庭”网络的 DNS 服务器。
允许远程用户通过其 VPN 隧道将数据包路由到 Internet 还需要一个关键步骤。您需要设置网络地址转换 (NAT),以便从 VPN 隧道进入您的“家庭”网络的流量看起来源自 OpenVPN 服务器。
这是因为远程客户端连接的网络将具有与您的“家庭”网络不同的网络 IP 地址,在这种情况下,您的“家庭”网络基础设施很可能没有到远程客户端的路由,或者它们将具有相同的网络 IP 地址,在这种情况下,VPN 隧道的相对端的不同主机很可能具有相同的主机 IP 地址!
请注意,这个问题在“桥接”(第 2 层)VPN 隧道和“路由”(第 3 层)VPN 隧道上的表现不同。由于到目前为止我的所有示例都涉及路由 VPN 场景,因此我接下来要说的关于 NAT 的内容适用于路由 VPN 隧道。
因此,完全回避远程客户端数据包上外国 IP 地址问题的方法是简单地使用 OpenVPN 服务器的本地 IP 地址重写所有进入 OpenVPN 服务器本地网络的数据包。要做到这一点,只需添加一条防火墙规则,就像这样
bash-$ sudo iptables -t nat -A POSTROUTING ↪-s 10.31.33.0/24 -o eth0 -j MASQUERADE
请注意,与您执行命令的任何其他时间一样iptables,这不是持久性更改。要使此规则在重启后保持持久,您需要将等效行添加到控制您的 OpenVPN 服务器上的防火墙的任何配置文件或脚本中。
OpenVPN 手册页有一个关于防火墙的完整章节(称为“FIREWALLS”),其中包含大量关于管理您的 OpenVPN 服务器上的 iptables 防火墙规则的良好信息。请记住,任何 VPN 服务器都是安全设备。运行的不仅仅是一个 NAT 规则是个好主意,而是一组详细的过滤规则,这些规则限制了人们如何连接到服务器以及您的 VPN 客户端可以连接到哪些系统。
(说到 iptables,自从我在本专栏中介绍 Linux 强大的防火墙功能以来已经很长时间了。请期待在未来的专栏中看到一篇关于编写您自己的 Linux 防火墙规则的深入文章。)
本文和我之前的四篇专栏文章涵盖了虚拟专用网络原理和架构;描述了 Linux 可用的一些 VPN 技术以及 SSL/TLS 解决方案与 IPsec 的不同之处;涵盖了 OpenVPN 服务器配置,包括如何生成和管理数字证书;并描述了客户端配置和用法;所有这些都适用于简单的远程访问使用场景。
有了所有这些以及我本月涵盖的实际使用细节,您应该能够很好地使用 OpenVPN 构建安全的远程访问 VPN 解决方案。如果您决定使用 OpenVPN 代替或额外地构建网络到网络 VPN 或进行“桥接”OpenVPN 解决方案,那么 OpenVPN 手册页、HOWTO 和 FAQ 现在对您来说应该比在阅读这些文章之前更有意义——所有这些都意味着,您不再有任何借口在没有保护的情况下通过不安全的无线热点上网!
资源
OpenVPN 官方主页:www.openvpn.net
OpenVPN FAQ:openvpn.net/index.php/open-source/faq.html
OpenVPN HOWTO:www.openvpn.net/index.php/open-source/documentation/howto.html
Ubuntu 社区 OpenVPN 页面:https://help.ubuntu.com/community/OpenVPN
Thomas Hood 和 Chris Hanson 编写的 update-resolv-conf 脚本:www.subvs.co.uk/openvpn_resolvconf
Mick Bauer (darth.elmo@wiremonkeys.org) 是美国最大的银行之一的网络安全架构师。他是 O'Reilly 出版的书籍 Linux 服务器安全 第二版(以前称为 使用 Linux 构建安全服务器)的作者,偶尔在信息安全会议上发表演讲,并且是“网络工程波尔卡舞曲”的作曲家。