news 2026/10/1 2:11:25

NIS与LDAP怎么选?内网几十台Linux主机统一账号的轻量级实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
NIS与LDAP怎么选?内网几十台Linux主机统一账号的轻量级实践

前阵子被一个朋友拉去收拾他们实验室的测试集群。二十多台CentOS 7的机器,每台/etc/passwd里都躺着好几个重复创建的账号,密码改一次要跑遍所有机器,离职同事的账号更是没人敢动。我第一反应是上LDAP,但坐下来理了理需求,发现用户量不到五十人、机器全在一个二层内网,也没有复杂的组织结构需求。这种情况下,用NIS(Network Information Service)反而是最省力的方案:十几分钟把服务端搭起来,客户端装几个包、改三个配置文件就能认账号,复杂度远低于LDAP那套目录树和证书体系。

这篇就按我这次实际操作的过程来写,从服务端搭建到客户端接入,再到我踩过的几个坑,最后补几个生产环境里的习惯。适合的人群很明确:内网里有几十台同构Linux机器需要统一账号、但不想为此搭一套LDAP/AD体系的运维同学。

1. 动手之前:NIS到底解决什么问题,边界在哪里

1.1 看清NIS的职责范围

NIS能干的事,说白了就是把/etc/passwd、/etc/group、/etc/hosts、/etc/netgroup这类“主机本地信息”集中到一个服务器上。客户端在需要用户名、密码、组、主机名映射的时候,会按 NSS(Name Service Switch,名称服务切换)的配置去问NIS服务器,再把拿到的结果当成本地文件一样使用。它解决的是“用户名密码在哪里查”的问题,而不是“用户的家目录在哪里”。

很多人混淆了这一点,以为配好NIS后用户登录就能直接看到自己的/home。实际上NIS只负责认证和账户属性,home目录还得靠NFS + autofs按需挂载,这俩是分开的两个服务。我这次部署的最后一步就是补了NFS共享和autofs,否则用户登录进来了会得到一个新的空目录,之前的工作文件全都不在,体验会很差。

1.2 NIS域名和DNS域名是两个东西

这是新手最先踩的坑。NIS域名长得很像DNS域名,比如nis.local,但它的作用只是给NIS map分组,和DNS解析没有半毛钱关系。一台机器可以同时有DNS域名client01.lab.example.com和NIS域名nis.local,两者互不影响。

在CentOS 7上查看NIS域名的命令是nisdomainname,临时设置用nisdomainname nis.local。注意不要拿hostname -d的输出来当NIS域名用。我这次部署踩过一次:客户端ypbind启动后一直bind不上,后来才发现是启动服务时NIS域名根本没设置成功,绑定报文里带的domain和服务器上的domain不一致,直接被拒绝。

1.3 适用场景与不适用的场景

我个人的判断标准很简单:

  • 适合:所有机器都在受信内网、账号数量不大(几百以内)、管理成本敏感、希望快速统一的场景。
  • 不适合:机器跨公网、账号数量几千上万、有复杂组织结构和权限模型的场景,这种还是老老实实上LDAP/AD。

另外NIS的密码哈希在局域网里是明文传输的,攻击者只要在链路上抓到map数据,就能离线破解密码。所以它只能用在完全可信的内网环境,这是我在任何场合都会提醒的一句话。

2. 服务端搭建:从装包到生成可查询的map

服务端我用的是一台双网卡物理机,内网IP192.168.1.10,主机名nis-server。客户端用192.168.1.20,主机名client01。NIS域名统一设为nis.local。整个服务端搭建过程,核心就四步:规划环境、装包、写配置、生成map。

2.1 环境规划与初始化

动手之前先把/etc/hosts写好,这一步非常容易被忽略。ypinit -m在初始化map的时候会检查当前主机名是否能在本地解析,如果/etc/hosts里没有,就会报类似self is not in /etc/hosts的错误,我当时第一次见到这个报错还以为是主机名没设好,折腾了半天才发现只是hosts文件缺了一行。

192.168.1.10 nis-server 192.168.1.20 client01

然后是防火墙和SELinux。测试环境我直接关掉了firewalld,如果是在生产环境,建议放行rpcbind和NIS相关端口,不要为了省事全关。SELinux方面,CentOS 7默认enforcing状态对NIS的服务进程卡得比较严,我这边实验环境直接setenforce 0。如果你不想完全关闭,可以放行对应的SELinux布尔值,允许NIS相关服务运行,建议在装完包之后先确认服务能起来,再慢慢收紧策略。

2.2 安装软件包与启动顺序

服务端需要两个包:ypserv提供NIS服务端程序,yp-tools提供ypcat、ypwhich、yppasswd这些命令行工具。

yum install -y ypserv yp-tools

启动顺序有个讲究:一定要先启动rpcbind,再启动ypserv。因为NIS基于RPC协议,ypserv启动时要向rpcbind注册自己的端口,rpcbind没起来,ypserv就算进程起来了也无法对外服务。

systemctl start rpcbind systemctl enable rpcbind

在启动ypserv之前,先确认NIS域名已经设置好。我用的是:

nisdomainname nis.local

这条命令只对当前会话生效,重启就丢了,所以还要写进/etc/sysconfig/network:

NISDOMAIN="nis.local"

CentOS 7里如果机器启用了network.service,启动时会读取这个变量并设置NIS域名。如果不确定自己的环境读不读,最稳妥的办法是写一个systemd单元或直接在/etc/rc.d/rc.local里补一行nisdomainname nis.local,保证开机后域名一定存在。域名没设置就启动ypserv,服务虽然能起来,但客户端来bind的时候会直接失败,这是高频坑。

确认域名没问题后,启动余下两个服务:

systemctl start ypserv systemctl start yppasswdd systemctl enable ypserv systemctl enable yppasswdd

yppasswdd是负责客户端改密的服务,很多教程只提ypserv不提这个,结果用户登录没问题,一改密码就报错,建议从一开始就一起装上、一起启动。

2.3 配置 ypserv.conf 控制访问范围

ypserv的主配置文件是/etc/ypserv.conf,默认内容其实已经能跑,但出于安全和可维护性考虑,我一般会改成下面这样:

dns: no files: 30 trust: none 192.168.1.0/255.255.255.0 : * : * : none

逐行解释一下。dns: no表示ypserv不要通过DNS反查客户端主机名,直接按IP处理,避免在DNS不通时拖慢响应甚至拒绝服务。files: 30是对以普通文本文件方式存放的map做30秒缓存,几秒到几十秒之间都可以,太短会频繁读盘,太长又会让map改动生效变慢。trust: none表示不信任外部RPC调用者,客户端必须按后面规则逐条匹配。

最后一行是核心规则,格式是“主机 : 域名 : map : 安全级别”。这里写的是允许整个192.168.1.0/24网段访问所有domain下的所有map,安全级别为none。安全级别有三档:none表示不校验客户端源端口,最宽松;port要求客户端源端口必须是1024以内的特权端口;deny直接拒绝。如果你对安全比较敏感,可以把客户端网段安全级别改成port,但这要求所有客户端的ypbind都是以root身份启动的,正常情况下都能满足,算是一个低成本的收紧手段。

配置改完记得重启ypserv:

systemctl restart ypserv

2.4 编辑Makefile并生成map

NIS把要发布的用户、组、主机映射做成一个个“map”文件,放在/var/yp/<域名>/目录下。生成map的执行文件是/var/yp/Makefile,发布哪些内容、过滤哪些账号,都在这份文件里控制。

先看关键的过滤项。默认情况下Makefile会把系统用户也一起发布出去,这会导致客户端里出现一堆bin、daemon、adm这类系统账号,非常危险。我强烈建议设置:

MINUID=1000 MINGID=1000

意思是只发布UID/GID大于等于1000的用户和组,把系统账号全部隔离在NIS之外。

再看合并项。默认生成的passwd map可能不带密码哈希,导致客户端能看到用户名但登录时验不了密码。关键在Makefile里的这两个开关:

MERGE_PASSWD=true MERGE_GROUP=true

设置为true后,生成map时会把/etc/shadow里的密码哈希合并进passwd map,客户端才能用密码认证。

然后是all行,它决定了哪些map会被生成。我的建议是保留passwd group hosts这几个常用项就够了,其他像services、protocols、rpc这些在全行业务里基本用不到,发出去反而增加暴露面。你可以按需改:

all: passwd group hosts

改完配置后,开始生成map:

make -C /var/yp

如果一切正常,在/var/yp/nis.local/目录下就能看到passwd.byname、passwd.byuid、group.byname等文件。这里有一点要提醒:每次手工修改服务器的/etc/passwd、/etc/shadow、/etc/group后,都需要重新跑一遍make -C /var/yp,改动才会被同步到map里,客户端查到的才是新数据。

2.5 服务端自我检查

客户端接入之前,先在服务端上验证一下地图是否正常。用rpcinfo确认RPC注册,用ypwhich确认NIS服务能响应,再用ypcat查看map里的实际内容。

rpcinfo -p localhost | grep ypserv ypwhich -d nis.local localhost ypcat -d nis.local passwd

ypcat passwd的输出里应该能看到你准备发布的用户列表,每个条目格式和/etc/passwd一致,密码字段位如果显示x或一个哈希串,同时系统里shadow内容也正常,说明map生成没问题。如果输出为空,多半是Makefile里过滤条件设得太狠,或者域名不对,回到上一步检查。

3. 客户端接入:改对三个文件,账号才能真正用起来

客户端配置相比服务端要简单,但最容易出问题的恰恰是那些“看起来很简单”的文件。整个过程分三步:装包、改配置、启动验证。

3.1 安装客户端软件并设置NIS域名

客户端需要ypbind(负责绑定NIS服务器)和yp-tools(提供查询工具):

yum install -y ypbind yp-tools

然后同样设置NIS域名:

nisdomainname nis.local

写入/etc/sysconfig/network:

NISDOMAIN="nis.local"

这一步不能省。如果客户端启动ypbind时NIS域名为空,ypbind会以空域名去广播查找,结果大概率是找不到服务器。很多“客户端绑不上”的问题,根源就是域名没设置。

3.2 三个关键配置文件的正确写法

第一个是/etc/yp.conf,告诉ypbind应该去找哪台NIS服务器。有两种写法,我习惯用指定服务器方式,避免广播在网络环境复杂时找不到目标:

domain nis.local server 192.168.1.10

第二个是/etc/nsswitch.conf,决定系统在查询用户名、密码、组时走什么数据源。核心改动这几行:

passwd: files nis shadow: files nis group: files nis hosts: files nis dns

这里的顺序非常关键。我把files放在前面,NIS放在后面,意思是先查本地文件,本地没有再去查NIS。如果你把nis放在最前面,一旦NIS服务器宕机,客户端的登录、getent查询都会因为超时变得极其缓慢,包括本地用户登录也受影响。反之,服务器宕机时本地用户不受影响,只是NIS用户暂时登不上。

第三个是PAM配置。CentOS 7的登录认证由/etc/pam.d/system-auth控制,默认会把密码验证交给pam_unix.so,而pam_unix.so内部调用的就是NSS。也就是说,只要nsswitch.conf里passwd和shadow行都加上了nis,一般不需要再额外改PAM文件。但我见过有人只改了passwd行、忘改shadow行,结果getent passwd能看到NIS用户,su登录却一直密码错误。所以检查时要确认shadow行也包含nis,这比passwd行还容易被遗漏。

3.3 启动ypbind并验证完整链路

配置写好后,启动客户端绑定服务:

systemctl start ypbind systemctl enable ypbind

验证分三步走,从底层到上层逐渐确认问题。

先看绑定是否成功:

ypwhich

正常情况下会输出NIS服务器的完整主机名,比如nis-server。如果输出为空或者报错,说明域名、网络或服务端配置有问题。

再看map能否拉到数据:

ypcat passwd

输出里应该能看到服务端定义的那些用户。如果这里能看到数据,说明网络、域名、RPC这几个环节都没问题。

最后验证NSS链路,也就是系统是否真的能识别NIS用户:

getent passwd <NIS用户名>

如果这个命令能输出类似testuser:*:3000:3000::/home/testuser:/bin/bash的条目,说明系统已经可以正常查询到NIS用户,可以尝试用ssh <NIS用户名>@<客户端IP>或su - <NIS用户名>做真实验证了。

到这里,账号认证已经有了。但就像开头说的,用户的家目录不在NIS职责范围内,登录进来的用户会得到一个空的/home/testuser,而且文件都存在本机。真正要做得“像一个统一系统”,还得配NFS共享和autofs:

  • 服务端在/etc/exports里导出/home目录,允许内网客户端访问。
  • 客户端安装autofs,在/etc/auto.master里加一行/home /etc/auto.home,再到/etc/auto.home里写* -rw,sync 192.168.1.10:/home/&。
  • 这样用户访问/home/testuser时,系统才会自动去NFS服务器挂载对应用户目录。NFS的配置不算复杂,这里的重点是理解“NIS管账号、NFS管目录、autofs管挂载时机”这三个角色的分工。

4. 排错实录:三个高频坑的完整排查链路

这部分写我是怎么一步步定位问题的,而不是直接给答案。按我这次部署遇到的顺序,把过程完整拆给你看。

4.1 坑一:客户端绑定失败,日志一直报超时

现象:客户端执行systemctl start ypbind后卡了一段时间才起来,ypwhich没有输出,journalctl -u ypbind里反复出现类似timeout、no server的日志。

排查过程:我一开始先怀疑网络,但ping 192.168.1.10是通的,排除了链路层问题。接着在服务端执行rpcinfo -p,看到ypserv的RPC注册信息也在,说明服务端正常。然后在客户端手动执行ypbind -debug,前台进程打印了完整的绑定过程,日志显示它带着一个空域名或错误域名去发广播,服务器端自然没回应。

根因:客户端的NIS域名没有设置成功。我检查时发现/etc/sysconfig/network里虽然写了NISDOMAIN="nis.local",但当前shell里的nisdomainname输出为空,说明写文件之后没有重新加载,而ypbind启动时读的是当前内核里的NIS域名,不是文件内容。

修复:在当前会话执行nisdomainname nis.local,然后再启动ypbind。重启后为了让文件生效,我另外确认了network.service读到了该配置。如果你用的环境不读这个文件,就在/etc/rc.d/rc.local里补上这条命令。

规律:遇到绑定类问题,先对比三处域名是否一致——服务端的nisdomainname、客户端的nisdomainname、/etc/yp.conf里的domain。这三处只要有一处不同,绑定就失败。这是我处理NIS问题时第一个检查的动作。

4.2 坑二:ypcat能查到数据,getent查不到用户

现象:客户端ypcat passwd输出里有NIS用户,但getent passwd nisuser没结果,ssh登录也提示用户不存在。

排查过程:这一步很迷惑,因为问题不在网络也不在服务端,而在客户端自身。我先确认了ypbind正常绑定,又用ypmatch nisuser passwd手动查询map,能查到。这就说明NIS链路完全正常,问题一定出在NSS配置上。打开/etc/nsswitch.conf检查,发现passwd行已经有nis,但shadow行只写了files,没有加nis。这里有个容易忽略的因果关系:getent passwd只依赖passwd行,所以能查到;但登录时PAM要验证密码,会去看shadow数据源,找不到NIS用户的shadow记录就直接拒绝。

根因:nsswitch.conf里shadow行缺失nis,导致密码验证阶段查不到NIS用户。

修复:把shadow行补成files nis,重启ypbind(或刷新NSS缓存目录),再执行getent passwd nisuser就正常了。

延伸排查:如果改了shadow行还是不行,第二嫌疑是SELinux。用ausearch -m avc -ts recent查一下有没有AVC拦截记录,有的话按提示放行相应布尔值。我这次没遇到SELinux拦截,但在网上帮人看问题时见过不少次,属于必须排查的一环。

4.3 坑三:客户端改密要么报错,要么改了不生效

现象:用户在客户端执行yppasswd,有的机器报RPC: Can't contact yppasswdd,有的机器改完提示成功,但其他客户端上旧密码仍然能用、新密码登不进去。

排查过程:先处理报错。yppasswd命令工作时,客户端会把请求发给服务端的yppasswdd服务,如果没装或没启动,就会报contact不到。到服务端执行systemctl status yppasswdd,发现确实没启动,启动后报错问题解决。

再处理“改完不生效”。在服务端查看/etc/shadow,发现密码字段确实已被更新,说明yppasswd请求到达成功。但去客户端ypcat passwd,发现map里的密码哈希还是旧的。这时候我才意识到,yppasswdd只负责更新服务端的本地文件,不一定自动触发map重建,需要手动执行make -C /var/yp刷新。

根因:map没有重新生成,客户端读到的还是旧数据。

修复:在服务端执行make -C /var/yp,之后在客户端再次ypcat passwd,就能看到map里密码哈希已经变化,新密码可以正常登录。

经验:手动修改服务端/etc/passwd、/etc/group或用户改密后,都养成一个习惯:顺手执行make -C /var/yp。把这条写进你的变更脚本里,就不会出现这种“改了等于白改”的情况。

5. 使用习惯与安全建议:生产环境里我的一些经验

5.1 UID段位规划要提前想好

NIS上线后,所有客户端的UID解释都会统一,因此账号的UID规划一定要事先定好。我这边约定的规则是:系统用户0-999,本地服务账号1000-1999,NIS统一用户2000以上。在服务端Makefile里把MINUID=2000、MINGID=2000设置好,既不会发布系统账号,也不会和客户端的本地服务账号撞车。这个习惯看似简单,但在实际出过事故——曾有一台机器的本地用户UID为1001,NIS用户也用了1001,登录后ls -l看文件所有权完全错乱。

5.2 map重建的自动化与备份

如果你经常在服务端批量建用户,建议把make -C /var/yp写成一个脚本,或者在发布账户的流程里固定带上这一步。另外/var/yp/<域名>/目录下的map文件虽然可以用make重新生成,但也别忽略/etc/passwd、/etc/shadow、/etc/group这几个源文件的备份。map坏了可以重建,源文件丢了才是真的麻烦。我通常会在每周的备份任务里额外打包一份/etc/passwd /etc/shadow /etc/group /etc/ypserv.conf /var/yp/Makefile,成本很低,恢复效率却很高。

5.3 安全加固的具体做法

NIS明文特性决定了它只适合受信内网。如果要在生产环境长期使用,我会做四件事:

第一,在/etc/ypserv.conf里严格限制允许访问的网段,不要让整个办公网都能查到NIS map;第二,只发布必要的map,我最常用的是passwd group hosts三个,其他默认map一律不生成,减少信息暴露面;第三,确保防火墙只放开必要的端口,生产环境不要图省事直接停firewalld;第四,如果集群规模超过五十台,或者有多个网段需要跨网络同步,就不要再用单点NIS服务器了,考虑加NIS slave或者直接迁移到FreeIPA。

这些是我在多次NIS部署中沉淀下来的做法。很多教程只写到ypcat passwd出来就结束,但实际运维中真正考验人的,往往是你对UID规划、map刷新机制和权限边界的理解。把NIS当成一个“内网专用的统一账号服务器”来用,控制在合适的规模和信任边界里,它的简单和直接反而能省下不少维护成本。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 2:09:57

Edge主页被劫持?四层控制机制深度解析与精准还原

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 2:09:25

SMU-ACM冬训周报:第一周基础算法训练与实战复盘

SMU-ACM 的 2026 冬训周报来了&#xff0c;这是第一期。写这个系列的目的很直接&#xff1a;把每周训练的安排、选题思路、代码实现、踩过的坑都摊开来讲&#xff0c;给队里同学一个复盘参考&#xff0c;也顺便给正在入门 ACM 的选手们一些可以抄作业的路线。这一周我们主要解决…

作者头像 李华