如何使用 openconnect 和 vpn-slice 连接到 Linux 中的企业 VPN

您想在工作中使用 Linux,但您的公司 VPN 不允许吗? 那么这篇文章可能会有所帮助,尽管这还不确定。 我想提前警告您,我不太了解网络管理问题,因此有可能我做错了一切。 另一方面,我也有可能写出一个普通人可以理解的指南,所以我建议你尝试一下。

这篇文章包含很多不必要的信息,但如果没有这些知识,我将无法解决设置 VPN 时意外出现的问题。 我认为任何尝试使用本指南的人都会遇到我没有遇到的问题,我希望这些额外的信息将有助于他们自己解决这些问题。

本指南中使用的大多数命令都需要通过 sudo 执行,为简洁起见,已将其删除。 记住。

大多数IP地址都被严重混淆了,所以如果您看到像435.435.435.435这样的地址,那么那里一定有一些正常的IP,特定于您的情况。

我有 Ubuntu 18.04,但我认为只需稍加修改,该指南就可以应用于其他发行版。 然而,在本文中,Linux == Ubuntu。

Cisco Connect

使用 Windows 或 MacOS 的用户可以通过 Cisco Connect 连接到我们的企业 VPN,需要指定网关地址,并且每次连接时输入由固定部分和 Google Authenticator 生成的代码组成的密码。

就 Linux 而言,我无法运行 Cisco Connect,但我设法在 google 上搜索到了使用 openconnect 的建议,该建议是专门用来替代 Cisco Connect 的。

开放连接

理论上,Ubuntu有一个专门的openconnect图形界面,但它对我不起作用。 也许是为了更好。

在 Ubuntu 上,openconnect 是从包管理器安装的。

apt install openconnect

安装后,您可以立即尝试连接VPN

openconnect --user poxvuibr vpn.evilcorp.com

vpn.evilcorp.com 是虚构 VPN 的地址
poxvuibr - 虚构的用户名

openconnect 会要求您输入密码,我提醒您,该密码由固定部分和来自 Google Authenticator 的代码组成,然后它将尝试连接到 VPN。 如果它有效,那么恭喜你,你可以安全地跳过中间的过程,这很痛苦,然后继续讨论 openconnect 在后台运行的问题。 如果不起作用,那么您可以继续。 尽管如果它在连接时有效,例如,通过工作时的访客 Wi-Fi 连接,那么现在高兴可能还为时过早;您应该尝试在家中重复该过程。

证明书

很可能什么都不会启动,并且 openconnect 输出将如下所示:

POST https://vpn.evilcorp.com/
Connected to 777.777.777.777:443
SSL negotiation with vpn.evilcorp.com
Server certificate verify failed: signer not found

Certificate from VPN server "vpn.evilcorp.com" failed verification.
Reason: signer not found
To trust this server in future, perhaps add this to your command line:
    --servercert sha256:4444444444444444444444444444444444444444444444444444444444444444
Enter 'yes' to accept, 'no' to abort; anything else to view: fgets (stdin): Operation now in progress

一方面,这是令人不快的,因为没有连接到 VPN,但另一方面,原则上如何解决这个问题是明确的。

在这里,服务器向我们发送了一个证书,通过该证书,我们可以确定连接是与我们本地公司的服务器建立的,而不是与邪恶的欺诈者建立的,并且该证书对于系统来说是未知的。 因此她无法检查服务器是否真实。 因此,为了以防万一,它会停止工作。

为了让 openconnect 连接到服务器,您需要使用 —servercert key 明确告诉它哪个证书应该来自 VPN 服务器

您可以从 openconnect 打印的内容中找到服务器直接发送给我们的证书。 这是这篇文章的内容:

To trust this server in future, perhaps add this to your command line:
    --servercert sha256:4444444444444444444444444444444444444444444444444444444444444444
Enter 'yes' to accept, 'no' to abort; anything else to view: fgets (stdin): Operation now in progress

使用此命令您可以尝试再次连接

openconnect --servercert sha256:4444444444444444444444444444444444444444444444444444444444444444 --user poxvuibr vpn.evilcorp.com

也许现在它正在发挥作用,那么你就可以继续进行到底了。 但就个人而言,乌本塔向我展示了这种形式的无花果

POST https://vpn.evilcorp.com/
Connected to 777.777.777.777:443
SSL negotiation with vpn.evilcorp.com
Server certificate verify failed: signer not found
Connected to HTTPS on vpn.evilcorp.com
XML POST enabled
Please enter your username and password.
POST https://vpn.evilcorp.com/
Got CONNECT response: HTTP/1.1 200 OK
CSTP connected. DPD 300, Keepalive 30
Set up DTLS failed; using SSL instead
Connected as 192.168.333.222, using SSL
NOSSSSSHHHHHHHDDDDD
3
NOSSSSSHHHHHHHDDDDD
3
RTNETLINK answers: File exists
/etc/resolvconf/update.d/libc: Warning: /etc/resolv.conf is not a symbolic link to /run/resolvconf/resolv.conf

/ etc / resolv.conf中

# Generated by NetworkManager
search gst.evilcorpguest.com
nameserver 127.0.0.53

/run/resolvconf/resolv.conf

# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
# 127.0.0.53 is the systemd-resolved stub resolver.
# run "systemd-resolve --status" to see details about the actual nameservers.

nameserver 192.168.430.534
nameserver 127.0.0.53
search evilcorp.com gst.publicevilcorp.com

habr.com 将会解决,但您将无法前往那里。 像 jira.evilcorp.com 这样的地址根本无法解析。

我不清楚这里发生了什么。 但实验表明,如果您将这一行添加到 /etc/resolv.conf

nameserver 192.168.430.534

然后 VPN 内的地址将开始神奇地解析,您可以浏览它们,也就是说,DNS 正在寻找的解析地址专门在 /etc/resolv.conf 中查找,而不是在其他地方。

您可以验证是否存在与 VPN 的连接并且它可以正常工作,而无需对 /etc/resolv.conf 进行任何更改;为此,只需在浏览器中输入其 IP 地址,而不是来自 VPN 的资源的符号名称

这样一来,就有两个问题

  • 连接到 VPN 时,未获取其 dns
  • 所有流量都通过VPN,不允许访问互联网

我会告诉你现在该怎么做,但首先是一点自动化。

自动输入密码的固定部分

到目前为止,您很可能已经输入了至少五次密码,而这个过程已经让您疲惫不堪。 一是因为密码长,二是因为输入时需要契合固定的时间段

该问题的最终解决方案并未包含在文章中,但您可以确保密码的固定部分不必输入多次。

假设密码的固定部分是fixedPassword,来自Google Authenticator的部分是567 987。可以使用参数 --passwd-on-stdin 通过标准输入将整个密码传递给 openconnect 。

echo "fixedPassword567987" | openconnect --servercert sha256:4444444444444444444444444444444444444444444444444444444444444444 --user poxvuibr vpn.evilcorp.com --passwd-on-stdin

现在,您可以不断返回到最后输入的命令,并仅更改其中的部分 Google 身份验证器。

企业 VPN 不允许您上网。

一般来说,当你必须使用单独的计算机去哈布尔时,这并不是很不方便。 无法从 stackoverfow 进行复制粘贴通常会导致工作瘫痪,因此需要采取一些措施。

我们需要以某种方式组织它,以便当您需要从内部网络访问资源时,Linux 会转到 VPN,而当您需要访问 Habr 时,它会转到 Internet。

openconnect 在启动并与 vpn 建立连接后,会执行一个特殊的脚本,该脚本位于 /usr/share/vpnc-scripts/vpnc-script 中。 一些变量作为输入传递给脚本,并配置 VPN。 不幸的是,我无法弄清楚如何使用本机脚本在企业 VPN 和互联网其他部分之间分配流量。

显然,vpn-slice 实用程序是专门为像我这样的人开发的,它允许您通过两个通道发送流量,而无需手鼓跳舞。 嗯,也就是说,你必须跳舞,但你不必成为萨满。

使用 vpn-slice 进行流量分离

首先,你必须安装 vpn-slice,你必须自己解决这个问题。 如果评论里有问题,我会单独写一篇文章讨论这个问题。 但这是一个常规的Python程序,所以应该不会有任何困难。 我使用 virtualenv 安装。

然后必须使用 -script 开关应用该实用程序,指示 openconnect 需要使用 vpn-slice,而不是标准脚本

echo "fixedPassword567987" | openconnect --servercert sha256:4444444444444444444444444444444444444444444444444444444444444444 --user poxvuibr --passwd-on-stdin 
--script "./bin/vpn-slice 192.168.430.0/24  " vpn.evilcorp.com 

--script 传递一个字符串,其中包含需要调用的命令而不是脚本。 ./bin/vpn-slice - vpn-slice 可执行文件的路径 192.168.430.0/24 - vpn 中要访问的地址掩码。 这里,我们的意思是,如果地址以192.168.430开头,那么需要在VPN内部搜索该地址的资源

现在的情况应该差不多正常了。 几乎。 现在你去Habr可以通过ip去企业内部资源,但是不能通过符号名去企业内部资源。 如果您在主机中指定符号名称和地址之间的匹配,则一切都应该有效。 并一直工作直到ip改变。 Linux 现在可以访问 Internet 或 Intranet,具体取决于 IP。 但仍使用非企业 DNS 来确定地址。

问题还可以通过这种形式表现出来——在工作中一切都很好,但在家里你只能通过IP访问公司内部资源。 这是因为当您连接到公司 Wi-Fi 时,也会使用公司 DNS,并在其中解析来自 VPN 的符号地址,尽管事实上不使用 VPN 仍然无法访问此类地址。

自动修改hosts文件

如果礼貌地询问 vpn-slice,则在启动 VPN 后,它可以转到其 DNS,通过符号名称找到必要资源的 IP 地址,并将其输入到主机中。 关闭 VPN 后,这些地址将从主机中删除。 为此,您需要将符号名称作为参数传递给 vpn-slice。 像这样。

echo "fixedPassword567987" | openconnect --servercert sha256:4444444444444444444444444444444444444444444444444444444444444444 --user poxvuibr --passwd-on-stdin
--script "./bin/vpn-slice 192.168.430.0/24  jira.vpn.evilcorp.com git.vpn.evilcorp.com " vpn.evilcorp.com 

现在一切都应该在办公室和海滩上都能正常工作。

在VPN给出的DNS中搜索所有子域的地址

如果网络内的地址很少,那么自动修改hosts文件的方法就很有效。 但如果网络上有很多资源,那么您将不断需要在脚本中添加像 zoidberg.test.evilcorp.com 这样的行,zoidberg 是其中一个测试平台的名称。

但现在我们已经了解了为什么可以消除这种需求了。

如果在启动 VPN 后,您查看 /etc/hosts,您可以看到这一行

192.168.430.534 dns0.tun0 # vpn-slice-tun0 自动创建

并在 resolv.conf 中添加了新行。 简而言之,vpn-slice 以某种方式确定了 vpn 的 dns 服务器所在的位置。

现在我们需要确保,为了找到以evillcorp.com 结尾的域名的IP 地址,Linux 会访问公司DNS,如果需要其他内容,则访问默认DNS。

我在 Google 上搜索了一段时间,发现 Ubuntu 中已经提供了这样的功能。 这意味着能够使用本地 DNS 服务器 dnsmasq 来解析名称。

也就是说,您可以确保Linux始终向本地DNS服务器查找IP地址,而本地DNS服务器又会根据域名在相应的外部DNS服务器上查找IP。

为了管理与网络和网络连接相关的所有内容,Ubuntu 使用 NetworkManager,而用于选择(例如 Wi-Fi 连接)的图形界面只是它的前端。

我们需要爬升它的配置。

  1. 在 /etc/NetworkManager/dnsmasq.d/evilcorp 中创建文件

地址=/.evilcorp.com/192.168.430.534

注意evilcorp前面的点。 它向 dnsmasq 发出信号,应在公司 dns 中搜索 evilcorp.com 的所有子域。

  1. 告诉 NetworkManager 使用 dnsmasq 进行名称解析

网络管理器配置位于 /etc/NetworkManager/NetworkManager.conf 您需要在那里添加:

[主要] dns=dnsmasq

  1. 重新启动网络管理器

service network-manager restart

现在,使用 openconnect 和 vpn-slice 连接到 VPN 后,即使您没有将符号地址添加到 vpnslice 的参数中,也会正常确定 IP。

如何通过VPN访问个人服务

成功连接VPN后,我高兴了两天,然后发现,如果我从办公室网络外连接VPN,那么邮件就不能用了。 这个症状很熟悉,不是吗?

我们的邮件位于mail.publicevilcorp.com,这意味着它不属于dnsmasq的规则,并且邮件服务器地址是通过公共DNS搜索的。

嗯,办公室仍然使用 DNS,其中包含这个地址。 和我想的一样。 事实上,将行添加到 dnsmasq 后

地址=/mail.publicevilcorp.com/192.168.430.534

情况根本没有改变。 ip保持不变。 我必须去上班。

后来,当我深入了解情况并稍微了解了问题后,一位聪明的人告诉我如何解决。 不仅需要通过VPN连接到邮件服务器

我使用 vpn-slice 通过 VPN 访问以 192.168.430 开头的地址。 而且邮件服务器不仅有一个不是evilcorp子域的符号地址,而且也没有以192.168.430开头的IP地址。 当然,他也不允许总网的人来找他。

为了让 Linux 通过 VPN 到达邮件服务器,您还需要将其添加到 vpn-slice。 假设邮寄者的地址是 555.555.555.555

echo "fixedPassword567987" | openconnect --servercert sha256:4444444444444444444444444444444444444444444444444444444444444444 --user poxvuibr --passwd-on-stdin
--script "./bin/vpn-slice 555.555.555.555 192.168.430.0/24" vpn.evilcorp.com 

通过一个参数提升 VPN 的脚本

当然,这一切并不是很方便。 是的,您可以将文本保存到文件中并将其复制粘贴到控制台中,而不是手动输入,但这仍然不是很愉快。 为了使该过程更容易,您可以将该命令包装在位于 PATH 中的脚本中。 然后您只需要输入从 Google Authenticator 收到的代码

#!/bin/sh  
echo "fixedPassword$1" | openconnect --servercert sha256:4444444444444444444444444444444444444444444444444444444444444444 --user poxvuibr --passwd-on-stdin 
--script "./bin/vpn-slice 192.168.430.0/24  jira.vpn.evilcorp.com git.vpn.evilcorp.com " vpn.evilcorp.com 

如果你把脚本放在 connect~evilcorp~ 中,你可以简单地在控制台中编写

connect_evil_corp 567987

但现在由于某种原因你仍然必须保持运行 openconnect 的控制台打开

在后台运行 openconnect

幸运的是,openconnect的作者很照顾我们,给程序添加了一个特殊的键——background,使得程序启动后在后台工作。 如果你像这样运行它,你可以在启动后关闭控制台

#!/bin/sh  
echo "fixedPassword$1" | openconnect --servercert sha256:4444444444444444444444444444444444444444444444444444444444444444 
--user poxvuibr 
--passwd-on-stdin 
--background 
--script "./bin/vpn-slice 192.168.430.0/24  jira.vpn.evilcorp.com git.vpn.evilcorp.com " vpn.evilcorp.com  

现在还不清楚日志去了哪里。 一般来说,我们并不真正需要日志,但你永远不知道。 openconnect 可以将它们重定向到 syslog,在那里它们将保持安全。 您需要将 –syslog 开关添加到命令中

#!/bin/sh  
echo "fixedPassword$1" | openconnect --servercert sha256:4444444444444444444444444444444444444444444444444444444444444444 
--user poxvuibr 
--passwd-on-stdin 
--background 
--syslog 
--script "./bin/vpn-slice 192.168.430.0/24  jira.vpn.evilcorp.com git.vpn.evilcorp.com " vpn.evilcorp.com  

因此,事实证明 openconnect 正在后台某个地方工作,并且不会打扰任何人,但尚不清楚如何阻止它。 也就是说,您当然可以使用 grep 过滤 ps 输出并查找名称包含 openconnect 的进程,但这在某种程度上很乏味。 感谢也思考过这个问题的作者。 Openconnect 有一个关键的 -pid-file,使用它可以指示 openconnect 将其进程标识符写入文件。

#!/bin/sh  
echo "fixedPassword$1" | openconnect --servercert sha256:4444444444444444444444444444444444444444444444444444444444444444 
--user poxvuibr 
--passwd-on-stdin 
--background  
--syslog 
--script "./bin/vpn-slice 192.168.430.0/24  jira.vpn.evilcorp.com git.vpn.evilcorp.com " vpn.evilcorp.com  
--pid-file ~/vpn-pid

现在您可以随时使用命令终止进程

kill $(cat ~/vpn-pid)

如果没有进程,kill会诅咒,但不会抛出错误。 如果该文件不存在,那么也不会发生任何不良情况,因此您可以安全地终止脚本第一行中的进程。

kill $(cat ~/vpn-pid)
#!/bin/sh  
echo "fixedPassword$1" | openconnect --servercert sha256:4444444444444444444444444444444444444444444444444444444444444444 
--user poxvuibr 
--passwd-on-stdin 
--background 
--syslog 
--script "./bin/vpn-slice 192.168.430.0/24  jira.vpn.evilcorp.com git.vpn.evilcorp.com " vpn.evilcorp.com  
--pid-file ~/vpn-pid

现在您可以打开计算机,打开控制台并运行命令,并向其传递来自 Google Authenticator 的代码。 然后就可以固定控制台了。

没有 VPN 切片。 而不是后记

事实证明,很难理解如何在没有 VPN 切片的情况下生活。 我必须大量阅读和谷歌。 幸运的是,在花了这么多时间解决一个问题之后,技术手册甚至 man openconnect 读起来就像令人兴奋的小说一样。

结果,我发现 vpn-slice 和原生脚本一样,修改了路由表以分离网络。

路由表

简单来说,这是一个表,第一列包含Linux要经过的地址应该从什么开始,第二列包含该地址要经过哪个网络适配器。 其实发言者还多了,但这并没有改变本质。

为了查看路由表,需要运行 ip route 命令

default via 192.168.1.1 dev wlp3s0 proto dhcp metric 600 
192.168.430.0/24 dev tun0 scope link 
192.168.1.0/24 dev wlp3s0 proto kernel scope link src 192.168.1.534 metric 600 
192.168.430.534 dev tun0 scope link 

在这里,每一行负责您需要去哪里才能将消息发送到某个地址。 第一个是地址应该从哪里开始的描述。 为了了解如何确定 192.168.0.0/16 意味着该地址应该以 192.168 开头,您需要 google 什么是 IP 地址掩码。 dev 之后是消息应发送到的适配器的名称。

对于VPN,Linux制作了一个虚拟适配器——tun0。 该线路确保以 192.168 开头的所有地址的流量都经过它

192.168.0.0/16 dev tun0 scope link 

您还可以使用以下命令查看路由表的当前状态 路线-n (IP 地址被巧妙地匿名化)该命令以不同的形式生成结果,并且通常已被弃用,但其输出通常可以在 Internet 上的手册中找到,并且您需要能够阅读它。

路由的 IP 地址应该从哪里开始可以通过 Destination 和 Genmask 列的组合来理解。 IP 地址中与 Genmask 中的数字 255 相对应的部分会被考虑在内,但 0 的部分则不会被考虑在内。 也就是说,Destination 192.168.0.0 和 Genmask 255.255.255.0 的组合意味着,如果地址以 192.168.0 开头,那么对其的请求将沿着这条路线进行。 如果目标地址为 192.168.0.0 但 Genmask 为 255.255.0.0,则对以 192.168 开头的地址的请求将沿着此路线进行

为了弄清楚 vpn-slice 实际做了什么,我决定查看前后表的状态

没开启VPN之前是这样的

route -n 

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         222.222.222.1   0.0.0.0         UG    600    0        0 wlp3s0
222.222.222.0   0.0.0.0         255.255.255.0   U     600    0        0 wlp3s0
333.333.333.333 222.222.222.1   255.255.255.255 UGH   0      0        0 wlp3s0

在没有 vpn-slice 的情况下调用 openconnect 后,它变成了这样

route -n

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         0.0.0.0         0.0.0.0         U     0      0        0 tun0
0.0.0.0         222.222.222.1   0.0.0.0         UG    600    0        0 wlp3s0
222.222.222.0   0.0.0.0         255.255.255.0   U     600    0        0 wlp3s0
333.333.333.333 222.222.222.1   255.255.255.255 UGH   0      0        0 wlp3s0
192.168.430.0   0.0.0.0         255.255.255.0   U     0      0        0 tun0
192.168.430.534 0.0.0.0         255.255.255.255 UH    0      0        0 tun0

在像这样与 vpn-slice 结合调用 openconnect 之后

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         222.222.222.1   0.0.0.0         UG    600    0        0 wlp3s0
222.222.222.0   0.0.0.0         255.255.255.0   U     600    0        0 wlp3s0
333.333.333.333 222.222.222.1   255.255.255.255 UGH   0      0        0 wlp3s0
192.168.430.0   0.0.0.0         255.255.255.0   U     0      0        0 tun0
192.168.430.534 0.0.0.0         255.255.255.255 UH    0      0        0 tun0

可以看到,如果不使用vpn-slice,那么openconnect明确写道,所有地址,除了特别指明的,都必须通过vpn访问。

这是:

0.0.0.0         0.0.0.0         0.0.0.0         U     0      0        0 tun0

在它旁边,立即指示另一条路径,如果 Linux 尝试通过的地址与表中的任何掩码都不匹配,则必须使用该路径。

0.0.0.0         222.222.222.1   0.0.0.0         UG    600    0        0 wlp3s0

这里已经写到,在这种情况下您需要使用标准的 Wi-Fi 适配器。

我相信使用了 VPN 路径,因为它是路由表中的第一个路径。

而且理论上,如果从路由表中删除这条默认路径,那么结合 dnsmasq openconnect 应该可以保证正常运行。

我试过了

route del default

一切顺利。

将请求路由到没有 VPN 切片的邮件服务器

但我还有一个地址为555.555.555.555的邮件服务器,也需要通过VPN访问。 到它的路由也需要手动添加。

ip route add 555.555.555.555 via dev tun0

现在一切都很好。 所以你可以不用 vpn-slice,但你需要清楚地知道你在做什么。 我现在正在考虑在本机 openconnect 脚本的最后一行中添加删除默认路由的功能,并在连接到 VPN 后为邮件程序添加一条路由,这样我的自行车中的移动部件就会更少。

也许,这篇后记足以让人们了解如何设置 VPN。 但是,当我试图了解做什么以及如何做时,我阅读了很多对作者有用的此类指南,但由于某种原因对我不起作用,我决定在这里添加我找到的所有内容。 我会对这样的事情感到非常高兴。

来源: habr.com

添加评论