如何在 Linux 中配置基于密钥认证的 SSH
什么是基于 SSH 密钥的认证?
众所周知,Secure Shell,又称 SSH,是允许你通过无安全网络(例如 Internet)和远程系统之间安全访问/通信的加密网络协议。无论何时使用 SSH 在无安全网络上发送数据,它都会在源系统上自动地被加密,并且在目的系统上解密。SSH 提供了四种加密方式,基于密码认证,基于密钥认证,基于主机认证和键盘认证。最常用的认证方式是基于密码认证和基于密钥认证。
在基于密码认证中,你需要的仅仅是远程系统上用户的密码。如果你知道远程用户的密码,你可以使用 ssh user@remote-system-name
访问各自的系统。另一方面,在基于密钥认证中,为了通过 SSH 通信,你需要生成 SSH 密钥对,并且为远程系统上传 SSH 公钥。每个 SSH 密钥对由私钥与公钥组成。私钥应该保存在客户系统上,公钥应该上传给远程系统。你不应该将私钥透露给任何人。希望你已经对 SSH 和它的认证方式有了基本的概念。
这篇教程,我们将讨论如何在 Linux 上配置基于密钥认证的 SSH。
在 Linux 上配置基于密钥认证的 SSH
为方便演示,我将使用 Arch Linux 为本地系统,Ubuntu 18.04 LTS 为远程系统。
本地系统详情:
- OS: Arch Linux Desktop
- IP address: 192.168.225.37/24
远程系统详情:
- OS: Ubuntu 18.04 LTS Server
- IP address: 192.168.225.22/24
本地系统配置
就像我之前所说,在基于密钥认证的方法中,想要通过 SSH 访问远程系统,需要将公钥上传到远程系统。公钥通常会被保存在远程系统的一个 ~/.ssh/authorized_keys
文件中。
注意事项:不要使用 root 用户生成密钥对,这样只有 root 用户才可以使用。使用普通用户创建密钥对。
现在,让我们在本地系统上创建一个 SSH 密钥对。只需要在客户端系统上运行下面的命令。
<span class="pln">$ </span><span class="kwd">ssh</span><span class="pun">-</span><span class="pln">keygen</span>
上面的命令将会创建一个 2048 位的 RSA 密钥对。你需要输入两次密码。更重要的是,记住你的密码。后面将会用到它。
样例输出:
<span class="typ">Generating</span><span class="kwd">public</span><span class="pun">/</span><span class="kwd">private</span><span class="pln"> rsa key pair</span><span class="pun">.</span>
<span class="typ">Enter</span><span class="kwd">file</span><span class="kwd">in</span><span class="pln"> which to save the key </span><span class="pun">(</span><span class="str">/home/</span><span class="pln">sk</span><span class="pun">/.</span><span class="kwd">ssh</span><span class="pun">/</span><span class="pln">id_rsa</span><span class="pun">):</span>
<span class="typ">Enter</span><span class="pln"> passphrase </span><span class="pun">(</span><span class="kwd">empty</span><span class="kwd">for</span><span class="kwd">no</span><span class="pln"> passphrase</span><span class="pun">):</span>
<span class="typ">Enter</span><span class="pln"> same passphrase again</span><span class="pun">:</span>
<span class="typ">Your</span><span class="pln"> identification has been saved </span><span class="kwd">in</span><span class="pun">/</span><span class="pln">home</span><span class="pun">/</span><span class="pln">sk</span><span class="pun">/.</span><span class="kwd">ssh</span><span class="pun">/</span><span class="pln">id_rsa</span><span class="pun">.</span>
<span class="typ">Your</span><span class="kwd">public</span><span class="pln"> key has been saved </span><span class="kwd">in</span><span class="pun">/</span><span class="pln">home</span><span class="pun">/</span><span class="pln">sk</span><span class="pun">/.</span><span class="kwd">ssh</span><span class="pun">/</span><span class="pln">id_rsa</span><span class="pun">.</span><span class="pln">pub</span><span class="pun">.</span>
<span class="typ">The</span><span class="pln"> key fingerprint </span><span class="kwd">is</span><span class="pun">:</span>
<span class="pln">SHA256</span><span class="pun">:</span><span class="pln">wYOgvdkBgMFydTMCUI3qZaUxvjs</span><span class="pun">+</span><span class="pln">p2287Tn4uaZ5KyE </span><span class="pun">[</span><span class="pln">email </span><span class="kwd">protected</span><span class="pun">]</span>
<span class="typ">The</span><span class="pln"> key</span><span class="str">'s randomart image is:</span>
<span class="str">+---[RSA 2048]----+</span>
<span class="str">|+=+*= + |</span>
<span class="str">|o.o=.* = |</span>
<span class="str">|.oo * o + |</span>
<span class="str">|. = + . o |</span>
<span class="str">|. o + . S |</span>
<span class="str">| . E . |</span>
<span class="str">| + o |</span>
<span class="str">| +.*o+o |</span>
<span class="str">| .o*=OO+ |</span>
<span class="str">+----[SHA256]-----+</span>
如果你已经创建了密钥对,你将看到以下信息。输入 y
就会覆盖已存在的密钥。
<span class="str">/home/</span><span class="pln">username</span><span class="pun">/.</span><span class="kwd">ssh</span><span class="pun">/</span><span class="pln">id_rsa already exists</span><span class="pun">.</span>
<span class="typ">Overwrite</span><span class="pun">(</span><span class="pln">y</span><span class="pun">/</span><span class="pln">n</span><span class="pun">)?</span>
请注意密码是可选的。如果你输入了密码,那么每次通过 SSH 访问远程系统时都要求输入密码,除非你使用了 SSH 代理保存了密码。如果你不想要密码(虽然不安全),简单地敲两次回车。不过,我建议你使用密码。从安全的角度来看,使用无密码的 ssh 密钥对不是什么好主意。这种方式应该限定在特殊的情况下使用,例如,没有用户介入的服务访问远程系统。(例如,用 rsync
远程备份……)
如果你已经在个人文件 ~/.ssh/id_rsa
中有了无密码的密钥,但想要更新为带密码的密钥。使用下面的命令:
<span class="pln">$ </span><span class="kwd">ssh</span><span class="pun">-</span><span class="pln">keygen </span><span class="pun">-</span><span class="pln">p </span><span class="pun">-</span><span class="pln">f </span><span class="pun">~</span><span class="str">/.ssh/</span><span class="pln">id_rsa</span>
样例输出:
<span class="typ">Enter</span><span class="kwd">new</span><span class="pln"> passphrase </span><span class="pun">(</span><span class="kwd">empty</span><span class="kwd">for</span><span class="kwd">no</span><span class="pln"> passphrase</span><span class="pun">):</span>
<span class="typ">Enter</span><span class="pln"> same passphrase again</span><span class="pun">:</span>
<span class="typ">Your</span><span class="pln"> identification has been saved </span><span class="kwd">with</span><span class="pln"> the </span><span class="kwd">new</span><span class="pln"> passphrase</span><span class="pun">.</span>
现在,我们已经在本地系统上创建了密钥对。接下来,使用下面的命令将 SSH 公钥拷贝到你的远程 SSH 服务端上。
<span class="pln">$ </span><span class="kwd">ssh</span><span class="pun">-</span><span class="pln">copy</span><span class="pun">-</span><span class="kwd">id</span><span class="pln"> sk@192</span><span class="pun">.</span><span class="lit">168.225</span><span class="pun">.</span><span class="lit">22</span>
在这里,我把本地(Arch Linux)系统上的公钥拷贝到了远程系统(Ubuntu 18.04 LTS)上。从技术上讲,上面的命令会把本地系统 ~/.ssh/id_rsa.pub
文件中的内容拷贝到远程系统 ~/.ssh/authorized_keys
中。明白了吗?非常棒。
输入 yes
来继续连接你的远程 SSH 服务端。接着,输入远程系统用户 sk
的密码。
<span class="str">/usr/</span><span class="pln">bin</span><span class="pun">/</span><span class="kwd">ssh</span><span class="pun">-</span><span class="pln">copy</span><span class="pun">-</span><span class="kwd">id</span><span class="pun">:</span><span class="pln"> INFO</span><span class="pun">:</span><span class="pln"> attempting to log </span><span class="kwd">in</span><span class="kwd">with</span><span class="pln"> the </span><span class="kwd">new</span><span class="pln"> key</span><span class="pun">(</span><span class="pln">s</span><span class="pun">),</span><span class="pln"> to filter out any that are already installed</span>
<span class="pun">/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">/</span><span class="kwd">ssh</span><span class="pun">-</span><span class="pln">copy</span><span class="pun">-</span><span class="kwd">id</span><span class="pun">:</span><span class="pln"> INFO</span><span class="pun">:</span><span class="lit">1</span><span class="pln"> key</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln"> remain to be installed </span><span class="pun">--</span><span class="kwd">if</span><span class="pln"> you are prompted now it </span><span class="kwd">is</span><span class="pln"> to install the </span><span class="kwd">new</span><span class="pln"> keys</span>
<span class="pln">sk@192</span><span class="pun">.</span><span class="lit">168.225</span><span class="pun">.</span><span class="lit">22</span><span class="str">'s password:</span>
<span class="str">Number of key(s) added: 1</span>
<span class="str">Now try logging into the machine, with: "ssh '</span><span class="pln">sk@192</span><span class="pun">.</span><span class="lit">168.225</span><span class="pun">.</span><span class="lit">22</span><span class="str">'"</span>
<span class="str">and check to make sure that only the key(s) you wanted were added.</span>
如果你已经拷贝了密钥,但想要替换为新的密码,使用 -f
选项覆盖已有的密钥。
<span class="pln">$ </span><span class="kwd">ssh</span><span class="pun">-</span><span class="pln">copy</span><span class="pun">-</span><span class="kwd">id</span><span class="pun">-</span><span class="pln">f sk@192</span><span class="pun">.</span><span class="lit">168.225</span><span class="pun">.</span><span class="lit">22</span>
我们现在已经成功地将本地系统的 SSH 公钥添加进了远程系统。现在,让我们在远程系统上完全禁用掉基于密码认证的方式。因为我们已经配置了密钥认证,因此不再需要密码认证了。
在远程系统上禁用基于密码认证的 SSH
你需要在 root 用户或者 sudo
执行下面的命令。
禁用基于密码的认证,你需要在远程系统的终端里编辑 /etc/ssh/sshd_config
配置文件:
<span class="pln">$ </span><span class="kwd">sudo</span><span class="kwd">vi</span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="kwd">ssh</span><span class="pun">/</span><span class="pln">sshd_config</span>
找到下面这一行,去掉注释然后将值设为 no
:
<span class="typ">PasswordAuthentication</span><span class="kwd">no</span>
重启 ssh 服务让它生效。
<span class="pln">$ </span><span class="kwd">sudo</span><span class="kwd">systemctl</span><span class="pln"> restart </span><span class="kwd">sshd</span>
从本地系统访问远程系统
在本地系统上使用命令 SSH 你的远程服务端:
<span class="pln">$ </span><span class="kwd">ssh</span><span class="pln"> sk@192</span><span class="pun">.</span><span class="lit">168.225</span><span class="pun">.</span><span class="lit">22</span>
输入密码。
样例输出:
<span class="typ">Enter</span><span class="pln"> passphrase </span><span class="kwd">for</span><span class="pln"> key </span><span class="str">'/home/sk/.ssh/id_rsa'</span><span class="pun">:</span>
<span class="typ">Last</span><span class="kwd">login</span><span class="pun">:</span><span class="typ">Mon</span><span class="typ">Jul</span><span class="lit">9</span><span class="lit">09</span><span class="pun">:</span><span class="lit">59</span><span class="pun">:</span><span class="lit">51</span><span class="lit">2018</span><span class="kwd">from</span><span class="lit">192.168</span><span class="pun">.</span><span class="lit">225.37</span>
<span class="pln">sk@ubuntuserver</span><span class="pun">:~</span><span class="pln">$</span>
现在,你就能 SSH 你的远程系统了。如你所见,我们已经使用之前 ssh-keygen
创建的密码登录进了远程系统的账户,而不是使用当前账户实际的密码。
如果你试图从其它客户端系统 ssh(远程系统),你将会得到这条错误信息。比如,我试图通过命令从 CentOS SSH 访问 Ubuntu 系统:
样例输出:
<span class="typ">The</span><span class="pln"> authenticity of host </span><span class="str">'192.168.225.22 (192.168.225.22)'</span><span class="pln"> can</span><span class="str">'t be established.</span>
<span class="str">ECDSA key fingerprint is 67:fc:69:b7:d4:4d:fd:6e:38:44:a8:2f:08:ed:f4:21.</span>
<span class="str">Are you sure you want to continue connecting (yes/no)? yes</span>
<span class="str">Warning: Permanently added '</span><span class="lit">192.168</span><span class="pun">.</span><span class="lit">225.22</span><span class="str">' (ECDSA) to the list of known hosts.</span>
<span class="str">Permission denied (publickey).</span>
如你所见,除了 CentOS(LCTT 译注:根据上文,这里应该是 Arch)系统外,我不能通过其它任何系统 SSH 访问我的远程系统 Ubuntu 18.04。
为 SSH 服务端添加更多客户端系统的密钥
这点非常重要。就像我说过的那样,除非你配置过(在之前的例子中,是 Ubuntu),否则你不能通过 SSH 访问到远程系统。如果我希望给更多客户端予以权限去访问远程 SSH 服务端,我应该怎么做?很简单。你需要在所有的客户端系统上生成 SSH 密钥对并且手动拷贝 ssh 公钥到想要通过 ssh 访问的远程服务端上。
在客户端系统上创建 SSH 密钥对,运行:
<span class="pln">$ </span><span class="kwd">ssh</span><span class="pun">-</span><span class="pln">keygen</span>
输入两次密码。现在,ssh 密钥对已经生成了。你需要手动把公钥(不是私钥)拷贝到远程服务端上。
使用以下命令查看公钥:
<span class="pln">$ </span><span class="kwd">cat</span><span class="pun">~</span><span class="str">/.ssh/</span><span class="pln">id_rsa</span><span class="pun">.</span><span class="pln">pub</span>
应该会输出类似下面的信息:
<span class="kwd">ssh</span><span class="pun">-</span><span class="pln">rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCt3a9tIeK5rPx9p74</span><span class="pun">/</span><span class="typ">KjEVXa6</span><span class="pun">/</span><span class="typ">OODyRp0QLS</span><span class="pun">/</span><span class="pln">sLp8W6iTxFL</span><span class="pun">+</span><span class="typ">UgALZlupVNgFjvRR5luJ9dLHWwc</span><span class="pun">+</span><span class="pln">d4umavAWz708e6Na9ftEPQtC28rTFsHwmyLKvLkzcGkC5</span><span class="pun">+</span><span class="pln">A0NdbiDZLaK3K3wgq1jzYYKT5k</span><span class="pun">+</span><span class="typ">IaNS6vtrx5LDObcPNPEBDt4vTixQ7GZHrDUUk5586IKeFfwMCWguHveTN7ykmo2EyL2rV7TmYq</span><span class="pun">+</span><span class="pln">eY2ZqqcsoK0fzXMK7iifGXVmuqTkAmZLGZK8a3bPb6VZd7KFum3Ezbu4BXZGp7FVhnOMgau2kYeOH</span><span class="pun">/</span><span class="typ">ItKPzpCAn</span><span class="pun">+</span><span class="pln">dg3NAAziCCxnII9b4nSSGz3mMY4Y7 ostechnix@centosserver</span>
拷贝所有内容(通过 USB 驱动器或者其它任何介质),然后去你的远程服务端的终端,像下面那样,在 $HOME
下创建文件夹叫做 .ssh
。你需要以 root 身份执行命令(注:不一定需要 root)。
<span class="pln">$ </span><span class="kwd">mkdir</span><span class="pun">-</span><span class="pln">p </span><span class="pun">~/.</span><span class="kwd">ssh</span>
现在,将前几步创建的客户端系统的公钥添加进文件中。
<span class="kwd">echo</span><span class="pun">{</span><span class="typ">Your_public_key_contents_here</span><span class="pun">}</span><span class="pun">>></span><span class="pun">~</span><span class="str">/.ssh/</span><span class="pln">authorized_keys</span>
在远程系统上重启 ssh 服务。现在,你可以在新的客户端上 SSH 远程服务端了。
如果觉得手动添加 ssh 公钥有些困难,在远程系统上暂时性启用密码认证,使用 ssh-copy-id
命令从本地系统上拷贝密钥,最后禁用密码认证。
推荐阅读:
好了,到此为止。基于密钥认证的 SSH 提供了一层防止暴力破解的额外保护。如你所见,配置密钥认证一点也不困难。这是一个非常好的方法让你的 Linux 服务端安全可靠。
不久我会带来另一篇有用的文章。请继续关注 OSTechNix。
干杯!
via: https://www.ostechnix.com/configure-ssh-key-based-authentication-linux/
作者:SK 选题:lujun9972 译者:LuuMing 校对:pityonline