Jusene's Blog

Linux ssh 多种方式登陆

字数统计: 2.1k阅读时长: 9 min
2017/02/18 Share

用户名密码登陆

1
[root@node1 ~]# ssh root@10.211.55.36
2
The authenticity of host '10.211.55.36 (10.211.55.36)' can't be established.
3
RSA key fingerprint is 4a:26:57:1f:d8:aa:88:2f:73:9c:d5:df:44:b6:17:c1.
4
Are you sure you want to continue connecting (yes/no)? yes
5
Warning: Permanently added '10.211.55.36' (RSA) to the list of known hosts.
6
root@10.211.55.36's password:

这里输入密码,即可登陆远程主机,这里需要我们验证的是远程主机是不是我们请求的目标主机,如果选择是,客户端会在~/.ssh/known_hosts中记录下远程主机的机器特征码,这样做的好处就是当该ip被给到别的主机或者网络中有人恶意模仿远程主机的ip,这里的验证就会通不过,这里也将提醒系统管理员是不是此ip的主机是不是做过修改。

如果远程主机ip与客户端记录的机器特征码不一致,会得到如下的警告信息,并且ssh会立即中断连接:

1
[root@node1 .ssh]# ssh root@10.211.55.36
2
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
3
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
4
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
5
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
6
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
7
It is also possible that the RSA host key has just been changed.
8
The fingerprint for the RSA key sent by the remote host is
9
80:26:e2:26:6a:8b:f0:59:f4:42:58:15:12:df:c8:e1.
10
Please contact your system administrator.
11
Add correct host key in /root/.ssh/known_hosts to get rid of this message.
12
Offending key in /root/.ssh/known_hosts:1
13
RSA host key for 10.211.55.36 has changed and you have requested strict checking.
14
Host key verification failed.

这样的确认机制是为ssh增加了安全,但是一些脚本中需要ssh连接新机器的时候这样验证是有碍自动化的实现的,以下方式可以忽略这样的确认机制:

bash脚本:

1
[root@node2 ~]# ssh -o StrictHostKeyChecking=no 10.211.55.35
2
Warning: Permanently added '10.211.55.35' (RSA) to the list of known hosts.
3
root@10.211.55.35's password:

python脚本:

1
import paramiko
2
ssh = paramiko.SSHClient()
3
#允许连接不在know_hosts的主机
4
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

公私钥登陆

首先让我们来去区分下加密与认证这两个基本概念:

  1. 加密是将数据资料加密,使得非法用户即使取得加密过的资料,也无法获取正确的资料内容数据,防止监听攻击。
  2. 认证是用来鉴定某个用户身份的合法性,确认身份后,系统才可以根据不同的身份给予不同权限。

基于公开密钥的加密过程

比如有两个用户Alice和Bob,Alice想把一段明文通过双钥加密技术发送给Bob,Bob有一对公钥和私钥,那么加密过程如下:

  • Bob将他的公开密钥传给Alice。
  • Alice用Bob的公开秘钥加密加密他的消息,然后传给Bob。
  • Bob用他的私人密钥解密Alice的消息。

基于公开秘钥的认证过程

身份认证和加密就不同了,主要用户鉴别用户的真伪。这里我们只要鉴别一个用户的私钥是正确的,就可以鉴别这个用户的真伪。

  • Alice用他的私人密钥对文件加密,从而对文件签名。
  • Alice将签名的文件传送给Bob。
  • Bob用Alice的公钥解密文件,从而验证签名。

Linux 公私钥登陆的实现

创建公私钥

1
root@node2 ~]# ssh-keygen -t rsa
2
Generating public/private rsa key pair.
3
Enter file in which to save the key (/root/.ssh/id_rsa): 
4
Enter passphrase (empty for no passphrase): 
5
Enter same passphrase again: 
6
Your identification has been saved in /root/.ssh/id_rsa.
7
Your public key has been saved in /root/.ssh/id_rsa.pub.
8
The key fingerprint is:
9
e2:ee:1a:7d:2d:12:0c:e8:45:29:05:e4:d4:d5:d6:75 root@node2
10
The key's randomart image is:
11
+--[ RSA 2048]----+
12
| .++oo.. . .. E  |
13
| o.oo   o .  .   |
14
|  o.o  .         |
15
| . . o           |
16
|  .   + S        |
17
|     o o .       |
18
|    . + o .      |
19
|     o o .       |
20
|    .oo          |
21
+-----------------+

ssh-keygen [opotion]

  • -t [rsa | dsa]:选择加密方式(默认rsa)
  • -f /path/to/key: 创建后的密钥存放的目录(默认~/.ssh/)
  • -N passphrase: 指定密码(可以在公私钥上再加一层密码认证)

将公钥给远程主机

在公私钥创建的目录下有id_rsa,id_rsa.pub,可以很容易知道id_rsa.pub为公钥,将里面的内容复制给远程主机的~/.ssh/authorized_keys里,这样我们就可以实现公私钥登陆了。我们来试试命令方式将密钥给远程主机:

1
[root@node2 .ssh]# ssh-copy-id root@10.211.55.35
2
The authenticity of host '10.211.55.35 (10.211.55.35)' can't be established.
3
RSA key fingerprint is bf:be:66:93:b3:6a:b2:c1:ec:55:04:eb:12:97:4d:ea.
4
Are you sure you want to continue connecting (yes/no)? yes
5
Warning: Permanently added '10.211.55.35' (RSA) to the list of known hosts.
6
root@10.211.55.35's password: 
7
Now try logging into the machine, with "ssh 'root@10.211.55.35'", and check in:
8
9
  .ssh/authorized_keys
10
11
to make sure we haven't added extra keys that you weren't expecting.

这样我们就可以只需要输入一次密码,就可以免密码登陆了,这里未指定将哪个公钥传给远程主机,默认的公钥都是~/.ssh/id_rsd.pub,我们可以使用-i选项来指定公钥,那么问题又来了,用户只要盗取这机器上的私钥就可以登陆这台能登陆的所有机器,当然这里我们还可以为公私钥再设置密码,两层保护,但是这又回到每次需要密码的的阶段,双机互信的便利性有没有了,怎么做到既要安全又要便利呢?

SSH代理:密码+密钥,但无需输入密码

ssh-agent ssh代理

首先我们需要创建一个带密码的公私钥,并将公钥给远程主机,这时我们即使有私钥也需要密码登陆。

1
[root@node1 .ssh]# eval `ssh-agent`
2
Agent pid 17239
3
[root@node1 .ssh]# ssh-add ~/.ssh/id_rsa   
4
Enter passphrase for /root/.ssh/id_rsa: 
5
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)
6
[root@node1 .ssh]# ssh 10.211.55.36        
7
Last login: Mon Feb 13 05:15:28 2017 from 10.211.55.35
8
[root@node2 ~]# exit
9
logout
10
Connection to 10.211.55.36 closed.
11
[root@node1 .ssh]# ssh 10.211.55.36
12
Last login: Mon Feb 13 05:16:54 2017 from 10.211.55.35

我们只需要输入一次密码,就不需要输入密码登陆了,ssh-add 要我的密码短语来对专用密钥进行解密并存储在 ssh-agent 的高速缓存中以备使用。一旦您已经用 ssh-add 把专用密钥(或多个密钥)添加到 ssh-agent 的高速缓存中,那么您可以使用 scp 和 ssh 同远程系统建立连接而不必提供密码短语。

但是ssh-agent的不足处,当我们退出当前shell的时候,下次登陆我们还是需要重复上次操作,ssh-agent是存储在高速缓存中数据,所以如果我们需要当每次登陆的时候自动提醒输入密码,我设计了一个脚本:

1
[root@node1 profile.d]# cat ssh-agent.sh 
2
#!/bin/sh
3
if [ -f ~/.agent.env ]; then
4
. ~/.agent.env >/dev/null
5
if ! kill -0 $SSH_AGENT_PID >/dev/null 2>&1; then
6
echo “Stale agent file found. Spawning new agent…”
7
eval `ssh-agent |tee ~/.agent.env`
8
ssh-add
9
fi
10
else
11
echo “Starting ssh-agent…”
12
eval `ssh-agent |tee ~/.agent.env`
13
ssh-add
14
fi

当然这还是很不方便,关键是这个无需要第三方程序即可实现,下面我们来使用第三方工具keychain来实现。

keychain 钥匙扣

1
[root@test ~]# wget http://www.funtoo.org/archive/keychain/keychain-2.7.1.tar.bz2
2
[root@test ~]# tar jxvf keychain-2.7.1.tar.bz2
3
[root@test ~]# cd keychain-2.7.1
4
[root@test keychain-2.7.1]# install -m 0755 keychain /usr/bin/
5
[root@test ~]# vim .bash_profile
6
在最后加入下面内容
7
hostname=`uname -n`
8
pidf=~/.keychain/${hostname}-sh
9
keychain ~/.ssh/id_rsa
10
source $pidf > /dev/null
11
source ~/.bashrc

这里我们我只需要输入一次公私钥的密码,就可以不需要输入密码登陆远程主机,即使退出当前shell,下次登入我们一样可以免密码登陆远程主机,真正实现密钥+密码,但是不需要密码,这样的好处,即使别人盗取私钥,还需要密码,而我们却不影响正常使用。

CATALOG
  1. 1. 用户名密码登陆
  2. 2. 公私钥登陆
    1. 2.1. 基于公开密钥的加密过程
    2. 2.2. 基于公开秘钥的认证过程
    3. 2.3. Linux 公私钥登陆的实现
      1. 2.3.1. 创建公私钥
      2. 2.3.2. 将公钥给远程主机
  3. 3. SSH代理:密码+密钥,但无需输入密码
    1. 3.1. ssh-agent ssh代理
    2. 3.2. keychain 钥匙扣