Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SSH's ProxyJump command #1073

Open
jameskirsop opened this issue Aug 31, 2020 · 6 comments
Open

Add support for SSH's ProxyJump command #1073

jameskirsop opened this issue Aug 31, 2020 · 6 comments

Comments

@jameskirsop
Copy link

jameskirsop commented Aug 31, 2020

Take the following SSH Config file example:

host 192.168.0.1
        Hostname 192.168.0.1
        User napalm
        IdentityFile /path/to/my/id_rsa

host * !192.168.0.1
        ProxyJump 192.168.0.1

This module ignores the ProxyJump line and tries to connect to the host directly, ignoring the provided configuration.

This is tangentially referenced here.

When calling from within NAPALM, the following is output in debug mode suggesting the root of the fault is with this module:

$ napalm --debug --user myUsername --password myPassword  -o "ssh_config_file='/path/to/ssh_config_file'" -v junos 10.0.0.5
2020-08-31 15:18:03,770 - napalm - DEBUG - Starting napalm's debugging tool
2020-08-31 15:18:03,770 - napalm - DEBUG - Gathering napalm packages
2020-08-31 15:18:03,771 - napalm - DEBUG - napalm==3.1.0
2020-08-31 15:18:03,771 - napalm - DEBUG - get_network_driver - Calling with args: ('junos',), {}
2020-08-31 15:18:03,772 - napalm - DEBUG - get_network_driver - Successful
2020-08-31 15:18:03,772 - napalm - DEBUG - __init__ - Calling with args: (<class 'napalm.junos.junos.JunOSDriver'>, '10.0.0.5', 'myUsername'), {'password': '*******', 'timeout': 60, 'optional_args': {'ssh_config_file': '/path/to/ssh_config_file'}}
2020-08-31 15:18:03,775 - napalm - DEBUG - __init__ - Successful
2020-08-31 15:18:03,776 - napalm - DEBUG - pre_connection_tests - Calling with args: (<napalm.junos.junos.JunOSDriver object at 0x7f6aab287550>,), {}
2020-08-31 15:18:03,776 - napalm - DEBUG - open - Calling with args: (<napalm.junos.junos.JunOSDriver object at 0x7f6aab287550>,), {}
2020-08-31 15:18:03,781 - napalm - ERROR - open - Failed: ConnectRefusedError(10.0.0.5)

================= Traceback =================

Traceback (most recent call last):
  File "/opt/netbox-2.9.1/venv/lib64/python3.6/site-packages/jnpr/junos/device.py", line 1339, in open
    "use_filter": self._use_filter,
  File "/opt/netbox-2.9.1/venv/lib64/python3.6/site-packages/ncclient/manager.py", line 168, in connect
    return connect_ssh(*args, **kwds)
  File "/opt/netbox-2.9.1/venv/lib64/python3.6/site-packages/ncclient/manager.py", line 135, in connect_ssh
    session.connect(*args, **kwds)
  File "/opt/netbox-2.9.1/venv/lib64/python3.6/site-packages/ncclient/transport/ssh.py", line 291, in connect
    raise SSHError("Could not open socket to %s:%s" % (host, port))
ncclient.transport.errors.SSHError: Could not open socket to 10.0.0.5:22

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/netbox-2.9.1/venv/bin/napalm", line 11, in <module>
    sys.exit(main())
  File "/opt/netbox-2.9.1/venv/lib64/python3.6/site-packages/napalm/base/clitools/cl_napalm.py", line 308, in main
    run_tests(args)
  File "/opt/netbox-2.9.1/venv/lib64/python3.6/site-packages/napalm/base/clitools/cl_napalm.py", line 283, in run_tests
    call_open_device(device)
  File "/opt/netbox-2.9.1/venv/lib64/python3.6/site-packages/napalm/base/clitools/cl_napalm.py", line 27, in wrapper
    r = func(*args, **kwargs)
  File "/opt/netbox-2.9.1/venv/lib64/python3.6/site-packages/napalm/base/clitools/cl_napalm.py", line 207, in call_open_device
    return device.open()
  File "/opt/netbox-2.9.1/venv/lib64/python3.6/site-packages/napalm/junos/junos.py", line 127, in open
    self.device.open(auto_probe=self.auto_probe)
  File "/opt/netbox-2.9.1/venv/lib64/python3.6/site-packages/jnpr/junos/device.py", line 1358, in open
    raise EzErrors.ConnectRefusedError(self)
jnpr.junos.exception.ConnectRefusedError: ConnectRefusedError(10.0.0.5)

Calling ssh -F ~/path/to/ssh_config_file [email protected] from the command line on the same host succeeds with no SSH connectivity issues.

@rahkumar651991
Copy link
Contributor

Hi @jameskirsop - What are the parameters sent to the device as login credentials. 10.0.0.5:22 doesn't match with host details.
Can you provide more details.

@jameskirsop
Copy link
Author

Sorry @rahkumar651991, I don't understand the question.

I've intentionally removed and masked login credentials to ensure device security:
$ napalm --debug --user myUsername --password myPassword -o "ssh_config_file='/path/to/ssh_config_file'" -v junos 10.0.0.5

The provided sample SSH Config File indicates that a connection to 10.0.0.5 will ProxyJump through 192.168.0.1.

@rahkumar651991
Copy link
Contributor

can you share the output for this command.

pip list | grep junos 

@rahkumar651991
Copy link
Contributor

@jameskirsop can you try with something like this

Host host_b
User user
Hostname 10.x.x.2
Port 22
ProxyCommand ssh -q -W %h:%p host-a

Host host-a
User user
Port 22
Hostname 10.x.x.3

@ktbyers
Copy link

ktbyers commented Aug 30, 2021

FYI, here is what I do in Netmiko for ProxyJump (Paramiko under the hood).

It only works with a single ProxyJump host, however:

https://github.com/ktbyers/netmiko/blob/develop/netmiko/base_connection.py#L904

You are welcome to reuse in PyEz if it helps.

@daemonkeeper
Copy link

daemonkeeper commented Mar 17, 2022

I've the very same problem. You can workaround this by running a SSH Socks proxy through your proxy machine. e.g. you do something like

Host 192.168.0.1
        Hostname 192.168.0.1
        User napalm
        IdentityFile /path/to/my/id_rsa
       DynamicForward 1080

This should open a socks5 proxy on localhost:1080 to proxy jump when ssh'ing to your host. Then, all you need is something like

import socks
import jnpr.junos

user = "youruser"
h = "target_host" 

s = socks.socksocket()
s.set_proxy(socks.PROXY_TYPE_SOCKS5, "localhost", 1080)
s.connect((h, 22))
j = jnpr.junos.Device(host=h, port=22, user=user, sock_fd=s.fileno())
j.open()
print(j.facts)

btw. I'd argue this is not a low priority enhancement. It's quite common to run DMZ/bastions to separate your prod devices from your corp network. Some people do that by blocking end-to-end connectivity and forcing you to jump through a proxy like the author and I are forced to.

With that being said, I do think this is not really an issue of py-eznc but down the path in ncclient which does not allow more complicated Paramiko customization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants