☰
群晖NAS短密码与SSH免密登录及多机互信配置
2026/9/30 15:14:20 网站建设 项目流程

1. 先把需求拆开看:三件事其实是三个层次的权限问题

在群晖 NAS 上折腾登录这件事,几乎每个把 NAS 当小型服务器用的人都会经历一遍。我用群晖有些年头了,从 DSM 6 一路升到 DSM 7,机器也从单台白群扩到一台白群加两台自组机器,平时跑 Docker、备份、同步、定时脚本。最开始只是想少输几次密码,后来发现登录这件事牵扯出来的东西远比想象中多——用户数据库怎么存、家目录挂在哪个卷、sshd 的配置在哪、DSM 升级会不会把你的改动冲掉,这些全都要摸一遍。这篇就把群晖 linux 环境下设置短密码、配置免密登录、以及多台群晖之间互相免密这三件事,从头到尾讲清楚。

之所以把这三件事放一起讲,是因为它们本质上都是"认证"问题,只是切入的层次不同。短密码解决的是"人机交互"这一层——你在 DSM 网页或者 SSH 终端里输入密码时的体验;单机免密登录解决的是"密钥认证"这一层——用公私钥对替代密码;多台群晖免密解决的是"信任传递"这一层——把一台上已经建立好的信任关系复制到整个集群。

适合谁来读?如果你手上有一台群晖,想用 SSH 跑脚本、做自动化备份、写定时任务,但每次都要手打密码觉得很烦,这篇对你有用。如果你有两台以上 NAS,想要它们之间自动同步、互相拉数据,第四部分会讲得很细。如果你只是想了解群晖这套 Linux 系统的认证机制是怎么跑的,前三部分也够你看明白。需要提前说明的是,本文所有操作都在我自己的家庭内网环境里完成,涉及密码策略的调整只针对隔离实验环境,公网暴露的机器请务必按第五部分的安全清单处理。

1.1 为什么群晖上折腾登录比普通 Linux 更别扭

如果你在 Ubuntu 或者 Debian 上做过同样的事,会觉得群晖简直是反着来的。普通发行版上,passwd改密码、ssh-keygen生成密钥、改/etc/ssh/sshd_config,一整套流程很顺。但在群晖上,你会撞上三堵墙。

第一堵墙是DSM 的图形界面和底层 Linux 之间不是完全等价的。DSM 的"控制面板"是群晖自己写的一层管理界面,它写用户信息的方式和标准 Linux 的useradd/passwd并不一样。你在网页上改的密码,最终落到哪个文件、格式是什么,得自己去翻。第二堵墙是家目录的位置。群晖的用户家目录默认不在/home,而是在/volume1/homes/用户名或者/var/services/homes/用户名这种软链接路径下,SSH 的StrictModes检查对路径很敏感,搞不清楚就会一直报"权限不对"。第三堵墙是配置的持久性。DSM 升级是个"重装系统"式的过程,/etc下很多文件会被重置,你辛苦改好的sshd_config可能升个版本就没了。

注意:群晖的系统分区(/)是只读挂载后叠加可写层的设计,很多目录重启后会还原。所以任何持久化改动都要考虑"重启后还在不在"这个问题。

理解了这三堵墙,后面的操作就不会觉得莫名其妙了。我在第一次折腾的时候,光是一个免密登录就卡了两个晚上,最后发现是家目录权限的问题——明明chmod 600了,还是提示权限太开放,原因是上层的/volume1/homes目录组权限不对。这类坑后面会逐个讲。

1.2 三种需求的真实场景与优先级

先说清楚每种需求到底对应什么场景,免得你做完发现没用上。

短密码这个需求,通常出现在两类场景。一是内网实验机,比如你在群晖上开了虚拟机或者用 Docker 跑了个临时 Linux,密码只是用来挡一下误操作,不需要很强。二是频繁手动登录的老机器,密码太长每次敲很烦,尤其是在手机端 SSH 工具上打字很痛苦。但这里必须先划一条线:密码强度是安全边界,不是纯粹的体验问题。如果这台群晖有任何端口映射到公网、或者接了不信任的网络,短密码就是自找麻烦。我的做法是,只对明确不出内网的机器放宽,而且一定要配合密钥登录一起用。

单机免密登录是投入产出比最高的一环。你只要花十分钟配一次,之后所有ssh、scp、rsync、git操作都不用再输密码,定时脚本也能在无人值守的情况下跑起来。这个几乎没有任何取舍,只要你的私钥文件保管好,安全性反而比密码更高。

多台群晖互免密是上面那一步的放大版。当你有三台机器,每台都要能 SSH 到另外两台,手工配就是六条信任关系,还要处理不同的端口、不同的用户名。这时候就需要一套可复制的方法,最好能用一个命令批量铺开。热词里提到的 Ansible 免密登录其实就是这个思路的延伸——先用免密打通所有节点,剩下的批量操作交给 Ansible。

1.3 方案选型:哪些用官方界面,哪些只能进命令行

我的原则是:能不动底层的就不动底层,非动不可的时候一定要留退路。

需求推荐做法是否需要命令行持久性
放宽密码长度synouser --setpw是持久,写入系统数据库
放宽密码长度DSM 控制面板密码策略否持久,但仍有最低限制
单机免密登录密钥对 +authorized_keys是家目录在共享文件夹,重启还在
多机互免密统一密钥对 + 批量分发是同上
修改 sshd 端口编辑/etc/ssh/sshd_config是易被升级重置,需额外持久化
关闭密码登录sshd_config的PasswordAuthentication是同上

从表里能看出来,关键分歧在于改动落在哪个文件系统上。落在/volume1(也就是你的存储卷)上的东西是持久的,因为那是一个真实的共享文件夹,DSM 不会去动它。落在/etc、/root这些系统分区上的东西,就得考虑持久化问题。authorized_keys在家目录里,家目录在/volume1/homes下,所以是持久的——这也是为什么免密登录这么值得配,配一次管很久。而sshd_config在/etc下,需要额外手段保住,后面第 4 部分会讲。


2. 短密码设置:绕过 Web 界面复杂度校验的几种做法

2.1 群晖的密码到底存在哪

不管图形界面做得多花哨,Linux 的用户密码最终只有两个去处:/etc/passwd和/etc/shadow。/etc/passwd里密码字段是x占位符,真正的哈希在/etc/shadow,只有 root 能读。

$ sudo cat /etc/shadow | head -5 root:*:19000:0:99999:7::: admin:$6$xxxxx...:19000:0:99999:7:::

开头的$6$表示用的是 SHA-512 加密,这是标准 Linux 的做法。群晖在这一层上没有搞特殊,你看到的哈希格式和 Debian、龙蜥 OS 这些系统是一样的。

但要注意,群晖在上面又加了一层自己的用户数据库。这套数据库由synouser、synogroup这些专用命令管理,它和标准的/etc/passwd之间是同步关系。也就是说,你直接改/etc/passwd可能当时生效,但 DSM 的某些功能(比如共享文件夹权限分配、套件里的用户识别)读的是它自己那套库,两边会不一致。这就是为什么推荐用synouser而不是直接改文件的原因——它走的是官方接口,两边都会同步。

提示:动手前先备份。sudo cp /etc/shadow /etc/shadow.bak这一条命令能救你一次,尤其在你把 root 密码也搞乱的时候。

2.2 Web 界面的密码策略限制在哪一层

DSM 的控制面板里,用户与群组→高级设置→密码设置有一组策略:最短长度、是否要求大小写混合、是否要求数字、是否要求特殊字符、是否禁止用户名出现在密码里。这些选项看起来是"禁用就放宽了",但实际上有下限。

我实测下来,DSM 7 的网页界面即使把所有强度要求都关掉,最短长度硬下限大概在 6 位左右,而且某些看起来很弱的组合仍然会被拒。原因在于网页这层校验是前端 + 后端双重校验,后端会走一遍pwquality库的规则,而这个库的配置文件在/etc/security/pwquality.conf。

$ sudo cat /etc/security/pwquality.conf #minlen = 8 #dcredit = -1 #ucredit = -1 #ocredit = -1 #lcredit = -1

默认全是注释,说明走的是内置默认值。理论上你把minlen设成 5 就能放宽,但这个文件在系统分区上,改完能不能持久另说,而且网页端的校验未必读这个文件。所以走网页改密码策略这条路,能到 6 位左右就是极限了。想要更短,必须绕开网页,直接写密码库。

2.3 用 synouser 直接写密码数据库

群晖自带的synouser是管理用户的核心命令,用法如下:

# 查看所有用户 sudo synouser --getall # 查看指定用户信息 sudo synouser --get 你的用户名 # 设置密码(关键命令) sudo synouser --setpw 你的用户名 '你的短密码'

--setpw这个子命令是绕过网页强度校验最直接的方式,因为它直接调用群晖的用户管理接口,不经过网页那层前端校验。我拿一个 4 位密码测过,命令执行完没有任何报错,SSH 直接就能登进去。

$ sudo synouser --setpw testuser 1234

执行成功没有输出,这是符合 Unix 惯例的"沉默即成功"。如果你输入的用户不存在,它会报User not found。

这里有个细节值得说:--setpw之后的密码,DSM 网页登录同样生效,因为网页认证最终也是查这套库。所以你不只是在改 SSH 的密码,而是在改这个账号的全局密码。这一点务必想清楚——如果你的账号同时也是管理员账号,那就等于整个 NAS 的管理密码变短了。

注意:synouser需要 root 权限。先执行sudo -i切换到 root,或者每条命令都带sudo。在 DSM 7 上,默认的admin账号是被禁用的,你的管理账号是安装时自建的那个。

2.4 chpasswd 与直接改 shadow 的取舍

除了synouser,还有两条路可以走,但各有代价。

第一条是chpasswd,这是标准 Linux 工具,群晖上也带着:

# 批量设置密码,格式为 用户名:密码 echo "testuser:1234" | sudo chpasswd

它的优点是通用,写脚本的时候很顺手,一台机器上几十个用户也能批量改。缺点是它改的是/etc/shadow,不走群晖自己的数据库。结果就是:SSH 登录能用新密码,但 DSM 网页登录可能还是旧密码,或者出现两边不一致的诡异状态。我一般不推荐在群晖上用它,除非你确定这个账号只用于 SSH 脚本、不参与任何 DSM 的权限分配。

第二条是直接编辑/etc/shadow,手动替换哈希值:

# 生成哈希 openssl passwd -6 '1234' # 输出类似 $6$salt$hash... # 然后编辑 shadow 文件替换对应行 sudo vi /etc/shadow

这条路最"底层",也最容易出错。手抖打错一个字符,整个账号就登不进去了,而且你没法用passwd去修复(因为passwd也要账号能正常读)。除非你在做极端情况下的救援,否则不要走这条路。

三条路的对比:

方法命令影响范围推荐度
synousersynouser --setpw全局,SSH + DSM 网页推荐
chpasswdecho u:p | chpasswd仅/etc/shadow,可能不一致谨慎
直接改 shadow手编仅/etc/shadow,风险最高不推荐

2.5 短密码的适用边界与风险控制

讲完怎么做,得认真讲讲什么时候不该做。

短密码的风险不在于密码本身短,而在于暴力破解的成本被大幅拉低。一个 4 位纯数字密码,理论上 1 万种组合,自动化工具在内网环境下几秒钟就能撞完。所以放宽密码长度这个操作,只在满足以下全部条件时才建议做:这台机器完全在隔离的内网、没有任何端口映射到外网、SSH 端口没有暴露、而且你已经配好了密钥登录并且打算尽快关掉密码登录。

我的实际做法是这样:短密码只作为过渡手段。先用短密码把 SSH 登录打通,方便我一次性把公钥推上去;公钥推完、确认免密登录正常之后,立刻把PasswordAuthentication关掉。这个顺序很关键,千万别反过来——先关了密码登录再配密钥,万一密钥配错了,你就只能去物理接触机器或者进 DSM 的救援模式了。

另外一个技巧是,不要把短密码用在管理账号上。专门建一个低权限账号,比如叫deploy或者script,给它短密码、给它配密钥,只用来跑自动化任务。管理账号保持强密码,走网页登录。这样即使短密码被撞,损失也可控。

# 建专用账号(在 DSM 控制面板或命令行都行) sudo synouser --add scriptuser '短密码' 0 '' 0 # 参数依次是:用户名、密码、描述、邮箱、用户类型

建完之后,记得在 DSM 控制面板里给这个账号配置共享文件夹权限,只给它需要访问的那几个目录,别一股脑给管理员组。


3. SSH 免密登录:从密钥生成到 sshd 配置逐项过关

3.1 先搞清楚公钥认证的完整链路

很多人配免密登录是"照着教程敲命令",敲完不知道哪一步出问题就只能瞎试。所以这里先把链路讲清楚,后面排查的时候你才知道该看哪一环。

公钥认证的完整过程是这样的:客户端发起连接,声明要用publickey方式认证;服务端说"可以,你拿公钥来试试";客户端把公钥发给服务端;服务端拿着这个公钥,去目标用户的~/.ssh/authorized_keys文件里找,看有没有匹配的;找到了之后,服务端生成一段随机数据,用这个公钥加密,发给客户端;客户端用私钥解密这段数据,把结果发回去;服务端比对结果,一致就认证通过。

关键在于,私钥从头到尾没有离开过客户端。它只用来做一次解密证明"我确实持有对应的私钥",这是公钥认证比密码更安全的核心原因。

这个链路里有三个可能断的地方:一是authorized_keys里没有这条公钥(分发没成功);二是文件权限不对,服务端直接拒绝读取;三是sshd_config里把PubkeyAuthentication关了。记住这三个断点,排查就有方向了。

3.2 密钥类型怎么选:ed25519 还是 rsa 4096

生成密钥的命令是ssh-keygen,但-t参数选什么,很多人是随手抄的。这里给个明确的建议:能用 ed25519 就用 ed25519。

# 推荐:ed25519,速度快、密钥短、安全性足够 ssh-keygen -t ed25519 -C "nas-key-2024" -f ~/.ssh/id_ed25519_nas # 兼容老系统:rsa 4096 ssh-keygen -t rsa -b 4096 -C "nas-key-2024" -f ~/.ssh/id_rsa_nas

两个参数说明一下。-C是注释,会写进公钥末尾,作用是让你以后能认出这是哪台机器的密钥,建议写清楚用途和年份。-f是指定文件名,如果你有多套密钥(比如一套给自己用、一套给脚本用),这个参数必须加,否则会覆盖默认的~/.ssh/id_ed25519。

为什么不推荐 rsa?不是不安全,而是 ed25519 在同样安全强度下密钥长度只有 68 字符左右,rsa 4096 的公钥有 700 多字符。往authorized_keys里追加的时候,短公钥出错的概率低得多。而且 ed25519 的签名和验证速度更快,跑批量脚本的时候有感知。

但有一个例外:如果你的群晖版本很老(DSM 6.0 以前),可能不支持 ed25519。这时候用 rsa 4096 更稳。判断方法很简单,生成完 ed25519 密钥后试一次连接,连不上再换 rsa。

生成过程中会让你输 passphrase,就是给私钥文件本身再加一层密码。如果是给脚本用的密钥,直接回车留空;如果是你自己的日常密钥,建议设一个,然后用ssh-agent免去每次输入。

3.3 公钥分发:没有 ssh-copy-id 也能干

标准 Linux 上有ssh-copy-id一条命令搞定,但群晖上默认没有这个工具。你执行会发现command not found。所以得手动来。

最直观的方式是用管道:

cat ~/.ssh/id_ed25519_nas.pub | ssh 用户名@群晖IP "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

这条命令拆开看有四步,每一步都有意义。mkdir -p ~/.ssh是保证目录存在(-p让它已存在时不报错);chmod 700 ~/.ssh是设目录权限;cat >>是追加公钥(一定要用>>不能用>,否则会把已有的公钥全冲掉);最后chmod 600设文件权限。这四个动作缺一不可,权限不对的话连得上才怪。

如果你本地有ssh-copy-id(比如你从一台 Ubuntu 或者 Kali 上操作),也可以用它,但要指定密钥文件:

ssh-copy-id -i ~/.ssh/id_ed25519_nas.pub 用户名@群晖IP

如果连的是非默认端口:

ssh-copy-id -i ~/.ssh/id_ed25519_nas.pub -p 2222 用户名@群晖IP

分发完成后,先别关当前那个密码登录的会话,另开一个终端测试:

ssh -i ~/.ssh/id_ed25519_nas 用户名@群晖IP

能进去说明成功了。这一步很重要,因为如果免密失败你还有原来那个密码会话可以调试,不然就锁在门外了。

3.4 权限数字不对,前面全白干

这是群晖上最容易翻车的地方。SSH 服务端在认证前会做一遍StrictModes检查,它会沿着路径往上查,确认没有任何一个环节是"组或其他用户可写"的。检查失败的典型表现是:ssh -v输出里出现Authentication refused: bad ownership or modes for file。

需要满足的权限是这样的:

路径权限属主
家目录~755 或 700用户自己
~/.ssh700用户自己
~/.ssh/authorized_keys600用户自己
~/.ssh/config(可选)600用户自己
$ chmod 700 ~/.ssh $ chmod 600 ~/.ssh/authorized_keys $ chmod 755 ~

群晖上的特殊之处在于,家目录不在/home,而是软链接到/volume1/homes/用户名。软链接上层目录的权限也会被检查。所以你要看看/volume1/homes这一层是不是权限过宽:

$ ls -ld /volume1/homes drwxrwxrwx 2 root root 4096 ...

如果是777,那就是问题了。正常应该是770或者755。改法:

sudo chmod 755 /volume1/homes

注意:改/volume1/homes的权限会影响所有用户的家目录访问,动手前确认一下当前权限,最好记下来,出问题能改回去。这个目录通常是群晖自动管理的,一般不该手动改,如果你的已经是 755 或 770,就别动它。

还有一种情况是用户的家目录服务没有启用。DSM 7 里,控制面板→用户与群组→高级→用户家目录,有一个"启用用户家目录服务"的勾选项。如果没勾,用户就没有/volume1/homes/用户名这个目录,SSH 登录后会落到根目录,~/.ssh也就不存在了。这时候你写的~/.ssh/authorized_keys会跑到一个奇怪的位置,看起来像是"公钥写了但不生效"。

3.5 sshd_config 的关键几行

群晖的 SSH 配置文件在/etc/ssh/sshd_config,和标准 Linux 一样。免密登录相关的关键项有这几个:

PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys PasswordAuthentication yes ChallengeResponseAuthentication no UsePAM yes StrictModes yes

逐条说。PubkeyAuthentication yes是公钥认证的总开关,群晖默认是开的,但值得确认一下。AuthorizedKeysFile定义了去哪找公钥文件,默认值就是这个,一般不用改——除非你把公钥放在别的地方,比如为了方便管理统一放到/etc/ssh/authorized_keys/%u,那就得改这里。PasswordAuthentication决定是否允许密码登录,配好密钥之前保持 yes,配好之后改成 no。UsePAM yes是走 PAM 认证框架,群晖默认开着,关掉可能导致一些账号认证异常。StrictModes yes就是前面说的权限检查开关,不建议关,关了等于自废武功,虽然能解决"权限不对"的报错,但也让攻击者可以篡改你的公钥文件。

改完配置要重启 SSH 服务:

sudo synoservice --restart sshd # 或者 sudo systemctl restart sshd

DSM 7 用的是 systemd(或者说兼容层),systemctl能用。DSM 6 用synoservice更稳。

改配置的顺序非常关键,我给你一个不会把自己锁死的流程:

  1. 保持当前密码会话不要关
  2. 新开终端,测试密钥登录是否成功
  3. 成功后,修改sshd_config,把PasswordAuthentication改成no
  4. 重启 sshd
  5. 再新开一个终端测试密钥登录
  6. 确认没问题,才关掉最开始那个密码会话

如果第 5 步失败了,你还有第 6 步之前的所有会话可以回滚。


4. 多台群晖互免密:拓扑、分发与持久化

4.1 先画拓扑:中心辐射还是全互联

两台机器互信好办,三台以上就要想清楚拓扑了。这里有两种常见结构。

中心辐射型,也叫星型。选一台机器当"跳板机"或者"控制节点",只有它持有私钥,其他所有机器只存它的公钥。这样的好处是密钥管理简单——只有一份私钥需要保护;批量操作的时候也简单,从控制节点往外推就行。缺点是控制节点成了单点,而且它连别人方便,别人连它需要另外配。

全互联型。每台机器都生成自己的密钥对,然后把所有机器的公钥都铺到所有机器上。好处是任意两台之间都能直接连,没有中心依赖。缺点是 N 台机器就有 N 份私钥和 N×N 条信任关系,管理起来是指数级的麻烦。

我的实际选择是中心辐射型 + 共享密钥:生成一对密钥,所有机器都用这同一对公私钥,同时把公钥铺到所有机器。这样产生的是"全互联"的能力,但只维护一份密钥。下面重点讲这个方案。

提示:共享同一对密钥的全互联方案,安全性上确实不如每机独立密钥——一台机器被攻破,等于所有机器的私钥都泄露了。所以这只适合内网、自己完全掌控的环境。如果机器分布在不同的信任域,请老老实实每台独立生成。

4.2 用同一对密钥铺满所有节点

假设你有三台群晖,IP 分别是192.168.1.10、192.168.1.11、192.168.1.12,统一用scriptuser这个账号。

第一步,在任意一台机器(或者你自己的电脑)上生成密钥:

ssh-keygen -t ed25519 -C "nas-cluster-2024" -f ~/.ssh/id_nas_cluster -N ""

-N ""表示不设 passphrase,方便脚本自动化。生成后得到id_nas_cluster(私钥)和id_nas_cluster.pub(公钥)两个文件。

第二步,写个循环把公钥推到所有机器:

#!/bin/bash KEY=~/.ssh/id_nas_cluster.pub USER=scriptuser HOSTS="192.168.1.10 192.168.1.11 192.168.1.12" for H in $HOSTS; do echo ">>> 正在处理 $H" cat $KEY | ssh $USER@$H "mkdir -p ~/.ssh && chmod 700 ~/.ssh && \ grep -qxF '$(cat $KEY)' ~/.ssh/authorized_keys 2>/dev/null || \ cat >> ~/.ssh/authorized_keys && \ chmod 600 ~/.ssh/authorized_keys" done

这段脚本里有个去重逻辑值得说。grep -qxF '公钥内容'是检查公钥是否已经存在,-x是整行匹配,-F是把内容当纯字符串(公钥里有特殊字符,不用-F会出错),-q是静默模式只看返回值。如果已经存在就不重复追加,避免你反复跑脚本导致authorized_keys里堆一长串重复内容。这个细节在手工操作时无所谓,但脚本会被反复执行,必须考虑幂等性。

如果你要推的机器很多,还可以分两步:先在一次密码会话里把公钥推上去,之后所有的连接都用密钥。这样第二遍跑脚本就不会再要密码了。

4.3 ssh config 让命令短下来

三个 IP 每次都要敲一遍太累,用~/.ssh/config给它们起别名:

Host nas1 HostName 192.168.1.10 User scriptuser Port 22 IdentityFile ~/.ssh/id_nas_cluster ServerAliveInterval 60 ServerAliveCountMax 3 Host nas2 HostName 192.168.1.11 User scriptuser Port 2222 IdentityFile ~/.ssh/id_nas_cluster Host nas3 HostName 192.168.1.12 User scriptuser Port 22 IdentityFile ~/.ssh/id_nas_cluster

配置完之后,ssh nas1就等于ssh -i ~/.ssh/id_nas_cluster -p 22 scriptuser@192.168.1.10。scp nas1:/volume1/data/file ./也能直接写。

ServerAliveInterval 60和ServerAliveCountMax 3这两个是心跳保活,每 60 秒发一次探测,连续 3 次没响应才断开。跑长时间同步任务的时候很需要,否则网络抖一下连接就断了,任务白跑。

配置文件本身的权限也要设对:

chmod 600 ~/.ssh/config

另外有个细节值得注意:如果你的机器有的用 22 端口、有的改了端口(比如2222),别名里一定要写清楚Port,不然连到 22 上会直接超时,报错信息看起来像是"主机不通",容易误判。

4.4 家目录、homes 服务和权限的三个坑

多机场景下,前面第 3 部分讲过的权限问题会被放大,因为你要在每台机器上都检查一遍。这里把最容易踩的整理出来。

第一个坑是群晖的 SSH 默认端口。DSM 的 SSH 服务在控制面板→终端机和 SNMP→终端机里开启,默认 22。如果你改过端口,ssh-copy-id和手动推送都要带上-p参数,config里也要写对。我见过有人改完端口忘了,公钥推到了另一个服务的端口上,结果当然是失败的。

第二个坑是共享文件夹权限和家目录权限是两套东西。群晖里,一个用户可以访问/volume1/data这个共享文件夹(在控制面板里授权),但未必有可用的家目录(家目录服务没启用)。而authorized_keys必须放在家目录里。所以光有共享文件夹权限是不够的,一定要确认家目录服务开启,并且~/.ssh真的存在。

第三个坑是homes目录本身的属主。群晖上,/volume1/homes这个目录的属主是root,组是homes,权限通常是770。这个配置是对的,不要改。但如果你手动mkdir建过用户目录,属主可能变成 root,那这个用户的 SSH 就会失败。检查方法:

$ ls -ld /volume1/homes/scriptuser drwxr-xr-x 5 scriptuser users 4096 ...

属主必须是用户自己。如果不对:

sudo chown -R scriptuser:users /volume1/homes/scriptuser

注意:chown -R是递归改属主,一定要确认路径写对,写错会把整个卷的权限搞乱。跑之前可以先ls一遍确认目标路径存在。

4.5 DSM 升级后配置被重置怎么办

这个问题我在 DSM 6 升 DSM 7 的时候碰到过。sshd_config里的自定义改动(比如端口、PasswordAuthentication)在升级后被还原成默认值。原因前面说过,/etc在系统分区,升级过程会重刷。

解决办法有两个。

方法一是写个开机任务。DSM 控制面板里有任务计划,可以建一个"触发的任务",在"开机"时执行一段脚本。脚本内容就是把你需要的sshd_config改动重新写一遍然后重启服务:

#!/bin/bash CONF=/etc/ssh/sshd_config # 关闭密码登录 sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' $CONF # 修改端口 sed -i 's/^#\?Port .*/Port 2222/' $CONF synoservice --restart sshd

把这个脚本存到/volume1/scripts/fix_ssh.sh(放存储卷上,持久),然后在任务计划里指向它,用户选root。

方法二是把配置文件放到持久分区,用软链接指过去。这个更彻底:

# 把配置移到存储卷 sudo cp /etc/ssh/sshd_config /volume1/scripts/sshd_config sudo rm /etc/ssh/sshd_config sudo ln -s /volume1/scripts/sshd_config /etc/ssh/sshd_config

这样即使系统分区被重置,/etc/ssh/sshd_config这个软链接指向的还是存储卷上的真实文件。不过要注意,软链接本身在系统分区,升级后可能被清掉,所以这个方案也不是 100% 保险,配合方法一一起用最稳。

免密登录本身反而不用担心。authorized_keys在家目录里,家目录在/volume1/homes,这是存储卷上的真实文件,升级不会动它。所以 DSM 升级后你可能会发现"密码登录被打开了、端口变回 22 了,但密钥登录还是好的"。这时候用密钥进去,重新修一遍sshd_config就行。


5. 常见问题与排查技巧实录

5.1 认证失败排查速查表

这部分是我踩坑踩出来的,按出现频率排序。

现象最可能原因排查命令
一直提示输密码公钥没推到,或推到了错误的家目录cat ~/.ssh/authorized_keys
Permission denied (publickey)权限过宽,StrictModes 拒绝ls -ld ~ ~/.ssh ~/.ssh/authorized_keys
Connection refusedSSH 服务没开或端口不对检查控制面板终端机设置
Connection timed out网络不通或防火墙拦截ping+ 检查群晖防火墙
连上了但立刻断开家目录不存在或不可写ls -ld ~
认证成功但cd ~报错家目录服务未启用控制面板用户家目录设置
有的机器能连有的不能端口不一致,config 没写 Portssh -v看实际端口
Host key verification failed重装过系统,指纹变了ssh-keygen -R 主机名

关于最后一条多说两句。known_hosts里存的是你之前连接过的主机指纹,如果对端重装过系统或者换了密钥,指纹就变了,SSH 会拒绝连接并警告可能有中间人攻击。这时候如果你确认对端是自己重装的,用ssh-keygen -R 192.168.1.10删掉旧记录再连就行。

5.2 ssh -v 输出怎么读

排查 SSH 问题,-v是最有用的工具,需要更详细就-vv或者-vvv。

ssh -vvv -i ~/.ssh/id_nas_cluster scriptuser@192.168.1.10

输出会很长,但你只需要盯几个关键行。看到Offering public key: ...说明客户端把公钥发出去了;接着看服务端的回应,Server accepts key说明公钥匹配上了;如果出现Authentication refused: bad ownership or modes,那就是权限问题,直接去查authorized_keys的权限;如果出现Permission denied (publickey,password)并且前面没有任何Offering public key的行,说明客户端根本没找到对应的私钥,检查-i参数。

有个小技巧是用grep过滤关键信息:

ssh -vvv scriptuser@192.168.1.10 2>&1 | grep -E "Offering|accept|refused|denied|Authentications"

5.3 日志在哪

客户端排查完了,服务端的日志也得看。群晖的 SSH 日志在/var/log/auth.log:

sudo tail -f /var/log/auth.log

边在这个终端tail -f,边在另一个终端尝试连接,能看到实时的认证记录。失败的尝试会连着几行,包含来源 IP 和失败原因。群晖的日志格式和标准 Linux 一致,Accepted publickey for scriptuser这种就是成功记录。

如果/var/log/auth.log不存在或者没内容,看看/var/log/messages,DSM 版本不同日志落点会有差异。另外 DSM 的日志中心图形界面里也能看到"连接"相关的日志,但不如命令行细。

5.4 和 ansible 批量操作串起来

免密登录配好之后,最爽的用法是接 Ansible。热词里提到的"龙蜥 os8 ansible 免密登录",思路是一样的——Ansible 本身就依赖 SSH 免密,它不需要在目标机上装 agent,全靠 SSH 推送模块。

一个最简单的 inventory 文件:

[nas] nas1 ansible_host=192.168.1.10 ansible_user=scriptuser ansible_port=22 nas2 ansible_host=192.168.1.11 ansible_user=scriptuser ansible_port=2222 nas3 ansible_host=192.168.1.12 ansible_user=scriptuser ansible_port=22 [nas:vars] ansible_ssh_private_key_file=~/.ssh/id_nas_cluster ansible_python_interpreter=/usr/bin/python3

然后就可以批量执行命令了:

ansible nas -m shell -a "df -h | grep volume1" ansible nas -m ping

ansible_python_interpreter这一行在群晖上很关键。群晖自带的 Python 路径和标准发行版不一样,不指定的话 Ansible 会去找/usr/bin/python然后失败。用which python3确认一下实际路径再填。

如果 Ansible 报Failed to connect to the host via ssh,八成还是免密本身有问题,先用ssh nas1手工验证一遍,确认能免密进去了再跑 Ansible。

5.5 最后的安全加固清单

配完这些,别急着收工,花五分钟过一遍这个清单。

第一,确认私钥文件的权限。私钥文件应该是600,而且不要放在共享文件夹里被同步来同步去。

chmod 600 ~/.ssh/id_nas_cluster

第二,确认短密码账号是低权限的。用synouser --get 用户名看它属于哪些组,不该有的组都去掉。别让它进administrators。

第三,公网暴露的机器维持强密码 + 关掉密码登录。如果 NAS 有任何形式的外网访问,PasswordAuthentication no是必须的,短密码绝对不能用在上面。

第四,定期清理authorized_keys。你可以手工打开看一眼:

cat ~/.ssh/authorized_keys | wc -l

如果行数和你实际使用的密钥数量对不上,多出来的就要查清楚来源。每一行末尾的注释(-C参数写的内容)就是帮你在做这件事时认人的。

第五,登录失败次数要关注。如果你看到auth.log里大量来自陌生 IP 的失败记录,说明有扫描器在撞你的 SSH。这时候要么换端口(能挡掉九成自动化扫描),要么上fail2ban之类的工具(群晖上可以通过第三方套件装)。

我个人在实际操作中的体会是,这些配置里最值得花时间的其实是日志。前面那些步骤,一次配好之后基本不会再碰,但日志是你以后出问题时唯一能告诉你"到底发生了什么"的东西。我现在的习惯是每次改完 SSH 相关配置,都开一个终端tail -f /var/log/auth.log,然后立刻测试一次连接,看着认证成功的日志滚出来,心里才踏实。这样改错了马上能发现,不会等到某天定时任务莫名其妙失败才回头查。

还有一个小技巧分享:把这三台机器的配置差异(IP、端口、用户名)单独写成一个表格存在 notes 里,别只留在ssh config里。因为ssh config在客户端,换台电脑就没了,而机器本身的信息是不变的。我换过两次主力电脑,每次都靠这份表格在十分钟内把环境重建起来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询