SSH详解
什么是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这种身份验证程序被禁止使用**
主机验证过程¶
客户端输入以下命令之后,首先进行主机验证过程**
ssh ip_addr
补充:实际上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指令
#Port 22 # 服务端SSH端口,可以指定多条表示监听在多个端口上
#ListenAddress 0.0.0.0 # 监听的IP地址。0.0.0.0表示监听所有IP
Protocol 2 # 使用SSH 2版本
#####################################
# 私钥保存位置 #
#####################################
# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key # SSH 1保存位置/etc/ssh/ssh_host_key
# HostKeys for protocol version 2
#HostKey /etc/ssh/ssh_host_rsa_key # SSH 2保存RSA位置/etc/ssh/ssh_host_rsa _key
#HostKey /etc/ssh/ssh_host_dsa_key # SSH 2保存DSA位置/etc/ssh/ssh_host_dsa _key
###################################
# 杂项配置 #
###################################
#PidFile /var/run/sshd.pid # 服务程序sshd的PID的文件路径
#ServerKeyBits 1024 # 服务器生成的密钥长度
#SyslogFacility AUTH # 使用哪个syslog设施记录ssh日志。日志路径默认为/var/log/secure
#LogLevel INFO # 记录SSH的日志级别为INFO
###################################
# 以下项影响认证速度 #
###################################
#UseDNS yes # 指定是否将客户端主机名解析为IP,以检查此主机名是否与其IP地址真实对应。默认yes。
# 由此可知该项影响的是主机验证阶段。建议在未配置DNS解析时,将其设置为no,否则主机验证阶段会很慢
###################################
# 以下是和安全有关的配置 #
###################################
#PermitRootLogin yes # 是否允许root用户登录
#GSSAPIAuthentication no # 是否开启GSSAPI身份认证机制,默认为yes
#PubkeyAuthentication yes # 是否开启基于公钥认证机制
#AuthorizedKeysFile .ssh/authorized_keys # 基于公钥认证机制时,来自客户端的公钥的存放位置
PasswordAuthentication yes # 是否使用密码验证,如果使用密钥对验证可以关了它
#PermitEmptyPasswords no # 是否允许空密码,如果上面的那项是yes,这里最好设置no
#MaxSessions 10 # 最大客户端连接数量
#LoginGraceTime 2m # 身份验证阶段的超时时间,若在此超时期间内未完成身份验证将自动断开
#MaxAuthTries 6 # 指定每个连接最大允许的认证次数。默认值是6。
# 如果失败认证次数超过该值一半,将被强制断开,且生成额外日志消息。
MaxStartups 10 # 最大允许保持多少个未认证的连接。默认值10。
###################################
# 以下可以自行添加到配置文件 #
###################################
DenyGroups hellogroup testgroup # 表示hellogroup和testgroup组中的成员不允许使用sshd服务,即拒绝这些用户连接
DenyUsers hello test # 表示用户hello和test不能使用sshd服务,即拒绝这些用户连接
###################################
# 以下一项和远程端口转发有关 #
###################################
#GatewayPorts no # 设置为yes表示sshd允许被远程主机所设置的本地转发端口绑定在非环回地址上
# 默认值为no,表示远程主机设置的本地转发端口只能绑定在环回地址上,见后文"远程端口转发"
# 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,[email protected],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命令¶
ssh [options] [user@]hostname [command]
参数说明:
-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部分,则表示使用本地当前用户。
:如果在hostname上不存在user用户,则连接将失败(将不断进行身份验证)。
command :要在远程主机上执行的命令。指定该参数时,ssh的行为将不再是登录,而是执行命令,命令执行完毕时ssh连接就关闭。
#id_ed25519.pub改为自己的算法对应的文件名,ip_addr改为自己的服务端ip
cat ~/.ssh/id_ed25519.pub | ssh ip_addr "umask 077; test -d ~/.ssh || mkdir ~/.ssh ; cat >> ~/.ssh/authorized_keys"
#该命令可以直接将公钥分发给服务端,具体实现逻辑和上述命令相同
ssh-copy-id ip_addr
scp命令¶
scp是基于ssh的远程拷贝命令,也支持本地拷贝,甚至支持远程到远程的拷贝。scp拷贝是使用的22端口,其实质是使用ssh连接到远程,并使用该连接来传输数据。 具体使用方式如下:
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 port:指定目标主机上ssh端口,大写的字母P,默认是22端口
-p:拷贝时保持源文件的mtime,atime,owner,group,privileges
-r:递归拷贝,用于拷贝目录。注意,scp拷贝遇到链接文件时,会拷贝链接的源文件内容填充到目标文件中(scp的本质就是填充而非拷贝)
-v:输出详细信息,可以用来调试或查看scp的详细过程,分析scp的机制
scp /etc/fstab /tmp/a.txt
scp /etc/fstab ip_addr:/tmp
scp ip_addr:/etc/fstab /tmp/a.txt
scp ip_addr1:/etc/fstab ip_addr2:/tmp/a.txt
生成密钥对¶
ssh-keygen 命令用于为 ssh 生成、管理和转换认证密钥,它支持 RSA 和 DSA 两种认 证密钥。 该命令的选项:
# 常用的选项
-b:指定密钥长度;
-C:添加注释;用于为指定注释,可以是任何内容,通常使用自己的邮件名作为注释。
-f:指定用来保存密钥的文件名;
-t:指定要创建的密钥类型(加密方式);
-e:读取openssh的私钥或者公钥文件;
-i:读取未加密的ssh-v2兼容的私钥/公钥文件,然后在标准输出设备上显示openssh兼容的私钥/公钥;
-l:显示公钥文件的指纹数据;
-N:提供一个新密语;
-P:提供(旧)密语;
-q:静默模式;
ssh-keygen -p
】。
生成后最好将私钥进行备份。
常用的两种加密方式:
* 为了安全考虑如果使用 rsa 加密方式则指定密钥长度为 -b 4096
(1024 的密钥长度能够被破解,建议指定为 4096)。
* 但现在有了更安全的加密方式 ed25519 ,这是目前最受推荐的公钥算法。当使用 ed25519 加密方式时,它会忽略 -b
选项,因为它的长度是固定的。生成的密钥更紧凑 、更短(仅包含 68 个字符)、在签名验证时也更快并且还更安全。它还将使用新的 OpenSSH 格式(OpenSSH 6.5+)而不是 PEM 格式保存私钥,Windows10 中的 OpenSSH 最先支持的也是 ed25519 类型的密钥。
使用 rsa 加密方式的示例:
$ ssh-keygen -t rsa -C "注释" -b 4096
Generating public/private rsa key pair.
# 指定密钥文件名称;直接回车则使用默认名称 id_rsa
Enter file in which to save the key (/home/xxx/.ssh/id_rsa):
# 输入密码(一般不输入密码,直接回车)
Enter passphrase (empty for no passphrase):
# 再次输入密码
Enter same passphrase again:
Your identification has been saved in /home/fan/.ssh/FDGitHub_rsa.
Your public key has been saved in /home/xxx/.ssh/id_rsa.pub. The key fingerprint is:
***********************
# 注意在其他地方导入公钥时一定要将公钥文件中的 *全部内容* 都导入,包括末尾你的邮箱。
ssh-keygen -t ed25519 -C "注释" # 默认的密钥文件中将带有ed25519,比如: ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub
16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
* 现在使用 sha256 哈希值并且使用 base64 进行格式 :SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8