Linux笔记 SSH服务

早过忘川 提交于 2019-11-28 22:28:44
一、概要
 
SSH 是 Secure Shell Protocol 的简写,由 IETF 网络工作小组(Network Working Group )制定;在进行数据传输之前,SSH先对联机数据包通过加密技术进行加密处理,加密后在进行数据传输。确保了传递的数据安全。SSH是专为远程登录会话和其他网络服务提供的安全性协议。利用 SSH 协议可以有效的防止远程管理过程中的信息泄露问题,在当前的生产环境运维工作中,绝大多数企业普遍采用SSH协议服务来代替传统的不安全的远程联机服务软件,如telnet(23端口,非加密的)等。
 
在默认状态下,SSH服务主要提供两个服务功能:
  提供类似telnet远程联机服务器的服务,即上面提到的SSH服务
  类似FTP服务的sftp-server,借助SSH协议来传输数据的。提供更安全的SFTP服务(vsftp,proftp)。
 
 
二、认证过程
 
1.认证分类与说明
 
>>>主机验证:通过主机验证,再通过该主机上的用户验证,就能唯一确定该用户的身份;一个主机上可以有很多用户,所以每台主机的验证只需一次,但主机上每个用户都需要单独进行用户验证;
>>>身份验证:一个主机上可以有很多用户,所以每台主机的验证只需一次,但主机上每个用户都需要单独进行用户验证
  常用身份验证方法:ssh支持多种身份验证,最常用的是密码验证机制和公钥认证机制,其中公钥认证机制在某些场景实现双机互信时几乎是必须的;虽然常用上述两种认证机制,但认证时的顺序默认是gssapi-with-mic,hostbased,publickey,keyboard-interactive,password;注意其中的主机认证机制hostbased不是主机验证,由于主机认证用的非常少(它所读取的认证文件为/etc/hosts.equiv或/etc/shosts.equiv),所以网络上比较少见到它的相关介绍;总的来说,通过在ssh配置文件(注意不是sshd配置文件)中使用指令PreferredAuthentications改变认证顺序不失为一种验证的效率提升方式;
 

1.1 主机验证过程

当客户端A要连接服务端B时,首先将进行主机验证过程,即判断是否曾经连接过主机B。

判断的方法是读取~/.ssh/known_hosts文件和/etc/ssh/known_hosts文件,搜索是否有主机B的主机信息(主机信息称为host key,表示主机身份标识)。如果没有搜索到对应该地址的host key,则询问是否保存主机B发送过来的host key,如果搜索到了该地址的host key,则将此host key和主机B发送过来的host key做比对,如果完全相同,则表示主机A曾经保存过主机B的host key,无需再保存,直接进入下一个过程——身份验证,如果不完全相同,则提示是否保存主机B当前使用的host key。

询问是否保存host key的过程如下所示

[root@xuexi ~]# ssh 172.16.10.6 
 The authenticity of host '172.16.10.6 (172.16.10.6)' can't be established.RSA key fingerprint is f3:f8:e2:33:b4:b1:92:0d:5b:95:3b:97:d9:3a:f0:cf.
 
Are you sure you want to continue connecting (yes/no)? yes

 

在说明身份验证过程前,先看下known_hosts文件的格式。以~/.ssh/known_hosts为例。

[root@xuexi ~]# cat ~/.ssh/known_hosts
 172.16.10.6 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC675dv1w+GDYViXxqlTspUHsQjargFPSnR9nEqCyUgm5/32jXAA3XTJ4LUGcDHBuQ3p3spW/eO5hAP9eeTv5HQzTSlykwsu9He9w3ee+TV0JjBFulfBR0weLE4ut0PurPMbthE7jIn7FVDoLqc6o64WvN8LXssPDr8WcwvARmwE7pYudmhnBIMPV/q8iLMKfquREbhdtGLzJRL9DrnO9NNKB/EeEC56GY2t76p9ThOB6ES6e/87co2HjswLGTWmPpiqY8K/LA0LbVvqRrQ05+vNoNIdEfk4MXRn/IhwAh6j46oGelMxeTaXYC+r2kVELV0EvYV/wMa8QHbFPSM6nLz
 

该文件中,每行一个host key,行首是主机名,它是搜索host key时的索引,主机名后的内容即是host key部分。以此文件为例,它表示客户端A曾经试图连接过172.16.10.6这个主机B,并保存了主机B的host key,下次连接主机B时,将搜索主机B的host key,并与172.16.10.6传送过来的host key做比较,如果能匹配上,则表示该host key确实是172.16.10.6当前使用的host key,如果不能匹配上,则表示172.16.10.6修改过host key,或者此文件中的host key被修改过。

 

主机B当前使用的host key保存在服务端B的/etc/ssh/ssh_host*文件中,这些文件是服务端B的sshd服务程序启动时重建的。以rsa算法为例,则保存在/etc/ssh/ssh_host_rsa_key和/etc/ssh/ssh_host_rsa_key.pub中,其中公钥文件/etc/ssh/ssh_host_rsa_key.pub中保存的就是host key。

[root@xuexi ~]# cat /etc/ssh/ssh_host_rsa_key.pub  # 在主机B上查看ssh-rsa 
AAAAB3NzaC1yc2EAAAADAQABAAABAQC675dv1w+GDYViXxqlTspUHsQjargFPSnR9nEqCyUgm5/32jXAA3XTJ4LUGcDHBuQ3p3spW/eO5hAP9eeTv5HQzTSlykwsu9He9w3ee+TV0JjBFulfBR0weLE4ut0PurPMbthE7jIn7FVDoLqc6o64WvN8LXssPDr8WcwvARmwE7pYudmhnBIMPV/q8iLMKfquREbhdtGLzJRL9DrnO9NNKB/EeEC56GY2t76p9ThOB6ES6e/87co2HjswLGTWmPpiqY8K/LA0LbVvqRrQ05+vNoNIdEfk4MXRn/IhwAh6j46oGelMxeTaXYC+r2kVELV0EvYV/wMa8QHbFPSM6nLz

 发现/etc/ssh/ssh_host_rsa_key.pub文件内容和~/.ssh/known_hosts中该主机的host key部分完全一致,只不过~/.ssh/known_hosts中除了host key部分还多了一个主机名,这正是搜索主机时的索引。

综上所述,在主机验证阶段,服务端持有的是私钥,客户端保存的是来自于服务端的公钥。注意,这和身份验证阶段密钥的持有方是相反的。

 

实际上,ssh并非直接比对host key,因为host key太长了,比对效率较低。所以ssh将host key转换成host key指纹,然后比对两边的host key指纹即可。指纹格式如下:

[root@xuexi ~]# ssh 172.16.10.6 
The authenticity of host '172.16.10.6 (172.16.10.6)' can't be established.RSA key fingerprint is f3:f8:e2:33:b4:b1:92:0d:5b:95:3b:97:d9:3a:f0:cf.
 
Are you sure you want to continue connecting (yes/no)? yes

host key的指纹可由ssh-kegen计算得出。例如,下面分别是主机A(172.16.10.5)保存的host key指纹,和主机B(172.16.10.6)当前使用的host key的指纹。可见它们是完全一样的。

[root@xuexi ~]# ssh-keygen -l -f ~/.ssh/known_hosts
 2048 f3:f8:e2:33:b4:b1:92:0d:5b:95:3b:97:d9:3a:f0:cf 172.16.10.6 (RSA)
 
 
[root@xuexi ~]# ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key
2048 f3:f8:e2:33:b4:b1:92:0d:5b:95:3b:97:d9:3a:f0:cf  (RSA)

 

其实ssh还支持host key模糊比较,即将host key转换为图形化的指纹。这样,图形结果相差大的很容易就比较出来。之所以说是模糊比较,是因为对于非常近似的图形化指纹,ssh可能会误判。图形化指纹的生成方式如下:只需在上述命令上加一个"-v"选项进入详细模式即可。

[root@xuexi ~]# ssh-keygen -lv -f ~/.ssh/known_hosts
 2048 f3:f8:e2:33:b4:b1:92:0d:5b:95:3b:97:d9:3a:f0:cf 172.16.10.6 (RSA)+--[ RSA 2048]----+
 
|                |
 
|                |
 
|          .    |
 
|          o      |
 
|        S. . +  |
 
|      . +++ + .  |
 
|      B.+.= .  |
 
|      + B.  +.  |
 
|      o.+.  oE  |
 
+-----------------+

  

1.2 身份验证过程

主机验证通过后,将进入身份验证阶段。SSH支持多种身份验证机制,它们的验证顺序如下:gssapi-with-mic,hostbased,publickey,keyboard-interactive,password,但常见的是密码认证机制(password)和公钥认证机制(public key)。当公钥认证机制未通过时,再进行密码认证机制的验证。这些认证顺序可以通过ssh配置文件(注意,不是sshd的配置文件)中的指令PreferredAuthentications改变。

如果使用公钥认证机制,客户端A需要将自己生成的公钥(~/.ssh/id_rsa.pub)发送到服务端B的~/.ssh/authorized_keys文件中。当进行公钥认证时,客户端将告诉服务端要使用哪个密钥对,并告诉服务端它已经访问过密钥对的私钥部分~/.ssh/id_rsa(不能直接提供给服务端匹配检测,因为私钥不能泄露),然后服务端将检测密钥对的公钥部分,判断该客户端是否允许通过认证。如果认证不通过,则进入下一个认证机制,以密码认证机制为例。

当使用密码认证时,将提示输入要连接的远程用户的密码,输入正确则验证通过。

 

1.2.1 密码认证

① 服务端生成自己的密钥,保存在/etc/ssh/目录下,该目录下存放着ssh_host_xxxkey和ssh_host_xxxkey.pub类型的文件

② 客户端发送ssh连接请求给服务器

③ 服务器把自己的公钥发送给客户端

④ 客户端保存发送过来的公钥至~/.ssh/known_hosts文件中,(我们第一次连接的时候需要敲yes就是保存公钥文件)如果之前保存过,则进行对比,一致则进行下去,不一致则报错。例如下图:

解决的办法是删除~/.ssh/known_hosts文件再重新连接。

⑤ 客户端生成自己的密钥

⑥ 客户端发送自己的公钥至服务端

⑦ 客户端用服务器的公钥对密码进行加密,然后发给服务器

⑧ 服务器用自己的私钥对公钥进行解密,获取密码,如果密码正确则允许登录

 

1.2.2 密钥登录

 

 

① 客户端生成一对密钥,生成的密钥保存在~/.ssh/(权限700)目录下,分别为id_xxx(私钥600)、id_xxx.pub(公钥644)

  客户端生成密钥:ssh-keygen [-t 密钥类型] 

② 把公钥id_xxx.pub发送给服务端,在服务端中把发送过来的公钥保存在~/.ssh/authorized_keys(644)文件中   

  拷贝公钥:ssh-copy-id -i id_xxx.pub

③ 客户端向服务端发送ssh连接请求,信息包括客户端的ip和用户名

④ 服务端收到该连接请求后,在~/.ssh/authorized_keys中查找是否有客户端的ip和用户名,如果存在的话服务端随机生成一段字符串char

⑤ 服务端用公钥authorized_keys加密char发送给客户端

⑥ 客户端收到后用私钥id_xxx解密,得到char

  在用私钥解密的之前可以加入密码:ssh-keygen -p

⑦ 客户端用服务端发送的公钥(服务端自己生成的公钥)加密char发送给服务端

⑧ 服务端收到后用私钥(服务端自己生成的私钥)解密,得到char与之前随机生成的char比对,如果一致则登录

 

实现密钥登录的方法:

① 我们要实现CentOS6密钥方式登录CentOS7,刚开始CentOS6的~/.ssh目录下并没有自己的密钥;

 

② CentOS6生成自己的密钥(公钥和私钥),白色框内的分别表示生成的密钥的文件名、是否输入密码、请再次输入密码,直接回车则保持默认,第二项的密码用在客户端用私钥解密的过程;

 

 ③ 将CentOS6生成的公钥拷贝发送给CentOS7;

 

④ 该公钥在CentOS7下的~/.ssh目录下,并按指定的命名规则命名该公钥文件;

 

⑤ 之后ssh登录就可以不用输入密码;

 

⑥ 设置客户端的私钥密码,这里的私钥密码不是服务端主机的登录密码,而是客户端在用私钥解密的时候要用到的密码。

 

 

1.3 验证通过

当主机验证和身份验证都通过后,分两种情况:直接登录或执行ssh命令行中给定某个命令。如:

[root@xuexi ~]# ssh 172.16.10.6 
 
 
[root@xuexi ~]# ssh 172.16.10.6  'echo "haha"'

(1).前者ssh命令行不带任何命令参数,表示使用远程主机上的某个用户(此处为root用户)登录到远程主机172.16.10.6上,所以远程主机会为ssh分配一个伪终端,并进入bash环境。

(2).后者ssh命令行带有命令参数,表示在远程主机上执行给定的命令【echo "haha"】。ssh命令行上的远程命令是通过fork ssh-agent得到的子进程来执行的,当命令执行完毕,子进程消逝,ssh也将退出,建立的会话和连接也都将关闭。(之所以要在这里明确说明远程命令的执行过程,是为了说明后文将介绍的ssh实现端口转发时的注意事项)

实际上,在ssh连接成功,登录或执行命令行中命令之前,可以指定要在远程执行的命令,这些命令放在~/.ssh/rc或/etc/ssh/rc文件中,也就是说,ssh连接建立之后做的第一件事是在远程主机上执行这两个文件中的命令。



三、配置文件

1.配置文件分布
 
在服务端上:
 
/etc/ssh/sshd_config :ssh服务程序sshd的配置文件。
 
/etc/ssh/ssh_host_* :服务程序sshd启动时生成的服务端公钥和私钥文件。如ssh_host_rsa_key和ssh_host_rsa_key.pub。其中.pub文件是主机验证时的host key,将写入到客户端的~/.ssh/known_hosts文件中。私钥文件严格要求权限为600,若不是则sshd服务可能会拒绝启动。
 
~/.ssh/authorized_keys:保存的是基于公钥认证机制时来自于客户端的公钥。在基于公钥认证机制认证时,服务端将读取该文件。
 
 
在客户端上:
 
/etc/ssh/ssh_config :客户端的全局配置文件。
 
~/.ssh/config :客户端的用户配置文件,生效优先级高于全局配置文件。一般该文件默认不存在。该文件对权限有严格要求只对所有者有读/写权限,对其他人完全拒绝写权限。
 
~/.ssh/known_hosts :保存主机验证时服务端主机host key的文件。文件内容来源于服务端的ssh_host_rsa_key.pub文件。
 
/etc/ssh/known_hosts:全局host key保存文件。作用等同于~/.ssh/known_hosts。
 
~/.ssh/id_rsa :客户端生成的私钥。由ssh-keygen生成。该文件严格要求权限,当其他用户对此文件有可读权限时,ssh将直接忽略该文件。
 
~/.ssh/id_rsa.pub :私钥id_rsa的配对公钥。对权限不敏感。当采用公钥认证机制时,该文件内容需要复制到服务端的~/.ssh/authorized_keys文件中。
 
~/.ssh/rc :保存的是命令列表,这些命令在ssh连接到远程主机成功时将第一时间执行,执行完这些命令之后才开始登陆或执行ssh命令行中的命令。
 
/etc/ssh/rc :作用等同于~/.ssh/rc。


2.配置文件简单介绍

分为服务端配置文件/etc/ssh/sshd_config和客户端配置文件/etc/ssh/ssh_config(全局)或~/.ssh/config(用户)。

 

2.1 sshd_config

简单介绍下该文件中主要参数含义。

Port            定义sshd服务的端口,默认为22
 
Protocol        定义ssh协议的版本号,一般为2
 
ListenAddress    定义sshd监听的IP地址,默认所有IP,若要指定则为:ListenAddress xxx.xxx.xxx.xxx
 
PidFile          定义开启sshd服务的进程ID的文件,/var/run/sshd.pid存放着PID
 
LoginGraceTime  定义输入密码阶段的宽容时间,超过该时间还没有连接成功则自动退出。默认2分钟
 
Compression      定义是否使用压缩方式传输,有yes no delayed(登录后采用压缩方式)
 
HostKey          定义sshd服务生成的密钥文件格式
 
 
SyslogFacility  定义ssh登录日志存放的文件,AUTHPRIV表示/var/log/secure
 
PermitRootLogin  表示是否允许root登录
 
StrictModes      表示是否对sshd相关的文件进行权限的检查
 
PubkeyAuthentication  表示是否允许用户密钥登录的方式
 
AuthorizedKeysFile    表示密钥登录的时候,客户端公钥需要保存为服务端的什么目录、格式,默认为.ssh/authorized_keys
 
PasswordAuthentication 表示是否需要进行密码验证
 
 
 
PermitEmptyPasswords  表示是否允许空密码登录,默认为no
 
UsePAM          表示是否使用PAM管理认证,默认为yes
 
X11Forwarding    表示是否允许图形化数据经过ssh通道转发
 
TCPKeepAlive    表示是否让ssh时刻监控TCP的连接状态
 
MaxStartups      定义允许同时出现连接输入密码界面的最大数目
 
UseDNS          表示是否对客户端进行DNS反向解析,用以判断客户端的合法性。默认为yes,如果内外互联可以设置为no
 
DenyUsers/DenyGroups  定义禁止登陆的用户和群组

 一般来说,如非有特殊需求,只需修改下监听端口和UseDNS为no以加快主机验证阶段的速度即可。

配置好后直接重启启动sshd服务即可。

[root@xuexi ~]# service sshd restart

 

 

2.2 ssh_config

需要说明的是,客户端配置文件有很多配置项和服务端配置项名称相同,但它们一个是在连接时采取的配置(客户端配置文件),一个是sshd启动时开关性的设置(服务端配置文件)。例如,两个配置文件都有GSSAPIAuthentication项,在客户端将其设置为no,表示连接时将直接跳过该身份验证机制,而在服务端设置为no则表示sshd启动时不开启GSSAPI身份验证的机制。即使客户端使用了GSSAPI认证机制,只要服务端没有开启,就绝对不可能认证通过。

下面也简单介绍该文件。

# Host *                              # Host指令是ssh_config中最重要的指令,只有ssh连接的目标主机名能匹配此处给定模式时,
 
                                      # 下面一系列配置项直到出现下一个Host指令才对此次连接生效
 
#  ForwardAgent no
 
#  ForwardX11 no
 
#  RhostsRSAAuthentication no
 
#  RSAAuthentication yes
 
#  PasswordAuthentication yes    # 是否启用基于密码的身份认证机制
 
#  HostbasedAuthentication no    # 是否启用基于主机的身份认证机制
 
#  GSSAPIAuthentication no        # 是否启用基于GSSAPI的身份认证机制
 
#  GSSAPIDelegateCredentials no
 
#  GSSAPIKeyExchange no
 
#  GSSAPITrustDNS no
 
#  BatchMode no                  # 如果设置为"yes",将禁止passphrase/password询问。比较适用于在那些不需要询问提供密
 
                                  # 码的脚本或批处理任务任务中。默认为"no"。
 
#  CheckHostIP yes
 
#  AddressFamily any
 
#  ConnectTimeout 0#  StrictHostKeyChecking ask        # 设置为"yes",ssh将从不自动添加host key到~/.ssh/known_hosts文件,
 
                                    # 且拒绝连接那些未知的主机(即未保存host key的主机或host key已改变的主机)。
 
                                    # 它将强制用户手动添加host key到~/.ssh/known_hosts中。
 
                                    # 设置为ask将询问是否保存到~/.ssh/known_hosts文件。
 
                                    # 设置为no将自动添加到~/.ssh/known_hosts文件。
 
#  IdentityFile ~/.ssh/identity    # ssh v1版使用的私钥文件
 
#  IdentityFile ~/.ssh/id_rsa      # ssh v2使用的rsa算法的私钥文件
 
#  IdentityFile ~/.ssh/id_dsa      # ssh v2使用的dsa算法的私钥文件
 
#  Port 22                          # 当命令行中不指定端口时,默认连接的远程主机上的端口
 
#  Protocol 2,1#  Cipher 3des                      # 指定ssh v1版本中加密会话时使用的加密协议
 
#  Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc  # 指定ssh v1版本中加密会话时使用的加密协议
 
#  MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160
 
#  EscapeChar ~#  Tunnel no
 
#  TunnelDevice any:any
 
#  PermitLocalCommand no    # 功能等价于~/.ssh/rc,表示是否允许ssh连接成功后在本地执行LocalCommand指令指定的命令。
 
#  LocalCommand            # 指定连接成功后要在本地执行的命令列表,当PermitLocalCommand设置为no时将自动忽略该配置
 
                            # %d表本地用户家目录,%h表示远程主机名,%l表示本地主机名,%n表示命令行上提供的主机名,
 
                            # p%表示远程ssh端口,r%表示远程用户名,u%表示本地用户名。
 
#  VisualHostKey no        # 是否开启主机验证阶段时host key的图形化指纹
 
Host *GSSAPIAuthentication yes

  如非有特殊需求,ssh客户端配置文件一般只需修改下GSSAPIAuthentication的值为no来改善下用户验证的速度即可,另外在有非交互需求时,将StrictHostKeyChecking设置为no以让主机自动添加host key。

 

 

四、相关工具
 
1.ssh
 
语法:ssh [options] [user@]hostname [command]
  option:
-b bind_address  :在本地主机上绑定用于ssh连接的地址,当系统有多个ip时才生效
-E log_file      :将debug日志写入到log_file中,而不是默认的标准错误输出stderr
-F configfile    :指定用户配置文件,默认为~/.ssh/config
-f              :请求ssh在工作在后台模式。该选项隐含了"-n"选项,所以标准输入将变为/dev/null
-i identity_file :指定公钥认证时要读取的私钥文件。默认为~/.ssh/id_rsa
-l login_name    :指定登录在远程机器上的用户名。也可以在全局配置文件中设置
-N              :显式指明ssh不执行远程命令。一般用于端口转发,见后文端口转发的示例分析
-n              :将/dev/null作为标准输入stdin,可以防止从标准输入中读取内容。ssh在后台运行时默认该项
-p port          :指定要连接远程主机上哪个端口,也可在全局配置文件中指定默认的连接端口
-q              :静默模式,大多数警告信息将不输出
-T              :禁止为ssh分配伪终端
-t              :强制分配伪终端,重复使用该选项"-tt"将进一步强制
-v              :详细模式,将输出debug消息,可用于调试,"-vvv"可更详细
-V              :显示版本号并退出
-o              :指定额外选项,选项非常多

    user@hostname

        指定ssh以远程主机hostname上的用户user连接到的远程主机上,若省略user部分,则表示使用本地当前用户
    command 
        要在远程主机上执行的命令。指定该参数时,ssh的行为将不再是登录,而是执行命令,命令执行完毕时ssh连接就关闭
 
2.scp
scp是基于ssh的远程拷贝命令,也支持本地拷贝,甚至支持远程到远程的拷贝;scp由于基于ssh,其端口也是使用ssh的端口;scp拷贝的实质是使用ssh连接到远程,并使用该连接来传输数据。
 
scp与rsync对比:
  scp只能进行全量拷贝,rsync支持增量拷贝;
  scp消耗系统资源较小,rsync需要消耗较多系统资源。
 
用法:scp [-12BCpqrv] [-l limit] [-o ssh_option] [-P port] [[user@]host1:]src_file ... [[user@]host2:]dest_file
    选项说明:
-1:使用ssh v1版本,这是默认使用协议版本
-2:使用ssh v2版本
-C:拷贝时先压缩,节省带宽
-l limit:限制拷贝速度,Kbit/s,1Byte=8bit,所以"-l 800"表示的速率是100K/S
-o ssh_option:指定ssh连接时的特殊选项,一般用不上
-p:拷贝时保持源文件的mtime,atime,owner,group,privileges
-P port:指定目标主机上ssh端口,大写的字母P,默认是22端口
-r:递归拷贝,用于拷贝目录,注意,scp拷贝遇到链接文件时,会拷贝链接的源文件内容填充到目标文件中(scp的本质就是填充而非拷贝)
-v:输出详细信息,可以用来调试或查看scp的详细过程,分析scp的机制

  

3.sftp
用法:sftp user@IP
get  下载
put  上传
ls
pwd
cd

  

 

 

 

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!