I'm trying to write a script to connect to VPN more easily. I want the script to use the user input and connect to a vpn endpoint via openvpn, print the process ID for the user, and then continue running in the background but return the user to the shell. I tried child.close(force=False), os.fork(), and a few other things without any luck. The code I'm using is below. Any advice is much appreciated!
import getpass
import os
import pexpect
import random
import subprocess
import sys
country = sys.argv[1] if len(sys.argv) > 1 else 'US'
print('Connecting to VPN through ' + country)
vpns=subprocess.run(['ls', '/etc/openvpn/'], capture_output=True).stdout.decode().split('\n')
matching_vpns=filter(lambda vpn: vpn[:2].lower() == country.lower(), vpns)
chosen_vpn = random.choice(list(matching_vpns))
print('Connecting to ' + chosen_vpn + '\n')
child = pexpect.spawnu('sudo openvpn /etc/openvpn/'+chosen_vpn)
child.expect('Enter Auth Username:')
username = input('Enter Auth Username: ')
child.sendline(username)
child.expect('Enter Auth Password:')
password = getpass.getpass('Enter Auth Password: ')
child.sendline(password)
child.logfile_read = sys.stdout
while True:
try:
child.expect('\n', timeout=None)
if 'Initialization Sequence Completed' in child.before:
print("\nSuccessfully connected to " + chosen_vpn)
print("To stop VPN, run 'sudo pkill -9 -P " + str(child.pid) + "'")
break
except pexpect.EOF:
break
Related
Im trying to telnet to a NETGEAR SWITCH through python script,
i succeed to connect through Putty, but when im trying with python code
i get nothing (no promt) after putting the password (which is empty, only need to press enter.
Here is the code:
import getpass
import telnetlib
import time
HOST = "10.10.10.1"
user = input("Enter your remote account: ")
password = getpass.getpass()
tn = telnetlib.Telnet(HOST)
tn.read_until(b"User: ")
tn.write(user.encode('ascii') + b"\n")
if password:
tn.read_until(b"Password: ")
tn.write(password.encode('ascii') + b"\n")
tn.write(b"ls\n")
tn.write(b"exit\n")
print(tn.read_all().decode('ascii'))
I tried to put sleep delays and double checked the read_until parameters and also with and without spaces, but with no success,
please help.
Out of function, the script works, but inside the function, script does not work.
import telnetlib
import sys
def teltest():
host = "192.168.2.2"
user = "admin"
password = "admin"
tn = telnetlib.Telnet(host)
tn.read_until("Username:")
tn.write(user + "\n")
tn.read_until("Password:")
tn.write(password + "\n")
tn.write("enable\n")
tn.write("config t\n")
tn.write("interface eth 0/0/13\n")
tn.write("description TEST\n")
teltest()
Why and how can i fix it?
This is happening because of the function returns before properly terminating the connection leaving the other end of the device in a meta state. Adding a sleep at the end as mentioned in the comments would let room for cleaning up the connection thereby executing what was written onto the device.
Telnet.write(buffer) Write a string to the socket, doubling any IAC
characters. This can block if the connection is blocked. May raise
socket.error if the connection is closed.
import telnetlib
import sys
def teltest():
host = "192.168.2.2"
user = "admin"
password = "admin"
tn = telnetlib.Telnet(host)
tn.read_until("Username:")
tn.write(user + "\n")
tn.read_until("Password:")
tn.write(password + "\n")
tn.write("enable\n")
tn.write("config t\n")
tn.write("interface eth 0/0/13\n")
tn.write("description TEST\n")
time.sleep(1)
teltest()
Posting this as an answer for the benefit of the community despite the fact that the op received help from comments.
Imagine a situation when two servers are available. One of them is constantly sshing to another one and executing some commands. The process takes around 5-10 seconds for each session since ssh connection must be established every time.
The question: is it possible to have a ready, established ssh connection in order to reduce the time of executing commands on remote server?
Here is an example for you. It can work as a ssh client. No need to recreate session everytime.
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import os,sys
import paramiko
import threading
import platform
curr_ssh = None
curr_prompt = ">>"
#how to use it
def printUsage():
print " !ls :list sessions."
print " !session id :connect session."
print " !conn host user password:connect host with user."
print " !exit :exit."
#connect using paramiko
def conn(ip,username,passwd):
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip,22,username,passwd,timeout=5)
print "Connect to ",ip," with ",username
global curr_prompt
curr_prompt=username+"#"+ip+">>"
return ssh
except:
return None
#get former session
sessions=[]
def loadSessions():
global sessions
try:
f = open("sessions")
sessions = f.readlines()
f.close()
except:
pass
#main function
def exe_cmd_local(cmd):
if(cmd == "!ls"):
loadSessions()
global sessions
i=0
print "Sessions:"
for s in sessions:
print"[%d] %s" %(i,s)
i+=1
else:
vals = cmd.split(' ')
if(vals[0]=="!session"):
id = (int)(vals[1])
if(id<len(sessions)):
os_name = platform.system()
new_console_cmd = ""
if(os_name == "Linux"):
new_console_cmd="gnome-terminal -e \"./ssh.py " + sessions[id]+"\""
elif(os_name == "Windows"):
new_console_cmd="start ssh.py " + sessions[id]
os.system(new_console_cmd)
else:
print "Didn't hava sessoin ",vals[1]
elif(vals[0]=="!conn"):
global curr_ssh
curr_ssh = conn(vals[1],vals[2],vals[3])
f = open("sessions","a")
line = vals[1]+" "+vals[2]+" "+vals[3]+"\n"
f.write(line)
f.close()
#execute command remotely
def exe_cmd_ssh(ssh,cmd):
if(ssh == None):
print "Didn't connect to a server. Use '!conn' to connect please."
return
stdin, stdout, stderr = ssh.exec_command(cmd)
print stdout.read()
print stderr.read()
if __name__=='__main__':
loadSessions()
if(len(sys.argv)==4):
curr_ssh = conn(sys.argv[1],sys.argv[2],sys.argv[3])
else:
printUsage()
while True:
cmd = raw_input(curr_prompt)
if(len(cmd)==0):
continue
if(cmd == "!exit"):
if(curr_ssh != None):
curr_ssh.close();
break
else:
if(cmd[0] == '!'):
exe_cmd_local(cmd)
else:
exe_cmd_ssh(curr_ssh,cmd)
Hope it helps. :)
One could use an existing ssh connection, by configuring ssh to re-use an already established connection. Please see man ssh_config:
ControlMaster
Enables the sharing of multiple sessions over a single network connection. When set to “yes”, ssh(1) will ...
So your ~/.ssh/config could contain:
Host firstServer
ControlMaster auto
ControlPath ~/.ssh/tmp/controlPath_%h_%p_%r
This will create a socket as a file named by 'ControlPath'. The next ssh connection will go through that same socket and will be lightning fast.
Enjoy
I have written a python program to telnet to a switch on the network, login and enter specific commands. But I don't know what is wrong with my program as the program never gets passed through after login. I doubt the program is even taking in the password I gave at command line.
Here is my program:
import telnetlib
import getpass
import sys
Host = "10.210.1.2"
user = raw_input("hbommireddy")
password = getpass.getpass()
tn = telnetlib.Telnet(Host)
tn.read_until("Login: ")
tn.write(user + "\n")
if password:
tn.read_until("Password: ")
tn.write(password + "\n")
tn.read_until("SYSTEM-QA-S4810>")
tn.write("en\n")
tn.read_until("SYSTEM-QA-S4810#")
tn.write("show interface status\n")
print tn.read_all()
I'm trying to check for the existence of an executable on a remote machine, then run said executable. To do so I'm using subprocess to run ssh <host> ls <file>, and if that's successful, run ssh <host> <file>. ssh asks for a password, of course, and I'd like to provide that automatically. Also, I'd like to get the returncode from ls, and stdout and stderr from running the command.
So I know the communicate() method is needed, to avoid deadlocks, but I can't get the password to be recognized by Popen(stdin). Also I'm using Python 2.4.3, and stuck on that version. Here's the code I've got so far:
import os
import subprocess as sb
def WallHost(args):
#passwd = getpass.getpass()
passwd = "password"
for host in args:
# ssh to the machine and verify that the script is in /usr/bin
sshLsResult = sb.Popen(["ssh", host, "ls", "/usr/bin/wall"], stdin=sb.PIPE, stderr=sb.PIPE, stdout=sb.PIPE)
(sshLsStdout, sshLsStderr) = sshLsResult.communicate(input=passwd)
sshResult = sshLsResult.returncode
if sshResult != 0:
raise "wall is not installed on %s. Please check." % host
else:
sshWallResult = sb.Popen(["ssh", host, "/usr/bin/wall", "hello world"], stdin=sb.PIPE, stderr=sb.PIPE, stdout=sb.PIPE)
(sshWallStdout, sshWallStderr) = sshWallResult.communicate(input=passwd)
print "sshStdout for wall is \n%s\nsshStderr is \n\n" % (sshWallStdout, sshWallStderr)
args = ["127.0.0.1", "192.168.0.1", "10.10.265.1"]
WallHost(args)
Any help getting the process to accept that password is appreciated. Or if you've got a better way to check for the executable and then run it on a remote host. ;)
thx
anthony
How about using authorized_keys. Then, you don't need to input password.
You can also go hard way (only work in Linux):
import os
import pty
def wall(host, pw):
pid, fd = pty.fork()
if pid == 0: # Child
os.execvp('ssh', ['ssh', host, 'ls', '/usr/bin/wall'])
os._exit(1) # fail to execv
# read '..... password:', write password
os.read(fd, 1024)
os.write(fd, pw + '\n')
result = []
while True:
try:
data = os.read(fd, 1024)
except OSError:
break
if not data:
break
result.append(data)
pid, status = os.waitpid(pid, 0)
return status, ''.join(result)
status, output = wall('localhost', "secret")
print status
print output
http://docs.python.org/2/library/pty.html