今天遇到了之前没遇到过的问题(倒不如说之前没遇到才是真的玄学),.ssh/authorized_keys 明明存在,但却没法免密登录。在一番搜索之后,我发现问题的关键在于权限问题。之前对权限的了解较浅,知道的也就 777、644 这几个数字,平时用到的也就只有 chmod +x,正好借这个机会好好学习一下。
文件和目录的权限在 《Beginning Unix》 中位于第 67 页。简单来说,权限可以分为四种:
r:读取权限(read)w: 写入权限(write)x: 执行权限(execute)-: 无权限(deny)
通过 ls -l,我们可以很方便的看到文件当前的权限配置:

值得注意的是,第一个字符代表的是“目录”的类型,有如下三种形式:
- d: 目录
- l: 符号链接
- -: 非目录(一般来说就是文件)

而之后的 9 个字符,则代表了三种不同用户对该文件/目录的权限。2-4 位是当前用户(user,简写为 u)的权限,5-7 位是当前用户组(group,简写为 g) 的权限,而 8-10 位则是其他用户(all,简写为 a)的权限。
权限的概念对于文件和目录而已也不尽相同。对文件而已,
r就是读取,w就是写入,x就是执行;而对目录而言,r是允许读取目录及子目录中的内容,w是允许向目录和子目录中写入,而x则是允许进入该目录。
现在我们知道了权限的字面表达方式,接下来就是修改了。
chmod 命令提供了三种修改权限的方式,其按照字符划分如下:
+: 增加权限,使用方式为chmod [用户组简写]+[权限] [文件],如chmod u+x ./run.sh-: 取消权限,使用方式为chmod [用户组简写]-[权限] [文件],如chmod -x ./run.sh(这里省略了 u)=: 设置权限,即覆盖当前权限设置,使用方式为chmod [用户组简写]=[权限] 文件,如chmod u=rwx ./run.sh- 以上三者可以同时使用,通过逗号连接。这里用原书中的例子好了:
chmod o+wx,u-x,g=r-x testfile
按照上文描述的方式,我们可以很方便(?)直观(!)地修改文件和目录的权限。
等等,方便?你不觉得这么长一段很费事吗?
于是,就有了数字表示法。其实数字表示法和上文的表示方法有简单的一一对应关系,而这种表示的本质——将其加和,实际上就是位运算:
0:-1:x2:w4:r
于是我们就知道了,700 代表的实际上是 u=rwx,g=---,a=---,而 600 则是 u=rw-。
回到最开始的问题:为什么 sshd 要求我们的 authorized_keys 必须为 600 权限呢?
我的猜想是这样的:密钥,就算是公钥,也不应该被其他未经许可的用户读取(当然 root 除外);而公钥也是不需要执行的。由此,我们便需要将 g 和 a 的权限全部取消,并且设置当前用户 u 也只能 rw。而对于 sshd 而言,通常是以 root 权限运行的(观察 /etc/systemd/system/multi-user.target.wants/ssh.service,可以发现其并没有规定用户,而不规定用户的情况下默认即为 root),因此可以直接读取内容。
当然了,这只是我的猜测。由于本人 C 语言8行,没在源码里找到佐证。
ま、それでは(