AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 789634
Accepted
symcbean
symcbean
Asked: 2025-01-16 00:58:07 +0800 CST2025-01-16 00:58:07 +0800 CST 2025-01-16 00:58:07 +0800 CST

ssh 代理转发-底层发生了什么?

  • 772

当我向 Google 询问 ssh 代理转发如何工作时,它给我提供了许多 SEO 优化垃圾链接,解释了如何配置 ssh-agent。这不是我问的。

我目前遇到一个问题,在 VPN 连接远端的屏幕会话中启动的作业会失败,因为在 VPN 发生故障后它们无法通过 ssh 连接。

通常这些作业依赖于来自源客户端的代理转发来进行连接。我怀疑这里出了什么问题,但更好地了解整个代理转发会有所帮助。

当我从 host0 连接到 hosta 时,host0 上的 ssh-agent 会将我的私钥提供给 host0 上的 ssh 客户端。在 hosta 上,我看到 SSH_AUTH_SOCK 已填充,引用本地套接字。如果我在 hosta 上 ssh hostb,ssh 客户端会以某种方式连接到 host0 上的 ssh-agent。大概是使用 host0-hosta ssh 连接中的备用通道。

hosta 上的 $SSH_AUTH_SOCK 发生了什么?

(fuser $SSH_AUTH_SOCK 表明没有任何东西打开)

就我的屏幕会话而言,如果启动屏幕会话的 ssh 会话已结束,并且我从 host0 到 hosta 启动新的 ssh 会话,那么来自屏幕会话的密钥请求是否会通过新连接发送?

ssh
  • 2 2 个回答
  • 48 Views

2 个回答

  • Voted
  1. Best Answer
    ilkkachu
    2025-01-16T01:16:39+08:002025-01-16T01:16:39+08:00

    好吧,任何需要 SSH 代理的东西都会查找环境变量SSH_AUTH_SOCK来找出用于访问代理的 Unix 套接字的路径。至少在 的手册页ssh-add中提到了这一点。(该路径可能看起来像/tmp/ssh-XXXXi1AqzV/agent.1149174。)

    当您启动代理时,它会打印出一组命令来设置该环境变量和其他环境变量。此外,当您使用 连接到某个地方时ssh -A,客户端会请求代理转发,远程 SSH 服务器会为会话设置该环境变量。

    但是...当您运行 screen 时,screen 会话内的进程看不到 screen 外的会话设置的环境变量。它们所拥有的只是SSH_AUTH_SOCKscreen 会话启动时设置的变量(如果有的话)。进程启动时,环境变量从父进程继承,并且不能从外部更改,因此您无法自动为 screen 内的进程提供新路径。(您可以检查新路径并将其分别分配给每个 shell,但这很快就会让人厌烦。)

    任何解决方案都要求环境变量在屏幕会话的整个生命周期内保持不变。幸运的是,Unix 套接字只是文件,因此您可以让环境变量指向具有已知路径的符号链接,并在打开新的 SSH 会话时更改链接目标。

    我的解决方案大致如下:

    ~/.screenrc:

    setenv SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock
    

    ~/.ssh/rc:

    if [ -S "$SSH_AUTH_SOCK" ]; then
        ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
    fi
    

    可能还有其他方法。这种方法的一个缺点是链接始终指向上次打开的 SSH 会话(使用代理转发)创建的套接字。因此,如果我打开两个会话并关闭第二个会话,则 screen 中的进程将无法找到代理。

    • 1
  2. symcbean
    2025-01-20T23:19:07+08:002025-01-20T23:19:07+08:00

    当@ikkachu 向我指出一个解决方案时,我在这里分享我实施的细节。

    首先要注意的是,在本地机器上运行的 ssh-agent 不仅仅是密钥的存储库;它处理用于协商(对称)会话密钥的非对称加密/解密。因此,您的私钥不会暴露在本地机器以外的任何地方(我提到这一点是因为我在 Google 为我找到的结果中没有看到这一点)。值得记住的是,ssh 会在使用的每个小时重新协商密钥。

    为了允许恢复,我将其添加到 ssh 服务器上的 bash_profile 中:

    if [ -n "$SSH_AUTH_SOCK" ]; then
       if [ ! -L "$HOME/.ssh/ssh_auth_sock" ]; then
          # No current provision - insert symbolic link in front of socket
          ln -s "$SSH_AUTH_SOCK" "$HOME/.ssh/ssh_auth_sock"
          SSH_AUTH_SOCK="$HOME/.ssh/ssh_auth_sock"
       else
          # test if existing provision is working
          BACKUP_SSH_AUTH_SOCK="$SSH_AUTH_SOCK"
          SSH_AUTH_SOCK="$HOME/.ssh/ssh_auth_sock"
          ssh-add -l >/dev/null 2>&1
          if [ 2 -eq "$?" ]; then
            # reprovision using current connection
            rm "$HOME/.ssh/ssh_auth_sock"
            ln -s "$BACKUP_SSH_AUTH_SOCK" "$HOME/.ssh/ssh_auth_sock"
          fi
       fi
    fi
    

    为了便于维持连接,我编写了一个 ssh 包装器,它将在以下情况下自动重新连接:

    • ssh 以非零退出代码退出
    • 操作至少 20 秒后

    此外,我将 connectTimeout 设置为 10 秒,将 clientAliveInterval 设置为 10 秒。此处另一个有用的功能是结合语音合成,当事情没有按计划进行时提醒我:

    function say_out_load () {
       local msg
       msg="$1"
       if [ -f "/etc/wsl.conf" ]; then
           powershell.exe -c "Add-Type -AssemblyName System.speech; \$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer; \$speak.Speak('$msg');"
           # powershell.exe -c '(New-Object Media.SoundPlayer "C:\Windows\Media\Windows Ringout.wav").PlaySync();'
       elif which say >/dev/null ; then
           say "$msg"
       fi
    }
    

    总的来说,这些并不能阻止远程主机的 ssh 继续传输失败,但可以大大减少这种情况发生的时间。当最小化/后台窗口中的任务失败时,我应该几乎立即意识到。

    • 0

相关问题

  • 为什么 ssh 实用程序被视为 pty?

  • Auto-SSH 手动工作,但不在后台工作

  • 远程运行 X 应用程序,在远程主机上运行 GUI [关闭]

  • rsync 端口 22 和 873 使用

  • SCP突然中止:管道损坏,消息验证码不正确

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve