Script shell vérifiant la disponibilité d’un nom de domaine

Un petit script pour déterminer si un nom de domaine est libre ou déjà déposé.

Les serveurs whois des différents registres de premier niveau renvoyant des réponses structurées différemment, il faut déterminer pour chaque TLD la réponse-type correspondant à un nom de domaine libre et l’inclure dans le script.

Voici ce que retourne une requête whois sur « domainequinexistesurementpas.fr » :

[root@pc-linux]# whois domainequinexistesurementpas.fr
[Requête en cours whois.nic.fr]
[whois.nic.fr]
%%
%% This is the AFNIC Whois server.
%%
%% complete date format : DD/MM/YYYY
%% short date format    : DD/MM
%% version              : FRNIC-2.5
%%
%% Rights restricted by copyright.
%% See http://www.afnic.fr/afnic/web/mentions-legales-whois_en
%%
%% Use '-h' option to obtain more information about this service.
%%
%% [XX.XX.XX.XX REQUEST] >> domainequinexistesurementpas.fr
%%
%% RL Net [##########] - RL IP [#########.]
%%
 
%% No entries found in the AFNIC Database.

A présent, la même requête sur « domainequinexistesurementpas.it » :

[root@pc-linux]# whois domainequinexistesurementpas.it
[Requête en cours whois.nic.it]
[whois.nic.it]
Domain:             domainequinexistesurementpas.it
Status:             AVAILABLE

Les deux réponses sont totalement différentes (« No entries found in the AFNIC Database » pour le .fr, « Status: AVAILABLE » pour le .it). Il est donc indispensable de prendre en compte, pour chaque TLD, la réponse-type correspondant à un nom de domaine libre.

En cas d’interrogation sur un TLD qui n’a pas été prévu dans le script, ce dernier retourne : « TLD NON PRIS EN COMPTE ».

Une particularité du script : placer dans une variable dans une autre variable. Cette particularité apparaît au moment de filtrer la réponse avec la réponse-type correspondant au TLD : la commande grep doit prendre en paramètre le contenu de la variable correspondant à la réponse-type du TLD, mais le nom de cette variable n’est pas fixe.

Le script :

#!/bin/bash
 
# On place dans une variable le TLD du domaine interrogé.
# Le . est remplacé par _ (cas du .co.uk notamment) pour des raisons de noms de variables.
tld=`echo $1 | cut -f 2- -d . | sed -e "s/\./_/"`
 
# On place pour chaque TLD la réponse-type d'un domaine libre dans une variable.
# La variable porte le nom du TLD, avec le _ remplaçant le . si nécessaire.
fr="No entries found"
be="Status:      FREE"
ch="We do not have an entry"
de="Status: free"
it="Status:             AVAILABLE"
pl="No information available"
pt="no match"
fi="Domain not found"
no="No match"
nl="is free"
dk="No entries found"
ru="No entries found"
at="nothing found"
co_uk="No match for"
net_uk="Not match for"
org_uk="No match for"
uk="Error for"
com="No match for"
net="No match for"
org="NOT FOUND"
info="NOT FOUND"
biz="Not found"
ws="No match for"
edu="No Match"
xxx="No match for"
 
if [ -z $1 ]; then
        echo "PARAMETRE MANQUANT"
else
        if [ -z $2 ]; then
                if [ -z "${!tld}" ]; then
                        # Aucune variable n'est nommée comme le TLD : pas de réponse-type
                        echo "TLD NON PRIS EN COMPTE"
                else
                        # On filtre la réponse du whois avec la réponse-type du TLD.
                        if [ -z "`whois $1 | grep "${!tld}"`" ]; then
                                echo "ENREGISTRE"
                        else
                                echo "LIBRE"
                        fi
                fi
        else
                echo "PARAMETRE EN TROP"
        fi
fi

Le script en action :

[root@pc-linux]# ./dispo_ndd.sh domaine.fr
ENREGISTRE
[root@pc-linux]# ./dispo_ndd.sh domaine-existepas.fr
LIBRE
[root@pc-linux]# ./dispo_ndd.sh domaine.ca
DOMAINE NON DISPONIBLE


 Manipulations sur les adresses e-mail d’une table sur MySQL

Supposons un intranet d’entreprise sur un domaine « domaine.fr », avec messagerie électronique en @domaine.fr pour tous les utilisateurs.

Arrive le jour où l’architecture de l’intranet fait l’objet d’une évolution passant par le changement de domaine : domaine.fr devient intranet.nom.fr. Il va falloir, sur nombre de tables, modifier toutes les adresses e-mail de tous les utilisateurs. Il faudra peut-être gérer, pour certains cas, des adresses e-mail mal orthographiées (domiane.fr), avec une casse différente (DOMAINE.FR), ou, comme j’ai pu le constater récemment sur un bug tracker où les utilisateurs s’inscrivaient eux-mêmes, des domaines totalement différents de celui mis en place (gmail.com)… voire pas de domaine du tout (simple nom d’utilisateur sous la forme prenom.nom) !

La simplicité voudrait que l’on édite le dump de la base de données avec son éditeur de texte favori (Notepad++ sur Windows, vi sous Linux… en ce qui me concerne) et que l’on fasse les modifications avec une fonction de remplacement de texte. Seulement, l’hétérogénéité des adresses e-mail enregistrées et surtout la taille du dump sont deux freins non négligeables à cette solution. Ouvrir un dump de 1 Go avec Notepad++ ? Impensable ! Exporter uniquement les tables où figurent les adresses e-mail, puis ensuite les réinjecter ? Pourquoi pas, mais en fonction des outils mis en place sur l’intranet, cette méthode peut se réveler fastidieuse. Modifier manuellement dans la table les adresses e-mail ? Oui pour quelques utilisateurs, non pour plusieurs dizaines voire centaines d’utilisateurs.

Il y a une solution simple, efficace et rapide avec MySQL. Démonstration :

mysql> DESC users;
+-------+-------------+------+-----+---------+-------+ 
| FIELD | TYPE        | NULL | KEY | DEFAULT | Extra |
+-------+-------------+------+-----+---------+-------+ 
| email | VARCHAR(50) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+ 
1 ROW IN SET (0.05 sec)
 
 
mysql> SELECT * FROM users;
+-------------------------------+ 
| email                         |
+-------------------------------+ 
| sergent.bellec                |
| capitaine.flamme@DOMAINE.FR   |
| lieutenant.columbo@domaine.fr |
| colonel.moutarde@youpi.fr     |
+-------------------------------+ 
4 ROWS IN SET (0.05 sec)
 
 
mysql> UPDATE users SET email=concat(substring_index(email,'@',1),'@intranet.nom.fr');
Query OK, 4 ROWS affected (0.00 sec)
ROWS matched: 4  Changed: 4  Warnings: 0
 
 
mysql> SELECT * FROM users;
+------------------------------------+ 
| email                              |
+------------------------------------+ 
| sergent.bellec@intranet.nom.fr     |
| capitaine.flamme@intranet.nom.fr   |
| lieutenant.columbo@intranet.nom.fr |
| colonel.moutarde@intranet.nom.fr   |
+------------------------------------+ 
4 ROWS IN SET (0.00 sec)

Explications :

- La fonction substring_index permet de découper la valeur d’un champ avec un délimiteur ;
- La fonction concat permet de concaténer (ah bon ?) deux éléments.

Grâce à ces deux fonctions, la requête récupère pour chaque utilisateur la partie avant l’arobase, y ajoute la valeur « @intranet.nom.fr » et met à jour le champ. Tout simplement.



 Censure dans les noms de pages Facebook : un cache-misère

Note importante :

La page présentée n’a été créée que dans l’unique but de servir d’illustration à cet article. Elle n’existe plus, et a été initiée depuis un compte créé lui aussi à cet effet. Par ailleurs, son intitulé ne reflète en rien la pensée de l’auteur de cet article. Il est volontairement « choquant » pour permettre de ne pas passer, dans un premier temps, les mailles de la censure Facebook.

L’une des fonctionnalités de Facebook, très prisée par une certaine tranche d’âge des utilisateurs, est le système de pages / groupes. Une page ou un groupe fédère des utilisateurs autour d’un point commun, qu’il soit sérieux (une enseigne de magasin, un artiste) ou totalement absurde.

Par mesure de précaution, une censure est mise en place au moment de créer une page ou un groupe, afin d’empêcher l’existence de pages telles que « j’aime la cocaïne » ou « Vive Marc Dutroux ! ». Tout ceci est parfaitement normal.

Toutefois, cette censure a ses limites, bien vite atteintes. Le but de cet article est d’en faire la démonstration, afin de « dénoncer » le manque de professionnalisme de la société Facebook dans ses obligations de sécurisation du site.

1. Première tentative de création d’une page

Ici, le nom « Faire l’apologie de crimes de guerre » est clairement refusé.

 

2. Seconde tentative de création d’une page

Le nom de la page demandée est « FAIRE L’APOLOGIE DE CRIMES DE GUERRE ». Encore une fois, refus. A noter que le nom, dans le champ, a une casse différente : le changement provient de Facebook, qui semble ne pas aimer les noms intégralement rédigés en majuscules.

 

3. Troisième tentative de création d’une page

Et bien oui ! En changeant le nom de la page demandée pour « FaiRe L’aPoLoGie De CRiMeS De GueRRe », le filtre n’y voit que du feu et valide la création. Rien n’a changé par rapport aux deux tentatives précédentes… si ce n’est la casse particulière de celle-ci.

 

4. Conséquence

Grâce à Facebook, n’importe quel utilisateur peut désormais déclarer aimer l’apologie de crimes de guerre, malgré le semblant de protection mis en place.

 

5. Tentative post-création

Cerise sur le gâteau : grâce à l’interface de gestion de la page, il est possible de demander le changement de nom pour celui qui nous avait été refusé à la première étape de cette démonstration. Où est le filtre ?

 

6. Résultat final

Malgré le filtre présent à la création de la page, il est tout à fait possible de nommer une page sans contrainte sur les termes choisis. Il est inquiétant de constater que Facebook semble prendre, une fois de plus, la question de la sécurité à la légère.

Il est à noter cependant qu’un nom propre, très fortement lié aux heures les plus sombres de la France durant la Seconde Guerre Mondiale, soit refusé à chaque étape de cette démonstration ; pourquoi seulement ce nom ? Le filtrage des pages Facebook est décidement bien étonnant.



 Firesheep : alerte sur vos données personnelles !

Une extension Firefox vient de voir le jour, nommée « Firesheep ».

Son but est de permettre le vol de cookies, ces petits fichiers utilisés pour vous « reconnaître » sur un site et vous dispenser de l’étape d’authentification. L’intérêt de les voler ? Pouvoir s’authentifier à votre place sur un site, sans aucun identifiant ou mot de passe.

L’utilisation de cette extension est enfantine et démontre à quel point il est urgent que certains sites (au hasard… Facebook) prennent enfin les mesures nécessaires pour garantir à ses utilisateurs un niveau de sécurité acceptable, ce qui n’est pas le cas à l’heure actuelle.

Parmi les sites concernés : Facebook, Twitter, Google, Flickr, Windows Live, Amazon, Yahoo…

Tant que les communications ne passeront pas systématiquement par le protocole SSL (adresses en https:// et petit cadenas affiché sur votre navigateur) de bout en bout, il est fortement recommandé de ne plus s’authentifier sur ces sites à partir d’une connexion non-sûre (réseau WiFi ouvert ou peu protégé). A l’heure actuelle, la protection SSL mise en place ne concerne bien souvent que l’étape d’authentification, et laisse le flux en clair pour le reste de la navigation.

Notez enfin que Firefox n’est pas responsable de cette extension, et que l’utilisation de cette dernière est réellement à la portée de n’importe quel pirate en herbe, qui aurait alors un accès total à vos données dans le cas où vous en seriez victime.



 Script de relance automatique du serveur SSH

Lorsque l’on administre un serveur à distance sans accès physique sur la machine, bien souvent, l’accès au serveur tient à un fil : celui du SSH. Si, pour une raison ou une autre, le serveur SSH s’arrête… les ennuis commencent pour l’administrateur et les utilisateurs.

Même si les connexions SSH actives ne sont pas interrompues lors de l’arrêt du serveur (à condition de ne pas tout stopper avec un killall !), il suffit d’un peu de malchance pour que celles-ci le soient : un plantage de votre système, une coupure électrique, une déconnexion de votre FAI juste après l’arrêt du serveur SSH et vous voilà coincé à la porte de votre serveur distant.

Pour éviter cela, j’ai imaginé un script qui vérifierait régulièrement l’état du serveur SSH et le relancerait si besoin, avec restauration d’une sauvegarde du fichier sshd_config en cas d’échec lors du redémarrage. Ce script est évidemment à placer dans la crontab d’un utilisateur ayant les droits requis pour travailler dans le répertoire de configuration de SSH et redémarrer le service… c’est à dire root, pour faire simple.

Attention :

- Vérifiez bien votre configuration pour les variables déclarées en entête du fichier. Par exemple, le service se nomme « ssh » sur Debian / Ubuntu, et « sshd » sur Red Hat / Fedora.

- Testez le script sur un environnement de test dans un premier temps, pour éviter de faire des erreurs sur un environnement de production.

#!/bin/bash
 
n_service="ssh"                      # Nom du service
f_exe="/usr/sbin/sshd"               # Exécutable du service
f_origine="/etc/ssh/sshd_config"     # Fichier de configuration actuelle
f_secours="/var/scripts/sshd_config" # Sauvegarde de la configuration
f_log="/var/log/restart_ssh"         # Fichier de log
 
now="$(date +%d/%m/%Y' - '%H:%M)"    # Date et heure pour le log
 
if ! ps ax | grep $f_exe | grep -v grep &> /dev/null
then
        /etc/init.d/$n_service start &> /dev/null
        if ps ax | grep $f_exe | grep -v grep &> /dev/null
        then
                echo "[$now] $n_service redémarré automatiquement" >> $f_log
        else
                rm $f_origine
                cp $f_secours $f_origine
                /etc/init.d/$n_service start &> /dev/null
                if ps ax | grep $f_exe | grep -v grep &> /dev/null
                then
                        echo "[$now] $n_service redémarré après restauration" >> $f_log
                else
                        echo "[$now] $n_service arrêté, restauration inefficace" >> $f_log
                fi
        fi
fi

Crontab root (à adapter selon vos souhaits, ici un lancement du script toutes les minutes) :

#       minute (de 0 à 59)
 
#       |       heure (de 0 à 23)
 
#       |       |       jour (de 1 à 31)
 
#       |       |       |       mois (de 1 à 12)
 
#       |       |       |       |       jour de la semaine (de 0 à 6, 0 = dimanche)
 
#       |       |       |       |       |       commande
 
        */1     *       *       *       *       /bin/bash /var/scripts/restart_ssh.sh