Zum Inhalt springen

PYthon3 Socket Multicall+SSL


Finux

Empfohlene Beiträge

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)

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...