
在Linux的权限体系里判断一个账户是否属于超级用户看的是UID而不是用户名。这意味着你完全可以在系统里放两个、三个甚至更多的UID 0账户它们的用户名各不相同但权限和root一模一样。我第一次碰到这种需求是在一套共管服务器上——运维组三个人都要root权限又坚持每人一个账户方便审计于是/etc/passwd里就同时出现了root、techops和ops2三个UID同样是0的账户。紧接着问题就来了这三个账户每次登录都要输密码实在麻烦得怎么实现免密这篇文章就围绕这个场景展开先讲清楚UID 0的权限判定机制再给创建多个UID 0账户的安全做法然后重点拆解SSH公钥免密登录的完整配置链路最后补充sudo、su在这些账户下的隐藏行为以及免密之后必须跟上的审计与加固手段。适合系统管理员、运维同学也适合刚接触Linux权限模型的新手——只要你手上有服务器要管这篇就能用得上。1. UID 0的权限本质用户名只是标签内核认的是编号1.1 一次权限判定看机制为什么用户名不同、权限却相同很多新手容易把“用户名”和“用户权限”当成一回事实际上在Linux内核里用户这个概念从始至终就是一个数字编号——UID。当你执行ls、mv、cat这些命令时内核做的权限判断是基于进程的有效用户IDeuid而不是一个字符串。比如一个进程的euid是0内核就认为它是超级用户几乎所有权限检查都可以跳过只有当需要映射名字给人看时才会去翻/etc/passwd把UID翻译成root、techops这样的易读名称。所以从机制上讲只要用户A的UID是0用户B的UID也是0那么这两个账户在内核眼中就是同一个东西。用户名只是给人类看的标签系统本身并不在乎它是root还是别的什么。这也是为什么“多个UID为0的用户”能够并存而且权限完全相同——它们干脆就是同一种身份的不同别名。/etc/passwd每一行的格式是用户名:x:UID:GID:描述:家目录:登录Shell。把任意一个用户的UID字段改成0这个用户立刻就获得超级用户权限。这个机制很强大也很容易被滥用所以后面所有安全讨论都绕不开它。1.2 免密与UID 0是两条线PAM认证和文件权限别搞混这里必须搞清楚一个容易被误解的点UID等于0不意味着登录的时候就不需要密码。登录过程的密码校验发生在PAM认证层。当你通过SSH或者本机终端登录系统会调用PAM模块去验证密码、检查账户状态、确认是否允许该用户登录。这一层跟你是不是UID 0没有直接关系——哪怕是根用户如果PAM策略要求密码照样得输。所谓的“免密”本质上是用其他认证方式替代密码。最典型的就是SSH公钥认证你有一把私钥服务器上存放对应的公钥SSH服务通过签名挑战验证“持有私钥的人就是授权用户”这个过程完全不涉及密码。所以“多个UID为0的用户如何实现root的免密”这个问题的核心不是修改权限模型而是在保留这些账户超级用户能力的同时为它们配置一套可靠的免密认证链路。理清这条线之后后面所有配置就有了方向我们要做的事是在SSH/PAM这个认证层面上让这些UID 0账户可以“凭密钥而非凭密码”进入系统进入系统之后它们本身就拥有root权限不需要额外提权。2. 创建多个UID 0账户三种做法、两种坑2.1 正规添加useradd -o -u 0 的参数解读如果系统里还没有第二个UID 0账户第一件事就是把它创建出来。很多发行版的useradd默认不允许重复UID所以必须加上-o参数允许使用非唯一UID再配合-u 0指定UID。useradd -o -u 0 -g 0 -d /root -s /bin/bash techops passwd techops这个命令创建了一个名为techops、UID为0、主组为root组GID也是0、家目录为/root、登录shell为bash的用户。执行id techops会看到uid0(root) gid0(root) groups0(root)注意-g 0很重要。如果不指定useradd会默认创建一个与用户名同名的组GID可能是1002之类的结果就是虽然UID是0但新文件的主组不是root组后续有些场景会别扭。家目录这块我见过有人直接指向/root也有人专门创建独立家目录useradd -o -u 0 -g 0 -m -d /home/techops -s /bin/bash techops两种我都用过。独立家目录的好处是多个UID 0账户的.ssh/authorized_keys互不干扰审计时一眼就能分清谁是谁的公钥缺点是家目录不在默认位置第一次登录时bash可能找不到一些启动脚本。如果团队人多我更推荐独立家目录后面讲SSH配置时你会体会到优势。2.2 偷懒改/etc/passwd什么时候能改、改完要做什么另一种做法是直接编辑/etc/passwd把某个普通用户的UID从1000改成0usermod -o -u 0 techops如果不带-ousermod会拒绝因为UID 0已经被root占用了。这个命令本质上就是修改/etc/passwd里的UID字段效果和手动编辑一样但更安全一点不会在编辑途中出错导致文件损坏。直接改UID有一个隐藏的坑这个用户家目录下原本的文件属主记录的UID还是1000现在系统里找不到UID 1000对应的账户了于是ls -l会显示一堆数字ID。这些文件的实际访问权限也乱了——因为内核判断属主是按UID来的文件属主是1000所有者信息跟当前UID 0账户对不上很多文件可能变得不可编辑或不可删除。解决办法是把家目录下的文件全部归到新UID下chown -R 0:0 /home/techops所以在生产环境里如果不是临时应急别干这种“拿现有用户改UID”的事直接用useradd建新账户干净得多。改成UID 0之前这个账户可能正常上了几个月班这一改文件归属、日志记录、审计线索全乱套。2.3 独立家目录与登录通道收敛创建完多个UID 0账户之后紧接着要思考一个安全问题系统里有多少个“门”可以让这些账户进来。我见过一个真实的翻车案例。某项目为了省事给两个UID 0账户都设了家目录/root还都用了一个共享的.ssh目录。后来其中一个同事想禁用另一个同事的免密直接删了/root/.ssh/authorized_keys里的一行——结果手一抖把整个文件删了两个人的免密同时失效当天下午所有自动化脚本全部报错。这就是共享家目录的代价。如果从一开始就采用独立家目录每个人的密钥文件就是/home/techops/.ssh/authorized_keys和/home/ops2/.ssh/authorized_keys互不干扰谁出问题就只影响谁。用户名不同、UID相同、家目录严格隔离这个组合才是干净的多超级用户布局。另外还要收敛登录通道。UID 0账户越多被攻破的入口就越多。建议把这些账户尽量限制为仅允许SSH密钥登录把密码认证、控制台登录等通路收窄后面第3章会给出具体的sshd_config写法。3. SSH公钥免密登录的完整落地链路3.1 密钥生成与公钥分发第一次还是要动手免密的第一步是生成密钥对。现在基本都用ed25519算法性能好、密钥短、安全性足够ssh-keygen -t ed25519 -a 100 -C techops-key-2024-C是注释建议写上账户名和用途方便日后在authorized_keys里识别。生成后私钥默认在~/.ssh/id_ed25519公钥在~/.ssh/id_ed25519.pub。公钥分发最省事的是用ssh-copy-idssh-copy-id -i ~/.ssh/id_ed25519.pub techopsserver它会自动把公钥追加到服务器上techops的authorized_keys同时修正目录权限。不过第一次执行时还是要输入一次密码毕竟服务器上还没有你的公钥这是没办法绕过的第一步。如果你用的是OpenSSH 8.4以上版本也可以直接用ssh-keygen -Y之类的签名/分发方式不过日常运维里ssh-copy-id已经够用。如果用的是共享家目录/root公钥分发时要格外小心别覆盖了别人的authorized_keys。我的建议是永远用追加方式cat ~/.ssh/id_ed25519.pub | ssh techopsserver cat ~/.ssh/authorized_keys而不是直接重定向。这个习惯能救你很多次。3.2 StrictModes下的权限清点家目录、.ssh、authorized_keys逐个查密钥配好了很多人的免密却登录失败十次里有八次是权限问题。OpenSSH默认开启StrictModes它会严格检查涉及认证的文件和目录权限任何一项过宽都会拒绝认证。需要满足的条件如下表所示检查项要求示例家目录属主为登录用户且不能是组或其他用户可写drwxr-xr-x~/.ssh目录属主为登录用户权限700drwx------authorized_keys属主为登录用户权限600或更小-rw-------所有父目录不能有组或其他用户可写权限/home属主为root具体到UID 0账户还有两个特殊情况。第一如果多个账户共享/root作为家目录StrictModes检查家目录时只要符合上面的要求就放行但你在审计时很难分辨authorized_keys里的哪把公钥属于谁第二如果你单独创建了/home/techops务必检查/home目录本身的权限不能因为操作失误把/home设成777。遇到权限拒绝时最快的排查办法是看服务端日志tail -f /var/log/secure一般会有类似Authentication refused: bad ownership or modes for directory /root这样的明确提示照着提示改权限即可。3.3 sshd_config开关组合与PermitRootLogin的边界密钥和权限都就绪后还需要在sshd_config里开门。以下是常用的配置组合PubkeyAuthentication yes PasswordAuthentication no ChallengeResponseAuthentication no PermitRootLogin prohibit-password前三行的意思是允许公钥认证关闭密码认证和密码交互式认证。这样UID 0账户只能通过密钥登录杜绝了暴力破解密码的路径。第四行PermitRootLogin prohibit-password很多人会误以为它限制了所有UID 0账户其实不是。OpenSSH实现这个检查时判断的是用户名是否等于“root”这个字符串而不是UID是否为0。也就是说这条规则只对名为root的账户生效其他UID 0账户比如techops并不会被它拦住。这意味着如果你把PasswordAuthentication设为no却没有对techops这类账户单独做限制它们实际上仍然允许用密码登录。想要统一收敛推荐用Match块Match User techops,ops2 PasswordAuthentication no AuthenticationMethods publickey或者把所有UID 0账户加入同一个组然后按组匹配Match Group superadmin PasswordAuthentication no AuthenticationMethods publickey这比逐个用户配置更集中也更好维护。改完配置后务必先检查语法再重启服务sshd -t systemctl restart sshd3.4 实测排查两次被拒登录的经验复盘这里分享两个我实际踩过的坑供参考。第一个坑出在authorized_keys文件权限。某次我把公钥写进了新账户的authorized_keys检查过大方向却忽略了一个细节——这个UID 0账户的家目录虽然在/home下但/home/techops的属主确实是我刚建的techops可从/home到/techops中間的路径因为之前手工改过权限home目录本身变成了组可写。StrictModes可不管中间路径有多少层只要有一层权限过宽就直接拒绝。当时日志里报的是bad ownership or modes for directory /home我盯着.ssh目录看了半天最后才发现问题出在父目录权限上。第二个坑出在AuthorizedKeysFile共享。多UID 0账户共用一个家目录时我试着用AuthorizedKeysFile /etc/ssh/authorized_keys/%u把每个账户的密钥文件拆开。这个指令的本意是好的——每个用户对应一个独立文件比如techops对应/etc/ssh/authorized_keys/techops。但实际配置时我忘了给/etc/ssh/authorized_keys目录设置正确的属主和权限sshd直接拒绝读取所有密钥。改成root属主、700权限后就好了。如果你也走这个方案记得目录权限这块别漏。4. sudo和su的免密行为UID 0下的隐藏逻辑4.1 sudo为什么几乎不问UID 0用户要密码有人可能会问这些账户都已经是UID 0了还要配置sudo吗这里有个大家容易忽略的机制sudo对UID为0的用户默认就不要求密码。原因是sudo在认证阶段会先判断调用者身份如果检测到调用者的euid是0就直接认为已经具备最高权限不需要再验证密码。你在root账户下执行sudo -i或者sudo whoami通常不会看到密码提示就是这个道理。所以对于多个UID 0账户不用配任何sudoers规则它们运行sudo天然就是免密的。这一点对排查问题也很重要。你新加了一个UID 0账户发现它执行sudo完全不用输密码不用惊讶这是系统设计的行为。但如果某一天你发现某个UID 0账户突然要密码了那基本可以断定它不是真正的UID 0或者有一层额外的PAM策略在拦。4.2 显式配置sudoers NOPASSWD的场景与坑既然默认就免密那为什么还要写sudoers主要目的是把策略显性化以及覆盖一些特殊场景。比如你希望明确记录“techops可以在所有主机上以任何用户身份执行任何命令且不需要密码”就可以在/etc/sudoers里写techops ALL(ALL) NOPASSWD: ALL这种写法在审计和文档化上有价值——规则写清楚了后来的人不必猜系统到底怎么放行的。另一个场景是UID 0账户通过sudo切换到非root用户且不想被密码打断techops ALL(nginx) NOPASSWD: /usr/sbin/nginx这条规则允许techops无需密码以nginx身份执行nginx管理命令。注意sudoers的匹配顺序后面的规则会覆盖前面所以如果你同时配了techops ALL(ALL) ALL和techops ALL(ALL) NOPASSWD: ALL最终生效的是后者。验证配置用的是visudovisudo -c一个常见的坑是手动编辑sudoers文件时写错语法比如漏了等号、写了错误的命令路径保存后sudo直接不可用。一旦发生系统里所有sudo操作都会报错而你可能已经没有root shell了。所以永远用visudo编辑它会做语法检查哪怕语法错了也会问你是否继续保存。真要手滑了先用pkexec visudo或者从root shell里修复。4.3 su到root的认证边界与wheel组的意外拦截还有一个容易忽略的点是su命令。普通用户su到root需要输入root密码但如果是UID 0账户执行su - rootsu程序检测到调用者本来就是超级用户不会要求密码。这实际上意味着任何一个UID 0账户都可以无密码切换到名为root的账户。不过这里藏着一个PAM的坑。很多发行版为了限制su权限启用了pam_wheel模块只允许wheel组成员可以su到root。如果你没给techops这个UID 0账户加wheel组那么即使它UID是0执行su - root时也可能被PAM策略拒绝——因为pam_wheel检查的是调用者的组信息而不是UID。这个反差很容易让人困惑我就在一台CentOS服务器上碰到过明明id显示uid0su却提示密码错误。解决办法是把这些UID 0账户加入wheel组usermod -aG wheel techops或者在PAM配置里调整pam_wheel的规则。就我的经验而言既然UID已经是0这个账户原本就拥有全部权限再卡su反而会造成运维操作的混乱不如统一放行并靠审计日志追踪。5. 免密后的安全审计与加固清单5.1 一条命令盘点所有UID 0账户权限越大责任越大。多个UID 0账户上线后第一条安全底线就是定期进行账号盘点确认系统里到底哪些账户拥有超级用户权。最常用的检查命令就一行awk -F: $30{print $1} /etc/passwd输出结果会是root techops ops2同时再检查一下这些账户的登录Shell和shadow状态getent passwd | awk -F: $30{print $1, $7} passwd -S root techops ops2如果有账户的Shell被设成/sbin/nologin或/bin/false说明它被禁用登录了如果passwd -S显示LKlocked也说明口令被锁定。这些状态要跟业务需求对应上别出现一个早就退化的UID 0账户还静静躺在系统里哪天成了别人的入口。5.2 日志、密钥与账户生命周期便利不等于放任免密登录解决的是效率问题但它不能替代审计。服务器上必须留存登录与提权相关的日志关键时刻能回答“谁在什么时间做了什么”。重点关注的日志文件有这些日志覆盖内容/var/log/secure或/var/log/auth.logSSH登录、sudo调用、su切换/var/log/sudo.logsudo命令明细如配置了syslog/var/log/wtmp、/var/log/lastlog登录时间与终端信息查看最近登录记录用last查看当前在线用户用who。对于UID 0账户的操作建议配置sudo和su都写日志并在日志服务器上做集中归档。免密可以省掉输密码的功夫但审计记录一条都不能少。密钥生命周期管理同样重要。一条建议每个UID 0账户用一把独立私钥私钥上设置passphrase把passphrase交给ssh-agent缓存。这样日常登录免密私钥泄露时还有一道防线。密钥如果怀疑泄露立刻从authorized_keys里删除对应公钥并生成新密钥对更新。5.3 我推荐的最终配置模板把整篇文章落到一个可参考的模板上。假设有三个人需要超级用户权限我的推荐做法是# 1. 分别创建独立账户UID 0独立家目录 useradd -o -u 0 -g 0 -m -d /home/admin_li -s /bin/bash admin_li useradd -o -u 0 -g 0 -m -d /home/admin_wang -s /bin/bash admin_wang passwd admin_li passwd admin_wang # 2. 各账户独立生成密钥公钥放到各自家目录 ssh-keygen -t ed25519 -C admin_li-key ssh-copy-id -i ~/.ssh/id_ed25519.pub admin_liserver # 3. sshd_config统一收敛 PubkeyAuthentication yes PasswordAuthentication no ChallengeResponseAuthentication no Match Group superadmin PasswordAuthentication no AuthenticationMethods publickey # 4. 把账户加入统一管理组 usermod -aG wheel admin_li usermod -aG superadmin admin_li这套模板兼顾了三件事每个账户身份独立、登录必须凭密钥、操作过程有日志可查。UID为0带来的超管能力没有打折扣但认证链路和审计链路都收紧了。最后再分享一个小习惯我每周都会在服务器上跑一遍awk -F: $30{print $1} /etc/passwd把结果和上周对比。系统里多了一个UID 0账户比多了一个普通用户严重得多这种变化必须第一时间发现。免密是给运维提效的工具但多UID 0账户的形态本身高强度特权任何新增、删除、密钥变更都值得用“变更单”级别的态度来对待。