开发者

fabric: how to double tunnel

开发者 https://www.devze.com 2023-03-08 18:54 出处:网络
Situation: A and B are remote hosts. Local machine can SSH into A, but not B. B ONLY accepts SSH connections from A.

Situation: A and B are remote hosts. Local machine can SSH into A, but not B. B ONLY accepts SSH connections from A.

Question: Is it possible to use fabric on the local machine to execute commands on Host B, preferably without having to insta开发者_运维问答ll fabric on A?


I managed to achieve this with env.gateway as follows:

from fabric.api import *

env.forward_agent = True
env.gateway = 'user@remote_MachineA'
env.hosts = ['user@remote_MachineB']

def function1():
  run('hostname')

env.forward_agent = True is there only to enable forwarding of your local SSH agent to the remote end

Alternatively, you can use ssh ProxyCommand, example here and tell fabric to use your ~/.ssh/config using use_ssh_config = True, documentation here


Looks like this might to the trick:

https://gist.github.com/856179


Since Fabric v1.5+ there is a method called remote_tunnel to solve cranberry situation

I have used a simple command (hostname) to illustrate the solution but any other command may be used instead. As you can see, we have invoked a command to be executed on remote_machineB from local_machine by using remote_machineA as jump host:

from fabric.api import settings, env, run, remote_tunnel

env.hosts=["user@remote_machineA"]

def funct1():
    def func1b(host):
        with settings(host_string=host):
            run("hostname")

    with remote_tunnel(remote_port=22022, local_port=22,
                       local_host="remote_machineB", remote_bind_address="0.0.0.0"):
        funct1b("user@remote_machineA:22022")

If you execute this fab file in local_machine this is what we get:

[user@local_machine ~]# fab hostname_check
[user@remote_machineA] Executing task 'hostname_check'
[user@remote_machineA:22022] run: hostname
[user@remote_machineA:22022] rtunnel: opened reverse tunnel: (u'X.X.3.75', 55804) -> ('X.X.3.78', 22) -> ('remote_machineB', 22)
[user@remote_machineA:22022] out: remote_machineB
[user@remote_machineA:22022] out:

Terminated

To do so it is very important to configure this jump machine ssh daemon with GatewayPorts yes. Otherwise remote tunnel would be accessible only from localhost.

Check:

tcp        0      0 127.0.0.1:22022         0.0.0.0:*               LISTEN     

versus:

tcp        0      0 0.0.0.0:22022           0.0.0.0:*               LISTEN     

For more info check official documentation http://docs.fabfile.org/en/latest/api/core/context_managers.html#fabric.context_managers.remote_tunnel


I'll just leave this here: http://www.popcornfarmer.com/2009/01/ssh-tunneling-tutorial/


As a variation on yeforriak's answer, if you only want to do this for an individual task, you can do:

from fabric.api import *

@with_settings(forward_agent=True, gateway='user@remote_MachineA')
@hosts(['user@remote_MachineB'])
def function1():
  run('hostname')


I'm just going to answer the SSH part: Yes, you can set up a double tunnel -- one SSH from local to A that tunnels from a secondary local port (like 2121) to port 21 on B, and then you can SSH to localhost:2121 and login on B. I've done stuff like that with PuTTY.

Implementing that in fabric is left as an exercise.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号