Ein Grafana Dashboard für Goetemp

Über mein kleines Projekt Goetemp habe ich hier schon öfter geschrieben. Seit nunmehr über sieben Jahren sammle ich Wetterdaten aus Göttingen und spiele damit herum.

In den vergangenen Tagen habe ich das Backend für die Simple JSON Datasource für Grafana implementiert. Damit ist es nun möglich die Daten auch in Grafana zu visualisieren. Zuerst hatte ich überlegt die Daten auch gleich in eine InfluxDB zu schreiben, aber die Implementierung des Backends für die Datasource war erheblich schneller realisiert.

Mehr dazu habe ich auf der Goetemp Webseite geschrieben. Hier kann auch das Dashboard heruntergeladen werden. Zum spielen mit dem Datenbestand habe ich einen Snapshot freigegeben:

Poodle und SSLv3 deaktivieren in Apache, Postfix und Dovecot

Nach Heartbleed und ShellShock nun also Poodle… In Apache ists die folgende Zeile:
SSLProtocol ALL -SSLv2 -SSLv3

In Postfix in der main.cf die folgenden:
smtpd_tls_mandatory_protocols = !SSLv2 !SSLv3
smtp_tls_mandatory_protocols = !SSLv2 !SSLv3
smtp_tls_protocols = !SSLv2, !SSLv3
smtpd_tls_protocols = !SSLv2 !SSLv3

und in Dovecot in conf.d/10-ssl.conf:
ssl_protocols = !SSLv2 !SSLv3

Danke an dieser Stelle an den guten Beitrag im Heinlein Support Blog mit dem Titel So deaktivieren Sie SSLv3 in Apache/Postfix/Dovecot (Poodle-Bug). Dort steht alles genau beschrieben und auch wie man es nach der Änderung testen kann.

HSTS – Was es ist, wie es funktioniert und wie man es in Apache einrichtet

HSTS steht für HTTP Strict Transport Security und ist ein HTTP-Header bei dem der Webserver dem anfragenden Browser mitteilt, das alle Verbindungen nur ueber SSL/TLS aufgebaut werden sollen.
HSTS soll „Man-in-the-middle“ Attacken abwehren oder erschweren. Das Angriffsszenario besteht darin, dass Nutzer in der Regel nie

https

in den Webbrowser eingeben, sondern immer nur

example.net

Die Weiterleitung von http:// zu https:// macht der Webserver. Das sieht dann zum Beispiel so aus:
ohne_hsts

Man kann sehen, dass die erste GET Anfrage mit einem HTTP 302 Weitergeleitet wird und die zweite dann ein 200 OK zurueck liefert. Der Webserver ist in diesem Fall so konfiguriert, das alles was per HTTP reinkommt, automatisch auf HTTPS umgeleitet wird:

<VirtualHost *:80>
        ServerAdmin webmaster@jan-von.de
        ServerName mail.jan-von.de
        DocumentRoot /var/www/empty
 
        RewriteEngine on
        RewriteCond %{HTTP:X-Forwarded-Proto} !https
        RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
 
        CustomLog /var/log/apache2/mail.jan-von.de-access.log combined
</VirtualHost>

Genau hier liegt auch das Problem. Man kann sich in einem fremden Netz befinden, zum Beispiel einem unbekannten oeffentichen WLAN, dort kann die HTTP Anfrage abgefangen und der HTTPS Aufruf auf einen alternativen Server weitergeleitet werden.

Hier kommt HSTS ins Spiel. Der Server teilt dem Webbrowser mit, dass er sich bitte fuer eine bestimmte Zeit (zum Beispiel ein Jahr) daran erinnern soll, das diese Webseite nur noch ueber HTTPS aufgerufen werden soll.

In Apache muss dafuer das Headers-Modul aktiviert sein:

a2enmod headers

und anschliessend fuegt man in den HTTPS vhost die folgende Zeile ein:

Header always set Strict-Transport-Security "max-age=31556926"

Der Parameter max-age wird in Sekunden gesetzt. 31556926 Sekunden sind 365 Tage. Ein weiterer Parameter den man optional noch mit Komma Semikolon separiert dahinter haengen kann ist includeSubDomains. Dafuer muss aber sichergestellt sein, dass auch alle Subdomains per HTTPS erreichbar sind.
Weiter muss man aufpassen, dass die entsprechenden vhosts auch die angegebene Zeit, also zum Beispiel ein Jahr lang per HTTPS erreichbar sind, ansonsten kann es zu Fehlermeldungen kommen.

Wenn man dann HSTS aktiviert hat und eine Webseite aufruft die es unterstuetzt, dann kann man schoen sehen, wie der Browser gleich HTTPS nimmt und gar nicht erst HTTP probiert.

mit_hsts

Weiteres zu dem Thema z.B. unter:

Howto: Nagios passive check through webproxy // NagiosProxySender

Ich moechte diesen Blogeintrag mit einer Graphik beginnen um die Ausgangsstellung besser aufzeigen zu koennen:

Mein Problem ist, dass ich mit Nagios den Server 1 ueberwachen moechte, der hinter einem Webproxy sitzt. Ich kann von aussen nicht aktiv per NRPE vom Server pullen, und passiv mit NSCA pushen funktioniert auch nicht, da es nicht durch den Webproxy geht. Als Loesungsansatz habe ich mich dann ein bisschen mit NPA auseinandergesetzt, bin aber zu der Ueberzeugung gekommen, dass es fuer das was ich eigentlich machen moechte zu gross und zu kompliziert ist.

Fragen, die ich mit einem bash-Skript nicht beantworten kann, versuche ich oft mit einem PHP-Skript zu loesen. Auch dieses mal ist es mir wieder gelungen. Das NagiosProxySender Skript erwartet drei Parameter:

  1. -h: Den in Nagios definierten Host fuer den ein Service aktualisiert werden soll
  2. -s: Den in Nagios definierten Service der aktualisiert werden soll
  3. -c: Den Pfad zu dem lokalen Nagios-Plugin, dass ausgefuehrt werden soll inkl. aller Parameter

Weiter muessen in dem NagiosProxySender Skript verschiedene Konfigurationseinstellungen gemacht werden. Dieses sind IP und Port von dem Webproxy, die komplette URL zu dem Nagios cmd.cgi-Skript sowie die HTTP-Authentifizierungsdaten um an das cmd.cgi-Skript heranzukommen. Das war es dann eigentlich auch schon. Wenn auf dem Nagios-Server die passiven Checks eingerichtet sind kann es losgehen.

Ich persoenlich habe mir jeden Aufruf in ein eigenes Bash-Skript gepackt, da ich dadurch flexibler bin. Zur Veranschaulichung hier drei Beispiele. Das erste uebermittelt den Updatestatus eines debianbasierten Systems. Das zweite prueft wann eine Logdatei zuletzt geaendert wurde und gibt Warnungen aus wenn es zu lange in der Vergangenheit liegt. Der dritte Aufruf ueberprueft ob auf einem Host beim Aufruf einer URL der HTTP-Code 200 zurueckgegeben wird und auf der Seite ein bestimmter String zu finden ist. Reagiert der Server zu traege gibt es ebenfalls Meldungen.

apt.sh

#!/bin/bash
 
/usr/bin/php /opt/skripte/nagios/nps.php -h myHost -s UPDATE -c "/usr/lib/nagios/plugins/check_apt"

log.sh

#!/bin/bash
 
/usr/bin/php /opt/skripte/nagios/nps.php -h myHost -s LOG -c "/usr/lib/nagios/plugins/check_file -w 300 -c 900 -f /var/log/myLog-$(date +%Y%m).log"

http.sh

#!/bin/bash
 
/usr/bin/php /opt/skripte/nagios/nps.php -h myHost -s HTTP -c "/usr/lib/nagios/plugins/check_http -H 1.2.3.4 -u http://www.example.net/my/page.html -e \"HTTP/1.1 200\" -s \"foobar \" -w 10 -c 20"

All diese Skripte rufe ich in den von mir gewuenschten Intervallen mit cron auf. Dafuer habe ich mir die Datei /etc/cron.d/nagios-passive angelegt:

#
# Regular cron jobs for the nagios passive checks
#
 
1          8,16         * * *   user    /opt/skripte/nagios/apt.sh
1,15,30,45 *            * * *   user    /opt/skripte/nagios/log.sh
1,15,30,45 *            * * *   user    /opt/skripte/nagios/http.sh

Zu guter letzt natuerlich das NagiosProxySender Skript (nps.php):

<?php
 
/***
 * Name:	Nagios Proxy Sender
 *
 * Description:	This script sends the output of a Nagios plugin through 
 *              a webproxy to the Nagios server using the cmd.cgi.
 *
 * Parameter:	-h:  Host name specified in Nagios that you want to update
 *		-s:  Service name of the host that you want to update
 *		-c:  Nagios plugin that you would like to execute with all 
 *                   parameters
 *
 *
 * Usage:	php nps.php -h myHost -s SERVICE -c "/usr/lib/nagios/plugins/check_dummy 0 foo"
 *
 *
 * Changelog:	2012-02-02 - initial Release  // Jan Toenjes <jan.toenjes@intranda.com>
 *
 ***/
 
 
 
 
/***
 * Please define your settings in this section 
 ***/
$baseurl = 'http://www.example.net/nagios/cgi-bin/cmd.cgi';	// set url to nagios cmd.cgi script
$http_username = 'username';					// set username for http authentication
$http_password = 'password';				        // set password for http authentication
 
$proxy_host = 'webproxy';					// set proxy hostname or ip address here
$proxy_port = '8080';						// set proxy port here
 
$verbose = 0; 							// set to 1 if you want some output
 
 
 
 
/***
 * Get commands passed as arguments to this script and give error message
 * if something seems to be wrong... 
 ***/
$options = getopt("h:s:c:");
if (!is_array($options) ) {
	print "There was a problem reading in the options.\n\n";
	exit(1);
}
 
if (count($options) != "3") {
	print "You need to specify the following parameters: \n
  -h:   Host name specified in Nagios that you want to update
  -s:   Service name of the host that you want to update
  -c:   Nagios plugin that you would like to execute \n\n";
	exit(2);
} 
if ($verbose == 1) { print_r($options); }
 
$host = trim($options['h']);
$service = trim($options['s']);
$check = trim($options['c']);
 
 
 
 
/***
 * Perform actual Nagios check and give error message
 * if the return code is not a valid Nagios return code
 ***/
exec("$check 2>&1", $output, $returnCode);
if ($returnCode != "0" && $returnCode != "1" && $returnCode !="2" && $returnCode != "3") {
	print "There was a problem running the Nagios check. Please check:
	Output: " . $output[0] . "
	Return Code: $returnCode\n\n";
	exit(3);
}
 
$plugin_state = $returnCode;
$plugin_output = urlencode($output[0]);
 
if ($verbose == 1) { print "plugin_state = $returnCode \n"; print "plugin_output = $output[0] \n"; }
 
 
 
 
/***
 * Create GET URL to pass the information to Nagios
 ***/
$url = $baseurl . "?cmd_typ=30&cmd_mod=2&host=$host&service=$service&plugin_state=$plugin_state&plugin_output=$plugin_output&btnSubmit=Commit";
 
 
 
 
/***
 * Trigger the GET URL using the provided proxy and HTTP Authentification information
 ***/
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 0);
curl_setopt($ch, CURLOPT_PROXY, "$proxy_host:$proxy_port");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST,'GET');
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, $http_username . ":" . $http_password);
$curl_output = curl_exec ($ch);
$http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
 
 
 
 
/***
 * Success and error handling
 ***/
if ($http_status == "200") {
	print "Success: The output was sent to Nagios successfully!\n\n";
}
elseif ($http_status == "0") {
	print "Error: Nothing was sent to the Nagios server. Please check your proxy settings.\n\n";
	exit(4);
}
else {
	print "Error: HTTP-Code $http_status received. Please check the given information.\n\n";
	if ($verbose == 1 ) { print_r($curl_output); }
	exit(5);
}
?>