Category Archives: Linux/BSD

[UPDATE] Blockieren von XMLRPC Attacken

Seit ein paar Tagen bin ich in irgend einer Liste für XML-RPC Brute Force Attacken gelandet und die müllen meine limitierten Apache Slots zu. Lösung:

#!/bin/bash
# script: block xmlrpc attacks
# author: Steffen Wirth <s.wirth@itbert.de>
 
LOGFILE="/var/log/apache2/access.log"
LASTLINES="20"
MAXCOUNT="5"
 
LIST=$(tail -n$LASTLINES $LOGFILE |grep "xmlrpc.php" | awk '{print $1}' | sort -n | uniq -c)
 
if [ -n "$LIST" ]; then
        while read -r count ip ; do
                if [ $count -ge $MAXCOUNT ]; then
                        iptables -A INPUT -s $ip -j DROP
                        logger -t "XMLRPC" "blocked ip $ip"
                fi
        done <<< "$LIST"
fi

wie immer auch im gist.github.com

Wie Sebastian korrekt darauf hinwies, wenn man fail2ban installiert hat ist es viel einfacher:

# grep -v "^#" /etc/fail2ban/filter.d/apache-xmlrpc.conf 

[INCLUDES]

before = apache-common.conf

[Definition]

failregex = ^ .*POST .*xmlrpc\.php.*

ignoreregex = 
# grep apache-xmlrpc /etc/fail2ban/jail.conf -A3
[apache-xmlrpc]
enabled = true
port    = http,https
filter  = apache-xmlrpc
logpath = /var/log/apache*/*access.log
maxretry = 5

Soundcloud Favorite Downloader

Früher sammelte man noch MP3 Dateien wie wild, aber das ist längst Vergangenheit. Heutzutage kann man (oder ich) gemütlich neue und alte Musik auf Soundcloud oder ähnlichen hören. Ich höre eigentlich fast ausschließlich Musik auf Soundcloud. Es gibt einfach sehr gute Musik, gerade Remixe von Liedern auf der Platform.

Leider kann man die Lieder nicht in der Soundcloud App cachen bzw. Offline hören. Deswegen ist es für das Handy eigentlich gänzlich ungeeignet, wenn man nicht seinen Traffic dafür verbrauchen will. Zum Glück bieten manche Künstler ihre Lieder zum kostenlosen Download an und das kann man sich ja zunutze machen. Dafür habe ich ein kleines Script zusammen gebastelt, das die favorisierten Lieder herunterlädt.

#!/usr/bin/perl
# script: download favorite songs from your soundcloud stream
# author: Steffen Wirth <s.wirth@itbert.de>

use WebService::Soundcloud;
use XML::Simple;
no warnings 'utf8';

# create a new app -> soundcloud.com/you/apps/new
my $client_id = "YOUR_CLIEND_ID";
my $client_secret = "YOUR_CLIENT_SECRET";
# soundcloud username and password
my $username = "YOUR_USERNAME";
my $password = "YOUR_PASSWORD";
# download path
my $file_path = "/tmp/";
    
my $scloud = WebService::Soundcloud->new($client_id, $client_secret,
	{ username => $username, password => $password, response_format => 'xml' }
);
    
# get access token
my $access_token = $scloud->get_access_token();
my $oauth_token = $access_token->{access_token};

# get favorites tracks
my $followings = $scloud->get('/users/' . $username . '/favorites');

$xml = XML::Simple->new;
$xml = XMLin($followings->content);

foreach my $item (@{$xml->{track}}) {
	my $id = $item->{id}->{content};
	my $title = $item->{title};
	my $downloadable = $item->{downloadable}->{content};
	my $downloadurl = $item->{'download-url'};

	# only download songs that are downloadable
	if ($downloadable eq "true") {

		# download track
		$title =~ s/\ /_/g;
		my $dest_file = $file_path . $id . "_" . $title . ".mp3";

		unless (-e $dest_file) {
			print "DOWNLOAD: $title ($id)" . "\n"; 
			#my $path = $scloud->download($id, $file_path);

			# verrrrrrry ugly way, but $scloud->download(); is not working.
			# have fun with big files :)
			my $track = $scloud->get($downloadurl);
			my $sound = $track->content;
			open (TRACK, ">>$dest_file");
				print TRACK $sound;
			close(TRACK);

		} else {
			print "IGNORING TRACK $title ($id)" . "\n";
		}
	}
	
}

oder auf gist.github.com

Update: ABER ABER, was machen wir mit den Liedern die wir nicht offiziell herunterladen dürfen? Dafuer gibt es Dienste wie zum Beispiel anything2mp3.com. Damit kann man auch “diese” Lieder herunterladen. Wir sind Faul, also los:

#!/usr/bin/perl
# script: download favorite songs from your soundcloud stream
# author: Steffen Wirth 

use WebService::Soundcloud;
use XML::Simple;
use HTTP::Cookies;
use LWP::Simple;
use Encode qw(encode_utf8);
no warnings 'utf8';

### settings ###

# create a new app -> soundcloud.com/you/apps/new
my $client_id = "YOUR_CLIEND_ID";
my $client_secret = "YOUR_CLIENT_SECRET";
# soundcloud username and password
my $username = "YOUR_USERNAME";
my $password = "YOUR_PASSWORD";
# download path
my $file_path = "/tmp/";
# download service
my $url = "http://anything2mp3.com/de";

### script ###

my $cookie_jar = HTTP::Cookies->new( 
    file => 'lwp_cookies.txt',
    autosave => 1,
    ignore_discard => 1,
);

my $ua = LWP::UserAgent->new;
	$ua->agent("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0");
	$ua->timeout(30);
	$ua->cookie_jar($cookie_jar);

my $scloud = WebService::Soundcloud->new($client_id, $client_secret,
	{ username => $username, password => $password, response_format => 'xml' }
);

# get access token
my $access_token = $scloud->get_access_token();
my $oauth_token = $access_token->{access_token};

# get favorites tracks
my $followings = $scloud->get('/users/' . $username . '/favorites');

$xml = XML::Simple->new;
$xml = XMLin($followings->content);

foreach my $item (@{$xml->{track}}) {
	my $id = $item->{id}->{content};
	my $title = $item->{title};
	my $downloadable = $item->{downloadable}->{content};
	my $downloadurl = $item->{'download-url'};
	my $permalink = $item->{'permalink-url'};

	# title and file 
	$title =~ s/\ /_/g;
	my $dest_file = $file_path . $id . "_" . $title . ".mp3";
	$dest_file = encode_utf8($dest_file);

	# only download songs that are downloadable
	if ($downloadable eq "true") {

		unless (-e $dest_file) {
			print "DOWNLOAD: $title" . "\n"; 
			#my $path = $scloud->download($id, $file_path);

			# verrrrrrry ugly way, but $scloud->download(); is not working.
			# have fun with big files :)
			my $track = $scloud->get($downloadurl);
			my $sound = $track->content;
			open (TRACK, ">>$dest_file");
				print TRACK $sound;
			close(TRACK);

		} else {
			print "IGNORING TRACK $title" . "\n";
		}
	} else {
		# lets download tracks that we are not supposed to

		unless (-e $dest_file) {
			print "D0WNL04D $title" . "\n";
			my $request = $ua->post($url,
				{
					url => $permalink,
					op => 'Convert',
					form_build_id => 'form-iKcdS_GJM5mRuRicuFJKS7wGB8oR7zbY6YbVeV4cjtM', # not sure how long this is valid
					form_id => 'videoconverter_form',
			});

			my $html = $ua->get($url . '/kostenlose-online-soundcloud-youtube-mp3-converter');
			$html = $html->content;

			while ($html =~ m@(((http://anything2mp3.com/de/system/temporary/mp3/))\S+[^.,!? ])@g) {
				$dl = $1;
				$dl =~ s/\>\Click//g;
			}

			($file) = $dl =~ m!([^/]+)$!;
			$file =~ s/\?download=1//g;

			my $track = $ua->get($dl);
			my $sound = $track->content;
			open (TRACK, ">>$dest_file");
				print TRACK $sound;
			close(TRACK);
		} else {
			print "IGNORING TRACK $title" . "\n";
		}

	}
	
}

auch auf gist.github.com

Videos auf dem Chromebook

Leider ist AC3 nur mit einer Lizenz zu genießen und kein Chromebook wird es möglich sein AC3 in einem Video abzuspielen. Das einzige was einem bleibt ist AC3 aus dem Video zu entfernen und durch ein anderes Format zu ersetzen.

Folgendes Script habe ich erfolgreich für MKV Dateien eingesetzt. Als erstes wird das AC3 extrahiert, in MP3 umgewandelt und wieder in die MKV Datei integriert. Anschließend AC3 entfernt. (gist)

#!/bin/bash
# script: convert AC3 to MP3 in MKV container
# author: bert2002 <s.wirth@itbert.de>

FILE=$1
FILENAME=$(basename $FILE mkv)
AC3AUDIO=$(mkvmerge --identify $FILE |grep "AC3" | awk -F':' '{print $1}' | awk '{print $3}')

mkvextract tracks $FILE $AC3AUDIO:${FILENAME}ac3
ffmpeg -i ${FILENAME}ac3 -acodec libmp3lame -ab 160k -ac 2 ${FILENAME}mp3

mkvmerge -o ${FILENAME}NEW.mkv $FILE ${FILENAME}mp3

MP3AUDIO=$(mkvmerge --identify ${FILENAME}NEW.mkv |grep MP3 | awk -F':' '{print $1}' | awk '{print $3}')
mkvmerge -o ${FILENAME}NEW.mkv.tmp -a $MP3AUDIO ${FILENAME}NEW.mkv && mv ${FILENAME}NEW.mkv.tmp ${FILENAME}NEW.mkv

Debian Wheezy auf einem Chromebook

Seit ein paar Tagen spiele ich mit einem HP Chromebook 11 herum und muss sagen, soweit bin ich eigentlich zufrieden. Nichtsdestotrotz darf man das Chromebook nicht als Notebook Ersatz sehen, sondern eher als Tablet Ersatz mit Tastatur und grösserem Bildschirm. Genau darin ist es gut. Es ist super einfach und schnell einzurichten und alle Daten fliesen zu Google. Wunderbar.

Nach ein paar Minuten herum spielen fehlte mir jedoch schon die bash und es musste eine Lösung her. Zum glück kann man Debian/Ubuntu als chroot installieren und beides parallel betreiben. Also als erstes das Chromebook in den Entwickler Modus packen:

 Esc + Refresh + Power Off

Dann kommt man zu einer schrecklichen Nachricht. Diese kann man jedoch getrost ignorieren und “Strg + D” drücken. Anschließend wird das Chromebook neu gestartet und ein neues Image wird aus dem Internet gezogen und installiert. Sobald man eingeloggt ist, braucht man eine Shell. Die “crosh” Shell bekommt man mittels “Strg + Alt + t”. Damit man aber in die richtige Shell kommt, muss man noch “shell” eingeben. Endlich!

Jetzt können wir unserer Chroot installieren. Ich habe dafür crouton benutzt und funktionierte einwandfrei:

# wget http://goo.gl/fd3zc
# sudo su -c crouton -r wheezy -t xfce

Den Anweisungen folgen und in ein paar Minuten hat man ein vollständiges Debian Wheezy in der Chroot mit XFCE4 installiert. Das kann man entweder über “sudo startxfce4” starten oder einfach in die chroot mittels “sudo enter-chroot”. Fertig!

Bitpay integration in PHP

Die letzten Wochen wollte ich in ein Projekt Bitcoins als bezahl Option einbauen und musste mich für einen Payment Anbieter entscheiden. Ich hatte Coinbase und Bitpay in meine engere Wahl genommen und am Ende fuer Bitpay entschlossen. Warum? Weil Bitpay Auszahlungen in die EU macht und Coinbase nur auf Amerikanische Konten. Diese Entscheidung wurde einem also relativ einfach genommen.

Jetzt ging es um die Integration der Bitpay API in den Shop. Die Seite benutzt keine Shop Software und somit musste ich die API selber in der Seite einbauen. Die Dokumentation ist eigentlich recht gut. Diese beinhaltet sehr gut wie man eine Rechnung erstellt. Ich finde die “callback” Funktion wird nicht gut beschrieben und ich musste erst einmal ein bisschen ausprobieren. Als erstes, es gibt keine Testumgebung und somit muss man mit echten Bitcoins seine Implementierung testen. Irgendwie schreckt das eigentlich schon direkt ab.

Zum glück bietet Bitpay eine eigene library für PHP an. Somit musste man sich nicht um wirklich alles kümmern. Die Konfiguration in bp_options.php sollte verständlich sein und ich gehe hier nicht auf diese ein.

Erstellen einer Rechnung:

 <?php
// bitpay
require 'bp_lib.php';


$post_data = array(
 'product' => $product
);

$addl_options = array(
 'itemDesc' => $description,
 'itemCode' => $product,
 'currency' => $currency
);

$response = bpCreateInvoice(null, $price, $post_data, $addl_options);
if(!empty($response)){
 $bitpay = $response["url"];
 if ($bitpay) {
 header("Location: $bitpay");
 }

?>

Die $post_data können später im callback verarbeitet werden, die anderen Werte sind nur für die Rechnung oder um die Umrechnung korrekt durchzuführen.

Verarbeiten des Callbacks:

Es hat also jemand ein Produkt gekauft und wir werden über dieses wunderbare Event informiert. Die Callback URL musste man vorher in den Optionen festlegen:

 <?php
// bitpay
require 'bp_lib.php';
$BITPAY_KEY = "YOUR_BITPAY_KEY";

$response = bpVerifyNotification( $BITPAY_KEY );
$id = $response['id'];
$url = $response['url'];

$product = $response['posData']['product'];
$status = $response['status'];
$btcPrice = $response['btcPrice'];
$price = $response['price'];
$currency = $response['currency'];
$btcPaid = $response['btcPaid'];
$rate = $response['rate'];

?>

Eigentlich sehr einfach und man kann die Daten weiter verarbeiten. Die Hürde war an der stelle vorhanden, das man echte Bitcoins benutzen musste. Ich hoffe das Bitpay das bald ändern wird und ggf. werden dann mehr Shops auf Bitpay setzen. Wenn die Tests ordentlich verlaufen wird es bald einen Shop mehr geben der Bitcoins als Option anbietet.

SSH Tunnel trotz /bin/false

Ein interessantes Feature von SSH ist das man trotz einer Shell wie /bin/false oder /bin/nologin einen SSH Tunnel aufbauen kann. Normalerweise setzt man einer der genannten Shells gerade für (s)/FTP Benutzer ein, damit sich diese nicht auf dem Server mit einer Shell einloggen dürfen. Leider interessiert dieses SSH absolut gar nicht und für einen Tunnel braucht man eben keine Shell (channel!).

Viele Anbieter bieten FTP für ihre Dienste an und falls dann noch SSH läuft wäre es somit möglich die Firewalls zu umgehen und einen direkten Zugang auf das System und den dahinterliegenden zu erhaschen. Das ganze funktioniert leider auch wenn man den Benutzer in einer Match Gruppe nur SFTP erlaubt hat.

Ein SSH Tunnel ist schnell aufgebaut und schon kann man loslegen:

# ssh -N -L 1337:localhost:80 $ftpuser@$server

Viel mehr Spaß macht es dann eigentlich nur noch die File Descriptor auf dem Server bequem und schnell zu verbrauchen:

# ssh -N -L 1337:localhost:80 $ftpuser@$server
# ssh -N -R 1337:localhost:80 $ftpuser@$server
# telnet localhost 1337

Das einzige was man dagegen machen kann ist den Zugriff auf SSH nur für bestimmte Benutzer zu erlauben (AllowUsers, AllowGroups) und Tunnel, Forwarding zu verbieten (AllowTcpForwarding, X11Forwarding, PermitTunnel)

Wunderbar beschrieben im Jahr 2005 auf semicomplete.com und immer noch möglich.

Chroot Manager

Aus verschiedenen Gründen muss man ab und zu eine komplette chroot für einen Benutzer erstellen. Meistens ist dieses einzusetzen wenn man noch eine alte Distribution benutzt neuere Möglichkeiten einfach nicht anbietet.

Vor ein paar Monaten hatte ich die Idee chrooted shells auf Servern die auf der ganzen Welt verteilt sind zu vermieten. Das ist ganz hilfreich wenn man seine Dienste aus anderen Ländern wie China testen möchte. Leider habe ich das Projekt nie komplett abgeschlossen und released. Zustande kam jedoch ein kleines Script das automatisch eine chroot für einen Benutzer erstellt. Zusätzlich wurde der Traffic limitiert, damit andere Benutzer nicht komplett ausgebremst werden und ein paar MB auf dem der Benutzer Scripte ablegen kann.

Getestet ist das Script auf Ubuntu 12.04, aber sollte auch auf nachfolgenden Versionen funktionieren. Als erstes muss man auf dem Server ein paar Programme installieren und Konfiguration für ssh und Limitierungen für die Benutzer setzen.

$ create_chroot.sh init_server

Anschließend kann man loslegen und einen Benutzer ‘u007’ erstellen:

$ create_chroot.sh create_user u007

Normalerweise wird eth0 benutzt und die Traffic Limitierung ist auf ca. 100kb/s. Falls etwas anderes gewünscht ist muss dieses im Script angepasst werden. Dieses gilt auch für die Programme die in der Chroot zur Verfügung gestellt sein sollen.

Gerade das Traffic Shaping für jeden einzelnen Benutzer einzugrenzen war etwas kniffelig, aber nach viel ausprobieren dann doch hinbekommen. Vielleicht kann ich damit jemanden viel Zeit sparen:

NEWUSERID=$(id -u $NEWUSER)
IF=eth0
DNLD=1kbps

iptables -t mangle -A OUTPUT -m owner --uid-owner $NEWUSER -j MARK --set-mark $NEWUSERID
tc qdisc add dev $IF root handle 1: htb default 30 >/dev/null 2>&1
tc class add dev $IF parent 1: classid 1:1 htb rate $DNLD >/dev/null 2>&1
tc filter add dev $IF protocol ip parent 1:0 prio 1 handle $NEWUSERID fw flowid 1:1 >/dev/null 2>&1

Mehr Optionen und das Script gibt es auf github.com.

StrongSwan IPSec Howto

Ob man nur in einem offenen HotSpot mit seinem Handy eingeloggt ist oder in einem Land die lokale Zensur umgehen muss – braucht man ein VPN. In China hatte ich das OpenVPN Konstrukt getestet. Es hatte mal funktioniert, dann wieder nicht. Es war also nicht zuverlässig und man musste darauf hoffen das die Sterne gut standen oder mal ein bisschen mehr nachforschen warum der TLS Handshake nicht durch kam.

Um für die Zukunft ein bisschen besser ausgerüstet zu sein habe ich mir noch StrongSwan aufgesetzt. Dabei ist mir aufgefallen das es kein wirklich einfaches Howto für dieses existiert. Viel muss man nicht machen, aber hier einmal ein Setup für IPv4 unter Ubuntu 12.04:

StrongSwan installieren:

# apt-get install strongswan

/etc/strongswan.conf

# strongswan.conf - strongSwan configuration file

charon {

	# number of worker threads in charon
	threads = 16

	# dns
	dns1 = 8.8.8.8
	ndns1 = 8.8.8.8

	plugins {

		sql {
			# loglevel to log into sql database
			loglevel = -1
		}
	}
}

libstrongswan {

	# test crypto at startup
        crypto_test {
                on_add = yes
        }
}

/etc/ipsec.conf

config setup

conn %default
 keyexchange=ikev2

conn roadwarrior
 left=%any
 leftauth=pubkey
 leftcert=serverCert.pem
 leftid=vpn.example.org
 leftsubnet=0.0.0.0/0,::/0
 leftfirewall=yes
 right=%any
 rightsourceip=10.0.1.0/24
 rightauth=pubkey
 rightcert=clientCert.pem
 rightauth2=eap-mschapv2
 auto=add
 esp=aes-aes256-sha-modp1024,aes256-sha512-modp4096
 ike=aes-aes256-sha-modp1024,aes256-sha512-modp4096

/etc/ipsec.secrets


: RSA serverKey.pem
mobile : EAP "ZNs8-93dI10pA"

Der Benutzernam auf dem Client ist jetzt “mobile” mit dem Passwort “ZNs8-93dI10pA”. Zusätzlich wird das Zertifikat “serverKey.pem” benutzt.

Zertifikate erstellen

Folgendes Script erstellt alle notwendigen Zertifikate für den Server und den Client. Auf dem Client muss anschließend das Zertifikat “clientCert.p12” installiert werden.

/etc/ipsec.d/certs/gen.sh

#!/bin/sh

HOST="vpn.example.org"

ipsec pki --gen --outform pem > caKey.pem
ipsec pki --self --in caKey.pem --dn "C=US, O=xxx, CN=xxxx" --ca --outform pem > caCert.pem
ipsec pki --gen --outform pem > serverKey.pem
ipsec pki --pub --in serverKey.pem | ipsec pki --issue --cacert caCert.pem --cakey caKey.pem --dn "C=US, O=xxx, CN=$HOST" --san="$HOST" --flag serverAuth --flag ikeIntermediate --outform pem > serverCert.pem
ipsec pki --gen --outform pem > clientKey.pem
ipsec pki --pub --in clientKey.pem | ipsec pki --issue --cacert caCert.pem --cakey caKey.pem --dn "C=US, O=xxx, CN=client" --outform pem > clientCert.pem
openssl pkcs12 -export -inkey clientKey.pem -in clientCert.pem -name "client" -certfile caCert.pem -caname "xxxx" -out clientCert.p12

mv caCert.pem /etc/ipsec.d/cacerts/
mv serverCert.pem /etc/ipsec.d/certs/
mv serverKey.pem /etc/ipsec.d/private/
mv clientCert.pem /etc/ipsec.d/certs/
mv clientKey.pem /etc/ipsec.d/private/

Vielleicht muss man auf seinem Server noch IP Forwarding aktivieren, aber ansonsten muss man nur noch StrongSwan starten und den Client konfigurieren. Ich benutze dafür den StrongSwan VPN Client für Android und kann bisher nichts negativen sagen. Einfach das Clientzertifikat “clientCert.p12” auf dem Gerät installieren und den gesetzten Benutzername/Passwort und Server in der App (IKEv2 Certificate + EAP) eintragen. Fertig.

Howto basiert auf dem Wiki Eintrag von OpenWRT.

OSSH Manager

Das einzige Script ossh hat sich weiterentwickelt und hat neue Features die VD netterweise eingebaut hat. So gibt es jetzt eine History der letzten Verbindungen über ossh und man kann das letzte Oktett einer v4 Adresse direkt manipulieren und sich somit auf einem anderen Server einloggen. Sehr nett in Cluster Umgebungen.

Das ganze gibt es im neuen zu Hause auf github: https://github.com/bert2002/ossh

RSS Feeder für pushover.net (Teil 2)

Der pushover.net Dienst begeistert mich immer noch und ich habe das RSS Script um ein Channel Management erweitert. Somit lassen sich jetzt die Channel in der Datenbank speichern und man muss nicht mehr für jeden Feed einen Cronjob starten.

Das Script kann man wieder über github beziehen und dafür braucht man rss2pushover.db und rss2pushover.pl. Um einen neuen Channel hinzuzufügen muss dieser in der Datenbank gespeichert sein. Dieses kann man folgendermaßen machen:

sqlite> INSERT INTO channel (status, url, token, user) VALUES (1,$FEED_URL,$PUSH_TOKEN,$PUSH_USER);

Über den Status kann man einstellen ob der Channel aktiv (1) oder deaktiviert (0) is. Die Url ist die des RSS Feeds und Token sowie User sind von pushover für die Applikation. Anschließend kann man das Script einfach wie gewohnt starten und erhält die Push Nachrichten.

Beispiel Screenshot:

Pushover

RSS Feeder für pushover.net (Teil 1)

UPDATE: Bessere Version gibt es jetzt mit Channel Managment.

Als ich auf Android umgestiegen bin musste ich auf meine selbst geschriebenen Apps für Blackberry verzichten. Für vieles gibt es eine Android App, aber z.B. für Exbir gibt es auch nicht mal diese. Eigentlich wollte ich mir wieder meinen eigenen Pushdienst für Android aufbauen, aber momentan fehlt dafür einfach die Zeit.

Dann bin ich auf pushover.net gestoßen. Ein Dienst der einen Push Gateway anbietet und eine Android/iOS app die diese empfängt. Die App kostet 3.66 EUR und diese sind einmalig und es entstehen keine monatlichen Kosten. Ich finde das ist eine ziemlich geniale Idee, weil wer will sich schon monatlich binden. Für die Anbieter ist das auch angenehm und ich denke das diese eine Mischrechnung haben, denn viele werden die App vielleicht nicht lange benutzen.

Wenn man sich registriert hat, muss man eine Applikation erstellen und erhält einen API Key für diese. Im Monat hat man 7,500 Nachrichten inklusive und für ein paar private kleine sachen sollte das Problemlos ausreichen – pro Applikation. Man kann sich natürlich mehrere erstellen ;)

Wie bekomme ich also meine Nachrichten auf die App? Natürlich über die API und diese ist sehr einfach gehalten. Ein einfacher POST Request mit User Key und Privaten Token. Auf der Homepage findet man Beispiele von curl bis Ruby. Das Einbinden von diesem hat keine 10 Minuten gedauert und ich kann mir schon verschiedene Einsatzmöglichkeiten vorstellen. So kann man unnötige Emails loswerden und sein Postfach schonen.

Das rss2pushover Script auf Github ermöglicht es einen RSS feed zu parsen und neue Einträge per pushover.net auf ein Endgerät pushen. Dabei wird eine kleine Datenbank eingesetzt um zu prüfen ob Einträge bereits verarbeitet wurden. Somit erhält man keine doppelten Nachrichten.

Beim Pushen der Nachrichten hat man mehrere Optionen angeben wie z.B. Sound, Wichtigkeit, Link etc.

Push Beispiel:


# send item to pushover.net
my $response = LWP::UserAgent->new()->post(
	"https://api.pushover.net/1/messages.json", [
	"token" => $PUSH_TOKEN,
	"user" => $PUSH_USER,
	"message" => $description,
	"title" => $title,
	"url" => $link,
	"url_title" => $title
]);

if ($response->is_success) {
	# push accepted
} else {
	# push not accepted
}

Einfacher kann man es nicht mehr machen. Bis jetzt sind die Nachrichten immer direkt und ohne merkbare Verzögerung angekommen. Mal schauen wo man das noch überall einbauen kann :)

dmesg mit Zeitangabe

Die dmesg Zeitangaben sind nicht wirklich zu lesen, aber manchmal braucht man sie dann doch eben. So einfach ist es dann doch wieder nicht:

# perl -e 'openf,"/proc/uptime";=~/\s/;$x=time-$`;for(qx{dmesg}){s/^\[\s*([\d.]+)\]\s+//;@t=(localtime($x+$1))[5,4,3,2,1,0];$t[0]+=1900;$t[1]+=1;printf"[%04d-%02d-%02d%02d:%02d:%02d] %s",@t,$_}'