Interactive SSH in SH

Started by deanwebb, February 03, 2017, 11:50:13 AM

Previous topic - Next topic

deanwebb

My task:
Over 4000 switches have moved from an outside vendor's full support to the full support of us, the internal guys. I have a box that runs Linux that can access them all, but that box has just sh, I believe. I can't install other packages on it.

What I need to do is:
1. ssh username@host
2. Go into interactive mode
3. provide password
4. execute "sh run | inc help"
5. Collect results - null if no results, Ok with just knowing if that command produced any response, specifics not important
6. "exit"
7. Back to 1 for the next switch on the list.

I keep getting stuck with the interactive part, and I'm a little tired of reading stackoverflow responses to that issue by saying to either install sshpass or use an RSA key that's loaded on all the hosts. I can't change the hosts, this is just recon to see if the switch is reachable, if it is SSH-able, and if it manages DHCP helper addresses.

As for #5, if the full output of the script was piped to a textfile, that would be fine. There are lots of switches, though, so the script needs to run unattended.

Any way to make a sh script to do interactive ssh?
Take a baseball bat and trash all the routers, shout out "IT'S A NETWORK PROBLEM NOW, SUCKERS!" and then peel out of the parking lot in your Ferrari.
"The world could perish if people only worked on things that were easy to handle." -- Vladimir Savchenko
Вопросы есть? Вопросов нет! | BCEB: Belkin Certified Expert Baffler | "Plan B is Plan A with an element of panic." -- John Clarke
Accounting is architecture, remember that!
Air gaps are high-latency Internet connections.

Otanx

Can you ssh to the linux box that has access to the switches? Then you can run a script on that box that logs into your locked down linux box, and usesscreen scraping to parse output and collect input. Kind of a hack, but maybe doable.

-Otanx

deanwebb

No other Linux box at present. We can get one spun up, but that could take up to 2 weeks. I can copy a script to the lockdown box, just can't install other packages on it.
Take a baseball bat and trash all the routers, shout out "IT'S A NETWORK PROBLEM NOW, SUCKERS!" and then peel out of the parking lot in your Ferrari.
"The world could perish if people only worked on things that were easy to handle." -- Vladimir Savchenko
Вопросы есть? Вопросов нет! | BCEB: Belkin Certified Expert Baffler | "Plan B is Plan A with an element of panic." -- John Clarke
Accounting is architecture, remember that!
Air gaps are high-latency Internet connections.

Otanx

You don't necessarily need another linux box. Powershell can do ssh. You will need to be able to install a plugin on the Windows box. See the link below. Have powershell ssh to the linux box using the Posh-SSH plug in, and then send commands using Invoke-SSHStreamExpectAction see the second link below. Depending on when you need to have this figured out I might be able to come up with something this weekend. Not very good at Powershell, but it should be an interesting problem.

http://www.thomasmaurer.ch/2016/04/using-ssh-with-powershell/

https://github.com/darkoperator/Posh-SSH/blob/master/Readme.md

-Otanx

deanwebb

I have a pair of Winders boxes where I have admin rights. I can go down that powershell route.
Take a baseball bat and trash all the routers, shout out "IT'S A NETWORK PROBLEM NOW, SUCKERS!" and then peel out of the parking lot in your Ferrari.
"The world could perish if people only worked on things that were easy to handle." -- Vladimir Savchenko
Вопросы есть? Вопросов нет! | BCEB: Belkin Certified Expert Baffler | "Plan B is Plan A with an element of panic." -- John Clarke
Accounting is architecture, remember that!
Air gaps are high-latency Internet connections.

wintermute000

#5
python....

this was one of my first efforts - goes in, does show ip int brie, puts all the IP addresses in a CSV. You can adapt this probably.


I know you said you only have sh or whatever. I know you're in global megacorp, this is 2017 FFS, having a standard linux box with python libraries etc. installed in your management subnet should not be any kind of issue. In fact anyone who objects (esp security.... tell them to do one ;) ) should be fired for being a luddite.

I also did this the painful 100% manual way including error checking SSH vs telnet. Nowadays there's things like netmiko and textfsm that make the grepping waaaaay easier.


from pprint import pprint
from Exscript.util.start import start
from Exscript.util.file  import get_hosts_from_file
from Exscript.util.match import first_match
from Exscript import Account
from Exscript.util.interact import read_login
from Exscript.protocols import SSH2
from Exscript.protocols import Telnet
from Exscript.util.interact import read_login
import Exscript.protocols.drivers
import collections
import socket
import csv

account = read_login()
show_ip_interface_brief = []
show_all_interfaces = []



# Create list of devices to query - uses list comprehension
hosts_to_action = {}
with open("get-interfaces.csv") as hosts_csv:
    hosts_to_action = collections.OrderedDict(line.strip().split(',') for line in hosts_csv if not line.startswith("#"))


# Function to test what port is open
def test_port(ip,port):
    connect = (ip,port)
    try:
        sock = socket.create_connection(connect,4)
        sock.close()
        return 1
    except Exception: return 0

# Function to grab show ip interface brief information off one device
def get_show_interface(ip):
    try:
        interfaces_raw = ""
        interface_lines = []
        interface_lines_raw = []

        # connect via Exscript

        conn.connect(ip)
        conn.login(account)

        conn.execute('terminal length 0')
        conn.execute('show ip interface brief | exclude unassigned')

        # Get output, split into list of lines
        interfaces_raw = repr(conn.response)
        interface_lines = interfaces_raw.split("\\r\\n")
        # Split each list entry into another list and insert hostname at beginning
        for line in interface_lines:
            # Ignore header line
            if 'Interface' in line:
                continue
            line_split = line.split()
            if len(line_split) == 6: #filter out irrelevant lines i.e. those not with 6 columns
                if_name, ip_addr, discard1, discard2, line_status, line_proto = line_split
                show_ip_interface_brief.append((ip, hostname, if_name, ip_addr, line_status, line_proto))
        # Append to master list and close connection
        show_all_interfaces.append(show_ip_interface_brief)

        resultfile = open("SHOW_IP_INTERFACES_BRIEF.CSV",'wb')
        wr = csv.writer(resultfile, dialect='excel')
        wr.writerows(show_ip_interface_brief)

        print('host '+ hostname +' successfully queried')
        conn.send('exit\r')        # Send the "exit" command
        conn.close()               # Wait for the connection to close

    except Exception as e: # Error handling - put login/pw errors into login-fail.log
        out_file = open("login-fail.log", "a")
        output = (hostname) + ',' + (ip) + ' has thrown a login error (password?)\n'
        out_file.writelines(output)
        print (hostname) + ',' + (ip) + " has thrown a login error (password?)"
        print(e)


# Function to iterate through list and call the show_interface function via appropriate mechanism
for hostname,ip in hosts_to_action.items():
    if test_port(ip,'22'):
      print('Querying host '+hostname+' via ssh...')
      conn = SSH2()
      get_show_interface(ip)

    elif test_port(ip,'23'):
      print('Querying host '+hostname+' via telnet...')
      conn = Telnet()
      get_show_interface(ip)

    else: # Error handling - put connectivity errors into connect-fail.log
      out_file = open("connect-fail.log", "a")
      output = (hostname) + ',' + (ip) + ' is not accessible via SSH or Telnet.\n'
      out_file.writelines(output)
      print (hostname) + ',' + (ip) + " is not accessible via SSH or Telnet."
      continue

print ("==============================================================================")
print ("Finished All Hosts - Results Below: Output to SHOW_IP_INTERFACES_BRIEF.CSV")
print ("==============================================================================")
pprint (show_all_interfaces)
print ("==============================================================================")










deanwebb

Quote from: wintermute000 on February 04, 2017, 04:05:26 AM
I know you're in global megacorp, this is 2017 FFS, having a standard linux box with python libraries etc. installed in your management subnet should not be any kind of issue.

We can get the box, but there's the twin massive wait of getting a VM spun up and then adding its IP to the VTY ACL for all our switches. Current production Linux box has that VTY access permitted but, it's prod, so no changes during our Financials Freeze and then other changes take approval, so... yeah... could be a month or two, three or four tops before I'd have that guy for use. Meanwhile, the project would like progress on this stuff in order to meet deadlines. This pretty much goes under a "problems of a company of a certain size" discussion.

As soon as I get that Linux box with access to everything, I'm putting python on it, you betcha. Meanwhile, it looks like either Powershell or the semi-scripted way I have currently that does the ssh connection automatically, I type the rest.
Take a baseball bat and trash all the routers, shout out "IT'S A NETWORK PROBLEM NOW, SUCKERS!" and then peel out of the parking lot in your Ferrari.
"The world could perish if people only worked on things that were easy to handle." -- Vladimir Savchenko
Вопросы есть? Вопросов нет! | BCEB: Belkin Certified Expert Baffler | "Plan B is Plan A with an element of panic." -- John Clarke
Accounting is architecture, remember that!
Air gaps are high-latency Internet connections.

Otanx

I tried to get the Posh-SSH stuff to work, but ran into a few problems. Mostly my lack of PowerShell skills. I can get the SSH session to open, and I can even send it a command, but you can't interact with the command this way (i.e. supply a password). I can't get the StreamExpect to work. Going to try again tonight. I feel like it is almost there.

-Otanx

deanwebb

Meanwhile, we kept after it and finished off the manual process. But I've got a Linux box request underway and I will make sure it can get into the business of every switch and router and firewall on the network.

And the WLCs and autonomous APs. Don't want to forget those...
Take a baseball bat and trash all the routers, shout out "IT'S A NETWORK PROBLEM NOW, SUCKERS!" and then peel out of the parking lot in your Ferrari.
"The world could perish if people only worked on things that were easy to handle." -- Vladimir Savchenko
Вопросы есть? Вопросов нет! | BCEB: Belkin Certified Expert Baffler | "Plan B is Plan A with an element of panic." -- John Clarke
Accounting is architecture, remember that!
Air gaps are high-latency Internet connections.

dlots

I imagine wintermutes is better, but you can probaby use the Linux box as a go between.

You'll probably want to add some error checking, and I didn't do any testing for this but something like this should work I would think.

Just stick the IPs you want to SSH to in a doc names 'switches'

If it doesn't work and you need a hand you have my e-mail.

import os
import re
import socket
import sys
import netmiko
import time

device_to_check = []
def read_in_switches(input):
for line in open(input, 'r').readlines():
device_to_check.append(line)

def to_doc(file_name, varable):
f=open(file_name, 'w')
f.write(varable)
f.close()

switches_list = 'switches'
read_in_switches(switches_list)
net_connect = netmiko.ConnectHandler(device_type='cisco_ios', ip='linuxs IP address', username='your username', password='your_password'
for switch in device_to_check:
send = 'ssh username@' + switch
net_connect.send_command_expect(send)
net_connect.send_command_expect('go to interactive mode')
net_connect.send_command_expect('password')
output = net_connect.send_command_expect("sh run | inc help")
to_doc(switch,output)
        print (switch,output)
net_connect.send_command_expect('exit')

wintermute000

dlots, does netmiko handle the non-privileged > prompt?

one of the things I found when using paramiko back int he dark ages was that it chokes on >, but works fine on # prompt.

dlots

Don't know, haven't run into that yet, I think you can make it work by using

net_connect.send_command
rather than
net_connect.send_command_expect

net_connect.send_command_expect is waiting for the prompt to come back, but net_connect.send_command seems to just wait for 30 sec.

icecream-guy

Quote from: deanwebb on February 07, 2017, 01:34:17 PM
I will make sure it can get into the business of every switch and router and firewall on the network.


That's quite risky, unless you have excellent Linux skills, patching and iptables, one wrong move and a compromise of the box and your network falls like a house of cards. You are in security you should know better than that....  can you setup two-factor with that linux box?

:professorcat:

My Moral Fibers have been cut.

deanwebb

Quote from: ristau5741 on February 08, 2017, 11:24:03 AM
Quote from: deanwebb on February 07, 2017, 01:34:17 PM
I will make sure it can get into the business of every switch and router and firewall on the network.


That's quite risky, unless you have excellent Linux skills, patching and iptables, one wrong move and a compromise of the box and your network falls like a house of cards. You are in security you should know better than that....  can you setup two-factor with that linux box?



CyberArk PAM FTW 8)
Take a baseball bat and trash all the routers, shout out "IT'S A NETWORK PROBLEM NOW, SUCKERS!" and then peel out of the parking lot in your Ferrari.
"The world could perish if people only worked on things that were easy to handle." -- Vladimir Savchenko
Вопросы есть? Вопросов нет! | BCEB: Belkin Certified Expert Baffler | "Plan B is Plan A with an element of panic." -- John Clarke
Accounting is architecture, remember that!
Air gaps are high-latency Internet connections.

deanwebb

Installing python-libs (410/1413)

:greatoffer:
Take a baseball bat and trash all the routers, shout out "IT'S A NETWORK PROBLEM NOW, SUCKERS!" and then peel out of the parking lot in your Ferrari.
"The world could perish if people only worked on things that were easy to handle." -- Vladimir Savchenko
Вопросы есть? Вопросов нет! | BCEB: Belkin Certified Expert Baffler | "Plan B is Plan A with an element of panic." -- John Clarke
Accounting is architecture, remember that!
Air gaps are high-latency Internet connections.