Mémo syslog-ng

Au sommaire de ce tour d’horizon de « syslog-ng » :

Rappel

« syslog-ng » Est un système de gestion des logs flexible et hautement configurable. Son fichier de configuration est, sur la plupart des distributions : « /etc/syslog-ng/syslog-ng.conf« .

Il ce base pour cela sur cinq blocs principaux :

  • les options définissant l’ensemble des options de l’application,
  • les sources de données (tous ce qui assure les remontées de logs),
  • les destinations (où doivent être rangés les différentes informations),
  • les filtres (sous quelles conditions une donnée est dirigée vers une destination plutôt qu’une autre),
  • les logs (association d’une source à une destination en tenant éventuellement compte des conditions).

Les options

Le bloc d’option définit les différents paramètres globaux de fonctionnement de l’application. Voyez le man de « syslog-ng.conf » (http://linux.die.net/man/5/syslog-ng.conf) pour plus de détails. Ce bloc est de la forme :

options {
   option1 ;
   option2 ;
...
   optionN ;
}

Les sources

La déclaration d’une source est de la forme :

source NOM {
   sourcedriver params;
   sourcedriver params;
   ... ;
};

où « NOM » est le nom désignant la source, « sourcedriver » le type de source (pouvant être un fichier -file-, un socket -unix-dgram,unix-stream-, une source réseau -udp,tcp-), et « params » les paramètres de la source.

Les destinations

Comme les sources les destinations sont de la forme :

destination NOM {
   destdriver params;
   destdriver params;
    ... ;
};

où les paramètres sont approximativement les mêmes que pour les sources.

Les destinations peuvent utiliser un certain nombre de variables ainsi que des templates (des modèles) pour la mise en forme des logs.

destination all_by_date {
   file("/var/log/$R_YEAR/$R_MONTH/$R_YEAR$R_MONTH$R_DAY.log"
      template("$ISODATE <$FACILITY.$PRIORITY> $HOST $MSG\n")
      template_escape(no)) ;
};

Un template peut être définit dans un bloc afin d’être rappelé par la suite.

Les filtres

Les filtres de « syslog-ng » sont une véritable évolution de la gestion des logs. Ils permettent de classer les logs en fonction de leurs contenu via des expressions régulières matchant le nom du programme, de l’hôte, le contenu de la chaîne de caractère, ou classiquement en fonction de leurs priorité ou de leur « facility ». Les différents éléments d’un filtre peuvent ensuite être associés par « and », « or » et « not ».

La déclaration d’un filtre est ensuite de la même forme que les autres blocs :

filter NOM {
   expression;
   expression1 or expression2;
   ... ;
 };

Les logs

Les logs sont des blocs associant une/des source(s) à une/des destination(s) en prenant en compte les conditions de filtre(s) :

log {
   source NOM_SRC1;
...
   source NOM_SRCN;
   filter FILTRE_1;
...
   filter FILTRE_N;
   destination DESTINATION_1;
...
   destination DESTINATION_N;
};

Fichier de configuration simple

Descriptif

Le fichier de configuration proposé ici :

  • définit une source de logs unique « src_all » regroupant les informations provenant des trois sources principales : « /dev/log », « /proc/kmsg » (préfixé par « kernel: « ) et « syslog-ng » lui même ;
  • crée plusieurs destinations associées aux besoins ;
  • crée 4 filtres destiné a aiguiller les logs ;
  • enfin établis six associations sources/destination selon les filtres définis.

Au final ce fichier de configuration :

  • affiche les informations systèmes sur la console 12 ;
  • affiche les remontées du pare feu sur la console 11 ;
  • enregistre les remontées système dans « /var/log/messages » ;
  • enregistre les logs du firewall dans « /var/log/firewall.log » ;
  • enregistre les informations d’envois/réception de mail dans « /var/log/mail.log » (ou plus généralement, tous ce qui est logué avec le niveau « mail ») ;
  • enregistre les statistiques de « syslog-ng » dans « /var/log/stat.log ».

Configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
@version: 3.0
## /etc/syslog-ng/syslog-ng.conf
#
# Description
#       Fichier de configuration de syslog-ng (/etc/syslog-ng/syslog-ng.conf)
#       Version simple.
#
# Par
#       https://www.admin-linux.fr
#
 
##
# Definition des options générales :
options {
# Concernant les machines :
#       Désactivation des noms chaîné de machines dans les logs :
        chain_hostnames(off);
#       Pas de résolution DNS des nom de machines ni en court ni en "full qualified" :
        use_dns(no);
        use_fqdn(no);
#       A tous hasard check des nom de machines -pour les caractères illégaux- :
        check_hostname(yes);
#       utilisation d'un cache DNS :
        dns_cache(yes);
#       si oui, expiration du cache :
        dns_cache_expire(86400);
#       un echec de résolution de nom est en cache durant :
        dns_cache_expire_failed(86400);
#       nombre de machine dans le cache :
        dns_cache_size(20);
 
# Concernant l'application :
#       Nombre de lignes en attente dans la file :
        log_fifo_size(2048);
#       Syslog-ng peut créer des répertoires :
        create_dirs(yes);
#       Appartenance des fichiers de logs :
        owner(root);
        dir_owner(root);
        group(root);
        dir_group(root);
#       Définition des droits sur les fichiers/répertoires :
        perm(0640);
        dir_perm(2750);
#       Temps entre 2 messages de "stats" :
        stats_freq(3600);
#       Temps d'attente avant qu'un fichier inutilisé soit fermé (défaut 60s) :
        time_reap(360);
#       Temps d'attente avant qu'une connection morte soit ré ouverte (défaut 60s) :
        time_reopen(30);
};
 
##
# Définition des sources (d'où viennent les logs ?) :
source src_all {
# Dans l'ordre nous avons :
# - la source standard sous linux (/dev/log),
# - les messages de syslog-ng,
# - les remontée du kernel (que l'on signal par le préfix "kernel: ").
        unix-stream("/dev/log");
        internal();
        file("/proc/kmsg" program_override("kernel: "));
};
 
##
# Définition des destinations (mais où vont ils ?) :
# all_messages : fichier de log par défaut.
destination all_messages {
        file("/var/log/messages");
};
 
# console_all : console d'affichage des logs.
destination all_console {
        file("/dev/tty12");
};
 
# logs_firewall : les logs du firewall sont dans un fichier à part :
destination logs_firewall {
        file("/var/log/firewall.log");
};
 
# console_firewall : Les logs du firewall sont séparés :
destination console_firewall {
        file("/dev/tty11");
};
 
# mails : Les logs de mails :
destination mails {
        file("/var/log/mail.log");
};
 
# statistiques syslog :
destination df_stat {
        file("/var/log/stat.log");
};
 
##
# Définition des filtres (qui correspond à qui ?) :
# Les mails ont la "facility" mail :
filter f_mail {
        facility(mail);
};
 
# Les lignes taguées par le firewall sont sortie des logs :
# d'où :
# - Une règle matchant les remontées du firewall,
# - Une autre matchant l'inverse.
# from_firewall : match ce qui vient du firewall.
filter from_firewall {
        match ("fw drop" value("MESSAGE")) or match ("fw accept" value("MESSAGE"));
};
 
# not_from_firewall : le contraire de from_firewall.
filter not_from_firewall {
        not match ("fw drop" value("MESSAGE")) and not match ("fw accept" value("MESSAGE"));
};
 
# Filtre pour les statistiques :
filter f_stat {
        match("Log statistics" value("MESSAGE")) and match("syslog-ng" value("PROGRAM"));
};
 
##
# Association des briques de base :
# Si l'on ne match pas avec les règles de firewall, direction all_messages :
log {
        source(src_all);
        filter(not_from_firewall);
        destination(all_messages);
};
 
# ... et sur la console 12 :
log {
        source(src_all);
        filter(not_from_firewall);
        destination(all_console);
};
 
# Le firewall logue dans logs_firewall :
log {
        source(src_all);
        filter(from_firewall);
        destination(logs_firewall);
};
 
# ... et sur la console 11 :
log {
        source(src_all);
        filter(from_firewall);
        destination(console_firewall);
};
 
# Traitement de faveur pour les mails qui sont logués et dans all_messages et dans mails :
log {
        source(src_all);
        filter(f_mail);
        destination(mails);
};
 
# stat.* log des statistiques /var/log/stat.log
log {
        source(src_all);
        filter(f_stat);
        destination(df_stat);
};

Télécharger le fichier de configuration simple de « syslog-ng ».

Remarque

ATTENTION : Dans le cas de serveur générant une grande quantité de logs remontés du firewall et/ou du système, les filtres peuvent rapidement devenir problématique. En effet, chaque ligne logué passera les tests des différents filtres avant d’être écrites sur les disques. Dans l’exemple proposé, chaque information loguée passe 2 tests par filtre associés à la séparation des logs du firewall de ceux du système. Ce fichier, sur de TRÈS gros serveurs gérants un TRÈS important trafique, peut donc devenir problématique c’est pourquoi, il est fortement conseillé d’utiliser un outil dédié aux logs du firewall tel que « ulogd ».

Centralisation des logs simple

Compte tenu du mode de fonctionnement de « syslog-ng », la centralisation des logs est très simple, elle ce résume à :

  • définir une nouvelle source (udp ou tcp) de donnée et l’associer à une destination sur le serveur;
  • définir une destination (udp ou tcp) de donnée est lui associer une source sur le client.

Dans cet exemple d’une configuration simple, nous utiliserons l’UDP pour centraliser les logs, mais l’adaptation au protocole TCP est absolument trivial (grosso modo, remplacer « udp » par « tcp » dans les exemples suivants.

Serveur de log

Sur le serveur de log, nous ajoutons au fichier présenté ci dessus une nouvelle source de donnée de type « UDP » :

# Définition d'une source réseau en UDP :
source src_lan {
   udp() ;
} ;

par défaut, « syslog-ng » ce met à l’écoute sur toutes les interfaces réseau disponibles sur la machine sur le port « 514 ». Ce comportement peut être modifié en modifiant les paramètres « ip » et « port » de la source UDP :

   udp(ip(10.0.2.100) port(6000)) ;

La source « TCP » ajoute également la notion de nombre maximum de connexions :

   tcp(ip(10.0.2.100) port(6000) max-connections(100)) ;

Attention : « ip(10.0.2.100) » signifie que le service « syslog-ng » écoute sur l’interface d’ip « 10.0.2.100 » et non qu’il écoute les logs provenant de la machine « 10.0.2.100 ».

Nous ajoutons également une destination pour les logs issus du réseau :

# centralisation des logs issus du lan dans le fichier /var/log/lan.log :
destination logs_from_lan {
   file("/var/log/lan.log") ;
} ;

enfin le tout est associé dans un bloc « log » :

# Les logs issus du lan sont re-dirigés vers la destination "logs_from_lan" :
log {
   source(src_lan) ;
   destination(logs_from_lan) ;
} ;

Bien entendu, il est possible de superposer des fitres à ce « log » de la même manière que pour tous autres.

Partie cliente

Coté client, toujours en partant du fichier présenté ci dessus, nous ajoutons une destination de logs :

# Log à destination de srvlogs.rez0.lan (ip 10.0.2.100) :
destination srvlogs {
   udp("srvlogs.rez0.lan", port(514)) ;
} ;

et renvoyons les logs issus des sources vers cette destination :

# Envois des logs vers le serveur de logs :
log {
   source(src_all);
   destination(srvlogs);
} ;

Centralisation des logs avec SSL

La centralisation des logs en SSL avec « syslog-ng » ce complique un peut… Nous utilisons pour cela l’outil « stunnel » afin de créer un tunnel crypté entre le client et les serveurs et re dirigeons la sortie de « syslog-ng » sur l’entrée du tunnel « stunnel » coté client. Côté serveur, nous récupérons l’entrée du tunnel et l’ajoutons en tant que source locale.

stunnel_et_syslog-ng

  1. Le client redirige tous ses logs sur le port 514 de son interface de loop.
  2. « stunnel » Crée un tunnel crypté entre le client et le serveur centralisant les logs. Il prends tous ce qui arrive sur le port 514 de l’interface lo …
  3. … et l’envois sur le port 5140 du serveur de log…
  4. … qui les rediriges sur le port 514 de son interface de loop.
  5. Le serveur utilise dans syslog-ng une nouvelle source correspondant à son interface de loop port 514.

Le but de cette « brève » étant la configuration de syslog-ng, nous passerons rapidement sur la configuration de « stunnel » mais suffisamment pour pouvoir mettre en œuvre le système.

« stunnel » Est packagé sur la plupart des distributions Linux. Il peut également être téléchargé depuis le site du projet (http://www.stunnel.org/) et installé depuis les sources par les classiques « ./configure », « make » et « make install ».

Pour plus de détails sur la mise en place d’une chaîne de certification, consulter l’article « Autorité de certification et certificats OpenSSL« .

Pour simplifier les choses, nous installerons une autorité de certification sur le serveur de centralisation des logs. Si le serveur connais le certificat de la machine cliente, il acceptera les logs, sinon, il rejettera la connexion.

Préparation du serveur

Génération des certificats

Première étape installation d’une autorité de certification locale :

19:55 srvlogs ssl # pwd
/etc/ssl
19:55 srvlogs ssl # tree
.
|-- misc
|   |-- CA.pl
|   |-- CA.sh
|   |-- c_hash
|   |-- c_info
|   |-- c_issuer
|   `-- c_name
`-- openssl.cnf
 
1 directory, 7 files
19:56 srvlogs ssl # grep CADAYS= misc/CA.pl
$CADAYS="-days 1825";   # 5 years
19:56 srvlogs ssl # ./misc/CA.pl -newca
CA certificate filename (or enter to create)
 
Making CA certificate ...
Generating a 1024 bit RSA private key
...........++++++
.......++++++
writing new private key to './demoCA/private/cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:FR
State or Province Name (full name) [Some-State]:Ile-De-France
Locality Name (eg, city) []:Paris
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Admin Linux
Organizational Unit Name (eg, section) []:Service Informatique
Common Name (eg, YOUR name) []:FHH
Email Address []:fhh@admin-linux.fr
 
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /etc/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number:
            f6:e2:81:3a:fc:dd:f6:52
        Validity
            Not Before: Oct 28 18:58:37 2009 GMT
            Not After : Oct 27 18:58:37 2014 GMT
        Subject:
            countryName               = FR
            stateOrProvinceName       = Ile-De-France
            organizationName          = Admin Linux
            organizationalUnitName    = Service Informatique
            commonName                = FHH
            emailAddress              = fhh@admin-linux.fr
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                57:DD:1C:52:C1:EF:4D:F2:D3:82:8D:6D:F4:FC:B3:C2:F7:8A:C0:B7
            X509v3 Authority Key Identifier:
                keyid:57:DD:1C:52:C1:EF:4D:F2:D3:82:8D:6D:F4:FC:B3:C2:F7:8A:C0:B7
                DirName:/C=FR/ST=Ile-De-France/O=Admin Linux/OU=Service Informatique/CN=FHH/emailAddress=fhh@admin-linux.fr
                serial:F6:E2:81:3A:FC:DD:F6:52
 
            X509v3 Basic Constraints:
                CA:TRUE
Certificate is to be certified until Oct 27 18:58:37 2014 GMT (1825 days)
 
Write out database with 1 new entries
Data Base Updated

Jusque là, rien de spécial, création d’une autorité de certification valable 5 ans.

Pour le contrôle des certificats, création de hash de certificat (voir « Autorité de certification et certificats OpenSSL » pour plus de détails) :

20:05 srvlogs ssl # cd demoCA/certs/
20:06 srvlogs certs # cp ../cacert.pem ./
20:06 srvlogs certs # c_rehash ./
Doing ./
cacert.pem => 47b19144.0

Création d’un certificat qui sera distribué a la machine cliente :

20:06 srvlogs certs # cd ..
20:07 srvlogs demoCA # openssl genrsa -out private/mafalda.rez0.lan.key 1024
Generating RSA private key, 1024 bit long modulus
...++++++
.........++++++
e is 65537 (0x10001)
20:13 srvlogs demoCA # openssl req -key private/mafalda.rez0.lan.key -new -out newcerts/mafalda.rez0.lan.csr -days 1095
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:FR
State or Province Name (full name) [Some-State]:Ile-De-France
Locality Name (eg, city) []:Paris
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Admin Linux
Organizational Unit Name (eg, section) []:Service Informatique (Gestion des logs)
Common Name (eg, YOUR name) []:mafalda.rez0.lan
Email Address []:fhh@admin-linux.fr
 
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
20:15 srvlogs demoCA # openssl req -x509 -in newcerts/mafalda.rez0.lan.csr -key private/mafalda.rez0.lan.key > certs/mafalda.rez0.lan.pem

Ok, ça vas un peut vite, mais une fois de plus, pour plus de détails sur les autorités de certifications voir « Autorité de certification et certificats OpenSSL« .

Enfin signature du nouveau certificat par l’autorité précédement créée :

20:22 srvlogs demoCA # cd ..
20:22 srvlogs ssl # openssl ca -policy policy_anything -out ./demoCA/certs/mafalda.rez0.lan.pem -infiles ./demoCA/newcerts/mafalda.rez0.lan.csr
Using configuration from /etc/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number:
            f6:e2:81:3a:fc:dd:f6:53
        Validity
            Not Before: Oct 28 19:22:51 2009 GMT
            Not After : Oct 28 19:22:51 2010 GMT
        Subject:
            countryName               = FR
            stateOrProvinceName       = Ile-De-France
            localityName              = Paris
            organizationName          = Admin Linux
            organizationalUnitName    = Service Informatique (Gestion des logs)
            commonName                = mafalda.rez0.lan
            emailAddress              = fhh@admin-linux.fr
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                9A:0C:89:A7:E1:70:60:F6:AA:DE:DD:6B:67:69:76:63:21:3A:72:D3
            X509v3 Authority Key Identifier:
                keyid:57:DD:1C:52:C1:EF:4D:F2:D3:82:8D:6D:F4:FC:B3:C2:F7:8A:C0:B7
 
Certificate is to be certified until Oct 28 19:22:51 2010 GMT (365 days)
Sign the certificate? [y/n]:y
 
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

Enfin création des hash de clé :

20:24 srvlogs ssl # c_rehash ./demoCA/certs/
Doing ./demoCA/certs/
mafalda.rez0.lan.pem => a99508f7.0
cacert.pem => 47b19144.0

Voici qui termine la fastidieuse partie des certificats.

Configuration de stunnel serveur

En comparaison à la génération de l’autorité de certification, la configuration de stunnel est absolument triviale. Tous ce passe dans le fichier de configuration « /etc/stunnel/stunnel.conf ». Dans un premier temps, nous déclarons sous quel utilisateur fonctionnera le service stunnel en renseignant les variables « setuid » et « setgid ». Ensuite nous renseignons la localisation du fichier de PID puis les paramètres de l’autorité de certification et le mode de contrôle des certificats souhaité. Enfin, nous déclarons un port ainsi que la source et la destination qui lui sont associé.

# Utilisateur faisant fonctionner le service :
setuid = stunnel
# Groupe associé :
setgid = stunnel
 
# Déclaration du fichier PID :
pid = /var/run/stunnel/stunnel.pid
 
# Paramètre de l'autorité de certification :
# - Certificat publique du CA
CAfile = /etc/ssl/demoCA/certs/cacert.pem
# - Fichier de hash (pour contrôle)
CApath = /etc/ssl/demoCA/certs/
 
# Mode de contrôle :
# Level 1: vérification si un certificat est présenté ;
# Level 2: vérification du certificat du client (le certificat est nécessaire) ;
# Level 3: vérification du certificat du client et de sa signature par l'autorité de certification locale ;
# par défaut, pas de vérification.
verify = 3
 
# Déclaration du port pour syslog-ng :
[5140]
#      Accepte les connexions sur l'ip 10.0.1.100 port 5140
        accept = 10.0.2.100:5140
#      Re dirige vers le loopback port 514
        connect = 127.0.0.1:514

une fois le fichier modifié, démarrer le service « stunnel » :

20:51 srvlogs ssl # /etc/init.d/stunnel start
 * Starting stunnel ...   [ ok ]

Configuration de syslog-ng

La configuration de « syslog-ng » ne diffère que très peut de la configuration serveur simple. La seule différence réside dans le fait que la source de donnée provient maintenant de l’interface de loopback. En reprenant la configuration présentée ci dessus, nous obtiendrions :

# Définition d'une source réseau locale TCP :
source src_lan {
   tcp(ip(127.0.0.1) port(514) max-connections(1)) ; ;
} ;

Tout le reste reste inchangé. Pensez à re démarrer « syslog-ng ».

Préparation du client

Transfert des certificats

Côté client, nous devons dans un premier temps récupérer les certificats générés sur le serveur et plus particulièrement les fichiers « /etc/ssl/demoCA/private/mafalda.rez0.lan.key » et « /etc/ssl/demoCA/cert/mafalda.rez0.lan.pem ».

21:33 srvlogs ssl # pwd
/etc/ssl
21:33 srvlogs ssl # mkdir mafalda.rez0.lan
21:34 srvlogs ssl # cp demoCA/private/mafalda.rez0.lan.key demoCA/certs/mafalda.rez0.lan.pem mafalda.rez0.lan/
21:34 srvlogs ssl # tar cjvfp mafalda.rez0.lan.tar.bz2 mafalda.rez0.lan/
mafalda.rez0.lan/
mafalda.rez0.lan/mafalda.rez0.lan.key
mafalda.rez0.lan/mafalda.rez0.lan.pem
21:35 srvlogs ssl # scp mafalda.rez0.lan.tar.bz2 mafalda.rez0.lan:/etc/stunnel/

Ensuite les extraire et adapter les droits des fichiers :

mafalda stunnel # pwd
/etc/stunnel
mafalda stunnel # tar xvf mafalda.rez0.lan.tar.bz2
mafalda.rez0.lan/
mafalda.rez0.lan/mafalda.rez0.lan.key
mafalda.rez0.lan/mafalda.rez0.lan.pem
mafalda stunnel # chown -R stunnel.stunnel mafalda.rez0.lan
mafalda stunnel # chmod -R go-rwx mafalda.rez0.lan

Note : Il n’est pas très bon qu’une clé privé soit dupliquée ou qu’elle ce promène sur le réseau. Pour les besoins de l’exemple, cette pratique est tolérable, mais dans un contexte de production, préférez générer la clé ssl sur le client afin de n’avoir que les fichiers publiques à transférer vers le serveur pour signature avant de les rapatrier à nouveau sur le client.

Configuration de stunnel client

La configuration de stunnel est proche de celle du serveur :

# Utilisateur faisant fonctionner le service :
setuid = stunnel
# Groupe associé :
setgid = stunnel
 
# Fonctionnement en mode client :
client = yes
 
# Déclaration du fichier PID :
pid = /var/run/stunnel/stunnel.pid
 
# Certificat présenté au serveur :
cert = /etc/stunnel/mafalda.rez0.lan/mafalda.rez0.lan.pem
# la clé privée associée :
key = /etc/stunnel/mafalda.rez0.lan/mafalda.rez0.lan.key
 
# Déclaration du port pour syslog-ng :
[5140]
#       Entrée du tunnel :
        accept = 127.0.0.1:514
#       Vers :
        connect = 10.0.1.100:5140

nous y spécifions le certificat à utiliser et le mode de fonctionnement « client ».

A noter également, la source et la destination qui sont inversés.

Lancer stunnel est vérifier les logs afin de s’assurer que la connexion s’établie correctement :

mafalda stunnel # /etc/init.d/stunnel start
 * Starting stunnel ...
 *    /etc/stunnel/stunnel.conf                                                                                                                                                                               [ ok ]
mafalda stunnel # tail /var/log/messages
...
Oct 28 21:56:19 mafalda stunnel: LOG5[3081:139903144200528]: 5140 connected remote server from 10.0.1.28:40985

Configuration de syslog-ng (client)

Tout comme pour le serveur, la configuration du client ne change que peut de la configuration simple. Cette fois, seul la destination varie :

# Log à destination de l'entrée stunnel :
destination srvlogs {
   tcp("127.0.0.1", port(514)) ;
} ;

Pensez a reloader syslog-ng :

mafalda stunnel # /etc/init.d/syslog-ng reload
 * Reloading configuration and re-opening log files ...    [ ok ]

Il ne reste plus qu’à vérifier le résultat obtenu sur le serveur.

Amélioration du système

A ce stade, si tous c’est bien passé, vous devriez recevoir sur votre serveur de log tous les logs issus du client. Le principal problème rencontré est que, pour le serveur, les logs sont remontés de l’interface « 127.0.0.1 » ce qui, en cas de nombreuses machines centralisées, rend la lecture des logs quasi impossible.

Oct 29 16:13:20 127.0.0.1 dhcpcd[10549]: eth0: renewing lease of 10.0.2.28
Oct 29 16:13:20 127.0.0.1 dhcpcd[10549]: eth0: acknowledged 10.0.2.28 from 10.0.2.100
Oct 29 16:13:20 127.0.0.1 dhcpcd[10549]: eth0: leased 10.0.2.28 for 600 seconds

Il est possible d’utiliser les « templates » afin d’associer les différents logs aux machines qui les émettent. Ainsi, vous pouvez modifier l’affichage des logs depuis le client en modifiant le fichier de destination :

destination srvlogs {
     tcp("127.0.0.1", port(514),
     template("$HOST : ($FACILITY / $PRIORITY / $LEVEL / $TAG ) $YEAR-$MONTH-$DAY $HOUR:$MIN:$SEC > $PROGRAM : $MSG\n")
     template_escape(yes));
};

Qui donne à l’execution des logs du type :

Oct 29 20:05:02 127.0.0.1 mafalda : (daemon / info / info / 1e ) 2009-10-29 19:58:38 > dhcpcd : dhcpcd[10549]: eth0: acknowledged 10.0.2.28 from 10.0.2.100
Oct 29 20:05:02 127.0.0.1 mafalda : (daemon / info / info / 1e ) 2009-10-29 19:58:38 > dhcpcd : dhcpcd[10549]: eth0: leased 10.0.2.28 for 600 seconds
Oct 29 20:05:24 127.0.0.1 mafalda : (cron / notice / notice / 4d ) 2009-10-29 19:59:00 > fcron : fcron[22915]: Job rm -f /var/spool/cron/lastrun/cron.hourly started for user systab (pid 22916)
Oct 29 20:05:26 127.0.0.1 mafalda : (cron / notice / notice / 4d ) 2009-10-29 19:59:02 > fcron : fcron[22915]: Job rm -f /var/spool/cron/lastrun/cron.hourly completed
Oct 29 20:06:17 127.0.0.1 mafalda : (daemon / info / info / 1e ) 2009-10-29 19:59:53 > dhclient : dhclient: DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 7

Enregistrement des logs dans MySQL

syslog-ng Permettant de définir des destination de log variées, l’insertion des logs dans une base de donnée est donc relativement simple.

Voici les différentes étapes :

  1. création d’une base de donnée (MySQL dans cet exemple) ;
  2. définition de la table destinée à l’enregistrement des logs ;
  3. définition d’un template syslog-ng pour l’export des logs ;
  4. définition d’un pipe permettant l’écriture des données dans la base ;
  5. ajout d’une destination à syslog-ng pointant vers la base de donnée.

Création de la base de donnée

Aucune surprise en ce qui concerne la création de la base de donnée sous MySQL :

15:52 srvlogs ~ # mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.0.84-log Gentoo Linux mysql-5.0.84-r1
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 
mysql> create database syslogng ;
Query OK, 1 row affected (0.00 sec)
 
mysql> grant all privileges on syslogng.* to syslogng@'localhost' identified by 'MonP@sswd' ;
Query OK, 0 rows affected (0.00 sec)
 
mysql> quit
Bye

Définition de la table des logs

A la question « Que voulons nous enregistrer comme information ? » la réponse est généralement : le nom de la machine, la « facility », la priorité, le niveau d’alerte, le tag, la date, le programme source et le message retourné.

Ce qui donne une table MySQL du type :

CREATE TABLE logs (
        id MEDIUMINT NOT NULL AUTO_INCREMENT,
        host VARCHAR(128) DEFAULT NULL,
        facility VARCHAR(10) DEFAULT NULL,
        priority VARCHAR(10) DEFAULT NULL,
        level VARCHAR(10) DEFAULT NULL,
        tag VARCHAR(10) DEFAULT NULL,
        datetime datetime DEFAULT NULL,
        program VARCHAR(15) DEFAULT NULL,
        msg text,
        PRIMARY KEY  (id),
        KEY datetime (datetime),
        KEY priority (priority),
        KEY facility (facility),
        KEY program (program),
        KEY host (host)
) ;

… que l’on crée dans MySQL :

16:10 srvlogs ~ # mysql -usyslogng -p syslogng
Enter password:
...
mysql> CREATE TABLE logs (
    ->         id MEDIUMINT NOT NULL AUTO_INCREMENT,
    ->         host varchar(128) default NULL,
    ->         facility varchar(10) default NULL,
    ->         priority varchar(10) default NULL,
    ->         level varchar(10) default NULL,
    ->         tag varchar(10) default NULL,
    ->         datetime datetime default NULL,
    ->         program varchar(15) default NULL,
    ->         msg text,
    ->         PRIMARY KEY  (id),
    ->         KEY datetime (datetime),
    ->         KEY priority (priority),
    ->         KEY facility (facility),
    ->         KEY program (program),
    ->         KEY host (host)
    -> ) ;
Query OK, 0 rows affected (0.02 sec)

Définition du template « syslog-ng »

Pour que syslog-ng puisse écrire dans la base de donnée, nous créons un modèle qui génère directement la requête SQL qui sera passée à MySQL :

template log2db {
        template("INSERT INTO logs (host, facility, priority, level, tag, datetime, program, msg) VALUES ( '$HOST', '$FACILITY', '$PRIORITY', '$LEVEL', '$TAG', '$YEAR-$MONTH-$DAY $HOUR:$MIN:$SEC', '$PROGRAM', '$MSG' );\n");
        template_escape(no);
};

Ce template sera ajouté plus tard à la destination « go2db ».

Remarque

Nous avons désormais toutes les bases nécessaires au fonctionnement du log des informations dans MySQL. Ainsi, si nous définissions une nouvelle destination associée au template « log2db » dans syslog-ng du type :

destination go2db {
        program( "/usr/bin/mysql -u syslogng --password=MonP@sswd syslogng -Bs > /dev/null"
                template(log2db) );
};

et une association des logs à cette destination… :

log {
        source(src_all);
        destination(go2db);
};

… le système fonctionne.

Si nous préférons créer un pipe plus un script permettant de loguer les informations, c’est simplement qu’au lancement de syslog-ng toutes les informations relatives au lancement de la commande d’écriture dans la base de donnée seront affichées en clair dans la liste des procéssus :

19:29 srvlogs ~ # ps aux | grep mysql
root      4521  0.0  0.0  10856  1328 ?        S    19:22   0:00 /bin/sh -c /usr/bin/mysql -u syslogng --password=MonP@sswd syslogng -Bs > /dev/null
root      4526  0.0  0.1  43256  3136 ?        R    19:22   0:00 /usr/bin/mysql -u syslogng --password=x xxxxx syslogng -Bs
root      4631  0.0  0.0   5604   692 pts/0    R+   19:29   0:00 grep --colour=auto mysql
mysql     5696  0.0  1.4 296284 30140 ?        Ssl  19:02   0:00 /usr/sbin/mysqld --defaults-file=/etc/mysql/my.cnf...

Création du pipe

Afin de ce débarrasser du problème soulevé précédemment, créons un tube de type « First In First Out » (fifo) dans lequel les logs seront déposés :

19:29 srvlogs ~ # mkfifo -m 640 /var/lib/mysql/syslog-ng.pipe
19:40 srvlogs ~ # chown root.mysql /var/lib/mysql/syslog-ng.pipe

Un script fonctionnant en parallèle (« /etc/syslog-ng/log2mysql » par exemple) ce chargera d’ajouter les données à la base de donnée :

#!/bin/bash
 
# Script enregistrant les logs dans MySQL.
#
# Sauvegarde les bases de données MySQL sous
# sous forme d'un fichier par base.
# 
 
# Définition des variables de connexion :
MYSQLUSER="syslogng" ;
MYSQLPASS="MonP@sswd" ;
MYSQLHOST="localhost" ;
MYSQLPORT="3306" ;
MYSQLDB="syslogng" ;
 
# Définition du pipe :
MYSQLPIPE="/var/lib/mysql/syslog-ng.pipe" ;
 
# Définition des binaires :
MYSQL="/usr/bin/mysql" ;
MKFIFO="/bin/mkfifo" ;
 
if [ ! -e ${MYSQLPIPE} ] ; then
        ${MKFIFO} -m 640 ${MYSQLPIPE} ;
fi
        while [ -e ${MYSQLPIPE} ]; do
                ${MYSQL} --host=${MYSQLHOST} --port=${MYSQLPORT} -u ${MYSQLUSER} \
                        --password=${MYSQLPASS} ${MYSQLDB} -s < ${MYSQLPIPE} > /dev/null
        done
fi

ATTENTION : ce script contiens le login et le mot de passe mysql en clair ! Les droits en lectures doivent donc être particulièrement restrictifs (par exemple 700).

Mise en place

Toutes les briques de bases une fois mises en place, il ne reste plus qu’à les associer.

Nous créons donc une nouvelle destination dans syslog-ng pointant vers l’entrée du pipe … :

destination go2db {
        pipe( "/var/lib/mysql/syslog-ng.pipe"
                template(log2db) );
};

… puis associons cette destination aux logs qu’elle doit recueillir :

log {
        source(src_all);
        destination(go2db);
};

Enfin nous lançons le script d’écriture des logs avant de relancer syslog-ng :

20:51 srvlogs ~ # nohup /etc/syslog-ng/log2mysql &
20:51 srvlogs ~ # /etc/init.d/syslog-ng restart
 * Stopping syslog-ng ...    [ ok ]
 * Starting syslog-ng ...     [ ok ]

Le résultat est immédiat dans MySQL :

20:54 srvlogs ~ # mysql -p -u root -sBe 'select * from syslogng.logs'
Enter password:
...
71      srvlogs  local5  info    info    ae      2009-11-02 20:56:08     -su     HISTORY: PID=30529 UID=0 ls

Remarque : syslog-ng et MS Windows

A l’aide d’outils tel que Snare Agent (http://www.intersectalliance.com/projects/SnareWindows/), Microsoft Windows peut également centraliser ses logs sur syslog-ng. Chaque messages remonté d’un poste Windows sera préfixé du tag « MSWinEventLog » que l’on pourra filtrer afin de séparer les logs Microsoft des autres.

Remarque générale

Comme on peut le voir dans ce récapitulatif, avec un peut d’astuce et la souplesse de fonctionnement de « syslog-ng », il est possible de faire de nombreuses choses plus ou moins pertinentes. Cependant il est important de souligner que les choix tel que l’approvisionnement d’une base de donnée ou la mise en place de logs sur SSL sont des pratiques alourdissant considérablement le système. Ces pratiques peuvent ce justifier mais ont un coup en temps système et donc un impacte financier non négligeable sur de grosses plateforme en production. Il conviens de bien analyser les besoins avant de ce lancer dans la mise en place de système parfois sur dimensionnés aux vue du besoin final. Les possibilités techniques offertes par les systèmes Linux et la satisfaction de « l’exploit technique » ne doivent pas être les seules motivations à la mise en place de système d’information complexe, gourmand en ressources et finalement difficile à gérer et administrer.

Références

Le site de syslog-ng : http://www.balabit.com/network-security/syslog-ng/
Man syslog-ng.conf : http://linux.die.net/man/5/syslog-ng.conf
Man de syslog-ng : http://linux.die.net/man/8/syslog-ng
Snare Agent : http://www.intersectalliance.com/projects/SnareWindows/

2 réflexions au sujet de « Mémo syslog-ng »

  1. Erreur dans le script : “log2mysql”

    remplacer < par ... bref la bonne ligne s’écrit : --password=${MYSQLPASS} ${MYSQLDB} -s /dev/null ;

    1. Merci pour ce retour (j’ai condensé les commentaires ;-)). Je ne vois pas, dans votre syntaxe, l’extraction du contenu de la fifo obtenu par la redirection dans l’exemple :

      ${MYSQL} --host=${MYSQLHOST} --port=${MYSQLPORT} -u ${MYSQLUSER} 
      --password=${MYSQLPASS} ${MYSQLDB} -s < ${MYSQLPIPE} > /dev/null

      Je teste et change en cas besoins… Quoi qu’il en soit, merci pour vos commentaires !

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *