1 SSH是什么?
SSH(Secure Shell 的缩写)是一种网络协议,用于加密两台计算机之间的通信,并且支持各种身份验证机制。
实际使用中,我们往往使用它进行远程登录云主机。
需要注意的是,ssh
是一种协议,而通常我们说的是实现了这种协议的软件,例如知名的openssh
。
2 安装openssh
一般linux系统都自带ssh,如果没有就可以安装一下
sudo apt update #更新数据
sudo apt upgrade #更新软件
sudo apt install openssh-server #下载安装ssh服务的服务器
sudo apt install openssh-client #下载安装ssh服务的客户端
这里给出的是ubuntu安装命令,其它系统请参考具体的安装命令
windows一般自带ssh客户端,如果没有可以参照官方文档教程进行安装
3 SSH客户端
ssh的安装位置为:
ubuntu
系统的位置是/usr/bin/ssh
。Windows
系统的位置是C:\Program Files\OpenSSH-Win64\ssh.exe
ssh 最常见的用途就是登录服务器,这要求服务器安装并正在运行 SSH 服务器软件。
ssh 登录服务器的命令如下:
ssh hostname
上面命令中,hostname
是主机名,它可以是域名,也可能是 IP
地址或局域网内部的主机名。
不指定用户名的情况下,将使用客户端的当前用户名,作为远程服务器的登录用户名,如果要指定用户名,可以采用下面的语法:
ssh user@hostname
上面的命令中,用户名和主机名写在一起了,之间使用@
分隔。
用户名也可以使用ssh
的-l
参数指定,这样的话,用户名和主机名就不用写在一起了。
ssh -l username host
ssh
默认连接服务器的22
端口,-p
参数可以指定其他端口。
ssh -p 8821 foo.com
上面命令连接服务器foo.com
的8821
端口
3.1 连接过程
ssh 连接远程服务器后,首先有一个验证过程,验证远程服务器是否为陌生地址。
如果是第一次连接某一台服务器,命令行会显示一段文字,表示不认识这台机器,提醒用户确认是否需要连接。
The authenticity of host 'foo.com (192.168.121.111)' can't be established.
ECDSA key fingerprint is SHA256:Vybt22mVXuNuB5unE++yowF7lgA/9/2bLSiO3qmYWBY.
Are you sure you want to continue connecting (yes/no)?
上面这段文字告诉用户,foo.com
这台服务器的指纹是陌生的,让用户选择是否要继续连接(输入 yes
或 no
)。
所谓“服务器指纹”,指的是 SSH 服务器公钥的哈希值。每台 SSH 服务器都有唯一一对密钥,用于跟客户端通信,其中公钥的哈希值就可以用来识别服务器。
下面的命令可以查看某个公钥的指纹:
ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key.pub
输出:
256 da:24:43:0b:2e:c1:3f:a1:84:13:92:01:52:b4:84:ff (ECDSA)
上面的例子中,ssh-keygen -l -f
命令会输出公钥/etc/ssh/ssh_host_ecdsa_key.pub
的指纹。
ssh
会将本机连接过的所有服务器公钥的指纹,都储存在本机的~/.ssh/known_hosts
文件中。每次连接服务器时,通过该文件判断是否为陌生主机(陌生公钥)。
在上面这段文字后面,输入yes
,就可以将当前服务器的指纹也储存在本机~/.ssh/known_hosts
文件中,并显示下面的提示。以后再连接的时候,就不会再出现警告了。
Warning: Permanently added 'foo.com (192.168.121.111)' (RSA) to the list of known hosts
然后,客户端就会跟服务器建立连接。接着,ssh
就会要求用户输入所要登录账户的密码。用户输入并验证密码正确以后,就能登录远程服务器的 Shell
了。
3.2 服务器变更
服务器指纹可以防止有人恶意冒充远程主机。如果服务器的密钥发生变更(比如重装了 SSH 服务器),客户端再次连接时,就会发生公钥指纹不吻合的情况。这时,客户端就会中断连接,并显示一段警告信息。
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ 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
77:a5:69:81:9b:eb:40:76:7b:13:04:a9:6c:f4:9c:5d.
Please contact your system administrator.
Add correct host key in /home/me/.ssh/known_hosts to get rid of this message.
Offending key in /home/me/.ssh/known_hosts:36
上面这段文字的意思是,该主机的公钥指纹跟~/.ssh/known_hosts
文件储存的不一样,必须处理以后才能连接。这时,你需要确认是什么原因,使得公钥指纹发生变更,到底是恶意劫持,还是管理员变更了 SSH
服务器公钥。
如果新的公钥确认可以信任,需要继续执行连接,你可以执行下面的命令,将原来的公钥指纹从~/.ssh/known_hosts
文件删除。
ssh-keygen -R hostname
上面命令中,hostname
是发生公钥变更的主机名。
除了使用上面的命令,你也可以手工修改known_hosts
文件,将公钥指纹删除。
删除了原来的公钥指纹以后,重新执行 ssh
命令连接远程服务器,将新的指纹加入known_hosts
文件,就可以顺利连接了。
3.3 参数选择
常用几个参数如下:
- -i:指定密钥文件登录sshd服务器
- -C:压缩数据传输
- -F:指定配置文件
3.4 配置文件
SSH 客户端的全局配置文件是/etc/ssh/ssh_config
,用户个人的配置文件在~/.ssh/config
,优先级高于全局配置文件。
除了配置文件,~/.ssh
目录还有一些用户个人的密钥文件和其他文件。下面是其中一些常见的文件。
~/.ssh/id_ecdsa
:用户的 ECDSA 私钥。~/.ssh/id_ecdsa.pub
:用户的 ECDSA 公钥。~/.ssh/id_rsa
:用于 SSH 协议版本2 的 RSA 私钥。~/.ssh/id_rsa.pub
:用于SSH 协议版本2 的 RSA 公钥。~/.ssh/identity
:用于 SSH 协议版本1 的 RSA 私钥。~/.ssh/identity.pub
:用于 SSH 协议版本1 的 RSA 公钥。~/.ssh/known_hosts
:包含 SSH 服务器的公钥指纹。
用户个人的配置文件~/.ssh/config
,可以按照不同服务器,列出各自的连接参数,从而不必每一次登录都输入重复的参数。下面是一个例子:
Host *
Port 2222
Host remoteserver
HostName remote.example.com
User neo
Port 2112
上面代码中,Host *
表示对所有主机生效,后面的Port 222
2表示所有主机的默认连接端口都是2222,这样就不用在登录时特别指定端口了。
这里的缩进并不是必需的,只是为了视觉上,易于识别针对不同主机的设置。
后面的Host remoteserver
表示,下面的设置只对主机remoteserver
生效。remoteserver
只是一个别名,具体的主机由HostName
命令指定
User
和Port
这两项分别表示用户名和端口。这里的Port会覆盖上面Host *
部分的Port设置。
以后,登录remote.example.com
时,只要执行ssh remoteserver
命令,就会自动套用 config
文件里面指定的参数。 单个主机的配置格式如下。
ssh remoteserver
等同于
ssh -p 2112 neo@remote.example.com
Host命令的值可以使用通配符,比如Host *
表示对所有主机都有效的设置,Host *.edu
表示只对一级域名为.edu
的主机有效的设置。它们的设置都可以被单个主机的设置覆盖。
3.5 可选的配置选项
常用的配置选项如下:
- AddressFamily inet:表示只使用 IPv4 协议。如果设为inet6,表示只使用 IPv6 协议。
- CheckHostIP yes:检查 SSH 服务器的 IP 地址是否跟公钥数据库吻合。
- Host server.example.com:指定连接的域名或 IP 地址,也可以是别名,支持通配符。Host命令后面的所有配置,都是针对该主机的,直到下一个Host命令为止。
- HostKeyAlgorithms ssh-dss,ssh-rsa:指定密钥算法,优先级从高到低排
- HostName myserver.example.com:在Host命令使用别名的情况下,HostName指定域名或 IP 地址。
- IdentityFile keyfile:指定私钥文件。
- PasswordAuthentication no:指定是否支持密码登录。不过,这里只是客户端禁止,真正的禁止需要在 SSH 服务器设置。
- Port 2035:指定客户端连接的 SSH 服务器端口。
- PubKeyAuthentication yes:是否支持密钥登录。这里只是客户端设置,还需要在SSH 服务器进行相应设置。
4 SSH服务器
SSH 的架构是服务器/客户端模式,两端运行的软件是不一样的。OpenSSH 的客户端软件是 ssh,服务器软件是 sshd。
sshd
上面的命令运行后,如果提示sshd re-exec requires execution with an absolute path
,就需要使用绝对路径来启动。
这是为了防止有人出于各种目的,放置同名软件在$PATH变量指向的目录中,代替真正的 sshd。
可以使用以下命令查找位置
which sshd
结果:
/usr/sbin/sshd
然后进行使用:
/usr/sbin/sshd
使用方法:
sudo service ssh start # 启用
sudo service ssh restart # 重启
sudo service ssh stop # 停止
下面的命令让 sshd 在计算机下次启动时自动运行:
sudo systemctl enable sshd.service
4.1 配置文件
sshd 的配置文件在/etc/ssh目录,主配置文件是sshd_config,此外还有一些安装时生成的密钥。
- /etc/ssh/sshd_config:配置文件
- /etc/ssh/ssh_host_ecdsa_key:ECDSA 私钥。
- /etc/ssh/ssh_host_ecdsa_key.pub:ECDSA 公钥。
- /etc/ssh/ssh_host_key:用于 SSH 1 协议版本的 RSA 私钥。
- /etc/ssh/ssh_host_key.pub:用于 SSH 1 协议版本的 RSA 公钥。
- /etc/ssh/ssh_host_rsa_key:用于 SSH 2 协议版本的 RSA 私钥。
- /etc/ssh/ssh_host_rsa_key.pub:用于 SSH 2 协议版本的 RSA 公钥。
- /etc/pam.d/sshd:PAM 配置文件。
注意,如果重装 sshd,上面这些密钥都会重新生成,导致客户端重新 ssh 连接服务器时,会跳出警告,拒绝连接。为了避免这种情况,可以在重装 sshd 时,先备份/etc/ssh目录,重装后再恢复这个目录。
配置文件sshd_config的格式是,每个命令占据一行。每行都是配置项和对应的值,配置项的大小写不敏感,与值之间使用空格分隔:
Port 2034
上面的配置命令指定,配置项Port的值是2034。Port写成port也可。
配置文件还有另一种格式,就是配置项与值之间有一个等号,等号前后的空格可选:
Port = 2034
配置文件里面,#开头的行表示注释。
# 这是一行注释
注意,注释只能放在一行的开头,不能放在一行的结尾。
Port 2034 # 此处不允许注释
上面的写法是错误的,另外,空行等同于注释。
sshd 启动时会自动读取默认的配置文件。如果希望使用其他的配置文件,可以用 sshd 命令的-f参数指定。
sshd -f /usr/local/ssh/my_config
上面的命令指定 sshd 使用另一个配置文件my_config。
修改配置文件以后,可以用 sshd 命令的-t(test)检查有没有语法错误。
sshd -t
配置文件修改以后,并不会自动生效,必须重新启动 sshd。
sudo service ssh restart
4.2 密钥
sshd 有自己的一对或多对密钥。它使用密钥向客户端证明自己的身份。所有密钥都是公钥和私钥成对出现,公钥的文件名一般是私钥文件名加上后缀.pub。
DSA 格式的密钥文件默认为/etc/ssh/ssh_host_dsa_key(公钥为ssh_host_dsa_key.pub),RSA 格式的密钥为/etc/ssh/ssh_host_rsa_key(公钥为ssh_host_rsa_key.pub)。
如果需要支持 SSH 1 协议,则必须有密钥/etc/ssh/ssh_host_key。
如果密钥不是默认文件,那么可以通过配置文件sshd_config的HostKey配置项指定。默认密钥的HostKey设置如下。
# HostKey for protocol version 1
# HostKey /etc/ssh/ssh_host_key
# HostKeys for protocol version 2
# HostKey /etc/ssh/ssh_host_rsa_key
# HostKey /etc/ssh/ssh_host_dsa_ke
上面命令前面的#表示这些行都是注释,因为这是默认值,有没有这几行都一样。
如果要修改密钥,就要去掉行首的#,指定其他密钥。
HostKey /usr/local/ssh/my_dsa_key
HostKey /usr/local/ssh/my_rsa_key
HostKey /usr/local/ssh/my_old_ssh1_key
以下是对原文的精要提炼,去除了不常用或版本特有(如 SSH1 专用)内容,并重新组织为结构清晰、重点突出的总结。
4.3 常用 sshd
命令参数
-d
:打印 debug 信息,前台运行一次连接过程。-D
:前台运行,不转为守护进程。-e
:将日志输出到 stderr。-f <file>
:指定配置文件。-h <key>
:指定密钥文件。-o <option=val>
:临时设置配置项,可多个使用。-p <port>
:指定监听端口,支持多个。-t
:检查配置文件语法。
故障提示解决:
sshd re-exec requires execution with an absolute path
:使用绝对路径,如/usr/sbin/sshd
。no hostkeys available -- exiting.
:使用sudo
启动或执行sudo ssh-keygen -A
创建密钥。
4.4 常用配置项
配置项所在文件:/etc/ssh/sshd_config
4.4.1 认证控制
PasswordAuthentication no
:关闭密码登录,仅使用密钥。PermitRootLogin no|prohibit-password
:禁用 root 登录或仅允许密钥。PubkeyAuthentication yes
:启用公钥认证。PermitEmptyPasswords no
:禁止空密码登录。AllowUsers user1 user2
:允许登录的用户。DenyUsers userX
:禁止登录的用户。AllowGroups group1
/DenyGroups groupX
:按用户组限制登录。
4.4.2 连接行为
Port 22
:监听端口,可设置多个。ListenAddress 0.0.0.0
:监听地址,也可设定为内网 IP。ClientAliveInterval 180
:客户端静默多久后发送探测(秒)。ClientAliveCountMax 3
:探测失败几次后断开连接。MaxAuthTries 3
:最大认证尝试次数。MaxStartups 10:50:20
:控制并发连接。
4.4.3 安全与日志
StrictModes yes
:检查用户文件权限(建议开启)。LogLevel INFO|DEBUG
:日志级别。UseDNS no
:禁用 DNS 反查,提高连接速度。
4.4.4 其他常见项
AuthorizedKeysFile .ssh/authorized_keys
:公钥存储路径。Banner /path/to/file
:登录前显示公告。Compression yes
:启用压缩传输。ChallengeResponseAuthentication no
:关闭键盘交互认证。X11Forwarding no
:是否启用 X11 图形转发。LoginGraceTime 60
:登录等待超时时间(秒)。
4.5 配置调试与重启
- 检查配置:
sshd -t
- 重启服务:
sudo service ssh restart