# 使用 SSH 代理转发

为简化向服务器的部署，您可以设置 SSH 代理转发以安全地使用本地 SSH 密钥。

SSH 代理转发可用于简化向服务器的部署。 它允许您使用本地 SSH 密钥，而不是将密钥（不带密码！）放在服务器上。

如果已设置 SSH 密钥来与 GitHub 交互，你可能已经熟悉 `ssh-agent`。 这是一个在后台运行的程序，它将密钥加载到内存中，因此您不需要每次使用密钥时都输入密码。 最妙的是，你可以选择让服务器访问你的本地 `ssh-agent`，就像它们已经在服务器上运行一样。 这有点像要求朋友输入他们的密码，以便您可以使用他们的计算机。

有关 SSH 代理转发的更详细说明，请参阅 [Steve Friedl 的技术提示指南](http://www.unixwiz.net/techtips/ssh-agent-forwarding.html)。

## 设置 SSH 代理转发

确保您自己的 SSH 密钥已设置并正常运行。 如果你还没有 SSH 密钥，请使用[我们的 SSH 密钥生成指南](/zh/enterprise-server@3.22/authentication/connecting-to-github-with-ssh)。

可以通过在终端输入 `ssh -T git@hostname` 来测试本地密钥是否正常工作：

```shell
$ ssh -T git@hostname
# Attempt to SSH in to github
> Hi USERNAME! You've successfully authenticated, but GitHub does not provide
> shell access.
```

开局不错。 让我们设置 SSH 以允许代理转发到您的服务器。

1. 使用你喜欢的文本编辑器打开位于 `~/.ssh/config` 的文件。 如果此文件不存在，则可以通过在终端中输入 `touch ~/.ssh/config` 来创建它。

2. 在文件中输入以下文本，将 `example.com` 替换为服务器的域名或 IP：

   ```
    Host example.com
   ```

ForwardAgent yes

> \[!WARNING]
> 你可能想使用 `Host *` 这样的通配符将此设置应用于所有 SSH 连接。 但这并不是一个好主意，因为你将与通过 SSH 连接到的每台服务器共享你的本地 SSH 密钥。 它们无法直接访问密钥，但是在建立连接后，它们可以像你一样使用这些密钥。 你应该只添加你信任并计划通过代理转发功能使用的服务器。

## 测试 SSH 代理转发

要测试代理转发是否适用于你的服务器，可以通过 SSH 连接到服务器，然后再次运行 `ssh -T git@hostname`。 如果一切正常，您将收到与本地使用相同的提示。

如果不确定是否在使用本地密钥，还可以检查服务器上的 `SSH_AUTH_SOCK` 变量：

```shell
$ echo "$SSH_AUTH_SOCK"
# Print out the SSH_AUTH_SOCK variable
> /tmp/ssh-4hNGMk8AZX/agent.79453
```

如果未设置变量，则表示代理转发不起作用：

```shell
$ echo "$SSH_AUTH_SOCK"
# Print out the SSH_AUTH_SOCK variable
> [No output]
$ ssh -T git@hostname
# Try to SSH to github
> Permission denied (publickey).
```

## SSH 代理转发疑难解答

以下是排查 SSH 代理转发时需要注意的一些事项。

### 您必须使用 SSH URL 检出代码

SSH 转发仅适用于 SSH URL，而不是 HTTP(s) URL。 检查服务器上的 `.git/config` 文件，并确保 URL 是 SSH 样式的 URL，如下所示：

```shell
[remote "origin"]
  url = git@hostname:YOUR_ACCOUNT/YOUR_PROJECT.git
  fetch = +refs/heads/*:refs/remotes/origin/*
```

### 您的 SSH 密钥必须在本地有效

在通过代理转发使密钥起作用之前，它们必须首先在本地有效。
[我们的 SSH 密钥生成指南](/zh/enterprise-server@3.22/authentication/connecting-to-github-with-ssh)可帮助你在本地设置 SSH 密钥。

### 您的系统必须允许 SSH 代理转发

有时，系统配置不允许 SSH 代理转发。 您可以通过在终端中输入以下命令来检查是否正在使用系统配置文件：

```shell
$ ssh -v URL
# Connect to the specified URL with verbose debug output
> OpenSSH_8.1p1, LibreSSL 2.7.3
> debug1: Reading configuration data /Users/YOU/.ssh/config
> debug1: Applying options for example.com
> debug1: Reading configuration data /etc/ssh_config
> debug1: Applying options for *
$ exit
# Returns to your local command prompt
```

在上面的示例中，首先加载文件 `~/.ssh/config`，然后读取 `/etc/ssh_config`。 通过运行以下命令，我们可以检查该文件以查看它是否覆盖了我们的选项：

```shell
$ cat /etc/ssh_config
# Print out the /etc/ssh_config file
> Host *
>   SendEnv LANG LC_*
>   ForwardAgent no
```

在此示例中，我们的 `/etc/ssh_config` 文件特别表示 `ForwardAgent no`，这是一种阻止代理转发的方式。 从文件中删除此行应该会使代理转发再次起作用。

### 您的服务器必须允许入站连接上的 SSH 代理转发

代理转发也可能在您的服务器上被阻止。 可以通过 SSH 连接到服务器并运行 `sshd_config`，以检查是否允许代理转发。 此命令的输出应指示已设置 `AllowAgentForwarding`。

### 本地 `ssh-agent` 必须正在运行

在大多数计算机上，操作系统会自动为你启动 `ssh-agent`。 但是，在Windows上，需要手动执行此作。 我们提供了[有关如何在打开 Git Bash 时启动 `ssh-agent` 的指南](/zh/enterprise-server@3.22/authentication/connecting-to-github-with-ssh/working-with-ssh-key-passphrases#auto-launching-ssh-agent-on-git-for-windows)。

要验证 `ssh-agent` 是否正在计算机上运行，请在终端中键入以下命令：

```shell
$ echo "$SSH_AUTH_SOCK"
# Print out the SSH_AUTH_SOCK variable
> /tmp/launch-kNSlgU/Listeners
```

### 密钥必须可供 `ssh-agent` 使用

可以通过运行以下命令来检查密钥是否对 `ssh-agent` 可见：

```shell
ssh-add -L
```

如果命令说没有身份可用，则需要添加密钥：

```shell
ssh-add YOUR-KEY
```

> \[!TIP]
> 在 MacOS 上，一旦在重新引导过程中重启 `ssh-agent`，它将“忘记”该密钥。 但是，您可以使用此命令将 SSH 密钥导入密钥链：
>
> ```shell
> ssh-add --apple-use-keychain YOUR-KEY
> ```

> \[!NOTE]
> 当你将 SSH 密钥添加到 ssh-agent 时，`--apple-use-keychain` 选项会将密码存储在你的密钥链中。 如果选择不向密钥添加密码，请运行命令，而不使用 `--apple-use-keychain` 选项。
>
> 选项 `--apple-use-keychain` 位于 Apple 的 `ssh-add` 标准版本中。 在 Monterey (12.0) 之前的 macOS 版本中，`--apple-use-keychain` 和 `--apple-load-keychain` 标志分别使用语法 `-K` 和 `-A`。
>
> 如果您没有安装 Apple 的 `ssh-add` 标准版本，可能会收到错误消息。 有关详细信息，请参阅“[错误：ssh-add：非法选项 -- apple-use-keychain](/zh/enterprise-server@3.22/authentication/troubleshooting-ssh/error-ssh-add-illegal-option----apple-use-keychain)”。
>
> 如果系统继续提示你输入密码，则可能需要将命令添加到 `~/.zshrc` 文件（或 bash 对应的 `~/.bashrc` 文件）。

[tech-tips]: http://www.unixwiz.net/techtips/ssh-agent-forwarding.html

[generating-keys]: /authentication/connecting-to-github-with-ssh

[ssh-passphrases]: /authentication/connecting-to-github-with-ssh/working-with-ssh-key-passphrases

[autolaunch-ssh-agent]: /authentication/connecting-to-github-with-ssh/working-with-ssh-key-passphrases#auto-launching-ssh-agent-on-git-for-windows