ktbyers / netmiko

Multi-vendor library to simplify Paramiko SSH connections to network devices
MIT License
3.54k stars 1.3k forks source link

After connecting to router through another router using netmiko, I can't run commands to the destination router #2251

Closed hackmoonlight closed 3 years ago

hackmoonlight commented 3 years ago

hello, I connected to the router R2 throught another router using netmiko and redispatch function , but after dooing the redispatch when I run commands it still be running under the jump router.

image

`from napalm import get_network_driver from robot.api.deco import keyword

import tools

from netmiko import ConnectHandler import os import sys import re import robot import time import subprocess

import IP

import traceback from netmiko import redispatch import textfsm`

`def sh_route(IP):

    device_info = {
                'device_type': 'cisco_ios',
                'host': 'hostname',
                'username': 'username',
                'password': 'pwd',}
    #connect to device1 from linux
    net_connect = ConnectHandler(**device_info)
    # Use raw read/write to SSH into device2
    net_connect.write_channel('ssh 192.168.247.2\n')
    time.sleep(1)
    output = net_connect.read_channel()
    if 'Username' in output:
        net_connect.write_channel('username' + '\r\n')
        time.sleep(1)
        output = net_connect.read_channel()
    if 'password' in output:
        net_connect.write_channel('pwd'+ '\n')
        time.sleep(1)
    ### Logged into Second device
    print ("SSH prompt: {}".format(net_connect.find_prompt()))
    redispatch(net_connect, device_type='cisco_ios')
    net_connect.enable()
    new_output = net_connect.send_command('show version', use_textfsm=True)
    #print(output)
    version= new_output[0]['rommon']
    if  version == 'IOS-XE':
        new_output = net_connect.send_command('show ip route connected')
        return new_output
    if  version == 'IOS-XR':
        new_output = net_connect.send_command('show route local')
        return new_output

`

ktbyers commented 3 years ago

Have you looked at the Netmiko session_log() to see where you are failing at? It sounds like you are not properly logging into the end-device (R2 in your diagram).

You will probably need some loop structure here:

    output = net_connect.read_channel()
    if 'Username' in output:
        net_connect.write_channel('username' + '\r\n')
        time.sleep(1)
        output = net_connect.read_channel()
    if 'password' in output:
        net_connect.write_channel('pwd'+ '\n')
        time.sleep(1)

That is probably very prone to being unreliable (i.e. I could easily see how this might fail.

hackmoonlight commented 3 years ago

This is the full code, : you think that i should make split ? and then check the Username and password patterns if they exist ?

`def sh_route(self,alias): global verif self.device = self._cache.switch(alias) device_info = { 'device_type': 'cisco_ios', 'ip': self.device.hostname, 'username': self.device.username, 'password': self.device.password,}

    #connect to device1 from linux
    net_connect = ConnectHandler(**device_info)
    ldp= self.get_ldp_neighbors(alias)
    for  x in ldp.keys():
        addr_list = ldp[x]['addresses'] #List of ldp ip adresses  

        src_ip_addr= ldp[x]['SrcIPaddr'] #source ip addr

        # Use raw read/write to SSH into device2
        net_connect.write_channel('ssh'+src_ip_addr+'\n')
        time.sleep(1)
        output = net_connect.read_channel()
        if 'Username' in output:
            net_connect.write_channel(net_connect.username + '\r\n')
            time.sleep(1)
            output = net_connect.read_channel()
        if 'password' in output:
            net_connect.write_channel(net_connect.password + '\n')
            time.sleep(1)
        ### Logged into Second device
        print ("SSH prompt: {}".format(net_connect.find_prompt()))
        redispatch(net_connect, device_type='cisco_ios')
        net_connect.enable()
        new_output = net_connect.send_command('show version', use_textfsm=True)

        version= new_output[0]['rommon']  #check ios version
        # check if addr_list exist in addr(list of ip addr got with cisco cmd)
        if  version == 'IOS-XE':
            new_output = net_connect.send_command('show ip route connected')
            addr= re.findall( r'[0-9]+(?:\.[0-9]+){3}', new_output) # list of @ip got from new_output
            #return addr
            # #return addr_list
            # #return addr
        if  version == 'IOS-XR':
            new_output = net_connect.send_command('sh route local')                
            addr= re.findall( r'[0-9]+(?:\.[0-9]+){3}', new_output)
        return addr`
ktbyers commented 3 years ago

Are you checking the Netmiko session_log? I would definitely check there.

hackmoonlight commented 3 years ago

you think that i should make split ? and then check the Username and password patterns if they exist ?

hackmoonlight commented 3 years ago

Are you checking the Netmiko session_log? I would definitely check there.

You mean that I should import logging and putting logging.basicConfig(filename='test.log', level=logging.DEBUG) logger = logging.getLogger("netmiko")

hackmoonlight commented 3 years ago

Have you looked at the Netmiko session_log() to see where you are failing at? It sounds like you are not properly logging into the end-device (R2 in your diagram).

You will probably need some loop structure here:

    output = net_connect.read_channel()
    if 'Username' in output:
        net_connect.write_channel('username' + '\r\n')
        time.sleep(1)
        output = net_connect.read_channel()
    if 'password' in output:
        net_connect.write_channel('pwd'+ '\n')
        time.sleep(1)

That is probably very prone to being unreliable (i.e. I could easily see how this might fail.

I did the same instructions : https://github.com/ktbyers/netmiko/issues/470#issuecomment-302160186

hackmoonlight commented 3 years ago

@ktbyers

ktbyers commented 3 years ago

Is there some reason, you don't want to look at the Netmiko session_log? Otherwise you are just guessing as to why it is not working.

Yeah, sure the above worked for me and doesn't work for you. Okay, so what do we do now? I think you should look at the Netmiko session_log and probably use a loop for the above username and password handling.

hackmoonlight commented 3 years ago

Hello ktbyers, now I cannot run the script and show you the output because there is a problem with proxy of our client( so I cannot make the virtual env to run the script) .

for the loop , what do you mean by looping over username and password?

tomorrow when the problem of proxy is resolved I will show you the session log

ktbyers commented 3 years ago

Okay, makes sense on the session_log.

Yeah, usually while trying to handle the username/password you want some form of loop to keep trying more than once if the login fails (i.e. if things get slightly out of sync timing wise).

Here is an example:

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

This is from a telnet login process, but it is basically the same idea i.e. you are trying to handle that username/password login in your code.

Regards, Kirk

hackmoonlight commented 3 years ago

Thank you Krik,

I will try it tomorrow and I will give you feedback. Regards, Younes

hackmoonlight commented 3 years ago

I added loop for the username and passord,

`

    def sh_route(self,alias):
        global verif
        self.device = self._cache.switch(alias)
        device_info = {
                    'device_type': 'cisco_ios',
                    'ip': self.device.hostname,
                    'username': self.device.username,
                    'password': self.device.password,}
        #connect to device1 from linux
        net_connect = ConnectHandler(**device_info)
        ldp= self.get_ldp_neighbors(alias)
        for  x in ldp.keys():
            addr_list = ldp[x]['addresses'] #List of ldp ip adresses  

            src_ip_addr= ldp[x]['SrcIPaddr'] #source ip addr
        # Use raw read/write to SSH into device2
            net_connect.write_channel('ssh'+src_ip_addr+'\n')
            time.sleep(1)
            output = net_connect.read_channel()
            i = 1
            while i <= 20:
                try:   
                    if 'Username' in output:
                        net_connect.write_channel(net_connect.username + '\r\n')
                        time.sleep(1)
                        output = net_connect.read_channel()
                    if 'password' in output:
                        net_connect.write_channel(net_connect.password + '\n')
                        time.sleep(1)
                        output = net_connect.read_channel()
                    i += 1
                except EOFError:
                    pass
                print(output)`
hackmoonlight commented 3 years ago

THIS is the log

DEBUG:paramiko.transport:starting thread (client mode): 0x31b464e0 DEBUG:paramiko.transport:Local version/idstring: SSH-2.0-paramiko_2.7.2 DEBUG:paramiko.transport:Remote version/idstring: SSH-2.0-Cisco-1.25 INFO:paramiko.transport:Connected (version 2.0, client Cisco-1.25) DEBUG:paramiko.transport:kex algos:['ecdh-sha2-nistp256', 'ecdh-sha2-nistp384', 'ecdh-sha2-nistp521', 'diffie-hellman-group14-sha1'] server key:['rsa-sha2-512', 'rsa-sha2-256', 'ssh-rsa'] client encrypt:['aes128-gcm', 'aes256-gcm', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr'] server encrypt:['aes128-gcm', 'aes256-gcm', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr'] client mac:['hmac-sha2-256-etm@openssh.com', 'hmac-sha2-512-etm@openssh.com', 'hmac-sha2-256', 'hmac-sha2-512'] server mac:['hmac-sha2-256-etm@openssh.com', 'hmac-sha2-512-etm@openssh.com', 'hmac-sha2-256', 'hmac-sha2-512'] client compress:['none'] server compress:['none'] client lang:[''] server lang:[''] kex follows?False DEBUG:paramiko.transport:Kex agreed: ecdh-sha2-nistp256 DEBUG:paramiko.transport:HostKey agreed: ssh-rsa DEBUG:paramiko.transport:Cipher agreed: aes128-ctr DEBUG:paramiko.transport:MAC agreed: hmac-sha2-256 DEBUG:paramiko.transport:Compression agreed: none DEBUG:paramiko.transport:kex engine KexNistp256 specified hash_algo DEBUG:paramiko.transport:Switch to new keys ... DEBUG:paramiko.transport:Adding ssh-rsa host key for Bnet-A101: b'a51ea5a576822573a37ce25441bd0241' DEBUG:paramiko.transport:userauth is OK INFO:paramiko.transport:Authentication (password) successful! DEBUG:paramiko.transport:[chan 0] Max packet in: 32768 bytes DEBUG:paramiko.transport:[chan 0] Max packet out: 4096 bytes DEBUG:paramiko.transport:Secsh channel 0 opened. DEBUG:paramiko.transport:[chan 0] Sesch channel 0 request ok DEBUG:paramiko.transport:[chan 0] Sesch channel 0 request ok DEBUG:netmiko:write_channel: b'terminal width 511\n' DEBUG:netmiko:Pattern is: terminal width 511 DEBUG:netmiko:_read_channel_expect read_data: CCCCCCCC

CC C


BNET-A101 at BRATISLAVA vLAB
THIS IS A PRIVATE SYSTEM MANAGED BY ORANGE BUSINESS SERVICES
ACCESS TO THIS DEVICE REQUIRES AUTHENTICATION AGAINST THE
>> LAB INFRASTRUCTURE TACACS SERVICE <<
Your "saturne" login should be used here
_____

DEBUG:netmiko:_read_channel_expect read_data: CCCCCCCC

CCCCCCCCCC CC C


  |                                                                |
  |  Activity on this device is recorded and possibly monitored    |
  |________________________________________________________________|

Bnet-A101#terminal width 5

DEBUG:netmiko:_read_channel_expect read_data: 11

DEBUG:netmiko:Pattern found: terminal width 511 CCCCCCCC

CC C


BNET-A101 at BRATISLAVA vLAB
THIS IS A PRIVATE SYSTEM MANAGED BY ORANGE BUSINESS SERVICES
ACCESS TO THIS DEVICE REQUIRES AUTHENTICATION AGAINST THE
>> LAB INFRASTRUCTURE TACACS SERVICE <<
Your "saturne" login should be used here
_____

CCCCCCCC CCCCCCCCCC CC C


  |                                                                |
  |  Activity on this device is recorded and possibly monitored    |
  |________________________________________________________________|

Bnet-A101#terminal width 511

DEBUG:netmiko:In disable_paging DEBUG:netmiko:Command: terminal length 0

DEBUG:netmiko:write_channel: b'terminal length 0\n' DEBUG:netmiko:Pattern is: terminal\ length\ 0 DEBUG:netmiko:_read_channel_expect read_data: Bnet-A101# DEBUG:netmiko:_read_channel_expect read_data: terminal len DEBUG:netmiko:_read_channel_expect read_data: gth 0

DEBUG:netmiko:Pattern found: terminal\ length\ 0 Bnet-A101#terminal length 0

DEBUG:netmiko:Bnet-A101#terminal length 0

DEBUG:netmiko:Exiting disable_paging DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel: DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel: Bnet-A101#

Bnet-A101# Bnet-A101# Bnet-A101# Bnet-A101# Bnet-A101# Bnet-A101#

DEBUG:netmiko:read_channel: DEBUG:netmiko:[find_prompt()]: prompt is Bnet-A101# DEBUG:netmiko:write_channel: b'ssh 192.168.247.2\n' DEBUG:netmiko:read_channel: ssh 192.168.247.2

Password:

DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel:

DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel: CCCCAuthentication failed, please try again!

Password:

DEBUG:netmiko:read_channel: DEBUG:netmiko:[find_prompt()]: prompt is Password: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:Pattern is: Bnet-A101 DEBUG:netmiko:_read_channel_expect read_data: CCCCAuthentication failed, please try again!

Password:

DEBUG:netmiko:_read_channel_expect read_data: CCCCAuthentication failed, please try again! Password:

DEBUG:netmiko:_read_channel_expect read_data:

DEBUG:netmiko:_read_channel_expect read_data:

[Connection to 192.168.247.2 closed by foreign host] Bnet-A101# Bnet-A101#

DEBUG:netmiko:Pattern found: Bnet-A101 CCCCAuthentication failed, please try again!

Password: CCCCAuthentication failed, please try again! Password:

[Connection to 192.168.247.2 closed by foreign host] Bnet-A101# Bnet-A101#

DEBUG:netmiko:read_channel:

Bnet-A101# Bnet-A101# Bnet-A101# Bnet-A101# Bnet-A101#

DEBUG:netmiko:Clear buffer detects data in the channel DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'\n' DEBUG:netmiko:read_channel:

Bnet-A101#

DEBUG:netmiko:read_channel: DEBUG:netmiko:[find_prompt()]: prompt is Bnet-A101# DEBUG:netmiko:read_channel: DEBUG:netmiko:write_channel: b'show version\n' DEBUG:netmiko:Pattern is: show\ version DEBUG:netmiko:_read_channel_expect read_data: s DEBUG:netmiko:_read_channel_expect read_data: how version

DEBUG:netmiko:Pattern found: show\ version show version

DEBUG:netmiko:read_channel: DEBUG:netmiko:read_channel: DEBUG:netmiko:read_channel: DEBUG:netmiko:read_channel: DEBUG:netmiko:read_channel: DEBUG:netmiko:read_channel: DEBUG:netmiko:read_channel: DEBUG:netmiko:read_channel: DEBUG:netmiko:read_channel: DEBUG:netmiko:read_channel:

output of sh ip route connected executed under R1 not R2

hackmoonlight commented 3 years ago

Terminal output:

ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
ssh 192.168.247.2
Password: 
SSH prompt: Password:
hackmoonlight commented 3 years ago

@ktbyers

hackmoonlight commented 3 years ago

@ktbyers

hackmoonlight commented 3 years ago

The log shows that the password is not written?

hackmoonlight commented 3 years ago

Hello @ktbyers , I made some change in the code and it connects to the remote device. but after using the redispatch function , I still not able to execute commands on the remote device.

Untill here I connected to the second router

`ldp= self.get_ldp_neighbors(alias) msg = '' for x in ldp.keys(): addr_list = ldp[x]['addresses'] #List of ldp ip adresses
print(addr_list) src_ip_addr= ldp[x]['SrcIPaddr'] #source ip addr print(src_ip_addr)

Use raw read/write to SSH into device2

        print(device_info)
        net_connect = ConnectHandler(**device_info)

        net_connect.write_channel('ssh'+' '+src_ip_addr+'\n')
        time.sleep(1)
        net_connect.write_channel(net_connect.password + '\n')
        time.sleep(1)
        output = net_connect.read_channel()
        print(output)
        ### Logged into Second device
        print ("SSH prompt: {}".format(net_connect.find_prompt()))`

but After runing the dispatch command I cannot run commands on the router.

` redispatch(net_connect, device_type='cisco_ios', session_prep=True)

        net_connect.enable()
        new_output = net_connect.send_command('show version', use_textfsm=True)

        version= new_output[0]['rommon']  #check ios version
        # check if addr_list exist in addr(list of ip addr got with cisco cmd)

        if  version == 'IOS-XE':
            new_output = net_connect.send_command('show ip route connected')
            addr= re.findall( r'[0-9]+(?:\.[0-9]+){3}', new_output) # list of @ip got from new_output
            verif = set(addr) & set(addr_list)
            #return src_ip_addr
            if verif == addr_list:
                msg= 'ip in the list'

        else:
            new_output1 = net_connect.send_command('sh route local')      self.cli   
            # cmd= "sh route local"
            # new_output1= self.device.cli([cmd])[cmd]
            addr= re.findall( r'[0-9]+(?:\.[0-9]+){3}', new_output1)
            if addr_list == addr:
                msg= 'ip in the list'
    return msg    `

This is the log from robot framework showing that I am connectd to the second router:

Start / End / Elapsed: 20210506 02:09:23.813 / 20210506 02:09:40.985 / 00:00:17.172 02:09:40.985 INFO ['192.168.242.80', '192.168.243.64', '192.168.247.13', '192.168.247.9', '192.168.247.6', '192.168.247.57'] 192.168.247.6 {'device_type': 'cisco_ios', 'ip': 'Bnet-A101', 'username': '*', 'password': '***', 'fast_cli': False} ssh 192.168.247.6 C


BRATISLAVA vLAB / bnet-P101
THIS IS A PRIVATE SYSTEM MANAGED BY ORANGE BUSINESS SERVICES
ACCESS TO THIS DEVICE REQUIRES AUTHENTICATION AGAINST THE
>> LAB INFRASTRUCTURE TACACS SERVICE <<
Your "Saturn" login should be used here
_____

Password: C


  |                                                                |
  |  Activity on this device is recorded and possibly monitored    |
  |________________________________________________________________|

SSH prompt: RP/0/RP0/CPU0:Bnet-P101# ['192.168.243.61', '192.168.247.10', '192.168.247.21', '192.168.247.17', '192.168.242.79', '192.168.247.70', '192.168.247.2'] 192.168.242.79 {'device_type': 'cisco_ios', 'ip': 'Bnet-A101', 'username': '', 'password': **', 'fast_cli': False} ssh 192.168.242.79 Password: CCCCCCC CCCCCCCCCC CC C


BNET-A201 at BRATISLAVA vLAB
THIS IS A PRIVATE SYSTEM MANAGED BY ORANGE BUSINESS SERVICES
ACCESS TO THIS DEVICE REQUIRES AUTHENTICATION AGAINST THE
>> LAB INFRASTRUCTURE TACACS SERVICE <<
Your "saturne" login should be used here
_____

CCCCCCC CCCCCCCCCC CC C


  |                                                                |
  |  Activity on this device is recorded and possibly monitored    |
  |________________________________________________________________|

Bnet-A201# SSH prompt: Bnet-A201#

02:09:40.985 INFO ${output} =

ktbyers commented 3 years ago

@hackmoonlight Did you work this out?