Dans cet article, je vais vous présenter une solution pour envoyer l’ensemble des commandes exécutées avec le shell bash sur un serveur syslog distant. Cette option est possible en utilisant la variable d’environnement PROMPT_COMMAND ou nativement avec bash à condition de le recompiler. C’est cette deuxième solution que je vais vous présenter avec deux alternatives : recompiler bash et l’installer directement depuis les sources ou modifier le paquet Debian. Nous verrons également une configuration rsyslog client/serveur pour centraliser tous vos logs à un seul endroit.

Installer bash depuis les sources

Compilation de bash avec syslog

Voici les étapes nécessaires pour compiler bash 4.2 sur une Debian Squeeze :

  • Installez le paquet build-essential.
  • Récupérez les sources de bash : wget ftp://ftp.gnu.org/gnu/bash/bash-4.2.tar.gz
  • Décompressez l’archive et placez vous dans le répertoire de bash :
tar xvf bash-4.2.tar.gz && cd bash-4.2
  • Créez un répertoire patchs et récupérez l’ensemble des patchs disponibles pour bash 4.2 :
mkdir patchs && cd patchs
ncftpget ftp://ftp.gnu.org/gnu/bash/bash-4.2-patches/bash42-???
cd ..
  • Depuis la racine des sources, patchez bash avec tous ces patchs :
for p in patchs/*
do
    patch -p0 < ${p}
done
  • Éditez le fichier config-top.h pour décommenter la ligne /* #define SYSLOG_HISTORY */ (tout en bas).
  • Vous pouvez ensuite compiler bash avec les options de votre choix. Par exemple, les options de compilation du paquet Debian :
./configure --with-curses --enable-largefile --prefix=/usr --infodir=/usr/share/info --mandir=/usr/share/man --enable-static-link --without-bash-malloc --bindir=/bin --host=`dpkg-architecture -qDEB_HOST_GNU_TYPE`
  • Reste à lancer la compilation :
make && make install

Rajouter des diversions

Pour éviter d’écraser les fichiers du paquet bash ou au contraire d’avoir la version de bash syslog écrasé par un upgrade du paquet, vous pouvez utiliser des diversions. Avant de faire le make install, lancez cette boucle qui va créer les diversions nécessaires :

DIVERT_FILES="/bin/bash
/usr/share/locale/en@quot/LC_MESSAGES/bash.mo
/usr/share/locale/af/LC_MESSAGES/bash.mo
/usr/share/locale/id/LC_MESSAGES/bash.mo
/usr/share/locale/tr/LC_MESSAGES/bash.mo
/usr/share/locale/fi/LC_MESSAGES/bash.mo
/usr/share/locale/eo/LC_MESSAGES/bash.mo
/usr/share/locale/lt/LC_MESSAGES/bash.mo
/usr/share/locale/pl/LC_MESSAGES/bash.mo
/usr/share/locale/vi/LC_MESSAGES/bash.mo
/usr/share/locale/ru/LC_MESSAGES/bash.mo
/usr/share/locale/de/LC_MESSAGES/bash.mo
/usr/share/locale/ca/LC_MESSAGES/bash.mo
/usr/share/locale/pt_BR/LC_MESSAGES/bash.mo
/usr/share/locale/et/LC_MESSAGES/bash.mo
/usr/share/locale/sv/LC_MESSAGES/bash.mo
/usr/share/locale/fr/LC_MESSAGES/bash.mo
/usr/share/locale/zh_TW/LC_MESSAGES/bash.mo
/usr/share/locale/ga/LC_MESSAGES/bash.mo
/usr/share/locale/es/LC_MESSAGES/bash.mo
/usr/share/locale/en@boldquot/LC_MESSAGES/bash.mo
/usr/share/locale/hu/LC_MESSAGES/bash.mo
/usr/share/locale/nl/LC_MESSAGES/bash.mo
/usr/share/locale/ro/LC_MESSAGES/bash.mo
/usr/share/locale/sk/LC_MESSAGES/bash.mo
/usr/share/locale/ja/LC_MESSAGES/bash.mo
/usr/share/locale/cs/LC_MESSAGES/bash.mo
/usr/share/locale/bg/LC_MESSAGES/bash.mo"

for file in $DIVERT_FILES
do
    dpkg-divert -package "bash-syslog" -add -rename -divert ${file}_debian ${file}
done

Grâce à ces diversions, les fichiers originaux sont renommés en _debian et une mise à jour du paquet bash ne risque pas de modifier votre installation manuelle.

Si vous souhaitez revenir au bash standard, faites un make uninstall et relancez la boucle précédente avec cette fois un remove des diversions :

for file in $DIVERT_FILES
do
  dpkg-divert -package "bash-syslog" -remove -rename -divert ${file}_debian ${file}
done

Modifier le paquet Debian

C’est à mon avis la meilleure solution : pas de risque de voir ses modifications écrasées par la mise à jour du paquet, pas besoin de faire des diversions mais pour rester simple, il faudra utiliser la version de la distribution. Les étapes nécessaires à partir d’une Debian Squeeze :

  • Modifiez votre sources.list pour rajouter les paquets sources :
# deb-src
deb-src http://ftp.fr.debian.org/debian/ squeeze main contrib non-free
  • Après un apt-get update, récupérez le paquet source bash avec un apt-get source bash après vous être placé dans le répertoire /usr/local/src.
  • Installez également le paquet devscripts qui contient les outils nécessaires à la création de paquets Debian ainsi que toutes les dépendances liées à la compilation de bash :
apt-get install devscripts
apt-get build-dep bash
  • Dans le répertoire créé, bash-4.1 à l’écriture de cet article, il y a un répertoire debian. Il faut rajouter un patch dans le répertoire patches et modifier le fichier rules utilisé pour la construction du paquet. Placez vous dans l’arborécence bash-4.1/debian/patches et créez le fichier enable-syslog.dpatch avec pour contenu :
for file in $DIVERT_FILES
do
  dpkg-divert -package "bash-syslog" -remove -rename -divert ${file}_debian ${file}
done

Modifier le paquet Debian

C’est à mon avis la meilleure solution : pas de risque de voir ses modifications écrasées par la mise à jour du paquet, pas besoin de faire des diversions mais pour rester simple, il faudra utiliser la version de la distribution. Les étapes nécessaires à partir d’une Debian Squeeze :

  • Modifiez votre sources.list pour rajouter les paquets sources :
# deb-src
deb-src http://ftp.fr.debian.org/debian/ squeeze main contrib non-free
  • Après un apt-get update, récupérez le paquet source bash avec un apt-get source bash après vous être placé dans le répertoire /usr/local/src.
  • Installez également le paquet devscripts qui contient les outils nécessaires à la création de paquets Debian ainsi que toutes les dépendances liées à la compilation de bash :
apt-get install devscripts
apt-get build-dep bash
  • Dans le répertoire créé, bash-4.1 à l’écriture de cet article, il y a un répertoire debian. Il faut rajouter un patch dans le répertoire patches et modifier le fichier rules utilisé pour la construction du paquet. Placez vous dans l’arborécence bash-4.1/debian/patches et créez le fichier enable-syslog.dpatch avec pour contenu :
#! /bin/sh -e

if [ $# -eq 3 -a "$2" = '-d' ]; then
    pdir="-d $3"
elif [ $# -ne 1 ]; then
    echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
    exit 1
fi
case "$1" in
    -patch) patch $pdir -f --no-backup-if-mismatch -p1 < $0;;
    -unpatch) patch $pdir -f --no-backup-if-mismatch -R -p1 < $0;;
    *)
	echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
	exit 1
esac
exit 0

# DP: enable syslog
--- bash/config-top.h~	2012-09-04 23:09:48.000000000 +0200
+++ bash/config-top.h	2012-09-04 23:09:59.000000000 +0200
@@ -101,7 +101,7 @@

 /* Define if you want each line saved to the history list in bashhist.c:
    bash_add_history() to be sent to syslog(). */
-/* #define SYSLOG_HISTORY */
+#define SYSLOG_HISTORY */
 #if defined (SYSLOG_HISTORY)
 #  define SYSLOG_FACILITY LOG_USER
 #  define SYSLOG_LEVEL LOG_INFO

Vous pouvez également changer la facilité et le niveau d’alerte syslog. Par exemple pour utiliser la facilité local1, changez : # define SYSLOG_FACILITY LOG_USER en # define SYSLOG_FACILITY LOG_LOCAL1

  • Dans le répertoire bash-4.1/debian, éditez le fichier rules. Il faut rajouter notre patch à la liste des patchs à appliquer aux sources de bash : recherchez la variable debian_patches (à la ligne 500 pour bash-4.1). Rajoutez à la suite des patchs enable-syslog.
  • Il faut ensuite générer ce nouveau paquet bash. Placez-vous dans le répertoire racine du paquet source bash-4.1. Pour éviter qu’il rentre en conflit avec celui livré par Debian, on rajoute un suffixe à la version du paquet ainsi qu’un petit commentaire pour le changelog du paquet :
dch --local +syslog "Enable syslog"
  • On lance la fabrication du paquet avec debuild -us -uc.
  • C’est terminé : votre nouveau paquet est disponible dans /usr/local/src. Vous pouvez l’installer simplement avec dpkg -i bash_4.1-3+syslog1_*.deb.

Configurer Rsyslog

Après avoir installé votre nouveau bash, relancez un bash ou reconnectez vous sur votre serveur pour utiliser la nouvelle version. Après quelques commandes, vérifiez votre /var/log/syslog. Vous obtenez l’historique bash au format suivant :

Sep  4 23:46:30 test-bash -bash: HISTORY: PID=26396 UID=0 htop
Sep  4 23:46:33 test-bash -bash: HISTORY: PID=26396 UID=0 last
Sep  4 23:46:40 test-bash -bash: HISTORY: PID=26396 UID=0 ll /etc/
Sep  4 23:46:43 test-bash -bash: HISTORY: PID=26396 UID=0 less /var/log/syslog

Si vous souhaitez centraliser vos logs sur un serveur, il faut modifier la configuration rsyslog de votre client et de votre serveur.

Sur le client

Rajoutez le fichier /etc/rsyslog.d/bash-history.conf avec pour contenu :

# remplacez mon_loghost par l'@ip de votre serveur syslog
user.info @mon_loghost

Relancez ensuite rsyslog : service rsyslog restart.

Sur le serveur

Sur votre serveur syslog, créez un fichier /etc/rsyslog.d/all-bash-history.conf avec le contenu suivant :

$template BashLogs,"/var/log/bash-history/history_%HOSTNAME%.log"
user.info ?BashLogs
& ~

Relancez ensuite rsyslog comme pour le client après avoir créé le répertoire /var/log/bash-history : service rsyslog restart. Le répertoire /var/log/bash-history contiendra un fichier de log par serveur. Dans mon cas, j’obtiens le fichier /var/log/bash-history/history_test-bash.log qui contient :

Sep  4 23:55:46 192.168.1.10 -bash: HISTORY: PID=26396 UID=0 less /var/log/syslog
Sep  4 23:55:48 192.168.1.10 -bash: HISTORY: PID=26396 UID=0 top
Sep  4 23:58:14 192.168.1.10 -bash: HISTORY: PID=26396 UID=0 service rsyslog restart

Pour info, le - devant bash dans vos logs indique qu’il s’agît d’un shell de login.

J’espère que cet article sera utile à ceux qui cherchent un moyen de centraliser et d’auditer toutes les commandes exécutées sur un ensemble de serveurs. Bons tests 😉