Mini-How-To: BusyBox-httpd als externer Webserver

Ach ja, meine Güte, so intensiv habe ich nicht getestet. Der IE ist etwas toleranter gegenüber fehlerhaften HTTP-Responses, d.h. wenn die Header fehlen. Zumindest der Content-Type-Header sollte aber da sein, sonst schmollen Opera und Firefox. Lauf RFC ist auch jede Header-Zeile mit CR+LF abzuschließen, nicht mit einfachem Zeilenvorschub (LF). Dann noch einmal CR+LF als Separator zum eigentlichen Seiteninhalt (dort sind die Zeilenenden dann egal), das war's. Also so:

Code:
#!/bin/sh

[COLOR="Blue"][B]echo -en "Content-Type: text/html\r\n\r\n"[/B][/COLOR]
cat << EOF
...
EOF

P.S.: Das ist mit den beiden Zwischendateien bei Dir etwas umständlich, das würde auch einfacher gehen. Aber wenn es funktioniert, laß es so. Du hast hoffentlich keinen Riesen-Traffic zu erwarten auf Deiner Seite.
 
Du hast schon recht, das eleganteste ist es nicht, aber das schnellste, was mit in dem Moment eingefallen ist, hatte auch nicht so viel Zeit.
Hast du noch nen kurzen Tipp, wie man es besser machen könnte?

edit:
so hab es jetzt so umgeschrieben, dass die ls ausgabe direkt an awk weitergeleitet wird und keine temp-Dateien erzeugt werden.
Code:
#!/bin/sh

echo -en "Content-Type: text/html\r\n\r\n"
cat << EOF
<html>
  <head>
    <title>Index of ${QUERY_STRING}</title>
  </head>
  <body>
    <h2>Index of ${QUERY_STRING}</h2>
    <table cellspacing=2 width="100%" border="0">
	<tr><td width="300">Name</td><td width="180">Last modified</td><td width="60">Size</td><td></td></tr>
	<tr><td colspan="4"><hr></td><tr>
	<tr><td colspan="4">$(
	exec 2>/dev/null
        [ "$QUERY_STRING" == "/" ] || echo '<a href="..">..</a>'
	)</td><tr>$(

	ls -lLhep ../${QUERY_STRING} | grep -v cgi-bin | grep -e '^d' | awk '{ #Verzeichnisse anzeigen
	i=index($0,$11)
	name=substr($0,i)
	print "<tr><td><a href=\""name"\">"name"</a></td><td>"$8"-"$7"-"$10" "$9"</td><td>---</td><td></td></tr>"
	}'
	
	ls -lLhep ../${QUERY_STRING} | grep -v cgi-bin | grep -ve '^d' | awk '{ #Datein anzeigen
	i=index($0,$11)
	name=substr($0,i)
	print "<tr><td><a href=\""name"\">"name"</a></td><td>"$8"-"$7"-"$10" "$9"</td><td>"$5"</td><td></td></tr>"
	}'

        )<tr><td colspan="4"><hr></td><tr>
      </table>
  </body>
</html>
EOF
 

Anhänge

  • pic1.JPG
    pic1.JPG
    32.4 KB · Aufrufe: 94
  • pic2.JPG
    pic2.JPG
    25.5 KB · Aufrufe: 52
Zuletzt bearbeitet:
Hier ist noch eine Variante mit folgenden Merkmalen:
  • nur eine (lange) Verarbeitungs-Pipe für die Ausgabe von ls, keine zwei Aufrufe mehr
  • trotzdem Verzeichnisse zuerst angezeigt durch spezielle Sortierfunktion
  • Proportional-Schrift mit ausgerichtetem Datum (einstellige Tageszahlen)
  • Tabelle mit flexiblen Spaltenbreiten (keine festen Pixel-Breiten)
  • keine Fehlformatierung (Jahreszahl rutscht vor den Dateinamen) bei Character Devices, z.B. bei Anzeige von /var/flash
Der Code sieht so aus:
Code:
#!/bin/sh

echo -en "Content-Type: text/html\r\n\r\n"
cat << EOF
<html>
  <head>
    <title>Index of ${QUERY_STRING}</title>
  </head>
  <body>
    <h2>Index of ${QUERY_STRING}</h2>
    <table cellspacing="2" border="0">
      <tr align="left"><th>Name</th><th>&nbsp;&nbsp;Last modified</th><th>&nbsp;&nbsp;Size</th></tr>
      <tr><td colspan="3"><hr></td></tr>
      <tr><td>$([ "$QUERY_STRING" == "/" ] || echo '<a href="..">..</a>')</td></tr>
      $(
        exec 2>/dev/null
        date_format1="[A-Z][a-z]{2} [A-Z][a-z]{2} [ 123][0-9] [0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{4}"
        replace="<tr><td><tt><a href='\3'>\3<\/a><\tt><\/td><td><tt>\&nbsp;\&nbsp;\2<\tt><\/td><td align=right><tt>\&nbsp;\&nbsp;\1<\tt><\/td><\/tr>"
        date_format2="([A-Z][a-z]{2} [A-Z][a-z]{2} ) ([0-9] [0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{4})"
        ls -lLep ../${QUERY_STRING} \
          | ([ "$QUERY_STRING" == "/" ] && grep -v 'cgi-bin' || cat) \
          | awk '{printf("%5d %s\n", NR,$0)}' \
          | sed -r 's/^([0-9 ]+ d)/X \1/' \
          | sed -r 's/^([0-9 ]+)/Y \1/' \
          | sort \
          | sed -r 's/^([^ ]+ +){6}(.*)/\2/' \
          | sed -r 's/^[0-9]+(.*)\/$/---\1/' \
          | sed -r "s/^([-0-9, ]+) ($date_format1) +(.*)$/$replace/" \
          | sed -r "s/$date_format2/\1\&nbsp;\2/"
      )
    </table>
  </body>
</html>
EOF

Jetzt das Ganze nochmal mit Kommentaren, die aber nicht im Code enthalten sein dürfen, wenn man das Skript einsetzt, sie dienen nur der Erläuterung:
Code:
#!/bin/sh

[COLOR="Blue"]# standardkonformen HTTP-Header erzeugen[/COLOR]
echo -en "Content-Type: text/html\r\n\r\n"
cat << EOF
<html>
  <head>
    <title>Index of ${QUERY_STRING}</title>
  </head>
  <body>
    <h2>Index of ${QUERY_STRING}</h2>
    <table cellspacing="2" border="0">
      <tr align="left"><th>Name</th><th>&nbsp;&nbsp;Last modified</th><th>&nbsp;&nbsp;Size</th></tr>
      <tr><td colspan="3"><hr></td></tr>
      <tr><td>$([ "$QUERY_STRING" == "/" ] || echo '<a href="..">..</a>')</td></tr>
      $(
        [COLOR="Blue"]# alle Fehler ins Nirvana umleiten[/COLOR]
        exec 2>/dev/null
        [COLOR="Blue"]# Datumsformat 1 zum Finden in der Verzeichnisliste[/COLOR]
        date_format1="[A-Z][a-z]{2} [A-Z][a-z]{2} [ 123][0-9] [0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{4}"
        [COLOR="Blue"]# langer Ersetzungsausdruck (daher separat), der eine Tabellenzeile
        # generiert[/COLOR]
        replace="<tr><td><tt><a href='\3'>\3<\/a><\tt><\/td><td><tt>\&nbsp;\&nbsp;\2<\tt><\/td><td align=right><tt>\&nbsp;\&nbsp;\1<\tt><\/td><\/tr>"
        [COLOR="Blue"]# Datumsformat 2 zum Separieren eines führenden Leerzeichens bei der
        # Tageszahl (muß durch festes HTML-Leerzeichen &nbsp; ersetzt werden)[/COLOR]
        date_format2="([A-Z][a-z]{2} [A-Z][a-z]{2} ) ([0-9] [0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{4})"
        ls -lLep ../${QUERY_STRING} \
          [COLOR="Blue"]# im Wurzelverzeichnis "cgi-bin" herausfiltern[/COLOR]
          | ([ "$QUERY_STRING" == "/" ] && grep -v 'cgi-bin' || cat) \
          [COLOR="blue"]# Zeilen numerieren, damit Reihenfolge innerhalb der beiden Gruppen
          # (Verzeichnisse und der Rest) später erhalten bleibt beim Sortieren[/COLOR]
          | awk '{printf("%5d %s\n", NR,$0)}' \
          [COLOR="Blue"]# "X" vor Verzeichnisse setzen, "Y" vor den Rest ("X" < "Y")[/COLOR]
          | sed -r 's/^([0-9 ]+ d)/X \1/' \
          | sed -r 's/^([0-9 ]+)/Y \1/' \
          [COLOR="blue"]# Sortieren bewirkt Gruppierung der Einträge[/COLOR]
          | sort \
          [COLOR="blue"]# Sortierhilfen + nicht benötigte Spalten löschen[/COLOR]
          | sed -r 's/^([^ ]+ +){6}(.*)/\2/' \
          [COLOR="blue"]# Dateigrößen für Verzeichnisse durch "---" ersetzen[/COLOR]
          | sed -r 's/^[0-9]+(.*)\/$/---\1/' \
          [COLOR="blue"]# eine Tabellenzeile je Verzeichniseintrag erzeugen[/COLOR]
          | sed -r "s/^([-0-9, ]+) ($date_format1) +(.*)$/$replace/" \
          [COLOR="blue"]# Sonderfall führendes Leerzeichen bei Tageszahl im Datum[/COLOR]
          | sed -r "s/$date_format2/\1\&nbsp;\2/"
      )
    </table>
  </body>
</html>
EOF

In den Screenshots sieht man, daß auch ungewöhntliche Dateinamen, die Leerzeichen enthalten bzw. so ähnlich sind wie ein Datum, funktionieren (Abb. 1) und daß Character Devices korrekt angezeigt werden (Abb. 2).
 

Anhänge

  • dir_var_tmp.gif
    dir_var_tmp.gif
    5.8 KB · Aufrufe: 86
  • dir_var_flash.gif
    dir_var_flash.gif
    5.8 KB · Aufrufe: 66
Zuletzt bearbeitet:
sag mal bist du sicher, das du es richtig kopiert hast,

bei dem replace fehlt doch z.b. ein " bzw der schluss des <td> tags und <tr> tags mit der Dateigröße?
daraus resultiert ein fehler in der nächsten zeile -> denn bei mir zeigt es nix an. :)

edit: filters du eigentlich mit absicht cgi-bin nicht mehr raus?
 
Zuletzt bearbeitet:
Die lange Replace-Zeile hatte ich aus dem Terminal-Fenster anstatt aus einem Editor kopiert, deswegen war sie abgeschnitten. Danke für den Hinweis, mein Fehler. Ist oben korrigiert. Den Filter für cgi-bin hatte ich schlicht vergessen, auch der ist inzwischen wieder drin, aber beschränkt aufs Wurzelverzeichnis. Falls woanders "cgi-bin" auftaucht als Verzeichnis- oder Dateiname, wird nicht gefiltert.

Zusätzlicher Tip: Wenn über einen Root-Link aufs ganze Verzeichnissystem der Box navigiert wird und man z.B. unter /usr/www oder /usr/mww weiter navigiert, bekommt man leere Seiten angezeigt bei manchen Unterverzeichnissen, z.B. all oder cgi-bin. Das liegt daran, daß in diesen Verzeichnissen auch wieder index.html oder index.cgi gefunden und entsprechend interpretiert werden, d.h. dort wird nicht unser Skript ausgeführt, sondern das entsprechende, welches sich dort befindet. Das ist also kein Bug, sondern schlicht eine technische Beschränkung dieser simplen Vorgehensweise. Würden diese Index-Dateien in unserem Kontext etwas Auswertbares liefern, würde auch etwas angezeigt. Im Quelltext der "leeren" Seiten sieht man, daß durchaus etwas zurückgeliefert wird.

Edit: Ich habe weiter oben gar nicht erklärt, warum ich statt Awk außer für die Numerierung nur Sed eingesetzt habe. Ganz einfach: Mit Regex-Ersetzung kenne ich mich gut aus, mit der Awk-Syntax gar nicht.
 
Zuletzt bearbeitet:
super danke für as update.

Ich hatte awk nur genommen, weil ich als erstes darüber gestolpert bin und eigentlich wirklich ein neuling in der shell script programmierung bin.
Da es bei Netzmafia mit angerissen war hab ich es mal ausprobiert. :)
Kann man dein script eigentlich auch so abändern, so man die Größe einer Datei auch verständig darstellen kann, also z.b. die Angabe die bei ls mit der Option -h erzeugt wird.
Dafür müsste man wahrscheinlich den Regulärenausdruck etwas ändern oder?
 
Könnte man das, was ich als Howto geschrieben habe nicht in das Webinterface des ds-mod als Konfigurationsmöglichkeit einbauen?

Müsste ja eigentlich nicht viel drinstehen:

1. Freizugebendes Verzeichnis
2. Interner Port des (zusätzlichen) Webservers
3. Externer Port des (zusäzlichen) Webservers

Die Freigabe des (externen) Portes und die Umleitung auf die imaginäre IP kann man sicherlich per Script einstellen, oder?

Ich habe keine Ahnung ob das geht und ob sowas überhaupt gewünscht ist, aber als Idee fände ich das recht brauchbar.
 
Das geht, aber es ist eher als Add-On sinnvoll. Normalerweise wird man einen Router nicht als Webserver verwenden wollen, und wer es doch will, hat besondere Bedürfnisse. Der eine will SSL, der andere unbedingt Apache, ein Dritter PHP und was weiß ich noch? Das soll jeder für sich machen, es ist ja nicht so schwierig.

@Matze: Na ja, weiter oben siehst Du doch schon die andere Variante, die noch die "L"-Option mit im ls hat, um die Größen anders darzustellen. Klar, den Ersetzungsausdruck anpassen wirst Du müssen, aber da mir persönlich es nicht gefällt, wenn unterschiedliche Größenordnungen (Byte, Kilobyte, Megabyte) untereinander sortiert da stehen, überlasse ich es Dir. Sonst sind am Ende 95% der Skriptanteile in Deinem Tutorial von mir. (Edit: Moment mal, das Tutorial ist ja von Spooks.) Was ich sinnvoller finden würde, wären entweder immer nur Bytes, KB oder MB, am liebsten für mich Bytes. Man könnte Tausender-Trennzeichen einfügen, dann würde man die Größenordnung auch schnell erkennen.
 
Zuletzt bearbeitet:
@ kriegaex (zum ersten Teil der Aussage): Ja, da hast du eigentlich recht. Ich find so einen Mini Webserver halt praktisch um z.B. Fotos mal eben ins's Netz zu stellen. Eine "dicke" homepage würde ich auch nicht hosten wollen.
 
Hallo zusammen,

der Busybox-httpd läuft seit einiger Zeit recht stabil, nun kommt aber noch die Anforderung nach einer weiteren Webseite auf. Gibt es die möglichkeiten mit virtuellen Hosts zu arbeiten oder muss ich dann auf einen anderen Webserver (Apache) wechseln? Ich benötige kein PHP oä..
 
Eine solche Konfig hatte ich für den httpd noch nciht gesehen.
 
@nick81: dafür ist es eben busybox, um minimalen Anforderungen zu genügen. Höchstens kann man sich vorstellen mehrere Instanzen von httpd an unterschiedlichen Ports laufen zu haben, mehr aber nicht. Und letztendlich ist die arme Box nicht dafür da, um als Webserver im großen Still zu dienen. Hast du denn überhaupt eine feste IP, oder willst du es über dyndns laufen lassen?

Also wenn es dir darum geht Webspace mit mehreren vhosts zu haben und du keine günstigen Angebote dafür findest, gerne PN an mich. Da lässt sich schon was machen.

Ansonsten eben Apache nehmen. Ich weiß aber nicht, ob es für die Box nicht etwas übertrieben ist.

MfG
 
Darf ich mich (als "Wiki-Beauftragter" ;)) mal kurz einmischen: Hat denn schon jemand eine Übertragung ins Wiki im Visier - oder soll das Resultat, wie Alexander andeutete, in ein Paket übertragen werden (dann würde ein Wiki-Artikel zum jetzigen Zeitpunkt wenig Sinn machen, da er mit dem Paket wieder überflüssig würde)?

Gruß,
Izzy.
 
bis jetzt hat noch keiner die umsetztung in ein Paket angefangen, soweit ich das weiß, denn der Hauptteil des Threads liegt auch schon ein Jahr zurück. Es wäre also wirklich nicht schlecht, wenn das seinen Weg ins Wiki findet.
 
geht es denn darum Verzeichnisse aufzulisten oder generell Server nach draußen frei geben? Wie sicher ist denn das Ganze? Im Beispiel von Alexander sieht man die komplette Verzeichnisstruktur der Box. Nach draußen und unverschlüsselt sollte man es nicht weitergeben. Aber ich glaube, das ist eher nur Beispiel. Bei dem httpd bleibt man doch zunächst in dem Verzeichnis, welches man freigegeben hat und kommt nicht höher. Oder sehe ich es falsch?

Als Paket realisieren könnte man es auf jeden Fall. Mit einem optionalen Listing und einem optionalen https über matrixtunnel.

Aber wie gesagt, bitte nicht vergessen: fritzbox bleibt erstmal fritzbox. Vieles läuft hier als root. Das sollte man nicht unterschätzen. Auf professionellen Servern mit Apache, php und mysql versucht wo es nur geht das Ausführen als root zu vermeiden, um den potentiellen Angreifer einzuschränken.

MfG
 
das Howto im ersten Posting geht, wenn ich mich richtig erinnere darum, wie man im allgemeinen den Busybox-httpd als Webserver laufen lassen kann.
Wie stabil der jetzt gegen das Hacken ist weiß ich nicht.
Er sollte es aber sein, solange man halt nur nen Verzeichnis, z.b. auf einem Stick frei gibt. Dieses wird dann wie eine Webpagestruktur mit den Unterordnern gehandhabt.

Ich habe damals zusätzlich zum einenfachen Webserver für eine kleine Benutzterverwaltung und ein DirectoryListing interessiert. Weil ich es als kleinen Dateiserver nutzen wollte. Alexander meinte dann, dass es diese Option nicht in der Config gibt, aber wenn es keine index.html gibt, würde der httpd nach einer index.cgi im cgi-bin-Ordner suchen darüber haben wir dann das Listing implementiert.

Die Bilder von Alexander sind nur ein Bsp. Ich persönlich nutze es immernoch als kleinen Fileserver für mich und Freunde, per ssl (stunnel) aber auch ohne.
Ich habe ein Verzeichnis auf dem Stick als Basis genommen. Solange man dort keinen link aufs Rootfs macht ist man auch im grünen Bereicht, aber in einem Käfig ist der httpd nicht gefangen, oder beschränkt, er würde also links folgen.


Das ganze als Paket zu machen, hängt davon ab, was man benötigt.
Will man nur den Webserver, braucht man ja nur 2 Felder mit Port und Verzeichnis. Will man zusätzlich noch benutzer über die Configseite müsste man sich schon mehr einfallen lassen. Wenn man das Listing auch noch configurieren möchte muss man die index.cgi mit in image packen beim build(nicht das thema) und dann beim starten des webservers an die richtige stelle packen unterhalb des Verzeichnisses.
 
@matze1985: Ich empfehle matrixtunnel anstatt stunnel. Es ist echt erstaunlich, wie klein das ist und trotzdem funktioniert.

Um zurück auf Posting #31 zu kommen. Da wäre doch wahrscheinlich eine Möglichkeit mit dem Reverse-Proxy. Ich gebe zu, ich war derjenige, der vor Paar Wochen diese Frage zu Reverse-Proxy hier im Forum gestellt hat. Ich hatte es aber mangels Zeit bis jetzt noch nicht ausprobiert. Theoretisch würde es für 4-Level-Domains a-la subdomain.meinebox.dyndns.org realisierbar sein. Muss man aber noch genau gegen die Optionen checken... Und trotzdem verstehe ich den Sinn der Idee nicht. Für 1-2 vhosts würde es evtl. noch gehen, aber auch nicht mehr.

MfG
 
danke, ich werde es mal bei gelegenheit noch ausprobieren, habe bis jetzt halt immer mit stunnel gearbeitet, und da ich kein platzprobleme habe (ich lager seit jahr und tag selber per fwmod_custom auf USB aus) mir nie überlegungen gemacht.

zu #31:
Da hast du recht, der reverse-proxy der busybox wäre wohl die einzige configuration, die das erreichen könnte.
 
Hallo zusammen und danke für die Antworten.

Zu einigen hier genannten Fragen: Es sollen auch nur zwei Webseiten werden. Das soll über dyndns laufen (zusätzlich habe ich eine Lease-Time von einer Woche, also an der Erreichbarkeit soll es nicht scheitern :) ), zur besseren Übersicht wird halt noch eine Subdomain als weiterleitung eingerichtet (z.b. .de.vu). Der Port 80 ist von außen auf einen internen Port auf der zweiten IP der Fritzbox geforwarded. Somit geht auch keine zweite Instanz auf einem anderen Port.

Es sollen keine großen Webseiten sein. Wie schon geschrieben werden PHP oder andere Serverbelastende Tools nicht benötigt. Da ligt nur HTML mit ein paar Bildern. Zwar laufen die Bilder unter Flash, allerdings wird Flash komplett vom Client interpretiert und die FB wird nicht wirklich mehr belastet.

Was ist mit dem reverse-proxy gemeint?
 
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.