后量子密钥交换警告
连接到旧版 OpenSSH 服务器时,新版客户端(OpenSSH 9.9+)会显示如下警告:
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
原因: OpenSSH 9.9 引入了后量子密钥交换算法(如 mlkem768x25519-sha256),当服务端不支持该算法时,连接回退到经典算法,客户端发出警告,提示存在「先存后解」攻击风险。
推荐解决方案: 升级服务端 OpenSSH 到 9.9 或更高版本。
临时屏蔽警告(仅客户端): 如果无法升级服务端,可以在 ~/.ssh/config 中对该主机设置 LogLevel ERROR,屏蔽 WARNING 级别的提示:
Host bwg
LogLevel ERROR
注意:此方法只是屏蔽了警告输出,并不能消除安全风险,仅适合临时或已评估风险的场景。
SSH 连接的两个阶段
SSH 建立连接时分为两个独立阶段,使用完全不同的密钥:
阶段一:密钥交换(Key Exchange)
在连接建立之初(握手阶段),客户端和服务器通过密钥交换算法协商出一个临时的共享会话密钥,用来加密后续所有通信。这个过程发生在身份认证之前,使用的是 DH/ECDH 等算法(如 curve25519-sha256)。
后量子警告针对的就是这一步:OpenSSH 9.9 引入了 mlkem768x25519-sha256(基于 ML-KEM / CRYSTALS-Kyber),可以抵抗量子计算机攻击。
这个机制与 TLS 握手原理相同——TLS 1.3 也在推进同一套后量子算法。
阶段二:身份认证(Authentication)
加密信道建立后,才进行身份验证。你平时配置的 ~/.ssh/id_rsa 或 ~/.ssh/id_ed25519 私钥就在这一步使用:服务器发送一个随机挑战,客户端用私钥签名后发回,服务器验证签名。
私钥本身从不离开本地,网络上只传输签名,因此被动窃听者无法反推私钥。
为什么必须先建立加密信道再认证?
- 密码认证:如果没有加密信道,密码明文传输,中间人可直接截获。
- 公钥认证:即使用 Ed25519,没有加密信道也存在中间人攻击风险——攻击者可冒充服务器完成认证,之后你的所有命令和输出都暴露给攻击者。
这也是 SSH 首次连接时要求手动确认 host key fingerprint 的原因:你在确认「我连的确实是那台服务器」,而不是中间人。
Ed25519 在量子时代安全吗?
目前安全,但长远来看同样面临量子威胁。 Ed25519 基于椭圆曲线离散对数,理论上量子计算机(Shor 算法)可以破解,与 RSA 一样脆弱。
OpenSSH 目前只在密钥交换这一步完成了后量子升级;身份认证的后量子标准(如基于格密码的签名算法)仍在推进中,尚未进入 OpenSSH 主流支持。
ssh config
host host0
hostname 192.168.1.10
port 22
user root
# for openwrt ssh-rsa
HostkeyAlgorithms +ssh-rsa
PubkeyAcceptedKeyTypes +ssh-rsa
https://daemon369.github.io/ssh/2015/03/21/using-ssh-config-file
https://blog.csdn.net/XXY2083123843/article/details/128370472
vim ~/.ssh/config
#---
Host *
ControlMaster auto # ssh multiplexing
ControlPath ~/.ssh/master-%r@%h:%p
ControlPersist 10m
ForwardAgent yes # ssh agent forward
User root # 默认用户
使用通配符 (wildcard)
host 192.168.*
user root
ssh client config, 保持连接
避免SSH连接因超时闲置断开
ssh 客户端保持连接
vim ~/.ssh/config
Host 192.168.*
ServerAliveInterval 120
User root
用 SSH 过程连接电脑时,经常遇到长时间不操作而被服务器踢出的情况,常见的提示如:
Write failed: Broken pipe
这是因为如果有一段时间在SSH连接上无数据传输,连接就会断开。解决此问题有两种方法。[1]
方案一: 在客户端设置
方法很简单,只需在客户端电脑上编辑 (需要root权限) /etc/ssh/ssh_config,并添加如下一行:
ServerAliveInterval 60
此后该系统里的用户连接SSH时,每60秒会发一个KeepAlive请求,避免被踢。
方案二: 在服务器端设置
如果有相应的权限,也可以在服务器端设置,即编辑/etc/ssh/sshd_config,并添加:
ClientAliveInterval 60
重启SSH服务器后该项设置会生效。每一个连接到此服务器上的客户端都会受其影响。应注意启用该功能后,安全性会有一定下降 (比如忘记登出时……)
vim /etc/ssh/sshd_config
#添加
# ClientAliveInterval指定了服务器端向客户端请求消息的时间间隔, 默认是0,不发送。而ClientAliveInterval 60表示每分钟发送一次,然后客户端响应,这样就保持长连接了。
ClientAliveInterval 30
# ClientAliveCountMax表示服务器发出请求后客户端没有响应的次数达到一定值,就自动断开
ClientAliveCountMax 3
Session Multiplexing
https://blog.wiloon.com/?p=16030
- ssh agent forward https://blog.wiloon.com/?p=16034
指定源端口
ssh -o 'ProxyCommand nc -p 2345 %h %p' $MY_SERVER
vim /etc/ssh/sshd_config
maxstartup
这个是限制处于联机页面的连接数,默认值10。联机页面就是当你登录ssh时,还没输入密码的页面。
三元组形式
10:30:60
10: 当连接数达到10时就开始拒绝连接,不过不是全部拒绝,我们继续往下看
30: 当连接数到达10时,之后的连接有30的概率被拒绝掉
60: 当连接数达到60时,之后的连接就全部拒绝了
一个数字的形式
我们可以直接 写个60,这样言简意赅,连接数达到60之前敞开玩,达到60后就不能玩了。
maxsessions
同一地址的最大连接数,也就是同一个IP地址最大可以保持多少个链接
https://blog.csdn.net/u014686399/java/article/details/84778292
SSH 参数配置有3个层次:
命令行参数,如-p 10086, -i /path/to/identity_file 等选项来设置SSH的端口号或认证证书位置
针对某个用户的配置文件,所在路径为~/.ssh/config,默认是不存在的,需要手动创建
针对系统所有用户的配置文件,,所在路径为/etc/ssh/ssh_config
参数重要性的顺序也是1>2>3,即越近的配置重要性越高。
用户配置文件在 ~/.ssh/config, 没有的话新建一个
Host 名称(自己决定,方便输入记忆的)
HostName 主机名
Port 22
User 登录的用户名
IdentityFile 证书文件路径
Host
Host配置项标识了一个配置区段。
ssh配置项参数值可以使用通配符: *代表0~n个非空白字符,?代表一个非空白字符,!表示例外通配。
我们可以在系统配置文件中看到一个匹配所有host的默认配置区段:
cat /etc/ssh/ssh_config | grep '^Host'
Host *
这里有一些默认配置项,我们可以在用户配置文件中覆盖这些默认配置。
host router
HostName 192.168.1.1
Port 22
User root
IdentityFile ~/.ssh/id_rsa
使用ssh的配置文件可以在很大程度上方便各种操作,特别适应于有多个ssh帐号、使用非标准端口或者写脚本等情况。
man ssh_config
可以查看手册
如果之前是用密码方式来登录ssh,需要先改用证书方式。可以看最后面生成SSH证书
两个SSH帐号,一个是github的,一个是其他服务器的,证书文件正如其名,那么可以这样写
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github
注意,github的Host必须写成"github.com"。你可以会有其他要求,比如指定端口号、绑定本地端口,这些都可以通过man来查询,比如
Port 端口号
DynamicForward 本地端口号
如果服务器同时有ipv4/ipv6地址,HostName使用域名会比较方便
使用
有了这些配置,很多操作就非常简化了。比如登录服务器
ssh server
传输文件
scp server:~/test .
如果使用Putty等工具,可能需要一些其他操作(转换私钥格式,貌似),自行搜索吧
生成SSH证书
登入服务器端,生成密钥(你使用哪个用户名登录,就在哪个用户名下生成)
ssh-keygen -t rsa
会询问将密钥放在何处,默认即可。然后是输入密码,留空(否则你登录不仅需要私钥还要输入密码)。
完成后在~/.ssh目录下会生成另个文件id_rsa、id_rsa.pub,一个私钥一个公钥。接着执行
cd ~/.ssh
cat id_rsa.pub » authorized_keys
chmod 600 authorized_keys
再将id_rsa取回本地,放入~/.ssh并将权限设为400。
服务器端,删掉这两个文件,并修改sshd配置。编辑/etc/ssh/sshd_config如下
PubkeyAuthentication yes
PasswordAuthentication
是否允许使用基于密码的认证。默认为"yes"。
之后重启sshd服务
https://vra.github.io/2017/07/09/ssh-config/
http://www.lainme.com/doku.php/blog/2011/01/%E4%BD%BF%E7%94%A8ssh_config