后量子密钥交换警告

连接到旧版 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 -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