记一次虚拟机作为内网环境跳板机的实践
扭曲的权限, 离谱的甲方
整件事情还得从去甲方驻场开始. 甲方的数据, 服务器, API等等都部署在内网环境中, 并通过两个WIFI进行接入, 分别是WIFIA和WIFIB. 而连接WIFIA之后需要进行网络认证之后才能进入内网环境.
使用WIFIA
但是WIFIA所要求的环境极其苛刻:
- 需要安装套壳的入网小助手
isAgent. (这个软件及其恶心, 安装之后卸载需要动态验证码, 只能去找运维要, 也就是基本不可能卸载的意思. 使用卸载工具进行卸载也没用, 看网上论坛说如果强行删除文件会破坏电脑网络相关驱动导致无法上网. 总之就是非常恶心, 而我是怎么卸载成功的, 又是另一个故事了.) - 需要安装一个企业内的远程接入软件. (
也是同样卸载不掉, 需要动态确认码. 而且这个软件会自动杀掉我的QQ进程, 使用微信也会频繁发出提醒.) - 需要安装企业内部定制版的天擎杀毒软件.
前两步都是自动安装的, 没有遇到什么问题(除了软件究极恶心之外), 直到遇到第三个软件, 网络上没有公开下载方式, 入网校验网页上有一个安装button, 但是点击之后跳转的download网址也被网关拦住了. 所以现在就陷入了一个死锁状态:

能感受到这种绝望吗🤣
尝试WIFIB
于是去问了之前给我们开通数据库权限的工作人员, 给我们的答复是连接WIFIB, WIFIB不会有这些奇奇怪怪的要求. 但是我们连接WIFIB的时候显示账号不存在. 经过反复询问, 打电话, 摇人之后才得知, 登录WIFIA和登录WIFIB的账号并不是同一个账号, 但是他们又有一种奇妙的绑定关系. 我们随即提出申请, 但是申请下来的账号仍然无法登录WIFIB. 最终, 给我们摇了一个运维人员, 到我们电脑前面指导.
解除死锁, 捏着鼻子连接WIFIA
运维人员来了, 很快啊, 啪的一下就给我连接了WIFIA, 并已经完成了第一个软件(isAgent)的安装. 我追悔莫及(因为第一次安装WIFIA之后受不了究极恶心的软件, 连夜重装了系统)但又无可奈何. 随即我提出在同门的电脑上进行操作, 他的电脑已经装了两个软件, 就卡在死锁上了.
运维人员重复了我们的操作, 确定无法下载杀毒软件之后, 掏出了一个U盘, 打开之后找到杀毒软件, 随着软件的复制, 我知道, 我必须得捏着鼻子用WIFIA了.
不过虽然死锁被解除了, 我发现我们并不能像其他工作人员那样, 连接WIFIA的同时还能够访问互联网. 这一点运维人员说可能没有给我们开权限, 之后就走了. 我们深知如果再去申请一波权限, 又要等到不知道猴年马月. 于是, 终于, 有了充足的动机, 催生我进行下面的实践了——在虚拟机里面访问内网.
安装虚拟机, 访问内网
使用VMWare
既然软件这么恶心, 所以干脆放在虚拟机里面, 一些内网操作都在虚拟机里面运行. 考虑到虚拟机里面可能要用到APIfox, Navicat等软件, 所以对性能还是有一定的要求. 之前看网上说性能优化上VMware会比VirtualBox要好一些, 于是使用VMware创建虚拟机.
虚拟机, 那就是极致的精简, 极致的性能取向, 所以毫不犹豫选择LSTC + Win10. 但是市面上存在很多修改LSTC, 更加精简, 更加丝滑, 按理说会体验会更好, 但是考虑到需求的紧迫性以及修改版的安装复杂度(大部分修改LSTC是esd后缀, 都需要在PE里进行单独操作, 这方面我还不是那么熟练), 最终还是选择了官方LSTC版本.

但是在VMware虚拟机装好之后发现了一个问题, 我的虚拟机网卡选择了桥接模式, 当我连接WIFIA的时候, 按理说虚拟机内部也能够打开网络认证网页才对, 但是既没有弹出网页, 我手动打开网页的时候也无法正常访问. 我再三确认了我配置是正确的, 并且在网上搜索了教程, 跟着教程又配了一遍(其实也没多少要改的), 均已失败告终. 所以, 最终还是放弃了VMware.
使用VirtualBox
最终还是回到了我熟悉的VirtualBox的怀抱. 先装好系统, 配置桥接模式并指定WIFI网卡. 连上WIFIA, 虚拟机一开机就弹出了网络认证页面, 相当顺畅.

接下来就是熟悉的安装三个软件, 至此, 内网终于可以在虚拟机里联通并使用了.
内网/外网? 我全都要
使用虚拟机是为了避免恶心软件对我日常电脑使用造成影响, 既然现在已经搞定了, 那么尝试使用一下.

虚拟机里虽然可以正常访问内网, 能够发送API, 连接数据库, 但是还是比较卡顿(类似于使用ToDesk连接一个网络条件不好的电脑), 操作又慢又迟缓. 即使我将虚拟机的配置开到了4核8G, 还是无法缓解.
这个时候就又产生了一个想法, 能否将虚拟机作为跳板机, 实现宿主机通过虚拟机的ip来访问内网呢? 这样的话就可以不接触虚拟机, 而仅需要虚拟机提供ip即可, 实际的软件操作都在宿主机上进行, 避免了卡顿, 还能够节约资源, 一举两得!
这时我又想到, 不仅是上面的问题, 还有一个内外网的痛点, 当我连了WIFIA之后, 我就无法访问互联网了, 同样使用互联网就没法连接内网环境了. 这对于开发是很难令人接受的, 开发中的搜索是特别频繁的.
以上两个痛点强烈驱使我寻找一个更加”优雅”的解决方案. 于是, 便有了这一节.
内外网同时访问
我仅存的计算机网络知识告诉我, 如果要同时访问内外网, 那么至少要两个IP地址, 内网通过一个IP访问, 外网通过另一个IP访问, 将路由规则制定好即可实现目标.
得亏于重装电脑的经验过于丰富, 有时候电脑刚重装之后电脑没有无线网卡的驱动, 这个时候上网就是采用手机USB共享网络给电脑进行互联网访问, 这在电脑上的表现形式(小图标)是有线以太网, 且是免驱的.

此时再连接WIFIA, 便有了两个IP, ipconfig信息如下:
以太网适配器 以太网 2: -------------------------------------------(USB网络IP)
连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . : fe80::7030:e99f:4565:e2ea%11
IPv4 地址 . . . . . . . . . . . . : 192.168.199.139
子网掩码 . . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . : 192.168.199.155
无线局域网适配器 WLAN:--------------------------------------------(无线IP)
连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . : fe80::8b2:cbf0:a408:67cf%9
IPv4 地址 . . . . . . . . . . . . : 10.18.39.137
子网掩码 . . . . . . . . . . . . : 255.255.254.0
默认网关. . . . . . . . . . . . . : 10.18.39.254
以太网适配器 以太网 3:--------------------------------------------(VirtualBox Host-Only网卡)
连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . : fe80::3497:ef6e:b6fc:3d28%18
IPv4 地址 . . . . . . . . . . . . : 192.168.56.1
子网掩码 . . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . :有了USB网络共享, 这个时候就可以访问互联网了, 但是当我们手动输入内网认证网页的时候发现又打不开了.

不用想, 肯定是路由配置的有问题, 我们尝试使用tracert命令来追踪ip对应走的路由:
PS C:\Users\Wongbuer> tracert 10.18.14.250
通过最多 30 个跃点跟踪到 10.18.14.250 的路由
1 <1 毫秒 <1 毫秒 <1 毫秒 192.168.199.155
2 20 ms 38 ms 18 ms 192.168.25.254
3 * 37 ms * 10.1.0.17
(被我用Ctrl + C中断)可以看到, 默认走的是USB的网关, 这与我们的预期是不符的, 我们需要的是内网走WIFI的网关, 外网走USB的网关.
所以我们需要手动配置一个路由规则, 鉴于目前遇到的内网IP都是(10.x.x.x)开头, 所以干脆配一个10.0.0.0/8的路由规则:
PS C:\Users\Wongbuer> route add 10.0.0.0 MASK 255.0.0.0 10.18.39.254 -p
操作完成!接着我们再次使用tracert命令进行跟踪:
PS C:\Users\Wongbuer> tracert 10.18.14.250
通过最多 30 个跃点跟踪到 10.18.14.250 的路由
1 * * * 请求超时。
2 * * * 请求超时。
3 * 6 ms 4 ms 10.18.9.25
4 7 ms 4 ms 5 ms 10.18.13.235
5 5 ms 4 ms 4 ms 10.18.14.250
跟踪完成。奇奇怪怪, 前两跳显示超时了, 不过可能是网关那边禁Ping, 不过我们可以看到, 是能成功访问内网地址的.
最后, 为了确保保险, 打印路由表看一下:
PS C:\Users\Wongbuer> route print
===========================================================================
接口列表
11...46 55 34 a6 a1 75 ......Remote NDIS Compatible Device
18...0a 00 27 00 00 12 ......VirtualBox Host-Only Ethernet Adapter
12...c2 bf be 47 0d 8a ......Microsoft Wi-Fi Direct Virtual Adapter
16...c2 bf be 47 1d 9a ......Microsoft Wi-Fi Direct Virtual Adapter #2
9...c0 bf be 47 2d aa ......MediaTek Wi-Fi 6E MT7922 160MHz Wireless LAN Card
10...c0 bf be 47 2d ab ......Bluetooth Device (Personal Area Network)
5...b0 25 aa 73 79 c8 ......Realtek PCIe GbE Family Controller
1...........................Software Loopback Interface 1
===========================================================================
IPv4 路由表
===========================================================================
活动路由:
网络目标 网络掩码 网关 接口 跃点数
0.0.0.0 0.0.0.0 192.168.199.155 192.168.199.139 25
0.0.0.0 0.0.0.0 10.18.39.254 10.18.39.137 35
10.0.0.0 255.0.0.0 10.18.39.254 10.18.39.137 36
10.18.38.0 255.255.254.0 在链路上 10.18.39.137 291
10.18.39.137 255.255.255.255 在链路上 10.18.39.137 291
10.18.39.255 255.255.255.255 在链路上 10.18.39.137 291
127.0.0.0 255.0.0.0 在链路上 127.0.0.1 331
127.0.0.1 255.255.255.255 在链路上 127.0.0.1 331
127.255.255.255 255.255.255.255 在链路上 127.0.0.1 331
192.168.56.0 255.255.255.0 在链路上 192.168.56.1 281
192.168.56.1 255.255.255.255 在链路上 192.168.56.1 281
192.168.56.255 255.255.255.255 在链路上 192.168.56.1 281
192.168.199.0 255.255.255.0 在链路上 192.168.199.139 281
192.168.199.139 255.255.255.255 在链路上 192.168.199.139 281
192.168.199.255 255.255.255.255 在链路上 192.168.199.139 281
224.0.0.0 240.0.0.0 在链路上 127.0.0.1 331
224.0.0.0 240.0.0.0 在链路上 192.168.56.1 281
224.0.0.0 240.0.0.0 在链路上 10.18.39.137 291
224.0.0.0 240.0.0.0 在链路上 192.168.199.139 281
255.255.255.255 255.255.255.255 在链路上 127.0.0.1 331
255.255.255.255 255.255.255.255 在链路上 192.168.56.1 281
255.255.255.255 255.255.255.255 在链路上 10.18.39.137 291
255.255.255.255 255.255.255.255 在链路上 192.168.199.139 281
===========================================================================
永久路由:
网络地址 网络掩码 网关地址 跃点数
10.0.0.0 255.0.0.0 10.18.39.254 1
===========================================================================
IPv6 路由表
===========================================================================
活动路由:
接口跃点数网络目标 网关
1 331 ::1/128 在链路上
18 281 fe80::/64 在链路上
9 291 fe80::/64 在链路上
11 281 fe80::/64 在链路上
9 291 fe80::8b2:cbf0:a408:67cf/128
在链路上
18 281 fe80::3497:ef6e:b6fc:3d28/128
在链路上
11 281 fe80::7030:e99f:4565:e2ea/128
在链路上
1 331 ff00::/8 在链路上
18 281 ff00::/8 在链路上
9 291 ff00::/8 在链路上
11 281 ff00::/8 在链路上
===========================================================================
永久路由:
无可以看到, 我们配置的路由规则已经被加上去且功能完好了.
至此, 我们实现了内外网同时访问的需求.(要是能给我们开一个互联网访问权限, 也不会有这么一大堆事情了😑
虚拟机设置跳板机
前文提到, 虚拟机上面的使用体验极其糟糕, 又卡又慢, 所以考虑将虚拟机设置为跳板机, 在宿主机中指定虚拟机作为代理, 将操作转移到宿主机

逻辑结构还是很简单的, 不过这里需要考虑使用什么代理软件的问题. 首先梳理一下我们的需求:
- 需要支持APIfox中对请求的代理, 即需支持
HTTP级代理 - 需要支持对MySQL的代理, 因为MySQL连接是基于TCP/IP的(或者unix, 共享内存, ssh通道等, 但是这些我们目前都用不了), 所以还需要支持
SOCKS5代理.
这里顺便说一下HTTP代理和SOCKS5代理的区别:
- HTTP代理处于OSI七层模型中的应用层, 它能够智能的缓存, 过滤, 拒绝请求. 但是只支持对HTTP请求以及基于HTTP协议的部分协议进行代理
- SOCKS5代理处于OSI七层模型中的会话层,它不关心传输的具体内容, 只负责数据的”搬运”. 当使用SOCKS5代理, 代理会与客户端建立TCP/IP连接, 然后与目标主机建立TCP/IP连接, 然后搬运这两个连接中的数据. 因为它所处的层级更低, 所以也就能够支持各种基于TCP/IP的协议(SSH, MySQL连接等)
在网上找了找, 发现了一个使用很简单的软件:gost, 它能够支持HTTP和SOCKS5代理, 只需要通过下面的命令:
gost -L="http://:10086" -L="socks5://:10010"完成到这一步之后, 我们只需要打开虚拟机, 运行一下上面的命令即可, 但是每次开机都需要手动运行, 也不是很优雅. 所以这个时候我找到了nssm. 它可以将任何exe软件的运行变成一个Windows Service从而实现开机自启.
使用也很简单:
- 在管理员权限的cmd/powershell中输入命令
nssm install <你的服务名称>. 接着会弹出一个可视化窗口 - 在可视化窗口中选中exe文件, 如果有参数, 则放在
arguments中. 对于我们使用的gost, 参数就是-L="http://:10086" -L="socks5://:10010" - 点击install即可完成安装
至此, 我们已经完成了95%的操作了, 接下来的就是一些配置操作:
给虚拟机加上一个Host-Only网卡, 用于宿主机和虚拟机通信(走代理)

固定虚拟机的Host-Only网卡的IP, 否则虚拟机的IP可能发生变动. 这样的话配置就得改

给APIfox配置HTTP代理

给Datagrip配置SOCKS5代理
这里为什么是Datagrip呢, 因为其他软件都无法直接配置SOCKS5代理, 就算可以也是通过SSH, 在SSH上配置, 而我们是无法使用SSH的. 就算是Datagrip, 也只能设置全局代理, 这意味着Datagrip配置代理之后就无法联网了, 需要提前把驱动下载下来.

总结
至此, 我们已经实现了内外网的同时访问, 每次只需要打开虚拟机即可, 不需要在虚拟机里面操作. 后续可能还会涉及到私有maven仓库的代理配置. 当实际处理的时候再进行记录与总结.