Kategorien
Linux

Die Trinität der Mailserver

Ohne diese werden die Server von anderen EMail Servern im Internet nicht akzeptiert.
Es folgend Fehlermeldungen wie
– 550 inconsistent or no DNS PTR record for IP-ADRESSE
– 550 5.7.1 Sorry, your helo has been denied
– 550 Bad DNS PTR resource record

“A – PTR – EHLO”
Der A-Record einer Subdomain muss auf die IP-Adresse des EMail Servers zeigen.

~$ host example.com
~$ dig -t A example.com

Der PTR (DNS Reverse Eintrag) der IP-Adresse des EMail Servers muss auf diese Subdomain zeigen.

~$ host 1.2.3.4
~$ dig ptr 4.3.2.1.in-addr.arpa

Das EHLO (HELO) des EMail Servers muss die oben genutzte Subdomain zurückgeben.

Bei einer Verbindung via Telnet muss dieser PTR Record im EMail-Banner und in der EHLO Antwort vorhanden sein:

~$ telnet example.com. 25
Trying 1.2.3.4...
Connected to example.com.
Escape character is '^]'.
220 example.com ESMTP MAILServerdienst
ehlo test
250-example.com

Bei meinem EMail Server sieht dies dann wie folgend aus:
Der PTR Record:

~$ dig PTR 163.118.214.85.in-addr.arpa

; <<>> DiG 9.3.4-P1.2 <<>> PTR 163.118.214.85.in-addr.arpa
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27856
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;163.118.214.85.in-addr.arpa.   IN      PTR

;; ANSWER SECTION:
163.118.214.85.in-addr.arpa. 1777 IN    PTR     server.angststalt.de.

;; Query time: 1 msec
;; SERVER: 81.169.163.106#53(81.169.163.106)
;; WHEN: Fri Sep  9 11:21:12 2016
;; MSG SIZE  rcvd: 79

Alternativ via host:

~$ host 85.214.118.163
163.118.214.85.in-addr.arpa domain name pointer server.angststalt.de.

Der A-Record:

~$ dig A mail.angststalt.de.

; <<>> DiG 9.3.4-P1.2 <<>> A mail.angststalt.de.
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31184
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;mail.angststalt.de.            IN      A

;; ANSWER SECTION:
mail.angststalt.de.     7157    IN      A       85.214.118.163

;; Query time: 1 msec
;; SERVER: 81.169.163.106#53(81.169.163.106)
;; WHEN: Fri Sep  9 11:20:02 2016
;; MSG SIZE  rcvd: 52

und der EHLO Eintrag des EMail Servers:

~$ telnet server.angststalt.de. 25
Trying 85.214.118.163...
Connected to server.angststalt.de.
Escape character is '^]'.
220 server.angststalt.de ESMTP Postfix
ehlo example.com
250-server.angststalt.de
250-PIPELINING
250-SIZE 20480000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
quit
221 2.0.0 Bye
Connection closed by foreign host.

 

Kategorien
Linux Postfix

Postfix, maximale größe der EMails festlegen

In Postfix kann die maximale Größe von zu verarbeitenden EMails übder die Konfigurationsvariable “message_size_limit” festgelegt werden.

Postfix wird alle EMails ablehnen die größer als der festgelegte Wert von “message_size_limit” ist. Der Vorgabewert von message_size_limit ist 10240000 (nahezu 10 Megabyte).

In der Postfix Konfigurationsdatei wird dieses Limit, zumindest unter debian nicht aufgeführt. Es kann direkt in der Datei /etc/postfix/main.cf, oder mit postconf hinzugefügt werden.

Die aktuelle Einstellung von Postfix kann mit dem folgenden Befehl angezeigt werden:

postconf message_size_limit

Mit der Eingabe von “postconf”, ohne zusätzliche Parameter, wird die gesammte Postfix konfiguration ausgegeben werden. Durch den Zusatz des “message_size_limit” wird nur diese eine Option ausgegeben. Die ausgabe des obig angegebenen Befehl zeigt die folgende Zeile:

message_size_limit = 10240000

Um den zugewiesenen Wert zu Ändern kann mit der folgenden Eingabe ein abweichender Wert zugewiesen werden. Um herauszufinden kann mit dem folgenden Shellscript eine beliebige anzahl MB in Bytes, die Angabe in der Postconf erfolgt in Bytes, umgerechnet werden.

awk '{$1=$1*1024*1024;printf "%.0f\n",$1}'

Nach der Eingabe auf der Shell zum Beispiel 20 eingeben und Enter drücken, als Ausgabe erfolgt 20971520. (Das Script  im Anschluss mit Strg und C abbrechen) Diesen Wert weisen wir jetzt mit postconf dem message_size_limit zu:

postconf message_size_limit=20971520

Hiermit wird in die letzte Zeile der Datei /etc/postfix/main.cf die Zeichenfolge “message_size_limit=20971520” angefügt und alle eventuell zuvor in der Dastei vorkommenden Zuweisungen “message_size_limit=” entfernt.

Im Anschluss muss noch der Dienst Postfix die neue Konfiguration lesen. Dies erfolgt durch die eingabe von:

service postfix reload

Im Anschluss gilt die neue Option und entsprechend größere EMails können angenommen werden.

Kategorien
Forensik Linux security

Alle TCP/UDP Ports prüfen

Ich suchte im Netz eine Möglichkeit in einem Fremden Netzwerk die erlaubten offenen Ports zu entdecken, leider fand ich keine “out of the box” Lösung im Internet und baute mir die hier dokumentierte Lösung.

Der Netzwerk Computer ist in der folgenden Konfiguration mit meinem Testserver verbunden.:
nmap-netzwerk für den Netzwerkscan
Auf der Laptop Seite hinterlege ich einen neuen SSH Private Key übertrage einen zugehörigen Public aus dem Server in die Datei ~/.ssh/authorized_keys:

ssh-keygen -b 4096
scp ~/.ssh/id_rsa.pub root@:
ssh root@
mkdir ~/.ssh
cat ~/id_rsa.pub >> ~/.ssh/authorized_keys
rm ~/id_rsa.pub
chmod 600 ~/.ssh/authorized_keys

Auf der zu testenden Seite legte ich mir dieses kleine Shellscript ab, das nach und nach Netcat lokal auf verschiedene Ports lauschen lässt und im Anschluss versucht die Ports von der Serverseite aus zu erreichen.:

#!/bin/bash

COMPUTER="85.214.70.215"
ME=$(/usr/bin/curl http://shortip.de/txt) 1>/dev/null 2>/dev/null

for ((PORT=1; PORT< =65535; PORT++)) do /bin/nc -l $PORT 2>/dev/null &
 ssh root@$COMPUTER -t "/bin/netcat -vv -n -z -w 3 $ME $PORT"
done

Um Netcat an UDP-Ports senden, oder auf UDP Ports lauschen zu lassen kann die Option -u mit angegeben werden.

Diese Methode dauert selbstverständlich ewig und ist nur anwendbar wen wenige Ports zu durchsuchen sind und nicht wie im Beispielscript angegeben alle 65535.

Kategorien
Linux

script: Terminal Sessions aufnehmen

Um eine Terminal Session aufzuzeichnen kann das häufig vorinstallierte “typescript” verwendet werden. Typescript nimmt alles auf das in einer Terminal Sitzung angezeigt wird. Die Befehle script & scriptreplay zeichnen eine Terminalsitzung auf, und spielen sie auch wieder ab.

Besonders zu empfehlen sind diese beiden Befehle zur Dokumentation oder um dritten eine Anleitung zukommen zu lassen.

Eine Aufnamesitzung kann durch eingabe des folgenden Komandos gestartet werden:

script -ttimefile recordfile

Es wird hierbei in zwei Dateien gesichert.

In die Datei recordfile werden alle Steuerzeichen geschrieben, in die Datei timefile wird ein Zeitindex für die Ausgaben gespeichert.

Nach dem Aufruf von script startet es im Hintergrund, ohne eine Ausgabe im Terminal zu verursachen. Alle folgenden Ausgaben werden aufgezeichnet.

Um die Aufname zu beenden und die Ausgabedateien fertigzustellen reicht ein Druck auf die Tasten [Strg] und D.

Um eine Aufnahme zu einem Späteren Zeitpunkt abzuspielen kann diese wiedergabe , wie im folgenden Beispiel, mit scriptreplay gestartet werden:

scriptreplay -ttimefile recordfile

Aufnahmen von Terminalsitzungen können auch mit fortgeschritteneren Werkzeugen wie ttyrecshelr oder timerec angesfertigt werden. Die Anwendung erfolgt ähnlich, jedoch benötigen diese Werkzeige keine Zeitdatei. Sie speichern die Ausgabe jedoch in einer Binärdatei und sind sehr selten bereits vorinstalliert.

Kategorien
Linux

Dateisystem “nachträglich” in RAID1 wandeln

Ich wurde im Februar 2015 bei einem erfolglosen Bewerbungsgespräch Zeuge, wie auf einem Arbeitsplatz-Computer das Dateisystem, welches ohne RAID-Verbund eingerichtet wurde, das System auf mittels mdadm in ein RAID 1 umgewandelt werden sollte.

Ich fand die Idee einen Arbeitsplatz Computer nachträglich, scheinbar direkt nach der Neuinstallation auf ein RAID zu verschieben überflüssig und umständlich.
Persönlich nutze ich lieber das Backup des Systems welches in jedem Fall vorhanden ist um nach einer Neuinstallation des Computers mit Einrichtung eines RAID Verbundes, zur Wiederherstellung der Daten.

Als Fingerübung fand ich die Idee jedoch interessant.
In meinen eigenen Überlegung gehe ich davon aus das im Notfall eine solche Nachträgliche Verschiebung der Daten in ein RAID die offline-Zeit eines Systems zugunsten einiger Arbeit und der zusätzlichen Chance das das System unerkannte Schäden enthält, reduziert werden. Daher ziehe ich auch in diesen Fällen eine saubere Neuinstallation vor.

Während des Bewerbungsgesprächs hörte ich nur ein paar Fetzen, ein Mitarbeiter fragte tatsächlich den Leiter seiner Abteilung wie mdadm und die Grub Installation erfolgreich durchzuführen seien. (Nein, es war ein fest eingestellter Mitarbeiter in der Administration, kein Azubi)

Nach nur zwei Versuchen, die beide erfolgreich waren, kann ich guten Gewissens berichten das die Umstellung eines Systems in ein RAID 1 ist tatsächlich so kompliziert nicht ist.

1.) Partitionierung klonen

Nach dem Einbau der zweiten Festplatte muss die Partitionierung der ersten Festplatte auf die neue Festplatte übertragen werden.

Auf der ersten Festplatte befinden sich 3 Partitionen, Boot, Swap und die eigentliche Datenpartition.

Der folgende Befehl liest die Partitionierung der Festplatte /dev/sda aus und schreibt diese auf die Festplatte /dev/sdb.

sfdisk -d /dev/sda | sfdisk /dev/sdb

“sfdisk -d” gibt die aktuelle Partitionstabelle der Festplatte /dev/sda aus und “sfdisk”, ohne Parameter, nimmt diesen Export und schreibt die Partitionen auf die Festplatte /dev/sdb.
Das die Übertragung der Partitionen erfolgreich war prüfe ich vor dem nächsten Schritt mit Hife der Eingabe von “sfdisk -l /dev/sdb”.

Im Anschluss wechseln wir die Partitions-ID von den für das RAID vorgesehenen Partitionen /dev/sdb1 und /dev/sdb3 auf fd (Linux raid autodetect).
Mit fdisk kann dies über das Kommando t, zum ändern der Partitions-ID, gefolgt von der Nummer der gewünschten Partition, zuerst 1 für die erste Partition später 3 für die dritten Partition, und in Folge die Eingabe der Zeichenfolge fd erfolgen.

fdisk /dev/sdb

Command (m for help): t
Partition number (1-4): 1
Hex code (type L to list codes): fd

Command (m for help): t
Partition number (1-4): 3
Hex code (type L to list codes): fd

Command (m for help): w
The partition table has been altered!

2.) Raid initialisieren

Anschließend erstellen wir das RAID 1 Arrays mit den neuen Partitionen und “mit fehlendem zweiten Datenträger”.
Hierbei ist missing der Platzhalter für die aktuell fehlenden, da “aktiven” und mit den Daten des Systems belegten Partitionen. “-l 1” steht für RAID 1, “-n 2” dafür daß das RAID 1 aus zwei Datenträgern bestehen wird.
(Bei einer minimal-Debian Installation muss mdadm zuvor mit dem Aufruf “apt install mdadm” installiert werden.)

# mdadm -C /dev/md0 -l 1 -n 2 missing /dev/sdb1 --metadata=0.90
mdadm: array /dev/md0 started

# mdadm -C /dev/md1 -l 1 -n 2 missing /dev/sdb3
mdadm: Note: this array has metadata at the start and
     may not be suitable as a boot device. If you plan to
     store '/boot' on this device please ensure that
     your boot-loader understamds md/v1.x metadata, or use
     --metadata=0.90
Continue creating array? y
mdadm: Defaulting to version 1.2 metadata
msads: array /dev/md1 started.

3.) Daten übertragen

Nach dem Anlegen der beiden neuen RAID 1 Arrays erzeuge ich ein ext3-Dateisystem auf den neuen Partitionen und erzeuge die neue swap-Partition.:

mkfs.ext3 /dev/md0
mkfs.ext3 /dev/md1
mkswap /dev/sdb2

Nach dem anlegen des Dateisystems können die Datenträger eingehängt werden…

mount /dev/md1 /mnt
mkdir /mnt/boot
mount /dev/md0 /mnt/boot

…und im Anschluss die Daten auf den neuen Datenträger kopieren:

cp --no-dereference --preserve --recursive --one-file-system / /mnt
cp --no-dereference --preserve --recursive --one-file-system /boot/ /mnt/

4.) RAID ergänzen

Wie bereits im ersten Schritt, werden nun die Partitions-IDs angepasst. Diesmal jedoch für die Festplatte /dev/sda auf welcher zuvor noch unsere Nutzdaten gespeichert waren:

fdisk /dev/sda

Command (m for help): t
Partition number (1-4): 1
Hex code (type L to list codes): fd

Command (m for help): t
Partition number (1-4): 3
Hex code (type L to list codes): fd

Command (m for help): w
The partition table has been altered!

Im Anschluss muss in der Datei /etc/fstab für / den Eintrag /dev/md0 und für /boot den Eintrag /dev/md1 hinerlegt werden.

Anschließend kann der Computer neu gestartet werden.

Sobald der Grub2 Bootloader erscheint mit der Taste e den Editor für den Booteintrag atarten. In dem Booteintarg die Zeile “linux /vmlinux-3.3 root=UUID=” in das aktuell verwendete “linux /vmlinux-3.3 root=/dev/md1” korrigieren und im Anschluss mit F10 den Bootvorgang starten.

Das RAID mit den folgenden beiden Befehlen vervollständigen.:

mdadm --add /dev/md0 /dev/sda1
mdadm --add /dev/md1 /dev/sda3

Der erste Aufruf fügt dem RAID Array md0 den Fehlenden Datenträger sda1 hinzu. Nicht schwer zu erraten fügt zweite Aufruf den Datenträger sda3 dem RAID md1 hinzu.

5.) Grub für das neue RAID Installieren

Jetzt abschließend den Grub Bootloader für beide Festplatten konfiguriert und auf diese Installieren.

nur noch die Zeile “GRUB_TERMINAL=console” in der Datei /etc/default/grub auskommentieren und mit den folgenden Befehlen eine neue Grub Konfiguration schreiben.

grub-mkdevicemap -n
update-grub
grub-install /dev/sda
grub-install /dev/sdb

Jetzt kann der Computer auch mit nur einer einzelnen Festplatte, /dev/sda oder /dev/sdb, erfolgreich starten.

Kategorien
Linux

lokale MySQL Sicherung mit Logrotate

Logrotate kann falsch genutzt werden um eine lokale MySQL Sicherung zu erstellen.

“logrotate” ist ein sehr weit verbreitetes Linux Werkzeug welches mit den meisten Linux Distribuntionen vorkonfiguriert ausgeliefert wird.

Im Verzeichnis /var/log sind die Dateien nach dem folgenden Schema angeordnet.:

/var/log/auth.log
/var/log/auth.log.0
/var/log/auth.log.1.gz
/var/log/auth.log.2.gz
/var/log/auth.log.3.gz

Das ist wofür “logrotate” geschrieben wurde. Die Logdatei wird von /var/log/auth.log umbenannt zu /var/log/auth.log.0 und am folgenden Tag komprimiert und umbenannt in /var/log/auth.log.1.gz. Wenn mehr als vier sicherungen der Logdatei existieren werden überzählige Sicherungen gelöscht. Genau was eine lokale Datenbank-Sicherung erreichen soll.

Normalerweise mache ich meine MySQL Sicherungen mit einem Cronjob, der mir dann relativ schnell die Festplatte mit Datenbanksicherungen füllt. Da es die Aufgabe von “logrotate” ist Logdateien umzubenennen, zu komprimieren und alte Logdateien zu löschen eignet es sich auch sehr gut für eine kleine lokale Datensicherung.

Mit ein wenig chreativem falsch gebrauch des Werkzeugs “logrotate” kann es verwendet werden um MySQL Sicherungen zu rotieren.

Hier die Kurzanleitung wie ich dies erreicht habe:

Zuerst erstelle ich das Verzeichnis /var/backups/mysql/ in dem die Datensicherung der MySQL Datenbank angelegt werden soll.

Um den “logrotate” Deamon dazu zu bringen die Datenbank zu sicher erstelle ich die Datei /etc/logrotate.d/0-mysql-backup mit dem folgenden Inhalt:

/var/backups/mysql/database.sql {
     daily
     rotate 10
     missingok
     compress
     nocreate
     prerotate
          /usr/bin/mysqldump -uUSERNAME -pPASSWORD -A --events --single-transaction > /var/backups/mysql/database.sql
     endscript
}

Diese “logrotate” Konfigurationsdatei läuft täglich (daily), behält 10 Backups (rotate 10), läuft auch wenn die Datei nicht vorhanden ist (missingok), komprimiert die Daten mit dem in logrotate eingestellten Kompressionsalgorithmus (compress), erstellt im Anschluss keine neue Datei (nocreate) und erstellt vor dem lauf von “logrotate” den MySQL Dump.

Da Logrotate ohne vorhandene Datei nicht einmal den Befehl im Bereich prerotate ausführt muss die sicherungsdatei database.sql zuerst angelegt werden.

/usr/bin/touch /var/backups/mysql/database.sql

Ob wir alles richtig gemacht haben können wir auf der Shell testen.

/usr/sbin/logrotate -f -v /etc/logrotate.d/0-mysql-backup

Bei dieser Sicherung handelt es sich nicht um ein vollwertiges Backup da das Sicherungsverzeichnis /var/backups/mysql/ sich auf dem gleichen Computer (oder sogar auf der gleichen Festplatte) befindet auf der auch der MySQL Server selbst läuft. Hier kann natürlich auch vor der Sicherung das Verzeichnis gemounted werden.

Kategorien
Allgemein

Logrotate Kompression von Logdateien festlegen

Logrotate komprimiert in den Standarteinstellungen die Logdateien mit “gz”, leider ist die Kompression von “gz” deutlich schlechter als von modernen Kompressionsprogrammen wie “xz”.

Zum Glück ist es ganz einfach das von Logrotate verwendete Kompressionsprogramm auszutauschen. Die Konfigurationsdatei /etc/logrotate.conf muss hierzu nur durch die folgenden vier Zeilen ergänzt werden.

compresscmd /usr/bin/xz
uncompresscmd /usr/bin/unxz
compressext .xz
compressoptions -9

Die letzte Option “compressoptions” kann weggelassen werden, hier wird die defaultoption “-9” einfach noch einmal in der Konfigurationsdatei festgelegt. Ich persönlich setze diese Option nur, um beim editieren der Datei sofort die gewählte Konfigurationsoption zu sehen.

Die Stelle in der Konfigurationsdatei spielt hierbei keine Rolle, meine Wahl fällt immer auf das Ende der Konfigurationsdatei.

Kategorien
Linux Raspberry Pi

Neuer Linux Kernel für Raspberry Pi

Manchmal brauche ich einfach das eine oder andere Kernel Modul welches sich nicht im Vanilla Kernel meines Rasbian befindet, oder ich möchte unbedingt einige Module loswerden oder ich will einen aktuelleren linux Kernel.
Um eines oder alle diese Ziele zu erreichen muss ein neuer Linux Kernel für den Raspberry Pi angefertigt werden. Hier die Kurzanleitung wie dies in fünf einfach Schritten zu schaffen ist.:

1.) Linux Kernel Quellen herunterladen

Um den Aktuellen Kernel übersetzen zu können brauchen wir einige Module. Um diese zu Installieren nutzen wir apt-get install.:

sudo apt-get install bc git build-essential

Um den “aktuellen” Linux Kernel zu bekommen holen wir über Git die Quellen:

git clone --depth=1 https://github.com/raspberrypi/linux

alternativ können wir auch einen aktuelleren Kernel (im Beispiel 4.5) holen lassen.:

git clone --depth=1 --branch=rpi-4.5.y https://github.com/raspberrypi/linux

und wechseln in das Installationsverzeichnis.

cd linux

2.) Default Konfiguration erstellen

Im Anschluss muss ich die default Linux Konfiguration für meinen Raspberry Pi erstellen, für Raspberry Pi 1 A oder B und das Compute Module:

KERNEL=kernel
make bcmrpi_defconfig

für den Raspberry Pi 2 geht dies über:

KERNEL=kernel7
make bcm2709_defconfig

3.) Kernel konfiguration anpassen (optional)

um die Konfiguration des Linux Kernels anzupassen bietet Linux die

make menuconfig

oder alternativ

make nconfig

4.) Kernel übersetzen

um den Kernel im Anschluss zu compilieren die folgenden Zeilen ausführen:

make zImage modules dtbs

5.) Kernel Installieren

sudo make modules_install
sudo cp arch/arm/boot/dts/*.dtb /boot/
sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/
sudo scripts/mkknlimg arch/arm/boot/zImage /boot/$KERNEL.img

Wenn der Kernel einen abweichenden Namen erhalten soll kann in der Datei config.txt die Zeile “kernel” für den verwendeten Kernel angepasst werden.:

kernel=meinKernel.img
Kategorien
Linux

Defekte Parallels Plesk MySQL Datenbank wiederherstellen

Manchmal geht die Plesk MySQL Datenbank beschädigt. Dies passiert häufig nach dem wiedereinspielen eines Backups auf VPower Server oder einem Stromverlust bei laufendem Server.

Mit ein paar einfachen Schritten kann jedoch das Backup, das Plesk selbst anlegt genutzt werden um Odin Plesk wieder in Funktion zu bringen.

MySQL Datenbank Stopen

sudo service mysql stop

MySQL Datenbank ohne Netzwerk und Benutzerverwaltung starten

sudo /usr/bin/mysqld_safe -–skip-grant-tables -–skip-networking --skip-syslog &

optional, so ohne Fehler überhaupt möglich, letztes Backup der tabellen

sudo mysqldump mysql --event > mysql.sql
sudo mysqldump psa > mysql.sql

MySQL Datenbanken ‘psa’ und ‘mysql’ entfernen

mysql
mysql> drop database psa;
Query OK, 220 rows affected (1.71 sec)

mysql> drop database mysql;
Query OK, 24 rows affected, 2 warnings (0.05 sec)

mysql> quit

MySQLdump aus /var/lib/psa/dumps/mysql.daily.dump.0.gz in die Datenbank einspielen

zcat /var/lib/psa/dumps/mysql.daily.dump.0.gz|mysql

MySQL Datenbank neu starten

sudo killall mysqld
sudo service mysql start
mysql start/running, process 8952
Kategorien
Allgemein

Apache, Zopfli – vorkomprimierte Dateien

Internetseiten können, wenn die Dateien komprimiert sind, da weniger Daten übertragen werden müssen, deutlich schneller aufgebaut werden.

Kompression der Daten mit Googlels Zopfli

Google hat im April 2013 auf github veröffentlicht. Die Zopfli deflate Implementierung kann deutlich besser komprimieren als das Standard GNU Gzip Program.
Google Zopfli ist zu finden unter: https://github.com/google/zopfli
Nach dem der Google Anleitung folgend Zopfli kompilliert und Installiert ist kann mit der folgenden Shellzeile eine Datei komprimiert werden.:

zopfli --i1000 dateiname.css

Um alle, in diesem Beispiel “CSS Dateien” zu komprimieren kann mit einer Schleife nach allen Dateien Dateien die auf .css enden gesucht werden und diese an Zopfli übergeben werden.

for f in *.css.css ; do zopfli -i1100 -c $$f > `basename $$f .css`.gz ; done

Auslieferung der mit Zopfli Komprimierten Dateien mit dem Apache Webserver

Bei nutzung eines Apache-Webservers ist ein möglicher Trick, das mit mod_rewrite jedem Browser der gzip unterstützung bietet andere Dateien ausliefert werden können als den Browsern die keine gzip Unterstützung anbieten. Das schöne dabei ist das  solange keine entsprechende Datei vorhanden ist, der Browser die Ursprungsdatei erhält.

Eine Beispiel .htaccess Datei:

RewriteEngine On
RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME} \.css$
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule ^(.*)$ $1.gz

In der ersten Zeile wird mod_rewrite aktiviert, in der Zweiten Zeile wird gefiltert, das die filgenden Regeln ausschließlich befolgt werden wenn der Request Header die Antwort als gzip komprimierten Datenstrom akzeptiert. In der dritten Zeile werden nur Dateien akzeptiert die auf .css enden.
Die vierte Zeile sucht im Dateisystem ob eine Datei gleichen Namens mit der Dateierweiterung .gz existiert.
Die fünfte Zeile liefert anstelle der .css Datei die .css.gz Datei aus.

Die Rechenzeit die der Apache Webserver dafür benötigt ist zum glück minimal.

Ergänzung durch einen “Automatismus”

Ich persönlich nutze gerne einen make Makefile um nach Änderungen schnell alle Dateien wieder zu komprimieren.

all: clean build chown

build:
	find ./css/ -type f -name "[^.]*.css" -execdir yui-compressor -o {}.css {} \;
	cd ./css/ && for f in *.css.css ; do zopfli -i1100 -c $$f > `basename $$f .css`.gz ; done

clean:  
	find ./css/ -name "*.css.css" -delete
	find ./css/ -name "*.css.gz" -delete

chown:
	find ./css/ -type f -name "[^.]*.css" -execdir chown www-data:www-data {} \;
	find ./css/ -type f -name "[^.]*.gz" -execdir chown www-data:www-data {} \;