简体   繁体   English

使用代理在多台机器上进行 Python ssh 隧道传输

[英]Python ssh tunneling over multiple machines with agent

A little context is in order for this question: I am making an application that copies files/folders from one machine to another in python.对于这个问题,有一点上下文:我正在制作一个应用程序,将文件/文件夹从一台机器复制到另一台机器上的python。 The connection must be able to go through multiple machines.连接必须能够通过多台机器。 I quite literally have the machines connected in serial so I have to hop through them until I get to the correct one.我确实让机器串行连接所以我必须跳过它们,直到找到正确的机器。

Currently, I am using python's subprocess module (Popen).目前,我正在使用 python 的子进程模块 (Popen)。 As a very simplistic example I have作为一个非常简单的例子,我有

import subprocess

# need to set strict host checking to no since we connect to different
# machines over localhost
tunnel_string = "ssh -oStrictHostKeyChecking=no -L9999:127.0.0.1:9999 -ACt machine1 ssh -L9999:127.0.0.1:22 -ACt -N machineN"

proc = subprocess.Popen(tunnel_string.split())
# Do work, copy files etc. over ssh on localhost with port 9999
proc.terminate()

My question: When doing it like this, I cannot seem to get agent forwarding to work, which is essential in something like this.我的问题:当这样做时,我似乎无法让代理转发工作,这在这样的事情中是必不可少的。 Is there a way to do this?有没有办法做到这一点?

I tried using the shell=True keyword in Popen like so我尝试在 Popen 中像这样使用 shell=True 关键字

tunnel_string = "eval `ssh-agent` && ssh-add && ssh -oStrictHostKeyChecking=no -L9999:127.0.0.1:9999 -ACt machine1 ssh -L9999:127.0.0.1:22 -ACt -N machineN"

proc = subprocess.Popen(tunnel_string, shell=True)
# etc

The problem with this is that the name of the machines is given by user input, meaning they could easily inject malicious shell code.这样做的问题是机器的名称是由用户输入给出的,这意味着它们很容易注入恶意的 shell 代码。 A second problem is that I then have a new ssh-agent process running every time I make a connection.第二个问题是,我每次建立连接时都会运行一个新的 ssh-agent 进程。

I have a nice function in my bashrc which identifies already running ssh-agents and sets the appropriate environment variables and adds my ssh key, but of cource subprocess cannot reference functions defined in my bashrc.我的 bashrc 中有一个很好的函数,它识别已经运行的 ssh-agents 并设置适当的环境变量并添加我的 ssh 密钥,但是当然子进程无法引用我的 bashrc 中定义的函数。 I tried setting the executable="/bin/bash" variable with shell=True in Popen to no avail.我尝试在 Popen 中使用 shell=True 设置 executable="/bin/bash" 变量无济于事。

You should give Fabric a try.你应该试试Fabric

It provides a basic suite of operations for executing local or remote shell commands (normally or via sudo) and uploading/downloading files, as well as auxiliary functionality such as prompting the running user for input, or aborting execution.它提供了一套基本的操作来执行本地或远程 shell 命令(通常或通过 sudo)和上传/下载文件,以及诸如提示正在运行的用户输入或中止执行的辅助功能。

The program below will give you a test run.下面的程序会给你一个测试运行。 First install fabric with pip install fabric then save the code below in fabfile.py首先使用pip install fabric然后将下面的代码保存在fabfile.py

from fabric.api import *

env.hosts = ['server url/IP'] #change to ur server.
env.user = #username for the server
env.password = #password

def run_interactive():
    with settings(warn_only = True)
    cmd = 'clear'
    while cmd is not 'stop fabric':
        run(cmd)
        cmd = raw_input('Command to run on server')

Change to the directory containing your fabfile and run fab run_interactive then each command you enter will be run on the server切换到包含您的 fabfile 的目录并运行fab run_interactive然后您输入的每个命令都将在服务器上运行

I tested your first simplistic example and agent forwarding worked.我测试了您的第一个简单示例并且代理转发有效。 The only think that I can see that might cause problems is that the environment variables SSH_AGENT_PID and SSH_AUTH_SOCK are not set correctly in the shell that you execute your script from.我认为可能会导致问题的唯一想法是环境变量 SSH_AGENT_PID 和 SSH_AUTH_SOCK 在您执行脚本的 shell 中设置不正确。 You might use ssh -v to get a better idea of where things are breaking down.您可以使用 ssh -v 来更好地了解事情发生在哪里。

Try setting up a SSH config file: https://linuxize.com/post/using-the-ssh-config-file/尝试设置 SSH 配置文件: https : //linuxize.com/post/using-the-ssh-config-file/

I frequently am required to tunnel through a bastion server and I use a configuration like so in my ~/.ssh/config file.我经常需要通过堡垒服务器进行隧道传输,我在~/.ssh/config文件中使用了这样的~/.ssh/config Just change the host and user names.只需更改主机名和用户名即可。 This also presumes that you have entries for these host names in your hosts ( /etc/hosts ) file.这还假定您的主机 ( /etc/hosts ) 文件中有这些主机名的条目。

Host my-bastion-server
        Hostname my-bastion-server
        User user123
        AddKeysToAgent yes
        UseKeychain yes
        ForwardAgent yes

Host my-target-host
        HostName my-target-host
        User user123
        AddKeysToAgent yes
        UseKeychain yes

I then gain access with syntax like:然后我可以使用以下语法访问:
ssh my-bastion-server -At 'ssh my-target-host -At'

And I issue commands against my-target-host like:我针对my-target-host发出命令,例如:
ssh my-bastion-server -AT 'ssh my-target-host -AT "ls -la"'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM