X-Powered-By entfernen

In vielen PHP Paketen ist leider per default die „Exposed“ Option eingeschaltet. Wenn dem so ist fügt PHP einen Header ein der die PHP Version ausgibt.

X-Powered-By: PHP/5.6.1

Ich halte zwar nichts davon Sicherheit durch verschweigen von etwas zu erzeugen, aber Infos rausbrüllen muss ich auch nicht unbedingt. Ich möchte also das der Header verschwindet. Dazu gibt es mehrere Möglichkeiten.

Weiterlesen

KVM VMs mit Bonding und VLANs und Cisco Switchen auf CentOS 6/7 bridgen

Wer große Rechner mit KVM und vielen VMs hat kommt vielleicht an einen Punkt an dem Ihm das Gigabit Interface nicht mehr reicht. Dann gibt es verschiedene Varianten die Bandbreite zu erhöhen.

Eine einfache Variante ist es auf ein 10 Gigabit Interface zu nutzen. Schnell einfach und schön, wenn man die Möglichkeit hat.

Alternativ kann man auch einzelne Gigabit Interfaces nutzen und die Rechner darauf verteilen. Das ist einfach und benötigt wenig Konfiguration, ist allerdings auch nur wenig flexibel und man muss immer aufpassen auf welchen Interface man einen Rechner anlegt.

Es gibt aber auch eine schicke Lösung für dieses Problem. Das Zusammenfassen von Interfacen. Dabei agieren <N> Interface wie ein einzelnes, erhöhen dabei aber die Gesamtbandbreite und sind untereinander Fehlertolerant. Ein entsprechendes Setup soll hier anhand von Cisco Switchen erläutert werden.

Weiterlesen

Zugriff auf das Filesystem innerhalb eines Xen Images

Hin und wieder kommt es leider vor, das ein Dateisystem innerhalb eines Xen Images beschädigt ist. Das kann recht problematisch werden, da man da ja nicht so einfach rankommt. Hier ein Weg wie man trotzdem noch was retten kann bzw. einen Filesystemcheck durchführen etc.:

  1. Mit kpartx -a <pfad zum image/imagename> das Image einbinden.
  2. Hat das Image einen LVM bei Punkt vier weitermachen.
  3. Hat das Image keinen LVM kann man nun via /dev/loop<device> auf die Platte zugreifen. Zum Abschluß noch Punkt 9 beachten.
  4. Bei einem Image mit LVM muss nun das System mit vgscannach neuen Devices durchsucht werden. Hat der LVM ein neues Device gefunden erhält man eine Ausgabe wie Found volume group „VolGroup00“ using metadata.
  5. Das gefundene Volume muss man nun mit vgchange -ay VolGroup00 aktivieren.
  6. Nun sind die einzelnen Partitionen unter /dev/Volgroup00/LogVol<Partitionsnummer> verfügbar.
  7. Filesystemcheck machen oder mounten: fsck.ext3 /dev/VolGroup00/LogVol00 -f   oder mount  /dev/VolGroup00/LogVol00 /mnt oder was immer man braucht.
  8. Wenn alle arbeiten abgeschlossen sind muss man dem LVM das Volume wieder wegnehmen. vgchange -an VolGroup00
  9. Nun noch das Image unmounten mit kpartx -d <pfad zum image/imagename>.

Da meistens was übles schiefgegangen ist, wenn man diese Anleitung sucht, wünsche ich allen Lesern viel Glück ;-).

 

 

Content Komprimierung mit dem Apache Tomcat und gzip

Ich hatte hier ja schon beschrieben, wie man Content direkt mit dem Apache Httpd komprimiert. Nun gibt es hin und wieder doch auch mal die Situation, das man einen Tomcat direkt am Netz hängen hat. Dieser soll natürlich auch seinen Content komprimieren und damit alle Vorteile bieten.

Hier nun was man eintragen muss, damit alles klappt:

In der server.xml sucht man den HTTP Connector:

<Connector port="8080" maxHttpHeaderSize="8192" strategy="ms"
 maxThreads="1024" minSpareThreads="25" maxSpareThreads="75"
 enableLookups="false" redirectPort="8443" acceptCount="100"
 connectionTimeout="20000" disableUploadTimeout="true"  server="Webserver"/>

Und fügt folgendes Hinzu:

compression="on"
compressionMinSize="2048"
noCompressionUserAgents="gozilla, traviata"
compressableMimeType="text/html,text/xml"

Anschließend sieht das ganze dann so aus:

<Connector port="8080" maxHttpHeaderSize="8192" strategy="ms"
 maxThreads="1024" minSpareThreads="25" maxSpareThreads="75"
 enableLookups="false" redirectPort="8443" acceptCount="100"
 connectionTimeout="20000" disableUploadTimeout="true"  server="Webserver"
 compression="on"
 compressionMinSize="2048"
 noCompressionUserAgents="gozilla, traviata"
 compressableMimeType="text/html,text/xml"/>

Und schon läuft der Tomcat mit Kompression.

Content Komprimierung mit mod_deflate und Apache 2

Warum soll ich meinen Content Komprimieren?

Hierfür gibt es einige Argumente:

  1. Verringerung der nötigen Bandbreite, Verkleinerung des Volumens der Seite
  2. Ggf. schneller Ladezeiten beim Nutzer
  3. Good Style ;-)

Tatsächlich ist es so, das heute viele Webseiten auf Komprimierung Ihrer Daten setzen, dies ist mit modernen CPUs und effektiven Modulen wie mod_deflate, selbst bei hochvolumigen Seiten, kein Problem mehr. Hiermit kann ohne großen Aufwand massiv Bandbreite gespart werden, da nahezu alle modernen Browser mit komprimierten Inhalten umgehen können. Nach meinen Erfahrungen kann man locker 10 bis 20% Traffic einsparen, aber auch hier ist das ganze natürlich abhängig von den lokalen Gegebenheiten.

Hier eine Beispielkonfiguration im Apache:

#Maximize Compression
DeflateCompressionLevel 9
<Location />
# Insert filter
SetOutputFilter DEFLATE

# Netscape 4.x has some problems…
BrowserMatch ^Mozilla/4 gzip-only-text/html

# Netscape 4.06-4.08 have some more problems
BrowserMatch ^Mozilla/4\.0[678] no-gzip

# MSIE masquerades as Netscape, but it is fine
# BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

# NOTE: Due to a bug in mod_setenvif up to Apache 2.0.48
# the above regex won’t work. You can use the following
# workaround to get the desired effect:
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

# Don’t compress images
SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png)$ no-gzip dont-vary

# Make sure proxies don’t deliver the wrong content
Header append Vary User-Agent env=!dont-vary

</Location>

Mit dem Parameter „DeflateCompressionLevel“ setzt man, wie bei gzip auch, die Stärke der Kompression. 9 ist das Maximum und 1 das schwächste. Dies kann man je nach Serverleistung variieren, wobei das ganze mit mod_deflate ziemlich effizient ist und ich auch mit einem 9 nur einen sehr geringen Anstieg der Serverlast hatte (Server mit mehreren Million Zugriffen/Tag). Der Rest der Konfiguration ist 1 zu 1 aus dem Apache Handbuch kopiert und ich hatte bisher nie Probleme damit.


Date Wed, 20 Jan 2010 08:12:01 GMT
Content-Type text/html;charset=ISO-8859-15
Vary Accept-Encoding,User-Agent
Content-Encoding gzip
Content-Length 6389
Xonnection close

Hier seht Ihr nochmal wie das dann im Header, welchen Ihr mit Firebug oder ähnlichem sehen könnt, anschließend aussieht. Content-Encoding ist gzip, das Kompressionslevel kann man hier nicht sehen, dieses wird im Header nicht angegeben. Ihr könnt allerdings mal mit dem CompressionLevel Paramter rumspielen und euch dann die Content-Length anschauen.

Hier noch der Link zum Apache Manual

Expire Header mit mod_expire im Apache 2

Wozu Expire Header?

Oft kommt es vor, das man Daten über einen Webserver ausliefert, welche lange Zeit konsistent bleiben, Logos, bestimmte Grafiken etc. Wenn man solche Bestandteile auf seiner Webseite hat, sollte man diese mit einem Expire Header versehen. Der Expire Header bewirkt dabei, das die statischen Bestandteile der Seite bei (den meisten) Nutzern nur einmal heruntergeladen werden und bis zum Ende der Expiration im Cache des Browser gehalten werden. Besucht der Anwender innerhalb der Expiration Zeit die Webseite nochmals, werden die statischen Bestandteile aus dem lokalem Cache des Benutzers geladen und müssen somit nicht erneut heruntergeladen werden. Dies bietet zwei Vorteile, zum einen spart man damit Bandbreite und Datenvolumen zum anderen ist die Ausgabe aus dem Cache, des Browsers, in der Regel deutlich schneller als das Herunterladen des Contents. Bei der Verbreitung von Breitbandanschlüßen (zu mindestens in Europa) kommt dem Argument des schnelleren Seitenaufbaus oft mehr Bedeutung zu als der genutzten Bandbreite, wobei dies natürlich auch stark vom jeweiligen Angebot abhängt.

Hin und wieder hat man den Bedarf Expire Header von bestimmten Dateitypen zu setzen, entweder weil die dahinterliegende Applikation dies nicht richtig kann, oder weil statischer Content direkt über den Apache ausgeliefert werden soll. Hierzu kann man das Modul mod_expire des Apache’s verwenden.

Hier ein Beispiel:

#set expire header for the static directorys to 7 days
<Directory /img/>
ExpiresActive On
ExpiresDefault „access plus 7 days“
</Directory>

In diesem Beispiel wird ein Expire Header für von 7 Tagen (bei wirklich statischem Content zu kurz) auf das Verzeichnis /img gesetzt.

Sobald das Modul aktiv ist und erfolgreich Arbeitet, kann man sich z.B. mit Firebug anschauen ob die Änderungen erfolgreich waren:
Date Wed, 20 Jan 2010 07:22:58 GMT
Server Apache
Last-Modified Wed, 08 Oct 2008 08:36:30 GMT
Etag "eb039a-33-458b9d013df80"
Accept-Ranges bytes
Content-Length 51
Cache-Control max-age=604800
Expires Wed, 27 Jan 2010 07:22:58 GMT
Content-Type image/gif

Hier sieht man nun sehr schön wie im Header die entsprechenden Expire Informationen gesetzt werden.

Hierzu gehören sowohl das Feld „Last-Modified“, „Cache-Control“ und natürlich „Expires“.

Eine Ramdisk unter Linux erstellen und verwenden

Eine Ramdisk erstellen

Hier beschreibe ich wie man unter den gängigen Linux Distributionen eine Ramdisk erstellt. Das kann an vielen Stellen ganz nützlich sein.

Was ist eine Ramdisk?

Eine Ramdisk ist ein Teil des flüchtigen Arbeitsspeichers (RAM –> Random Access Memory), auf welchen man wie auf eine Festplatte zugreift. Großer Vorteil der Ramdisk ist, das diese erheblich schneller ist als eine Festplatte. Während man von modernen Festplatten bis ca. 150 MB/s lesen kann, kann dies bei einer Ramdisk leicht mit über 1 GB/s passieren. Großer Nachteil an einer Ramdisk ist, das der Inhalt in einem flüchtigen Speicher liegt und bei jedem Reboot oder bei jedem abschalten der Maschine verloren geht. D.h. die Ramdisk muss bei jedem starten neu „beladen“ werden bzw. durch temporären Inhalt versorgt werden.

Wie erstellt man eine Ramdisk

Ein Ramdisk kann man heute unter jeder aktuellen Linux Distribution erstellen. Der Support für Ramdisks ist im Kernel integriert. Ich beschreibe hier alle Schritte die nötig sind um eine Ramdisk zu erstellen und diese als „Plattenersatz“ zu verwenden.

Kerneloptionen konfigurieren

Zum Erstellen einer Ramdisk muss man dem Kernel eine Option mitgeben diese zu erstellen. Das tut man in der Regel in seinem Bootloader. Auf dem meisten gängigen Distributionen ist dies Grub. Die Konfigurationsdatei befindet sich bei den meisten Distributionen unter /boot/grub/menu.lst. In dieser ist der zu bootende Kernel aufgeführt und seine Parameter. Erkennen kann man das an dem vorgestelltem Wort kernel. Wir fügen an diese Zeile einfach den Parameter ramdisk_size=xxxxxx an, wobei xxxxxxx durch eine Anzahl 1024KB Blöcke ersetzt wird. D.h. wenn ich 10 Megabyte Ramdisk haben möchte setze ich den Wert auf 10 * 1024 = 10240. Damit erhalte ich eine 10 MB Ramdisk. 300 MB Ramdisk sind dann entsprechend 307200. Ein Beispiel einer Ramdisk mit 976,5625 MB .

# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE:  You have a /boot partition.  This means that
#          all kernel and initrd paths are relative to /boot/, eg.
#          root (hd0,0)
#          kernel /vmlinuz-version ro root=/dev/sda2
#          initrd /initrd-version.img
#boot=/dev/sda
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.18-53.1.21.el5)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-53.1.21.el5 ro root=LABEL=/ ramdisk_size=1000000
        initrd /initrd-2.6.18-53.1.21.el5.img

Ist der Parameter hinzugefügt worden muss gebootet werden. Damit der Kernel die Option bei Starten auswerten kann. Im Anschluß an den boot Vorgang kann man sich mit dem Befehl dmesg das Log des Kernels anschauen und folgendes entdecken:

Diese Ausgabe kommt nicht bei jeder Distribution …

Kernel command line: ro root=LABEL=/ ramdisk_size=1000000

Diese Ausgabe sollte man aber immer sehen, die Zahlen beziehen sich auf das Beispiel mit der 976,5625 MB Ramdisk.

RAMDISK driver initialized: 16 RAM disks of 1000000K size 4096 blocksize

Das sagt uns das jetzt prinzipiell 16 RAM disks mit 1000000K große zur Verfügung stehen. Das ist ein bischen viel, weil 16 * 1000000 K = 15625 MB = 15.2587890625 GB. Zuviel für die meisten Rechner. Den Rechner den ich hier verwende hat auch nur 8 GB RAM. Also hätten wir ein Problem, da uns der RAM nicht reicht. Aber keine Angst, wir haben nun nur die Möglichkeit 16 Ramdisks in der größe verwendet, der Speicher wird erst dann verbraucht wenn wir diese auch tatsächlich nutzen. Ich benötige nur eine und hab damit noch genug ram frei.

Ramdisk nutzen

Nachdem wir nun erfolgreich die Ramdisk(s) initialisiert haben, können wir diese nun nutzen. Dazu müssen wir ein Dateisystem auf der Ramdisk erstellen, damit wir auch Dateien abspeichern können. Die Ramdisk steht uns unter einer Device Adresse zur Verfügung, ähnlich wie eine Festplatte. /dev/ram0 ist die erste Ramdisk in einem System /dev/ram1 die zweite und so weiter, in meinem Fall bis /dev/ram15, also die 16te Ramdisk. Ich brauche ja nur eine, nehme also die /dev/ram0. Auf dieser Ramdisk benötigen wir kein tolles Filesystem mit Journaling oder ähnlichem, da es sowieso bei jedem booten verloren geht. Also entscheide ich mich für das klassiche ext2 Dateisystem, dies ist recht ausgereift und auf ner Ramdisk ausreichend performant. Wir verwenden also folgenden Befehl: mkfs.ext2 -m /dev/ram0. Damit erstellen wir das Dateisystem auf dem Device /dev/ram0, die Option -m bewirkt das wir das Dateisystem im vollen Umfang nutzen können und kein Platz für den Benutzer root reserviert wird (weil das brauchen wir hier ja nicht). Und schon ist unsere Ramdisk fertig. Wir können Sie nun mounten und verwenden. mount /dev/ram0 /mnt.

Zu Beachten

  • Die Erzeugung des Filesystems und das mounten muss nach jedem reboot wiederholt werden. Ich verwende dafür ein init script, mann kann es natürlich auch anders machen.
  • Auch zu beachten ist, das man jetzt eine hochperformante Platte hat, von der Daten schnell gelesen und in die Daten schnell geschrieben werden können. Es kann durchaus dazu kommen, das Prozesse die zuvor an zu langsamen Platten gescheitert sind, nun plötzlich an nicht ausreichender Prozessorperformance scheitern, bzw. den Rechner enorm auslasten. Das muss man im Einzelfall testen.

Netcat

Netcat ist ein sehr nützliches Tool für viele Gelegenheiten. Ich persönlich benutze es meistens nur um den Durchsatz eines Netzwerkes zu testen wenn ich mir nicht sicher bin ob Performanceprobleme auf das Netwzerk, oder die Software zurückzuführen sind.

Dazu muss man auf dem Zielrechner netcat (oft auch nc) starten:

netcat -l <Port> > <Dateiname>

Und natürlich auf der sendenden Maschiene ein entsprechendes Netcat starten damit auf dem Zielhost empfangen werden kann:

netcat <Zieladresse> <Port> < <Dateiname>

Wenn man die Zeit des des Befehl auf der sendenden Maschine misst, kann man daraus den Durchsatz errechnen, dieser kommt meist nahe der praktischen Leistungsgrenzen der Netzwerkverbindung, da dort weder Kompression noch aufwändige Protokolle overhead erzeugen.

Backup mit Netcat

Weiterhin kann man ganz nette Backups mit Netcat machen. Z.b. ganze Partitionen, oder ganze Platten. Partitionen kann man hinterher schön mounten, deswegen finde ich das praktischer. Will man eine Partition mit netcat über das Netzwerk wegsichern, macht man folgendes:

Auf dem Quellrechner:

dd if=/dev/<partition> | netcat/nc <Zieladresse> <Port> 

Auf dem Zielrechner:

netcat/nc -l <Port> > <Dateiname>

Und schon hat man ein file in dem die Partion enthalten ist. Diese kann man nun ein bischen aufpeppen.

Backup mit Tricks

Will man das ganze noch ein bischen verfeineren, schribt man bevor man ein solches Backup macht erstmal den restlichen space mit „0“ voll. Das geht ganz einfach mit:

cd <Verzeichnis auf der Partition>
dd if=/dev/zero of=lala.txt

Das hat den Sinn, das der freie Platz mit nullen überschrieben wird und sich so besser komprimieren läßt.

Aufpassen muss man bei der root Partition, da muss man ein wenig Platz freilassen. Das kann man mit der Angabe bs=1m und count=<mb frei – 50>. So vermeidet man das das System unansprechbar wird.

Anschließend komprimieren wir die Ausgabe des dd durch folgende Angabe:

Quellrechner:

dd if=/dev/<Partition> | gzip -9 -c | netcat <Zieladresse> <Port>

Damit wird das ganze dann „on the fly“ komprimiert. Das kostet zwar CPU Zeit, spart aber viel Platz. Auf dem Zielsystem braucht man eigentlich nicht viel ändern, ich würde als Endung einfach .gz anfügen, damit man weiß das das Image komprimiert ist.