openssh加密密钥代理验证


sshpass非交互登录


sshpass+ssh可以实现完全非交互式密码访问远程主机,可直接跳过第一次访问时的yes/no,现如今炙手可热的ansible安装时也会一并安装上sshpass噢


格式:sshpass -p 密码 ssh -o StrictHostKeyChecking=no 用户@主机


如:

sshpass -p password ssh -o StrictHostKeyChecking=no foo@192.168.1.1



expect非交互登录


示例:



将如下内容保存为expect脚本,foo.exp



#!/usr/bin/expect
set timeout 5; 
set
set
set
$user@$host
{
        "Connection refused" exit
        "Name or service not known" exit
"continue connecting" {send "yes\r";exp_continue}
"password:" {send "$password\r";exp_continue}
 }
 expect eof 
 interact



运行时执行,expect -f foo.exp即可自动登录




SSH服务端加速
提示1:Ubuntu发行版默认不 允许root ssh远程登录,注释掉/etc/ssh/sshd_config 中的如下一行即可开启root远程登录



PermitRootLogin without-password 提示2:禁用ssh DNS反解,加快访问速度,修改或添加如下行即可 UseDNS no



提示3: 未使用Kerberos时,可以设置
GSSAPIAuthentication no

SSH客户端 ControlPersist

版本新一点的openssh,如centos7默认自带的版本。

在ssh客户端配置文件/etc/ssh/ssh_config中加入如下内容,可以在~/.ssh/目录下生成访问缓存文件,第一次访问会生成临时的socket隧道,之后再次连接时无需输入再次输入密码

Host *
   SendEnv LANG LC_*
   ControlMaster auto
   ControlPath ~/.ssh/%h-%p-%r
   ControlPersist yes
 
jlive@MacBook-Pro:~
  | |   \--= 00751 jlive ssh root@192.168.130.254
  |     \--- 00876 jlive grep ssh
  |--= 00752 jlive /usr/bin/ssh-agent -l
  |--= 00755 jlive ssh: /Users/jlive/.ssh/192.168.130.254-22-root [mux] 
  
  |--= 00816 jlive ssh: /Users/jlive/.ssh/10.157.20.8-22-wasadmin [mux] 
jlive@MacBook-Pro:~ $ls .ssh/
10.157.20.8-22-wasadmin
id_rsa.pub



忽略主机指纹检查(第一次访问远程主机时不用输yes确认)



StrictHostKeyChecking no
 
   
UserKnownHostsFile=/dev/null




一.本地用户密码验证


ssh正常登录某主机会提示输入密码,如没有指定以谁的身份登录则以当前用户的身份来验证


root@jun-live:~#ssh 192.168.2.104 
   
 The authenticity of host '192.168.2.104 (192.168.2.104)' can't be established. 
   
 RSA key fingerprint is 81:9a:a5:90:4d:4b:2d:b1:df:45:39:33:1a:7f:af:d5. 
   
 Are you sure you want to continue connecting (yes/no)? 
   yes   
   
 Warning: Permanently added '192.168.2.104' (RSA) to the list of known hosts. 
   
root@192.168.2.104's password: 
   
 Last login: Tue Sep  9 10:04:14 2014



二.公私钥验证


A.通过ssh-keygen在本机生成公私钥对


提示: 静默生成ssh-keygen  -t rsa -N '' -f ~/.ssh/id_rsa -q -b 2048




root@vhost4:~# 
   ssh-keygen 
   
 Generating public/private rsa key pair. 
   
 Enter file in which to save the key 
   (/root/.ssh/id_rsa):      
   
 Enter passphrase (empty for no 
   passphrase): 
   
 Enter same 
   passphrase again: 
   
 Your identification has been saved in /root/.ssh/id_rsa. 
   
 Your public key has been saved in /root/.ssh/id_rsa.pub. 
   
 The key fingerprint is: 
   
c8:07:b6:d5:f4:26:91:7e:1b:97:86:5d:8a:b2:39:e2 root@vhost4 
   
 The key's randomart image is: 
    +---[RSA 2048]----+
 |            .BE++|
 |         .  +..o |
 |        . .... o |
 |     . .  .. oo +|
 |    o o S ... ..+|
 |     * = =.   .o |
 |    . = =.B    o |
 |     . ..*.*  o  |
 |       ..o*=+.   |
 +----[SHA256]-----+



加密算法默认采用的是rsa加密,dsa可选。


ssh-keygen生成公钥和私钥时会“问”,公私钥存放的位置及名称,如果不指定则默认放在

~/.ssh这个目录,并且默认叫id_rsa(私钥), id_rsa.pub(公钥),known_hosts里存放的则是所有远程主机的信息,每个主机一条标识,当远程主机名一样但IP等信息发生变化时会提示信息不匹配,这里只需要把known_hosts里对应的那条记录删掉,再重新建立连接一次,这里该主机的信息会再次自动添加known_hosts文件。可以通过你喜欢的编辑器来打开~/.ssh/known_hosts这个文件删除对应的行,我这里直接用

sed流编辑器


@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 @    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
 Someone could be eavesdropping on you right now (man-in-the-middle attack)!
 It is also possible that the RSA host key has just been changed.
 The fingerprint for the RSA key sent by the remote host is
 c7:b3:03:2f:7c:ab:9e:75:fe:c9:a3:45:63:1b:55:3f.
 Please contact your system administrator.
 Add correct host key in /root/.ssh/known_hosts to get rid of this message.
 Offending key in /root/.ssh/known_hosts:66
RSA host key for 192.168.2.251.
 Host key verification failed.
 lost connection 
   

sed  -i  '/192.168.2.251/d'  ~/.ssh/know_hosts



在提示公私钥的存放位置后还会问,是否给公私钥设置密码,直接回车则不设置密码,如果设置了密码则每次去连接远程主机时都会提示输入公私钥的密码。



问题:


1.没有设置密码的公私钥,配对成功后访问远程主机更方便但不安全,随便copy到另外一台主机就可以无密码直接ssh到已经经过该公私钥配对验证成功的主机


2.设置密码后的公私钥更安全,即便被窃取,但在使用时会提示输入密码,破解也是需要时间的,但每次访问某台主机都需要输入本地公私钥对的密码,不太方便,麻烦。


3.远程主机非常多,并且需要非交互地远程执行一些脚本或命令,这时如果登录一台就输入一次公私钥对的密码,那也很麻烦,怎么办---

代理



root@vhost4:~#pwd 
   
 /root 
   
 root@vhost4:~#ls .ssh/ 
   
id_rsa  id_rsa.pub  known_hosts 
   
 root@vhost4:~# 
   cat .ssh/id_rsa.pub 
   
 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAtDgmYibO4iuwRj0mAhHvWxvAF1uxCPEtif3yDiISJJncvHGB99V17F/AodzIFv9SOV9F4qekcjmnjNu95VJ7bdAQUnKUJIEABGo4LjhPZB3BJd2RxAdCXvP/IiDIlNjT7RzOd5n9peVmbaMX2wpslvNxdHV3FbHnIa3RrbwfiQ6EitvtOthlOGQgkOgYAEnVbX8RyKAj5ATSW4yrHO1vIyPOe/9/ng0nlwgEoLQnmcetbjJGbcgcdAfY31dE3GTnFVKwbpYWLKnDSGRNj1fPUe2ytBEI4cGMp7uYezROt8m0yd95d4+m6O+6BhO2FYtjaYN1+PlVA8pNiQEyp+Rb0Q 
   == root@vhost4




B.将本机的公钥copy到远程主机的~/.ssh/authorized_keys中


root@vhost4:~# 
   ssh-copy-id -i .ssh/id_rsa.pub 192.168.2.250 
   
 root@192.168.2.250's password: 
   
 /root/.bashrc: line 48: bind: warning: line editing not enabled 
   
 /root/.bashrc: line 54: bind: warning: line editing not enabled 
   
 /root/.bashrc: line 59: bind: warning: line editing not enabled 
   
 Now try logging into the machine, with "ssh '192.168.2.250'", and check in: 
   

   
   .ssh/authorized_keys 
   

 to make sure we haven't added extra keys that you weren't expecting.


默认情况下都是放在远程主机的~/.ssh/authorized_keys这个文件中,除远程主机的/etc/ssh/sshd_config配置文件有重新定义,下面是截取的一段,大概在49行的样子,不同版本可能有些微差异。


47 #RSAAuthentication yes 
   
 48 #PubkeyAuthentication yes 
   
49 #AuthorizedKeysFile     .ssh/authorized_keys 
   
 50 #AuthorizedKeysCommand none 
   
 51 #AuthorizedKeysCommandRunAs nobody 
   

ssh-copy-id  #自动将本地公钥添加到远程主机~/.ssh/authorized_keys的脚本,一般在安装了openssh后就会有 
   
 ssh-copy-id  -  
   install  your  public  key in a remote machine’s authorized_keys 
   

 SYNOPSIS 
   
        
   ssh-copy-id [-i [identity_file]] [user@]machine 
   

 DESCRIPTION 
   
        ssh-copy-id is a script that uses ssh to  log  into  a  remote  machine 
   
        (presumably  using  a login password, so password authentication should 
   
        be enabled, unless you’ve done some clever use of multiple  identities) 
   
        It  also changes the permissions of the remote user’s home, ~/.ssh, and 
   
        ~/.ssh/authorized_keys to remove group writability (which would  other- 
   
        wise  prevent  you  from logging in, if the remote sshd has StrictModes 
   
        set in its configuration).  If the -i option is given then the identity 
   
        file  (defaults  to  ~/.ssh/id_rsa.pub)  is used, regardless of whether 
   
        there are any keys in your

ssh-agent


ssh-copy-id能很方便地将本地公钥添加到远程主机对应的认证文件中,当然如果没有这个工具要怎么办呢,通常我们搜索到的文章讲述的时手动copy到远程主机,再把公钥追加到认证文件authorized_keys中。



scp -p ~/.ssh/id_rsa.pub  192.168.2.250:/tmp      #把本地的公钥copy到远程的某个目录 
   
ssh 192.168.2.250       #登录到远程主机


cat /tmp/id_rsa.pub >>~/.ssh/authorized_keys   #把公钥追加到authorized_keys,这所以要追加是因为远程主机的认证文件authorized_keys中可能已经有了其它客户端的公钥了,如果直接覆盖则其它主机又得重新验证。


rm -rf /tmp/id_rsa.pub   #删掉公钥,以确保安全。



C.ssh-agent公私钥代理认证


1.未启用代理,当登录远程主机时会提示输入key的密码,这个密码就时用ssh-keygen生成公私钥对时设置的密码。每次登录都会要求输入密码验证,


root@vhost4:ssh#ssh 192.168.2.250 
   
 Enter passphrase for key '/root/.ssh/id_rsa':


2.启用代理


There are two main ways to get an agent set up: The first is that the agent starts a new subcommand 
   
      into which some environment variables are exported, eg 
   ssh-agent xterm &.  The second is that the 
   
      agent prints the needed shell commands (either sh(1) or csh(1) syntax can be generated) which can be 
   
      evaluated in the calling shell, eg 
   eval ‘ssh-agent -s‘ for Bourne-type shells such as sh(1) or ksh(1) 
   
      and 
   eval ‘ssh-agent -c‘ for csh(1) and derivatives.


 从上面的man帮助中我们可以知道,有2种方式来设置代理,



a. 代理subcommand 

如,ssh-agent xterm &,通过ssh-agent代理开启了一个xterm后台会话,只要在这个xterm终端中输入ssh-add然后再提示并正确输入公私钥对密码后,通过这个xterm发出的ssh连接都不需要再输入任何密码(前提是针对已经通过该公私钥验证过的远程主机)。


b.直接代理shell进程,如,eval 'ssh-agent -s' 代理sh,ksh; eval 'ssh-agent -c'代理csh,tcsh;

注意:这两种方式都只是代理某个进程及由该进程衍生的子进程,举例来说,代理xterm,那么其它的终端去连远程主机照样需要输入本地公私钥的密码,代理的sh,也只局限于该sh进程,也就时在eval 'ssh-agent -s'这条命令回车后在该终端发起的远程连接,如果Ctrl+D回到上层sh,则代理失效。

下面的进程树可以说明这个问题,





启用代理前

root@vhost4:~#ps aux|grep ssh-agent
 root      2138  0.0  0.1 103252   808 pts/0    R+   11:32   0:00 grep --color=auto ssh-agent
 root@vhost4:~#pstree|grep pstree -A3 -B3
      |-6*[mingetty]
      |-rsyslogd---3*[{rsyslogd}]
      |-sshd---sshd---bash-+-grep
      |                                  `-pstree
      `-udevd---2*[udevd]

直接代理bash

验证代理凭据

root@vhost4:~#ssh-agent bash
 root@vhost4:~#ps aux|grep ssh-agent
 root     2142  0.0  0.1  57700   744 ?        Ss   11:33   0:00 ssh-agent bash
 root      2153  0.0  0.1 103252   812 pts/0    S+   11:33   0:00 grep --color=auto ssh-agent

启用代理后,代理ssh-agent是上一bash衍生出的子bash的子进程

root@vhost4:~#ssh-add
 Enter passphrase for /root/.ssh/id_rsa:
 Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)

root@vhost4:~#pstree|grep pstree -A3 -B3
      |-6*[mingetty]
      |-rsyslogd---3*[{rsyslogd}]
      |-sshd---sshd---