Eklablog Tous les blogs
Editer l'article Suivre ce blog Administration + Créer mon blog
MENU

Blog traitant d'informatique, de programmation, de python, de golang, de linux...

Publicité

Créez un tampon DNS avec votre fichier /etc/hosts en python

1/ Le fichier hosts (/etc/hosts)

Ce fichier hosts devra donc être mis à jour assez régulièrement (globalement, je lance une mise à jour par semaine, parfois plus, parfois moins), ou au moins à chaque fois que le navigateur  affiche un message comme quoi il ne trouve pas le site en question.

Pour faciliter un peu les choses, j'ai légèrement modifié le fichier hosts, en lui ajoutant 2 lignes :

###BEGIN myLocal DNS Server

 et

###END myLocal DNS Server

qui me serviront de repères pour la section à modifier / mettre à jour. Tout ce qui se trouve avant la ligne ###BEGIN... sert à définir le localhost, l'adresse de votre machine sur le réseau local, ainsi que tous les sites que vous voulez filtrer en les redirigeant vers 127.0.0.1 (ou autre n° d'IP si besoin). Tout ce qui se trouve après ###END... sert à définir les adresses utiles en IPV6. J'ai laissé cette section IPV6 comme à l'origine, je ne l'utilise pas. Enfin, tout ce qui se trouve entre les lignes ###BEGIN... et ###END... contient la partie 'tampon DNS' (myLocal DNS Server), la liste des IP et URL qui nous intéresse.

Attention, pour diverses raisons liées au script python, on ne devra plus utiliser le caractère # pour mettre un commentaire ailleurs que dans la section IPV6 ! L'effet en serait qu'une ligne commençant par # ne serait pas recopiée dans la liste finale, et serait donc purement oubliée et supprimée du fichier hosts après mise à jour. Pour le cas ou un commentaire serait placé dans la section myLocal DNS en fin de ligne comme ceci :

172.217.18.202 youtube.googleapis.com # Mon commentaire ici

--> toute la partie ' # Mon commentaire ici' disparaîtrait simplement de la version mise à jour.

 

Fichier hosts type :

  1 127.0.0.1 localhost
  2 127.0.0.1 tawr6o.vkcache.com
  3 127.0.0.1 todqjw.vkcache.com
  4 127.0.0.1 www.meilleursoldes.com
  5 127.0.0.1 M_adam-desktop
  6 127.0.0.1 M_This
  7 ###BEGIN myLocal DNS Server
  8 216.58.206.13 accounts.google.com
  9 194.187.168.100 www.qwant.com
 10 212.82.100.150 www.yahoo.fr
 11 ###END myLocal DNS Server
 12 # The following lines are desirable for IPv6 capable hosts
 13 # ::1 ip6-localhost ip6-loopback
 14 # fe00::0 ip6-localnet
 15 # ff00::0 ip6-mcastprefix
 16 # ff02::1 ip6-allnodes
 17 # ff02::2 ip6-allrouters

 

 

2/ Le fichier python pyHosts.py

Ce fichier python contient le script permettant de mettre à jour le fichier hosts. Pour que ce script fonctionne, il faut d'abord installer la librairie python3-dnspython qui permettra au programme d'aller interroger un vrai serveur DNS pour la mise à jour.

Dans un premier temps, ce script vérifie si il existe un fichier nommé 'history.json' dans le répertoire courant. Pour plus de détails, voir directement les commentaires explicatifs dans le script à partir de la ligne 20.

Dans un deuxième temps, pyHosts.py va alors regarder si il existe un fichier tcpdump.log (Voir les détails dans les commentaires du script à partir de la ligne 27).

Enfin, le script va charger le fichier hosts actuel (voir commentaires ligne 13 dans le code) puis procéder à la mise à jour de l'ensemble des DNS de ce fichier, en y ajoutant si nécessaires les nouvelles URLs provenant de l'historique du navigateur Brave d'un côté, et de la surveillance effectuée au préalable par tcpdump de l'autre. Vous pouvez jetez un oeil au code ci-dessous. Le zip de ce script est téléchargeable directement ici. Dans une précédente version de cette article, j'ai eu quelques soucis de nommage de cette archive. Je n'ai pas bien compris ce qui s'est passé mais le problème est résolu. Ce zip contient un répertoire /pyHosts/ qui contient le fichier pyHosts.py. Attention, ce script n'a été testé que sous python3.6 ! Je ne peux pas garantir son bon fonctionnement sous une autre version pour le moment. Pour le lancer, placez-vous en console dans le répertoire ../pyHosts, puis lancez tout simplement la commande :

 you@yourComputer:~/pyHosts$ python3 pyHosts.py

 

Script pyHosts.py :

    1 #!/usr/bin/env python3
    2 # -*- coding: utf-8 -*-
    3 # Version 0.2 du 24/05/2019
    4 
    5 
    6 ####
    7 #    NB : Ce script est prévu pour fonctionner sous Linux essentiellement (mais doit être adaptable
    8 #    assez facilement pour d'autres OS...)
    9 #
   10 #    Pré-requis : installation de python3-dnspython (sudo apt-get install python3-dnspython sur
   11 #    debian et dérivées)
   12 #
   13 #    Ce script permet de mettre à jour toutes les entrées présentes dans le fichier hosts du
   14 #    répertoire .../pyHosts
   15 #    Attention, ce fichier est une copie du fichier /etc/hosts réellement utilisé par le système.
   16 #    Une fois la mise à jour effectuée, il faudra remplacer manuellement le fichier /etc/hosts
   17 #    par le fichier .../pyHosts/hosts, à moins qu'un lien symbolique de .../pyHosts/hosts vers
   18 #    /etc/hosts n'ai été créé avec les droits d'écriture qui vont bien...
   19 #
   20 #    Ce script permettra aussi l'ajout de l'historique de navigation du navigateur Brave au
   21 #    fichier hosts. Cet historique est obtenu avec l'extension 'History Export' :
   22 #    --> https://chrome.google.com/webstore/detail/history-export/lpmoaclacdaofhlijejogfldmgkdlglj
   23 #    Cette extension permet de sauver l'historique dans un fichier history.json. Il faut sauver ce
   24 #    fichier dans le répertoire .../pyHosts
   25 #    A la fin du script, ce fichier history.json sera effacé.
   26 #
   27 #    pyHosts.py peut aussi ajouter les entrées des connexions vues par tcpdump. Au préalable, avant
   28 #    de lancer le script pyHosts.py, il faudra démarrer le process tcpdump dans un terminal, à
   29 #    partir du répertoire .../pyHosts 
   31 #                        --> sudo tcpdump -tq tcp > tcpdump.log
   32 #    Cela produira le fichier .../pyHosts/tcpdump.log, qui mémorisera toutes les connexions de
   33 #    votre navigation internet tant que vous n'arrêterez pas ce process. Quand vous déciderez de
   34 #    l'arrêter, vous pourrez alors mettre à jour le fichier hosts en lançant le script
   35 #    .../pyHosts/pyHosts.py. Attention, pour lancer le script pyHosts.py, tcpdump doit
   36 #    impérativement être arrêté ! A la fin du script, le fichier tcpdum.log sera effacé.
   37 #
   38 #    NB : Ce script a été testé sous python3.6.
   39 ####
   40 
   41 
   42 
   43 
   44 import os
   45 import time
   46 import dns.resolver
   47 
   48 
   49 
   50 def removeRNFromListe(listName):
   51     ''' Permet de supprimer les \r\n des fins de lignes avant ajout à la stringlist '''
   52     newList = []
   53     for oneLine in listName:
   54         if oneLine.endswith("\r\n"):
   55             oneLine = oneLine[0:(len(oneLine)-2)]
   56         if oneLine.endswith("\n"):
   57             oneLine = oneLine[0:(len(oneLine)-1)]
   58         if len(oneLine) >0:
   59             newList.append(oneLine)
   60     return newList
   61 
   62 
   63 def readFileLines(filename):
   64     ''' Ouverture du fichier filename et stockage des lignes lues dans newList'''
   65     if os.path.exists(filename):
   66         myFile = open(filename, 'r')
   67         oneStringList = myFile.readlines()
   68         myFile.close()
   69         newList = removeRNFromListe(oneStringList)
   70         return newList
   71     else:
   72         return ("Le fichier "+filename+" n'existe pas!")
   73 
   74 
   75 def writeFile(filename, lines):
   76     ''' Ecriture des lignes lines dans le fichier filename '''
   77     myFile = open(filename, 'w')
   78     for line in lines:
   79         oneStr = line + "\r\n"
   80         myFile.write(oneStr)
   81     myFile.close()
   82     return ("Écriture du fichier hosts OK")
   83 
   84 
   85 
   86 
   87 ###################### Lancement du programme principal
   88 #
   89 if __name__ == "__main__":
   90 
   91     tDepart = time.time()
   92     currentWorkingDir = os.getcwd()
   93     currentHostsFilePath = currentWorkingDir + '/hosts'
   94     currentBraveHistoryFilePath = currentWorkingDir + '/history.json'
   95     currentTcpdumpFilePath = currentWorkingDir + '/tcpdump.log'
   96 
   97     #### Lecture/chargement du fichier history.json -> Historique de navigation du navigateur Brave
   98     #
   99     returnedObject = readFileLines(currentBraveHistoryFilePath)
  100     braveUrlList = []
  101     if "<class 'list'>" in str(type(returnedObject)):
  102         for oneLine in returnedObject:
  103             if 'https://' in oneLine:
  104                 sep1 = oneLine.split('https://')
  105                 myUrl = sep1[1].split('/')[0]
  106                 if len(myUrl.split('.')) != 4:
  107                     braveUrlList.append(myUrl)
  108                 else:
  109                     try:
  110                         nb1 = int(myUrl.split('.')[0])
  111                         nb2 = int(myUrl.split('.')[1])
  112                         nb3 = int(myUrl.split('.')[2])
  113                         nb4 = int(myUrl.split('.')[3])
  114                     except:
  115                         braveUrlList.append(myUrl)
  116             if 'http://' in oneLine:
  117                 sep1 = oneLine.split('http://')
  118                 myUrl = sep1[1].split('/')[0]
  119                 if len(myUrl.split('.')) != 4:
  120                     braveUrlList.append(myUrl)
  121                 else:
  122                     try:
  123                         nb1 = int(myUrl.split('.')[0])
  124                         nb2 = int(myUrl.split('.')[1])
  125                         nb3 = int(myUrl.split('.')[2])
  126                         nb4 = int(myUrl.split('.')[3])
  127                     except:
  128                         braveUrlList.append(myUrl)
  129         braveUrlSet = set(braveUrlList)
  130         braveUrlList = list(braveUrlSet)
  131 
  132     #### Lecture/chargement du fichier tcpdump.log - Ce fichier aura eventuellement été
  133     #    créé par la commande "sudo tcpdump -tq tcp > tcpdump.log" à partir du répertoire
  134     #    courant .../pyHosts
  135     #
  136     returnedObject = readFileLines(currentTcpdumpFilePath)
  137     print(type(returnedObject))
  138     tcpdumpUrlList = []
  139     if "<class 'list'>" in str(type(returnedObject)):
  140         for oneLine in returnedObject:
  141             if not 'IP This.' in oneLine:
  142                 sep1 = oneLine.split('.http')
  143                 myUrl = sep1[0][3:]
  144                 if len(myUrl.split('.')) != 4 and not ' > ' in myUrl:
  145                     tcpdumpUrlList.append(myUrl)
  146                 else:
  147                     try:
  148                         nb1 = int(myUrl.split('.')[0])
  149                         nb2 = int(myUrl.split('.')[1])
  150                         nb3 = int(myUrl.split('.')[2])
  151                         nb4 = int(myUrl.split('.')[3])
  152                     except:
  153                         if not ' > ' in myUrl:
  154                             tcpdumpUrlList.append(myUrl)
  155         tcpdumpUrlSet = set(tcpdumpUrlList)
  156         tcpdumpUrlList = list(tcpdumpUrlSet)
  157 
  158     #### Chargement du fichier hosts -> Attention, ce fichier hosts est une copie du fichier
  159     #    /etc/hosts (attention aux droits d'écriture) ! CE FICHIER DOIT TOUJOURS EXISTER !!!
  160     #
  161     hostsUrlList = []
  162     listIPV4_127 = []
  163     listIPV6 = []
  164     newLines = []
  165     myLines = readFileLines(currentHostsFilePath)
  166     for oneLine in myLines:
  167         myIP = oneLine.split()[0]
  168         myHost = oneLine.split()[1]
  169         if '127.0.0.1' in myIP or '127.0.1.1' in myIP or '###BEGIN' in myIP:
  170             listIPV4_127.append(oneLine)
  171         if '###END' in oneLine or '# ' in oneLine:
  172             listIPV6.append(oneLine)
  173         if not '127.0.0.' in myIP and not '127.0.1.' in myIP and not '#' in myIP:
  174             hostsUrlList.append(myHost)
  175 
  176     #### Ajouts des nouvelles entrées en provenance de l'historique de Brave et de tcpdump à la
  177     #    liste des DNS à mettre à jour dans hostsUrlList - Suppression des URLs déjà présentes 
  178     #    dans listIPV4_127 de la liste hostsUrlList (si ces URLs sont dans listIPV4_127, c'est 
  179     #    que l'on souhaite les filtrer, il ne faut pas qu'elle soit dans la liste des adresses
  180     #    à mettre à jour!)
  181     #
  182     nbLinesBeforeUpdate = len(hostsUrlList)
  183     hostsUrlList.extend(braveUrlList)
  184     hostsUrlList.extend(tcpdumpUrlList)
  185     hostsUrlSet = set(hostsUrlList)
  186     hostsUrlList = list(hostsUrlSet)
  187     hostsUrlList.sort()
  188     toRemoveIndex = []
  189     for oneL127 in listIPV4_127:
  190         try:
  191             myHost127 = oneL127.split()[1]
  192             for theIndex, oneLUrlList in enumerate(hostsUrlList):
  193                 myHostUrlList = oneLUrlList.split()[1]
  194                 if myHost127 in myHostUrlList and myHostUrlList in myHost127:
  195                     toRemoveIndex.append(theIndex)
  196         except:
  197             pass
  198     toRemoveIndex.sort(reverse=True)
  199     for iddx in toRemoveIndex:
  200         del myHostUrlList[iddx]
  201     nbLines = len(hostsUrlList)
  202     newEntriesInHosts = nbLines - nbLinesBeforeUpdate
  203     listIPV4_127.sort()
  204     listIPV4_127.append(listIPV4_127[0])
  205     del listIPV4_127[0]
  206     newLines.extend(listIPV4_127)
  207 
  208     #### Mise à jour des DNS et sauvegarde du fichier hosts
  209     #
  210     for index, oneHost in enumerate(hostsUrlList):
  211         try:
  212             answ = dns.resolver.query(oneHost, 'A')
  213             rdata = answ[0]
  214             newLines.append(str(rdata.address)+' '+oneHost)
  215             print (index,'/', nbLines, ": ", rdata.address, oneHost)
  216         except:
  217             print('Erreur sur résolution DNS de :', oneHost)
  218     newLines.extend(listIPV6)
  219     print()
  220     print('Mise à jour du fichier hosts terminée.', str(newEntriesInHosts),
  221           'entrées ont été ajoutées au fichier hosts')
  222     print()
  223     status = writeFile(currentHostsFilePath, newLines)
  224     print(status)
  225     print()
  226     tUpdate = int(time.time() - tDepart)
  227     nbMin = int(tUpdate / 60)
  228     nbSec = int(tUpdate % 60)
  229     print('Mise à jour effectuée en', str(nbMin), 'min et', str(nbSec), 'sec')
  230     print()
  231     print()
  232     try:
  233         os.remove(currentBraveHistoryFilePath)
  234         os.remove(currentTcpdumpFilePath)
  235     except:
  236         '''Rien à faire, les fichiers history.json et/ou tcpdump.log auront été
  237         effacés si besoin'''
  238         pass
Publicité
Retour à l'accueil
Partager cet article
Repost0
Pour être informé des derniers articles, inscrivez vous :
Commenter cet article