2010. február 3., szerda

Apache logok gyűjtése syslog-ng segítségével

Adott egy webszerver rengeteg virtual hostal. Jelenleg egy chrootban figyel, de lehetne virtual szerveren, sőt igazi gépen is. Szeretném a naplókat összegyűjteni a következő feltételekkel:
  • Az apache mellett ne maradjanak ott a logok
  • Ne kelljen száz és ezer naplófájlt illetve csatornát kezelni, ha lehet egy kapcsolatban menejen át (na jó kettőn;-)
  • Ne kelljen a helyszínen rotálgatni és támogassuk az archíválást
  • Természetesen használjunk valamilyen megbízható protokollt, de ezt írni sem kell:-)
Hogyan kezdjünk hozzá? Első lépésben vegyük rá az apacheot, hogy named pipe-ba írja az üzeneteit. Ehhez semmit nem kell tennünk, csak gyártsuk le a két szükséges pipe-ot. Hazsnáljuk az mknod parancsot:
mknod /var/log/apache/access.log p
mknod /var/log/apache/error.log p
Majd minden virtuál hostunkat loggoltassuk ide:
ErrorLog /var/log/apache2/error.log
LogLevel debug
CustomLog /var/log/apache2/access.log combined
Fontos, hogy ezután minden virtual host ide naplózzon! Ennek eredményeképpen a napló üzenetek ide nem kerülnek tárolásra. Már csak fel kell olvasni az üzenetet. Egyetlen apró bökkenő, hogy az apache Common Log Format-ot használ, ami meglehetősen távol áll bármely syslog formátumtól. Szerencsére az apacheban ezt is lehet állítani. Ha megfigyelitek, az access.log utáni combined szó az üzenet formátumát jelenti, mely az apache2.conf-ban állítható. Eredetileg így néz ki:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
Nos ezt a formátumot írjuk át úgy, hogy syslog megfelelő legyen. Az enyém így néz ki:
LogFormat "<123>Jan 12 12:12:12 %v apache[666]: %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combine
Most ne törődjünk a furcsa PRI és időpecsét mezőkkel. A még viccesebb PID se zaklasson fel, csak a google miatt haszáltam:-) Ami itt számít az a hostname mező, ahol a virtual host nevét viszem át (%v = a virtual host neve) az eredeti üzenetet meg az üzenet helyén ($MSGONLY) helyén viszem át. Tehát most készen vagyunk az apache oldallal, jöhet a syslog-ng. Első lépésben felolvassuk a két pipe-ot:
source s_apache_access {
pipe("/var/log/apache2/access.log);
};
Majd a fogadó oldalon egyszerűen hostnevenként más fájlba tesszük!
destination d_apache_access {
file("/var/log/apache2/$FULLHOST" template("$MSGONLY\n") template-escape(no) owner("root") group("adm") perm(0640));
file("/var/log/archive/$R_YEAR/apache/$R_MONTH/$FULLHOST.$R_DAY" template("$MSGONLY\n") template-escape(no) owner("root") group("adm") perm(0640) create_dirs(yes) dir_owner("root") dir_group("adm"));

};
Én szeretem az archíválást is egyúttal megejteni, amit a példa destination második célja meg is tesz. Már csak össze kell valahogy kötni a két üzenetet. Ehhez kliens oldalon egy hálózati célt definiálunk:
destination d_logserver_net {
tcp("1.2.3.4" port(514)
tls(ca_dir("/opt/syslog-ng/etc/syslog-ng/ca.d")

key_file("/opt/syslog-ng/etc/syslog-ng/key.d/client.key")
cert_file("/opt/syslog-ng/etc/syslog-ng/cert.d/client_cert.pem")));
};
log {
source(s_apache_access);
destination(d_logserver_net);
};
A szerver oldalon pedig fogadjuk az üzeneteket:
source s_apache_net {
t
cp(ip(0.0.0.0) port(1999)
tls( key_file("/opt/syslog-ng/etc/syslog-ng/key.d/syslog-ng.key")
cert_file("/opt/syslog-ng/etc/syslog-ng/cert.d/syslog-ng.cert")
ca_dir("/opt/syslog-ng/etc/syslog-ng/ca.d")) );
};

log {

source(s_apache);
destination(d_apache_access);
};
És kész! Ugye egyszerű volt?

4 megjegyzés:

Attila írta...

Üdv!
Köszi a leírást,biztos egyszerű,de sajnos nekem egy ennél is egyszerűbb távoli logolás sem akaródzik működni:
"A" serverről /tmp/source fileba kerülő bejegyzéseknek kellene bekerülnie "B" server /tmp/destination filejába:
"A" server:
source s_online
{
file("/tmp/source");
};
destination d_online
{
tcp("0.0.0.0" port(514)) );
};
log {
source(s_online);
destination(d_online);
};
"B" server:
source s_online
{
tcp(ip(0.0.0.0) port(514));
};
destination d_online
{
file("/tmp/destination");
};
log {
source(s_online);
destination(d_online);
};
/tmp/destination-ban ez található:
"Syslog connection established;"
Erre esetleg lenn ötleted?
Köszi:zoltán

Höltzl Péter írta...

destination d_online
{
tcp("0.0.0.0" port(514)) );
};

Ha a 0.0.0.0-ra küldöd, akkor nem tudja, milyen szerverhez kell kapcsolódni! Helyette a "B" szerver IP-jét kell beállítani. Amúgy gyere hivatalos syslog-ng levelezési listára (sajna csak angolul van) ott hamarabb is kaphatsz válaszokat, meg többen is vagyunk: https://lists.balabit.hu/mailman/listinfo/syslog-ng

Attila írta...

Üdv!
Köszönöm a választ,először "B" server ip címével próbáltam:
destination d_online
{
tcp("b_server_ip" port(514)) );
};
ettől függetlenül,csak a "Syslog connection established;" kerül be a fileba+netstattal látszik,hogy a kapcsolat létrejön:
tcp 0 0 b_server_ip_címe:514 a_server_ip_címe:42058 established
Üdv:zoltán

Höltzl Péter írta...

kmmm, meg kellene nézni pontosan mi is történik. pzolee írt erről egy érdekeset itt: http://pzolee.blogs.balabit.hu/2010/01/syslog-ng-hibakereses.html

Megjegyzés küldése