Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- exercice = "TP 1"
- title = "Simulation d'encapsulation"
- author = "Équipe : ..."
- date = "2019-01-12"
- description = "Simulation d'encapsulation des protocoles réseau en Python, avec journalisation"
- def info():
- print("---------------------")
- print(exercice, ":", title)
- print(author)
- print(date)
- print("---------------------")
- print(description)
- print("---------------------")
- import abc # Pour des classes abstraites
- import logging # Pour journalisation
- import binascii # Pour calculation de CRC
- import re # Pour recherche dans listes
- #les diffents types d'entetes
- class Header:
- def Header(self):
- pass
- class Ethernet(Header):
- def __init__(self, macsource, macdestination):
- self.macsource=macsource
- self.macdestination=macdestination
- def __str__(self):
- # return "Ethernet " + str(self.Header())
- return "Ethernet {} -> {}".format(self.macsource, self.macdestination)
- def Header(self):
- return [self.macsource,self.macdestination]
- class IP(Ethernet):
- def __init__(self,macsource, macdestination, IPsource, IPdestination):
- Ethernet.__init__(self,macsource,macdestination)
- self.IPsource=IPsource
- self.IPdestination=IPdestination
- def __str__(self):
- # return "IP " + str(self.Header())
- return "IP {} ({}) -> {} ({})".format(self.IPsource, self.macsource, self.IPdestination, self.macdestination)
- def Header(self):
- # Version originale ne va pas marcher ! https://stackoverflow.com/a/7507308/6123418
- # return Ethernet.Header(self).extend([self.IPsource,self.IPdestination])
- # Alors :
- return [self.IPsource,self.IPdestination] + Ethernet.Header(self)
- class TCP(IP):
- def __init__(self, macsource, macdestination, IPsource, IPdestination, portsource, portdestination):
- IP.__init__(self, macsource, macdestination, IPsource, IPdestination)
- self.portsource = portsource
- self.portdestination = portdestination
- def __str__(self):
- # return "TCP " + str(self.Header())
- return "TCP {}:{} ({}) -> {}:{} ({})".format(self.IPsource, self.portsource, self.macsource, self.IPdestination, self.portdestination, self.macdestination)
- def Header(self):
- return [self.portsource, self.portdestination] + IP.Header(self)
- #le paquet
- class Paquet:
- def __init__(self, header, data, checksum):
- self.header = header #strategy pattern
- self.data = data
- self.checksum = checksum #strategy pattern
- def Paquet(self):
- return [self.header.Header(),self.data,self.checksum.checksumAlgorithm(self.header.Header(),self.data)]
- #les differents types de checksum algorithms
- class Checksum(metaclass=abc.ABCMeta): # Question 5 : Checksum strategie
- @abc.abstractmethod
- def checksumAlgorithm(self, entete, donnees):
- pass
- class CRC(Checksum):
- def checksumAlgorithm(self, entete, donnees):
- # Algorithm de crc32
- crc_source = "" # Préparer une variable
- for token in entete: # Y ajouter toutes les entêtes
- crc_source = crc_source + str(token)
- crc_source = crc_source + str(donnees) # Ajouter les données
- # Convertir string en bytearray et en calculer la CRC :
- # crc_calculated = binascii.crc32(bytearray(crc_source, 'utf-8'))
- return binascii.crc32(bytearray(crc_source, 'utf-8'))
- class Paritybit(Checksum):
- def checksumAlgorithm(self, entete, donnees):
- #algorithm de bit de parite
- crc_source = "" # Préparer une variable
- for token in entete: # Y ajouter toutes les entêtes
- crc_source = crc_source + str(token)
- crc_source = crc_source + str(donnees) # Ajouter les données
- # Calculer parité
- x = int(0)
- for i in range(0, len(crc_source)):
- x ^= ord(crc_source[i])
- shiftamount = 1
- while x >> shiftamount:
- x ^= x >> shiftamount
- shiftamount <<= 1
- return x & 1
- # Calculer parité d'un int
- # https://stackoverflow.com/a/49934659/6123418
- def parity_of_int(x):
- shiftamount = 1
- while x >> shiftamount:
- x ^= x >> shiftamount
- shiftamount <<= 1
- return x & 1
- # Calculer parité d'une ligne de texte
- def parity(texte):
- x = int(0)
- for i in range(0, len(texte)):
- x ^= ord(texte[i])
- shiftamount = 1
- while x >> shiftamount:
- x ^= x >> shiftamount
- shiftamount <<= 1
- return x & 1
- # La classe Event (événement) pour le patron observateur
- class Event(object):
- pass
- # Calculer CRC
- def crc(texte):
- return binascii.crc32(bytearray(texte, 'utf-8'))
- #la class firewall observable
- class Firewall(object):
- paquets = []
- blacklist = []
- observateurs = []
- #les donnees de la classe observable
- @classmethod
- def ajouter(cls, paquet):
- #implementation
- cls.paquets.append(paquet)
- @classmethod
- def supprimer(cls, index = 0):
- cls.paquets.pop(index)
- @classmethod
- def verifier(cls):
- # Implementation
- if cls.paquets: # Seulement si la ligne d'attente n'est pas vide
- blocked = False
- for address in cls.blacklist:
- # Compiler un pattern regex selon les adresses dans blacklist
- mask = re.compile(address)
- # L'adresse IP source : cls.paquets[0].Paquet()[0][2]
- if re.match(mask, cls.paquets[0].Paquet()[0][2]):
- blocked = True
- # Revérifier CRC ou Paritybit : cls.paquets[0].Paquet()[2]
- crc_source = "" # Préparer une variable
- for token in cls.paquets[0].Paquet()[0]: # Y ajouter toutes les entêtes
- crc_source += str(token)
- crc_source += str(cls.paquets[0].Paquet()[1]) # Ajouter les données
- if len(str(cls.paquets[0].Paquet()[2])) == 1:
- # Vérifier Paritybit
- if cls.paquets[0].Paquet()[2] != parity(crc_source):
- print("Checking parity: {}".format(crc_source))
- blocked = True
- else:
- # Vérifier plutôt CRC
- if cls.paquets[0].Paquet()[2] != crc(crc_source):
- print("Checking CRC: {}".format(crc_source))
- blocked = True
- if blocked:
- cls.dispatch("Block", cls.paquets[0])
- else:
- cls.dispatch("Pass", cls.paquets[0])
- cls.supprimer() # Finalement, supprimer le paquet de la ligne d'attente
- @classmethod
- def bloquer(cls, IPsource):
- cls.blacklist.append(IPsource)
- @classmethod
- def register(cls, who, callback = None):
- if callback == None:
- callback = getattr(who, 'update')
- cls.observateurs.append(callback)
- @classmethod
- def dispatch(cls, status, paquet):
- for callback in cls.observateurs:
- callback(status, paquet)
- # La classe réseau observatrice
- class reseau:
- # les données de la classe réseau (observateur)
- def __init__(self):
- self.paquets = []
- Firewall.register(self, self.update)
- def update(self, status, paquet):
- if status == "Pass":
- self.paquets.append(paquet)
- logging.debug("Paquet passed (IPsrc {}, IPdst {})".format(paquet.Paquet()[0][2], paquet.Paquet()[0][3]))
- print("Passed (IPsrc {}, IPdst {}, checksum {})".format(paquet.Paquet()[0][2], paquet.Paquet()[0][3], paquet.Paquet()[2]))
- #la classe logfile observatrice
- class logfile:
- # les donnees de la classe logfile (observateur)
- def __init__(self):
- logging.basicConfig(filename='tp1.log',level=logging.DEBUG, format='%(asctime)s [%(levelname)s] %(message)s')
- logging.debug("----- >8 -----") # Ça sert juste à délimiter les tests
- Firewall.register(self, self.update)
- def update(self, status, paquet):
- if status == "Block":
- logging.warning("Paquet blocked (IPsrc {}, IPdst {})".format(paquet.Paquet()[0][2], paquet.Paquet()[0][3]))
- print("Blocked (IP src {}, IPdst {}, checksum {})".format(paquet.Paquet()[0][2], paquet.Paquet()[0][3], paquet.Paquet()[2]))
- # =========================================================================
- # Testing ground
- # =========================================================================
- info()
- # Ici on teste les ajouts de plusieurs paquets au Firewall. Format:
- # Firewall.ajouter(Paquet)
- # Le Paquet ici est une liste de 3 elements : entête, données et checksum.
- # L'entête peut être de niveau Ethernet, IP ou (normallement) TCP. Pour TCP :
- # TCP(MAC_src, MAC_dst, IP_source, IP_destination, Port_src, Port_dst)
- # Données = une ligne de texte
- # Checksum spécifie un de deux algorithmes de calcule de checksum : CRC() ou Paritybit()
- print()
- print("Test: appending paquets to firewall")
- for i in range(1, 6): # Générer 5 paquets avec differentes données, qui seront acceptés
- Firewall.ajouter(Paquet(TCP("AAAA", "BBBB", "192.168.1.{}".format(i), "192.168.1.20{}".format(i), "21", "2021"), "Test_{}".format(i), CRC() ))
- for i in range(1, 3): # Générer 2 autres paquets, qui seront refusés par le Firewall
- Firewall.ajouter(Paquet(TCP("AAAA", "BBBB", "192.155.23.{}".format(i), "192.168.1.200", "21", "2021"), "Test_{}".format(i), CRC() ))
- for t in Firewall.paquets:
- print(t.Paquet())
- print()
- print("Test: registering net and log as observers for Firewall")
- net = reseau()
- log = logfile()
- print("...")
- print()
- print("Test: setting up firewall blacklist")
- Firewall.bloquer("192.168.*.3") # Ajouter une adresse dans blacklist du Firewall
- Firewall.bloquer("192.155.23.*") # L'adresse à bloquer selon l'énoncé
- for mask in Firewall.blacklist:
- print("Blacklisted: {}".format(mask))
- print()
- print("Test: verifying paquets by firewall")
- while Firewall.paquets: # Processer tous les paquets dans la liste d'attente
- # print(Firewall.paquets[0].Paquet()) # Pour debugging
- Firewall.verifier() # Vérifier !
- print()
- print("Test: verifyting the log file")
- print("Le fichier tp1.log devrait contenir une ligne [DEBUG] sur chaque paquet accepté,")
- print("aussi bien qu'une ligne [WARNING] pour chaque paquet bloqué.")
Advertisement
Add Comment
Please, Sign In to add comment