SSH to jump server that uses Authorization Code as second step verification

Viewed 198

I am a bit new to writing code, and I'm trying to automate some kind of searching mac-address in APR Table in firewalls.

in our deployment, we can access (SSH) the firewalls only through a jump server. so this is kind of nested ssh and I've found posts and codes that run that with no issues using Paramiko.

The challenge for me here is that the jump server after entering the username and password sends an email to me with a link to click to complete the authentication or to copy a code from this email and enter it in the shell following the messages that ask to enter this code.

Of course with my code, I always get authentication fails because I am ignoring this second authentication step. I don't know how to keep the ssh tunnel open and prompt the script to allow me to enter this auth code I receive in the email and to continue the script afterwards?

My piece of code that accesses the jump server and verify that I can run a command from its shell is below:

import paramiko
import sys
import subprocess

ssh_access = paramiko.SSHClient()
ssh_access.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_access.connect('192.168.1.1', username='root', password='root')
stdin, stdout, stdrr = ssh_access.exec_command("ls -l")

response = stdout.read()
print(response)

I am stuck on this part and appreciate help to continue with doing the actual target from the script.

Part of debugging file when I do SSH to the jump server

debug1: Authentications that can continue: password,keyboard-interactive^M
debug1: Next authentication method: keyboard-interactive^M
debug1: Authentication succeeded (keyboard-interactive).^M
Authenticated to 10.101.xx.xx ([10.101.xx.xx]:22).^M
debug1: channel 0: new [client-session]^M
debug1: Requesting no-more-sessions@openssh.com^M
debug1: Entering interactive session.^M
debug1: pledge: network^M
debug1: client_input_global_request: rtype hostkeys-00@openssh.com 
want_reply 0^M
debug1: Sending environment.^M
debug1: Sending env LANG = C.UTF-8^M
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0^M
debug1: client_input_channel_req: channel 0 rtype eow@openssh.com reply 
0^M
debug1: channel 0: free: client-session, nchannels 1^M
debug1: fd 2 clearing O_NONBLOCK^M
Connection to 10.101.xx.xx closed.^M
Transferred: sent 2760, received 4520 bytes, in 21.5 seconds^M
Bytes per second: sent 128.4, received 210.3^M
debug1: Exit status 0^M
1 Answers

So I was able to resolve this by using the auth_interactive_dumb which transports the prompts from the remote server to the terminal so you can interact and respond to those prompts

Below is the piece of code that worked for me:

import paramiko
import socket
import getpass

def connect_ssh(user):
    my_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    my_socket.connect(("xx.xx.xx.xx", 22))
    my_transport = paramiko.Transport(my_socket)
    my_transport.start_client(timeout=60)
    my_transport.auth_interactive_dumb(user)
    channel = my_transport.open_session()
    channel.exec_command("netstat -an")
    channel.recv_ready()
    response = channel.recv(1024).decode("utf-8")
    print(response)

connect_ssh('your_user_name')

When i run the script, i am prompted to enter my password. then i got this message for the second verification step

Email sent to xxxx@abc.com. Click the link or manually enter the 
code to authenticate. After that, please press <enter> to finish authentication:

I click on the link and hit enter and the exec_command runs so i get the below output

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 127.0.0.1:5000          0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:5001          0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:6062          0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:8089            0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:8126          0.0.0.0:*               LISTEN     
tcp        0      0 10.101.xx.xx:22         10.47.xx.xx:55533     ESTABLISHED
tcp        0      0 10.101.xx.xx:22         10.47.xx.xx:62391     ESTABLISHED
Related