1. Posts/

SSH 101: 一文掌握使用 SSH 的正确姿势

·2370 字·5 分钟·
云原生 ssh 工程效率
Cloud Native 101
作者
Cloud Native 101
与「Cloud Native 101」同行,让云原生技术触手可及!
Table of Contents

cover

日常工作中你是否经常需要使用 SSH 登录远程服务器,平时你只用到一两台服务器还好,如果量上去了,你是否有为管理多台服务器苦恼过?

需要记住那么多的 IP 地址、用户名、以及不同非标准的默认端口,还要输入繁琐的口令密码,太难了。

我相信大家也不愿意去记这玩意儿,纯属浪费时间,而且这确实也不是一种非常有效率的方式,对于一个有追求的新生代农民工来说是不能忍的。

这个问题其实有很多种方法去解决,在我们团队内部,我发现大家使用的方法也各有不同。

SSH
#

我们先来看下维基百科对 SSH 的介绍。

Secure Shell(安全外壳协议,简称 SSH)是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境。SSH 通过在网络中创建安全隧道来实现 SSH 客户端与服务器之间的连接。SSH 最常见的用途是远程登录系统,人们通常利用 SSH 来传输命令行界面和远程执行命令。

摘自 Secure Shell

    ssh 客户端(ssh)                    ssh 服务端(sshd)

     +----------+                       +---------+
     |          |                       |         |
     |          |                       |         |
     |          |                       |         |
     |          |                       |         |
     +---+---+--+                       +-+---+---+
         |   |                            |   |
         |   |                            |   |
         |   +----------------------------+   |
         |                                    |
         |        ssh 加密了的 TCP 通信         |
         +------------------------------------+

Non-Interactive SSH Login
#

初次使用 SSH 登录远程服务器的同学一般很老实的采用交互式的方式,通过输入密码登录,操作久了难免也会乏味。那么有没有什么工具可以让你摆脱这种重复的流程呢?有的,它就是 sshpass

sshpass 它是一个非常优秀的非交互式 SSH 登录工具,使用起来非常的简单,我先来看几个常用命令。

# 使用默认端口
sshpass -p '<PASSWORD>' ssh <USER_NAME>@<HOST_NAME>

# 使用非标准端口
sshpass -p '<PASSWORD>' ssh -p 8000 <USER_NAME>@<HOST_NAME>

# 密码作为环境变量 `SSHPASS` 传递
SSHPASS='<PASSWORD>' sshpass -e ssh <USER_NAME>@<HOST_NAME>

# 其他使用方法,可以通过 help 自行摸索
sshpass -h

聪明如你,通过这个工具我们其实就有很多发挥的空间了,比如扩展 Bash Aliases 或者通过 Shell Script 做一些自动化的东西。

Bash Aliases
#

你可以在你的 ~/.aliases 配置文件里追加以下配置

# Login devbox
alias login_devbox="sshpass -p '<PASSWORD>' ssh <USER_NAME>@<HOST_NAME>"

然后你就可以通过更简短的命令来登录了,我们来验证下

➜ login_devbox

Last login: Sat Oct 30 12:51:16 2021 from 10.0.3.xxx
[root@vm-ds2-srv26-42 ~]#

Shell Script
#

我们来看个简单例子,用 sshpassShell script 里能做什么事情。

SSHPASS='<PASSWORD>' sshpass -e ssh <USER_NAME>@<HOST_NAME> df -h

效果如下

SSHPASS='tx#M58bFKQ' sshpass -e ssh [email protected] df -h

Filesystem      Size  Used Avail Use% Mounted on
devtmpfs         15G     0   15G   0% /dev
tmpfs            15G     0   15G   0% /dev/shm
tmpfs            15G  1.5G   14G  10% /run
tmpfs            15G     0   15G   0% /sys/fs/cgroup
/dev/vda5       126G  7.6G  119G   6% /
/dev/vda2        15G   33M   15G   1% /var/lib/mysql
/dev/vda1      1014M  195M  820M  20% /boot
/dev/vdc        1.9T  144G  1.7T   8% /minio02
/dev/vdb        1.9T  144G  1.7T   8% /minio01
tmpfs           3.0G     0  3.0G   0% /run/user/0

但是需要注意的是 永远不要在生产服务器上使用,建议只在本地开发机器上使用,解脱重复乏味的操作即可,原因相信大家都懂的。

如何安装 sshpass,可以参考以下链接

Installing SSHPASS

SSH Passwordless Login
#

SSH 通过密码方式认证,难免会产生一些不必要的麻烦,那么还有没其他更简单的登录方式,而且又能防止信息泄露呢?当然有,它就是 Public-key Authentication,一种相对安全的模式,且能做到免密码登录远程服务器。

Step 1. 在客户端生成 RSA 密钥对
#

我们用 ssh-keygen 命令来生成 rsa key pair,以下是生成过程。

➜ ssh-keygen -t rsa -C "[email protected]" -f ~/.ssh/example-rsa -b 4096

Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):

对私钥进行保护的口令密码我们可以留空,直接按 Enter

➜ ssh-keygen -t rsa -C "[email protected]" -f ~/.ssh/example-rsa -b 4096
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/linqiong/.ssh/example-rsa
Your public key has been saved in /Users/linqiong/.ssh/example-rsa.pub
The key fingerprint is:
SHA256:Z2/4RbsSZeYlYYpgkiG42w4SJZZI9decFouFMyPrB7k [email protected]
The key's randomart image is:
+---[RSA 4096]----+
|o.oo. .o.o       |
|ooo .oo=B +   o  |
|.o . .+=+B . o . |
|. .  +. . . . = .|
| . o. o S o  =.o |
|. o .E . o o.... |
| . o  .   . o.o  |
|    .      o.. . |
|            ...  |
+----[SHA256]-----+

成功生成后,我们来查看下刚刚生成的一对 RSA 密钥

需要特别注意的是 私钥 是不能对外泄露的

➜ ls -lha ~/.ssh |grep example
-rw-------    1 linqiong  staff   3.3K Oct 30 14:45 example-rsa      #私钥
-rw-r--r--    1 linqiong  staff   742B Oct 30 14:45 example-rsa.pub  #公钥

当然,你也可以给不同的场景配置不同的 rsa key pair,如下所示

# company
ssh-keygen -t rsa -C "[email protected]"

# github
ssh-keygen -t rsa -C "[email protected]" -f ~/.ssh/github-rsa -b 4096

Step 2. 拷贝公钥到远程服务器
#

通过 ssh-copy-idStep 1 生成的客户端公钥追加到远程机器的 authorized_keys 文件中(需要输入密码)

这里说明下,密钥只针对本地生成的用户有效,其他用户需要自己生成,并做同样的操作

# 拷贝公钥文件
ssh-copy-id -i ~/.ssh/example-rsa.pub [email protected]

Step 3. 验证免密登录
#

现在通过使用客户端私钥来登录,我们来验证下是否生效了

➜ ssh [email protected] -i ~/.ssh/example-rsa

Last login: Sat Oct 30 15:35:38 2021 from 10.0.3.xxx
[root@vm-ds2-srv26-42 ~]#

同时使用 scp 命令,验证下上传动作

➜ scp -i ~/.ssh/example-rsa ~/Downloads/ssh.png [email protected]:/home/qiong.lin
ssh.png                                         100%  976KB 234.3KB/s   00:04

SSH Config File
#

大家肯定也发现了,免密登录的方式虽然比 sshpass xxx 简化了很多,不过还是比较麻烦的,要记住用户名的同时又要记住具体服务器的 ip 地址,我们还有没有更方便的方式呢?

我们可以通过对 ~/.ssh/config 文件的配置,简化 SSH 相关的操作。

SSH Config File Example
#

需在客户端的 ~/.ssh 目录下新建名称为 config 的文件,配置多个不同的 host 可以使用不同的 ssh key

我们先来看一个配置文件,如下所示

Host login_devbox                         # 目标服务器别名
    HostName 172.18.0.xxx                 # 主机地址
    User root                             # 用户名
    Port 22                               # 指定端口
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/example-rsa       # 私钥文件路径

现在登录方式变的更加简洁,完全不需要再去记 IP 地址、用户名、以及不同非标准的端口,也不需要在指定 -i 参数了,只需用自定义的服务器别名登录即可。

➜ ssh login_devbox

Last login: Sat Oct 30 16:59:25 2021 from 10.0.3.xxx
[root@vm-ds2-srv26-42 ~]#

我们在来看下文件上传命令是否也更简单了

➜ scp ~/Downloads/ssh.png login_devbox:/home/qiong.lin
ssh.png                   100%  976KB 234.3KB/s   00:04

同时我们也可以利用 ssh 直接来验证上传的文件

➜ ssh login_devbox "ls -lh /home/qiong.lin"

total 980K
-rw-r--r-- 1 root root 977K Oct 30 17:05 ssh.png

小技巧
#

对于一些有规律的主机配置,我们其实不需要为每台机器设置一个配置,比如说一个 Kubernetes 集群的节点,如下所示:

➜ kubectl get node -owide
NAME         STATUS   ROLES    AGE    VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION              CONTAINER-RUNTIME
kind-dev1     Ready    master   219d   v1.19.2   172.18.0.135   <none>        CentOS Linux 7 (Core)   5.7.7-1.el7.elrepo.x86_64   docker://20.10.5
kind-dev2     Ready    master   219d   v1.19.2   172.18.0.136   <none>        CentOS Linux 7 (Core)   5.7.7-1.el7.elrepo.x86_64   docker://20.10.5
kind-dev3     Ready    master   219d   v1.19.2   172.18.0.137   <none>        CentOS Linux 7 (Core)   5.7.7-1.el7.elrepo.x86_64   docker://20.10.5
kind-dev4     Ready    <none>   219d   v1.19.2   172.18.0.138   <none>        CentOS Linux 7 (Core)   5.7.7-1.el7.elrepo.x86_64   docker://20.10.5

按照惯性思维,如果这四台机器你都要维护,你是不是准备要设置四份配置,反正很简单嘛,复制粘贴改一下就行嘛,又不是不能用?

其实有更简单的办法,看一下以下配置,通过一些参数来完成。

Host 1*
  HostName 172.18.%h
  User qiong.lin
  IdentityFile ~/.ssh/id_rsa
  Port 22

配置完后,我们来看下效果吧。

# 登录 `172.18.0.135` 节点
➜ ssh 135

Last login: Sat Oct 30 18:14:14 2021 from 10.0.3.42
[qiong.lin@kind-dev1 ~]$ ifconfig|grep 135
        inet 172.18.0.135  netmask 255.255.255.0  broadcast 172.18.0.255
# 登录 `172.18.0.138` 节点
➜ ssh 138

Last login: Sat Oct 30 18:14:41 2021 from 10.0.3.42
[qiong.lin@kind-dev4 ~]$ ifconfig|grep 138
        inet 172.18.0.138  netmask 255.255.255.0  broadcast 172.18.0.255

连接 github
#

将本地公钥添加到 github 的 SSH keys 中

# 验证登录 github
➜ ssh -T [email protected]
Hi lqshow! You've successfully authenticated, but GitHub does not provide shell access.

Conclusion
#

通过这篇文章的介绍,相信大家都知道 SSH 支持两种形式的登录认证。

  1. Password Authentication
  2. Public-key Authentication

文中提到过的两种 SSH 免密登录,对我们日常工作中是非常有用的,特别是在做一些自动化任务(比如使用脚本自动备份、使用 SCP 命令同步文件和远程命令执行等),且该模式安全性是非常高的。

其实 SSH Config 不仅能帮助我们快速的使用 SSH 登录不同的主机,同时还可以管理多个 SSH key pairs

希望这篇文章对大家有所帮助。

Official Account
关注公众号 「Cloud Native 101」,设为「星标」,不迷路!

Related

Kubernetes Patterns 101: 初识初始化容器,探索容器设计的精髓
··2989 字·6 分钟
云原生 Kubernetes Init Container Kubernetes Patterns 101