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

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

ModAJP tips+tricks

Ich Arbeite recht viel mit der Kombination aus Tomcat und Apache. Dazu benötigt man das das modajp (Ich weiß man kanns auch mit mod proxy machen). Hier mal ein paar Infos die ich mit der Zeit gelernt hab.

Basiskonfiguration

Theoretisch funktioniert der Kram recht easy, und zwar indem man mod_proxy und mod_proxy_balancer einschaltet und folgendes in die httpd.conf einträgt:

ProxyRequests Off

Das verhindert erstmal, das wir offener Proxy spielen, ganz, ganz, ganz, ganz … wichtig. Und nun brauchen wir noch den AJP Connect:

ProxyPass / ajp://127.0.0.1:8009/

Und fertig sind wir, wir haben jetzt einen AJP Connector auf das Loopbackinterface und Port 8009 konfiguriert. Dazu muss natürlich, in der server.xml des Tomcats, folgendes eingetragen sein:

<Connector port=“8009″ protocol=“AJP/1.3″ redirectPort=“8443″ />

Genau, ein AJP Connector.

Also funktioniert das ganze jetzt schon mal. Meiner Erfahrung nach, läuft es aber so einfach, gerade in Hochlastzeiten nicht zufriedenstellend. Deswegen ….

A bisl Tuning

Wir haben eben den ajp connector im Apache gemacht, diesem kann man wenn man mag noch ein paar hilfreiche Optionen mit auf den Weg geben. Getestet mit ein paar Milliarden zugriffen bisher ist folgendes:

ProxyPass / ajp://127.0.0.1:8009/ smax=5 max=20 ttl=10 retry=0 disablereuse=On

Das macht meiner Erfahrung nach die ganze Nummer erheblich stabiler.

Den Connector des Tomcats kann man dazu natürlich auch noch ein bischen anpassen, siehe dazu die Optionen des HTTP Connectors.

Server Tokens im Apache konfigurieren

Wie gewöhne ich dem Apache ab zuviel Informationen über sich Preis zu geben? Einfach

ServerTokens Prod

in die httpd.conf einfügen.

Wie sehe ich nun ob das was gebracht hat? Einfach ein fehlendes Dokument aufrufen. Wenn das sowas erscheint:

Not Found

The requested URL /dkwjhdwe was not found on this server.
Apache/2.2.2 (Fedora) Server at www.xxx.de Port 80

dann sieht man zuviel, nochmal checken bitte. Wenn das ganze allerdings so aussieht:

Error 404
tn.genano.de
Wed Jun 27 17:05:58 2007
Apache

Dann passt das.

Self Signed (Selbst signiertes) Zertifikat erstellen

Privaten Schlüssel generieren:

Zuerst brauchen wir einen privaten Schlüssel, den generieren wir mit openssl:

openssl genrsa -des3 -out server.key 1024

Hier steht die 1024 für die stärke (Bitanzahl) des Schlüssels, je größer der Wert, desto sicherer. Allerdings auf je größer der Wert, desto mehr rechenaufwand ist nötig. Gute werte sind zwischen 1024 und 4096 bit.

Wir erhalten folgende Ausgabe:

openssl genrsa -des3 -out server.key 1024
Generating RSA private key, 1024 bit long modulus
……………………………………………………++++++
…….++++++
e is 65537 (0x10001)
Enter pass phrase for server.key:
Verifying – Enter pass phrase for server.key:

Die Passphrase die Ihr hier eingebt müsst Ihr euch merken, da wir diese benötigen um die Passphrase hinterher zu entfernen und das Zertifikat zu erstellen. Wollt Ihr das Zertifikat nicht für einen Webserver verwenden oder Ihr habt wirklich starke Sicherheitsansprüche, kann es sinnvoll sein, das Passwort zu belassen. Ihr müsst die Passphrase dann allerdings bei jedem Start des Apaches eingeben.

CSR (Certificate Signing Request) generieren

Jetzt müssen wir den CSR generieren. Auch hier benötigen wir wieder openssl.

openssl req -new -key server.key -out server.csr

Wenn wir den Befehl abgesetzt haben erhalten wir folgende Ausgabe:

Enter pass phrase for server.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ‚.‘, the field will be left blank.
—–
Country Name (2 letter code) [GB]:DE
State or Province Name (full name) [Berkshire]:Bavaria
Locality Name (eg, city) [Newbury]:Nuernberg
Organization Name (eg, company) [My Company Ltd]:Meine Firma
Organizational Unit Name (eg, section) []:IT
Common Name (eg, your name or your server’s hostname) []:tn.genano.de
Email Address []:nicht.an.schreiben@genano.de

Please enter the following ‚extra‘ attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Hier tragen wir die Daten ein und kommen schon zum nächsten Schritt, dem entfernen der Passphrase.

Passphrase vom Schlüssel entfernen

Um nicht jedes mal ein Passwort eingeben zu müssen wenn wir den Apache starten, entfernen wir die Passphrase vom Schlüssel. Ich möchte allerdings darauf hinweisen, das dieses Vorgehen, sicherheitstechnisch nicht korrekt ist! Aber für die meisten Zwecke ausreicht.

cp server.key server.key.org

Wir kopieren als erstes mal den Schlüssel und anschließend entfernen wir die Passphrase

openssl rsa -in server.key.org -out server.key
Enter pass phrase for server.key.org:
writing RSA key

Dieses eine mal müssen wir das PW noch eingeben, dann aber haben wir mit dem server.key einen passwortloen Schlüssel für unseren Webserver. Jetzt brauchen wir nur noch das Zertifikat.

Zertifikat erstellen

Um ein Zertifikat mit einer Gültigkeit von 365 Tagen zu erstellen machen wir jetzt folgendes:

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Wir erhalten folgende Ausgabe:

Signature ok
subject=/C=DE/ST=Bavaria/L=Nuernberg/O=Meine Firma/OU=IT/CN=tn.genano.de/emailAddress=nicht.an.schreiben@genano.de
Getting Private key

Und tada nun haben wir alles zusammen was wir brauchen.

Im Apache

Jetzt müssen wir den Kram noch in den Apachen eintragen, hier ein mini Beispiel:

Listen 443

<VirtualHost *:443>
DocumentRoot „/var/www/html/“
ServerName tn.genano.de
ServerAdmin webmaster@genano.de
ErrorLog /var/log/httpd/error_log
TransferLog /var/log/httpd/access_log

SSLEngine on

SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile /etc/ssl/ServerCerts/server.crt
SSLCertificateKeyFile /etc/ssl/ServerCerts/server.key
<Files ~ „\.(cgi|shtml|phtml|php3?)$“>
SSLOptions +StdEnvVars
</Files>
<Directory „/srv/www/cgi-bin“>
SSLOptions +StdEnvVars
</Directory>
<Directory „/var/www/html>
Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>
SetEnvIf User-Agent „.*MSIE.*“ \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
CustomLog /var/log/httpd/ssl_request_log   ssl_combined
</VirtualHost>