什么是SSH
Secure Shell (SSH) 是一个允许两台电脑之间通过安全的连接进行数据交换 的网络协议。
传统:FTP、Telnet 是再网络中明文传送数据、用户帐号和密码,很容易受到中间人攻击 。
SSH:利用 SSH 协议 可以有效防止远程管理过程中的信息泄露问题。通过SSH可以对所有传输的数据进行加 密,也能够防止 DNS 欺骗和 IP 欺骗。
补充:SSH使用的是非对称加密的一种:使用公钥和私钥进行加密和解密,一般使用公钥加密,私钥解密。
SSH的身份验证阶段,SSH只支持服务端保留公钥,客户端保留私钥的方式,所以方式只有两种:客户端生成密钥对,将公钥分发给服务端;服务端生成密钥对,将私钥分发给客户端。只不过出于安全性和便利性,一般都是客户端生成密钥对并分发公钥。
SSH概要
SSH是会话层上的协议
SSH服务的守护进程是sshd,默认监听在22端口
SSH客户端命令读取两个配置文件,也可以在输入命令时配置。
- 全局:/etc/ssh/ssh_config
- 用户:~/.ssh/config
- 优先级:命令配置>用户>全局
SSH涉及到两个验证:主机验证、用户验证
SSH支持多种身份验证,它们的验证顺序如下:gssapi-with-mic,hostbased,publickey,keyboard-interactive,password,但常见的是密码认证机制(password)和公钥认证机制(public key)。
SSH客户端有很多强大的功能:端口转发、代理认证、连接共享等
SSH服务端配置文件为/etc/ssh/sshd_config(与客户端配置文件区分开)
易被忽略:SSH登陆会被分配一个伪终端,可以配置sudo这种身份验证程序被禁止使用
主机验证过程
客户端输入以下命令之后,首先进行主机验证过程
1 | ssh ip_addr |
客户端首先读取~/.ssh/known_hosts文件和/etc/ssh/known_hosts文件,看其中是否存储了服务端的主机信息(host key),如果没有,询问是否保存该服务端的主机信息;如果有,直接进入身份验证
服务端的host key在/etc/ssh/ssh_host_*.pub文件中(不同加密算法不同,在sshd服务程序启动时重建)
主机验证阶段:服务端持有的是私钥,客户端保存的是服务端的公钥,这和身份验证阶段密钥持有方相反
补充:实际上ssh对比的不是host key,因为太长了,对比的是host key的指纹。指纹可以通过ssh-kegen计算得出。ssh还支持host key的模糊比较(图形对比)。
更详细的主机认证过程是:先进行密钥交换(DH算法)生成session key(rfc文档中称之为shared secret),然后从文件中读取host key,并用host key对session key进行签名,然后对签名后的指纹进行判断。
身份认证过程
常见的身份认证为密码认证和公钥认证,当公钥认证机制未通过时,再进行密码认证机制。认证顺序可以通过ssh配置文件中的指令PerferredAuthentications改变。
- 公钥认证:客户端需将自己生成的公钥(
/.ssh/id_*.pub)发送到服务端的/.ssh/authorized_keys文件中。认证时将私钥推导或者公钥指纹(不同版本)发给服务端。服务端判断是否认证通过,如果认证不通过,则进入下一个认证机制:密码认证机制。 - 密码认证:输入服务端用户密码。
配置文件分布
服务端:
- /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。
简单介绍sshd_config指令
1 | Port 22 # 服务端SSH端口,可以指定多条表示监听在多个端口上 |
关于/etc/ssh/sshd_config的更多配置选项参考sshd_config中文文档
简单介绍ssh_config文件相关指令
1 | Host * # Host指令是ssh_config中最重要的指令,只有ssh连接的目标主机名能匹配此处给定模式时, |
关于上述配置文件的相关内容参考相关链接
ssh命令
1 | ssh [options] [user@]hostname [command] |
如果要ssh免密登陆可以使用以下命令:
1 | id_ed25519.pub改为自己的算法对应的文件名,ip_addr改为自己的服务端ip |
或者直接使用提供好的命令:
1 | 该命令可以直接将公钥分发给服务端,具体实现逻辑和上述命令相同 |
scp命令
scp是基于ssh的远程拷贝命令,也支持本地拷贝,甚至支持远程到远程的拷贝。scp拷贝是使用的22端口,其实质是使用ssh连接到远程,并使用该连接来传输数据。
具体使用方式如下:
1 | scp [-12BCpqrv] [-l limit] [-o ssh_option] [-P port] [[user@]host1:]src_file ... [[user@]host2:]dest_file |
(1).本地拷贝到本地:/etc/fstab–>/tmp/a.txt。
1 | scp /etc/fstab /tmp/a.txt |
(2).本地到远程:/etc/fstab–>ip_addr:/tmp/a.txt。
1 | scp /etc/fstab ip_addr:/tmp |
(3).远程到本地:ip_addr:/etc/fstab–>/tmp/a.txt。
1 | scp ip_addr:/etc/fstab /tmp/a.txt |
(4).远程ip_addr1到远程ip_addr2:ip_addr1:/etc/fstab–>/ip_addr2:/tmp/a.txt。
1 | scp ip_addr1:/etc/fstab ip_addr2:/tmp/a.txt |
生成密钥对
ssh-keygen 命令用于为 ssh 生成、管理和转换认证密钥,它支持 RSA 和 DSA 两种认 证密钥。
该命令的选项:
1 | 常用的选项 |
生成密钥对时,有一个选项要求你设置密码(passphrase),该密码是用来保护你的私钥的 密码。如果设置了则在使用私钥时会要求你输入这个密码;一般不设置,记不住【之后 还可更改此密码,使用ssh-keygen -p
】。
生成后最好将私钥进行备份。
常用的两种加密方式:
- 为了安全考虑如果使用 rsa 加密方式则指定密钥长度为
-b 4096
(1024 的密钥长度能够被破解,建议指定为 4096)。 - 但现在有了更安全的加密方式 ed25519 ,这是目前最受推荐的公钥算法。当使用 ed25519 加密方式时,它会忽略
-b
选项,因为它的长度是固定的。生成的密钥更紧凑 、更短(仅包含 68 个字符)、在签名验证时也更快并且还更安全。它还将使用新的 OpenSSH 格式(OpenSSH 6.5+)而不是 PEM 格式保存私钥,Windows10 中的 OpenSSH 最先支持的也是 ed25519 类型的密钥。
使用 rsa 加密方式的示例:
1 | ssh-keygen -t rsa -C "注释" -b 4096 |
使用 ed25519 加密方式生成密钥的示例:
1 | ssh-keygen -t ed25519 -C "注释" # 默认的密钥文件中将带有ed25519,比如: ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub |
公钥是一串很长的字符;为了便于肉眼比对和识别,所以有了指纹这东西;指纹位数短 ,更便于识别且与公钥一一对应。
公钥加密指纹 fingerprint 有两种形式:
- 之前的十六进制形式:
16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
- 现在使用 sha256 哈希值并且使用 base64 进行格式 :
SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8