如何拦截SSH stdin和stdout? (不是密码)

时间:2011-04-11 14:06:19

标签: c linux ubuntu ssh pipe

我意识到这个问题经常被问到,主要是那些想要拦截SSH密码问题阶段的人。这不是我想要的。我是在登录后的文字。

我想为ssh编写一个包装器,它充当SSH和终端之间的中介。我想要这个配置:

(typing on keyboard / stdin) ----> (wrapper) ----> (ssh client)

和来自ssh的输出相同:

(ssh client) -----> (wrapper) -----> stdout

我似乎能够通过在网上找到的标准技巧(简化代码)来达到我想要的stdout效果:

pipe(fd)
if (!fork()) {
  close(fd[READ_SIDE]);
  close(STDOUT_FILENO);  // close stdout ( fd #1 )
  dup(fd[WRITE_SIDE]);   // duplicate the writing side of my pipe ( to lowest # free pipe, 1 )
  close(STDERR_FILENO);
  dup(fd[WRITE_SIDE]);
  execv(argv[1], argv + 1); // run ssh
} else {
  close(fd[WRITE_SIDE]);
  output = fdopen(fd[READ_SIDE], "r");
  while ( (c = fgetc(output)) != EOF) {
    printf("%c", c);
    fflush(stdout);
  }
}
像我说的那样,我觉得这很有效。但是,我似乎无法做相反的事情。我无法关闭(STDIN_FILENO)并重复管道的读取。 SSH似乎检测到并阻止它。我已经读过我可以使用“-t -t”选项强制SSH忽略其输入的非标准输入特性;但是当我尝试这个时它仍然无效。

任何提示?

非常感谢!

5 个答案:

答案 0 :(得分:1)

使用popen(而不是 execv )执行ssh cmd并能够读取和写入会话。

答案 1 :(得分:1)

如果您希望允许任何交互式使用ssh与拦截器,管道将无法工作。在这种情况下,您需要创建一个伪tty。查找posix_openptptsnamegrantpt函数。还有一个名为openpty的非标准但更加直观的函数,以及一个名为forkpty的包装器,它使你想要做的事情非常容易。

答案 2 :(得分:1)

Python的Paramiko使用SSH完成所有这些操作,但它使用的是Python源代码。但是,对于C程序员来说,阅读Python就像阅读伪代码一样,所以请到源代码并准确了解它的作用。

答案 3 :(得分:0)

这是一个写入ssh的工作示例:

#include <unistd.h>

int main(int argc, char **argv)
{
    int pid;
    int fds[2];

    if (pipe(fds))
        return -1;

    pid = fork();

    if (!pid)
    {
        close(fds[1]);
        close(STDERR_FILENO);
        dup2(fds[0], STDIN_FILENO);
        execvp(argv[1], argv + 1);
    }
    else
    {
        char buf[256];
        int rc;

        close(fds[0]);
        while ((rc = read(STDIN_FILENO, buf, 256)) > 0)
        {
            write(fds[1], buf, rc);
        }
    }
    wait(NULL);
    return 0;
}

答案 4 :(得分:0)

这一行可能错了:

  execv(argv[1], argv + 1); // run ssh

如果你使用argv []来自main()的参数,那么数组必须用NULL指针终止。我认为没有任何保证是这种情况。编辑:刚刚检查了C99标准,argv被NULL终止。

execv()不会搜索要执行的文件的路径,因此如果您将ssh作为参数传递,则它等同于./ssh,这可能不是您想要的。您可以使用execvp(),但如果ssh之前的$ PATH中出现名为/bin/ssh的恶意程序,则存在安全风险。最好使用execv()并强制使用正确的路径。