【安全与加密】TCP-Wrapper与PAM模块
TCP-Wrapper
TCP wrappers 通常被称为 wrappers,它是由 Wieste Venema 编写,已经出现几年了。其背后的思想很简单,其要旨是可以在 (UNIX/Linux) 主机上快速轻松地锁定流行的通过 TCP 访问的客户端。
Wrappers 允许系统管理员控制 wrappers 支持的基于 TCP 的服务或守护进程的访问。Tcpd 控制从 /etc/inetd.conf 中运行的 TCP 守护进程。不过,很多基于 TCP 的应用程序已加入 wrappers 支持(一般使用 libwrap 库),并且能感知 wrapper;不通过 /etc/inetd.conf 进行控制也没有关系。可以在 wrappers 下进行访问控制的通常有 telnet、ssh、sendmail、ftp 包、pop3 和 stunnel。
Wrappers 提供对基于 UDP 的连接的有限控制,不过我建议使用内置或第三方防火墙进行基于 UDP 的访问。
如果要看应用程序是否支持 wrapper,使用 strings 命令和 grep 获取 hosts_access 或 host:
# strings /usr/sbin/sshd|grep hosts_access``@(#)65 1.1 src/tcpwrapper/usr/sbin/tcpwrapper/hosts_access.c, tcpwrap, 53twrp2``10, 0617A_53twrp210 2/27/06 04:52:25
或者可以使用 ldd 命令:
ldd </``path``/application> | grep libwrap
wrappers 守护进程称为 tcpd。得到调用的是它,而非 /etc/inetd.conf 文件中的实际守护进程。Tcpd 读取两个文件,hosts.allow 和 hosts.deny,读取时基于这两个文件中的规则。当找到第一条规则匹配后,会拒绝或允许调用客户端的访问。所有操作都会被记录到消息文件或指定的日志文件中,这可以通过 syslog 来确定。通常情况下,hosts.allow 包含允许访问的规则,而 hosts.deny 包含拒绝访问的规则。
下面看一下典型的 telnet 客户端场景,它是这样工作的。客户端试图通过 telnet 会话连接到配置有 wrappers 的主机上。未知的客户端连接到 wrappers 守护进程,而不是实际的 telnentd 守护进程。根据 hosts.allow 或 hosts.deny 文件中的规则,会允许或拒绝该客户端的访问。如果拒绝访问,就会终止 telnet 连接。如果该客户端符合允许访问规则,那么 tcpd 就会交出对所调用的实际守护进程的控制权(本例中是 telnetd)。无论哪种情况,许可或拒绝访问都会通过 syslog 被记录下来。
构建 wrappers
…
配置 wrappers
下一个任务是在 /etc/inetd.conf 中调用 tcpd 而不是实际的守护进程或服务。首先,创建 /etc/inetd.conf 的备份。在本例中,我仅仅替换想要控制访问的守护进程。我会用 tcpd 替代 ftpd 和 telnetd 作为 /etc/inetd.conf 中的调用守护进程。随意保护此文件中的其他守护进程。/etc/inetd.conf 中我们感兴趣的行有:
ftp stream tcp6 nowait root /usr/sbin/ftpd ftpd ``telnet stream tcp6 nowait root /usr/sbin/telnetd telnetd -a
我们只是替换想要保护的守护进程,本例中是用 tcpd 替换 ftpd 和 telnetd。编辑完成后,更改以下配置:
ftp stream tcp6 nowait root /usr/sbin//tcpd ftpd``telnet stream tcp6 nowait root /usr/sbin/tcpd telnetd -a
下一步,刷新 inted 让更改生效。
# refresh -s inetd
根据以上所述,对于其他的 wrapper 支持的第三方应用程序,应查询 hosts.allow 和 hosts.deny 文件。履行文件中的规则从而拒绝或允许对自己的客户端的访问是应用程序的责任。我们现在开始配置主机文件。
wrappers 会默认记录到 /var/adm/messages,使用的是设备级的权限:
auth.info /var/adm/messages
如果您在 makefile 中指定了 LOCAL 设备,那么您必须告诉 syslog 使用 syslog.conf 中哪个文件。以下示例中,所有在 wrappers 中使用 LOCAL 的消息都记录到 /var/adm/wrappers.log 文件中。
local0.info /var/adm/wrappers.log
确保在重启 syslog 之前创建 wrappers.log 文件:
# refresh -s syslogd
规则
要关闭 wrappers,只需将 hosts.allow 和 hosts.deny 文件改成其他文件名即可。如果不存在允许或拒绝访问文件,wrappers 将不会使用访问控制,从而有效关闭 wrappers 。或者将主机文件清空或清零,这会有同样的效果。
Wrappers 首先在 hosts.allow 文件中查找规则匹配。如果找到匹配,那么 tcpd 会根据规则停下来,批准或拒绝访问。如果在 hosts.allow 文件中未找到匹配,那么 tcpd 会读取 hosts.deny 文件直到找到匹配。如果找到匹配,就拒绝访问,否则批准访问。
我在前面提到了两个文件 hosts.allow 和 deny,但根据规则的灵活性,可以只用一个文件,通常是 hosts.allow 来包含 wrappers 所有规则。
Wrappers 会查询 hosts.allow 和 hosts.deny 中的规则来确定访问。规则的基本格式是:
daemon, daemon, ...: client, client, ...: option
其中:
daemon | 要监控的服务,如 telnetd、ftpd、sshd |
---|---|
client | 主机名、IP 地址/IP 范围,或域名 |
选项有:
allow | 对客户端的访问 |
---|---|
deny | 对客户端的访问 |
except | 会匹配第一个列表中所有项,除非匹配第二个列表。例如,允许 domainA 中所有项,除了 hostX.domainA 和 hostY.domanA。 |
当一行有多个守护进程或客户端时,用逗号分隔开来。可以用 ALL 关键字来表示所有守护进程或所有客户端。
LOCAL 关键字表示匹配所有不包含点号(“.”)的主机;这表示所有与域不相关的主机。
如果规则允许的话,在每个规则末尾都加上允许或拒绝选项,这是一个好的做法、好的习惯(因为这可以清晰地描绘访问规则,尤其是在 hosts.allow 中有多个允许或拒绝规则时)。
还有一些其他的选项,我将在稍后演示。现在,我们将访问控制结合在一起。
对 hosts.allow 和 hosts.deny 的更改是动态的。一旦文件保存,更改就会生效。
一个好的起点是,仅仅允许您想要访问主机的客户端使用允许的守护进程,拒绝其他所有客户端。
所以,hosts.deny 可以使用以下规则拒绝所有客户端访问所有守护进程:
ALL:ALL
本节的其他示例都是只与 hosts.allow 文件有关。为了能让所有守护进程从本地主机(即,与域名不相关的主机)访问,可以使用:
ALL:LOCAL : allow
就我个人而言,我不喜欢使用在任何主机上匹配的 LOCAL 模式,因为网络中所有主机应该属于您的或是某个域。如果原来不是,那么应该是的。尽管如此,在一些小型网络的情况下,却不是这样,LOCAL 允许这些主机访问。
我们假设仅仅允许属于 mydomain.com 域的主机使用 telnet 或 ssh。以下的 hosts.allow 条目能完成此任务:
telnetd,sshd:.mydomain.com :allow
请注意本例中 mydomain.com 之前的点号(“.”)。这是个通配符,表示所有主机以 mydomain.com 结尾。我们还在规则结尾指定这是一条允许规则。尽管这不是严格限制,但如前所述,这样做是一种好的做法。
现在进一步假设我们允许使用以下 IP 地址远程登录 ssh 和 telnet:192.168.4.10 和所有以 192.168.6 开头的 IP 地址。请再次注意,在部分 IP 地址后使用点号;这相当于 192.168.6.*.,或者更精确一点,以 192.168.6 开头的所有 IP 地址。另一种看待 192.168.6. 范围内 IP 地址的方法是等于 192.168.6/24 或所有 192.168.6.1 与 192.168.6.254 之间的 IP 地址。
另外,我们还想允许使用 telnet 和 ssh 访问以下域:mydomain.com 和 mydomain2.com 域。以下命令能完成此任务:
telnetd,sshd:.mydomain.com, .mydomain2.com :allow``telnetd,sshd:192.168.4.10 , 192.168.6.: allow
现在,我们假设允许从 mydomain.com 域中的所有主机上进行 ftp 访问,除了 mydomain.com 中的两个主机:uktrip1 和 uktrip2 。通过使用允许规则,我们可以利用 except 选项提供两个列表,让 “except” 左侧的主机允许访问,“except” 右侧列表中包含的主机拒绝访问。
telnetd,sshd:.mydomain.com :allow``telnetd,sshd:192.168.4.10 , 192.168.6.: allow``ftpd:.mydomain.com except uktrip1.mydomain.com, uktrip2.mydomain.com : allow
我们现在看看拒绝规则。要拒绝 192.168.8. 和 192.168.9. 的 telnet 访问,但允许 192.168.6. 的 telnet 访问,我可以使用:
telnetd :192.168.8., 192.168.9.: deny``telnetd :192.168.6.: allow
前一个示例也可以用 except 选项来改写:
telnetd:192.168.6. except 192.168.8., 192.168.9.: allow
Wrappers 会将消息记录到 /var/adm/messages 文件中。消息文件中一个典型的名为 tardis 的被拒绝 telnent 连接会像这样:
Oct 23 15:50:55 rs6000 auth|security|warning telnetd[270546]: refused connect from`` ``tardis
一个典型的名为 tardis 的失败的 ssh 连接像这样:
Oct 23 15:53:36 rs6000 auth|security:info sshd[262252]: refused connect from tardis
如果打开 PARANOID,那么 wrappers 会通知您所有无法解析的主机与 IP 不匹配情况:
error ftpd[2605110]: warning:/etc/hosts.allow, line 2: host name/address mismatch: ``192.168.7.12 != uktrn004.mydomain.com
有时候能看到哪些主机 DNS 条目不正确也是好事,这样可以被负责 DNS 维护的人员纠正过来。在公司内部网络尤其如此。与拒绝不匹配主机/IP 不同的是,只允许域用户进入(假设这是在安全的公司网络中)。在以下示例中,所有属于 mydomain.com 域的用户都允许访问,请注意对所有守护进程都使用了 ALL:
ALL:PARANOID, mydomain:allow
PAM
对于 Linux 用户,安全地共享文件是一项麻烦的任务。例如,需要费力地回想多个密码,并且重新设计系统访问应用程序(如 login、su、password、ftp 等)十分耗费时间。增加这一复杂度的是验证 过程,在该过程中,系统将识别用户并为该用户提供相应的访问控制。
PAM 的使用历史记录
PAM 是关注如何为服务验证用户的 API。在使用 PAM 之前,诸如 login(和 rlogin、telnet、rsh)之类的应用程序在 /etc/passwd
中查找用户名,然后将两者相比较并验证用户输入的名称。所有应用程序使用了这些共享服务,但是并未共享实现细节和配置这些服务的权限。
接下来,应用程序开发人员尝试编写自定义过程代码。在此过程中,需要分离应用程序与安全模块(通用安全模块可以在应用程序之间共享并且可以根据需求进行配置)。
PAM 机制将把多个低级别验证模式集成到高级别 API 中,该 API 将允许以独立于底层验证模式的方式编写使用验证的程序。PAM 的主要特征表现为通过 /etc/pam.d
或 /etc/pam.conf
文件实现动态验证配置。
PAM 可以被配置为拒绝某些程序对用户进行验证,或者在某些程序尝试验证时发出警告。PAM 程序将使用 PAM 模块(验证模块):这些模块在运行时与应用程序绑定在一起才能工作。
图 1 显示了 PAM 模块的基本流程。
图 1. PAM 库将解析配置文件并将模块装入其中
哪些操作系统支持 PAM?
PAM 最初是由 Sun Microsystems 于 1995 年开发的,并且以下操作系统版本(及更高版本)都提供支持:
- RedHat 5.0
- SUSE 6.2
- Debian 2.2
- Mandrake 5.2
- Caldera 1.3
- TurboLinux 3.6
最新版本的 Solaris™、AIX®、HP-UX 和 Mac OS® X 也支持 PAM。PAM 后来被标准化为 X/Open UNIX® 标准化流程(在 X/Open 单点登录服务(XSSO)架构中)的一部分。
PAM 模块是什么样子的?
安装 PAM 是一个逐步的过程。要获得安装说明,请参阅 参考资料。
PAM 模块是按模块类型归类的。任何给定的模块至少要实现四种模块类型功能之一:
- 验证模块用于验证用户或设置/销毁凭证。
- 帐户管理模块将执行与访问、帐户及凭证有效期、密码限制/规则等有关的操作。
- 会话管理模块用于初始化和终止会话。
- 密码管理模块将执行与密码更改/更新有关的操作。
PAM 将提供不同的功能,例如单点登录验证、访问控制等。每个功能的实现都是由不同的模块处理的。下面是一些主要模块:
-
pam_access
将使用登录名/域名,根据 /etc/security/access.conf 中的预定义规则交付日志守护进程样式的登录访问控制。 -
pam_cracklib
将根据密码规则检查密码。 -
pam_env sets/unsets
环境变量来自 /etc/security/pam_env_conf。 -
pam_debug
将调试 PAM。 -
pam_deny
将拒绝 PAM 模块。 -
pam_echo
将打印消息。 -
pam_exec
将执行外部命令。 -
pam_ftp
是匿名访问模块。 -
pam_localuser
要求将用户列于 /etc/passwd 中。 -
pam_unix
将通过/etc/passwd
提供传统密码验证。
还有许多其他模块(pam_userdb
、pam_warn
、pam_xauth
),这些模块将获取返回的一组值(这些模块的详细信息可以在 参考资料 的 PAM 管理指南中找到)。
配置 PAM
PAM 配置通常是在 /etc/pam.d
或 /etc/pam.conf
(用于旧版本)中的配置文件中实现的。
配置文件的结构
对于使用 PAM 的各项服务,目录中都有一个对应的文件,其中包含应当如何获取该服务的验证及帐户信息的规则或说明。通常每一行有一个规则。
PAM 配置文件中的字段包括:
-
Service_name
将指定服务/应用程序的名称(默认值为 OTHER)。 -
Module_type
将为Service_name
字段中的相应服务指定模块类型(auth/account/session/passwd
)。 -
Control_flag
将指定模块的堆栈行为。它可以获取诸如requisite
、required
、sufficient
和optional
之类的值。 -
Module_path
将指定实现模块的库对象的路径名称。默认情况下,它将被设为/lib/security
。 -
Module_options
/module_args
(可选字段)将指定可以传递给服务模块的选项或实参。
模块将按照在配置文件中列出的顺序被调用,这取决于每个条目允许的 Control_flag
的值。Control_flag 值包括:
- Required:堆栈中的所有 Required 模块必须看作一个成功的结果。如果一个或多个 Required 模块失败,则实现堆栈中的所有 Required 模块,但是将返回第一个错误。
- Sufficient:如果标记为 sufficient 的模块成功并且先前没有 Required 或 sufficient 模块失败,则忽略堆栈中的所有其余模块并返回成功。
- Optional:如果堆栈中没有一个模块是 required 并且没有任何一个 sufficient 模块成功,则服务/应用程序至少要有一个 optional 模块成功。
PAM 配置文件示例
表 1 显示了各种操作系统中的 PAM 配置文件的一些示例。
表 1. PAM 配置文件的世界
系统 | 配置文件所在位置 | 类型 | Control_flag | 模块 |
---|---|---|---|---|
Red Hat | /etc/pam.d | auth | required | /lib/security/pam_unix.so |
Red Hat | /etc/pam.d | account | sufficient | /lib/security/pam_unix.so |
Red Hat | /etc/pam.d | session | required | /lib/security/pam_limit.so |
AIX | /etc/pam.conf | auth | required | /usr/lib/security/pam_aix |
AIX | /etc/pam.conf | account | required | /usr/lib/security/pam_aix |
AIX | /etc/pam.conf | password | required | /usr/lib/security/pam_aix |
zSUSE 64-bit | 32-bit | /etc/pam.conf | auth | required | /lib64/security/pam_unix.so | /lib/security/pam_unix.so |
zSUSE 64-bit | 32-bit | /etc/pam.conf | account | required | /lib64/security/pam_unix.so | /lib/security/pam_unix.so |
zSUSE 64-bit | 32-bit | /etc/pam.conf | session | required | /lib64/security/pam_unix.so | /lib/security/pam_unix.so |
Solaris | /etc/pam.conf | auth | required | /usr/lib/security/pam_unix.so.1 |
Solaris | /etc/pam.conf | account | required | /usr/lib/security/pam_unix.so.1 |
Solaris | /etc/pam.conf | password | required | /usr/lib/security/pam_unix.so.1 |
HP-UX | /etc/pam.conf | auth | required | libpam_unix.so.1 |
HP-UX | /etc/pam.conf | account | required | libpam_unix.so.1 |
HP-UX | /etc/pam.conf | password | required | libpam_unix.so.1 |
PAM 的 “other” 文件
默认的 PAM 配置文件 /etc/pam.d
用于没有明确配置的所有其他服务,并且可能是 PAM 所依赖的最简单而又最健壮的默认文件。该文件内部类似如下所示:
/etc/pam.d/other File
auth required pam_warn.so
auth required pam_deny.so
account required pam_warn.so
account required pam_deny.so
password required pam_warn.so
password required pam_deny.so
session required pam_warn.so
session required pam_deny.so
此文件非常简单。对于所有模块类型,Control_flag 都是一样的:required
。调用两个模块:
- 首先,调用
pam_warn.so
来记录关于正在进行的尝试的信息。 - 然后调用
pam_deny.so
仅返回错误并防止发生任何类型的连接或验证。
因此,使用 PAM 的所有服务都必须被明确配置为允许验证;否则,尝试将失败。
设计简单 PAM 登录应用程序的 10 个步骤
这 10 个步骤可以帮助您实现自己的 PAM 应用程序并帮助您了解 PAM 会话的工作方式:
- 包括 PAM 实现的头文件(例如,pam_appl.h、pam_misc.h)。
- 在
main
函数中,使用惟一的句柄初始化 PAM 库 libpam.so(该库将装入应用程序的配置文件中指定的模块)。 - 尝试验证所有模块并处理失败场景。
- 检查用户凭证和帐户详细信息。
- 打开一个新 PAM 会话。
- 为使用凭证的用户设置环境。
- 当用户完成时,取消用户环境。
- 关闭 PAM 会话。
- 从带有句柄值的 libpam.so 库中退出。
- 退出。
上一篇: How to configure pam_tally2 to lock user account after certain number of failed login attempts
下一篇: NoMachine - waiting for the desktop user to authorize your connection
推荐阅读
-
【安全与加密】TCP-Wrapper与PAM模块
-
循序渐进学.Net Core Web Api开发系列【16】:应用安全续-加密与解密
-
基于云计算加密与数据安全
-
SQLServer 2008中的代码安全(一) 存储过程加密与安全上下文
-
goweb-安全与加密
-
云计算时代,部署加密软件是对信息安全的有效巩固与加强
-
加密货币与COVID-19:比特币的安全港之路
-
驱动程序无法使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误: RSA premaster secret error
-
详解使用Nodejs内置加密模块实现对等加密与解密
-
SQLServer 2008中的代码安全(一) 存储过程加密与安全上下文