Category Archives: Linux/BSD

Nagios check_disk wrapper für PHP

Manchmal muss man auch mal die Disk durch einen einfachen HTTP request abfragen. Warum also nicht bestehende Scripte, wie das Nagios Plugin check_disk dafür verwenden. Anbei ein kleines Script, dass genau dieses macht. Eine kleine Einschränkung, der HTTP Response Code ist bei Warning und Critial der gleiche – natürlich leicht zu erweitern ;)

<?php

// global binary
$NAGIOS_DISK = "/usr/lib/nagios/plugins/check_disk";
$DISK_KEY = "Uvg2kFMfy3DU";

if (isset($_GET['key'], $_GET['w'], $_GET['c'])) {
	// okay
	$key = $_GET['key'];
	$warning = $_GET['w'];
	$critical = $_GET['c'];

	if(! (preg_match('/^[0-9]+%$/', $warning) && preg_match('/^[0-9]+%$/', $critical)) ) {
		echo "Critical or Warning values are not a valid value.\n";
		header("HTTP/1.0 510 Not Extended");
		exit;
	}

	if ($key == $DISK_KEY ) {
		// correct key

		$return = shell_exec("$NAGIOS_DISK -l -x /dev/shm -w $warning -c $critical");

		if (stripos($return,"OK")) {
			print "$return\n";
			header("HTTP/1.0 200 Okay");
		} else {
			print "$return\n";
			header("HTTP/1.0 507 Insufficient Storage");
		}

	} else {
		print "ERROR\n";
		header("HTTP/1.0 401 Unauthorized");
	}

} else {
	// error
	print "ERROR\n";
	header("HTTP/1.0 418 I’m a teapot");
}

?>

Android und OpenVPN

Auf einem aktuellen Android (4.x) einen OpenVPN Client einzurichten ist dank OpenVPN for Android auch kein Problem mehr. Einfach die App installieren und man könnte eigentlich schon fast loslegen, wenn man auch einen OpenVPN Server hätte.

Die Jungs von Tinfoil Security haben sich ein paar Minuten hingesetzt und haben ein sicheres Script geschrieben, dass einen Server in Minuten aufsetzt. Dieses ist zwar nur für Debian basierte Systeme geeignet, aber das sollten die meisten sein die man mal so hat. Notfalls kann man sich schnell ein Droplet bei DigitalOcean, etc. einrichten.
Das Script muss man als root ausführen und es erstellt die Server und Client Konfiguration, sowie das Zertifikat. Anschließend muss man nur noch /etc/openvpn/client.ovpn sicher (nein nicht per Email!) auf sein Android laden und man kann sich per ipv4 sicher in öffentlichen Netzen herumtreiben. Happy VPN!

Offene SSH Verbindungen anzeigen

Wow! Ich glaube das ich den Blog ein bisschen vernachlässigt habe. Es sind schon ein paar Monate vergangen seitdem ich das letzte mal etwas geschrieben habe, aber natürlich war ich in der IT nicht untätig. Bin jedoch seit ein paar Wochen kein Blackberry jünger, sondern ein Android Evangelist geworden und bin mit dem Nexus 5 super zufrieden.

In den vergangenen Monaten habe ich selber natürlich in vielen Blogs und Seiten gelesen und dabei recherchiert. So viele Leute beteiligen sich am Open Source und so will ich auch mal wieder was der Community zurückgeben – so gut es geht.

Fangen wir mal etwas klein an und als erstes gibt es ein Script das ganz einfach offene SSH Verbindungen anzeigt und man sich somit schnell auf einen Server einloggen kann. Das ist sehr Hilfreich, wenn man auf vielen Server unterwegs ist und deren DNS oder IP man nicht immer im Kopf hat. Leider hatte ich noch nicht die Lust das Script “IPv6 ready” zu machen, aber vielleicht findet sich da ja jemand ;)

Update: Das Script kann jetzt ordentlich mit v6 umgehen und auch Optionen der SSH Verbindung. Läuft wunderbar unter Linux und MacOSX.

Update 2: noch besser: https://github.com/bert2002/ossh

Blackberry BB10 Webworks SDK auf Linux

Bisher musste ich immer ein Windows oder MacOSX dafür missbrauchen meine Blackberry Applikationen zu bauen, aber das wird sich für BB10 sehr schnell ändern. Das BB10 Webworks SDK wird zwar nicht offiziell unterstützt, aber badtoyz ist es gelungen, relativ einfach, das SDK auf Linux zu portieren.

Was brauchen wir?

  • Java
  • Signing Keys (entweder von einer alten Installation oder über das Native SDK erstellbar)
  • BB10 Webworks SDK von badtoyz

Falls man seine Singin Keys von einer vorherigen Installation benutzen will, benötigt man ein paar Dateien: yourkeyname.p12, barsigner.csk and barsigner.db. Die befinden sich, je nach Betriebssystem, an unterschiedlichen stellen:

  • Windows® XP:  %HOMEPATH%\Local Settings\Application Data\Research In Motion
  • Windows Vista® and Windows 7®:  %HOMEPATH%\AppData\Local\Research In Motion
  • Mac OS:  ~/Library/Research In Motion

Die Keys kopieren wir nach: ~/.rim/ Wenn jedoch das Native SDK benutzt werden soll,brauchen wir nach Erhalt der Keys diese noch aktivieren:

blackberry-signer -register -csjpin PIN -storepass KeystorePassword AppSigningCSJFile DebugTokenCSJFile

Als nächstes brauchen wir das SDK und das bekommen wir am besten direkt über guthub:

$ git clone https://github.com/badtoyz/BB10-WebWorks-SDK-Linux.git
Cloning into ‘BB10-WebWorks-SDK-Linux’…
remote: Counting objects: 527, done.
remote: Compressing objects: 100% (413/413), done.
remote: Total 527 (delta 65), reused 525 (delta 63)
Receiving objects: 100% (527/527), 10.54 MiB | 887 KiB/s, done.
Resolving deltas: 100% (65/65), done.

Über git kann man dann auch das SDK aktuell halten und ich empfehle jedem @bbdevlinux und @badtoyz zu folgen um auf dem aktuellen Stand zu bleiben.

Jetzt haben wir das BB10 Webworks SDK auf Linux und können direkt die erste Applikationen bauen. Ich habe dazu die bbui.js samples genommen:

bbwp samples.zip -g KeyStorePassword -buildID number -o /path/to/folder

So einfach ist das und da fragt man sich doch warum RIM das nicht selber unterstützt…

GIT auf Low-End Server

Wenn man auf einem System mit wenig Arbeitsspeicher, aber einem großen Repo arbeite kann es beim pushen von dem git zu Speicherproblemen kommen. Als Abhilfe ist es möglich dem git einen Limit für der verbrauch vom Speicher zu setzen.

$ git push master
user@example.orge’s password:
Counting objects: 139, done.
Delta compression using up to 2 threads.
error: pack-objects died of signal 9
error: pack-objects died with strange error
[…]

Lösung:

$ git config –global pack.windowMemory “32m”
$ git config –global pack.SizeLimit “32m”
$ git config –global pack.threads “1”

WordPress XMLRCP API

Ich glaube die WordPress API ist einer der am wenigsten dokumentierten API die ich jemals gesehen habe. Deswegen gibt es jetzt ein Beispiel um in Perl ein Bild hochzuladen, einen Post zu erstellen mit Categories, Custom Fields und einem Featured Image.

#!/usr/bin/perl
# script: publish article to a wordpress blog using XMLRPC interface. Uploading a picture and setting this as a featured image. Additionally add custom fields.
# author: <bert2002>
use strict;
use utf8;
use XMLRPC::Lite;
use IO::Socket::SSL;
my ($buf,$contents);
my $pictureid;
my @categories;
# settings
my $username = “USERNAME”;
my $password = “PASWORT”;
my $server = “https://www.yourblog.com/xmlrpc.php”;
my $image = “PATHtoIMAGE”
my $htmlpost = “THErealCONTENT”;
# upload picture to wordpress
open(FILE, “$image”) or die “$!”;
while (read(FILE, $buf, 60*57)) {
        $contents .= $buf;
}
close(FILE);
my $res = XMLRPC::Lite
->proxy($server)
->call(‘metaWeblog.newMediaObject’, 1, $username, $password,
{ name => $image, type => ‘image/jpeg’, bits => $contents } )
->result;
if (defined ($res)) {
$pictureid = $res->{id};
print “. picture uploaded with id $pictureid\n”;
} else {
        print ” .. uploading picture failed: $!”;
}
# post article to wordpress
my $publishdate = “20100220T12:34:56”;
# prepare categories
my $multicategories = “cat1 cat2 cat3”;
@categories = split(/ /, $multicategories);
# finally create that fucking post
my $res = XMLRPC::Lite
->proxy($server)
->call(‘metaWeblog.newPost’, 1, $username, $password,
{
        categories => \@categories,
        custom_fields => [
                { “key” => “keyone”, “value” => “value one” },
                { “key” => “keytwo”, “value” => “value two” }
        ],
        description => $htmlpost,
        title => $productname,
# dateCreated => $publishdate,
        mt_allow_comments => 0,
        wp_post_thumbnail => $pictureid,
}, 1)->result;
if (defined ($res)) {
        print “. posted article id $res and picture id $pictureid\n”;
} else {
        print “.. posting article with id $res failed: $!”;
}
 oder auf gist.github.com

Raspberry Pi + Squid + Block Ads

Machen wir in meiner kleinen Pi Serie weiter. Auf normalen Desktop Computern hat man eigentlich immer AdBlock im Browser aktiviert um lästige Werbung loszuwerden. Auf den “neuen” Geräten wie Smartphone oder Tablet sind diese nicht verfügbar und man muss einen kleinen Umweg gehen.

Was bietet sich also nicht eher an als einen Proxy aufzusetzen und unerwünschten Inhalt zu filtern? Zensur im eigenen Netzwerk, basierent auf der Anleitung von calomel.org! Dank an pgl.yoyo.org gibt es eine ordentliche Liste die auch noch immer aktualisiert wird. Man kann sich die Liste in mehrere Formate ausgeben lassen und die Domains/IPs auch gerne per iptables sperren. Ich gehe den Weg des Proxies, weil zum Beispiel mein Blackberry Playbook kein IPv6 kann (ARGH!) (muss nur im Wlan Profil aktiviert werden) und ich durch den Proxy wenigstens sekundär v6 benutzen kann. Also erstmal Squid3 installieren, weil Squid2 kein v6 kann:

# apt-get install squid3

In der Konfiguration /etc/squid3/squid.conf müssen wir folgenden Eintrag hinzufügen. Dieser muss vor allen anderen acl Einträgen stehen (ungefähr Zeile: 693) und sieht folgendermaßen aus:

acl ads dstdom_regex "/etc/squid3/ad_block.txt"
http_access deny ads

Damit haben wir Squid gesagt, dass es allen Zugriff auf die Domains in der txt Datei sperren soll. Die Liste der zu sperrenden Domains erhalten wir durch einen Cronjob den wir uns schreiben:

#!/bin/bash
# script: update ad server list
# get new ad server list
wget -q -t 5 'http://pgl.yoyo.org/adservers/serverlist.php?hostformat=squid-dstdom-regex&showintro=0&mimetype=plaintext' -O /etc/squid3/ad_block.txt

# refresh squid /usr/sbin/squid3 -k reconfigure

Das Script speichern wir unter /etc/squid3/fetch_adserver.sh. Es lädt sich die Liste herunter und Squid wird dazu gezwungen die Liste neu einzulesen. Ein einfacher Cronjob führt das Script alle drei Tage aus:

35   5    *   *   */3 /etc/squid3/fetch_adserver.sh >> /dev/null 2>&1

Erstmalig das Script per Hand ausführen und die Datei erstellen. Squid wird automatisch neu geladen und schon kann man surfen. Ach auf dem Playbook macht es wieder mehr Spaß :)

Vorher:

Nachher:

Damit man nicht zu viele Fehlermeldungen vom Squid im Browser sieht, sollte man noch die Datei ” /usr/share/squid3/errors/English/ERR_ACCESS_DENIED” bearbeiten und die Fehlermeldungen entfernen. Dabei sollte man den Inhalt einfach durch ein “<a>” ersetzen.

Raspberry Pi + IPv6 Gateway

Mein Pi soll als mein IPv6 Gateway dienen, weil mein normaler Router leider nichts kann. Momentan muss man leider noch _sehr_ darauf achten welches Image man benutzt, weil nicht alle IPv6 unterstützen und ip6tables. Es sieht also noch sehr düster aus. Wenn man aber endlich eins gefunden hat und sich irgendwo einen Tunnel besorgt hat. Am Ende habe ich mich für eine Private Lösung entschieden, weil Sixxs einfach zu lange braucht :)

Bei ipv6 ist es eigentlich normal das man eine IP + ein 64er Netz bekommt. Warum? Die einzelne IP dient dazu die Verbindung zum Anbieter aufzubauen und das Netz kann dazu benutzt selber zu announcen oder als Service IPs zu benutzen. Man wirft also sprichwörtlich mit IP Adressen um sich… wenn man es hat…

Wenn man also seine IP und vielleicht später sein Netz bekommen hat kann man anfangen sein Pi in einen IPv6 Router umzuwandeln. Als erstes sollten wir dem Kernel erlauben v6 Pakete weiterzuleiten:

/sbin/sysctl -w net.ipv6.conf.all.forwarding=1

Es empfiehlt sich dies in der /etc/sysctl.conf zu verewigen, damit es auch nach einem Neustart automatisch gesetzt wird. In meinem Beispiel werde ich mein v6 Netz über ein tap0 Gerät laufen, dass kann bei jedem anders sein. Es ist keine Hexerei und einfacher geht es eigentlich nicht:

# single ip address
/sbin/ip -6 a a 2c01:118:a315:12::13/64 dev tap0
# default route to my provider
/sbin/ip -6 route add default via 2c01:118:a315:12::1 dev tap0
# my 64 network
/sbin/ip -6 a a 2c01:118:a315:44::1/64 dev eth0

Wie man erkennen kann habe ich meine einzelne IP auf dem tap0 Gerät und mein Netz auf eth0, damit ich das später in meinem “privaten” Netzwerk announcen kann. Jetzt sollte es schon möglich sein v6 Adressen zu erreichen. Dies testen wir mit einem simplen ping Test:

# ping6 itbert.de -c 5
PING itbert.de(2001:4d88:1ffc:4f6::1) 56 data bytes
64 bytes from 2001:4d88:1ffc:4f6::1: icmp_seq=1 ttl=56 time=22.9 ms
64 bytes from 2001:4d88:1ffc:4f6::1: icmp_seq=2 ttl=56 time=26.4 ms
64 bytes from 2001:4d88:1ffc:4f6::1: icmp_seq=3 ttl=56 time=20.4 ms
64 bytes from 2001:4d88:1ffc:4f6::1: icmp_seq=4 ttl=56 time=21.2 ms
64 bytes from 2001:4d88:1ffc:4f6::1: icmp_seq=5 ttl=56 time=23.0 ms

— itbert.de ping statistics —
5 packets transmitted, 5 received, 0% packet loss, time 4006ms
rtt min/avg/max/mdev = 20.427/22.810/26.405/2.062 ms

Sollte man keinen v6 Host pingen können, sollte man nochmal seinen Tunnel und die Adressen überprüfen. Ansonsten ist der kleine Pi bereit als Router zu dienen. Wie bekommen den unsere Clients dazu eine IP Adresse aus unserem Netz zu benutzen? Bei v6 gibt es an sich keinen DHCP wie man ihn von v4 kennt. Es gibt unter anderem auch keine NAT mehr. Das heißt, jeder Host aus dem ganzen Internet erreichbar ist, wenn man keine Firewall auf seinem Gateway einsetzt. Ich wette das wird noch ganz viel Spaß mit sich bringen, wenn erst mal alle Provider anfangen v6 Adressen auszuliefern. Also erstmal eine einfache Firewall einrichten:

#!/bin/bash
# script: ip6tables firewall script

IPV6T=”/sbin/ip6tables”
INFOUT=”tap0″
INFLOCAL=”eth0″
HOSTIP=”2c01:118:a315:12::13″

# First, delete all:
$IPV6T -F
$IPV6T -X

# Allow anything on the local link
$IPV6T -A INPUT  -i lo -j ACCEPT
$IPV6T -A OUTPUT -o lo -j ACCEPT

# Allow anything out on the internet
$IPV6T -A OUTPUT -o $INFOUT -j ACCEPT
# Allow established, related packets back in
$IPV6T -A INPUT  -i $INFOUT -m state –state ESTABLISHED,RELATED -j ACCEPT

# Allow the localnet access us:
$IPV6T -A INPUT -i $INFLOCAL -j ACCEPT
$IPV6T -A OUTPUT -o $INFLOCAL -j ACCEPT

# Filter all packets that have RH0 headers:
$IPV6T -A INPUT -m rt –rt-type 0 -j DROP
$IPV6T -A FORWARD -m rt –rt-type 0 -j DROP
$IPV6T -A OUTPUT -m rt –rt-type 0 -j DROP

# Allow Link-Local addresses
$IPV6T -A INPUT -s fe80::/10 -j ACCEPT
$IPV6T -A OUTPUT -s fe80::/10 -j ACCEPT

# Allow multicast
$IPV6T -A INPUT -d ff00::/8 -j ACCEPT
$IPV6T -A OUTPUT -d ff00::/8 -j ACCEPT

# Allow ICMPv6 everywhere
$IPV6T -I INPUT  -p icmpv6 -j ACCEPT
$IPV6T -I OUTPUT -p icmpv6 -j ACCEPT
$IPV6T -I FORWARD -p icmpv6 -j ACCEPT

# Allow forwarding
$IPV6T -A FORWARD -m state –state NEW -i $INFLOCAL -o $INFOUT -j ACCEPT
$IPV6T -A FORWARD -m state –state ESTABLISHED,RELATED -j ACCEPT

# SSH in
$IPV6T -A INPUT -i $INFOUT -p tcp -d $HOSTIP –dport 22 -j ACCEPT

# Set the default policy
$IPV6T -P INPUT   DROP
$IPV6T -P FORWARD DROP
$IPV6T -P OUTPUT  DROP

Das Script verbietet jeden eingehen Traffic von $INFOUT und erlaubt nur SSH zu dem Host $HOSTIP. Ausgehender Verkehr bzw. Zugriff von $INFLOCAL ist ohne Einschränkungen möglich. Jetzt sind unsere Clients von Zugriffen aus dem bösen Internet sicher.

Wenn man die Firewall eingerichtet hat, können wir uns endlich um unserer Clients kümmern. Es gibt verschiede Dienste um v6 Netze zu announcen. Die bekanntesten sind quagga und radvd. Radvd ist wesendlich kleiner und wer nur Adressen announcen will ist damit besser beraten als mit quagga.

Die Konfiguration ist einfach in einer Datei untergebracht. Leicht zu verstehen und zu erweitern:

interface eth0 {
AdvSendAdvert on;
MinRtrAdvInterval 3;
MaxRtrAdvInterval 10;
prefix 2c01:118:a315:44::/64 {
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr on;
};
route ::/0  {};
};

Bei diesem Beispiel wird das Netz 2c01:118:a315:44::/64 über eth0 announced und der default gw auf den Clients wird auch announced. Ist der Dienst gestartet, sollten auch schon die Clients eine v6 Adresse erhalten haben und der Standard Gateway ist gesetzt. Unter Archlinux funktionierte alles einwandfrei und ich musste nichts ändern. Ansonsten kann man die Route auf den Clients auch per Hand setzen:

/sbin/ip -6 r a ::/0 via 2c01:118:a315:44::1 dev eth0

Fehlen nur noch ein paar v6 Tests und man kann fröhlich in die Zukunft schauen…

Raspberry Pi + Firmware Updaten

Leider ist beim Pi nicht alles Opensource und es werden Firmwares benötigt. Zum Glück hat sich Hexxeh die mühe gemacht und ein kleines Update Script geschrieben. Mit diesem ist es möglich die Firmware ohne Probleme zu aktualisieren. Unter Debian musste ich noch ein paar Programme nachinstallieren:

apt-get install ca-certificates git-core binutils

Die Installation von rpi-update ist recht einfach und man kann eigentlich nichts falsch machen:

wget http://goo.gl/1BOfJ -O /usr/bin/rpi-update && chmod +x /usr/bin/rpi-update

Schon ist das Script einsatzbereit und es kann durch ein aufrufen durch: rpi-update gestatet werden. Der Rest geschieht automatisch oder man wird darauf hingewiesen noch Pakete zu installieren.

Dank des Updates wurde auch endlich ip6tables und andere Module aktiviert, die ich unbedingt braucht um ein vernünftiges IPv6 Gateway zu bauen.

Raspberry Pi + Debian

Nachdem ich meine Desktop Distribution Archlinux auf dem Raspberry testete wollte ich Debian auch eine Chance geben. Die Installation ist die gleiche wie bei Archlinux, jedoch muss man noch die Swap Partition löschen UND was für mich unverständliches: Man muss SSH nachinstallieren. Es wird also unbedingt eine Tastatur und Monitor mit HDMI gebraucht. Wieso macht man so etwas? Argh!

Mein Pi soll für mich ein kleiner Gateway werden und wird in der nahen Zukunft mit IPv6, Proxy, VPN und anderen Spielereien bestückt. Dabei bin ich gespannt ob die Hardware ausreichend ist und wie man die Programme optimieren kann damit sie auf dem Pi ordentlich funktionieren.

Fangen wir mit einem IPv6 Tunnel von sixxs.net an.

Das “neue” Internet verbreitet sich immer weiter und als Administrator sollte man langsam anfangen sich damit auseinander zu setzen. Alle meine Server, Seiten und Dienste sind bereits per IPv6 erreichbar. Bis jetzt gibt es noch nicht viel zu erobern mit IPv6, aber die Infrastruktur muss erst einmal aufgebaut werden und das geschieht zur Zeit im Hintergrund mit einem parallelen laufen von IPv4 und IPv6.

Mein Provider bietet leider noch kein natives v6 und deswegen muss ich auf einen Tunnel von sixxs.net zurück greifen. Zum herumspielen und Testen sollte das vollkommen reichen. Auf dem Pi werde ich den Aiccu client installieren um den Tunnel aufzubauen. Dieser befindet sich schon im Debian Repository und kann einfach installiert werden:

apt-get install aiccu

Nach der Anmelden bei sixxs und ein paar Tage warten bekommt man die benötigten Zugangsdaten zugeschickt. Danach muss man sich noch für einen PoP entscheiden und diesen auch separat beantragen. Dies kann auch wieder ein paar Tage dauern oder auch nur Stunden.

Leider kommt das Debian Image ohne IPv6 Module und muss daher noch nachinstalliert werden. Entweder man kompiliert es sich oder man greift auf die Module auf github.com zurück. Die Installation ist recht einfach:

wget –no-check-certificate “https://github.com/raspberrypi/firmware/tarball/master” -O master.tar.gz
tar -xzf master.tar.gz
mv /lib/modules/3.1.9+/ old_modules
cp -rf raspberrypi-firmware-34c977e/modules/3.1.9+ /lib/modules/
# /boot muss gemounted sein!
cp raspberrypi-firmware-34c977e/boot/kernel.img /boot/
depmod -a
reboot

UPDATE: rpi-update

Funktioniert leider nicht und wir gehen einen anderen Weg und benutze ein anderes Image von linuxsystems.it. Wenn ihr das Image auch verwendet, dann folgt der Anleitung nach der Installation des Images und vergesst nicht die SSH host keys neu zu erstellen:

ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key

Und schon hat man ein minimal Debian Image mit SSH und IPv6 + Patches und neuster Firmware am laufen. Es fehlen noch die einen und anderen Module, aber warum nicht gleich so? Also weiter mit aiccu…

Javascript: Multilingual

Wenn man eine Seite oder Applikation für mehrere Sprachen zur Verfügung stellen will braucht man Bausteine. Hier und Jetzt ganz einfach:

 var language = {
 	"en": {
 		bla: "Englisch"
 	},
 	"de": {
 		bla: "Deutsch"
 	}
 };

var lang = "en";
var text = language[lang];
alert(text.bla);
Das lag schon länger als Draft herum, aber ein Devblog Eintrag hat es wieder zum Vorscheinen gebracht.