笔者目前在一家公司打杂,为了能够在家里也能访问公司内网,就地加班,给自己的设备安装了某终端控制软软件,但是它卸载要管理员授权、强行安装某终端软件还无法卸载、禁止安装某些软件、屏蔽大量第三方邮箱网址、据说在运行过程中还会偷偷截屏。不是哥们,你的手伸的也太宽了吧😓
于是我就想可不可以把它装进虚拟机办公,让它偷窥一个没有任何东西的"空环境",省的它污染我的本机环境。说干就干,但是实验没一会我就受不了了,虚拟机实在是太卡了,于是我就开始收集资料,尝试让宿主机通过虚拟机的VPN访问内网。下文仅作技术记录。
VPN做了些什么
在正式动手之前,先要搞清楚VPN到底都干了些什么
创建虚拟网络适配器
为了完全代理所有内网地址,VPN软件会新建一个虚拟的网络适配器,这个网络适配器会被分配一个 内网ip地址、代理网关地址、子网掩码 等,这里以VMWare的虚拟适配器为例。

更新路由表
VPN软件访问内网一般不会代理你的公网流量,所以它会新建很多条路由规则将内网ip流量转发到代理网关。10.0.0.0/8 这个网段覆盖了整个公司内网的ip地址,因此VPN工作的原理就是:只要目标地址是10.0.0.0/8网段的都会被转发到网关10.xxx.xxx.xxx,这些数据包会由VPN创建的虚拟网络适配器(下图的接口)处理和转发

设置DNS
光代理目标ip显然是不够的,公司内网系统都有自己的域名,我们不可能一个一个记不同系统的ip地址,内网系统也不能裸ip部署。所以VPN还需要设置DNS解析服务(有些VPN内置dnsmasq),当你在浏览器输入内网域名时,将域名解析到类似于10.123.45.6的ip地址

让宿主机通过虚拟机VPN访问内网

虚拟机桥接网络+修改宿主机路由表
既然VPN的原理是路由表,那么我们可以想当然的认为只要在宿主机上配上相同的路由规则,让目标地址是 10.0.0.0/8 的数据都走VPN的虚拟网络适配器(简称 VPN网卡)不就可以让宿主机访问内网了吗?但是VPN创建的网卡又不在宿主机上,我们没法让宿主机可以直接访问到VPN网卡又该怎么办呢?
- 虚拟机上目前会有两个网卡,第一个是创建虚拟机时默认的NAT网卡,第二个是VPN创建的VPN网卡。然后先将虚拟机网卡的连接方式修改为桥接模式(简称 桥接网卡),然后桥接网卡和宿主机网卡会分配到相同网段的ip地址,再到虚拟机里输入 ipconfig 查看桥接网卡的ipv4地址、默认网关、子网掩码、dns地址等(提前记住)

- 修改宿主机路由表,将目标地址是10.0.0.0/8的流量转发到 虚拟机桥接网卡上,后面再想办法把流量转到VPN网卡上,就可以通过 宿主机网卡 -> 虚拟机桥接网卡 -> 虚拟机VPN网卡 的方式访问内网了
shell
route add 10.0.0.0 mask 255.0.0.0 ${虚拟机桥接网卡ip} -p

验证:执行tracert -d 10.xxx.xx.xx 任意内网地址,看看第一个跃点是不是桥接网卡的ip
打开虚拟机网卡转发+共享VPN网卡连接
为了让桥接网卡能把流量转到VPN网卡(实际上应该是内核侧去做,不过windows需要更多配置,为了方便理解先这么理解)
- 打开控制面板 > 服务,将Routing And Remote Access服务设置为自动并启动

- 按win+r,输入regedit,找到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters 设置IPEnableRouter的值为1

- 找到虚拟机桥接网卡,记住他的ifIndex,并通过Set-NetIPInterface指令设置Forwarding为Enabled

- 完成上述配置后,仍然不能转发桥接网卡的流量到VPN网卡,需要打开 控制面板>网络和Internet>查看网络状态和任务,找到VPN网卡点击属性>共享,打开Internet连接共享,并选择分享连接到桥接网卡

- 将连接分享给桥接网卡后,桥接网卡的ip地址、网关地址、dns配置等都会发生变化(windows的问题),请打开桥接网卡的属性>网络,并分配固定ip地址、网关、子网掩码和dns (全部填第一步记住的那些值)

配置宿主机DNS访问内网域名
完成上述操作步骤之后,可以ping一下一个内网ip看看是不是能够联通了,如果不通,需要tracert检查一下是不是哪里配错了、配漏了。然后去VPN软件找dns地址 或 控制面板>网络和Internet>查看网络状态和任务,找到VPN网卡点击详细信息,找到DNS地址,配置到宿主机的网络适配器就可以愉快的访问内网了
有些VPN软件会内置dnsmasq等dns server,它的上游是内网dns地址,所以有可能会看到VPN网卡配置的dns地址是127.0.0.1。如果VPN软件没有展示上游dns地址,可以通过隧道访问虚拟机的53端口,然后配置宿主机的网络适配器dns地址也为127.0.0.1
shell
ssh -L 53:localhost:53 user@${虚拟机桥接网卡ip}

解决SSO登录客户端检查
某些内网网站需要通过SSO登录,而SSO登录还会增加一个客户端检查,其原理就是VPN软件拉起一个本地http/https设备认证码服务并支持跨域,每次登录SSO时都会从该本地服务请求客户端认证码做远端认证

这里面最关键的 localhost.vpn.com 会被VPN的dns解析到127.0.0.1,而宿主机没有这个认证码服务进程,宿主机浏览器访问127.0.0.1:8443会失败,因此会被SSO拦住。解决方案就是把宿主机对本机8443端口的访问转发到虚拟机的8443端口的认证码服务进程
shell
ssh -L 8443:localhost:8443 user@${虚拟机桥接网卡ip}