当用户(或程序)需要访问系统时,需要进行认证,确认身份是受信任。
警告 | |
---|---|
PAM 的配置错误可能会锁住你的系统。你必须有一个准备好的救援 CD,或者设立一个替代的 boot 分区。为了恢复系统,你需要使用它们启动系统并纠正错误。 |
一般的 Unix 认证由 PAM (Pluggable
Authentication Modules,即可插入的验证模块) 下的 pam_unix
(8)
模块提供。它的 3 个重要文件如下,其内的条目使用 “:
” 分隔。
表 4.1. pam_unix
(8) 使用的 3 个重要配置文件
文件 | 权限 | 用户 | 组 | 说明 |
---|---|---|---|---|
/etc/passwd |
-rw-r--r-- |
root |
root |
(明文的)用户账号信息 |
/etc/shadow |
-rw-r----- |
root |
shadow |
安全加密的用户账号信息 |
/etc/group |
-rw-r--r-- |
root |
root |
组信息 |
“/etc/passwd
” 包含下列内容。
... user1:x:1000:1000:User1 Name,,,:/home/user1:/bin/bash user2:x:1001:1001:User2 Name,,,:/home/user2:/bin/bash ...
如 passwd
(5) 中所述,这个文件中被 “:
” 分隔的每项含义如下。
登录名
密码形式说明
数字形式的用户 ID
数字形式的组 ID
用户名或注释字段
用户家目录
可选的用户命令解释器
“/etc/passwd
” 的第二项曾经被用来保存加密后的密码。在引入了
“/etc/shadow
” 后,该项被用来说明密码形式。
“/etc/shadow
” 包含下列内容。
... user1:$1$Xop0FYH9$IfxyQwBe9b8tiyIkt2P4F/:13262:0:99999:7::: user2:$1$vXGZLVbS$ElyErNf/agUDsm1DehJMS/:13261:0:99999:7::: ...
如 shadow
(5) 中所述,这个文件中被 “:
” 分隔的每项含义如下。
登录名
加密后的密码(开头的 “$1$
” 表示使用 MD5 加密。“*” 表示无法登录。)
最后一次修改密码的时间,其表示从 1970 年 1 月 1 日起的天数
允许用户再次修改密码的天数间隔
用户必须修改密码的天数间隔
密码失效前的天数,在此期间用户会被警告
密码失效后的天数,在次期间密码依旧会被接受
账号失效的时间,其表示从 1970 年 1 月 1 日起的天数
…
“/etc/group
” 包含下列内容。
group1:x:20:user1,user2
如 group
(5) 中所述,这个文件中被 “:
” 分隔的每项含义如下。
组名称
加密后的密码(不会被真正使用)
数字形式的组 ID
使用 “,” 分隔的用户名列表
注意 | |
---|---|
“ |
注意 | |
---|---|
如果" |
注意 | |
---|---|
|
下面是一些管理账号信息的重要命令。
表 4.3. 管理账号信息的命令
命令 | 功能 |
---|---|
getent passwd user_name |
浏览 “user_name ” 的账号信息 |
getent shadow user_name |
浏览用户 "user_name " 隐藏的账户信息 |
getent group group_name |
浏览 “group_name ” 的组信息 |
passwd |
管理账号密码 |
passwd -e |
为激活的账号设置一次性的密码 |
chage |
管理密码有效期信息 |
其中的一些功能只能被 root 使用。密码和数据的加密参见 crypt
(3)。
注意 | |
---|---|
在设置了 PAM 和 NSS 的系统上(例如 Debian salsa 机器),本地的
“ |
在系统安装时建立一个账号或使用 passwd
(1) 命令时,你应该选择一个好密码,它应该由 6 到 8 个字符组成,其中包含下列根据
passwd
(1) 设定的每个组合中的一个或多个字符。
小写字母
数字 0 到 9
标点符号
警告 | |
---|---|
密码中不要使用可以猜到的词。账号名、身份证号码、电话号码、地址、生日、家庭成员或宠物的名字、字典单词、简单的字符序列(例如 “12345” 或 “qwerty”)等都是糟糕的选择。 |
下面是一些用于 生成加盐的加密密码 的独立工具。
表 4.4. 生成密码的工具
软件包 | 流行度 | 大小 | 命令 | 功能 |
---|---|---|---|---|
whois
|
V:25, I:251 | 387 | mkpasswd |
具备 crypt (3) 库所有特性的前端 |
openssl
|
V:841, I:995 | 2111 | openssl passwd |
计算密码哈希 (OpenSSL). passwd (1ssl) |
现代的类 Unix 系统(例如 Debian 系统)提供 PAM (Pluggable Authentication Modules,插入式验证模块) 和 NSS(Name Service Switch,名称服务切换) 机制给本地系统管理员,使他们能够配置自己的系统。它们的功能可以概括为以下几点。
PAM 给应用软件提供了一个灵活的认证机制,因此涉及到了密码数据的交换。
NSS 提供了一个灵活的名称服务机制,它经常被 C 标准库使用,使例如
ls
(1) 和 id
(1) 这样的程序获得用户和组名称。
PAM 和 NSS 系统必须保持配置一致。
PAM 和 NSS 系统中重要的软件包如下。
表 4.5. PAM 和 NSS 系统中重要的软件包
软件包 | 流行度 | 大小 | 说明 |
---|---|---|---|
libpam-modules
|
V:889, I:999 | 984 | 插入式验证模块(基础服务) |
libpam-ldap
|
V:0, I:6 | 249 | 允许 LDAP 接口的插入式验证模块 |
libpam-cracklib
|
V:0, I:8 | 117 | 启用 cracklib 支持的插入式验证模块 |
libpam-systemd
|
V:571, I:936 | 627 | 用于 logind 注册用户会话的插入式验证模块(PAM) |
libpam-doc
|
I:0 | 152 | 插入式验证模块(html 和 文本文档) |
libc6
|
V:917, I:999 | 12988 | GNU C 库:同样提供“名称服务切换”服务的共享库 |
glibc-doc
|
I:8 | 3503 | GNU C 库:帮助页面 |
glibc-doc-reference
|
I:4 | 13841 | GNU C 库:参考手册,有 info、pdf 和 html 格式(non-free) |
libnss-mdns
|
I:510 | 141 | 用于解析组播 DNS 名称的 NSS 模块 |
libnss-ldap
|
I:5 | 265 | NSS 模块,用于使用 LDAP 作为一个名称服务的 |
libnss-ldapd
|
I:15 | 129 | NSS 模块,用于使用 LDAP 作为一个名称服务的(libnss-ldap 的新 fork) |
libpam-doc
中 “The Linux-PAM System Administrators' Guide”
是了解 PAM 配置的必要文档。
glibc-doc-reference
中的 “System Databases and Name Service
Switch” 是了解 NSS 配置的重要文档。
注意 | |
---|---|
你可以使用 “ |
注意 | |
---|---|
PAM 是用来为每个程序使用系统范围的默认值来初始化环境变量的最基础方法。 |
在 systemd 下,
libpam-systemd
软件包被安装用来管理用户登录,通过为 logind 在 systemd
控制组层级中注册用户会话来实现。参见
systemd-logind
(8)、logind.conf
(5)和
pam_systemd
(8)。
下面是一些 PAM 和 NSS 访问的重要配置文件。
表 4.6. PAM 和 NSS 访问的配置文件
配置文件 | 功能 |
---|---|
/etc/pam.d/program_name |
为 “program_name ” 程序设置 PAM 配置;参加
pam (7) 和 pam.d (5) |
/etc/nsswitch.conf |
为每个服务条目设置 NSS 配置。参见 nsswitch.conf (5) |
/etc/nologin |
通过 pam_nologin (8) 模块限制用户登录 |
/etc/securetty |
通过 pam_securetty (8) 模块限制 root 访问 tty |
/etc/security/access.conf |
通过 pam_access (8) 模块设置访问限制 |
/etc/security/group.conf |
通过 pam_group (8) 模块设置基于组的限制 |
/etc/security/pam_env.conf |
通过 pam_env (8) 模块设置环境变量 |
/etc/environment |
通过带有 “readenv=1 ” 参数的 pam_env (8)
模块设置额外的环境变量 |
/etc/default/locale |
通过带有 “readenv=1 envfile=/etc/default/locale ” 参数的
pam_env (8) 模块设置语言环境值(在 Debian 系统中) |
/etc/security/limits.conf |
通过 pam_linits (8) 模块设置资源限制(ulimit、core 等等) |
/etc/security/time.conf |
通过 pam_time (8) 模块设置时间限制 |
/etc/systemd/logind.conf |
设置systemd 的登录管理器配置 (参见 logind.conf (5)
和 systemd-logind.service (8)) |
密码选择的限制是通过 PAM 模块 pam_unix
(8) 和
pam_cracklib
(8) 来实现的。它们可以通过各自的参数进行配置。
提示 | |
---|---|
PAM 模块在文件名中使用后缀 “ |
现代的集中式系统管理可以使用集中式的轻量目录访问协议(LDAP)服务器进行部署,从而通过网络管理许多类 Unix 和 非类 Unix 系统。轻量目录访问协议的开源实现是 OpenLDAP 软件。
LDAP 服务器使用带有 PAM 和 NSS 的libpam-ldap
和
libnss-ldap
软件包为 Debian 系统提供账号信息。需要一些动作来启用
LDAP(我没有使用过这个设置,并且下面的信息纯粹是第二手的信息。请在这种前提下阅读下列内容。)。
你通过运行一个程序,例如独立的 LDAP 守护进程 slapd
(8),来建立集中式的 LDAP 服务器。
你在 “/etc/pam.d/
” 目录中的 PAM 配置文件里,使用
“pam_ldap.so
” 替代默认值 “pam_unix.so
”。
Debian 使用 “/etc/pam_ldap.conf
” 作为
libpam-ldap
的配置文件,“/etc/pam_ldap.secret
” 作为保存 root 密码的文件。
你在 “/etc/nsswitch.conf
” 文件中改变 NSS 配置,使用
“ldap
” 替代默认值(“compat
” 或
“file
”)。
Debian 使用 “/etc/libnss-ldap.conf
” 作为
libnss-ldap
的配置文件。
为了密码的安全,你必须让 libpam-ldap
使用 SLL(或
TLS)连接。
为了确保 LDAP 网络开销数据的完整性,你必须让 libpam-ldap
使用 SLL(或 TLS)连接。
为了减少 LDAP 网络流量,你应该在本地运行 nscd
(8) 来缓存任何 LDAP 搜索结果。
参见由 libpam-doc
软件包提供的 pam_ldap.conf
(5)
中的文档和 “/usr/share/doc/libpam-doc/html/
”,以及
glibc-doc
软件包提供的 “info libc 'Name Service
Switch'
”。
类似地,你可以使用其它方法来设置另一种集中式的系统。
同 Windows 系统集成用户和组。
通过 winbind
和 libpam_winbind
软件包访问
Windows domain 服务.
参见 winbindd
(8) 和 Integrating MS Windows Networks
with Samba。
同古老的类 Unix 系统集成用户和组。
通过 nis
软件包访问 NIS
(之前叫 YP) 或 NIS+。
这是在旧的 “info su
” 底部 Richard M. Stallman 所说的一句名言。别担心:Debian
系统中当前的 su
命令使用了 PAM,这样当在
“/etc/pam.d/su
” 中启用了带有 “pam_wheel.so
”
的行后,就能够限制非 wheel 组的用户 su
到 root
组的能力。
安装 libpam-cracklib
软件包你能够强制使用严格的密码规则。
在一个典型的 GNOME 系统,将会安装
libpam-gnome-keyring
,"/etc/pam.d/common-password
"
看起来像:
# here are the per-package modules (the "Primary" block) password requisite pam_cracklib.so retry=3 minlen=8 difok=3 password [success=1 default=ignore] pam_unix.so obscure use_authtok try_first_pass yescrypt # here's the fallback if no module succeeds password requisite pam_deny.so # prime the stack with a positive return value if there isn't one already; # this avoids us returning an error just because nothing sets a success code # since the modules above will each just jump around password required pam_permit.so # and here are more per-package modules (the "Additional" block) password optional pam_gnome_keyring.so # end of pam-auth-update config
注意 | |
---|---|
这里的信息也许不能完全满足你的安全需求,但这里应当是一个好的起点。 |
许多流行的传输层服务都使用纯文本来传输包括密码验证信息在内的各类消息。使用纯文本在公网上传输密码是很糟糕的做法,因为这样传输的密码很容易在网上被他人截获。为了确保整个沟通过程,包括密码信息在内都使用加密传输来确保安全,您可以在“传输层安全(Transport Layer Security,TLS)”协议或者其前身,“安全套接字层(Secure Sockets Layer,SSL)”协议之上运行这些服务。
表 4.7. 安全和不安全的服务端口列表
不安全的服务名 | 端口 | 安全的服务名 | 端口 |
---|---|---|---|
www (http) | 80 | https | 443 |
smtp (邮件) | 25 | ssmtp (smtps) | 465 |
ftp-data | 20 | ftps-data | 989 |
ftp | 21 | ftps | 990 |
telnet | 23 | telnets | 992 |
imap2 | 143 | imaps | 993 |
pop3 | 110 | pop3s | 995 |
ldap | 389 | ldaps | 636 |
加密消耗 CPU 时间。作为对 CPU 有益的替代方案,你可以保持使用纯文本通讯,仅仅使用安全认证协议加密密码,比如说:POP 使用"Authenticated Post Office Protocol" (APOP),SMTP 和 IMAP 使用 "Challenge-Response Authentication Mechanism MD5" (CRAM-MD5)。(你的邮件客户端通过互联网上你的邮件服务器发送邮件时,最近流行使用新的递交端口 587 来代替传统的 SMTP 端口 25,这样可以避免在使用 CRAM-MD5 认证自己时,网络提供商阻塞 25 端口。)
安全 Shell (SSH)
程序使用安全认证来提供不安全网络上两个不可信任主机之间的安全加密通讯。它由 OpenSSH
客户端, ssh
(1), 和 OpenSSH
后台守护进程(daemon), sshd
(8)组成.SSH 使用端口转发特性,可以给 POP 和 X
之类的不安全的协议通讯建立隧道,使其可以在互联网上安全传输。
客户端可以使用如下方式来认证自己:基于主机的认证、公钥认证、质疑应答认证、密码认证。使用公钥认证,可以实现远程免密码登录。参见 第 6.3 节 “服务器远程访问和工具 (SSH)”.
即使你运行 Secure Shell (SSH) 和 Point-to-point tunneling protocol (PPTP) 这样的安全服务,在互联网上,仍然有机会使用野蛮暴力猜测密码攻击进入。 使用防火墙策略 (参见 第 5.7 节 “Netfilter 网络过滤框架”),并和下面的安全工具一起,可以提升安全形势。
表 4.8. 提供额外安全方式的工具列表
软件包 | 流行度 | 大小 | 说明 |
---|---|---|---|
knockd
|
V:0, I:2 | 110 | 小的 port-knock 后台守护进程(daemon) knockd (1) 和客户端
knock (1) |
fail2ban
|
V:98, I:111 | 2126 | 禁用造成多个认证错误的 IP |
libpam-shield
|
V:0, I:0 | 115 | 把尝试猜测密码的远程攻击者关在外面 |
为阻止人们使用 root 权限访问你的机器,你需要做下面的操作。
阻止对硬盘的物理访问
锁住 UEFI/ BIOS 来阻止从可移动介质启动
为 GRUB 交互式会话设置密码
锁住 GRUB 菜单,禁止编辑
如果可以物理访问硬盘,则可以使用下面的步骤,相对简单的重置密码。
将硬盘拿到一个可以设置 UEFI/BIOS 从 CD 启动的电脑。
使用紧急介质启动系统(Debian 启动磁盘, Knoppix CD, GRUB CD, …)。
用读写访问挂载根分区。
编辑根分区的"/etc/passwd
"文件,使 root
账户条目的第二段为空。
对于 grub-rescue-pc
,即使用紧急介质启动的电脑,如果有编辑 GRUB 菜单条目 (参见 第 3.1.2 节 “第二阶段:引载加载程序”) 的权限,在启动时,使用下面的步骤更加简单。
使用内核参数启动系统来修改一些事情,比如说,"root=/dev/hda6 rw init=/bin/sh
".
编辑 "/etc/passwd
" 文件,使 root
账户条目的第二段为空。
重启系统。
系统的 root shell 现在可以无密码访问了。
注意 | |
---|---|
一旦某人拥有 root shell 访问权限,他能够访问任何内容,并可以重设系统上的任何密码。此外,他可以使用
|
为避免这些相关问题,仅有的理论上的软件解决方案是使用 dm-crypt 和
initramfs (参见 第 9.9 节 “数据加密提示”)加密 root 分区(或
"/etc
" 分区) 。这样的话,你总是需要密码来启动系统。
在密码基于认证和文件权限之外,系统也有其它的访问控制。
注意 | |
---|---|
参见 第 9.4.16 节 “Alt-SysRq 键” 来限制内核的安全警告密钥(SAK)功能。 |
访问控制列表 ACL 是在 第 1.2.3 节 “文件系统权限” 里面解释的普通权限的一个超集。
在现代桌面环境中,你会遇到 ACL 行为。比如,当一个已经格式化的 USB 存储设备自动挂载到
"/media/penguin/USBSTICK
",一个普通用户
penguin
能够执行:
$ cd /media/penguin $ ls -la total 16 drwxr-x---+ 1 root root 16 Jan 17 22:55 . drwxr-xr-x 1 root root 28 Sep 17 19:03 .. drwxr-xr-x 1 penguin penguin 18 Jan 6 07:05 USBSTICK
在第 11 列的 "+
" 表示 ACL 在使用。如果没有 ACL,一个普通用户
penguin
应该不能够像这样列出目录内容,因为 penguin
不在
root
组。你能够按如下方式查看 ACL:
$ getfacl . # file: . # owner: root # group: root user::rwx user:penguin:r-x group::--- mask::r-x other::---
这里:
"user::rwx
"、"group::---
" 和
"other::---
" 相应的为普通所有者、组和其它人的权限。
ACL "user:penguin:r-x
" 运行普通用户 penguin
有 "r-x
" 权限。这个能够让 "ls -la
" 列出目录内容。
ACL "mask::r-x
" 设置上层绑定权限。
更多信息参见 "POSIX Access Control
Lists on Linux"、acl
(5)、
getfacl
(1) 和 setfacl
。
sudo
(8) 程序是为了使一个系统管理员可以给用户受限的 root 权限并记录 root
活动而设计的。sudo
只需要一个普通用户的密码。安装 sudo
软件包并通过设置 “/etc/sudoers
” 中的选项来使用它。参见
“/usr/share/doc/sudo/examples/sudoers
” 和 第 1.1.12 节 “sudo 配置” 中的配置示例。
我将 sudo
用于单用户系统(参见 第 1.1.12 节 “sudo 配置”)是为了防止自己可能做出的愚蠢行为。就我个人而言,我认为使用
sudo
会比使用 root 账号操作系统来得好。例如,下列命令将
“some_file
” 的拥有者改变为
“my_name
”。
$ sudo chown my_name some_file
当然如果你知道 root 密码(比如自行安装 Debian 的用户所做的),任何用户账号都可以使用 “su -c
”
让任何命令以 root 运行。
PolicyKit 是在类 Unix 操作系统中控制整个系统权限的一个操作系统组件。
较新的 GUI 图形界面程序设计时便考虑到了不作为特权进程来运行。它们通过 PolicyKit 来和特权进程通信,从而执行管理操作。
在 Debian 系统中,PolicyKit 限制了属于 sudo
组的用户账号的这种操作。
参见 polkit
(8)。
对系统安全而言,尽可能的禁用服务程序,是一个好的主意。网络服务是危险的。有不使用的服务,不管是直接由后台守护进程(daemon)激活,还是通过super-server 程序激活,都被认为是安全风险。
许多程序,比如说 sshd
(8), 使用基于 PAM 的访问控制。也还有许多方式来限制访问一些服务端的程序。
配置文件: "/etc/default/program_name
"
后台守护进程(daemon)的 Systemd 服务单元配置
super-server 使用
"/etc/inetd.conf
"
TCP wrapper 使用
"/etc/hosts.deny
" 和 "/etc/hosts.allow
"
, tcpd
(8)
Sun RPC" 使用 /etc/rpc.conf
"
atd
(8) 使用 "/etc/at.allow
" 和
"/etc/at.deny
"
crontab
(1) 使用 "/etc/cron.allow
" 和
"/etc/cron.deny
"
参见 第 3.5 节 “系统管理”、第 4.5.1 节 “PAM 和 NSS 访问的配置文件” 和 第 5.7 节 “Netfilter 网络过滤框架”。
提示 | |
---|---|
如果你远程访问最新的 Debian
系统有问题,看下在" |
Linux 内核已经发展和支持在传统的 UNIX 实现里面没有的安全特征。
Linux 支持 扩展属性,扩展了传统的 UNIX 属性 (参见
xattr
(7))。
Linux 把传统的超级用户相关的特权分开到不同的单元,被称为
capabilities
(7),它能够独立的启用和禁用。从 2.2 版本内核开始,Capabilities
是一个线程独立的属性。
Linux Security Module (LSM) 安全模块框架 提供了一个多方面的安全检查机制,和新的内核扩展关联。例如:
这些扩展紧缩的权力模型比普通的类 Unix 安全模型策略更加严格,甚至 root 的权力也被限制。建议你阅读 kernel.org 上的 Linux 安全模块(LSM)框架文档。
Linux 的 namespaces
封装了一个全局系统资源到一个抽象的概念,全局系统资源在 namespace 内对进程可见,并且 namespace 有它们自己的全局资源隔离实例。
对其它进程全局资源的可见性的改变是,同一个 namespace 的成员可见,但是对非同一个 namespace 的其它进程不可见。从内核 5.6
版本起,有 8 种 namespaces (参见 namespaces
(7),
unshare
(1), nsenter
(1))。
在 Debian 11 Bullseye (2021) 中, Debian 使用 unified cgroup hierarchy(统一 cgroup 层级架构) (亦称为 cgroups-v2)。
namespaces 同 cgroups 一起来隔离它们的进程,允许资源控制的使用示例是:
沙盒环境。参见 第 7.7 节 “沙盒”。
Linux 容器,比如 Docker、 LXC。参见 第 9.11 节 “虚拟化系统”。
这些功能不能够通过 第 4.1 节 “一般的 Unix 认证” 实现。这些高级话题大部分超出了本介绍文档的范围。