在数据库中快速查找授权的 SSH 密钥

note 本文档描述了 authorized_keys 文件的直接替换。对于标准(非部署密钥)用户,请考虑使用 SSH 证书。它们甚至更快,但不是直接替代品。

随着用户数量的增长,常规 SSH 操作变得缓慢,因为 OpenSSH 通过线性搜索搜索密钥来授权用户。在最坏的情况下,例如当用户无权访问极狐GitLab 时,OpenSSH 会扫描整个文件连搜索密钥。这可能会花费大量时间和磁盘 I/O,从而延迟用户尝试推送或拉取仓库的时间。更糟糕的是,如果用户频繁添加或删除密钥,操作系统可能无法缓存 authorized_keys 文件,从而导致磁盘被重复访问。

极狐GitLab Shell 通过提供一种在数据库中快速索引查找来授权 SSH 用户的方法,来解决这个问题。本页介绍如何启用快速查找授权的 SSH 密钥。

caution 需要 OpenSSH 版本 6.9+,因为 AuthorizedKeysCommand 必须能够接受指纹。使用 sshd -V 检查服务器上 OpenSSH 的版本。

Geo 要求使用快速查找

云原生极狐GitLab 不同,Linux 软件包安装默认管理位于 git 用户主目录中的 authorized_keys 文件。对于大多数安装实例,此文件位于 /var/opt/gitlab/.ssh/authorized_keys 下,但您可以使用以下命令在系统上找到 authorized_keys

getent passwd git | cut -d: -f6 | awk '{print $1"/.ssh/authorized_keys"}'

authorized_keys 文件包含允许访问极狐GitLab 的用户的所有公共 SSH 密钥。但是,为了维护单一事实来源,必须将 Geo 配置为通过数据库查找执行 SSH 指纹查找。

作为设置 Geo 的一部分,您需要针对主要节点和次要节点执行以下概述的步骤,但必须仅在主要节点上取消选中**写入“授权密钥”文件 **,因为如果数据库复制正在工作,它会自动反映在次要节点上。

设置快速查找

极狐GitLab Shell 提供了一种通过对极狐GitLab 数据库进行快速索引查找来授权 SSH 用户的方法。极狐GitLab Shell 使用 SSH 密钥的指纹来检查用户是否有权访问极狐GitLab。

可以使用以下 SSH 服务器启用快速查找:

您可以通过为每个服务使用单独的端口来同时运行这两个服务。

使用 gitlab-sshd

要设置 gitlab-sshd,请参阅 gitlab-sshd 文档。 启用 gitlab-sshd 后,极狐GitLab Shell 和 gitlab-sshd 被配置为自动使用快速查找。

使用 OpenSSH

caution 需要 OpenSSH 版本 6.9+,因为 AuthorizedKeysCommand 必须能够接受指纹。使用 sshd -V 检查服务器上的 OpenSSH 版本。

将以下内容添加到您的 sshd_config 文件中。该文件通常位于 /etc/ssh/sshd_config,但如果您使用的是 Linux 软件包安装的 Docker,它位于 /assets/sshd_config

Match User git    # Apply the AuthorizedKeysCommands to the git user only
  AuthorizedKeysCommand /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-keys-check git %u %k
  AuthorizedKeysCommandUser git
Match all    # End match, settings apply to all users again

重新加载 OpenSSH:

# Debian or Ubuntu installations
sudo service ssh reload

# CentOS installations
sudo service sshd reload

通过在 authorized_keys 文件中注释掉您的用户密钥来确认 SSH 正在工作(以 # 开始注释它的行),然后从您的本地计算机尝试提取仓库或运行:

ssh -T git@gitlab.example.com

成功的拉取或欢迎消息意味着极狐GitLab 能够在数据库中找到密钥,因为它不存在于文件中。

note 对于源安装实例,该命令将位于 /home/git/gitlab-shell/bin/gitlab-shell-authorized-keys-check。您可能需要考虑在其他地方创建一个包装脚本,因为此命令必须由 root 拥有,并且不能由组或其他人写入。您还可以考虑根据需要更改此命令的所有权,但可能需要在 gitlab-shell 升级期间临时更改所有权。
caution 在确认 SSH 工作正常之前不要禁用写入;否则,文件很快就会过时。

在查找失败(很常见)的情况下,仍会扫描 authorized_keys 文件。因此,只要存在大文件,Git SSH 的性能对于许多用户来说仍然会很慢。

要禁用对 authorized_keys 文件的写入:

  1. 在左侧边栏中,选择 搜索或转到
  2. 选择 管理中心
  3. 在左侧边栏中,选择 设置 > 网络
  4. 展开 性能优化
  5. 清除 使用 authorized_keys 文件来验证 SSH 密钥 复选框。
  6. 选择 保存更改

再次,通过在 UI 中删除用户的 SSH 密钥、添加新密钥并尝试提取仓库来确认 SSH 是否正常工作。

然后您可以备份和删除您的 authorized_keys 文件以获得最佳性能。 当前用户的密钥已经存在于数据库中,因此无需迁移,无需用户重新添加其密钥。

如何返回使用 authorized_keys 文件

这个概述很简短。有关更多上下文,请参阅上述说明。

  1. 重建 authorized_keys 文件
  2. 允许写入 authorized_keys 文件。
    1. 在左侧边栏中,选择 搜索或转到
    2. 选择 管理中心
    3. 在左侧边栏中,选择 设置 > 网络
    4. 展开 性能优化
    5. 选中 使用 authorized_keys 文件来验证 SSH 密钥 复选框。
  3. 如果您使用的是 Linux 软件包安装的 Docker,请从 /etc/ssh/sshd_config/assets/sshd_config 中删除 AuthorizedKeysCommand 行。
  4. 重新加载 sshdsudo service sshd reload

SELinux 支持和限制

极狐GitLab 支持使用 SELinux 进行 authorized_keys 数据库查找。

由于 SELinux 策略是静态的,系统目前不支持更改内部网络服务器端口的功能。管理员必须为环境创建一个特殊的 .te 文件,因为它不是动态生成的。

故障排查

如果您的 SSH 传输速度或导致高 CPU 负载,请务必检查 /var/log/btmp 的大小,并确保它定期轮换或在达到一定大小后轮换。 如果这个文件非常大,极狐GitLab SSH 快速查找会导致更频繁地遇到瓶颈,从而进一步降低性能。 如果可以的话,您可以考虑在 sshd_config 中禁用 UsePAM 以避免完全读取 /var/log/btmp

在正在运行的 sshd: git 进程上运行 stracelsof 会返回调试信息。 要通过 IP x.x.x.x 的 SSH 连接在正在进行的 Git 上获取 strace,请运行:

sudo strace -s 10000 -p $(sudo netstat -tp | grep x.x.x.x | egrep 'ssh.*: git' | sed -e 's/.*ESTABLISHED *//' -e 's#/.*##')

或者为通过 SSH 进程运行的 Git 获取一个 lsof

sudo lsof -p $(sudo netstat -tp | egrep 'ssh.*: git' | head -1 | sed -e 's/.*ESTABLISHED *//' -e 's#/.*##')