我目前正在使用 FreeBSD 11.2(可能会在一段时间内迁移到 12)。我需要一个小型的仅权威 DNS 服务器(无需查找或缓存,在 10 个域和 10 个查询/小时以下,几乎没有记录更改)。
我可能会选择, 其中的TinyDNS
一部分djbdns
,它以安全着称,而且看起来很小,可以满足我的需要。
安全的部分原因是它会暴露在互联网上,尽管在 IP/端口过滤器和非常低的速率、速率限制器(pf
用于此)之后。但出于这个原因,我确实想特别注意守护程序的设置方式,以避免明显的漏洞。我的意思是诸如所需的用户和组、启动/停止脚本、jail/chrooting 以及最小化/禁用/拒绝攻击者可能转向的主要非必要访问/功能等方面。
(我应该提一下,我可以在测试系统上“通常”安装 tinydns,并创建所需的.conf
文件,因此纯粹是如何以安全的方式运行它,这是缺失的)
我在设置软件以运行 chrooted/jailed 或查看 chrooted/jailed 包以获取适当的安全实践方面没有经验,这也是我第一次尝试做这样的事情,尽管我选择了特定的DNS 服务器包专门为其明显的设置简单性。
忽略该.conf
文件,“配方”会是什么样子,将 TinyDNS 设置为作为服务正确运行,并在理想情况下最小化对“其他对守护进程不是必需但对攻击者有帮助的东西”的访问?
这是相当长的,所以对于那些懒得读完的人来说,这是一个非常简短的版本:
我通常会将这个问题评为“过于宽泛”,并直接将人们推荐给FreeBSD 手册。但我自己发现那部分写得相当糟糕而且令人困惑。一切都在那里——但事情比看起来要容易得多!我只是希望他们更多地关注概念而不是列出命令。你可能会喜欢阅读监狱——高价值但糟糕的虚拟化
相反,我要做的是谦虚地概述我个人所做的事情以及我遇到的绊脚石。我的失败可能不是你的,但因为我曾经和你处于同样的境地,我希望我的旅程能有所帮助。你对 FreeBSD 的整体理解越好,越容易越狱。
什么是监狱?
许多描述掩盖了监狱的重要部分。它极大地有助于理解内核的作用。它“运行”代码并跟踪 PID(进程 ID)和 UID(用户 ID)。这是许多 Unix 用户的常识。FreeBSD 内核随后添加了 JID(监狱 ID)的概念。然后内核能够将进程划分为监狱。这实际上意味着 FreeBSD 内核能够“虚拟化”系统而无需任何开销。您仍然只有一个内核,但可以拥有多个系统。这是我理解这个概念的关键。
如果您运行“没有”监狱的香草盒。那么所有进程都属于 JID 0。当您开始使用监狱时,我们将其称为“监狱主机”。
考虑到这一点,我下一步是了解与 FreeBSD 实际工作方式的联系。如果您来自 Linux 背景,您可能知道 Linux “只是”内核。构成系统的原因是随发行版提供的用户空间(Ubuntu、Debian、Slackware 等)。FreeBSD 是内核和用户空间的组合。它是完整的操作系统(操作系统)。
所以第 12 章的一个非常粗略的总结。FreeBSD 引导过程是:
您可能知道 FreeBSD 是多么模块化,并且您可以用OpenRC之类的东西替换 rc 系统,但我们暂时忽略它以保持简单。
然后,当您启动(引导)一个 jail 时,内核会使用一个新的 JID(即 1)进行初始化。然后这里的所有东西都被限制在监狱 1 中。init 需要接触的东西必须在 chroot 文件系统中。如果你想让事情变得简单,那就是完整的用户空间。但是我们希望将监狱与主机系统分开,所以这是用户空间的完整副本!
这些事物如何相互关联的重要性不可低估。当您完全了解它时,您会注意到许多 FreeBSD 工具直接支持监狱。不仅仅是简单的事情,
ps -J
但是bsdinstall
,freebsd-update
和pkg
!如果维护 FreeBSD 系统是您的第二天性,那么监狱将是您的乐园!但对于我们大多数人来说,我们在通往涅槃的道路上处于中间位置,可能不得不与一些概念作斗争才能“正确”地完成它。
希尔
我是他的超级粉丝。它提供了一个清晰一致的观点,即应该放置物品的位置。不幸的是,权力永远不会决定监狱的默认位置是什么。当您将它与许多使用不同位置的不同教程结合起来并混合使用各种术语作为“基本安装”和“模板”时,事情会很快变得混乱!
手册没有讨论这个,只是参考
/here/is/the/jail
。在最后一个示例中,他们使用/home/j
and/home/j/mroot
。我更喜欢将用户目录和仅用户目录保留在/home
.j
在我的书中,简单地使用速记符号就像是一个很大的禁忌。我想说最常见和“正确”的位置是
/usr/local/jails
. 对于使用 ZFS 的人来说,一个强有力的竞争者是/jails
在这个位置,我会为我的监狱放置 chroot。我是这样讲的。从此以后的监狱将在这里找到。
当我开始时,我发现这非常令人困惑。给我自由将它放在任何地方让我更加不安全,因为我不明白后果。
为了增加这种混乱,许多教程使用“basejail”、“skeleton directory”、“templates”。这增加了监狱的真正含义,并将其与许多管理混为一谈。
文件系统
我们并不真正关心我们使用的是什么文件系统。它可以是 UFS 或 ZFS。为了监狱,我们只需要一个目录来存放我们的 chroot。
使用 UFS 时要注意的重要一点是如何排列切片。初学者往往没有考虑这么多。哪个切片有足够的空间来容纳 chroot。这就是为什么我特别不喜欢
/home
为此目的使用。也许您为此目的创建了一个切片,或者您只是在某个地方创建了一个目录,然后再确定您是否有足够的空间。如果您使用的是 ZFS,问题实际上是相同的。由于 ZFS 的结构方式,您可能会争辩说创建一个新数据集比仅仅做
mkdir
. 但对于初学者来说,你不应该担心。使用 ZFS 执行“mkdir”对您来说更好。这使事情变得更简单,您可以在没有 ZFS 的情况下继续前进。下一个问题是许多教程也使用“basejail”,这是一个完整的香草系统,可以复制以创建新的监狱。然后,一些教程会告诉您进行 ZFS 克隆而不是复制。很长一段时间,您将更新 basejail 并自然地对其进行快照。但是随后您注意到您无法删除任何具有它们克隆的快照。所以在实际使用中我更喜欢使用zfs send/receive。
在我看来,教程应该只将 ZFS 作为附录。ZFS 本身就是一个巨大的话题,应该这样对待。当您对 jails 和 ZFS 都感到满意时,您就可以心满意足地结合起来并从中获益。如果不是这样,您最终会建造一座非常脆弱的塔,而在它们破裂时没有任何修复能力。
胖/厚vs瘦
FreeBSD 手册谈到了“完整的”监狱和“服务”的监狱。大多数其他地方使用术语厚(胖/满)和薄监狱。厚监狱和瘦监狱都是“完整的”虚拟化 FreeBSD 系统,FreeBSD 手册将其称为“完整的”监狱。然而,“服务”监狱更加难以捉摸
厚监狱是完整操作系统的副本。但那是多少脂肪?带有 base/lib32/ports 的 FreeBSD 11.2 的重量为 1.4G,但对于监狱,“base”本身可能会使您保持在相对苗条的 512M(与 Windows 10 的 C:\Windows 的 20G 相比)。
一个瘦监狱是一个技巧,可以最大限度地减少“完整”监狱的磁盘使用。通过使用nullfs(一个回送文件系统子树)来挂载一个只读文件系统和几个放置良好的符号链接来启用读/写部分,您可以减少磁盘使用量。不幸的是,我手头没有任何数字。当您拥有磁盘结构后,您只需在启动 jail 时添加
mount.fstab
到您的文件系统以挂载文件系统。jail.conf
我从FreeBSD Jails得到了如何做到这一点的想法。这教会了我如何在没有任何 3rd 方实用程序的情况下处理监狱,并最终让这些作品适合我。尽管有标题 - 这实际上是简单的方法。然而,他们确实弄错了一件事。您不应该执行 zfs 克隆,而应该按照Unadulterated Jails, the Simple Way中的描述执行 zfs 发送/接收。两者都可能从略过时的带有 nullfs 的 Multiple FreeBSD Jails中找到了灵感。另一个有价值的来源是FreeBSD Thin Jails。最后一个更新的资源也涵盖了 VNET(我们将回到那个!)是 How to configure a FreeBSD Jail with vnet and ZFS
以上通常被称为瘦监狱,但可以通过其他方式完成。条条大路通罗马,您自己决定如何在当地实施。
所有这些都将我们引向难以捉摸的“服务”监狱。在最锁定的场景中只运行一项特定服务的监狱。只是实际的应用程序,只有一个薄层来支持它。它可以完成,但我还没有看到很多工作。
典型的
jail.conf
将包含:这是确保 rc 系统在启动/停止时运行监狱的原因。如果你有一个非常简单的可执行文件,你可以简单地指向它。所以问题是:我的服务需要访问多少操作系统?需要哪些共享库,您是否运行脚本?
我知道没有任何工作为您完成了这项工作。所以你从一个完整的监狱开始,然后删除你的特定服务不需要的东西。许多命令行实用程序(例如
top
和 )可以安全删除ps
,tail
因为它们通常不被守护程序使用。但是,如果您自己在监狱中进行调试,您可能会错过它们。如果你直接启动一个守护进程,exec.start
你不需要rc.subr
和朋友。如果你走这条路并开始疯狂杀戮以确定在服务保持功能的同时可以从操作系统中删除多少(以减少攻击面),那么你应该知道nanobsd。这可以帮助您根据需要定制安装。
所以 - 绝对可行。但我知道没有公共工作。大多数人都会选择厚监狱或薄监狱,然后在那里运行他们指定的服务。
依赖地狱
在做瘦监狱时,你需要非常小心地做所有正确的事情,否则事情会破裂。当您更新系统时,您需要记住更新所有不同的部分。您开始的基地监狱或来源。模板和实际的监狱。这是很多移动的轮子,使管理更加困难。可以做到,但您应该权衡努力与奖励。磁盘空间非常便宜——因此您需要相当多的服务才能使其值得付出努力。
然后,我会建议使用带有完整操作系统的简单胖监狱。
如果您对 ZFS 非常满意,那么一定要疯狂。但如果不是,那么我强烈建议将 chroot 放在一个简单的目录中。当你觉得在监狱里工作很舒服时,你就可以开始添加奶油了。
关键是将监狱视为一个独立的系统。如果你今天正确地维护你的系统,你应该已经有使用的习惯,
freebsd-update fetch install
你就会知道它会更新内核和用户空间。在将监狱添加到混合中时,您只需要记住也更新它们:
如果您正在进行升级 - 还要记住监狱:
就像您保持包裹新鲜一样
嗨,老兄!我只是想监禁一项服务!
好的!有了所有的警告购买者,让我们在一个完全普通的系统上以简单的方式完成这项工作。TinyDNS 是一个不好的例子,所以让我们安装nginx
/etc/jail.conf
lib32
/ports
)nginx
包添加到监狱。完毕!
1 和 2 仅用于为监狱做准备。每个新监狱 3 - 6 个。每项服务 7 - 9 个。
这就是我声称的做监狱和简单管理的“正确”方式。有很多变化 - 最后一行可以替换为
service jail restart testjail
. 此时,我可以在我的入狱 nginx 实例上浏览网页。一些 FreeBSD 的默认设置不适合监狱。所以也考虑设置这些:
删除监狱
要删除监狱:
以上是为了表明使用手头的工具管理监狱并不难,而第三部分不需要监狱管理工具。
嗨,老兄!我只是想监禁 TinyDNS!
您写道您可以“通常”安装 tinydns - 因此我将把它留给您。对于可能正在关注的其他人,他们可能会猜测它应该很简单:
但是,无论是谁创建了这个包,都不足以为 tinydns 中的
/usr/local/etc/rc.d
. 然后,您需要弄清楚如何将其作为守护程序运行。您可以选择使用替代服务管理,例如主管或简单的 hack,将其添加到/etc/rc.local。或者为布朗尼点创建一个 rc 脚本并将其回馈给我们所有人享受!这将我们引向您真正需要知道的仅有的两个特定的监狱命令:列出正在运行的监狱的jls和允许您在监狱内执行内容的jexec 。
要以 root 身份获取命令行,我们只需执行 root shell(记住那是 tcsh!)
在那个 shell 中工作时,一切都在你的 jail/chroot 中。
他们不告诉你什么!
到目前为止,我还没有偏离大多数教程会告诉你的内容。在文件系统上浪费了大量时间之后,他们跳过了令人兴奋的部分。今天,没有网络访问的计算机没有太多乐趣。在上面的示例中,我们与主机共享网络堆栈。这意味着您不能在使用与监狱相同的端口的监狱主机上运行任何东西。在我的示例中,这是网络服务器的端口 80。
另一方面,现在很容易设置防火墙。您只需将所有端口视为本地端口。如果您使用的是 IPv6,事情就轻而易举了。但是我们中的大多数(全部?)仍然需要与 IPv4 斗争。IPv4 很简单,但您可能没有所需的地址,然后我们需要求助于某种 NAT。
如果您想真正了解网络,我们有虚拟网络接口VNET。它多年来已经成熟,但要使用它,您需要编译一个支持 VIMAGE 的内核。这在FreeBSD 12.0及更高版本的通用内核中启用。
使用 VNET 时,您有一个很好的虚拟接口,您可以在监狱内运行防火墙。
我目前不使用 VNET 作为监狱主机上的统一防火墙,这对我和我想要的来说已经足够了。有了这个,我可以控制进出监狱的交通。这使得从监狱中破解东西变得更加困难。
在监狱主机上,我经常允许一些出站流量(http/ftp/nameresolution)。但是我的监狱中的所有交通我都会明确指定哪些端口可以双向以及在监狱之间进行。
诀窍是将流量移动到另一个接口。本地环回接口
lo0
是一个很好的选择。但为了更好地分离规则,最好将其克隆为新的接口名称lo1
。您可以设置它并在监狱主机中使用ifconfig
. 但是没有必要,因为 jail 子系统会自动为您处理所有这些。为此,我们
/etc/jail.conf
现在看起来像这样:请注意如何
ip4/6 = inherit;
更改为interface="lo1"
. 另请注意mount.fstab
- 这就是我添加 nullfs 挂载的方式,但我现在不会进一步讨论。然后我添加了要用于测试监狱的内部 IP。然后我们通过添加
lo1
来克隆/etc/rc.conf
:您需要为此重新启动。如果您想在不重新启动的情况下立即试用,您需要自己创建接口:
cloned_interfaces="lo1"
这与设置中的效果相同/etc/rc.conf
。您不需要为 IP 地址创建别名,因为这会在监狱启动时自动处理。然而,这很无聊,因为交通无处可去。
为了让流量继续,我们需要设置防火墙并进行一些 NAT。我选择的毒药是pf。你有你的规则集
/etc/pf.conf
要从外部 NAT 到 http 的监狱 IP,请执行以下操作:
如果无法连接到自己,许多服务不喜欢启动。因此,我也为此添加了一条规则。
仅当您希望外部人员连接时才需要 NAT 规则。当您开始拥有多个监狱时,您通常只希望一个监狱能够连接到另一个监狱。
通过这些简单的防火墙设置,您可以在监狱和外部之间进行非常好的网络隔离。
概括
根据我自己的经验,我建议通过以下途径来了解如何使用监狱:
That is my recipe. Probably not quite what you hoped for :-)
If you do not want to handle the gritty bits with the supplied tools then have a look at some of the 3rd party tools:
Bastille
ezjail
iocage
From all this you can see that your question was rather broad and depends heavily on your preferred setup. I believe I have shown a receipe for a well behaved package such as
nginx
but maybe you need to ask some other questions:But then I would leave the jail parts out of it.