python sockets application not functioning as expected from terminal - python

I'm following a book I purchased called 'Black Hat Python' but have run into an issue I cannot seem to resolve.
The book so far has had the reader create a few python applications: a command line tool to send/receive data, execute commands remotely and a TCP proxy client that redirects a connection via specified host/port.
The issue is that when I launch these from the terminal, I receive no output and the terminal waits for my input with a screen grab type cursor. It awaits for me to 'grab' an image or part of the screen 3 times and then fails. I then have some image files save to my Home folder named, 'getopt', 'socket', 'subprocess', 'threading' and 'sys'. The output I get from the terminal after 'grabbing' the screen 3 times is:
root#c0ff33:~# ./1proxy.py 127.0.0.1 21 ftpserver.ftp 21 True
./1proxy.py: line 5: syntax error near unexpected token `('
./1proxy.py: line 5: `def server_loop(local_host, local_port, remote_host, remote_port, receive_first):
However, when I run this in my IDE client, it runs fine when I pass it the same arguments. The connection is initiated and awaits the connection to the remote host. The output is then correct and the proxy client waits for a connection via localhost on port 21:
[*] Listening on 127.0.0.1:21
[==>] Receive incoming connection from 127.0.0.1:49475
Does anyone know why this is happening? Why can I not execute this from the terminal with the same results?
The arguments I am passing are:
./myproxy.py 127.0.0.1 21 ftpserver.ftp 21 True
127.0.0.1 = localhost
21 = local port
ftpserver.ftp = remote host
21 = remote port
True = receive first

That could happen because your shell tries to pass your script to BASH to execute. BASH will see lots of errors in your code. Instead of typing ./code.py you need to run python code.py or add #!/path/to/python in the beginning of your script.

Related

How to send data from a file in a Python docker container to remote SFTP server?

I have a Python script I am trying to run in a Docker container to send a file that is on this container to an SFTP server.
I tried the following :
import paramiko
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
session = ssh.connect(hostname="X", port=X, username='X', password="X")
stdin,stdout,stderr = ssh.exec_command('sftp -P X ldzdl#hostname', get_pty=True)
I also tried with paramiko transport method but didn't work from remote (docker container) to remote SFTP.
But I have the following error : paramiko.ssh_exception.AuthenticationException: Authentication failed.
How can I do this ? I don't know if my method is okay or if there is other better way to solve it (send data from container to an SFTP server).
The argument given to the exec_command function is not the command you would normally run on the local (client) host's shell, but rather attempted to be ran on the remote (server) host. While it is not likely to get an AuthenticationException by attempting to run remote commands, as you did not post a full traceback in the question - it is hard to tell for sure.
I suggest checking the following code:
import paramiko
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
session = ssh.connect(hostname="X", port=X, username='X', password="X")
### so far, same code as in the question ###
print("Auth OK")
sftp_connection = ssh.open_sftp()
sftp_connection.put("local/file/path", "remote/file/path")
If you see the "Auth OK" print - then you should be good to go, just replace the file path arguments of the sftp_connection.put() method with actual local and remote file paths.
Otherwise - there is an actual authentication issue which should be resolved.

How can I output/print "proof" that the server is being rebooted using the script I've written?

Essentially I wrote a script that reboots a server using python and an SSH library called paramiko. My script runs as it should, but I don't know if it is actually rebooting the server because the server is not on site in the office. Is there a way where I can print and output "proof" that the server is actually being rebooted ? I am a little new to using python to give commands to network devices using SSH.
I did actually run my code and it runs as it should, but I have not tested to see if a server is actually turning on and off.
There is no need to copy and paste all of my code, but there are two functions that are extremely important:
def connectToSSH(deviceIP, deviceUsername, devicePassword):
ssh_port = 22
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(deviceIP, ssh_port, deviceUsername, devicePassword)
time.sleep(5)
return ssh
def reboot_server(ssh):
prompt = raw_input('Are you sure you want to reboot this server ?')
if prompt.lower() == 'y' or prompt.lower() == 'n':
print('Proceeding to reboot the switch\n')
else:
print('Proceeding to exit the program\n')
sys.exit(-1)
channel = ssh.invoke_shell()
ssh.exec_command("/sbin/reboot -f > /dev/null 2>&1 &") # executes command to reboot server , is this the right command ? I found this on another stackOverflow post ?
channel.close()
print("Please wait for server to be rebooted")
I am receiving no compile errors but I want to be sure that the command:
ssh.exec_command("/sbin/reboot -f > /dev/null 2>&1 &")
is actually rebooting the server. If it is, is there a way I can print/output proof that it is being rebooted ? If so, how do I go about doing that ?

Executing Interactive SSH Command via Python script

I am trying to automate to collect the logs from the Cisco Call Manager via CLI by using the from paramiko_expect import SSHClientInteraction where I am not able to send the interactive command to the server.
While trying to download the logs, it will ask information like SFTP IP address, username, password and directory which needs to send an interactive command.
whenever the code runs, it stops at the interactive command section where its not sending the command to the server because of which python script stops here. need to know is there any other way to code these requirements.
for example
Below section is interactive shell where I have to type y/xx.xx.xx.xx/22/User ID/Password/Directory but I can't do the same.
I need help here.. to send the command
+++++++++++++++++++++++++++++++++
Would you like to proceed [y/n]? y
SFTP server IP: xx.xx.xx.xx
SFTP server port [22]: 22
User ID: *****
Password: *****
Download directory: /
+++++++++++++++++++++++++++++++++
Command Line Interface is starting up, please wait ...
Welcome to the Platform Command Line Interface
VMware Installation:
4 vCPU: Intel(R) Xeon(R) Platinum 8180 CPU # 2.50GHz
Disk 1: 110GB, Partitions aligned
6144 Mbytes RAM
admin:file get activelog /syslog/AlternateSyslog
Please wait while the system is gathering files info ...
Get file: active/syslog/AlternateSyslog
done.
Sub-directories were not traversed.
Number of files affected: 5
Total size in Bytes: 23354752
Total size in Kbytes: 22807.375
Would you like to proceed [y/n]? y
SFTP server IP: xx.xx.xx.xx
SFTP server port [22]:
User ID: *****
Password: *****
Download directory: /
The authenticity of host 'xx.xx.xx.xx (xx.xx.xx.xx)' can't be established.
Are you sure you want to continue connecting (yes/no)? yes
.....
Transfer completed.
admin:
I am able to get the show command output but not able to download the logs.
#!/usr/bin/python
# PSFL license
# Importing SSHClientInteraction from paramiko
import paramiko
from paramiko_expect import SSHClientInteraction
import threading
# Specify connection info for each node in square brackets: ["IP ADDRESS", "USERNAME", "PASSWORD"]
connection = [["xx.xx.xx.xx", "userid", "password"]]
# Define function which is responsible for opening SSH connection and running specified commands
def cucm(ip, username, password):
sshsession = paramiko.SSHClient()
sshsession.set_missing_host_key_policy(paramiko.AutoAddPolicy())
sshsession.connect(ip, username=username, password=password)
# "display=True" is just to show you what script does in real time. While in production you can set it to False
interact = SSHClientInteraction(ssh, timeout=600, display=True)
# program will wait till session is established and CUCM returns admin prompt
interact.expect('admin:')
# program runs show status command
interact.send('show status')
# program waits for show status command to finish (this happen when CUCM returns admin prompt)
interact.except('admin:')
# program sends syslog to download the file
interact.send('file get activelog /syslog/AlternateSyslog')
if interact.last_match == 'Would you like to proceed [y/n]? ': # program matches prompted command by using if command and will send interact command to it.
interact.send('y')
if interact.last_match == 'SFTP server IP:':
interact.send('xx.xx.xx.xx')
if interact.last_match == 'SFTP server port [22]:':
interact.send('22')
if interact.last_match == 'User ID:':
interact.send('userid')
if interact.last_match == 'Password:':
interact.send('password')
if interact.last_match == 'Download directory:':
interact.send('/')
interact.expect('admin:')
output = interact.current_output_clean # program saves output of show status command to the "output" variable
sshsession.close()
# Run loop which will open separate thread for each node specified in the connection list. This targets "session" function defined at the beginning
for i in connection:
t = threading.Thread(target = cucm, args = (i[0], i[1], i[2]))
t.daemon = True
t.start()
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Below is the output for the python script.
there is no error message but it stops at Would you like to proceed [y/n]? here
Command Line Interface is starting up, please wait ...
Welcome to the Platform Command Line Interface
VMware Installation:
4 vCPU: Intel(R) Xeon(R) Platinum 8180 CPU # 2.50GHz
Disk 1: 110GB, Partitions aligned
6144 Mbytes RAM
admin:file get activelog /syslog/AlternateSyslog
Please wait while the system is gathering files info ...
Get file: active/syslog/AlternateSyslog
done.
Sub-directories were not traversed.
Number of files affected: 1
Total size in Bytes: 2261400
Total size in Kbytes: 2208.3984
Would you like to proceed [y/n]?
You could try adding the global configuration command "file prompt quiet" at the beginning of your program before any other commands are sent. This will suppress any yes/no questions and auto them to the default. Just make sure that at the end of the code you turn it back off to prevent any later nasty surprises using "file prompt alert".
This works in most Cisco IOS platforms, if the command is different in CUCM I'm sure there will be an equivalent to do the same thing.
maybe you already sorted this out, but I see, that you have there one small type, which could stop that script of moving forward:
you have there:
interact.except('admin:')
instead of:
interact.expect('admin:')

Get command result from SSH/Telnet via another SSH jump server in Python

I am writing a Python code to SSH or Telnet remote hosts, execute some commands and get the result output. Here we have a jump server, so the code must be "connected" with this server and from it, Telnet or SSH the remote hosts.
All my approaches work fine within the jump server, for example I can get the output of commands inside it. The problem is when I try to remote connect to hosts from it.
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('IP', 22, username="user", password="pass")
stdin, stdout, stderr = client.exec_command("command")
for line in stdout:
print('... ' + line.strip('\n'))
client.close()
Using the library jumpssh get same results, and I am not will able to Telnet hosts. I tried the follow approach, but get the error
Administratively prohibited.
from jumpssh import SSHSession
gateway_session = SSHSession('jumpserver','user', password='pass').open()
remote_session = gateway_session.get_remote_session('IP',password='pass')
print(gateway_session.get_cmd_output('command'))
In the last company i worked we had a license from an SSH client that supports Python scripts, and worked fine in a more "textual" treatment.
There is any way of accomplish same task natively in Python?
SSHSession is trying to open direct-tcpip port forwarding channel over the gateway_session.
"administratively prohibited" is OpenSSH sshd server message indicating that direct-tcpip port forwarding is disabled.
To enable port forwarding, set AllowTcpForwarding and DisableForwarding directives in sshd_config appropriately.
If you cannot enable the port forwarding on the server, you cannot use jumpssh library.
If you have a shell access to the server, you can use ProxyCommand-like approach instead.
See Paramiko: nest ssh session to another machine while preserving paramiko functionality (ProxyCommand).

P4 python connection broken SSL error

I'm already using P4V client and everything is fine, no connection error.
Error:
I've got some SSL errors when I try to execute p4 command from Python.
And it's random, If i re run the script, error isnt thrown everytime
From the client, the output is :
SSL receive failed.\nread: Operation succeed : WSAECONNRESET
From the server side logs, i've got :
Connection from 90.XX.XX.93:53929 broken. SSL receive failed. read:
Connection reset by peer: Connection reset by peer
After le P4 Connection with p4.connect(), I run a p4.run_trust() command and the result seems ok
Trust already established
This error is trown doing a p4 fetch, of p4 edit myfile
Configuration
I'm starting my python script from the same computer running the P4V client. I'm using the same configuration ( user, workspace, url+port > ssl:p4.our-url.domain:1666 ). The SSL error happened with or without the P4V client started.
The SSL certificate was generated during the Perforce Server installation and configuration.
There is no apache server behind our subdomain p4.our-domain, so I can't test the SSL certificate using online SSL checker ( my network knowledge reach its limit there )
When i do a p4 info there is a "peer address", basically my IP with a random generated port (53929). What is this port ? Do i need to set a fixed port and redirect to my computer runing the script ?
Do you have any ideas where that error come from ? Is that a bad server configuration ( weird cause every p4v client in the office works).
Do i need to establish and distribute a new certificate to all users of the P4Python script ?
Python 3.5.4
PyOpenssl 18.0.0
P4Python 2017.2.1615960
Thanks a lot for any advice.
ANSWER suggested by Sam Stafford
Sam was right, It seems I got a timeout. I was opening the P4 connection and connecting to the server on the script launch, then processing was launched to generate files before using p4 fetch/add/submit. Here is a workaround to reconnect in case on disconnection from the server
# self.myp4 = P4() was created on init, files are added
submited = False
maxTry = 5
while not submited and maxTry > 0:
try:
reslist = self.p4.run_submit(ch)
except P4Exception as p4e:
print(str(self.p4.errors))
self.myp4.disconnect()
maxTry -= 1
self.myp4.connect()
submited = reslist is not None and len(reslist) > 0
That works if you want to keep the connection open. I guess the best way to avoid timeout is to call P4.connect() method just before any P4.run_*method*() and close it after. Instead of wating for timeout to restart the connection.
"Connection reset by peer" is a TCP error.
What does "connection reset by peer" mean?
Maybe your script is holding its connection open longer than P4V does, and a transient network failure during that period causes the connection to be reset? The best fix is probably to have the script catch the error, open a new connection, and pick up where it left off.

Categories