最近遇上了这么一个需求,我找到了某个非常厉害的软件xxxSoftware,声称可以提供某种神秘服务。 经过测试,这个软件的确可以像它宣传的那样提供该种神秘服务, 可是在网络上搜索到的各种版本是有可能带病毒的, 那么既能使用该软件提供的服务,又要保证系统的安全,就成为了一个问题。
对于运行不放心的软件,一个办法是将它放进沙盒里面,与系统隔离,确保软件不能危害到系统。 在各种隔离方式中,最彻底的隔离方案显然是使用虚拟机。
1. virtualbox简介
virtualbox是一款开源,跨平台的虚拟机软件。 它的主要功能就是虚拟出一台计算机,并能够在其中安装各种主流的操作系统。 虚拟机内的操作系统称为guest os, 运行虚拟机软件的操作系统称为host os。
guest os中的各种硬件全部都是virtulbox虚拟出来的,包括CPU,内存,硬盘,网卡等等。 由于virtualbox是在硬件层次所做的虚拟,因此它的隔离效果是非常好的, guest os内的一切活动都被隔离在这个虚拟的环境之内,无法危害到host os。
那么,我们就可以利用virtualbox,把xxxSoftware安装到虚拟机内,将这个不安全的软件与系统隔离。
2. 创建虚拟机
由于xxxSoftware是跨平台软件,并且是一种通过监听端口对外提供服务的server,因此guest os安装linux最合适。 这是因为,对linux而言图形界面只是一个可选项,无图形界面的linux的系统占用极低,大大节约系统资源。
首先,利用virtualbox自带的GUI创建一个虚拟机,像往常一样,设置合适的内存大小,虚拟硬盘大小等配置。 这里要重点说下虚拟网卡的模式。
virtualbox对虚拟网卡的设置有这么几种模式:
- NAT网络地址转换。guest os是通过NAT网络地址映射来访问互联网的,就像通过家里wifi路由器上网的手机一样。
- 桥接网卡。guest os被接入到host os所在的网络中,与host os在同一网络内。
- 内部网络。虚拟机之间组成的一个内部网络。
- 仅主机网络(Host-Only)。host os会多一张虚拟网卡,guest os和host os共同组建了一个网络。
由于我们需要guest os能够联网,并且尽量减少guest os和host os之间的通信,因此选择第一种模式,NAT网络地址转换是最合适的。
创建好虚拟机后,启动它并安装无图形界面的linux,我选择的是最熟悉的debian。
3. 配置ssh访问
安装好系统后,启动虚拟机,首先我们要安装的是一些必备的工具,假设你用于操作的普通账户名是username:
|
|
我们安装了sudo命令,并且将username用户加入了sudo组。
由于这个虚拟机是要放在后台运行的,不带任何的图形窗口,因此我们需要通过ssh操作它,安装ssh服务器;
|
|
默认ssh服务器应该就是开启在 0.0.0.0:22 端口的,可以通过查看 /etc/ssh/sshd_config
确认,有如下两行:
|
|
4. 配置端口映射
但是现在,我们还无法通过主机访问虚拟机的ssh服务器。 这是因为,虚拟机是通过NAT网络地址映射来和主机通信的,为了搞清楚这个问题,先来复习下NAT地址映射的原理。
NAT地址映射中,首先有一个利用保留IP地址组建的内部网络,在virtulbox中使用的是10.开头的A类ip地址。 然后,其中有一台主机,NAT网关,拥有外部网络的ip地址,用以与外部网络通信。
某台内部主机想访问外网,来自 10.0.0.3:5555
的传输层报文会到达NAT网关。 网关会选择外网ip的一个未使用的端口,比如 12345
,与之对应。这样:
- 内部主机的报文到达NAT网关时,网关修改报文内对应字段并正确的发送给外部主机
- 当有传输层报文进入时,NAT网关根据端口信息,修改报文内对应字段并能够将报文正确转发给内部主机
然而这种映射关系只是在内部主机主动访问外部主机时才会建立,外部主机是无法访问内部主机的。
解决这个问题的方法是, 端口映射 。 通过事先配置,告诉NAT网关,将外网ip中 12345
固定的映射到 10.0.0.3:5555
上去。
virutualbox的图形界面就能配置端口转发,首先关闭虚拟机,进入设置 => 网络 => 选择一个网卡如网卡1 => 高级配置 => 端口转发。如:
- 协议一列填入使用该端口的协议,tcp或者udp。因为tcp的5555端口和udp的5555端口是两个不同的端口,并不冲突,需要手动指定。
- 主机ip填入127.0.0.1,主机端口填入2222
- 子系统ip不填,virtualbox会智能识别,子系统端口填入22.
这样,当在host os内访问 127.0.0.1:2222
,请求会被转发到guest os的 22
端口。
再次打开虚拟机,启动后,在host os中运行(假设虚拟机中的普通用户是username):
|
|
输入密码,成功登录到了guest os中!现在不仅达到了目标,还顺便练习了下通过ssh操作远程主机。
登录后,在虚拟机中安装xxxSoftware,同样通过配置端口映射的方式,使得host os能够访问到虚拟机内的该服务。
5. 脚本自动化
由于这个虚拟机仅仅是用来提供服务,并不需要图形界面。 而每次启动虚拟机,都会打开一个大大的图形窗口,不仅占用系统资源,还碍事。
假设这个虚拟机名称为xxxSoftware-server,那么以下命令:
|
|
将会启动虚拟机,并且不会打开图形窗口。
而当我们不需要xxxSoftware提供的服务的时候,可以将它关闭。但是一个更好的办法是使用休眠, virtualbox会把虚拟机的内存状态写入磁盘并关机。 下次启动时,能直接从磁盘中恢复内存的状态,非常方便,有了它,guest os连配置自动启动都省了。
以下命令将打开的虚拟机休眠:
|
|
这样,我们就可以制作一个简单的脚本,一键开启和关闭虚拟机:
|
|
6. 结尾
虚拟化是一种很有趣的技术,不仅可以拿来隔离危险软件,还可以做更多的事情。
比如,把一个配置极其繁琐复杂的服务放到虚拟机(或其它轻量的容器如docker)上,部署起来极其方便,把虚拟机镜像拷贝过去就行了。 再比如,使用linux的用户可以安装安卓虚拟机,不仅能享受到国内各种app提供的服务,备份起来也极其方便,只需要备份虚拟机镜像即可。
linux的一个优点是对脚本编程的良好支持。通过编写脚本,把各种无聊机械的操作放到脚本里,我只需要一键就能完成这些操作,十分方便。