diff --git a/docs/EzHub-SSH诊断报告.md b/docs/EzHub-SSH诊断报告.md new file mode 100644 index 0000000..dadf0ee --- /dev/null +++ b/docs/EzHub-SSH诊断报告.md @@ -0,0 +1,216 @@ +# EzHub SSH 无法认证 —— 诊断报告 + +> 给 EzHub 运维看的。客户端的证据都在这,含完整复现步骤。 + +--- + +## 结论先说 + +**EzHub 的 SSH 是系统 OpenSSH 在处理,但它的 `git` 用户 `authorized_keys` +里没有网页上注册的公钥。** + +Forgejo/Gitea 把公钥存在**自己的数据库**里,不会自动写进 +`~git/.ssh/authorized_keys`。要么开启内置 SSH 服务, +要么给 sshd 配 `AuthorizedKeysCommand` 去问 Forgejo。现在两个都没做, +所以公钥加了也没用。 + +--- + +## 客户端证据 + +### 1. 密钥是对的 + +``` +EzHub 网页上注册的: + id=1 title=ykxmz + key=ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMFMh2Zqwm+8KFhU3DhzhOO5Sx7cIzybYqUsrbt1c3ly ykxmz-ezhub + fingerprint=SHA256:Acmu49YQcjw3m5WefOXSBzYNY2WPHLL2vvhnlYRAttA + 创建于=2026-10-07T04:22:13Z + +客户端本机的: + key=ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMFMh2Zqwm+8KFhU3DhzhOO5Sx7cIzybYqUsrbt1c3ly ykxmz-ezhub + fingerprint=SHA256:Acmu49YQcjw3m5WefOXSBzYNY2WPHLL2vvhnlYRAttA +``` + +**指纹完全一致**,公钥内容逐字符相同。(通过 +`GET /api/v1/user/keys` 读的,不是截图对比。) + +### 2. 客户端确实把钥匙送出去了 + +`ssh -vv` 的输出: + +``` +debug1: Offering public key: /c/Users/shu/.ssh/id_ed25519_ezhub + ED25519 SHA256:Acmu49YQcjw3m5WefOXSBzYNY2WPHLL2vvhnlYRAttA explicit +``` + +### 3. 服务端拒绝了 + +``` +debug1: Authentications that can continue: publickey,password +debug1: Authentications that can continue: publickey,password +Permission denied, please try again. +git@git.261826.xyz: Permission denied (publickey,password). +``` + +### 4. 服务端是系统 OpenSSH,不是 Forgejo 内置的 + +``` +debug1: Remote protocol version 2.0, + remote software version OpenSSH_9.6p1 Ubuntu-3ubuntu13.19 +``` + +**这条是判定的关键。** Forgejo/Gitea 内置的 SSH 服务 +(`START_SSH_SERVER = true`)banner 会带自己的标识, +而且**只支持 publickey**,不会提供 `password` 这个选项。 + +现在服务端说 `publickey,password` —— 这是 Ubuntu 系统 sshd 的默认行为, +说明 22 端口上是系统 OpenSSH 在接,跟 Forgejo 无关。 + +### 5. 只用 22 端口 + +``` +22 : 开 +2222 : 不通 +2022 : 不通 +22022 : 不通 +``` + +说明 Forgejo 没开内置 SSH(内置的默认在 2222)。 + +--- + +## 复现步骤 + +```bash +ssh -vv -T git@git.261826.xyz +# 观察三行: +# Remote protocol version ... OpenSSH_9.6p1 Ubuntu <- 系统 sshd +# Offering public key: ... SHA256:Acmu49YQ... <- 钥匙送出去了 +# Authentications that can continue: publickey,password <- 被拒 +# 最后 Permission denied +``` + +用 `git` 也一样: + +```bash +GIT_SSH_COMMAND='ssh -v' git ls-remote ssh://git@git.261826.xyz/xmz/ykxmz.git +# fatal: Could not read from remote repository. +``` + +--- + +## 服务端怎么修(任选一种) + +### 方案 A:开启内置 SSH 服务(推荐,最省事) + +编辑 Forgejo 的 `app.ini`(通常在 `/etc/forgejo/app.ini` +或 `/var/lib/forgejo/custom/conf/app.ini`): + +```ini +[server] +START_SSH_SERVER = true +SSH_PORT = 2222 +SSH_LISTEN_HOST = 0.0.0.0 +``` + +然后: + +```bash +systemctl restart forgejo +# 放行防火墙 +ufw allow 2222/tcp # 或 firewall-cmd / 安全组放行 +# 确认在监听 +ss -lntp | grep 2222 +``` + +**注意**:开启后克隆地址会变成 +`ssh://git@git.261826.xyz:2222/xmz/ykxmz.git`(**带端口**)。 +如果希望用户不带端口,要么把内置服务直接放在 22 上 +(那就得让系统 sshd 让位),要么用方案 B。 + +### 方案 B:继续用系统 OpenSSH,让它去问 Forgejo + +在 `/etc/ssh/sshd_config` 里加: + +```apache +AuthorizedKeysCommand /usr/bin/forgejo keys -e git -u %u -t %t -k %k +AuthorizedKeysCommandUser git +``` + +**路径按实际改**。先确认二进制在哪: + +```bash +which forgejo gitea +# 常见位置: +# /usr/bin/forgejo +# /usr/local/bin/forgejo +# /usr/local/bin/gitea +``` + +也可以先手动试一下命令能不能跑通(把 `<你的公钥>` 换成实际内容): + +```bash +sudo -u git /usr/bin/forgejo keys -e git -u git -t ssh-ed25519 -k '<你的公钥>' +# 能返回一行 command="..." 开头的 authorized_keys 格式,就说明对了 +``` + +如果报 `command not found` 或权限错,就是路径或用户不对。 + +然后: + +```bash +sshd -t # 先验证配置语法 +systemctl reload ssh # 或 systemctl reload sshd +``` + +**注意 `AuthorizedKeysCommandUser` 必须是 Forgejo 能读数据库的那个用户** +(一般就是运行 Forgejo 的用户,常是 `git`)。配错会静默失败, +日志在 `/var/log/auth.log`。 + +--- + +## 排查时可以先看这几处 + +```bash +# 1. Forgejo 当前的 SSH 相关配置 +grep -A8 '^\[server\]' /etc/forgejo/app.ini + +# 2. sshd 有没有配 AuthorizedKeysCommand +grep -i -A2 authorizedkeys /etc/ssh/sshd_config + +# 3. git 用户的 authorized_keys 到底有没有内容 +sudo ls -la ~git/.ssh/ +sudo cat ~git/.ssh/authorized_keys +# 如果这个文件不存在或是空的 —— 就是本文说的问题 + +# 4. Forgejo 有没有在内置 SSH 上监听 +ss -lntp | grep -E ':(22|2222)' + +# 5. 认证失败的具体原因(最有用) +sudo tail -50 /var/log/auth.log | grep -i ssh +``` + +`/var/log/auth.log` 里会明确写是 +`Failed publickey for git` 还是 `invalid user`, +一看就清楚。 + +--- + +## 附:客户端用的公钥 + +``` +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMFMh2Zqwm+8KFhU3DhzhOO5Sx7cIzybYqUsrbt1c3ly ykxmz-ezhub +``` + +指纹 `SHA256:Acmu49YQcjw3m5WefOXSBzYNY2WPHLL2vvhnlYRAttA`。 + +**不用再让客户端换密钥或重加** —— 网页上那条已经是对的。 + +--- + +## 补充:目前用 HTTPS + 令牌可以正常工作 + +修 SSH 之前,客户端改用 HTTPS + 访问令牌推代码是通的 +(`write:repository` 权限),内容完全一样,不影响使用。 +所以这个问题**不紧急**,方便的时候再修。