SSH学习
2023-05-28
概念知识
参考: https://codecharms.me/posts/security-ssh
SSH
SSH (Secure Shell)是一种连接加密机制,能够保证我们在传送数据时,会先进行加密,并且只有通过认证的才能解密。使用的是公钥加密技术
属于client-server模型,要建立一个ssh连接的条件:
- 远端服务器要跑一个SSH daemon,默认监听端口22的连接
- 本地要用一个SSH client程序,使用SSH protocol来传送数据
SSH使用形式:
- 最基本的ssh连接远端
- tunneling 隧道
- SFTP
- SCP
SSH具体使用公钥加密的运行机制:
公钥(用于认证和让别人加密)和私钥(用于电子签名和解密)。举个例子:A要使用SSH传数据给B,此时他们都拥有了对方的公钥。过程包含5个步骤:
- A用自己的私钥给信息签名
- A用B的公钥给信息加密
- 信息传送给B
- B用自己的私钥解密
- B用A的公钥来确认签名来自A
其实SSH登陆有这三种方式:
- 密钥
- 密码
- 证书
OpenSSH
OpenSSH 是一個 SSH 協定的開源實作,也可以說是遵守 SSH 的一組工具。
sshd
是 OpenSSH 的 server component,當出現一個連線請求,sshd
會根據 client 來建立對應的連線
主要包括几个部分:ssh(客户端)、sshd(主程序)、scp、sftp、ssh-keygen、ssh-agent、ssh-add等
SSL/TLS
HTTPS的核心技术(SSL/TLS):握手,以及使用CA进行身份认证。与SSH作用有些相似,都是为了保证安全连接。但前者主要用户资料传输,后者用于执行指令。
一个实例
来自 https://codecharms.me/posts/security-ssh 的关于github的一个ssh例子:
每當我們要送訊息(指令)給 GitHub (remote server) 時,我們就可以
- 用我們的私鑰加密指令。
- 用 Github 的公鑰加密指令。
- 傳送指令到 GitHub server。
- GitHub server 用它自己的私鑰解密。
- GitHub server 用我們的公鑰來驗證我們的身份。
SSH常用命令
登陆
# 没有指定用户名的登陆,默认用当前用户名登陆。第一次连接时,需要确认目标主机的真实性,通常需要输入yes
ssh 域名/ip
# 指定用户名登陆
ssh username@host
# 指定特定端口登陆(默认22端口)
ssh xxx -p 1234
# 用户名和主机名不用写一起
ssh -l username host
远程执行命令
# 如果只是想执行一条命令,直接在后面跟上命令即可
ssh xxx ls -l
服务器指纹
当ssh首次连接某个远程服务器时,会有这个确认提示:
The authenticity of host 'xxx' can't be established.
ECDSA key fingerprint is SHA256:Vybt22mVXuNuB5unE++yowF7lgA/9/2bLSiO3qmYWBY.
Are you sure you want to continue connecting (yes/no)?
# 输入yes后
Warning: Permanently added 'foo.com (192.168.121.111)' (RSA) to the list of known hosts
这里的sha256就是所谓的服务器指纹,也就是该远程服务器的公钥的哈希值。
这是因为首次连接时,对于本机来说远程服务器是陌生的,所以需要额外确认下服务器指纹。输入yes,就会将该指纹写入本机的~/.ssh/known_hosts
中。每次连接时,服务器会判断欲连接的远程主机是否已在此known_hosts文件中,如果在,就不弹出确认提示。
此外,查看公钥的指纹命令:
$ 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;或是通过虚拟地址可连接主备机中的主机,当主备切换时,连接实际主机的公钥信息也不同),此时需要会有这样的警告:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ 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
中删掉,或直接vi进入文件删除对应行:
ssh-keygen -R hostname
此后,再次尝试连接,并将新的公钥指纹添加进来即可。
参考:https://ronpad.com/docs/ssh/client-3.html
配置文件
sshd配置文件(服务端配置文件)
路径:/etc/ssh/sshd_config
格式:
- 每个命令占据一行,大小写不敏感
- 中间用空格或等号连接,如
port 2034
或port = 2034
#
开头的行表示注释,但是#
只能放在开头
修改完配置文件后:
# 可以用此命令检查语法错误(-t:test)
sshd -t
# 需要重启sshd才能生效
sudo systemctl restart sshd.service
配置项
sshd配置文件中支持很多配置项,这里就先了解一些我认为常用的吧!
- AllowGroups 允许登陆的用户组
- AllowUsers 允许登陆的用户(也可用user@address的形式),用空格或多行指定(如果不指定,默认所有用户可登陆)
- AllowTCPForwarding 是否允许端口转发,默认yes。local表示只允许本地转发,remote表示只允许远程端口转发
- ClientAliveInterval 允许客户不输入的间隔时间,超过这段时间,用户没发任何信号的话会自动关闭SSH连接
- DenyGroups 指定不允许登陆的用户组
- DenyUsers 指定不允许登陆的用户
- PermitRootLogin 是否允许root用户登陆,默认yes,建议改为no
- Port 指定sshd监听的端口(默认22),可以通过配置多行来同时监听多个端口
- PubKeyAuthentication 是否允许公钥登陆,默认yes
- X11Forwarding 指定是否打开X window的转发,默认no
参考:https://ronpad.com/docs/ssh/server-2.html
ssh配置文件(客户端配置文件)
路径:/etc/ssh/ssh_config,用户个人的配置文件在~/.ssh/config,优先级高于全局的
个人连接配置文件设置
可以在~/.ssh/config
中设置连接各个远程主机的默认连接参数,例如:
Host *
Port 2222
Host remoteserver
HostName remote.example.com
User neo
Port 2112
上面代码中,
Host *
表示对所有主机生效,后面的Port 2222
表示所有主机的默认连接端口都是2222,这样就不用在登录时特别指定端口了。这里的缩进并不是必需的,只是为了视觉上,易于识别针对不同主机的设置。
配置项
同理,就先列举出一些我认为常用的吧!
- checkHostIP 检查SSH服务器的IP地址是否和公钥数据库吻合
- Port 指定客户端连接的SSH服务器端口
- PubKeyAuthentication 是否支持密钥登陆,还需要在服务端配置
- StrictHostKeyChecking
yes
表示严格检查,服务器公钥为未知或发生变化,则拒绝连接。no
表示如果服务器公钥未知,则加入客户端公钥数据库,如果公钥发生变化,不改变客户端公钥数据库,输出一条警告,依然允许连接继续进行。ask
(默认值)表示询问用户是否继续进行。(详细分析见下面会单独给出)
端口转发
SSH除了作为登陆远程服务器的作用,还可以作为加密通信的中介。比如在两台无加密的服务器之间的充当加密通信的跳板。这个功能称为端口转发(port forwarding),也称为SSH 隧道(tunnel)。
- 动态转发
- 本地转发
- 远程转发
StrictHostKeyChecking
用于ssh连接时指定是否要进行远程主机的公钥确认,可以有这三种取值:
- no:如果key在本地不存在,则直接添加到known_hosts中,只给出警告,并不会停下来
- ask:默认的级别,如果连接时判断到远程key不匹配,则给出交互式提示,不会直接登陆
- yes:如果不匹配,拒绝连接,不会提示详细信息
该参数的配置在:
- ssh客户端配置文件 /etc/ssh/ssh_config
- 当前用户的ssh配置文件 ~/.ssh/config
- 直接在ssh命令中指定:
ssh -o StrictHostKeyChecking=no ....
参考:https://www.cnblogs.com/aspirant/p/10654041.html