fabric: how to double tunnel
Asked Answered
H

7

19

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 install fabric on A?

Hundredweight answered 28/5, 2011 at 12:9 Comment(0)
C
13

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

Camper answered 16/2, 2016 at 11:28 Comment(0)
A
4

Looks like this might to the trick:

https://gist.github.com/856179

Advert answered 22/7, 2011 at 8:48 Comment(1)
Tried this and it does exactly what the OP was asking for +1Coraciiform
A
3

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

Aperiodic answered 17/12, 2014 at 16:27 Comment(0)
S
2

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

Swirly answered 11/4, 2012 at 4:45 Comment(0)
L
1

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')
Liva answered 1/10, 2019 at 21:32 Comment(0)
B
0

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.

Benelux answered 28/5, 2011 at 12:51 Comment(0)
C
0

In Fabric 2+, the API has been reorganized and the module fabric.api no longer exists, thus deprecating several answers on this page.

Addressing the question of "double tunnel" is still possible in this modern API, and still uses the concept of gateway, but relies on the Connection objects.

from fabric import Connection

c1 = Connection('remote_machineA', user='user')
c2 = Connection('remote_machineB', user='user', gateway=c1)
c2.run('hostname')

Note that this answer is only valid if we interpret the statement B ONLY accepts SSH connections from A as Due to network restrictions, [...].

Both hosts A and B should have your local SSH public key as authorized key (so, in some sense, B does accept SSH connections from the local machine). The public keys stored on A are not used to log on B.

Charpoy answered 12/2 at 8:58 Comment(1)
This answer has been elaborated using Fabric 3.2.2.Charpoy

© 2022 - 2024 — McMap. All rights reserved.