blog.bartlweb - a technologist's external brain

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>.

Dieser Artikel hat Dir deinen Tag gerettet?

... und mühevolles Probieren, Recherchieren und damit Stunden an Zeit gespart? Oder einfach nur Dein Problem gelöst?

Dann würde ich mich freuen, wenn Du meine Zeit für die Erstellung dieses Blogartikels mit einer kleinen Anerkennung honorierst:

Zahlung mit PayPal oder Kreditkarte.

Hinweis zur Verwendung

Die Übermittlung einer Zahlung ist eine persönliche Anerkennung Ihrerseits an den Entwickler (Christian Bartl, Privatperson). Eine Zahlung ist nicht zweckgebunden und es ist keine Gegenleistung zu erwarten. Bitte beachten Sie, dass für eine übermittelte Zahlung keine Quittung ausgestellt werden kann.

Über den Autor

Christian Bartl

Christian Bartl Requirements Engineer
& Solution Architect für Online und Mobile

Als Technologie-Enthusiast und begeisterter Programmierer entwickle ich in meiner Freizeit Websites, Software und IT-Lösungen, die mir selbst und anderen den Alltag vereinfachen.

mehr auf christian.bartl.me

Kommentare

  1. 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.

    kommentieren

Kommentar schreiben

Der hier angegebene Name wird gemeinsam mit deinem Kommentar auf der Website veröffentlicht.

Deine E-Mail-Adresse wird zur einmaligen Benachrichtigung bei Veröffentlichung des Kommentars genutzt.

Benachrichtigung per E-Mail über Antworten auf meinen Kommentar erhalten.

Bitte tippe die Zahlenkombination "5853" ein, nur dann kann ich deinen Kommentar entgegennehmen.

Bitte fülle dieses Feld nicht aus, nur dann kann ich deinen Kommentar entgegennehmen.