安全漏洞和利用这些漏洞的歹徒无处不在。 在一个典型的网络上运行的软件中包含数百万行代码,从统计上讲,不可能百分之百地免受所有可能的威胁。 然而,一个好的网络管理员会关注当前的网络安全趋势,并采取一切可能的预防措施来帮助确保网络尽可能地安全。 在这一章中,我们将看看可以做些什么来提高您的网络的安全性。
在本章中,我们将介绍:
- 限制攻击面
- 确保 SSH
- 配置 iptables 防火墙
- 使用 fail2ban 保护系统服务
- 理解 SELinux
- 配置 Apache 使用 SSL
- 部署安全更新
最重要的网络安全规则是限制攻击范围。 简而言之,这意味着你安装的软件和/或你运行的服务越少,它被用来对付你的可能性就越小。 如果这还不够糟糕,在某些情况下,服务器软件中一个未修补的漏洞可能会让歹徒利用您的服务器攻击其他人。 通过限制系统中使用的包的数量,可以降低发生不良事件的可能性。
这听起来很简单,而且确实很简单,但是要记住,这不仅仅是只安装您需要的东西的问题。 许多 Linux 发行版附带了您可能永远都不需要使用的软件。 这不仅适用于服务器。 甚至您的终端用户工作站也可能有一些不必要的服务正在运行,这些服务将成为攻击者使用的宝库。 一个常见的例子是在系统上运行一个邮件传输代理(MTA)。 令人惊讶的是,许多 Linux 发行版都默认使用运行 MTA。 除非您特别需要 MTA(对于示例,您已经安装了需要向管理员发送电子邮件消息的脚本),否则您应该从系统中删除这些包。
当在任何网络上推出 Linux 时,您应该做的第一件事是找出安装了什么和正在运行什么,然后决定要关闭什么和/或卸载什么。 这就是所谓的限制你的攻击面。 的确,Linux 是最安全的系统之一,但如果您不关注正在运行的系统并侦听网络上的连接,那么什么也帮不了您。 在本节的剩余部分中,我将介绍几种可以限制攻击面的方法。
首先,让我们打印出系统上安装的所有软件包的列表。 这将允许我们看到安装了什么,然后我们可以删除任何突出的,我们确定我们不需要。 这个列表可能很大,因为它包含了所有东西; 我指的是所有东西——甚至是允许我们的系统运行的库和各种包。 您肯定不会理解它们每个包的用途,但是随着您对 Linux 了解的更多,您将对它们有更多的了解,并知道需要删除哪些包。 例如,我知道从所有安装中删除exim
或postfix
包,因为我个人在任何地方都不需要它们。 由于您无法理解系统上安装的所有软件包的目的,所以我建议您快速查看并删除那些您确信不需要的软件包。 要打印已安装包的列表,运行以下命令之一:
对于基于 debian 的系统,执行以下命令:
# dpkg --get-selections > installed_packages.txt
对于 CentOS 系统,执行如下命令:
# rpm -qa > installed_packages.txt
在任何一种情况下,您都将在当前工作目录中得到一个名为installed_packages.txt
的文本文件。 这个文本文件将包含系统上安装的所有包的列表。 随时检查它,看看是否有什么突出的东西,你可以删除。 此外,这个文件还可以作为方便的备份。 如果您需要关闭一个服务器并设置一个具有类似目的的新服务器,您可以将一个服务器上的包与另一个服务器上的包进行比较,以确保安装了正确的包。
另一个发现系统上正在运行的东西的技巧是使用netstat
命令。 虽然我们将在第 10 章,故障诊断网络问题中进一步讨论这个命令,让我们现在来尝试一下:
netstat -tulpn
您应该看到在本地计算机上运行的服务列表,这些服务实际上正在监听网络连接。 这些应该给予主要的注意,因为任何侦听外部连接的东西都可能是进入您的系统的切入点。 如果您在这里看到一些正在侦听连接的东西,而您不需要它侦听连接,则删除该包。 您总是可以禁用一个服务,但是删除底层包更好,因为它们不会意外启动。 如果您发现确实需要这些包,可以随时重新安装它们。
netstat 命令,列出正在运行和侦听的服务
在我的情况下,我可以看到我有同步和 Chrome 正在监听外部连接。 这是预期。 但在生产环境中,比如服务器,需要注意 Apache web 服务器(如果服务器不是 web 服务器,这将是一个问题)、后缀或任何不应该安装的文件传输实用程序。
另一个有用的工具是sheldsup,它是 GRC 在互联网上提供的服务。 无论如何,这不是一个特定于 Linux 的工具,但如果您在路由器上使用 Linux,并希望确保将其配置为尽可能隐蔽的,这个工具可以用于测试。 您可以在以下网址访问此工具:
请记住,sheldsup 是一个在线工具,不受作者或出版商的控制或管理。 因此,它可能会在任何时候改变。 话虽如此,这个网站在相当长的一段时间内没有改变,它是一个非常有用的工具。
要使用它,请单击Proceed,然后单击All Service Ports。 该服务通过检查哪些端口响应外部请求来工作。 如果一个端口是打开的,它将显示红色,您应该能够单击它以找到关于该端口通常用于什么的更多信息。 这个将为您提供关于禁用哪些内容的线索。 如果服务不包含关于特定端口的信息,只需在谷歌上搜索以寻找线索。
使用 ShieldsUP ! 查看哪些端口响应外部请求
最后,systemctl
命令还可以用来查看您的机器上当前安装了哪些服务:
systemctl list-units -t service
使用前面的命令将打印到终端的列表,您将能够看到当前安装的单元文件及其状态。
这基本上总结了如何询问您的系统,以找出什么正在运行。 在了解服务的典型名称时,您可能需要进行一些谷歌搜索,以便了解每个服务的用途,但随着时间的推移,它会变得越来越容易。 如果你完全不确定哪些功能可以禁用,那么在你真正调整你的运行服务之前,先做一下研究。 在最坏的情况下,如果您禁用了一个必要的服务,您的服务器可能不会启动下一次。 与往常一样,在更改系统服务之前,确保有良好的备份。
OpenSSH 是一个很好的工具; 它是 Linux 管理员最好的朋友。 它节省了您必须走进服务器室并连接显示器和键盘以便在您的网络上执行工作的麻烦。 使用连接到同一网络的任何计算机,你几乎可以做任何你想做的事情,就像你正站在机器前面一样。 问题是,不安全的 SSH 实现给了不法分子同样的特权。 在您的网络上运行的所有东西中,SSH 肯定是您需要重点关注的一个。
对于 SSH,第一个也是最常见的安全性调整是只使用协议的 Version 2。 要确定您的 Linux 安装使用的是哪个版本,grep
的/etc/ssh/sshd_config
文件:
cat /etc/ssh/sshd_config |grep Protocol
如果答案是 1,您应该编辑该文件并将读取协议 1的行更改为协议 2,并重新启动 SSH。 这一点之所以重要,是因为协议 1 的安全性远远低于协议 2。 幸运的是,SSH Version 7 及以后版本现在默认为协议 2,所以这并不像以前那样常见。 但在撰写本文时,Version 7 刚刚发布,还没有进入许多发行版。 希望在您阅读本文时,您的发行版已经升级到 Version 7 了。 但如果不是,那么确保所有服务器只使用 SSH 的协议 2 是很重要的。 您可以通过更改sshd_conf
文件中的相关行,然后重新启动 SSH 服务来实现这一点。
另一个值得对 SSH 进行的更改是更改它侦听的端口。 缺省情况下,SSH 在端口 22上侦听。 你可以用下面的命令来确认:
cat /etc/ssh/sshd_config |grep Port
除非你改了,否则答案是 22。 因为 22 是 SSH 的默认端口,所以每个人(包括坏人)都希望它是这个端口。 在/etc/ssh/sshd_config
文件中,将有一个靠近顶部的端口选项。 如果你把它换成别的东西,它对外人来说就不那么明显了。 然而,我不想让你在这里产生一种错误的安全感。 更改 SSH 的端口并不是防止通过 SSH 入侵的神奇屏障。 在有针对性的攻击中,歹徒会扫描服务器上的每个端口,所以如果他们确定了,他们会找出您将其更改为哪个端口。 我之所以推荐这个改变是因为它是一个非常容易的改变。 只需几秒钟就可以更改您的 SSH 端口,并且您可以做任何使您的网络对外部人员不那么明显的更改都是值得欢迎的。 只有当您的网络用户希望 SSH 端口位于端口 22 时,更改 SSH 端口才会成为一个潜在的问题。 只要你把这个改变传达给每个人,它应该不是一个问题。
为了连接到一个非标准 SSH 端口的服务器,使用-p
标志:
ssh -p 63456 myhost.mynetwork
您还可以在使用scp
时指定端口:
scp -P 63456
注意,scp
中的-P
参数是大写的,而在ssh
命令中不是。 这是故意的。 这是因为已经使用了scp
中的小写-p
选项,它用于在传输文件时保存修改时间。
如果似乎不能养成为 SSH 请求不同端口的习惯,那么为它创建一个别名。 然而,如果您的一些主机仍然使用端口 22,那么这可能是一个问题,所以只有当您连接的所有内容都在相同的端口上时,才会使用这个别名。 在下面的示例中,我们可以将别名设置为ssh
,以强制它始终使用端口63456
:
alias ssh="ssh -p 63456"
对 SSH 配置的另一个非常重要的更改是不允许 root 登录。 在任何情况下,任何 Linux 服务器都不允许 root 登录。 如果您的配置要求您以 root 身份通过 SSH 登录到服务器,请更正您的配置。 要检查 root 登录是否通过 SSH 启用,请执行以下命令:
cat /etc/ssh/sshd_config |grep PermitRootLogin
如果启用了 root 登录,请在/etc/ssh/sshd_config
中修改下面的配置行来禁用它。 但是,首先要确保您能够使用普通用户帐户通过 SSH 访问服务器; 否则,你会被锁在门外。 下面的配置行在sshd_config
将禁止根用户登录:
PermitRootLogin no
像往常一样,在对ssh
的配置进行任何更改后重新启动它。 不用担心在使用 SSH 时重新启动它,当前的连接不会中断。
对于 Debian 系统,执行以下命令:
# systemctl restart ssh
对于 CentOS 系统,执行如下命令:
# systemctl restart sshd
另一个值得实现的实践是将 SSH 锁定为只允许通过特定用户和/或组进行连接。 默认情况下,任何拥有系统帐户的用户都可以通过 SSH 访问。 要改变这一点,在配置文件的最底部添加以下一行:
AllowUsers jdoe
如果有多个用户,可以在同一行中添加多个用户:
AllowUsers jdoe bsmith
您还可以允许特定的组。 首先,创建一个用于 SSH 访问的组:
groupadd ssh_admins
接下来,向组中添加一个或多个用户:
usermod -aG ssh_admins jdoe
最后,将下面的添加到 SSH 配置文件的底部。 重启 SSH 后,访问权限将被限制为该组的成员。 每次您需要将 SSH 访问权限授予某人时,您所需要做的就是将他们的用户 ID 添加到这个组,而不必每次都重新启动sshd_config
配置文件。
AllowGroups ssh_admins
最后,SSH 最安全的选项是根本不允许基于密码的身份验证。 相反,用户可以使用公钥/私钥对进行访问。 使用这种方法,密码不会通过网络传输,并且那些没有与接受的公钥相匹配的私钥的密码将不被允许访问。 这是我向大家推荐的做法。 缺点是,它还带来了最多的管理开销。 要实现这个改变,每个用户需要用以下命令为 SSH 生成一个密钥对:
ssh-keygen
您将被问及几个问题,其中大多数问题都可以作为默认的保留。 对于密码短语,要想出一些独特的东西,并确保它与你的密码不一样。 如果你不想在建立连接时被要求输入密码,你可以把它留空,但我建议你自己创建一个。
接下来,配置服务器以允许您通过密钥进行连接的最简单的方法是在禁用密码身份验证之前将该密钥导入服务器*。 要做到这一点,可以使用以下方法:*
ssh-copy-id -i ~/.ssh/id_rsa.pub myserver.mynetwork.com
此时,系统将要求您使用普通密码登录服务器。 然后,下次连接到它时,您将默认使用您提出的密钥对,如果您创建了一个密钥对,您将被要求提供密码短语。
在所有用户生成密钥并将其导入服务器之后,您可以实现此更改。 在 SSH 配置文件中查找类似如下所示的行:
PasswordAuthentication yes
只需将该选项更改为 no,重新启动 SSH,就应该已经全部设置好了。 这个工作的原因是当你复制 SSH 密钥使用ssh-copy-id
命令,它实际上做的是复制的内容您的公钥(~/.ssh/id_rsa.pub
)在本地机器上的~/.ssh/authorized_keys
在远程计算机上的文件。 禁用密码身份验证后,SSH 将检查那里列出的密钥是否与您的私钥(~/.ssh/id_rsa
)匹配,然后允许您访问。
通过这些调整,您的 SSH 实现应该是相当安全的。 如果您使用弱密码或密码短语,它当然不会帮助您,但这些是您应该在所有服务器上采取的一般步骤。
默认情况下,Linux 包括防火墙iptables。 这个防火墙应该在大多数(如果不是全部)版本的 Linux 上自动可用。 在这个小活动中,我们将在 Linux 系统上设置防火墙。 不管您使用的是哪个主要发行版,这都应该可以很好地工作,但我将列出任何可能特定于发行版的内容。 在我们开始之前,我建议您在测试机器上使用它,比如 VM 或您可以物理访问的东西。 如果您正在使用 SSH,那么当我们启用防火墙时,您可能会断开连接,不过我将按照不应该断开连接的顺序提供这些步骤。 无论如何,拥有一台专用的测试机器是一个好主意。
让我们开始吧。 不幸的是,在默认情况下,iptables
是完全开放的。 它是如此开放,事实上,它什么也阻挡不了。 要亲自看到这一点,将iptables -L
作为根。 你的输出可能看起来像这样:
Chain INPUT (policy ACCEPT)
Chain FORWARD (policy ACCEPT)
Chain OUTPUT (policy ACCEPT)
你在这里看到的是iptables
的三条链,每一条都对应于输入、输出和转发。 如果您还没有对此进行配置(并且您的发行版没有提供任何默认配置),您可能会看到每个的默认策略是ACCEPT
,这就像它听起来的那样:它允许一切。
我想要实现的第一个规则是允许 SSH:
# iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
通过这个命令,我们使用 TCP 将一个新规则(-A
)附加到接口eth0
上的INPUT
链,并接受来自dport
(目的端口)22
的流量。 如果您之前更改了 SSH 端口,请确保相应地调整此命令。 另外,如果您的接口不是eth0
,也要更改它。 当然,我们的防火墙允许任何操作,因为我们从未更改默认策略。 如果你还记得的话,它默认接受所有东西。 让我们用下面的命令来改变它:
# iptables -P INPUT DROP
# iptables -P FORWARD DROP
# iptables -P OUTPUT DROP
现在,如果我们查看iptables -L
的输出,我们应该看到默认策略是DROP
,并且允许 SSH。
然而,有一个问题是我们不能做其他任何事情。 我们不能再安装软件包了。 事实上,我们不能在互联网上做任何事情。 例如,尝试 ping 谷歌。 你不能这么做。 如果您遵循了下面的操作,那么我们将默认策略设置为DROP
,它实际上意味着DROP
。 目前不允许任何流量进出服务器,除非它是 SSH。 为了恢复网络,我们需要允许更多的事情。 首先,让我们允许 DNS,它利用端口53
:
# iptables -I INPUT -s 10.10.96.0/22 -p udp --dport 53 -j ACCEPT
# iptables -I OUTPUT -s 10.10.96.0/22 -p udp --dport 53 -j ACCEPT
这里,我们允许端口53
,但只对我们的内部10.10.96.0/22
网络开放。 注意,DNS 使用 UDP,因此我们将-p udp
包含到我们的命令中。 这是不言而喻的,但调整10.10.96.0/22
部分,无论您的网络方案是什么。
在这一点上,我们对系统的锁定仍然比我们希望的要多一些。 例如,我们现在有 DNS,但如果不允许端口80
和443
,我们就无法浏览互联网。 让我们接下来来处理这个问题。
# iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -o eth0 -p tcp --dport 80 -m state --state ESTABLISHED -j ACCEPT
# iptables -A INPUT -i eth1 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -o eth1 -p tcp --dport 443 -m state --state ESTABLISHED -j ACCEPT
从现在开始,您应该能够在这台机器上浏览 Internet 并通过 SSH 访问它,但是不应该访问其他端口和服务。 如果所讨论的机器是路由器,您可能还需要配置端口转发。 下面是端口转发的一个示例:
# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 65254 -j DNAT --to-destination 10.10.96.10
在本例中,我们将从端口65254
接收的流量转发到10.10.96.10
。 如果您在除22
之外的其他端口上有类似 SSH 的东西可用,并且希望能够使用该端口访问计算机(在本例中为10.10.96.10
),则此示例非常有用。 服务器现在将它在该端口上接收到的通信转发到该计算机。 这使用了PREROUTING
的概念,它处理进入的数据包,并能够通过 NAT 重新分配它们。在这种情况下,我们使用防火墙创建一个 NAT 规则,将这些流量发送到适当的位置。
如果您正在设置此防火墙的服务器注定要成为路由器,那么您还需要启用接口之间的路由。 在上一章中,我们从 Linux 级别开始考虑这个问题,但是由于我们将防火墙默认配置为DROP
,所以我们不能再这样做了。 为了继续在接口之间路由,我们还需要在防火墙内启用路由。 为此,我们可以使用以下命令:
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# iptables -A FORWARD -i eth1 -j ACCEPT
在前面的命令中,我们允许在接口eth0
和eth1
之间路由。 调整前面的命令以适合您的发行版的网络接口命名方案,以便它适合您的环境。 我们还使用了POSTROUTING
,在iptables
中,它是对外流量的另一个词。
另一个可能有用的改变是允许 ping。 在我们目前的配置中,ICMP ping 报文被阻止了。 如果您 ping 您的服务器,您将不会得到响应。 我们可以通过以下命令重新启用 ping 响应。 请确保修改 IP 地址以匹配您的服务器:
# iptables -A INPUT -p icmp --icmp-type 8 -s 0/0 -d 10.10.96.1 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
# iptables -A OUTPUT -p icmp --icmp-type 0 -s 10.10.96.1 -d 0/0 -m state --state ESTABLISHED,RELATED -j ACCEPT
如果由于某些原因你犯了一个错误,或者你想再次启动这个活动,发出以下命令来刷新(重置)iptables
防火墙:
# iptables –flush
注意,这不会撤销您的默认策略,如果您想撤销到目前为止所做的所有操作,可以显式地将该策略设置为ACCEPT
。 我们可以使用以下命令将每个表设置为默认值(ACCEPT
):
# iptables -P INPUT ACCEPT
# iptables -P FORWARD ACCEPT
# iptables -P OUTPUT ACCEPT
我们选择DROP
作为默认策略,因为在这种模式下,当拒绝流量时,防火墙不会以状态响应发送主机。 从某种意义上说,当将策略设置为DROP
时,就好像将数据包发送到一个无穷无尽的黑洞。 这是一件好事,因为歹徒可以利用他们从服务器得到的响应来更好地瞄准他们的攻击。 对他们来说,最好是不要得到任何回应。
所以,请随意使用iptables
,直到您能够执行所有您通常能够执行的任务。 一旦您有了一个可以工作且经过良好测试的防火墙,就该保存配置了。 否则,当您重新启动时,所有这些辛苦的工作都将丢失。 使用以下命令保存您的防火墙配置:
# iptables-save > /etc/iptables.rules
要导入这些规则,可以使用以下命令:
# iptables-restore < /etc/iptables.rules
您可能希望在每次系统引导时自动恢复这些更改。 Debian 和 CentOS 都有自己的方式来实现这一点。 下面是保存规则的方法。
在 Debian 中,首先像以前一样保存规则:
iptables-save > /etc/iptables.rules
接下来,创建以下文件:
/etc/network/if-pre-up.d/iptables
在该文件中,放置以下文本:
#!/bin/sh
/sbin/iptables-restore < /etc/iptables.rules
在 CentOS 操作系统中执行如下命令:
# iptables-save > /etc/sysconfig/iptables
从这一点开始,您的防火墙规则应该在每次重新启动服务器时保持不变。
防火墙是一个很好的东西,但它不能做太多来保护被允许的服务。 防火墙只允许或不允许访问。 但是,一旦允许访问某个服务,其安全性就取决于其配置以及是否存在任何安全性漏洞。 值得安装的一个服务是fail2ban,这是一个在后台运行的整洁的小工具,它会监视您的日志中任何不寻常的事情,比如访问一个服务的多次失败。 fail2ban
最流行的用途是保护 SSH 不受那些试图强行使用它的人的伤害。 在很多方面,fail2ban
是denyhosts的后继者,而几乎做了同样的事情。 但是fail2ban
能够保护比 SSH 更多的服务,另一个例子是 Apache。
当fail2ban
发现一个源试图访问一个服务并且失败时,它将动态地设置防火墙规则来阻止该服务从您的服务器上访问。 首先,在服务器上安装fail2ban
包。 在 Debian 系统中,这在默认存储库中是可用的。 CentOS 系统可以在我们过去设置的epel
存储库中找到这个包。 安装完成后,如果还没有使用以下命令,则使用systemctl
启用并启动它:
# systemctl start fail2ban
# systemctl enable fail2ban
在/etc/fail2ban
目录中,您应该看到主配置文件jail.conf
。 将此配置复制到本地副本是一个好主意,因为如果您编辑jail.conf
,总是有可能被包升级覆盖。 如果找到fail2ban
服务将读取jail.local
,如果要升级,则不会覆盖fail2ban
:
# cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
既然我们有一个本地副本,现在我们可以配置它来保护我们的服务。 让我们从 SSH 开始。 为此,在文本编辑器中打开/etc/fail2ban/jail.local
并查找[ssh]
部分。 在我的系统上,这个部分看起来像这样:
[ssh]
enabled = true
port = 65256
filter = sshd
action = iptables[name=SSH, port=65256, protocol=tcp]
logpath = /var/log/auth.log
maxretry = 6
正如您所看到的,配置是相当不言自明的。 第一行启用了 SSH 监狱,它使用sshd
过滤流量,并在/var/log/auth.log
中查找与 SSH 相关的消息。 虽然您可能已经注意到了,但是我们需要在这个文件中调用 SSH 端口。 如果您坚持使用端口 22,则可以将文件的相关部分保留在配置中。 但是,如果您将 SSH 端口更改为其他端口,请确保进行相应的调整。 有两个地方可以放置 SSH 端口,第一个在第 3 行上,第二个在第 5 行上。
现在我们已经有了我们的配置,我们可以重新启动fail2ban
来开始为我们保护 SSH:
# systemctl restart fail2ban
看看我们可能想要启用的其他服务的配置文件。 一个例子可以是我们的 web 服务器的 Apache,甚至是 NGINX,如果你已经设置好了的话。 默认配置文件包含大量您可以使用的示例。 要使用一个,只需将enabled = false
更改为enable = true
,然后重新启动fail2ban
。
Security Enhanced Linux(SELinux)是一个内核模块,通过增强强制访问控制来提高安全性。 这个概念使您能够确保用户和应用只能访问为了完成指定的任务而绝对需要的东西。 虽然防火墙有助于保护系统不受外部入侵,但 SELinux 有助于防止内部资源执行它们不应该执行的操作。 这听起来可能有些模糊,因为这就是 SELinux 的使用方式,而您如何从它中受益完全取决于您如何实现它。 想要阻止用户创建一个全世界都可读的非常私有的文件? 当然,你可以这么做。 也许确保 Apache 不能访问/var/www
以外的文件? 你也可以这么做。 如果没有 SELinux,您将只依赖于组和用户权限。 SELinux 通过在组合中添加额外的安全性层,帮助您设置更细粒度的安全性限制。
SELinux 并不专属于任何一个发行版,尽管您通常会发现它安装在 Red Hat、Fedora 和 CentOS 系统上。 在 Debian 这样的系统中,如果想要使用它,就需要安装selinux
。 不幸的是,在撰写本文时,SELinux 在 Debian 中不能正常工作,因为一个必需的包(selinux-policy-default
)包含在 Jessie 发行版中没有及时修复的 bug,所以这个包在 Debian 8 中被省略了。 x“杰西”存储库。 然而,在 Debian 中安装 SELinux 的过程(如果该包在发布后可用)归结为将该包与selinux-basics
一起安装。 安装完这些包后,您应该能够通过运行以下命令并重新启动系统来完成 SELinux 安装:
# selinux-activate
# systemctl enable selinux-basics.service
SELinux 使用策略来确定是否允许某个操作。 策略是用存在于SELinux 用户空间中的工具创建的,而实际的检查是在内核层完成的。 每个在默认情况下实现 SELinux 的发行版通常都会附带一组经过测试和受支持的策略,以便您合理地期望运行的所有服务都能正常工作。 如果没有缺省的策略集,手动配置 SELinux 可能会非常麻烦(如果开始配置 SELinux 的话)。 正如前面提到的,Debian 的策略包目前还不是主存储库的一部分,因此在 Debian 中启用 SELinux 可能会有些混乱。 但是在 CentOS 中,使用 SELinux 所需的一切都可以开箱即用。 事实上,除非您禁用了它,否则您已经在使用它了!
SELinux 有三种操作模式,为强制,允许和禁用。 默认情况下,我最近看到的大多数安装都被设置为enforcing
,但是您可以通过执行sestatus
来查看您的三个安装设置为哪一个。
在 CentOS 上从 sestatus 输出
使用enforcing
,SELinux 被配置为启用其策略,并将对任何违背该策略的操作进行操作。 如果发生违规,SELinux 将阻止该操作并记录它。 在permissive
模式下,操作不会被阻止,但所有内容仍会被记录,因此您可以稍后自己审计服务器。 disabled
状态是不言而喻的; 在这种模式下,SELinux 在被禁用时不会阻止或记录任何内容。 很常见的是,管理员会简单地禁用 SELinux,假设如果它妨碍了合法的用例,那么它会是一个很大的负担。 但是不建议禁用 SELinux,除非绝对必要,因为它是另一层安全,否则您可以从中受益。 至少,您可能希望受益于permissive
模式,以便在服务器上发生可疑事件时,您的日志中有更多可用信息。
要动态更改 SELinux 的操作模式,可以使用setenforce
命令。 例如:使用setenforce Enforcing
将模式改为enforcing
。 通过setenforce
所做的更改不是永久性的。 重新启动机器后,模式将切换回默认模式或您在配置文件中配置的模式。 要永久更改模式的配置文件是 Red Hat 样式发行版中的/etc/sysconfig/selinux
文件,或者 Debian 中的/etc/selinux/config
文件。 该文件允许您配置两个主要设置,以确定如何配置 SELinux,即模式和类型。 要永久更改其中之一,请更新此文件并重新启动服务器。 我们已经讨论了模式(可以将其设置为enforcing
、permissive
或disabled
),类型是我们配置希望 SELinux 使用的策略的位置。 可以设置为targeted
、minimum
或多级安全性(mls
)。
在更新策略方面,targeted
是在新安装上默认使用的进程(至少当涉及到 Red Hat/CentOS 时),并且它是由 Red Hat 完全支持的。 使用此策略,每个进程都运行在一个名为unconfined_t
的类型中,该类型实际上完全不受限制。 相反,进程将运行在 Linux 本地的DAC(简称自主访问控制)下,该机制将它们从其他进程中沙箱化,以帮助包含任何可能被破坏的内容。 MLS,或多层安全,在启用时,对被s0
指定的对象应用敏感性评级。 (通过执行sestatus
,您可以查看是否启用了 MLS)。 稍后我们将看到一些上下文输出的示例。 使用最小类型,只有我们显式选择的进程才会受到保护。
启用 SELinux 的系统中中的每个资源都包含一个标签,这就是 SELinux 如何识别资源并理解如何监管资源。 通过在一个或多个命令(如ls
、id
或ps
中使用-Z
参数,您可以自己查看这些标签(也称为上下文)。 只有在将系统配置为使用 SELinux 时,这些命令才可以使用这个特殊参数,并且它允许您将上下文作为正常输出的一部分来查看。 例如,在 SELinux 系统上,您可以将-Z
参数与ls
命令一起使用,您将看到如下输出:
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 myfile
通常,在查看ls
等命令的输出时,ls
命令的输出将包含修改日期和大小等字段。 但是同样,-Z
参数是特殊的。 这意味着您希望看到与 SELinux 相关的命令输出,而不是通常得到的输出。 您还可以尝试使用id
(id -Z
)和ps
(ps auxZ
)来让这些命令的输出也显示它们的 SELinux 上下文。
标签包含多个字段。 在我粘贴的ls
命令的输出中,我们可以看到字段unconfined_u
、object_r
、admin_home_t
和s0
。 为了更好地理解这一点,看看每个字符的最后几个字符。 _u
指定用户,_r
指定角色,_t
代表类型。 因此,我们可以从前面的输出中看到,名为myfile
的文件的用户上下文为unconfined_u
; 它被赋予了object_r
的角色和admin_home_t
的类型。 让我们看另一个例子。 在我的 CentOS 系统上的ps auxZ
输出中,我看到以下一行用于我的 SSH 会话:
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 jay 20575 0.0 0.0 135216 2080 ? S 10:40 0:00 sshd: jay@pts/0
看看行首,我们又有了用户、角色和类型的上下文。 在本例中,每一个都被命名为 unrestricted,但是我们可以通过最后两个字符来判断哪一个是 unrestricted。
类型是输出中最重要的部分,因为 SELinux 就是这样执行的。 给定类型,SELinux 知道如何限制(或不限制)对象。 在第一个例子中,我们有admin_home_t
,在第二个例子中我们有unconfined_t
。 由此,我们可以得出结论,SELinux 没有对我的 SSH 会话(unconfined_t
)强制执行任何操作,而是为我的主目录(文件的输出来自该目录)设置了特定的策略。 我们在示例输出中看到的另一个上下文是角色,由后缀_r
指定。 在应用角色时,SELinux 能够将各种上下文组合在一起,并用一个调用将它们应用到一个用户对象。 这使得指定用户能够做什么以及允许他们如何与其他对象交互变得更加容易。
有几个命令可以用来重新标记对象的上下文信息。 首先,使用chcon
命令。 chcon
命令与-t
参数一起使用,该参数指定要将对象更改为的类型,后跟对象名称:
# chcon -t admin_home_t myfile
使用-R
,我们告诉chcon
命令递归地进行更改,如果您正在更改目录的上下文,这将非常有用。 此外,如果您想更改角色而不是类型,还可以使用-r
。 如果您犯了一个错误,或者您想要恢复您的更改,restorecon
就可以做到这一点。 restorecon
命令将将对象恢复到其策略中定义的默认状态。 另一个用于管理 SELinux 的命令是semanage
。 通过这个命令,我们可以永久性地改变对象的处理和标记方式。 重要的是要注意,通过chcon
进行的更改可能并不总是持续。 虽然通过chcon
进行的更改可能会在重新引导后继续存在,但如果文件系统被重新标记,这些更改将持续存在。 semanage
命令允许我们使这些更改更持久。 使用semanage
,我们可以更改文件上下文、用户映射以及用户上下文。
首先,一个将用户jdoe
映射到sysadm_u
SELinux 用户的例子:
# semanage login -a -s sysadm
下面是一个使用fcontext
和semanage
的例子,我们可以改变文件对象的类型:
# semanage fcontext -a -t admin_home_t myfile
更多示例请参见semanage
的手册页。 SELinux 是一个很大的主题,已经有一整本书是为它写的。 完整的 SELinux 简介需要分好几个章节,但是这里提供的信息可以作为足够的入门知识。 如果实现得当,它可以极大地增强服务器上的安全性。
第七章,通过 Apache 托管 HTTP 内容都是关于 Apache 的。 在那里,我们学习了如何让它运行并使用进行配置,以便在我们的网络上托管一个站点。 但是,如果我们要创建一个可能承载个人身份信息的站点,我们将希望确保使用适当的安全措施来保护这些信息。 为我们的站点使用SSL证书允许通过安全端口 443 访问它,从而提高安全性。 利用 SSL 并不是我们唯一能够提高网络服务器安全性的方法,但这绝对是一个开始。
我们可以使用两种证书。 我们可以创建一个自签名证书,也可以使用证书颁发机构(CA)注册一个证书。 后者是首选,尽管如果您创建的站点仅供内部使用,那么它可能开销过大。 不同之处在于自签名证书不受任何浏览器的信任,因为它不可能来自已知的 CA。当您使用这样的证书访问站点时,它会抱怨站点的证书无效。 这并不一定是正确的,因为自签名证书肯定是有效的; 只是浏览器没有办法确定。 通过 CA 注册证书可以缓解这种情况,但要付出一定的代价。 根据范围的不同,注册证书的费用可能很高。 选择权在你。
在 Debian 系统上,确保使用以下命令启用 SSL:
# a2enmod ssl
首先,您需要在 web 服务器的文件系统中选择一个存放证书文件的位置。 这里没有严格的规则,唯一的要求是 Apache 能够访问它(最好是其他任何人都不能!) 一些很好的候选包括 Debian 中的/etc/apache2/ssl
和 CentOS 中的/etc/httpd/ssl
。 我把我的放在/etc/certs
。 无论您选择哪条路径,请切换到该目录,然后我们将继续。
如果你已经决定创建一个自签名证书,你可以使用以下命令:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout server.key -out server.crt
在生成证书时,将要求您提供与您的组织、联系信息和域有关的一些信息。 这里有一个你会被问到的问题的例子和一些例子的答案:
Country name: US
State or Province Name: Michigan
Locality Name (City): White Lake
Organization Name: My Company
Organizational Unit Name: IT Dept
Common Name (Fully Qualified Domain Name): myserver.mydomain.com
Email Address: [email protected]
这将在当前工作目录中为您创建两个文件server.key
和server.crt
。 这些文件的文件名是任意的,您可以随意命名它们。 现在,我们需要确保我们的网络服务器能够找到并使用这些文件。
在 Debianweb 服务器上,我们可以通过编辑/etc/apache2/sites-available/default-ssl.conf
来实现这一点。 在该文件中,将有一个部分用于添加启用键的指令。 寻找有关于 SSL 注释的部分。 在该节内增加下列行:
SSLCertificateFile /etc/certs/server.crt
SSLCertificateKeyFile /etc/certs/server.key
在 CentOS 中,我们会将相同的行添加到/etc/httpd/conf/httpd.conf
文件中,但是使用了SSLEngine on
指令。 这应该放到它自己的VirtualHost
指令中,类似于下面的例子。 只需确保更改路径以匹配您的 web 服务器设置:
<VirtualHost *:443>
SSLEngine On
SSLCertificateFile /etc/certs/server.crt
SSLCertificateKeyFile /etc/certs/server.key
SSLCACertificateFile /etc/certs/ca.pem (Only include this line if the certificate is signed).
DocumentRoot /var/www/
</VirtualHost>
设置签名 SSL 证书与此类似,但不同之处在于如何请求它。 该过程需要创建一个证书请求(CSR),您将该请求提交给您的提供商,而该提供商将为您提供一个已签名的证书。 最终的结果是相同的,文件将在相同的地方结束。 您只需在提交 CSR 后使用供应商提供给您的文件。 让我们先创建一个 CSR,我们将使用openssl
命令为我们生成:
openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr
你会问同样的问题,但请注意,我们讲openssl``.csr
给我们,所以我们将有一个server.csr
文件在我们的工作目录我们将使用从我们的 CA 请求的一个关键。从你的证书提供商你收到文件后,你将更新 Apache 正如我们前面所做的。
虽然对于那些在安全方面经验丰富的人来说,似乎是常识,但是发布发行版的更新是有原因的。 在某些情况下,更新仅用于添加新特性或将软件更新到最新版本。 但是对于像 CentOS 和 Debian 这样的企业发行版来说,这些更加重要。
这是基于消费者的发行版和企业发行版的不同之处。 Ubuntu 的非 lts 发行版、Linux Mint 和 Fedora 等发行版比 CentOS、Debian 和 Red Hat 等企业发行版获得了更多的前沿软件包。 这是因为终端用户通常想要最新版本的网页浏览器、电子邮件客户端、文字处理器或游戏。 对于企业号来说,这并不重要。 在 Enterprise 中,安全更新是至关重要的。 虽然在大多数情况下,面向消费者的发行版肯定会在几乎相同的水平上更新安全补丁,但这些补丁与特性更新混杂在一起,可能会损害而不是帮助稳定性。
在 Debian 中,实际上提供了两种风格。 主要的发行版被称为Debian 稳定版,它只接收安全补丁。 即使是默认的浏览器(Iceweasel)也不会像其他平台上的 Firefox 那样频繁更新。 这里的想法是,改变代表着潜在的破坏。 需要做相当多的工作来确保您在 stable 中获得的包是经过检验的、正确的,而不是最新的、最好的。 这个概念也类似于 CentOS,尽管它的包通常比 Debian 的更老。 为了让您了解这一点,在我撰写本章时,最新的 Linux 内核是 4.1。 Debian Jessie(最新的“稳定版”)包含 3.16 内核,而 CentOS 7 甚至更老,为 3.10。 并不是说内核老了没什么错,我只是举个例子。 Red Hat 和 Debian 都有更多可用的前沿发行版。 Fedora由 Red Hat 赞助,包含更多最新的软件包。 它是面向用户谁喜欢有最新的软件。 Debian 测试也包括更多的最新包,尽管它不像 Fedora 那样稳定,不时会遇到包损坏。 Debian 测试的目标是那些想要测试 Debian 下一个版本的人,因为随着 Debian 的成熟,Debian 测试最终会成为新的 Debian 稳定版。
出于安全目的,安装最新的安全更新是至关重要的。 的确,Linux 比许多其他平台更安全、更稳定,但不管操作系统有多安全,归根结底,它的安全取决于它的管理方式。 如果发现了可利用的漏洞,更新落后的 Linux 发行版的安装就很容易受到攻击。
考虑到终端用户和企业发行版的存在,管理它们的安全更新可能是一项挑战。 如果您的组织在两台服务器和终端用户的机器上都使用 Linux,那么您可以很好地使用这两种类型的发行版。 这是因为尽管 CentOS 是安全和稳定的,但您不太可能成功地将其部署到最终用户的机器上。 由于 CentOS 的内核稍早一些,它不会支持目前终端用户工作站可用的所有新硬件。 此外,没有那么多的定制,使其适合台式机或笔记本电脑使用。 虽然可以这样做(很多人都这样做),但在终端用户设备上安装 CentOS 通常是一种挫折。 对于终端用户的机器,您可能会选择 Ubuntu、Linux Mint 或 Fedora。 但是有了这些,您就需要花更多的时间关注哪些更新是为了安全性,哪些更新是为了应用中的新特性。 根据更新的性质,您可以选择不同的方式进行更新。
理想情况下,在一个完美的服务器空间中,服务器的所有更新都将在发布后立即安装,不会出现任何问题,一切都会顺利进行。 但在现实中,保持安全更新是有挑战的。 可能出现的回归会导致重要的应用无法运行。 另外,打包过程中的错误可能会破坏 RPM 数据库(这是一种非常令人沮丧的体验!),所以虽然更新很重要,但也需要一些谨慎的练习。
最好的策略(或者至少是我发现的对我很有效的策略)是创建测试服务器,以便在将更改推出生产环境之前对其进行测试。 在虚拟机服务器的情况下,您甚至可以克隆生产服务器,并在它们上测试更新或其他更改,看看如果将它们推出生产环境,它们将如何反应。 然后,您可以有理由相信新的更新不会破坏生产服务器。 公平地说,这种情况很少发生。 但是考虑到 Linux 的灵活性和 Linux 服务器易于克隆的事实,没有理由不进行测试。
在 CentOS 系统中,您可以使用yum update
命令更新服务器上的所有包。 您可以使用yum update
和包的名称来更新该包。 在 Debian 系统中,您可以使用apt-get update
来刷新源代码,然后您可以使用带有包名的apt-get install
来更新包。 要更新所有内容,您需要更新源代码,然后运行apt-get dist-upgrade
。
在实际安装中,您可能不会更新服务器上所有可用的包。 相反,一种方法是根据需要更新包。 这需要管理员进行大量的研究,以便关注当前的安全趋势,然后选择影响当前生产中使用的服务的安全更新。 对于基于 Debian 和 Red Hat 的系统,有两个方便的网站与常见漏洞和暴露(CVE)相关,您应该将其加为书签。
对于 Red Hat,请使用以下 URL:
https://access.redhat.com/security/cve/
Debian 使用的 URL 如下:
https://security-tracker.debian.org/tracker
这两个站点都允许您查看单独的 CVE 报告,它将告知您有关易受攻击的软件包以及它们是否已修补。 在某些情况下,CVE 在您的特定发行版中甚至是不可利用的,在这种情况下,您不需要做任何事情。 但是通过跟踪这些报告,您可以对哪些潜在漏洞可能影响您的组织做出明智的决定。 这将允许您创建一个计划,将必要的补丁部署到服务器上。
安全性是一个非常复杂的主题。 如此复杂,没有人能成为无所不知的专家,即使是业内的顶尖人士也在不断学习。 同样地,在统计上也不可能创建一个无法攻破的防弹服务器。 但作为网络管理员,您的职责是尽最大努力确保节点的安全。 安全通常是反动的,这需要你保持警觉。 在本章中,我们了解了一些保护网络免受风险的方法。 我们讨论了诸如保护 SSH、限制攻击面、使用 SSL 保护 Apache、fail2ban 和部署安全更新等概念。
在下一章中,我们将研究当出现问题时,您可以做些什么来排除故障。