36

使用Linux容器迅速搭建渗透测试环境(下篇)

 5 years ago
source link: https://www.linuxprobe.com/linux-test-environment%e2%80%8e.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在本文的上篇中,我们为读者介绍了如何配制宿主机和网络,在本文篇中,我们将为读者介绍容器的创建和启动等内容。

创建我们的第一个容器

lxc发行版附带了许多工具来帮助用户创建和管理容器。第一个是lxc-create,该工具可以通过模板为各种Linux平台创建最小化的安装。您可以通过查看/usr/share/lxc/templates目录来查看当前可用的模板。在我的Slackware 14.2宿主机上,我的模板目录如下所示。


我可以选择部署其中的任何一种平台。关于如何在Linux上创建一个带有iptables的家庭路由器,网上可用的教程数不胜数,所以这里就不赘述了,同时,我觉得很多读者可能早就有这方面的经验了。读者可以在计算机上部署dhcpd和bind或dnsmasq,同时为测试环境部署DNS和DHCP。接下来要介绍的是如何设置容器——我会继续使用Slackware,但是,读者可以使用自己喜好的系统。
lxc-create -n router -t slackware -B Btrfs
运行上述命令,并稍等片刻以便从Web上获取所需文件,最终会得到一个新的容器,名为“router”。就像网络名称一样,我总是喜欢保持简洁明了,所以这里也是利用角色为其命名。
当lxc-create生成目录后,将得到/var/lib/lxc/router,其中存放与新容器关联的所有文件。值得注意的是,它将包含两部分内容:定义容器的配置文件,以及保存容器文件系统的rootfs控制器(实际上是Btrfs子卷,稍后将详细介绍)。
配置的具体内容如下所示。其中用红色标识的内容,是我修改过的;对于这些内容,将在后面分别加以介绍。

# Template used to create this container: /usr/share/lxc/templates/lxc-slackware
# Parameters passed to the template:
# Template script checksum (SHA-1): 1d5a84ae1fd3725be88e7d347128402c61000d19
# For additional config options, please look at lxc.container.conf(5)
# Uncomment the following line to support nesting containers:
#lxc.include = /usr/share/lxc/config/nesting.conf
# (Be aware this has security implications)
lxc.start.auto = 1
#Probably change network.0 to dhcp inside the container at some point
lxc.network.0.type = phys
lxc.network.0.link = eth1
lxc.network.0.name = wan
lxc.network.0.flags = up
lxc.network.0.ipv4 = 192.168.1.20/24
lxc.network.0.ipv4.gateway = 192.168.1.1
lxc.network.0.hwaddr=DE:AD:BE:EF:FF:FF
lxc.network.1.type = veth
lxc.network.1.link = lab
lxc.network.1.name = lab0
lxc.network.1.flags = up
lxc.network.1.ipv4 = 192.168.16.254/24
lxc.network.1.hwaddr=DE:AD:BE:EF:00:FF
lxc.rootfs = /var/lib/lxc/router/rootfs
lxc.rootfs.backend = Btrfs
lxc.utsname = router
lxc.mount = /var/lib/lxc/router/fstab
#lxc.console = none
lxc.tty = 4
lxc.pts = 1024
lxc.rootfs = /var/lib/lxc/router/rootfs
lxc.cgroup.devices.deny = a
# /dev/null and zero
lxc.cgroup.devices.allow = c 1:3 rwm
lxc.cgroup.devices.allow = c 1:5 rwm
# consoles
lxc.cgroup.devices.allow = c 5:1 rwm
lxc.cgroup.devices.allow = c 5:0 rwm
lxc.cgroup.devices.allow = c 4:0 rwm
lxc.cgroup.devices.allow = c 4:1 rwm
# /dev/{,u}random
lxc.cgroup.devices.allow = c 1:9 rwm
lxc.cgroup.devices.allow = c 1:8 rwm
lxc.cgroup.devices.allow = c 136:* rwm
lxc.cgroup.devices.allow = c 5:2 rwm
# rtc
lxc.cgroup.devices.allow = c 254:0 rwm
# we don’t trust even the root user in the container, better safe than sorry.
# comment out only if you know what you’re doing.
lxc.cap.drop = sys_module mknod mac_override mac_admin sys_time setfcap setpcap
# you can try also this alternative to the line above, whatever suits you better.
# lxc.cap.drop=sys_admin

首先,我将lxc.start.auto改为值1。大多数安装了LXC的系统都提供了启动脚本,该脚本会寻找将该值等于1的容器,并在系统引导时自动启动它们。请记住,要使其正常工作,需要预先提供所需的网桥和文件系统。
下一个修改之处是lxc.network.0.type的值——我已将其设置为“phys”,它代表物理适配器。lxc.network.0.link的值为eth1——这是我想要传递给容器的宿主机的第二个NIC。请注意,它将从正在运行容器的宿主机的ifconfig输出中消失。如果我们使用上行链路桥接器,那么类型将是“veth”,链路将是“uplnk”,以将其连接到宿主机上的桥接器上。最后,该接口在容器内部的名称为“wan”。此外,我还添加了网关和hwaddr条目,这些无需多言。就我而言,这个容器上行连接到我的家用路由器。当容器启动时,内核将这些值作为最初值分配给接口。根据安装的操作系统的不同,其启动脚本之后可能会重新配置该接口,也可能不会这样做。
为了向容器添加更多接口,只需复制lxc.network.[N]节,并根据需要增加索引[N]的值即可。但是,只能包含一个gateway语句。该路由器将提供两个适配器。在我的实际实验室中,路由器有10个接口。为此,只需在主机上创建网桥,并为每个网桥添加相应的lxc.network节就行了。
另外需要注意的是,hwaddr语句是可选的,但是,没有为其赋值的话,那么容器启动时将选择一个随机值。虽然这确实有助于防止MAC地址冲突,但我在测试过程中发现,这会导致容器频繁的重启。因为它们在每次启动时都会创建一个唯一的MAC,所以,很快就耗尽了DHCP地址池。所以,现在为会为容器指定MAC。但是,当IP地址总是在变化时,还是会令人非常抓狂。
最后需要注意的是:网络的lxc.network.[N].name必须与链接名称(网桥)不同,但可以跨容器进行复制。例如,您可以创建一个名为lan的网桥和一个容器,并且它的网络也名为lan,如果在多个容器中的话,这时可以将其命名为lan0。
最后一个修改之处是lxc.mount语句,它指向容器目录中名为fstab的文件。LXC能够理解普通的/etc/fstab格式的文件。所有路径都应该是相对于宿主机的相对路径。容器启动时,它将挂载其中规定的所有文件系统。搞定路由器容器后,我将在/var/lib/lxc/router/fstab创建fstab文件。

lxcpts /var/lib/lxc/router/rootfs/dev/pts devpts defaults,newinstance 0 0
none /var/lib/lxc/router/rootfs/proc proc defaults 0 0
none /var/lib/lxc/router/rootfs/sys sysfs defaults 0 0
none /dev/shm tmpfs defaults 0 0
none /run tmpfs defaults,mode=0755 0 0
/home /var/lib/lxc/router/home none bind,ro 0 0
/etc/hosts /var/lib/lxc/router/rootfs/etc/hosts none bind,ro 0 0
/etc/networks /var/lib/lxc/router/rootfs/etc/networks none bind,ro 0 0
/etc/passwd /var/lib/lxc/router/rootfs/etc/passwd none bind,ro 0 0
/etc/group /var/lib/lxc/router/rootfs/etc/group none bind,ro 0 0
/etc/shadow /var/lib/lxc/router/rootfs/etc/shadow none bind,ro 0 0
/etc/passwd /var/lib/lxc/router/rootfs/etc/passwd none bind,ro 0 0
/etc/shadow- /var/lib/lxc/router/rootfs/etc/shadow- none bind,ro 0 0
/etc/sudoers /var/lib/lxc/router/rootfs/etc/sudoers none bind,ro 0 0
/etc/sudoers.d /var/lib/lxc/router/rootfs/etc/sudoers.d none bind,ro 0 0
/etc/profile /var/lib/lxc/router/rootfs/etc/profile none bind,ro 0 0
/etc/profile.d /var/lib/lxc/router/rootfs/etc/profile.d none bind,ro 0 0
/etc/slackpkg/mirrors /var/lib/lxc/router/rootfs/etc/slackpkg/mirrors none bind,ro 0 0
/etc/resolv.conf /var/lib/lxc/router/rootfs/etc/resolv.conf none bind,ro 0 0

当然,我们也可以将普通的块设备安装到容器中,尽管这里并没有这么做。我已经使用其特殊名称挂载了proc和sysfs文件,以防容器中的启动脚本没有照顾到它们。它们将收到一个容器名称空间范围内的特殊视图。
在这里,我想为大家介绍一下绑定装载。利用它,我们可以将宿主机的文件系统挂载到容器名称空间内的某个位置。这意味着,可以在宿主机和任意数量的容器间共享/home,而无需设置NFS服务器,只需将相同的文件夹绑定到多个容器即可。当然,这必须作为容器启动的一部分来进行,但是如果在容器运行后这样做,外部文件系统在容器的名称空间中不可见。对于目录的绑定,想必大家已经都很熟悉了,实际上,我们也可以对单个文件执行该操作。如果缺少任何挂载点,容器将无法启动,这个问题将在后文加以介绍。
我认为路由器是可信基础架构的一部分,因此,我选择与宿主机共享许多关键的身份验证文件,尽管是以只读方式。通过绑定passwd、group、shadow和其他文件,我可以使用普通的用户名和密码进行登录。为方便起见,我还可以共享一些配置文件。显然,您可能不想在测试环境中对不受信任的系统执行这些操作,或者您可能需要指定自己的共享的文件。

启动容器

现在我们的路由器已配置完毕,下面开始启动它。从命令行中以手动方式启动容器并不难,具体命令如下所示。

lxc-start -n router:

好吧,但是它能正常工作吗?命令lxc-info -n router会告诉我们答案。如果容器正在运行,会得到这样的结果

lxc-info命令的运行结果
如果启动失败,可以尝试使用以下命令重新启动:

lxc-start -n router -F

执行该命令后,容器将在前台启动,这样就可以看到所有错误信息了。此外,您还可以使用命令lxc-top查看正在运行的容器的相关信息和统计数据。
接下来的步骤,是配置路由器,让它完成路由和防火墙等任务。为了访问它,可以使用lxc-console -n router连接到虚拟控制台。退出时,可以使用<[ctrl]+[a] q>。进入控制台后,可以使用installpkg、apt、yum等添加所需的软件包。然后,就可以使用ssh或xnest来管理它了。

为什么要使用Btrfs?

现在,是Btrfs的表演时间。假设需要将10个Ubuntu工作站加入我的测试域,为此,我将部署一个Ubuntu容器作为模板。

lxc-create -t ubuntu -n TubuntuWS -B Btrfs

然后,还需要进行进行配置,就像前面的路由器配置一样。接下来,用单个veth接口设为lxc.network.0,并将lab设为链接。在这种情况下,就用不着使用特殊fstab了。同时,也不用设置lxc.start.auto。然后,通过lxc-start -n TubuntuWS命令启动容器,并利用lxc-console进行连接,这样就可以构建机器了。
如果一切都符合要求,就可以将其关闭了。为此,可以从宿主机的容器内部执行lxc-stop -n TubuntuWS命令。
现在,我可以使用BTRFS轻松创建大量的低开销的副本。首先,在/var/lib/lxc/下为其他容器创建目录。
然后,克隆模板容器,即TubuntuWS。

cat /var/lib/lxc/TubuntuWS/config | sed ‘s/TubuntuWS/ubuntuWS01/g’ > /var/lib/lxc/ubuntuWS01/config
Btrfs subvolume snapshot /var/lib/lxc/TubuntuWS/rootfs /var/lib/lxc/ubuntuWS01/rootfs

好了,一个克隆完成了!当然,我们可能需要更改一些网络设置。之后,可以使用lxc-create启动它。由于Btrfs已经创建了模板rootfs的写时复制快照,所以至少在进行大量更新之前,几乎不会占用任何磁盘空间。
Btrfs也可以完成其他有用的事情。比如,可以根据需要制作任意数量的卷,创建快照的快照,也可以删除原始源卷。
还记得路由器吗?它所有的配置都是按照这里来的,所以请将其rootfs的快照创建为rootfs.bak。您甚至可以使用它来完成卷的增量式流备份。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK