error message in terminalhelp I am trying to create an ssh server in python according to the book blackhat python, when I run this code I get "FileNotFoundError: [Errno 2] No such file or directory: '/home/burp/blackhatpy/.test_rsa.key'"
do I need to create the file .test_rsa.key? Help!! am a beginner and new to python, the image is what error i get When i try to run the server
import os
import paramiko
import socket
import sys
import threading
CWD = os.path.dirname(os.path.realpath(__file__))
HOSTKEY = paramiko.RSAKey(filename=os.path.join(CWD, '.test_rsa.key'))
class Server (paramiko.ServerInterface):
def __init__(self):
self.event = threading.Event()
def check_channel_request(self, kind, chanid):
if kind == 'session':
return paramiko.OPEN_SUCCEEDED
return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
def check_auth_password(self, username, password):
if (username == 'tim') and (password == 'sekret'):
return paramiko.AUTH_SUCCESSFUL
if __name__ == '__main__':
server = '137.184.226.245'
ssh_port = 2222
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((server, ssh_port))
sock.listen(100)
print('[+] Listening for connection ...')
client, addr = sock.accept()
except Exception as e:
print('[-] Listen failed: ' + str(e))
sys.exit(1)
else:
print(f'[+] Got a connection! from {addr}')
bhSession = paramiko.Transport(client)
bhSession.add_server_key(HOSTKEY)
server = Server()
bhSession.start_server(server=server)
chan = bhSession.accept(20)
if chan is None:
print('*** No channel.')
sys.exit(1)
print('[+] Authenticated!')
print(chan.recv(1024).decode())
chan.send('Welcome to bh_ssh')
try:
while True:
command = input("Enter command: ")
if command != 'exit':
chan.send(command)
r = chan.recv(8192)
print(r.decode())
else:
chan.send('exit')
print('exiting')
bhSession.close()
break
except KeyboardInterrupt:
bhSession.close()
In the book you refer to, where it presents the code that you've included here, it tells you where to get the SSH key file that should be used to run that code. It says:
For this example, we’re using the SSH key included in the Paramiko demo files.
That file can be found here:
https://github.com/paramiko/paramiko/blob/main/demos/test_rsa.key
The code you provide refers to a file with the name ".test_rsa.key". In the copy of the book that I have, the leading period (.) is not there. I only mention this in case you wonder why the file name in your version of the code is slightly different than that of the file I mention above.
You are missing the file test_rsa.key
On Ubuntu you can use the following command to download on the path you specified "/home/burp/blackhatpy/.test_rsa.key":
wget https://raw.githubusercontent.com/paramiko/paramiko/main/demos/test_rsa.key -O /home/burp/blackhatpy/.test_rsa.key
Related
I've been trying to make a program that would allow me to remote into my computer. It works perfectly when both computers are connected to the same network, and I am able to access a sort of command line that I have coded.
I am very inexperienced with networks and I'm not entirely sure what sort of information is needed.
This is the code I used:
Server:
import sys
import socket
def create_socket():
try:
global host
global port
global s
host = ""
port = 9999
s = socket.socket()
except socket.error as msg:
print("SocketCreationError: " +str(msg))
def bind_socket():
try:
global host
global port
global s
print("binding the port " + str(port)+"...")
s.bind((host,port))
s.listen(5)
except socket.error as msg:
print("SocketBindingError: " + str(msg))
print("retrying...")
bind_socket()
def socket_accept():
conn,address = s.accept()
print("Connection established. \nIP:"+address[0]+"\nPort:"+str(address[1]))
print(str(conn.recv(1024), "utf-8"), end="")
send_command(conn)
conn.close()
#allows user to send command to client computer
def send_command(conn):
while True:
try:
cmd = input(">")
if cmd == 'exit':
conn.close()
s.close()
sys.exit()
if len(str.encode(cmd)) > 0:
conn.send(str.encode(cmd))
clientResponse = str(conn.recv(1024),"utf-8")
print(clientResponse, end="")
except Exception:
print("Something went wrong...")
def main():
create_socket()
bind_socket()
socket_accept()
main()
Client:
import socket
import os
import subprocess
#connect to socket and send cwd
s = socket.socket()
host = 'myIP'
port = 9999
s.connect((host, port))
s.send(str.encode(os.getcwd()))
#allows form of command line on host pc
while True:
try:
data = s.recv(1024)
outputStr = ""
if data.decode("utf-8") == 'dir':
dirList = os.listdir(os.getcwd())
for i in dirList:
print(i)
outputStr = outputStr + i + "\n"
elif data[:2].decode("utf-8") == 'cd':
dirTo = data[3:].decode("utf-8")
print(data[3:].decode("utf-8"))
os.chdir(os.getcwd() + "\\" + dirTo)
elif len(data) > 0:
cmd = subprocess.Popen(data.decode("utf-8"), shell=True,stdout=subprocess.PIPE,stdin=subprocess.PIPE, stderr=subprocess.PIPE)
outputByte = cmd.stdout.read() + cmd.stderr.read()
outputStr = str(outputByte, "utf-8")
print(outputStr)
cwd = os.getcwd()
s.send(str.encode(outputStr +"\n"+cwd))
#handle something going wrong and just allows to continue
except Exception:
cwd = os.getcwd()
s.send(str.encode("Something went wrong...\n"+ cwd))
I am using ipv4 addresses. I think it may have something to do with port forwarding on the server side, but again I am not sure?
Thank you for any answers in advance :)
You can't connect to your computer using a remote network because of port forwarding. If you dont know what that is, I recommend taking a look at the Wikipedia article on it: https://en.wikipedia.org/wiki/Port_forwarding
There are many different methods to perform Port Forwarding, the simplest of which is the UPnP/IGD (look it up), but if you're just interested in being able to Access your computer remotely, you could just use an SSH (Secure Shell Connection) to do just this (I think it Works on remote networks as well). If you're using Linux this should be pretty easy to set up, just look up how to do it. Good luck!
I am trying to build a simple server-client model to do the file transfer task. My server.py and client.py look like this:
<Server.py>
import socket
s = socket.socket()
host = socket.gethostname()
port = 1717
s.bind((host, port))
s.listen(1)
print(host)
print("Waiting for the client ...")
conn, addr = s.accept()
print(addr, "Connected!")
filename = "My file name"
file = open(filename, 'rb')
file_data = file.read(2048)
conn.send(file_data)
print("File has been sent to server.")
s.close()
<Client.py>
import socket
import time
time.sleep(3)
s = socket.socket()
host = "ubuntu"
port = 1717
s.connect((host, port))
print("Connected ....")
filename = "My file name"
file = open(filename, 'wb')
file_data = s.recv(2048)
file.write(file_data)
file.close()
print("File has been received.")
Also, I wrote a shell file to run the server and client, because I can only get no error if the server runs before the client, I wrote in my shell script something like this:
python3 ./some_path/server.py &
python3 ./some_path/client.py $n
Notice that I also added the time.sleep(3) at the beginning of my Client.py because I found the shell script command I wrote does not guarantee that server runs first. Now this problem is resolved, however, I am getting the 'Adress already in use' error because of s.bind() in the server.py every time I want to run the whole thing for the second time.
That's saying, If I open my Ubuntu, and run the shell script, it worked and everything is fine as expected. But when it's done and I want to run again, I would get the 'Adress already in use'.
So my questions are:
How to solve this, so that I test the functionalities without rebooting the whole computer.
Are there any more sophisticated way to make client.py always run after the server.py than my time.sleep() way?
Are there any more sophisticated ways to get the hostname instead of specifying in advance? As you can see from the client.py I basically set the host to "ubuntu" because that's what I get if I print the hostname from the server-side.
Thank you so much for reading these long questions...I just want to make things more clear...
Much appreciated it if you can answer any one of my questions or even give some suggestions.
By the way, I am testing all these on a ubuntu 14.04 machine.
Firstly you need to close the socket in the client as well.
Secondly you should call shutdown before closing the socket.
Please see this https://stackoverflow.com/a/598759/6625498
Try to reboot entirely the system.
It may means that the process still running.
How to solve this, so that I test the functionalities without rebooting the whole computer.
Please run this command on the shell script if you get the this message "Adress already in use"
sudo killall -9 python3
And then run your server and client.
Are there any more sophisticated way to make client.py always run after the server.py than my time.sleep() way
Please use this codes.
server.py
import socket
import threading
import socketserver
socketserver.TCPServer.allow_reuse_address = True
__all__ = ['server']
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
cur_thread = threading.current_thread()
requests = self.server.requests
if self.request not in requests:
requests[self.request] = {'client_id': cur_thread.ident,
'client_address': self.client_address[0],
'client_port': self.client_address[1]}
if callable(self.server.onConnected):
self.server.onConnected(self.request, self.server)
while True:
try:
buffer = self.request.recv(my_constant.MSG_MAX_SIZE)
if not buffer:
break
buffer = str(binascii.hexlify(buffer))
buffer = [buffer[i:i + 2] for i in range(2, len(buffer) - 1, 2)]
self.server.onData(buffer, self.server, self.request) # process receive function
except socket.error:
print(str(socket.error))
break
if callable(self.server.onDisconnected) and (self.request in requests):
self.server.onDisconnected(self.request, self.server)
self.request.close()
class server(socketserver.ThreadingTCPServer):
def __init__(self, host='', port=16838, *args, **kwargs):
socketserver.ThreadingTCPServer.__init__(self, (host, port), ThreadedTCPRequestHandler)
self.requests = {}
self.server_thread = threading.Thread(target=self.serve_forever)
self.server_thread.setDaemon(True)
self.server_thread.start()
self.onConnected = None
self.onDisconnected = None
self.onData = None
def stop(self):
self.quote_send_thread_stop = True
for request in list(self.requests):
self.shutdown_request(request)
if self.onDisconnected:
self.onDisconnected(request, self)
self.shutdown()
self.server_close()
def broadcast(self, data):
for request in list(self.requests):
try:
request.sendall(data)
except socket.error:
print(str(socket.error))
del self.requests[request]
def send(self, request, data):
try:
request.sendall(data)
except socket.error:
print(str(socket.error))
del self.requests[request]
def sendRaw(self, client_id, data):
pass
def disconnect(self, client_id):
for request in list(self.requests):
if client_id == self.requests[request]['client_id']:
self.shutdown_request(request)
if self.onDisconnected:
self.onDisconnected(request, self)
else:
del self.requests[request]
def onConnected(request, server):
try:
print('[onConnected] client_address: ' + str(server.requests[request]))
except Exception as e:
print(str(e))
def onDisconnected(request, server):
try:
print('[onDisconnected] client_address: ' + str(server.requests[request]))
del server.requests[request]
except Exception as e:
print(str(e))
def onData(request, server):
#define your process message
pass
main.py
his_server = server.server(sever_host, sever_port)
his_server.onConnected = server.onConnected
his_server.onDisconnected = server.onDisconnected
his_server.onData = server.onData
client.py
import socket
import time
from common.constant import *
from threading import Thread
import binascii
from .packet import *
import threading
def recv_msg(sock):
while True:
try:
res = sock.recv(buf_size)
if not res:
continue
buffer = str(binascii.hexlify(res))
buffer = [buffer[i:i + 2] for i in range(2, len(buffer) - 1, 2)]
#packet parsing, you maybe change this part.
packet_parsing(buffer)
time.sleep(0.100)
except socket.error:
print(str(socket.error))
break
class history_thread(threading.Thread):
def __init__(self, threadID, name, delay, server, port):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.delay = delay
self.server = server
self.port = port
self.sock = None
def run(self):
print("Starting " + self.name)
while True:
try:
self.sock = socket.socket()
self.sock.connect((self.server, self.port))
tc = Thread(target=recv_msg, args=(self.sock,))
tc.start()
threads = []
threads.append(tc)
for pip in threads:
pip.join()
self.sock.close()
self.sock = None
except socket.error:
print(str(socket.error))
if self.sock is not None:
self.sock.close()
self.sock = None
time.sleep(self.delay)
def send(self, data):
if self.sock is None:
return -1
try:
self.sock.sendall(data)
except:
print(str(socket.error))
So i've recently started testing out sockets and i have managed to create a server and client, which are both working together when i run them on the same pc. However, when i put in the server on a diffrent computer it gives me the following error: ""TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond""
Here is my server:
import socket
import pyautogui
import os
computerIP = socket.gethostbyname(socket.gethostname())
def Main():
host = computerIP
port = 5000
value = 0
mySocket = socket.socket()
mySocket.bind((host,port))
mySocket.listen(1)
conn, addr = mySocket.accept()
print ("Connection from: " + str(addr))
while True:
data = conn.recv(1024).decode()
if not data:
break
elif data == "shift":
pyautogui.keyDown("shift")
elif data == "relshift":
pyautogui.keyUp("shift")
elif data == "logout":
os.popen("shutdown -l")
elif data == "click":
pyautogui.click()
pyautogui.click()
print ("from connected user: " + str(data))
data = str(data).upper()
print ("sending: " + str(data))
conn.send(data.encode())
conn.close()
if __name__ == '__main__':
Main()
My client:
import socket
def Main():
host = #same ip as server
port = 5000
mySocket = socket.socket()
mySocket.connect((host,port))
message = input(" -> ")
while message != 'q':
mySocket.send(message.encode())
data = mySocket.recv(1024).decode()
print ('Received from server: ' + data)
message = input(" -> ")
mySocket.close()
if __name__ == '__main__':
Main()
OS: Windows 8.1
Python verion: 3.4
I tried looking this up on the internet but since i'm pretty new to python i didn't understand much.
Tell me if there is anything i need to clearify.
Looks like the port is blocked due to some firewall.
Use socket.connect_ex() instead of socket.connect(). If the connection succeeds it would return 0, otherwise the value of the errno variable will help you debug why the connection failed.
Prior to the connection also use socket.settimeout() so that the connection times out in the given no. of seconds.
So I decided to read more about networks in Python, and in the book I'm reading, there's this piece of code that creates a SSH server using paramiko (a third party SSH module) and socket.
The problem I'm having is that whenever I input a server address, it says "Address already in use". In addition, I'm already using sock.setsockopt(sock.SOL_SOCKET, sock.SO_REUSEADDR, 1) so the address can be reused, but the problem still persists.
Here's the full code:
import socket
import paramiko
import threading
import sys
import traceback
# using the key from the Paramiko demo files
host_key = paramiko.RSAKey(filename='test_rsa.key')
class Server (paramiko.ServerInterface):
def __init__(self):
self.event = threading.Event()
def check_channel_request(self, kind, chanid):
if kind=='session':
return paramiko.OPEN_SUCCEEDED
return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
def check_auth_password(self,user, password):
if (usernae == 'matheus') and (password == 'password'):
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED
server = sys.argv[1]
ssh_port = int(sys.argv[2])
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((server, ssh_port))
sock.listen(100) # Wow so many connections
print ("[+] Listening for connection ...")
client, addr = sock.accept()
except Exception, e:
print("[-] Listen failed: " + str(e))
traceback.print_stack()
sys.exit(1)
print("[+] Got a connection!") # runs as except exits
try:
bhSession = paramiko.Transport(client)
bhSession.add_server_key(host_key)
server = Server()
try:
bhSession.start_server(server=server)
except paramiko.SSHException, x:
print("[-] SSH negotiation failed.")
chan = bhSession.accept(20)
print("[+] Authenticated!")
print(chan.recv(1024))
chan.send("Welcome to bh_ssh")
while True:
try:
command = raw_input("Enter command: ").strip('\n')
if command != 'exit':
chan.send(command)
print(chan.recv(1024)+'\n')
else:
chan.send('exit')
print("exiting")
bhSession.close()
raise Exception("exit")
except KeyboardInterrupt:
bhSession.close()
except Exception, e:
print("[-] Caught exception: " + str(e))
try:
bhSession.close()
except:
pass
sys.exit(1)
The addresses I've tried are:
192.168.1.107 (current device address)
0.0.0.0
0.0.0.1
127.0.0.1 (localhost)
The port was always 22.
Peace!
Try using the SO_REUSEADDR socket option before binding the socket.
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
SO_REUSEPORT is what most people would expect SO_REUSEADDR to be.
Basically, SO_REUSEPORT allows you to bind an arbitrary number of sockets to exactly the same source address and port as long as all prior bound sockets also had SO_REUSEPORT set before they were bound.
I have a homework assignment which involves implementing a proxy cache server in Python. The idea is to write the web pages I access to temporary files on my local machine and then access them as requests come in if they are stored. Right now the code looks like this:
from socket import *
import sys
def main():
#Create a server socket, bind it to a port and start listening
tcpSerSock = socket(AF_INET, SOCK_STREAM) #Initializing socket
tcpSerSock.bind(("", 8030)) #Binding socket to port
tcpSerSock.listen(5) #Listening for page requests
while True:
#Start receiving data from the client
print 'Ready to serve...'
tcpCliSock, addr = tcpSerSock.accept()
print 'Received a connection from:', addr
message = tcpCliSock.recv(1024)
print message
#Extract the filename from the given message
print message.split()[1]
filename = message.split()[1].partition("/")[2]
print filename
fileExist = "false"
filetouse = "/" + filename
print filetouse
try: #Check whether the file exists in the cache
f = open(filetouse[1:], "r")
outputdata = f.readlines()
fileExist = "true"
#ProxyServer finds a cache hit and generates a response message
tcpCliSock.send("HTTP/1.0 200 OK\r\n")
tcpCliSock.send("Content-Type:text/html\r\n")
for data in outputdata:
tcpCliSock.send(data)
print 'Read from cache'
except IOError: #Error handling for file not found in cache
if fileExist == "false":
c = socket(AF_INET, SOCK_STREAM) #Create a socket on the proxyserver
hostn = filename.replace("www.","",1)
print hostn
try:
c.connect((hostn, 80)) #https://docs.python.org/2/library/socket.html
# Create a temporary file on this socket and ask port 80 for
# the file requested by the client
fileobj = c.makefile('r', 0)
fileobj.write("GET " + "http://" + filename + "HTTP/1.0\r\n")
# Read the response into buffer
buffr = fileobj.readlines()
# Create a new file in the cache for the requested file.
# Also send the response in the buffer to client socket and the
# corresponding file in the cache
tmpFile = open(filename,"wb")
for data in buffr:
tmpFile.write(data)
tcpCliSock.send(data)
except:
print "Illegal request"
else: #File not found
print "404: File Not Found"
tcpCliSock.close() #Close the client and the server sockets
main()
To test my code, I run the proxy cache on my localhost and set my browser proxy settings accordingly like so
However, when I run this code and try to access google with Chrome, I'm greeting with an error page saying err_empty_response.
Stepping through the code with the debugger made me realizing it's failing on this line
c.connect((hostn, 80))
and I have no idea why. Any help would be greatly appreciated.
P.S. I'm testing this with Google Chrome, Python 2.7, and Windows 10
You cannot use a name on connect. Connect expects an IP address to connect to.
You can get the socket information you need to build the connection using getaddrinfo(). In my pure-python-whois package I used the following code to create a connection:
def _openconn(self, server, timeout, port=None):
port = port if port else 'nicname'
try:
for srv in socket.getaddrinfo(server, port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_ADDRCONFIG):
af, socktype, proto, _, sa = srv
try:
c = socket.socket(af, socktype, proto)
except socket.error:
c = None
continue
try:
if self.source_addr:
c.bind(self.source_addr)
c.settimeout(timeout)
c.connect(sa)
except socket.error:
c.close()
c = None
continue
break
except socket.gaierror:
return False
return c
Note that this isn't great code because the loop is actually there for nothing instead of using the different alternatives. You should only break the loop once you have established a connection. However, this should work as an illustration for using getaddrinfo()
EDIT:
You are also not cleaning your hostname correctly. I get /www.example.com/ when I try accessing http://www.example.com/ which obviously won't resolve. I'd suggest that you use a regular expression to get the file name for your cache.