SSH代理转发特定密钥而不是所有已注册的ssh密钥

时间:2022-04-06 07:36:41

I am using agent forwarding, it works fine. But the ssh client is sharing all registered (ssh-add) keys with the remote server. I have personal keys that I don't want to share with the remote server. Is there a way to restrict with keys are being forwarded?

我正在使用代理转发,它工作正常。但是ssh客户端正在与远程服务器共享所有已注册(ssh-add)的密钥。我有个人密钥,我不想与远程服务器共享。有没有办法限制密钥被转发?

I have multiple github accounts and aws accounts. I don't want to share all the ssh-keys.

我有多个github帐户和aws帐户。我不想分享所有的ssh-key。

2 个解决方案

#1


4  

The keys themselves are not shared by forwarding your agent. What's forwarded is the ability to contact the ssh-agent on your local host. Remote systems send challenge requests through the forwarding tunnel. They do not request the keys themselves.

转发您的代理不会共享密钥本身。转发的是能够联系本地主机上的ssh-agent。远程系统通过转发隧道发送质询请求。他们自己不要求钥匙。

See http://www.unixwiz.net/techtips/ssh-agent-forwarding.html#fwd for a graphical explanation.

有关图形说明,请参见http://www.unixwiz.net/techtips/ssh-agent-forwarding.html#fwd。

#2


4  

Looks like it is possible with OpenSSH 6.7 - it supports unix socket forwarding. We could start secondary ssh-agent with specific keys and forward it's socket to remote host. Unfortunately this version is not available for my server/client systems at the time of writing.

看起来可以使用OpenSSH 6.7 - 它支持unix套接字转发。我们可以使用特定密钥启动辅助ssh-agent并将其套接字转发到远程主机。不幸的是,在撰写本文时,我的服务器/客户端系统无法使用此版本。

I have found another possible solution, using socat and standard SSH TCP forwarding.

我找到了另一种可能的解决方案,使用socat和标准SSH TCP转发。

Idea

  1. On local host we run secondary ssh-agent with only keys we want to see on remote host.
  2. 在本地主机上,我们运行辅助ssh-agent,只包含我们希望在远程主机上看到的密钥。
  3. On local host we set up forwarding of TCP connections on some port (portXXX) to secondary ssh-agent's socket.
  4. 在本地主机上,我们将某些端口(portXXX)上的TCP连接转发到辅助ssh-agent的套接字。
  5. On remote host we set up forwarding from some socket to some TCP port (portYYY).
  6. 在远程主机上,我们设置从某个套接字转发到某个TCP端口(portYYY)。
  7. Then we establish ssh connection with port forwarding from remote's portYYY to local portXXX.
  8. 然后我们建立ssh连接,从远程的portYYY到本地portXXX的端口转发。

Requests to ssh agent go like this:

对ssh代理的请求如下:

local ssh-agent (secondary)
    ^
    |
    v
/tmp/ssh-.../agent.ZZZZZ   - agent's socket
    ^
    |   (socat local)
    v
localhost:portXXX
    ^
    |   (ssh port forwarding)
    v
 remote's localhost:portYYY
    ^
    |   (socat remote)
    v
 $HOME/tmp/agent.socket
    ^
    |   (requests for auth via agent)
    v
 SSH_AUTH_SOCK=$HOME/tmp/agent.socket
    ^
    |   (uses SSH_AUTH_SOCK variable to find agent socket)
    v
   ssh

Drawbacks

  1. It is not completely secure, because ssh-agent becomes partially available through TCP: users of remote host can connect to your local agent on 127.0.0.1:portYYY, and other users of your local host can connect on 127.0.0.1:portXXX. But they will see only limited set of keys you manually added to this agent. And, as AllenLuce mentioned, they can't grab it, they only could use it for authentication while agent is running.
  2. 它并不完全安全,因为ssh-agent通过TCP部分可用:远程主机的用户可以在127.0.0.1:portYYY上连接到本地代理,本地主机的其他用户可以在127.0.0.1:portXXX上连接。但他们只会看到您手动添加到此代理的有限密钥集。并且,正如AllenLuce所提到的,他们无法抓住它,他们只能在代理运行时使用它进行身份验证。
  3. socat must be installed on remote host. But looks like it is possible to simply upload precompiled binary (I tested it on FreeBSD and it works).
  4. socat必须安装在远程主机上。但看起来可以简单地上传预编译的二进制文件(我在FreeBSD上测试它并且它可以工作)。
  5. No automation: keys must be added manually via ssh-add, forwarding requires 2 extra processes (socat) to be run, multiple ssh connections must be managed manually.
  6. 无自动化:必须通过ssh-add手动添加密钥,转发需要运行2个额外进程(socat),必须手动管理多个ssh连接。

So, this answer is probably just a proof of concept and not a production solution.

所以,这个答案可能只是概念证明,而不是生产解决方案。

Let's see how it can be done.

让我们看看它是如何完成的。

Instruction

Client side (where ssh-agent is running)

Run new ssh-agent. It will be used for keys you want to see on remote host only.

运行新的ssh-agent。它将用于您只想在远程主机上看到的密钥。

$ ssh-agent # below is ssh-agent output, DO NOT ACTUALLY RUN THESE COMMANDS BELOW
SSH_AUTH_SOCK=/tmp/ssh-qVnT0UsgV6yO/agent.22982; export SSH_AUTH_SOCK;
SSH_AGENT_PID=22983; export SSH_AGENT_PID;

It prints some variables. Do not set them: you will loose your main ssh agent. Set another variable with suggested value of SSH_AUTH_SOCK:

它打印一些变量。不要设置它们:你将丢失主ssh代理。使用SSH_AUTH_SOCK的建议值设置另一个变量:

SSH_AUTH_SECONDARY_SOCK=/tmp/ssh-qVnT0UsgV6yO/agent.22982

Then establish forwarding from some TCP port to our ssh-agent socket locally:

然后在本地建立从某个TCP端口到我们的ssh-agent套接字的转发:

PORT=9898
socat TCP4-LISTEN:$PORT,bind=127.0.0.1,fork UNIX-CONNECT:$SSH_AUTH_SECONDARY_SOCK &

socat will run in background. Do not forget to kill it when you're done.

socat将在后台运行。完成后不要忘记杀死它。

Add some keys using ssh-add, but run it with modified enviromnent variable SSH_AUTH_SOCK:

使用ssh-add添加一些键,但使用修改后的enviromnent变量SSH_AUTH_SOCK运行它:

SSH_AUTH_SOCK=$SSH_AUTH_SECONDARY_SOCK ssh-add

Server side (remote host)

Connect to remote host with port forwarding. Your main (not secondary) ssh agent will be used for auth on hostA (but will not be available from it, as we do not forward it).

通过端口转发连接到远程主机。您的主要(非次要)ssh代理将用于hostA上的auth(但不会从它获取,因为我们不转发它)。

home-host$ PORT=9898 # same port as above
home-host$ ssh -R $PORT:localhost:$PORT userA@hostA

On remote host establish forwarding from ssh-agent socket to same TCP port as on your home host:

在远程主机上建立从ssh-agent套接字转发到与主机上相同的TCP端口:

remote-host$ PORT=9898 # same port as on home host
remote-host$ mkdir -p $HOME/tmp
remote-host$ SOCKET=$HOME/tmp/ssh-agent.socket
remote-host$ socat UNIX-LISTEN:$SOCKET,fork TCP4:localhost:$PORT &

socat will run in background. Do not forget to kill it when you're done. It does not automatically exit when you close ssh connection.

socat将在后台运行。完成后不要忘记杀死它。关闭ssh连接时,它不会自动退出。

Connection

On remote host set enviromnent variable for ssh to know where agent socket (from previous step) is. It can be done in same ssh session or in parallel one.

在远程主机上为ssh设置enviromnent变量,以了解代理套接字(来自上一步)的位置。它可以在同一个ssh会话中完成,也可以并行执行。

remote-host$ export SSH_AUTH_SOCK=$HOME/tmp/ssh-agent.socket

Now it is possible to use secondary agent's keys on remote host:

现在可以在远程主机上使用辅助代理的密钥:

remote-host$ ssh userB@hostB # uses secondary ssh agent
Welcome to hostB!

#1


4  

The keys themselves are not shared by forwarding your agent. What's forwarded is the ability to contact the ssh-agent on your local host. Remote systems send challenge requests through the forwarding tunnel. They do not request the keys themselves.

转发您的代理不会共享密钥本身。转发的是能够联系本地主机上的ssh-agent。远程系统通过转发隧道发送质询请求。他们自己不要求钥匙。

See http://www.unixwiz.net/techtips/ssh-agent-forwarding.html#fwd for a graphical explanation.

有关图形说明,请参见http://www.unixwiz.net/techtips/ssh-agent-forwarding.html#fwd。

#2


4  

Looks like it is possible with OpenSSH 6.7 - it supports unix socket forwarding. We could start secondary ssh-agent with specific keys and forward it's socket to remote host. Unfortunately this version is not available for my server/client systems at the time of writing.

看起来可以使用OpenSSH 6.7 - 它支持unix套接字转发。我们可以使用特定密钥启动辅助ssh-agent并将其套接字转发到远程主机。不幸的是,在撰写本文时,我的服务器/客户端系统无法使用此版本。

I have found another possible solution, using socat and standard SSH TCP forwarding.

我找到了另一种可能的解决方案,使用socat和标准SSH TCP转发。

Idea

  1. On local host we run secondary ssh-agent with only keys we want to see on remote host.
  2. 在本地主机上,我们运行辅助ssh-agent,只包含我们希望在远程主机上看到的密钥。
  3. On local host we set up forwarding of TCP connections on some port (portXXX) to secondary ssh-agent's socket.
  4. 在本地主机上,我们将某些端口(portXXX)上的TCP连接转发到辅助ssh-agent的套接字。
  5. On remote host we set up forwarding from some socket to some TCP port (portYYY).
  6. 在远程主机上,我们设置从某个套接字转发到某个TCP端口(portYYY)。
  7. Then we establish ssh connection with port forwarding from remote's portYYY to local portXXX.
  8. 然后我们建立ssh连接,从远程的portYYY到本地portXXX的端口转发。

Requests to ssh agent go like this:

对ssh代理的请求如下:

local ssh-agent (secondary)
    ^
    |
    v
/tmp/ssh-.../agent.ZZZZZ   - agent's socket
    ^
    |   (socat local)
    v
localhost:portXXX
    ^
    |   (ssh port forwarding)
    v
 remote's localhost:portYYY
    ^
    |   (socat remote)
    v
 $HOME/tmp/agent.socket
    ^
    |   (requests for auth via agent)
    v
 SSH_AUTH_SOCK=$HOME/tmp/agent.socket
    ^
    |   (uses SSH_AUTH_SOCK variable to find agent socket)
    v
   ssh

Drawbacks

  1. It is not completely secure, because ssh-agent becomes partially available through TCP: users of remote host can connect to your local agent on 127.0.0.1:portYYY, and other users of your local host can connect on 127.0.0.1:portXXX. But they will see only limited set of keys you manually added to this agent. And, as AllenLuce mentioned, they can't grab it, they only could use it for authentication while agent is running.
  2. 它并不完全安全,因为ssh-agent通过TCP部分可用:远程主机的用户可以在127.0.0.1:portYYY上连接到本地代理,本地主机的其他用户可以在127.0.0.1:portXXX上连接。但他们只会看到您手动添加到此代理的有限密钥集。并且,正如AllenLuce所提到的,他们无法抓住它,他们只能在代理运行时使用它进行身份验证。
  3. socat must be installed on remote host. But looks like it is possible to simply upload precompiled binary (I tested it on FreeBSD and it works).
  4. socat必须安装在远程主机上。但看起来可以简单地上传预编译的二进制文件(我在FreeBSD上测试它并且它可以工作)。
  5. No automation: keys must be added manually via ssh-add, forwarding requires 2 extra processes (socat) to be run, multiple ssh connections must be managed manually.
  6. 无自动化:必须通过ssh-add手动添加密钥,转发需要运行2个额外进程(socat),必须手动管理多个ssh连接。

So, this answer is probably just a proof of concept and not a production solution.

所以,这个答案可能只是概念证明,而不是生产解决方案。

Let's see how it can be done.

让我们看看它是如何完成的。

Instruction

Client side (where ssh-agent is running)

Run new ssh-agent. It will be used for keys you want to see on remote host only.

运行新的ssh-agent。它将用于您只想在远程主机上看到的密钥。

$ ssh-agent # below is ssh-agent output, DO NOT ACTUALLY RUN THESE COMMANDS BELOW
SSH_AUTH_SOCK=/tmp/ssh-qVnT0UsgV6yO/agent.22982; export SSH_AUTH_SOCK;
SSH_AGENT_PID=22983; export SSH_AGENT_PID;

It prints some variables. Do not set them: you will loose your main ssh agent. Set another variable with suggested value of SSH_AUTH_SOCK:

它打印一些变量。不要设置它们:你将丢失主ssh代理。使用SSH_AUTH_SOCK的建议值设置另一个变量:

SSH_AUTH_SECONDARY_SOCK=/tmp/ssh-qVnT0UsgV6yO/agent.22982

Then establish forwarding from some TCP port to our ssh-agent socket locally:

然后在本地建立从某个TCP端口到我们的ssh-agent套接字的转发:

PORT=9898
socat TCP4-LISTEN:$PORT,bind=127.0.0.1,fork UNIX-CONNECT:$SSH_AUTH_SECONDARY_SOCK &

socat will run in background. Do not forget to kill it when you're done.

socat将在后台运行。完成后不要忘记杀死它。

Add some keys using ssh-add, but run it with modified enviromnent variable SSH_AUTH_SOCK:

使用ssh-add添加一些键,但使用修改后的enviromnent变量SSH_AUTH_SOCK运行它:

SSH_AUTH_SOCK=$SSH_AUTH_SECONDARY_SOCK ssh-add

Server side (remote host)

Connect to remote host with port forwarding. Your main (not secondary) ssh agent will be used for auth on hostA (but will not be available from it, as we do not forward it).

通过端口转发连接到远程主机。您的主要(非次要)ssh代理将用于hostA上的auth(但不会从它获取,因为我们不转发它)。

home-host$ PORT=9898 # same port as above
home-host$ ssh -R $PORT:localhost:$PORT userA@hostA

On remote host establish forwarding from ssh-agent socket to same TCP port as on your home host:

在远程主机上建立从ssh-agent套接字转发到与主机上相同的TCP端口:

remote-host$ PORT=9898 # same port as on home host
remote-host$ mkdir -p $HOME/tmp
remote-host$ SOCKET=$HOME/tmp/ssh-agent.socket
remote-host$ socat UNIX-LISTEN:$SOCKET,fork TCP4:localhost:$PORT &

socat will run in background. Do not forget to kill it when you're done. It does not automatically exit when you close ssh connection.

socat将在后台运行。完成后不要忘记杀死它。关闭ssh连接时,它不会自动退出。

Connection

On remote host set enviromnent variable for ssh to know where agent socket (from previous step) is. It can be done in same ssh session or in parallel one.

在远程主机上为ssh设置enviromnent变量,以了解代理套接字(来自上一步)的位置。它可以在同一个ssh会话中完成,也可以并行执行。

remote-host$ export SSH_AUTH_SOCK=$HOME/tmp/ssh-agent.socket

Now it is possible to use secondary agent's keys on remote host:

现在可以在远程主机上使用辅助代理的密钥:

remote-host$ ssh userB@hostB # uses secondary ssh agent
Welcome to hostB!