py-junos-eznc icon indicating copy to clipboard operation
py-junos-eznc copied to clipboard

Add support for SSH's ProxyJump command

Open jameskirsop opened this issue 4 years ago • 6 comments

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.

jameskirsop avatar Aug 31 '20 05:08 jameskirsop

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.

rahkumar651991 avatar Sep 01 '20 06:09 rahkumar651991

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.

jameskirsop avatar Sep 01 '20 08:09 jameskirsop

can you share the output for this command.

pip list | grep junos 

rahkumar651991 avatar Sep 02 '20 16:09 rahkumar651991

@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

rahkumar651991 avatar Jun 01 '21 04:06 rahkumar651991

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.

ktbyers avatar Aug 30 '21 17:08 ktbyers

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.

daemonkeeper avatar Mar 17 '22 10:03 daemonkeeper