HTTP/2: Welchen Vorteil bringt der neue Webstandard?

Diesen Artikel habe ich bereits im Firmen Blog von menadwork GmbH veröffentlicht: Düsseldorf, am 04.11.2015 von Lars Moelleken


Der im Mai 2015 veröffentlichte Webstandard HTTP/2 bewirkt, dass Webseiten schneller angezeigt werden. Die Kompatibilität von HTTP/2 ist in fast allen aktuellen Webbrowsern gegeben, wer dies jedoch einsetzen will muss zwangsläufig ein SSL-Zertifikat einsetzen, so dass die Webseite verschlüsselt übertragen wird.

In Kürze vorab:

Haben Browser und Ser73_221_de_ver im vorherigen HTTP/1.x Standard aus dem Jahr 1996 noch sehr viel Zeit mit „Warten“ verbracht, können durch den neuen Webstandard HTTP2 Webseiten schneller angezeigt werden.

Die Kompatibilität von HTTP/2 ist in fast allen aktuellen Webbrowsern gegeben – ein guter Grund, auf das neue Protokoll zu setzen. Serverseitig unterstützt der Apache Webserver (v2.4.17) den entsprechenden Webstandard.

73_222_de

Wer HTTP/2 einsetzen will muss zwangsläufig ein SSL-Zertifikat einsetzen, so dass die Webseite verschlüsselt (via https://) übertragen wird.

Und nun zu den Details …

Grundsätzliches: So funktioniert das Internet

73_224_de

Um zu erklären, was HTTP/2 ist, sollte man zuerst verstehen wie das Internet grundsätzlich funktioniert. Alle Daten im Computer und auch im Internet sind digital, das bedeutet so viel wie „die Daten werden intern binär verarbeitet“ (z.B. a => 01100001, b => 01100010, c => 01100011).

Um diese Daten nun an einen anderen Computer zu übertragen, benötigt jeder Computer, jedes Smartphone usw. eine eindeutige Adresse, die sogenannte IP-Adresse.

Die Daten werden bei der Übertragung im Internet bzw. im Netzwerk zu sogenannten Paketen zusammengefasst. Jedes Paket wird zusätzlich mit der Information bestückt von welcher IP-Adresse diese gesendet und an welche IP-Adresse diese gesendet werden sollten, solche Informationen nennt man Header-Informationen.

Um nun eine Verbindung von einem zum anderen Computer herzustellen, nutzt man sogenannte Netzwerkprotokolle: Diese definieren einen Standard, so dass unterschiedliche Systeme miteinander kommunizieren können. Im Internet werden UDP (User Datagram Protocol) bzw. TCP (Transmission Control Protocol) verwendet.Das Netzwerkprotokoll UDP ist im Gegensatz zu TCP verbindungslos, d. h. es wird keine eindeutige Verbindung aufgebaut. UDP wird z. B. verwendet um eine Domain (menadwork.com) in die entsprechende IP-Adresse aufzulösen.

Diese Netzwerkprotokolle nutzen unterschiedliche Ports, welche man sich wie Türen vorstellen kann: Jeder Computer hat – ähnlich einem Haus – eine eindeutige Adresse (IP-Adresse) und bietet Platz für unterschiedliche Dinge. diese Dinge können z. B. Webseiten (Port:80), E-Mails (Port:143) oder Dateien (Port:21) sein. Dies ist der Grund, warum man beispielsweise eine Webseite auch wie folgt aufrufen kann: „menadwork.com:80„.

Auch diese Ports sind zumindest von 0 bis 1023 mit fest definierten Anwendungsprotokollen (z. B. HTTP: 80, IMAP: 143, FTP: 21) belegt, so dass man verschiedene Anwendungen über TCP bzw. UDP ansteuern kann.

Die Einführung von HTTP/1.0 und HTTP/1.1

HTTP (Hypertext Transfer Protocol) wurde zusammen mit den Konzepten für die URL und HTML geschaffen und 1996 als HTTP/1.0 publiziert. Für jede verknüpfte Datei in einem HTML-Dokument – wie z. B. Bilder – wurde eine neue TCP-Verbindung aufgebaut.

Im Jahr 1999 wurde dann HTTP/1.1 publiziert, welches unter anderem Pipelining ermöglicht: Dabei werden mehrere HTTP-Anfragen über eine TCP/IP-Verbindung geschickt, so dass man den Overhead beim Verbindungsauf- und -abbau nicht bei jeder HTTP-Anfrage (Bilder, JavaScript-Dateien oder CSS-Dateien) hat. Jedoch ist dieses Feature bei fast allen Browsern standardmäßig deaktiviert und kann somit meistens nicht genutzt werden. Zudem kollidiert hier mal wieder Theorie und Praxis, da zwar theoretisch mehrere Anfragen direkt nacheinander abgearbeitet werden können, aber das sogenannte „head-of-line blocking“-Problem tritt auf: Denn die Anfragen werden noch immer nach dem FIFO-Prinzip (First In – First Out) verarbeitet und die erste Anfrage muss vor der zweiten Anfrage vom Server verarbeitet werden. Man kann sich dies wie die Kasse beim Supermarkt vorstellen: Nur, weil man mehrere Kunden an einer Kasse bedient heißt dies nicht, dass diese schneller bedient werden, solange man auch hier nach dem FIFO-Prinzip arbeitet.

Der neue Webstandard HTTP/2

HTTP/2 wurde im Mai 2015 veröffentlicht und unterstützt unter anderem das Zusammenfassen von mehrere HTTP-Anfragen über ein Multiplexverfahren. Beim Multiplexen werden Daten gebündelt und gemeinsam übertragen. Außerdem werden die Daten und Header nun komprimiert übermittelt und Daten werden binär kodiert übermittelt.

Webseite via HTTP/1.1 laden Webseite via HTTP/2 laden
1. Erstellt sechs bis acht HTTP-Verbindungen zum Server 1. Erstellt eine Verbindung zum Server
2. Anfrage der HTML-Seite 2. Anfrage der HTML-Seite
3. Empfang der HTML-Seite 3. Empfang der HTML-Seite
4. Decode der HTML-Seite 4. Decode der HTML-Seite
5. Erstellt sechs bis acht Verbindungen zu Dateien in der HTML-Seite, ohne Prioritäten

(unkomprimierten, plain-text Header)

5. Empfang von allen Dateien in der HTML-Seite, mit Prooritäten

(komprimierte, binary Header)

6. Die Verbindung wartet, bis die angeforderte Datei ankommen ist (Dateien werden über den gemultiplexten

Stream gesendet)

7. Fordert die nächste Datei, auf der jetzt offenen Verbindung an
8. Wiederhole Punkt 6-7 bis alle Dateien angekommen sind
9. Schließe sechs bis acht HTTP-Verbindungen 8. Schließe die eine Verbindung

Quelle: https://www.nginx.com/wp-content/uploads/2015/09/NGINX_HTTP2_White_Paper_v4.pdf

73_227_de

Statement von Google: „Google observed an ~88% reduction in the size of request headers and an ~85% reduction in the size of response headers after enabling compression. This amounted to a saving of between 45 and 1142 ms in the overall page load time.“ Quelle: http://www.chromium.org/spdy/spdy-whitepaper

Diese binären Daten werden als Streams bezeichnet und können mit unterschiedlichen Priorisierungen angefordert werden, zum Beispiel 1. HTML, 2. JavaScript, 3. CSS, 4. Fonts, 5. Bilder. Zudem kann man theoretisch mit der Funktion „Server-Push“ auch Dateien zum Client senden, welche dieser gar nicht angefragt hat, so könnte man HTML, CSS und Font senden, wenn nur das HTML angefragt wurde, jedoch ist dieses Funktion z. B. in der aktuellen Version von Apache (v2.4.17) noch nicht implementiert.

Im offiziellen Standard ist HTTP/2 zwar auch ohne SSL (https://) geplant, aber die Browser-Hersteller bieten HTTP/2 nicht ohne Verschlüsselung an. Da SSL-Zertifikate jedoch momentan nicht kostenlos sind, haben Mozilla, die Electronic Frontier Foundation (EFF), Cisco, Akamai und IdenTrust eine neue SSL-Zertifizierungsstelle (CA) mit dem Namen „Let’s Encrypt“ gegründet, welche in Zukunft kostenlose Zertifikate ausstellt.

 

UPDATE: (04.11.2015)

Let’s Encrypt hat heute sein Beta-Programm gestartet, sodass man über wenige Zeilen auf der Kommandozeile bereits ein gültiges SSL-Zertifikat nutzen kann.

  git clone https://github.com/letsencrypt/letsencrypt
  cd letsencrypt
  ./letsencrypt-auto --agree-dev-preview --server \
  https://acme-v01.api.letsencrypt.org/directory certonly
 Wer noch einen weiteren Grund benötigt, seine Webseite über eine verschlüsselte Verbindung (SSL) auszuliefern, der sollte sich das neue Feature von Firefox 44 anschauen, welches eine Warnung anzeigt, wenn Login-Daten über eine nicht verschlüsselte Verbindung übermittelt werden.

Was ändert sich für Webentwickler?

Jede Technik, welche HTTP-Anfragen reduziert, ist mittels HTTP/2 obsolet, da einzelne kleine HTTP-Anfragen nun schneller abgearbeitet werden als eine große Anfrage. Zu diesen Techniken zählen z. B. das Zusammenfassen (concat) von JavaScript- und CSS-Dateien oder auch das Sprite-Image, welches mehrere kleine Bilder zu einem Bild darstellt. Aber auch das aufteilen von HTTP-Request auf verschiedene Subdomains ist nicht länger sinnvoll, da ansonsten wieder neue TCP-Verbindungen aufgebaut werden müssen. Zudem ist das „Inlinen“ von z. B. Bildern via Data-URIs (data:image:png;base64,…) nicht mehr zweckmäßig.

Mit der „Server-Push-Funktion“ können bereits einige Webserver umgehen, so dass man serverseitig bestimmen kann, dass bestimmte Dateien zusätzlich ausgeliefert werden sollen, wenn z. B. eine HTML-Datei angefragt wird. Dafür müssen in den meisten Fällen bestimmte Header-Daten definiert werden (z. B. X-Associated-Content: „/foo.css“:1,“/bar.js“:1,“/baz.js“:1).

Alle diese Änderungen spielen Frameworks wie Polymer in die Hände, da der Quelltext hier in einzelne Pakete bzw. Komponenten geordnet ist und somit schneller übertragen werden kann.

Was ändert sich für Administratoren?

Administratoren müssen zunächst Server aktualisieren, da z. B. nur die aktuelle Version von Apache (v2.4.17) HTTP/2 unterstützt. Darüber hinaus müssen Pakete für die verschiedenen Linux-Distributionen müssen gebaut werden.

Indem via HTTP/2 die HTTP-Anfragen über eine TCP-Verbindung laufen, werden weniger Verbindungen pro User zum Server aufgebaut, der Web-Server benötigt weniger Speicher und die CPU-Last wird verringert.

HTTP HTTPS SPDY (HTTP/2)
Max. pages/s 16.3 @ 120 users 15.9 @ 120 users 98 @ 777 users
Response @ 100 users 1.1s 1.3s 1.1s
Response @ 120 users 1.4 s 1.5s 1.1s
Response @ 200 users 7.1s 7.8s 1.1s
Response @ 777 users 70.2s 72s 2.7s
First error 405 Users 225 Users 884 Users

Quelle: http://www.neotys.com/blog/performance-of-spdy-enabled-web-servers/

Server-Anfrage Speicherverbrauch (für die selbe Beispiel-Anfrage)
HTTP 59 MB
HTTPS 79 MB
SPDY (HTTP/2) 24 MB

Quelle: http://www.neotys.com/blog/performance-of-spdy-enabled-web-servers/

Vergleich der Ladezeiten

73_232_de

Außerdem sollte man sich ein wenig mehr mit dem Thema SSL auseinandersetzen, so kann man z. B. über den „Strict Transport Security„-Header die Ladezeit von HTTP/2 Seiten weiter reduzieren. Dies geschieht, indem die Nutzung von HTTPS sozusagen gecacht wird und Anfragen via HTTP direkt via HTTPS verarbeitet werden.

Quellen:

Apache & HTTP/2: http://www.apache.org/dist/httpd/CHANGES_2.4.17
„Can I use“ HTTP/2: http://caniuse.com/#search=http%2F2
Info zu HTTP/2: http://http2-explained.readthedocs.org/en/latest/
FAQ zu HTTP/2: https://http2.github.io/faq/
Spec zu HTTP/2: https://http2.github.io/http2-spec/
Präsentation zu HTTP/2 (von @derSchepp): https://schepp.github.io/HTTP-2/#/
Präsentation zu HTTP/2 (von @mnot): https://www.mnot.net/talks/http2-expectations/#/
W3C – preload: http://w3c.github.io/preload/
nghttp2 – Server-Push: https://nghttp2.org/documentation/nghttpx.1.html#server-push
heise: HTTP/2: http://www.heise.de/netze/artikel/Wie-HTTP-2-0-das-Surfen-beschleunigt-2164146.html
Free SSL: https://letsencrypt.org/2015/10/19/lets-encrypt-is-trusted.html
heise: Free SSL: http://www.heise.de/netze/meldung/Let-s-Encrypt-Meilenstein-zu-kostenlosen-SSL-Zertifikaten-fuer-alle-2679600.html

Demos:

https://http2.akamai.com/demo
http://http2.golang.org/gophertiles?latency=0

Mr. Robot | Staffel 1, Folge 1 in a nutshell

Die Fernsehserie folgt einem jungen Programmierer (Elliot), der von dem mysteriösen Mr. Robot für eine Hackergruppe rekrutiert wird und wer die Serie bisher noch nicht geschaut hat, sollte dies nachholen.

In Folge 1 muss Elliot einen Rootkit ausfindig machen, viel mehr werde ich an dieser Stelle nicht vorwegnehmen. Viele der folgenden Befehle sind nicht ohne weiteres auf jedem Linux System auszuführen oder es gibt diese gar nicht. Jedoch versteht bzw. sieht man was diese bewirken sollen.

1. Status

mr robot | status

Um das Problem vom Büro aus zu analysieren, werden zunächst Netzwerk und Dienste geprüft.

status -scanports -s WBUSl12345678WB1 -p[80-7655]

Hier hat Elliot sich anscheinend eine Shell-Funktion geschrieben, welche einen Portscan auf der Server „WBUSl12345678WB1“ mit der Port-Range 80 bis 7655 durchführt.

Der folgender Befehl würde wirklich funktionieren.

nmap WBUSl12345678WB1 -p80-7655

Als nächstes wird anscheinend geprüft welche Prozesse momentan auf dem Remote-Server ausgeführt werden.

status -services -s WBUSl12345678WB1

Dies könnte auch eine selbst programmiere Shell-Funktion sein, welche sich auf dem Remote-Server einloggt und die Prozesse z.B. via „ps aux“ auflistet.

ssh user@WBUSl12345678WB1 ‚ps aux‘

Resultat: Die Services sind nicht mehr erreichbar und anscheinend läuft auf dem Server ein Xorg. ;) Da der Fehler nicht einzugrenzen ist, wird Elliot (mit dem Jet) zum Rechenzentrum geflogen, um den infizierten Server zu lokalisieren und zu isolieren. *freu*

2. Ping

mr robot | multi-ping

Der Befehl selbst ist in der Sequenz nicht zu sehen aber dies könnte so ähnlich aussehen.

fping -g 194.122.82.0/24

Resultat: Ein Server ist noch aktiv, dies muss der Übeltäter sein …

3. Locate WBKUW300PS345672

mr robot |locate-server

Der gehackte Server soll in der nächsten Szene manuell durch den Backup-Server ersetzt werden. Es wird der Befehl „Locate“ ausgeführt, um sich zunächst an dem gehacktem Server anzumelden.

Der „locate“ Befehl ist eigentlich zum suchen von Dateien gedacht, aber diese wird ja auch klein geschrieben.

4. astsu

Hier wird außerdem der fiktive Befehl „astsu“ ausgeführt, um Informationen vom Netzwerk-Informationen vom Server zu erhalten.

Folgende Befehle funktionieren tatsächlich…

DNS:

cat /etc/resolv.conf

IP:

ifconfig

ROUTING:

route

mr robot | astsu-what

In der nächsten Szene sehen wir sowohl die vorherigen aus auch die nächsten Befehle welche auf der Konsole eingegeben wurden.

astsu -close port: * -persistent

Und wie wir sehen übernimmt der Befehl „astsu“ auch noch die Funktionalität von „iptables„. ;)

Locate BKUW300PS345672

Hier kommt nocheinmal der „Locate“ Befehl zum Einsatz, um sich auf den Backup-Server einzuloggen.

mr robot | server_backup

set waneth0* : * 23.234.45.1 255.255.255.0 [45.85.123.10; 45.85.124.10; 45.85.125.10]

Im Output kann man ein „false“ sehen, aber Elliot verwendet „-force“ um dieses Problem zu lösen. Natürlich ist auch diese Befehl ausgedacht, aber viele andere Linux Kommandos akzepieren ebenfalls einen „–force“ Parameter, daher ist dies gar nicht so abwegig.

set -force -ovr02 waneth04 : 23.234.45.62:441 23.234.45.1 255.255.255.0 [45.85.123.10; 45.85.124.10;

Um die IP-Adresse wirklich zu konfigurieren kann man z.B. „ifconfig & route“ oder „ip“ verwenden.

ip addr add 45.85.123.10/24 dev eth0

ip addr add 45.85.124.10/24 dev eth0

ip addr add 45.85.125.10/24 dev eth0

ip route add default via 23.234.45.1

Resultat: Der gehacket Server ist offline und der Backup-Server hat dessen Funktion übernommen.

5. ps aux | grep root

mr robot | ps-aux

ps aux | grep root

Nachdem die Gefahr gebannt ist, schau Elliot sich den gehackten Server noch einmal genauer an und findet einen Prozess (pid: 24) welcher mit höchster Priorität (-20) läuft.

astu trace -pid 244 -cmd

Hier tauch eine abgewandelte Version vom fiktiven Befehl „astsu“ auf, warum die pid 244 und nicht die 24 weiter untersucht wird, bleibt ungeklärt.

Um einen Prozess tatsächlich näher zu untersuch, würde ich zunächst folgende Befehle nutzen.

strace -p 24

lsof -p 24

nginx

Beispiel für „strace“ & „lsof“

6. ps aux | grep root | cpuset

mr robot | astu-what

ps aux| grep root | cpuset

„cpuset“ würde hier nicht funktionieren und ich bin mir nicht ganz sicher was „cpuset“ überhaupt macht?!

astu -ls ./root/fsociety/ -a

Nun wird der Inhalt vom Verzeichnis „/root/fsociety/“ angezeigt, folgender Befehl würde funktionieren.

ls -la /root/fsociety/

mr robot | more

Elliot schau sich nun die README Datei der Hacker an und möchte den Rootkit zunächst im folgenden löschen.

more readme.txt

astu -rm -norecycle /root/ fsociety/

Um das Verzeichnis wirklich zu löschen, müsste der folgende Befehl ausgeführt werden.

rm -rf /root/fsociety/

mr robot | chmod

Aber er entscheidet sich dagegen und ändert stattdessen die Berechtigungen der Datei, so dass nur noch er selber Zugriff darauf hat.

chmod -R ER280652 600

Auch dieser Befehl wird so nicht funktionieren, da man „chmod“ und „chown“ unterscheidet. Folgende Befehle würden funktionieren.

chmod -R 600 /root/fsociety/

chown -R ER280652 /root/fsociety/

Resultat: Der ursprüngliche Server ist offline, der Backup-Server ist online und der Rootkit ist noch immer im System.

Fazit: echo „Ich mag diese Serie.“ | sed ’s/Serie/Nerd-Serie/‘

Admin meets Frontend

… oder was „JavaScript“ und „Shell-Script“ gemeinsam haben.

Zu beginn muss ich zugeben, dass ich bei meinen ersten Skripten auch nicht auf den Sichtbarkeitsbereich von Variablen (Scope) geachtet habe. Wenn man sich jedoch etwas mit Softwareentwicklung auseinandersetze stellt man schnell fest, dass globale Variablen direkt aus der Hölle kommen und nichts im Quelltext zu suchen haben.

Range_of_Variables

Variablen sind zumindest in der Shell und in JavaScript zunächst global, selbst innerhalb von Funktionen und werden erst durch den Zusatz „var“ bzw. „local“ zur lokalen Variable. In vielen anderen Programmiersprachen erkennt man den Scope einer Variable direkt im Zusammenhang, ist z.B. eine Variable innerhalb einer Methode deklariert, so ist diese nur innerhalb dieser Methode verfügbar. Wird die Variable jedoch innerhalb der Klasse deklariert, so ist diese für die ganze Klasse und somit für alle Ihre Methoden verfügbar.

Es folgen ein paar Beispiele, wo der Inhalt (Title der Beiträge) des RSS-Feeds von „planet.ubuntuusers.de“ ausgegeben werden soll.

JS-Beispiel: mit globalen Variablen

test-1

Um dies selber zu testen, öffne die Verlinkte Datei im Browser (leere Webseite) und öffne die Entwicklertools (F12), schalte die Ansicht auf „Konsole“ und lade die Seite neu. Im Quelltext sind ausschließlich globale Variablen verwendet, jedoch funktioniert dieses Script „leider“ wie gewünscht. Das Problem mit globalen Variablen ist, dass man den Quelltext dadurch ggf. schwerer lesen kann und diesen nicht wiederverwenden kann. Wenn man z.B. verschiedene Funkionen als unterschiedlichen Skripten zusammenfügt oder zusammen nutzen möchte, welche jedoch ebenfalls globale Variablen nutzen, dann können da sehr eigenartige Ergebnisse bei herauskommen.

JS-Beispiel: mit lokalen Variablen

test-1_1

test-1_1_2

 

In den DevTools von Chrome kann man jetzt den entsprechenden Variablen-Scope sehen. Jedoch ist der Quellcode noch nicht wirklich wiederverwendbar, da wir das zu lösende Problem (also das laden und parsen einer JSON-Datei) nicht auf eine eigene Abstraktionsschicht gebracht haben.

JS-Beispiel: mit lokalen Variablen und Klassen

test-1_2

In diesem Beispiel wurde nun die Klasse „PlanetUbuntuuserJsonData“ erstellt welche wiederum von der Klasse „JsonData“ dessen Eigenschaften (Variablen & Methoden) erbt. Leider ist der Quelltext hierbei von zirka 50 auf zirka 80 Zeilen erhört worden und funktioniert dabei z.B. nicht im IE < 10. (siehe Kommentare im Quelltext)

JS-Beispiel: ohne Variablen + jQuery

test-2

Dieses Beispiel benötigt zwar die „jQuery“-Bibliothek, welche jedoch bereits entsprechende Funktionalitäten kapselt. Vergleich man diesen Quellcode mit der Vorherigem Version, kann man schnell erkennen, das entschieden weniger Quellcode deutlich besser zu lesen ist. ;-)

Shell-Beispiel: mit globalen Variablen (test_1.sh)

test-bash

In diesem Beispiel sind wieder sehr viele globale Variablen verwendet und wieder funktioniert das entsprechende Skript „leider“ trotzdem. Die Funktion „parse_json()“ gibt nicht einmal einen Rückgabewert zurück, dafür teilen sich die beiden Funktionen die Variablen. Und im Grunde könnte man den ganzen Quelltext auch einfach ohne Funktionen untereinander schreiben, dies hätte den selben Effekt.

Shell-Beispiel: mit lokalen Variablen (test_2.sh)

Die entsprechende Ausgabe ist bereits im Vorherigen Bild zu sehen. Bei Shell-Skripten kommt es seltener vor, dass man dessen Funktionalität wirklich wiederverwenden möchte, jedoch ist der Quelltext deutlich besser zu lesen, wenn man entsprechende Rückgabewerte und Übergabeparameter verwendet.

Quellen / Links:
– Shell: Advanced Bash-Scripting Guide
– Shell: Coding-Style-Guide von „Oh My Zsh“
– JS: Sichtbarkeitsbereich (Scope) von Variablen
– JS: Objektattribut

 

I ❤ ~/

Vor einiger Zeit habe ich bereits einen Blog-Post über meine „.dotfiles“ geschrieben, jedoch habe ich mich damals mehr auf die Installation beschränkt und habe keine Beispiele gezeigt, so dass man den Vorteil der .dotfiles nur schwer erfassen konnte.

Außerdem benötigt man ggf. nur einige Funktionen oder Dateien um sein System an an seine Bedürfnisse anzupassen. Auf der Webseite GitHub ❤ ~/ gibt es sehr gute .dotfiles Sammlungen, welche man einfach „forken“ und anpassen und nutzen kann.

PS: wer sich bisher nicht mit „git“ auskennt, sollte sich einmal eines der folgenden interaktiven git-Tutorials anschauen:
try.github.io/
pcottle.github.io/learnGitBranching/
gitreal.codeschool.com/


Beispiele zu meinen .dotfiles:

Navigation:
https://github.com/voku/dotfiles/blob/master/.aliases#L75 easier navigation via aliases

Farben für die Kommandozeile:
https://github.com/voku/dotfiles/blob/master/.aliases#L116color for ping / traceroute / ps / top / ...

difflight & filename auto-completion via zsh

Nützliche Shortcuts: z.B. date_*
https://github.com/voku/dotfiles/blob/master/.aliases#L295
more useful shortcuts

Copy&Past via „getclip“ und „putclip“: https://github.com/voku/dotfiles/blob/master/.aliases#L368copy text via "getclip" & putclip

kill & pkill via z-shell: https://github.com/voku/dotfiles/blob/master/.redpill/lib/4_completion.zsh#L122kill & pkill via z-shell

grep & ack: https://github.com/voku/dotfiles/blob/master/.aliases#L242grep & ack

git via z-shell: https://github.com/voku/dotfiles/blob/master/.gitconfiggit via z-shell

„ls“-aliases: https://github.com/voku/dotfiles/blob/master/.aliases#L196optimized "ls"-aliases

vim » Automatisch zur letzten Position springen 
https://github.com/voku/dotfiles/blob/master/.vimrc "vim" » jump to last position

vim » Schell-Suche via „#“ "vim" » quick search via "<#>" or "*"

vim » markieren Leerzeichen am Ende der Zeile"vim" » highlight trailing spaces in annoying red

vim » Tabs nutzen
https://github.com/voku/dotfiles/blob/master/.vimrc#L564
vim » NERD Tree via „,“ + „-„
https://github.com/voku/dotfiles/blob/master/.vimrc.bundles#L18"vim" » "tabs" & "file-view"

vim » Autovervollständigung via Tabulatur-Taste
https://github.com/voku/dotfiles/blob/master/.vimrc#L755"vim" » tab-completion


Erklärungen zu meinen .dotfiles:

.config_dotfiles

In dieser Datei kann man Einstellungen für meine .dotfiles vornehmen. Wenn du z.B. deinen Standard-User-Namen in der Variable „CONFIG_DEFAULT_USER“ hinterlegst, wird diese nicht mehr in der Shell-Prompt angezeigt.

.path

In dieser Datei kannst du Pfade zu deinen Ausführbaren Dateien einfügen, so dass du diese ohne Angabe des Pfades ausführen kannst.

Diese Datei ist nicht im öffentlichen Repository und ist via „.gitignore“ aus git verbannt, da es vertrauliche Informationen enthalten kann. z.B.: export PATH=“$HOME/utils:$PATH“

.load

In dieser Datei laden wir weitere optionale Einstellungen, welche ggf. gar nicht installiert und somit auch nicht geladen werden müssen.

.colors

Hier definieren wir einige Farben, welche dann in den folgenden Dateien verwendet werden können. z.B.: COLOR_BLACK=\e[0;30m

.exports

Variablen in Shell-Scriptes verhalten sich so ähnlich wie in JavaScript. Variablen sind Standardmäßig „global“, dass heißt selbst Variable innerhalb einer Funktion sind anschließend auch außerhalb der Funktion verfügbar. Daher verwenden wir „local“ innerhalb von Funktionen, für Variablen welche nur innerhalb der Funktion zur Verfügung steht sollen. Außerdem können wir Variablen via „export“ exportieren, so dass diese nicht nur zur Ausführungszeit, sondern anschließend ebenfalls allen Kindprozessen als Umgebungsvariable zur Verfügung stehen.

.icons

Wie die Farben werden auch die entsprechenden Icons exportiert, so dass wir diese anschließend in Funktionen etc. nutzen können.

.aliases

In dieser Datei werden Abkürzungen für komplexe Befehle oder / und Fallbacks definiert, welche anschließend als Befehl ausgeführt werden.

z.B.:
alias starwars=’telnet towel.blinkenlights.nl‘
alias sgrep=’grep -R -n -H -C 5 –exclude-dir={.git,.svn,CVS}‘

.bash_complete // completion.zsh

Auch wenn die „Z-Shell“ (zsh) bessere Tabcompletion bietet, kann man auch in der „Bash“ einige  Tabcompletion-Features nutzen.

z.B.:

apt- [Tabulator]
apt-g [Tabulator]
apt-get [Tabulator]
apt-get i [Tabulator]
apt-get install [Tabulator] [Tabulator]
apt-get install apa [Tabulator]

.functions

Hier habe ich einige praktische Funktionen gesammelt, welche ich öfters nutze und nicht als Plugin auslagern möchte.

z.B.:
lman() -> „Open the manual page for the last command you executed“
netstat_free_local_port() -> „get one free tcp-port“
iptablesBlockIP() -> „block a IP via ‚iptables'“

Überlegungen: In der „normalen“ Programmierung nutzt man lowerCamelCase für normale Variablen / Funktionen und Methoden, jedoch sind eigentlich alle Funktionen in der Shell lowercase z.B.: whoami, updatedb, killall. Ich mich dafür entschieden mich bei neuen Funktionen und Aliases an einem Original-Befehl zu orientieren, so dass man diese nicht neu lernen muss, sondern diese via [Tabulator] nutzen kann.

.extra

Auch diese Datei ist nicht im öffentlichen Repository und ist via „.gitignore“ aus git verbannt, da es vertrauliche Informationen enthalten kann. Hier kann man alle zuvor gesetzten Variablen, Einstellungen, Funktionen überschreiben oder ergänzen.

ShellShock – Sicherheitsproblem bei der Unix-Shell $(bash)

Alle alten Version der Unix-Shell „bash“ enthalten eine kritische Sicherheitslücke (CVE-2014-6271), so dass man Befehle z.B. über CGI-Skripte oder via DHCP ausführen kann.  Ggf. benötigt nun dein Handy (z.B. CyanogenMod), dein Router oder deinen Mac / Linux / BSD und so weiter Software-Updates.

Teste dein System:

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

vulnerable
this is a test

Nachdem man die aktuellen Updates eingespielt hat (z.B. via aptitude) dann sollte die Ausgabe folgendermaßen aussehen.

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

bash: warning: x: ignoring function definition attempt bash: error importing function definition for `x‘ this is a test

Technische Erklärung:

(http://seclists.org/oss-sec/2014/q3/650)
Das Problem ist, dass das man zwischen unterschiedlichen Bash-Instanzen Variablen und Funktionen teilen kann.

export foo='() { echo "bar" ; }'
bash -c 'foo'

Jede neue Bash-Instanz wird nun beim Start die Funktion „foo“  registrieren, so dass man diese Ausführen kann. Wenn man nun jedoch eine Funktion exportiert, führt die Bash den nächsten Befehl ebenfalls aus, da der String der „() {“ nicht korrekt geparst wird. Damit können wir nun Befehle ausführen, indem wir bestimmte Strings (Funktionsdefinitionen) an z.B. ein CGI-Skript übergeben.

Links:

http://www.heise.de/newsticker/meldung/Bash-Luecke-ShellShock-ist-noch-nicht-ausgestanden-2403607.html

http://www.heise.de/newsticker/meldung/ShellShock-Standard-Unix-Shell-Bash-erlaubt-das-Ausfuehren-von-Schadcode-2403305.html

http://ftp.gnu.org/pub/gnu/bash/bash-4.3-patches/bash43-025

 

Kurztipp: lokalen offenen Port finden (bash)

Habe soeben folgende Funktionen zu meinen dotfiles hinzugefügt, um einen freien lokalen Port zu finden. Diese werden wiederum verwendet, um z.B. die „phpserver„-Funktion auszuführen.

# -------------------------------------------------------------------
# netstat_used_local_ports: get used tcp-ports
netstat_used_local_ports()
{
  netstat -atn | awk '{printf "%s\n%s\n", $4, $4}' | grep -oE '[0-9]*$' | sort -n | uniq
}

# -------------------------------------------------------------------
# netstat_free_local_port: get one free tcp-port
netstat_free_local_port()
{
  read lowerPort upperPort < /proc/sys/net/ipv4/ip_local_port_range
 
  # create a local array of used ports 
  local all_used_ports=($(netstat_used_local_ports))

  for port in $(seq $lowerPort $upperPort); do
    for used_port in "${all_used_ports[@]}"; do
      if [ $used_port -eq $port ]; then
        continue
      else
        echo $port
        return 0
      fi
    done
  done 
}

 

Web Development mit Linux (Video)

Im folgenden Video zeige ich kurz (~ 5 min.) wie meine Toolchain im Live-Betrieb aussieht, dabei nutze ich unter anderem Sublime Text, PHP, Twig, Grunt, Sass, Compass, LiveReload und ein paar Funktionen aus den „dofiles“ (z.B. phpserver).

 

Wer den Beispiel-Code aus dem Video selber ausprobieren möchte, hier die Zusammenfassung:

sudo apt-get install git

cd ~
git clone https://github.com/voku/dotfiles/
cd dotfiles/
./firstInstall.sh
./bootstrap.sh
cd ~
vim ~/.extra #1

cd ~
mkdir Projects/
git clone https://github.com/voku/twig-wrapper-example/
cd twig-wrapper-example/
npm install
grunt watch

cd ~/Projects/twig-wrapper-example/
phpserver

#1 füge deine persönlichen Git-Einstellungen hier hinzu

 

Wer mehr Infos oder Erklärungen zu den hier verwendeten Tools haben möchte, sollte sich einmal folgende Videos anschauen: suckup.de/howto/html/moderner-build-development-workflow-via-bower-grunt-yeoman/

 

Kurztipp: mysqldump + Views

Problem: „DEFINER“

Jeder MySQL-Dump welcher mit dem Befehl „mysqldump“ erstellt wird beinhalte die Einstellung zum „DEFINER“.

z.B.: DEFINER=`root`@`localhost` SQL SECURITY DEFINER

Dies bedeutet, dass man diesen SQL-Dump nicht einfach z.B. auf dem Ziel-Server nutzen kann, da die Applikation wahrscheinlich / hoffentlich keinen Root-Zugriff auf die Datenbank hat.

Lösung: via „grep“

Als schnelle Lösung für diese Problem entferne ich einfach den entsprechenden DEFINER-Eintrag.

mysqldump -u your_user --skip-comments --skip-opt --complete-insert --databases your_db | grep -v 'SQL SECURITY DEFINER' > ~/your_dump.sql

http://gist.suckup.de/tpl_default.php?pid=1#sec_fb936cf7878c32a5f0b0

Tipp im Tipp

Falls man mit Windows arbeiten muss, empfehle ich die Git-Bash (MinGW + GIT) zu installieren und das „mysql/bin“ Verzeichnis im Windows PATH (System -> Erweiterte Systemeinstellungen -> Umgebungsvariablen) einzutragen. So kann man den oben genannten Befehl (und vieles mehr) auch unter Windows nutzen!

 

Links & Quellen:

– http://dev.mysql.com/doc/refman/5.1/de/create-view.html
– http://www.sitepoint.com/mysql-views/
– http://www.mingw.org/
– http://msysgit.github.io/

Prompt › Bash

Ich habe schon vor einiger Zeit über die „.bashrc“ berichtet und hier die Installation meiner dotfiles [~/.*] vorgestellt.

Heute möchte ich an einigen Bildern zeigen wie die Bash aussieht nachdem man die bereits erwähnten dotfiles installiert und wie man diese nach seinen Wünschen anpasst.

bash_prompt

1.) der Code

.bashrc: Dies ist die Konfigurationsdatei der Bash, diese wird bei jedem Aufruf einer interaktiven Shell ausgeführt. In meiner .bashrc stehen zunächst einmal ein paar Informationen, wovon ich hier nur die entsprechenden Links nennen möchte, welche man sich einmal anschauen sollte:

– http://www.kfirlavi.com/blog/2012/11/14/defensive-bash-programming/
– www.commandlinefu.com/commands/browse/sort-by-votes
– https://twitter.com/climagic

.bash_profile: Diese Datei hat die selbe Aufgabe wie die .bashrc, wird jedoch „eigentlich“ nur für Login-Shells aufgerufen. In diesem Fall wird die Datei jedoch auch für interaktive Shells verwende, da wir diese in der .bashrc inkludiert haben.

for file in ~/.{path,colors,icons,exports,aliases,bash_complete,functions,extra,bash_prompt}; 
do [ -r "$file" ] && [ -f "$file" ] && source"$file" 
done 
unset file

In dieser Datei werden wiederum andere Shell-Konfigurationen geladen (siehe vorheriges Code-Beispiel), welche auch von anderen Shells (z.B.: der zsh) genutzt werden können.

Desweiteren werden einige Einstellungen in einer zweiten for-Schleife ausgeführt. Andere Einstellungen sind näher beschrieben bzw. nur für nicht root-User geeignet und werden daher einzeln ausgeführt.

 .bash_prompt: Wie wir im vorherigem Code-Ausschnitt sehen konnten, wird diese Datei zum Schluss geladen, so dass wir zuvor definierte Funktionen und Variablen verwenden können.

# Local or SSH session?
local remote=""
[ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ] && remote=1

Wir prüfen, ob es sich hier um ein lokales Terminal oder um eine SSH Verbindung handelt, so dass wir den Hostnamen nur anzeigen, wenn dieser auch benötigt wird.

# set the user-color
local user_color=$COLOR_LIGHT_GREEN           # user's color
[ $UID -eq "0" ] && user_color=$COLOR_RED     # root's color

Root-User bekommen in der Prompt einen Roten-Usernamen angezeigt.

PS: die User-ID (UID) ist in der passwd zu finden: „cat /etc/passwd“

# set the user
local user="\u"

Die Zeichenkette „\u“ wird beim Aufruf der Bash-Prompt in den entsprechenden Usernamen umgewandelt.

PS: hier gibt es eine Übersicht über weiter Zeichenketten, welche von der Bash-Prompt verarbeitet werden können z.B. die Uhrzeit

# set the hostname inside SSH session
local host=""
[ -n "$remote" ] && host="\[$COLOR_LIGHT_GREEN\]${ICON_FOR_AT}\h"

Wie bereits erwähnt zeigen wir den Hostnamen („\h“) nur an, wenn es sich um eine Remote-Verbindung handelt.

if [[ -n $remote ]] && [[ $COLORTERM = gnome-* && $TERM = xterm ]] && infocmp gnome-256color >/dev/null 2>&1; then
  export TERM='gnome-256color'
elif infocmp xterm-256color >/dev/null 2>&1; then
  export TERM='xterm-256color'
fi

256 Farben in der lokalen Shell verwenden.

# INFO:   Text (commands) inside \[...\] does not impact line length calculation which fixes stange bug when looking through the history
#         $? is a status of last command, should be processed every time prompt prints

Da der Bash-Prompt bestemmte Zeichen nicht mag und wir davon einige in der bereits inkludierten „.colors„-Datei verwendet haben, müssen wir diese Variablen nun hier escapen.

# Format prompt
export PS1="\`if [ \$? -eq 0 ]; then echo -e \[\$COLOR_GREEN\]\${ICON_FOR_TRUE}; else echo -e \[\$COLOR_RED\]\${ICON_FOR_FALSE}; fi\` \[$user_color\]${user}${host}\[$user_color\]:\[$COLOR_LIGHT_BLUE\]\w\[$COLOR_LIGHT_RED\]${ICON_FOR_ARROW_RIGHT}\$(__git_branch)\$(__svn_branch)\$(__git_dirty)\[$COLOR_NO_COLOUR\] "

Der Prompt wird in der Variable PS1 („echo $PS1“) gespeichert und nach jedem Befehl auf der Kommandozeile neu aufgerufen / ausgeführt, daher rufen wir in der Variable wiederum Funktionen auf, so dass diese Funktionen ebenfalls erneut ausgeführt werden.

PS: „$?“ muss als erstes ausgeführt werden, da dieser Befehl den Rückgabewert des letzten Kommandos zurückliefert

2.) Beispiele

bash_prompt_false

– Root-User wird rot gekennzeichnet

– „“ anzeigen, wenn der letzte Befehl nicht korrekte funktioniert hat

 

bash_prompt_remote

– Anzeigen des Hostnamens nur bei Remoteverbindungen

– Repository-Branch (git, svn) anzeigen

–  Repository-Status anzeigen (! anfügen, wenn etwas nicht eingecheckt ist)

 

Links & Quellen:

http://wiki.ubuntuusers.de/Bash/Prompt
https://wiki.archlinux.de/title/Bash-Prompt_anpassen
http://ezprompt.net/

CSS > SCSS > CSS

Neue Webseiten werden heutzutage oft via SASS erstellt, aber was macht man mit alten Projekten? Kann man auch hier SASS einsetzten? – Ja! Das schöne an „SCSS“-Dateien ist das diese 100% mit CSS kompatibel sind, so dass man die entsprechende Dateiendung umbenennen kann und neue / kleine Anpassungen in der SASS-Syntax schreiben kann. Wer jedoch eine ganze CSS-Datei auf den SCSS-Style anpassen möchte kann z.B. den „sass-convert“-Befehl auf der Kommandozeile verwenden.


See the Pen tqJvn by Lars Moelleken (@voku) on CodePen.
1

CSS > SCSS

Mit dem folgendem Befehl kann man die CSS-Datei in eine SCSS-Datei umwandeln lassen.

sass-convert --from css --to scss test.css test.scss


See the Pen Arxuv by Lars Moelleken (@voku) on CodePen.
1

Es folgt eine kleine manuelle Optimierung, dabei gilt: Umso besser die ursprüngliche CSS-Datei aufgebaut war, desto besser kann diese konvertiert werden.


See the Pen eFdlJ by Lars Moelleken (@voku) on CodePen.
1

SCSS > CSS

Nun erstellen wir aus der neuen SCSS-Datei wieder eine CSS-Datei + Sourcemap

scss  --sourcemap --line-comments --style expanded test.scss test_new.css


See the Pen pErjB by Lars Moelleken (@voku) on CodePen.
1

PS: mithilfe der Source Map kann Chrome automatisch die entsprechenden Code-Stellen in der entsprechenden SCSS-Datei  anzeigen :)

 

Links:
http://sassmeister.com/
http://css-tricks.com/sass-style-guide/

Quellen:
http://sass-lang.com/documentation/file.SASS_REFERENCE.html#output_style