Finux Geschrieben 12. September 2019 Teilen Geschrieben 12. September 2019 Hallo, zunächst kleine Anmerkung: Ich bin Anfänger, mit Netzwerkkommunikation nicht gut vertraut und aktuell noch in der Ausbildung/Umschulung FiAe. Bitte werdet nicht ungemütlich... Ich bin sehr am verzweifeln. Meine aktuelle Aufgabe ist es Server- und Clientsockets in Python3 zu programmieren. Die Voraussetzung, die die aufgebaute Kommunikation erfüllen muss ist folgende: 1. Es sollen mehrere Clients zeitgleich von der server.py bedient werden können. 2. Es müssen Funktionsaufrufe von der client.py auf der server.py möglich gemacht werden 3. Die ganze Kommunikation muss via SSL verschlüsselt sein (hierzu habe ich bereits ein eigenes Zertifikat + Schlüssel von OpenSSL) Einzelne Pythonscripts mit den unterschiedlichen Funktionen habe ich bereits, und sie funktionieren wunderbar (also [1; threading], [2; xmlrpc-multicall], [3; SSL]). Ich schaffe es einfach nicht diese 3 Funktionalitäten übereinander in ein Script zu bekommen. Vielleicht gehe ich das aber auch falsch an, vielleicht ist mein Code nicht aufgeräumt, bzw. so unübersichtlich durch unterschiedliche Namensgebung etc., dass ich einfach nicht mehr durchblicke? Es ist eben leider zusammenkopiert, weil ich zunächst die Funktionalität der einzelnen funktionellen Ansprüche sicher stellen wollte. (Vielleicht ist die Herangehensweise aber schlecht, und man sollte sofort seinen "eigenen Code" also Namensgebung etc. daraus machen?). Mir fehlt vieles an Grundwissen, aber ich bin nicht bereit "aufzugeben"! ? Recherchen haben mir leider keinen Aufschluss gebracht, und ich weiß einfach nicht mehr weiter. Zunächst habe ich versucht das xmlrpc-skript mit dem ssl zu vereinen. Fakt ist: xmlrpc kann offiziell mit openssl genutzt werden. Aber wie ich diese 2 Funktionalitäten vereint bekomme- dazu finde ich nichts im Netz. Hier meine bisher noch hilfreichsten Quellen: Python docs zu xmlrpc (client) Python docs zu SSL Hintergrund ist, dass die Clientsockets von einer Homepage geöffnet werden. Hier sollen Funktionsaufrufe für den Nutzer möglich gemacht werden (daher meine Idee mit dem xmlrpc Multicall). Vielleicht sehe ich den Wald vor lauter Baum nicht mehr, aber ich weiß weder wo ich "anfangen" soll, noch ob ich überhaupt auf dem richtigen Weg bin und mich nicht gerade ins Jenseits schleppe. Vielleicht kann jemand helfen. Ich bin wirklich für jeden Tipp dankbar. Greez, Finux Was ich bisher zusammentragen oder programmieren konnte sind hier die Einzelscripts: [1; threading] #################################################################### ################# MULTITHREADING EINFACH SCK ################### ############# + --------- server.py --------- + ############## #################################################################### import socket import argparse import threading parser = argparse.ArgumentParser(description="This is the server for the multithreaded socket demo!") parser.add_argument('--host', metavar='host', type=str, nargs='?', default='xx.xxx.xx.xx') # host ip parser.add_argument('--port', metavar='port', type=int, nargs='?', default=xxxx) # port args = parser.parse_args() print("Running the server on: {} and port: {}".format(args.host, args.port)) sck = socket.socket() #TODO: IPv4 & IPv6 Erkennung sck.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: sck.bind((args.host, args.port)) sck.listen(5) except Exception as e: raise SystemExit("We could not bind the server on host: {} to port: {}, because: {}".format(args.host, args.port, e)) def on_new_client(client, connection): ip = connection[0] port = connection[1] print("Client: {} \n Connection: {}".format(client, connection)) print("The new connection was made from IP: {}, and port: {}!".format(ip, port)) while True: msg = client.recv(1024) if msg.decode() == 'exit': break print("The client said: {}".format(msg.decode())) reply = "You told me: {}".format(msg.decode()) client.sendall(reply.encode('utf-8')) #TODO: .send oder .sendall? (Kontrollmöglichkeit der gesendeten Daten) print("The client from ip: {}, and port: {}, has gracefully diconnected!".format(ip, port)) client.close() while True: try: client, ip = sck.accept() threading._start_new_thread(on_new_client, (client, ip)) except KeyboardInterrupt: print("Gracefully shutting down the server!") except Exception as e: print("Well I did not anticipate this: {}".format(e)) sck.close() # ========================================================================== # # ============================ B R E A K =================================== # # ========================================================================== # #################################################################### #################### MULTITHREADING EINFACH SCK #################### ############### + --------- client.py --------- + ################ #################################################################### import socket import argparse parser = argparse.ArgumentParser(description="This is the client for the multi threaded socket server!") parser.add_argument('--host', metavar='host', type=str, nargs='?', default='xx.xxx.x.xxx') # host ip parser.add_argument('--port', metavar='port', type=int, nargs='?', default=xxxx) # port args = parser.parse_args() with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sck: try: print("TRYING to connect to server: {} on port: {}".format(args.host, args.port)) sck.connect((args.host, args.port)) print("Connected to server: {} on port: {}".format(args.host, args.port)) except Exception as e: raise SystemExit("We have failed to connect to host: {} on port: {}, because: {}".format(args.host, args.port, e)) while True: msg = input("What do we want to send to the server?: ") sck.sendall(msg.encode('utf-8')) if msg == 'exit': print("Client is saying goodbye!") break data = sck.recv(1024) print("The server's response was: {}".format(data.decode())) [2; xmlrpc-multicall] #=============================# #=========== CSK Funktionsaufrufe mehrfach ===========# #=============== server.py =================# #===================# from xmlrpc.server import SimpleXMLRPCServer as Server def fak(n): """ Berechnet die Fakultaet der ganzen Zahl n. """ erg = 1 for i in range(2, n+1): erg *= i print(erg) return erg def quad(n): """ Berechnet das Quadrat der Zahl n. """ print(n*n) return n*n def name(): """ Standort: Nirgendwo """ standort = "Irgendwo im Nirgendwo" return standort srv = Server(("xx.xxx.x.xxx", xxxx)) # ip, port srv.register_function(fak) srv.register_function(quad) srv.register_function(name) srv.register_multicall_functions() # ermöglicht mehrfach Funktionsaufruf, Funktionen müssen mit .register_function(funktionsname) registriert sein # srv.register_introspection_functions() # SICHERHEITSLÜCKE! ermöglicht .listMethods, .methodHelp, .methodSignature srv.serve_forever() # ========================================================================== # # ============================ B R E A K =================================== # # ========================================================================== # #=============================# #=========== CSK Funktionsaufrufe mehrfach ===========# #=============== client.py =================# #===================# from xmlrpc.client import ServerProxy, MultiCall cli = ServerProxy("http://xx.xxx.x.xxx:xxxx") # ip, port als ein string! mc = MultiCall(cli) # mc.system.listMethods() # SICHERHEITSLÜCKE! listet alle Funktionen auf # mc.system.methodHelp('name') # SICHERHEITSLÜCKE! gibt Doc-string der jew.Funktion zurück # mc.system.methodSignature('fak') # SICHERHEITSLÜCKE! listet alle Schnittstellen der Funktion auf for i in range(10): mc.fak(i) mc.quad(i) mc.name() for ergebnis in mc(): print(ergebnis) [3; SSL] # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # ~~~~~~~~~~~~~~~~~ SSL Verschlüsselung ~~~~~~~~~~~~~~~ # # ~~~~~~~~~~~~~~~~~~ server.py ~~~~~~~~~~~~~~~~~~# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # """ To make ur own SSL-certificate on linux type: openssl req -new -days 999 -newkey rsa:4096bits -sha512 -x509 -nodes -out server.crt -keyout server.key Note: CN (Common Name) has to be the server adress (e.g. IP) Don't forget to change rights for server.crt and server.key (chmod -v 777 server.crt) Source: https://wiki.manitu.de/index.php/Server:Selbst-signiertes_SSL-Zertifikat_erstellen/erzeugen """ import socket, ssl def deal_with_client(connstream): data = connstream.recv(1024) while data: if not data: connstream.close() break data = connstream.recv(1024) context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) context.load_cert_chain(certfile="/home/PFADNAME/server.crt", keyfile="/home/PFADNAME/server.key") bindsocket = socket.socket() bindsocket.bind(('127.0.0.1', xxxx)) # zu internen zwecken, da nur 1x linux auf vm vorhanden, port bindsocket.listen(5) while True: newsocket, fromaddr = bindsocket.accept() connstream = context.wrap_socket(newsocket, server_side=True) try: deal_with_client(connstream) finally: connstream.shutdown(socket.SHUT_RDWR) connstream.close() # ========================================================================== # # ============================ B R E A K =================================== # # ========================================================================== # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # ~~~~~~~~~~~~~~~~~ SSL Verschlüsselung ~~~~~~~~~~~~~~~ # # ~~~~~~~~~~~~~~~~~~ client.py ~~~~~~~~~~~~~~~~~~# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # try: import socket, ssl, pprint except ImportError: pass context = ssl.SSLContext() context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = True context.load_verify_locations("/home/PFADNAME/server.crt") conn = context.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), server_hostname="127.0.0.1") conn.connect(('127.0.0.1', xxxx)) # port cert = conn.getpeercert() pprint.pprint(cert) Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Finux Geschrieben 13. September 2019 Autor Teilen Geschrieben 13. September 2019 Ich hab meinen Fehler gefunden Habe in meinem Versuch Threading mit ssl zu verknüpfen nicht bedacht, dass ich die wrap-socket variable auch an die folgenden Funktionen übergeben muss. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.