Monero Mining on Ubuntu 16.04

Account:

Der einfachste Weg einen Account zu erstellen ist auf mymonero.com. Man muss sich um keine Blockchain kümmern und es ist komplett Anonym. Auf der Seite bekommt man auch seine WalletID die wir bei dem Miner mit angeben müssen. Diese müsst Ihr bei $WALLETID ersetzen. Als Mining Pool nehmen wir monerohash.com

Installation:

apt update
apt install libcurl4-openssl-dev libncurses5-dev pkg-config automake yasm
sysctl -w vm.nr_hugepages=48 # three times more then your cpu cores
cd /opt/
git clone https://github.com/wolf9466/cpuminer-multi
cd cpuminer-multi
./autogen.sh
CFLAGS="-march=native" ./configure
make

Start:

/opt/cpuminer-multi/minerd -a cryptonight -o stratum+tcp://monerohash.com:3333/
-u $WALLETID -p $RANDOM

Reporting:

Falls man mehrere Instanzen am laufen hat, will man diese auch ein bisschen überwachen bzw. wissen was läuft. Dafür habe ich einen kleinen Bot geschrieben der mit der Monerohash IP sich die aktuellen Daten zieht und diese mir in einem Slack Channel sendet. Das ganze gibt es auf github.com.

BlaBlaDNS – Ein Kostenloser DynDNS Anbieter

NOTE: BlaBlaDNS ist jetzt bekannt als TokenDNS.

Ich darf mit Freude verkünden das endlich mein neustes Projekt online gegangen ist. Ein kleiner, aber feiner Dynamic DNS Dienst der natürlich kostenlos ist. Getauft ist das Projekt auf BlaBlaDNS und kann unter www.blabladns.co erreicht werden.

Es gibt schon unzählige DDNS Dienste, aber leider keiner der mir alle Features bot die ich haben wollte. Er sollte sicher sein, schöne API und ich wollte auch IPv6 Rekords sowie die TTL bestimmen können. Konnte ich nicht finden und so musste ich mir einen bauen.
Momentan muss man die API unbedingt benutzen, weil das Webinterface noch keinen Schreibzugriff auf die API hat, aber das wird sich bald ändern.

Wie kann ich also BlaBlaDNS benutzen?

Als erstes muss man sich sicher anmelden und wenn man den API Key hat kann man direkt los legen. Den rest kann man einfach per API machen. Beispiele existieren momentan für curl, aber die Dokumentation wird noch erweitert.

Kleines Beispiel um die Subdomain www5.blabladns.xyz zu registrieren und aktualisieren.

Subdomain Registrieren

curl --get "https://api.blabladns.co/v1/reserve" \
  -d apikey=${apikey} \
  -d name=www5

Rekord Aktualisieren

curl --get "https://api.blabladns.co/v1/update" \
  -d apikey=${apikey} \
  -d name=www5 \
  -d content=$(curl -4 ifconfig.co)

Status

curl --get "https://api.blabladns.co/v1/reserve" \
  -d apikey=${apikey} \
  -d name=www5

Rekord automatisch mit cron aktualisieren

echo "0 * * * * root curl -s --get https://api.blabladns.co/v1/update -d apikey=${apikey} -d name=www5 -d content=$(curl -s -4 ifconfig.co) >/dev/null" > /etc/cron.d/blabladns

Die Features und Möglichkeiten werden in nächster Zeit noch weiter wachsen und wer die Entwicklung weiter verfolgen möchte sollte dem Blog von BlaBlaDNS folgen.
Wünsche? Anregungen? Features? Gerne baue ich die in den Dienst ein! Einfach Melden!

Chef + Ruby Integration

Auch wenn Chef Ruby einsetzt unterstützt es leider doch nicht alles. Ich wollte eine nette Regex direkt im Cookbook ausführen lassen. In Ruby wunderbar funktioniert, beim Chef run wurde die Regex nicht korrekt ausgeführt. Ich habe sogar zwei verschiedene ausprobiert (wobei die erste nicht ganz korrekt ist, aber auch funktioniert), aber leider Erfolglos. sed funktioniert eben einfach immer :)

Regex: Kommentiere eine Zeile, wenn ubuntu.com oder canonical.com enthalten ist und nicht mit einer Raute anfängt.

 ruby_block 'modify /etc/apt/sources.list' do
  block do
    File.write( f = "/etc/apt/sources.list",
      #File.read(f).gsub(/(?!^#)(.*)(?:ubuntu\.com|canonical\.com)(.*)/) { "# #{$&}" }
      File.read(f).gsub(/^[^!#]*(?:ubuntu\.com|canonical\.com)/m) { "# #{$&}" }
    )
  end
end
 

Lösung:

execute 'modify /etc/apt/sources.list with sed' do
  command "sed -i -e '/ubuntu\.com/s/^#*/#/' -e '/canonical\.com/s/^#*/#/' /etc/apt/sources.list"
end

Cloudera Manager und Grafana

example_graph

In dem Cloudera Manager kann man sich schon verschiedene Grafen der einzelnen Komponenten anschauen, wenn man jedoch auch Grafana benutzt will man nicht wirklich immer umschalten.
Es ist jedoch möglich ein Plugin für Grafana zu schreiben um die Daten direkt aus dem CDH zu ziehen. Amir Pakdel hatte ein Plugin für Grafana 1.x geschrieben, welches ich für Grafana 2.x umgeschrieben habe.

Download: Grafana CDH Datasource Plugin

Installation

Damit wir in kein Problem mit XSS kommen müssen wir unsere anfragen an das CDH mit einem kleinen Proxy über den Server von Grafana abfertigen. Dafür muss folgende Apache Konfiguration angelegt werden:


    ProxyPass http://$CLOUDERAMANAGER:7180/api/v9
    ProxyPassReverse http://$CLOUDERAMANAGER:7180/api/v9
    RequestHeader set Authorization "Basic <base64>"
    Header set Access-Control-Allow-Origin "*"

Das $CLOUDERAMANAGER muss mit dem Hostnamen von dem CDH Manager ersetzt werden und in dem RequestHeader der Benutzername:Passwort (in base64) von dem Benutzer der mit der API von CDH reden darf. Anschließend noch ein paar Module aktivieren:

# a2enconf cdh
# a2enmod proxy_http proxy request headers
# service apache2 restart

Anschließend können wir das Modul installieren und Grafana neu starten. Vor dem Neustart, muss jedoch noch die $GRAFANAURL in der datasource.js angepasst werden.

 # tar -xzf cdh.tar.gz -C /usr/share/grafana/public/app/plugins/datasource/ 
# service grafana-server restart

Jetzt kann man schon beginnen eine neue Datasource zu erstellen und fleißig Graphen bauen. Wie baut man die Graphen? Man muss die SQL Statements aus dem CDH in Grafana übertragen. Die Statements bekommt man aus den vorhanden Graphen:

hdfsio

In dem JSON befindet sich das Query, welches einfach in die Row im Grafana eingetragen werden muss. Fertig.

Owncloud 8.0 Upgrade

Wenn man momentan auf Owncloud 8.0 upgraded erhalten viele Benutzer nur noch eine weiße Seite und nichts passiert. In den Logdateien kann man auch keine Fehler finden.
Das Problem liegt an ein paar Plugins die noch nicht für 8.0 aktualisiert worden. Diese muss man deaktivieren:

# cd /zur/deiner/owncloud
# sudo -u www-data php occ app:disable calendar
# sudo -u www-data php occ app:disable contacts

SSH Tunnel in einer Jail öffnen

Gehen wir mal davon aus das wir einen SSH Benutzer in einer Jail eingesperrt haben. Dieser möchte aber unbedingt einen SSH Tunnel  zu einem anderen Server aufbauen. Normalerweise will man das nicht und verbietet dieses in der sshd_config Konfiguration mittels AllowTcpForwarding no.

Ich wollte das trotzdem einmal habe und konnte einfach nicht finden warum es nicht möglich war. Meine Fehlermeldung:

# ssh -N -L 1337:127.0.0.1:3306 user@$remoteserver -vv

debug1: Connection to port 1337 forwarding to 127.0.0.1 port 3306
requested.
debug2: fd 7 setting TCP_NODELAY
debug1: channel 2: new [direct-tcpip]
channel 2: open failed: administratively prohibited: open failed
debug2: channel 2: zombie
debug2: channel 2: garbage collecting
debug1: channel 2: free: direct-tcpip: listening port 1337 for
127.0.0.1 port 3306, connect from ::1 port 58509, nchannels 3

Ein kleiner Test:

# telnet localhost 1337
Trying ::1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.

Hat leider nichts geholfen und wenn die Fehlermeldung schon sagt das es $irgendwas nicht öffnen kann, muss man sich das einmal genauer mit strace anschauen:

# strace -p $pid -ff
Process $pid attached - interrupt to quit
select(8, [3 7], [], NULL, NULL)        = 1 (in [3])
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
read(3,
"\354O-\1\374O\215\5\4G\323\226\371\207V\325s\37\277-\350\207$)\261}\235\241\320\306\302M"...,
16384) = 96
socket(PF_FILE, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 4
connect(4, {sa_family=AF_FILE, path="/dev/log"}, 110) = -1 ENOENT (No such file or directory)
close(4)                                = 0
select(8, [3 7], [3], NULL, NULL)       = 1 (out [3])
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
write(3,
"\374\231G-+\2,\365\255\312\240Y\20\217YL\350\3t193O\35\323\224\237\3728\260\233\223"...,
64) = 64
select(8, [3 7], [], NULL, NULL

In der Jail hat kein /dev/log existiert und ohne ein bisschen herumzuloggen möchte SSH anscheinend auch keinen Tunnel aufbauen. Kurzerhand das Device angelegt und schon ging es.

root@server:/var/jail/user/dev# ls -al log
srw-rw-rw- 1 root root 0 Mar  3 16:08 log
root@server:/var/jail/user/dev# grep -E '^\$' /etc/rsyslog.d/jail.conf
$AddUnixListenSocket /var/jail/user/dev/log
root@server:/var/jail/user/dev#

SSH Benutzer auf git shell limitieren

Ich benutze kein Gitlab oder Github für private Repositories sondern greife auf diese normal per ssh zu. Wenn man das alleine auf einem Server macht ist das kein Problem. Was aber wenn jemand da zustößt und will auch an das Repository? Dieser sich aber auch sonst nicht auf dem Server einloggen und am System zu schaffen machen.

Zum Glück kann man pro SSH Pubkey erlauben welche Programme ausgeführt werden dürfen. Ein Feature was meines Erachtens viel zu wenig angewendet wird. Dafür brauchen wir erst einmal ein kleines Script, welches der Key ausführen darf und somit unserer Limitierung ist. Das platzieren wir in dem Home Verzeichnis des Benutzers:

# cat ~/gitserve && chmod g+x ~/gitserve


#!/bin/sh
exec git-shell -c "$SSH_ORIGINAL_COMMAND"

Dem SSH Key müssen wir dieses jetzt nur noch bei bringen:

command="./gitserve",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty
ssh-rsa AAAAB.....

Der Benutzer kann jetzt nur noch mit der git-shell interagieren.

Brother QL-570 auf ArchLinux

Ich habe mir einen Etikettendrucker zugelegt und habe mich bin dabei für de QL-570 von Brother entschieden. Den gab es gerade günstig bei Amazon zu kaufen und kommt mit Einzeletiketten und Endlospapier klar.

Bei Brother kann man sich die Treiber herunterladen. Ich habe mich für deb entschieden. Entpacken muss man sie so oder so:

# ar xv ql570cupswrapper-1.0.1-0.i386.deb
# ar xv ql570lpr-1.0.1-0.i386.deb

Den Inhalt von der data.tar.gz kann man dann nach “/” kopieren. Anschließend muss man nur noch einen Befehl ausführen damit der Treiber auch im cups konfiguriert wird:

# /opt/brother/PTouch/ql570/cupswrapper/cupswrapperql570pt1

Leider hat das bei mir nicht ganz gereicht. Ich musste die größe des Papiers noch mit angeben. Das mitgelieferte Papier hat eine Breite von 62mm. Den Befehl bastelt man am besten mit der Ausgabe von dem cupswrapper Befehl (wegen der Seriennumber):

# lpadmin -p QL-570 -E -v usb://Brother/QL-570?serial=<SERIAL> -P /usr/share/cups/model/Brother/brother_ql570_printer_en.ppd -o PageSize=62x29

Anschließend kann man in der angegebenen Größe mittels gLabels auch direkt losdrucken :) Die passenden Optionen kann man sich einfach anzeigen lassen:

# lpoptions -pQL-570 -l

Bitcoin Geldautomat in Hong Kong

Als ich letztens in Hong Kong war musste ich einfach einen Bitcoin ATM besuchen und schnell und einfach Geld tauschen. Ich habe mir dazu den HK Bitcoin ATM ausgesucht. Es war ein bisschen schwer zu finden, aber wenn man erst einmal im richtigen Gebäude ist finde man es schnell.

Der Lamassu Automat ist einfach super zu bedienen. QR Code einscannen vom Wallet, Geld rein schieben und Bestätigen. Ein paar Sekunden später waren die Bitcoins auf meinem Wallet. Warum gibt es davon nicht schon viel mehr?

Mojolicious mit Facebook OAuth2

Ich wollte mich einmal ein bisschen mit dem Graphen von Facebook und Authentifizierung mittels OAuth2 per Facebook schlau machen und bin dabei über den Blog Eintrag bei tudorconstantin.com gestoßen. Genaueres steht auf der Seite, jedoch ist der Code nicht sofort einsetzbar und habe ich ein mal korrigiert:

#!/usr/bin/env perl
use Mojolicious::Lite;
use Net::Facebook::Oauth2;

my $config = {
  facebook => {
      app_id => '',
      secret => '',
      redirect_url => 'http://mojo.dev:3000/redirect_from_fb',
    },
};

plugin 'o_auth2', {
  facebook => {
    key    => $config->{facebook}->{app_id},
    secret => $config->{facebook}->{secret},
}};

get '/' => sub {
  my $self = shift;

  $self->redirect_to('authenticate') unless $self->session->{user}->{fb_username};
  return $self->render('index_authenticated');
  
} => 'index';

get authenticate => sub {
  my $self = shift;

  my $url = $self->get_authorize_url(
    'facebook',
    scope => 'offline_access publish_stream user_likes email',
    redirect_uri => $config->{facebook}->{redirect_url},
  );

  $self->redirect_to( $url->to_abs->to_string );
} => 'authenticate';

get redirect_from_fb => sub {
  my $self = shift;
  my $token = $self->param('code');

  my $fb = Net::Facebook::Oauth2->new(
    application_id     => $config->{facebook}->{app_id},
    application_secret => $config->{facebook}->{secret},
    access_token       => $token,
    callback           => $config->{facebook}->{redirect_url}
  );

	my $access_token = $fb->get_access_token(code => $token);

	$fb = Net::Facebook::Oauth2->new(
		access_token => $access_token
  );

	my $info = $fb->get(
		'https://graph.facebook.com/me'
  );
							    
  print $info->as_json;

  $self->session->{user} = {
	    fb_username   => $info->as_hash->{name},
  };

  $self->redirect_to('index');
} => 'redirect_from_fb';

app->start;
__DATA__

@@ index_unauthenticated.html.ep
% layout 'default';

<%= link_to 'Click here to authenticate with FB' => 'authenticate'; %>

@@ index_authenticated.html.ep
% layout 'default';

Hello <%= session->{user}->{fb_username} %>

<%= link_to 'Click here to authenticate with FB' => 'authenticate'; %>

@@ layouts/default.html.ep
<%= content %>

oder auf gist.github.com.