Server-Notfallwartung mittels IPMI über Webinterface auf OpenWrt-Router
Mein Server läuft und läuft, außer ich bin gerade nicht zu Hause, dann hängt er sich aus unerklärlichen Gründen ab und zu auf. Zuverlässiger im Dauerbetrieb ist da schon mein OpenWrt-Router. Darum nutze ich diesen, um dort ein zusätzliches Webinterface für das Absetzen eines IPMI-Befehls zum Neustart des Servers (siehe: Server über IPMI mithilfe von ipmitool fernsteuern), laufen zu lassen. Dazu habe ich unter OpenWrt PHP installiert und einen zusätzlichen Host inkl. Passwortschutz im Webserver eingerichtet, sowie ein kleines PHP-Skript erstellt.
uhttpd konfigurieren
Umstellen des Zugriffs auf HTTPS
Zunächst habe ich uhttpd um die Fähigkeit von SSL-gesicherten Verbindungen mittels HTTPS erweitert und dabei auch gleich den Zugriff auf das Konfigurationsinterface (Luci) auf HTTPS umgestellt.
Dazu wird zunächst das Paket luci-ssl installiert, das sich um die automatische Konfiguration bzw. Erstellung der notwendigen Zertifikate kümmert.
opkg install luci-ssl
Danach muss uhttpd umkonfiguriert werden. Die Konfigurationsdatei liegt unter /etc/config/uhttpd. Unter dem config-Abschnitt main muss listen_https auf den Port 443 umgestellt werden, bzw. die entsprechenden bereits durch das installierte Paket luci-ssl eingefügten Code-Zeilen auskommentiert werden. Zusätzlich habe ich den Zugriff auf das Webinterface durch Angabe der IP-Adresse des Routers auf den Zugriff aus dem internen Netzwerk beschränkt und somit zusätzlich abgesichert.
config uhttpd main
# HTTP listen addresses, multiple allowed
# list listen_http 0.0.0.0:80
# list listen_http [::]:80
# HTTPS listen addresses, multiple allowed
list listen_https 192.168.0.1:443
# list listen_https [::]:443
Sämtliche Änderungen an der Konfigurationsdatei müssen mit dem folgenden Befehl gesichert bzw. bestätigt werden:
uci commit uhttpd
Die Änderungen werden erst nach dem Neustart des Webservers wirksam.
/etc/init.d/uhttpd restart
Einrichten des Hosts
In derselben Konfigurationsdatei können wir auch unseren neuen Host eintragen, der dann über einen eigenen Port erreichbar ist. Die folgende Konfiguration enthält bereits die Einbindung von PHP und des Passwortschutzes. Beides wird im nachfolgenden Kapitel näher erörtert. Fügen Sie den folgenden Code an das Ende der Konfigurationsdatei /etc/config/uhttpd an. Als Root-Verzeichnis für die Dateien habe ich das Verzeichnis /www2 erstellt.
config uhttpd www2
list listen_https 0.0.0.0:8080
option home /www2
option cert /etc/uhttpd.crt
option key /etc/uhttpd.key
option index_page index.php
list interpreter ".php=/usr/bin/php-cgi"
option realm Authentification required
option config /etc/httpd-www2.conf
Wie nach allen Änderungen am Webserver muss die Konfiguration wieder gesichert und der Server neu gestartet werden.
Einrichten von PHP
Um PHP zu aktivieren, muss dieses nicht nur in die Konfiguration von uhttpd aufgenommen, sondern zunächst auch die entsprechenden Pakete installiert werden.
opkg install php5
opkg install php5-cli
Beim ersten Versuch auf die Seite zuzugreifen und eine PHP-Datei auszuführen habe ich als Rückgabe im Browser eine leere Seite mit folgendem Fehler erhalten
No input file specified.
Um dieses Problem zu beheben, muss die Konfiguration von PHP in der Datei /etc/php.ini angepasst werden. Der Wert von doc_root muss auf unser Root-Verzeichnis zeigen, also den Wert /www2 erhalten und die Zeile cgi.force_redirect = 0 muss auskommentiert werden.
Einrichten des Passwortschutzes
Die Basiskonfiguration für den Passwortschutz haben wir bereits in der uhttpd-Konfiguration erledigt. Jetzt muss noch eine Datei mit dem gewünschten Benutzernamen und Passwort erstellt werden. Dazu erstellen wir die Datei /etc/httpd-www2.conf mit folgendem Inhalt:
/:<Benutzername>:<Passwort-Hash>
Den notwendigen Passwort-Hash erzeugen wir mit dem folgenden Befehl:
uhttpd -m <password>
PHP-Skript
Für die einfache Ausführung der Verwaltungsbefehle mittels IPMI habe ich ein kleines PHP-Skript erstellt. Dieses setzt das OpenSource-Tool ipmitool voraus, das sich über folgenden Befehl installieren lässt:
opkg install ipmitool
Danach können wir das unten stehende PHP-Skript unter /www2/index.php ablegen und am Anfang der Datei die Konfiguration entsprechend unseres Setups anpassen. Alle Befehle, die zu einer Aktion führen, sind zusätzlich durch die Abfrage eines PINs geschützt.
<?php
$config = array(
'host' => '192.168.0.10',
'username' => 'user',
'password' => 'password',
'ipmitool' => '/usr/sbin/ipmitool',
'securePin' => '596a96cc7bf9108cd896f33c44aedc8a' //md5 hash of pin
);
$commandPrefix = $config['ipmitool'] . ' -H ' . $config['host'] . ' -U ' . $config['username'] . ' -P ' . $config['password'];
$commands = array(
'status' => array(
'title' => 'server status',
'command' => 'chassis status',
'confirm' => false
),
'sensors' => array(
'title' => 'server sensors',
'command' => 'sdr elist full',
'confirm' => false
),
'reset' => array(
'title' => '>> server reset <<',
'command' => 'power reset',
'confirm' => true
),
'cycle' => array(
'title' => '> server cycle <',
'command' => 'power cycle',
'confirm' => true
),
'soft' => array(
'title' => '(server graceful shutdown)',
'command' => 'power soft',
'confirm' => true
),
'off' => array(
'title' => '(server off)',
'command' => 'power off',
'confirm' => true
),
'on' => array(
'title' => '(server on)',
'command' => 'power on',
'confirm' => true
),
);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Fernwartung</title>
</head>
<body>
<h1>Fernwartung</h1>
<?php foreach($commands as $key => $val) { ?>
<h2><?php echo htmlspecialchars($val['title']); ?></h2>
<form action="." method="post" onsubmit="document.getElementById('securePin-<?php echo htmlspecialchars($key); ?>').value=prompt('Enter the secure pin to execute the command:', '');">
<fieldset>
<input type="submit" name="<?php echo htmlspecialchars($key); ?>" value="<?php echo htmlspecialchars($key); ?>" <?php if($val['confirm']) { echo 'onclick="return confirm(\'Do you want to execute ' . htmlspecialchars($val['title']) . '\')"'; } ?>" />
<input type="hidden" id="securePin-<?php echo htmlspecialchars($key); ?>" name="secure" value="" />
</fieldset>
</form>
<?php
if(isset($_POST[$key])) {
if(isset($_POST['secure'])) {
if(md5($_POST['secure']) == $config['securePin']) {
exec($commandPrefix . ' ' . $val['command'], $output);
echo '<textarea name="textarea" rows="10" cols="80">' . implode("\n", $output). '</textarea>';
} else {
echo '<input type="text" readonly="readonly" value="Secure pin not accepted." name="text">';
}
} else {
echo '<input type="text" readonly="readonly" value="Provide secure pin to execute the command." name="text">';
}
}
?>
<?php } ?>
</body>
</html>
Tipp:
Um Textdateien über die Kommandozeile komfortabel zu editieren nutze ich meist mcedit. Dieser steht unter OpenWrt nach der Installation des Pakets opkg install mc zu Verfügung. Einziger Unterschied zu den gängigen Linux-Distributionen: Der Aufruf über den Alias mcedit funktioniert nicht, sondern nur die Langform mc -e <dateiname>.
Für OpenWrt Chaos Calmer 15.05 fehlt ipmitool im Repository und kann daher nicht installiert werden. Über eine Lösung dafür wäre ich sehr dankbar.