欢迎大家关注我的个人博客【数洞】 【备用站】
程序员同学少不了天天登录自己的开发机,但是开发机都是需要密码的,在漆黑的终端中输入密码并不是一个愉快的体验。
因为输入的时候,屏幕上并不会有任何的显性的提示,输入多一位少一位或者输入错误都无法迅速发现,只能在报错之后小心翼翼地重新输入一遍,这也导致我们根本不敢设置太过复杂的密码,因为太容易在登录环节卡住……
所以对我们来说,免密登录就是一个神器,至少能让我们每天在登录开发机时不会因为密码错误而破坏心情。
一、ssh-key方案
先给大家演示一下效果:
# dain @ qixizhuangdeMac-Pro in ~ [21:46:50]
$ ssh tc
Last login: Fri Sep 28 23:32:50 2018 from 123.116.144.44
# root @ VM_0_16_centos in ~ [21:47:20]
$
可以看到,我们直接用一个简单的命令就登陆上了我们的服务器,这个过程里不需要输入任何密码。
那接下来我们来演示一遍如何配置。首先,因为我们的这台本地机器已经成功配置了自动登录,所以我们需要还原一下:
# root @ VM_0_16_centos in ~ [21:50:59]
$ cd .ssh # 进入$HOME下的.ssh目录中,这是ssh程序在每个用户下的默认配置目录
# root @ VM_0_16_centos in ~/.ssh [21:51:01]
$ cat authorized_keys # 查看本地机器授权的key
ssh-rsa AAAAB3...CSG0P dain@DataInsightsdeMacBook-Pro.local
ssh-rsa AAAA...fRDT51B dain@DataInsightsdeMac-Pro.local
# 此处因为太长,省略了大量字符
从末尾我们看出第二条记录是当前我们使用的设备,所以我们将第二条删除并保存退出。然后我们离开服务器回到本地,同样进入.ssh目录,查看一下现有的文件:
# root @ VM_0_16_centos in ~/.ssh [21:51:20]
$ exit
Connection to 132.232.117.41 closed.
# dain @ qixizhuangdeMac-Pro in ~ [21:57:10]
$ cd .ssh
# dain @ qixizhuangdeMac-Pro in ~/.ssh [21:57:22]
$ ll
total 32
-rw-r--r-- 1 dain staff 762B 9 28 23:26 config
-rw------- 1 dain staff 1.6K 9 27 23:37 id_rsa
-rw-r--r-- 1 dain staff 412B 9 27 23:37 id_rsa.pub
-rw-r--r-- 1 dain staff 1.4K 9 28 23:32 known_hosts
我们配置自动登录需要的就是上边列出的前三个文件,其中第一个是本地配置文件,第二、第三个文件用于服务器认证本地机器,这两个文件分别是RSA私钥和公钥。.ssh
目录下没有上述文件的,可以通过如下命令生成:
# dain @ qixizhuangdeMac-Pro in ~/.ssh [22:01:31] C:130
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/dain/.ssh/id_rsa):
/Users/dain/.ssh/id_rsa already exists.
Overwrite (y/n)?
程序会询问一些选项,直接Enter保持默认即可。现在,我们已经成功生成了RSA公钥和私钥,接下来,我们就需要将公钥传递给我们的服务器,即在服务器的$HOME/.ssh/authorized_keys
文件中添加我们的id_rsa.pub中的内容。
# dain @ qixizhuangdeMac-Pro in ~/.ssh [22:07:30]
$ ssh-copy-id -i id_rsa.pub root@132.232.117.00
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@132.232.117.41's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'root@132.232.117.41'"
and check to make sure that only the key(s) you wanted were added.
# dain @ qixizhuangdeMac-Pro in ~/.ssh [22:07:46]
$
我们通过这一命令非常快速地将我们的公钥添加到了服务器上,这一过程里需要我们输入服务器上对应的密码。
好了,接下来我们配置本地的config文件:
# Private
Host bd
HostName 180.xx.171.xxx
User root
Port 22
Host tc
HostName 132.xxx.117.xx
User root
Port 22
其中,Host后边填写一个自定义的服务器名称,方便为主,我把百度的服务器命名为bd,腾讯的服务器命名为tc。HostName这里需要配置服务器的地址,User后边配置用户名,Port一般保持默认22即可。
这样配置好之后,我们保存退出,测试一下:
# dain @ qixizhuangdeMac-Pro in ~/.ssh [22:14:24]
$ ssh tc
Last login: Sat Sep 29 22:07:10 2018 from 123.116.144.44
# root @ VM_0_16_centos in ~ [22:17:42]
$
OK,搞定。
二、使用expect命令脚本
事实上,我们还有一种选择,通过自动输入密码来登录服务器,但是这种方法会导致服务器密码明文出现在脚本中,不是特别安全。
#!/usr/bin/expect -f
spawn ssh ${YOUR_NAME}@${YOUR_HOST}
set timeout 30
match_max 100000
expect "*password*"
send -- "${YOUR_PASSWORD}\n"
expect "~]"
interact
这种方法不需要额外的配置,通过匹配服务器的输出来自动进行设定好的下一步输入,这样我们就用脚本模拟了密码登录的过程。事实上,在第一次登录服务器的时候,一般会要求我们将服务器的公钥添加到本地的.ssh/known_hosts文件中,这个过程我们需要输入一个yes。上述脚本并没有考虑这种情况,因此可能会报错退出。因此,假如需要考虑到我们从未登陆过一台服务器的情况,我们可以使用如下脚本:
#!/usr/bin/expect -f
spawn ssh ${YOUR_NAME}@${YOUR_HOST}
set timeout 30
match_max 100000
expect {
"(yes/no)?" {
send "yes\n"
expect "password:"
send "${YOUR_PASSWORD}\n"
}
"password:" {
send "${YOUR_PASSWORD}\n"
}
}
实际使用过程中,将${YOUR_PASSWORD}
、${YOUR_NAME}
等变量替换为实际情况,保存为脚本,并赋予执行权限,移动到系统变量目录中即可。比如我喜欢将自己的工具脚本放入/usr/local/bin
或者$HOME/bin
目录中。
三、绕过跳板机自动登录
这一过程通过方法一、二都可以轻松实现。
1. 使用expect命令
针对第二种方法,无非就是将expect-send的过程增加一环即可:
#!/usr/bin/expect -f
spawn ssh ${YOUR_NAME}@${YOUR_HOST}
set timeout 30
match_max 100000
expect {
"(yes/no)?" {
send "yes\n"
expect "password:"
send "${YOUR_PASSWORD}\n"
expect "~]"
send "ssh ${YOUR_HOST_2}"
expect {
"(yes/no)?" {
send "yes\n"
expect "password:"
send "${YOUR_PASSWD_2}"
}
"password:" {
send "${YOUR_PASSWD_2}"
}
}
}
"password:" {
send "${YOUR_PASSWORD}\n"
expect "~]"
send "ssh ${YOUR_HOST_2}"
expect {
"(yes/no)?" {
send "yes\n"
expect "password:"
send "${YOUR_PASSWD_2}"
}
"password:" {
send "${YOUR_PASSWD_2}"
}
}
}
}
就是这样,没有技术难度,只是单纯的代码重复。
2. 使用ssh-key
我更推荐这种方式,一个原因是方便快捷,一个原因是不需要堆砌一堆垃圾代码。尤其是当需要配置多个服务器自动登录的时候,这种方法明显更为高效易用。
其实核心思路没有变,依然是将本地的公钥添加到服务器的authorized_keys文件中,只不过这次需要多次添加而已,接下来我描述一下这一过程:
首先,假设本地机器为机器A,跳板机为机器B,开发机为机器C:
-
在机器A上通过
ssh-keygen -t rsa
生成公钥私钥 -
在机器A上通过
ssh-copy-id -i .ssh/id_rsa.pub HOST_B
将机器A的公钥添加到跳板机B。 -
将机器A的
id_rsa
和id_rsa.pub
文件复制到机器B:scp -r .ssh/id_rsa* HOST_B:
-
登录跳板机B:
ssh HOST_B
-
在机器B上生成机器B的公钥私钥:
ssh-keygen -t rsa
-
在机器B上通过
ssh-copy-id -i .ssh/id_rsa.pub HOST_C
将机器B的公钥添加到机器C。 -
在机器B上通过
ssh-copy-id -i id_rsa.pub HOST_C
将机器A的公钥添加到机器C -
截止现在,机器B上有了机器A的公钥,机器C上有了机器A、机器B的公钥。事实上这一过程完全可以通过复制粘贴来完成,目标文件是对应机器上的
.ssh/authorized_keys
,使用追加新的一行的方式粘贴进去即可。 -
我们还需要配置下本地机器A的
$HOME/.ssh/config
文件。
下面是我的简略版的配置,其中,capital是我的跳板机的名称,而fs、a0、i1分别是我的三台开发机,他们都需要通过跳板机来登录。
需要注意的是,我们使用ProxyCommand来配置我们访问开发机时自动经由跳板机来访问。在实际使用过程中,你需要将capital替换为你自己命名的跳板机的名称或HOST,其他HostName、User也替换为对应的IP和用户名即可。
# Work
Host capital
HostName 101.xxx.220.xxx
User qixizhuang
Port 22
Host fs
HostName 10.xx.142.xxx
User qixizhuang
Port 22
ProxyCommand ssh -q -W %h:%p capital
Host a0
HostName 10.xx.26.xxx
User qixizhuang
Port 22
ProxyCommand ssh -q -W %h:%p capital
Host i1
HostName 10.xxx.136.xxx
User qixizhuang
Port 22
ProxyCommand ssh -q -W %h:%p capital
好了,这样大多数的登录行为我们都可以免密完成了。大家有问题可以留言,我收到回及时回复,大家一起探讨。