Vom Noob-OS zum IPv6-Router

Eigentlich habe ich in meinem letzten Blog-Post angekündigt, diesmal “den abgebissenen Apfel bis auf den Kern” zu schälen. Aber gerade als ich alle Vorbereitungen dafür abgeschlossen hatte, erinnerte mich ein außergewöhnlich religiöser Kollege (der an dieser Stelle nicht namentlich genannt werden möchte) daran, was Adam und Eva damals widerfahren ist, nachdem sie vom selbigen Apfel “nur” abgebissen hatten. Ein Risiko von solchem Kaliber für einen einzigen Blogpost einzugehen, wäre einfach nur unverhältnismäßig. Deshalb beschränke ich mich in diesem Beitrag darauf, dem Skript vom letzten mal IPv6-Unterstützung zu verleihen.

Bestandsaufnahme

Weder die Topologien der Netzwerke, noch die damit einhergehenden Probleme haben sich seit dem letzten Beitrag geändert. Das Setup wurde “lediglich” auf IPv6 umgestellt – schließlich wird man in Zukunft über die Nutzung von IPv4 wahrscheinlich ähnlich wertend reden wie heute über die Nutzung von Schreibmaschinen. Das Problem besteht darin, dass eine VM im Netz 2001:db8::192.0.2.16/124 nicht ohne weiteres mit Containern im Netz 2001:db8::192.0.2.32/124 kommunizieren kann, da sie nicht weiß, dass letztgenanntes Netz hinter der VM 2001:db8::192.0.2.18 liegt. Um dieses Problem zu beheben, kann man entweder jeder einzelner betroffener VM diesen Weg beizubringen – oder man nutzt…

Statische IPv6-Routen auf Mac OS X

Leider ist dies etwas schwieriger, als die Einrichtung von IPv4-Routen – zumindest wenn die VMs mit Parallels betrieben werden. Dem Host wird nämlich die IP 2001:db8::192.0.2.17 nicht automatisch zugewiesen. Und es gibt anscheinend keine Möglichkeit, dies über die Netzwerkeinstellungen dauerhaft zu ändern.

Dann eben durch die Hintertür…

Das zuletzt bereits angelegte Skript /usr/local/sbin/add-static-routes.sh, das beim Systemstart automatisch ausgeführt wird (siehe letzten Blogbeitrag), kann für diesen Zweck mitgenutzt werden, indem man am Ende folgende Zeile hinzufügt:

/usr/local/sbin/assign-inet6-address.pl "$(/usr/local/sbin/get-iface-by-inet-address.pl 192.0.2.17)" 2001:db8::192.0.2.17/124

Alle Skripte, die nicht im letzten Blogpost auftauchen stehen am Ende dieses Blogposts. Die konkreten Daten sind nicht aus der Luft gegriffen, sondern müssen mit den Parallels-Netzwerkeinstellungen übereinstimmen – wobei die Adresse der Netzwerk-Schnittstelle “Subnetz + 1” sein sollte:

2001:db8::c000:210 + 1 = 2001:db8::c000:211 = 2001:db8::192.0.2.17

Zurück zu der Route

Nach der eben vollendeten Überwindung der Parallels-Hürde steht der Eigentlichen statischen Route nichts mehr im Wege. Diese wird einfach in /usr/local/sbin/add-static-routes.sh mit aufgenommen:

/usr/local/sbin/add-static-route6.pl 2001:db8::192.0.2.32/124 2001:db8::192.0.2.18

Diese Route tritt spätestens nach einem Neustart in Kraft. Mangels Geduld kann man auch die zwei hinzugefügten Zeilen direkt auf der Kommandozeile ausführen:

# bash
bash-3.2# /usr/local/sbin/assign-inet6-address.pl "$(/usr/local/sbin/get-iface-by-inet-address.pl 192.0.2.17)" 2001:db8::192.0.2.17/124
bash-3.2# /usr/local/sbin/add-static-route6.pl 2001:db8::192.0.2.32/124 2001:db8::192.0.2.18

Fazit

“Warum extrem einfach wenn es auch unnötig kompliziert geht?” Diesem Motto werde ich auch weiterhin treu bleiben – also stay tuned!

Skripte

/usr/local/sbin/get-iface-by-inet-address.pl

#!/usr/bin/perl 

# (C) 2017 NETWAYS GmbH | GPLv2+
# Author: Alexander A. Klimov

my $inet_addr = shift;

exit 2 if ! defined $inet_addr; # RTFM at https://wp.me/pgR2o-rur


my $iface;
$inet_addr = quotemeta($inet_addr);

POLL: for (;;) {
	for (`/sbin/ifconfig`) {
		if (/^(\S+?): /) {
			$iface = $1
		} elsif (defined($iface) && /^\tinet $inet_addr /) {
			print $iface;
			last POLL
		}
	}

	sleep 1
}

/usr/local/sbin/assign-inet6-address.pl

#!/usr/bin/perl 

# (C) 2017 NETWAYS GmbH | GPLv2+
# Author: Alexander A. Klimov

my $iface = shift;
my $inet6_addr = shift;

exit 2 if !(defined($iface) && defined($inet6_addr) && $inet6_addr =~ m~^(.+)/(\d+)$~); # RTFM at https://wp.me/pgR2o-rur


my $status = system("/sbin/ifconfig", $iface, "inet6", $1, "prefixlen", $2) >> 8;
die "/sbin/ifconfig: $status" if ($status != 0)

/usr/local/sbin/add-static-route6.pl

#!/usr/bin/perl 

# (C) 2017 NETWAYS GmbH | GPLv2+
# Author: Alexander A. Klimov

my $destination = shift;
my $gateway = shift;

exit 2 if !(defined($destination) && defined($gateway) && $destination =~ m~^(.+)/(\d+)$~); # RTFM at https://wp.me/pgR2o-rur


$destination = $1;
my $destination_prefixlen = $2;
my $gatewayBin = ip6adr2bin($gateway);

POLL: for (;;) {
	for (`/sbin/ifconfig`) {
		if (/^\tinet6 (.+?)(?:%\S+)? prefixlen (\d+)/) {
			if (ip6bin2prefix($gatewayBin, $2) eq ip6bin2prefix(ip6adr2bin($1), $2)) {
				my $status = system("/sbin/route", "add", "-inet6", "-prefixlen", $destination_prefixlen, "-net", $destination, $gateway) >> 8;
				die "/sbin/route: $status" if ($status != 0);
				last POLL
			}
		}
	}

	sleep 1
}


sub ip6adr2bin
{
	my $raw = shift;

	if ($raw =~ /::/) {
		my ($head, $tail) = split(/::/, $raw);
		$head = ip6part2bin($head);
		$tail = ip6part2bin($tail);

		return $head . ("0" x (128 - (length($head) + length($tail)))) . $tail
	}

	ip6part2bin($raw)
}

sub ip6bin2prefix
{
	my $addr = shift;
	my $prefixlen = shift;

	substr($addr, 0, $prefixlen) . ("0" x (128 - $prefixlen))
}

sub ip6part2bin
{
	join("", map({ /\./ ? join("", map({ sprintf("%08b", $_) } split(/\./, $_))) : sprintf("%016b", hex($_)) } split(/:/, shift())))
}
Alexander Klimov

Autor: Alexander Klimov

Alexander hat 2017 seine Ausbildung zum Developer bei NETWAYS erfolgreich abgeschlossen. Als leidenschaftlicher Programmierer und begeisterter Anhänger der Idee freier Software, hat er sich dabei innerhalb kürzester Zeit in die Herzen seiner Kollegen im Development geschlichen. Wäre nicht ausgerechnet Gandhi sein Vorbild, würde er von dort aus daran arbeiten, seinen geheimen Plan, erst die Abteilung und dann die Weltherrschaft an sich zu reißen, zu realisieren - tut er aber nicht. Stattdessen beschreitet er mit der Arbeit an Icinga Web 2 bei uns friedliche Wege.

Vom Noob-OS zum IPv4-Router

Dass man die Docker-Alternative LXD ohne große Hürden auch auf Mac OS X betreiben kann, habe ich in meinem letzten Blog-Post bereits detailliert erläutert.

Leider kann ich im Rahmen meiner Arbeit nicht alles in diesen Ubuntu-Containern betreiben. Die Entwicklungsumgebungen für so manche Anwendungen wie z. B. Icinga Web 2 werden mit Vagrant provisioniert und dieses Programm lässt sich nur sehr mühsam an LXD koppeln. Deshalb komme ich nur mit der einen LXD-VM wohl oder übel nicht aus.

Spätestens wenn die anderen VMs (oder deren Container) mit den LXD-Containern kommunizieren müssen, stößt dieses Setup an seine Grenzen… oder?

Das Setup im Detail

Wie auch jeder andere Gewerbebetrieb, in dem keine Schreibmaschinen mehr zum Einsatz kommen, verfügt NETWAYS über ein internes IP-Netz – beispielhaft mit den Host-Adressen 192.0.2.1 – 192.0.2.14. Der Router zum Internet beansprucht für sich die 192.0.2.1 und meinem Arbeitsgerät ist die 192.0.2.2 zugeteilt.

Um mit meinen virtuellen Maschinen kommunizieren zu können, teilt meine Workstation sich ein IP-Netz mit ihnen (192.0.2.17 – 192.0.2.30). Und schließlich sollen auch meine LXD-Container nicht so isoliert sein wie ein Schreibmaschinen-Nutzer – deshalb teilen sie sich ein wieder anderes IP-Netz (192.0.2.33 – 192.0.2.46) mit der LXD-VM.

Wenn nun ein Knoten einen anderen ansprechen will, muss er entweder im selben IP-Netz sein wie der gewünschte Gesprächspartner – oder in der Netz-Hierarchie unter einem Router stehen, der den gewünschten Gesprächspartner erreichen kann.

Beispiel #1

LXD-Container #1 will mit 192.0.2.50 kommunizieren, ist aber nicht im selben Netz. Ihm bleibt nichts anderes, als über sein Standard-Gateway, 192.0.2.33, zu senden und zu hoffen, dass die Verbindung erfolgreich zustande kommt. Die LXD-VM ist aber auch nicht im selben Netz. Daher muss sie sich wiederum auf ihren Standard-Gateway (192.0.2.17) verlassen. Meine Workstation delegiert wiederum an 192.0.2.1 usw.. Und wenn da draußen tatsächlich eine 192.0.2.50 online ist (und alle Internet-Router so rund laufen wie unser Firmen-Gateway) kommt letztendlich die Verbindung erfolgreich zustande.

Beispiel #2

VM #1 will mit 192.0.2.34 kommunizieren, ist aber nicht im selben Netz. Ihr bleibt nichts anderes, als an ihr Standard-Gateway, 192.0.2.17, zu delegieren. Leider weiß Mac OS nichts vom Netz 192.0.2.32/28 und delegiert an unser Firmen-Gateway. Das und alles dahinter kann noch so rund laufen, aber der Zug in Richtung des LXD-Container-Netzes ist längst abgefahren.

Aber ich würde nicht schon gut 3,5 Jahre bei NETWAYS arbeiten wenn ich diese Hürde nicht spielend einfach überwinden könnte. Dazu braucht es nur…

Statische Routen auf Mac OS X

Natürlich könnte ich auch auf jeder VM eine statische Route hinterlegen, aber das wäre zusätzlicher Aufwand bei jeder VM-Erstellung. Sollte darüber hinaus die Anzahl der VMs mit Linux-Containern zunehmen, steigt damit auch mein Aufwand beim Routen-Management nicht zu knapp…

Deshalb ist es langfristig so oder so sinnvoller, alle VMs an die Workstation delegieren zu lassen und diese zum Router zu befördern. Wie praktisch, dass Mac OS X auf 4.4BSD basiert und damit zur *nix-Familie gehört. Damit ist dieses Vorhaben ein Kinderspiel (wenn man weiß wie es geht).

Jetzt aber endlich mal Butter bei die Fische

Schritt 1: Konzentration!

Um Mac OS die gewünschten statischen Routen beizubringen, muss man tiefer ins System eingreifen, als es ein durchschnittlicher Mac-Nutzer es gewohnt ist. Dabei lässt sich mit ein bisschen Schusseligkeit sehr viel kaputt machen. Wenn Du gerade z. B. eine ordentliche Portion G&T konsumiert hast… habe Geduld. Morgen ist auch noch ein Tag und Mac OS läuft schon nicht weg.

Schritt 2: Root-Rechte

Obwohl Mac OS sich an weniger versierte Nutzer richtet, bietet es die Möglichkeit, Root-Rechte zu erlangen wie man das von verbreiteten GNU/Linux-Distributionen kennt:

Alexanders-MacBook-Pro:~ aklimov$ sudo -i
Password:
Alexanders-MacBook-Pro:~ root#

Schritt 3: Hilfs-Skripte

Die eben erlangten Privilegien berechtigen uns, Skripte in dem OS vorbehaltene Verzeichnisse zu platzieren – wovon wir auch Gebrauch machen, indem wir zunächst das Verzeichnis /usr/local/sbin erstellen und darin zwei Skripte ablegen:

Alexanders-MacBook-Pro:~ root# mkdir -p /usr/local/sbin
Alexanders-MacBook-Pro:~ root# vim /usr/local/sbin/add-static-route.pl
Alexanders-MacBook-Pro:~ root# chmod 0755 /usr/local/sbin/add-static-route.pl
Alexanders-MacBook-Pro:~ root# vim /usr/local/sbin/add-static-routes.sh
Alexanders-MacBook-Pro:~ root# chmod 0755 /usr/local/sbin/add-static-routes.sh

Das erste Skript, /usr/local/sbin/add-static-route.pl, dient dem Hinzufügen von statischen Routen, sobald die entsprechende Netzwerk-Schnittstelle online ist:

#!/usr/bin/perl

# (C) 2017 NETWAYS GmbH | GPLv2+
# Author: Alexander A. Klimov

my $destination = shift;
my $gateway = shift;

if (!(defined($destination) && defined($gateway))) {
    exit 2 # RTFM at https://wp.me/pgR2o-rlj
}


my $gatewayDec = ip4_2dec($gateway);

POLL: for (;;) {
    for (`/sbin/ifconfig`) {
        if (/^\tinet (.+?) netmask (.+?) /) {
            my $mask = hex($2);
            if (($gatewayDec & $mask) == (ip4_2dec($1) & $mask)) {
                my $status = system("/sbin/route", "add", "-net", $destination, $gateway) >> 8;
                die "/sbin/route: $status" if ($status != 0);
                last POLL
            }
        }
    }

    sleep 1
}


sub ip4_2dec
{
    hex(join("", map({ sprintf("%02x", $_) } split(/\./, shift()))))
}

Das zweite Skript, /usr/local/sbin/add-static-routes.sh, ruft das erste Skript auf und fügt damit konkrete Routen hinzu:

#!/bin/bash

set -e
set -o pipefail

/usr/local/sbin/add-static-route.pl 192.0.2.32/28 192.0.2.18

Die Kommandozeilen-Schnittstelle des ersten Skripts habe ich extra so gestaltet, dass die Routen-Liste (das zweite Skript) möglichst einfach erweitert werden kann. Wenn bspw. eine zweite LXD-VM mit der IP-Adresse 192.0.2.21 dazukommt und mit ihren Containern über das Netz 192.0.2.64/28 verbunden ist, gehört folgende Zeile ans Ende der Routen-Liste:

/usr/local/sbin/add-static-route.pl 192.0.2.64/28 192.0.2.21

Schritt 4: Autostart

Damit das zweite Skript nicht bei jedem Systemstart manuell ausgeführt werden muss, lassen wir Mac OS es für uns automatisch starten:

Alexanders-MacBook-Pro:~ root# pushd /Library/LaunchDaemons
/Library/LaunchDaemons ~
Alexanders-MacBook-Pro:LaunchDaemons root# vim mystaticroutes.plist
Alexanders-MacBook-Pro:LaunchDaemons root# launchctl load mystaticroutes.plist

Inhalt von mystaticroutes.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>MyStaticRoutes</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/sbin/add-static-routes.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
  </dict>
</plist>

Fazit

Obwohl mich die Kollegen aus den eigenen Reihen – aber auch aus NMS und PS – spätestens seit diesem Blogeintrag mit besorgten Blicken überschütten, werde ich einfach nicht müde, das Noob-OS von Apple auf biegen und brechen meinen seltsamen Bedürfnissen entsprechend aufzubohren.

Abonniert gerne kostenlos diesen Blog um auch über die nächste Runde informiert zu werden – wenn ich den abgebissenen Apfel bis auf den Kern schäle…

Alexander Klimov

Autor: Alexander Klimov

Alexander hat 2017 seine Ausbildung zum Developer bei NETWAYS erfolgreich abgeschlossen. Als leidenschaftlicher Programmierer und begeisterter Anhänger der Idee freier Software, hat er sich dabei innerhalb kürzester Zeit in die Herzen seiner Kollegen im Development geschlichen. Wäre nicht ausgerechnet Gandhi sein Vorbild, würde er von dort aus daran arbeiten, seinen geheimen Plan, erst die Abteilung und dann die Weltherrschaft an sich zu reißen, zu realisieren - tut er aber nicht. Stattdessen beschreitet er mit der Arbeit an Icinga Web 2 bei uns friedliche Wege.

VM Volumes live anpassen mittels blkdeviotune

This entry is part 2 of 2 in the series Cloud Management

Wir bei NETWAYS setzen für das erstellen von VMs bestimmte Templates ein. In diesen Templates sind alle möglichen Konfigurationen hinterlegt. Unter anderem auch für die VM Volumes. Doch nicht immer passen diese Konfigurationen und so sind einzelne Anpassungen an der laufenden VM nötig. Mittels “blkdeviotune” ist man als Admin in der Lage, live die Volume-Daten der VMs zu bearbeiten.
Hierzu begibt man sich mittels “virsh” in das dazugehörige Terminal.

root@virt-system:~# virsh
Welcome to virsh, the virtualization interactive terminal.
Type: 'help' for help with commands
'quit' to quit
virsh # list
Id Name State
----------------------------------------------------
01 one-1000 running
02 one-1001 running
03 one-1002 running
04 one-1003 running

In diesem Terminal hat man verschiedene Parameter die man anpassen kann. Welche verfügbar sind, kann man wie folgt anzeigen lassen. Hierbei wird die ID aus obigen Kommando benötigt:

virsh # blkdeviotune 02 vda
total_bytes_sec: 62914560
read_bytes_sec : 0
write_bytes_sec: 0
total_iops_sec : 500
read_iops_sec : 0
write_iops_sec : 0

Folglich ist hier die Möglichkeit gegeben, oben genannte Parameter anzupassen. Ob man hier nun die Limitierungen der IOPs und die “Bytes per second” bezüglich “read” und “write” unterscheidet, oder ob man einen totalen Wert angibt, bleibt jedem Admin selbst überlassen. In diesem Beispiel hat die VM mit der OpenNebula ID “one-1001” Limitierungen auf die Parameter “total_bytes_sec” und “total_iops_sec“. Die anderen Werte sind hier unlimitiert, jedoch werden sie durch den übergeordneten Parameter beschränkt. Wenn man die Werte nun entsprechend seiner Wünsche anpassen möchte, ist es wie im folgenden Beispiel wichtig, alle Werte mit anzugeben, auch wenn sie nicht verändert werden sollen. Als Beispiel wird hier nun der Parameter “total_bytes_sec” auf 0 zurück gesetzt und einzelne Limitierungen für die Werte “read_bytes_sec” und “write_bytes_sec” gesetzt. Ebenso werden die maximal zulässigen IOPs erhöht.

virsh # blkdeviotune 02 vda 0 31457280 31457280 1000 0 0
virsh # blkdeviotune 02 vda
total_bytes_sec: 0
read_bytes_sec : 31457280
write_bytes_sec: 31457280
total_iops_sec : 1000
read_iops_sec : 0
write_iops_sec : 0

Derartige Änderungen können live geschehen und benötigen keine weiteren Aktionen innerhalb der VMs. Wir bei NETWAYS reagieren so zum Beispiel auf temporäre Mehrauslastungen einzelner VMs.

Marius Gebert

Autor:

Marius ist seit September 2013 bei uns beschäftigt. Er hat im Sommer 2016 seine Ausbildung zum Fachinformatiker für Systemintegration absolviert und kümmert sich nun um den Support unserer Hostingkunden. Seine besonderen Themengebiete erstrecken sich vom Elastic-Stack bis hin zu Puppet. Auch an unserem Lunchshop ist er ständig zu Gange und versorgt die ganze Firma mit kulinarischen Köstlichkeiten. Seine Freizeit verbringt Marius gern an der frischen Luft und wandert dabei durch die fränkische Schweiz

NETWAYS Web Services: Request Tracker

This entry is part 8 of 8 in the series NETWAYS Web Services

Unsere NWS-Produktfamilie ist um ein weiteres Mitglied gewachsen: Den BestPractical Request Tracker. Dies wird vor allem Kunden freuen, die zwar ein stabiles und zuverlässiges Ticketsystem nutzen möchten, sich aber nicht um die Bereitstellung von Ressourcen, die Installation sowie die Wartung kümmern möchten – denn all dies wird von unserer NETWAYS Web Services Plattform übernommen. Der Kunde selbst muss sich nur um eine Hand voll Voreinstellungen kümmern, die jedoch direkt über Webformulare an die App übergeben werden.

Diese Voreinstellungen umfassen folgende Aspekte, die der Kunde bereitstellen muss:

  • ein IMAP oder POP3 Postfach, von dem der Request Tracker Kundenmails abholt und daraus ein Ticket generiert. Dies stellt vor allem sicher, dass bestehende Mail-Adressen weiter genutzt werden können.
  • einen SMTP-Server, der den Versand der Mails aus dem Request Tracker steuert.

Des Weiteren bietet unsere App viele Möglichkeiten, den Request Tracker nach Belieben anzupassen. Kunden können nicht nur den Namen Ihres Request Trackers und Ihrer Organisation festlegen, sondern auch eine Zeitzone und eine eigene Absender-Mail-Adresse eintragen:

Auch innerhalb der App kann der Request Tracker hervorragend an Ihr Unternehmen angepasst werden. Es können nicht nur im administrativen Bereich User-Gruppen und Ticket-Queues erstellt werden, sondern auch das Erscheinungsbild des Tools individualisiert werden.

Wichtiger Hinweis: Alle Angebote bei den NETWAYS Web Services können Sie 30 Tage kostenfrei testen!

Nicole Lang

Autor: Nicole Lang

Ihr Interesse für die IT kam bei Nicole in ihrer Zeit als Übersetzerin mit dem Fachgebiet Technik. Seit 2010 sammelt sie bereits Erfahrungen im Support und der Administration von Storagesystemen beim ZDF in Mainz. Ab September 2016 startete Sie Ihre Ausbildung zur Fachinformatikerin für Systemintegration bei NETWAYS, wo sie vor allem das Arbeiten mit Linux und freier Software reizt. In ihrer Freizeit überschüttet Sie Ihren Hund mit Liebe, kocht viel Gesundes, werkelt im Garten, liest Bücher und zockt auch mal gerne.

Cloud Management – Teil 1: blkdeviotune/migrate-setmaxdowntime

This entry is part 1 of 2 in the series Cloud Management

Viele von euch haben bestimmt schon einmal von OpenNebula oder OpenStack gehört, beiden Plattformen verwenden standardmäßig libvirtd als Hypervisor, da jedoch die darunter liegende Hardware mit unter stark beansprucht werden wird, vor allem im Cloud Bereich, wo mehrerer KVM Instanzen auf einem Virt Host um CPU/Speicher/IO Resourcen konkurrieren, ist es gelegentlich notwendig die einen oder andere Instanz zu bändigen bzw. in die Schranken zu weisen.

Unsere Cloud läuft derzeit noch mit OpenNebula, wir selbst sind sehr zufrieden mit dem Stack, da sich dieser leicht Verwalten lässt und sich auch gut mit unserem Ceph als Backend verträgt, natürlich verwenden wir in unserem Cloud Stack noch andere Tools, diese sind aber nicht Gegenstand dieses Artikels, mehr dazu in späteren Teilen der Serie.

Libvirtd kann mit CLI Tools wie virsh gesteuert werden, auch besteht die Möglichkeit libvirtd über die entsprechende libvirt C API oder durch seine ScriptLanguage Bindings für ruby/python/perl/javascript/etc… anzusprechen bzw. anzusteuern zu können.

So beispielsweise unterstützt man OpenNebula wenn die Migration einer KVM Instanz von Virt Host A zu Virt Host B aufgrund von Last auf der Instanz selbst partout nicht klappen will…

root@virt1: ~ $ virsh migrate-setmaxdowntime --downtime 1800 one-8366
error: Requested operation is not valid: domain is not being migrated (dieser Fehler kommt nur wenn sich die Instanz nich im Status Migrate befindet, ist hier also nur exemplarisch mit abgebildet)

…oder wenn die Instanz AMOK läuft und somit andere Instanzen zu stark beeinträchtigt…

root@virt1: ~ $ virsh blkdeviotune one-8366 vda --live
total_bytes_sec: 62914560
read_bytes_sec : 0
write_bytes_sec: 0
total_iops_sec : 400
read_iops_sec  : 0
write_iops_sec : 0

…dann limitieren wir diese einfach ein bisschen…

root@virt1: ~ $ virsh blkdeviotune one-8366 vda --live 62914560 0 0 200 0 0

…und vergewissern uns nochmal ob unsere neuen IOPs Limits übernommen wurden…

root@virt1: ~ $ virsh blkdeviotune one-8366 vda --live
total_bytes_sec: 62914560
read_bytes_sec : 0
write_bytes_sec: 0
total_iops_sec : 200
read_iops_sec  : 0
write_iops_sec : 0

…ich denke, damit sollte klar sein worauf wir hier abzielen möchten.

In folgenden Teilen dieser Serie werden wir euch noch mehr Tips & Tricks mit auf den Weg geben, die helfen sollen eure Cloud zu bändigen bzw. aufkommende Probleme anzugehen, also bleibt gespannt. 😉

Enrico Labedzki

Autor: Enrico Labedzki

Enrico ist beruflich ganz schön rumgekommen – IT hat ihn aber immer beschäftigt. Nach einem Ausflug in die Selbstständigkeit im Bereich Webentwicklung und Network Solutions, wurde es dann Zeit Nägel mit Köpfen zu machen und endlich den Weg als Softwareentwickler und Systemintegrator einzuschlagen. In seiner Freizeit widmet sich der passionierte Bastler der Elektrotechnik und Animatronik. Bei Netways bereichert er mit seinem vielseitigen Know-How das Managed Service-Team.

Setting up a TURN Server for Nextcloud Video Calls

We recently had an support inquiry from one of our Nextcloud customers at Netways Web Services. He told us that he had installed the Nextcloud Video Calls app from the Nextcloud Appstore but was not able to make any video calls. He and the person on the other end always got a black video screen when attempting to call each other.
After some research I identified the potential cause of the problem. It turned out that a TURN server was required (pardon the pun).

 

TURN – what is that?

The Nextcloud Video Calls app contains a WebRTC-based server called spreed. WebRTC uses the ICE (Interactive Connectivity Establishment) framework to overcome networking complexities (like NATs) where connecting the participating clients directly isn’t possible. But it will need at least a STUN server to accomplish that. STUN standing for “Session Traversal Utilities for NAT” will enable the clients to discover their public IP addresses and the NAT where they are behind. Note that this server is only used to initially establish the connection. Once the connection is set up the media will stream directly between the clients. The Nextcloud Video Calls app is preconfigured with “stun.nextcloud.com:443” as STUN server. But this doesn’t always work – just like our customer experienced it, for some clients a STUN server won’t be enough to establish the connection. That might be the case if one or multiple participants are behind a symmetric NAT where UDP hole punching does not work. And that’s where the TURN server comes in. “Traversal Using Relay NAT” (TURN) extends STUN capabilities to make media traversal possible even if the clients are behind symmetric NATs. But that means that the whole traffic will flow through the TURN server since it is acting as a relay. Therefore most TURN servers use credential or shared secret mechanisms to authenticate the clients. So after all you end up having two options: either you find a TURN server provider that you can trust and who is willing to grant you access to his service or you set up your own TURN server.

 

How to set up a TURN Server

We decided to set up our own TURN. Like most of the tutorials recommend we installed Coturn. Our “TURN-VM” is running Ubuntu 16.04 and has a public IP address – this is actually quite important since the TURN server needs at least one dedicated public IP address to work properly. In order to have full STUN/TURN server functionality it’s even required to have two public IP addresses.
Now let’s start – first install coturn:

apt-get install coturn

Next enable coturn as service (use the editor of your choice):

vim /etc/default/coturn

Now uncomment the last line, save and close the file:

#
# Uncomment it if you want to have the turnserver running as 
# an automatic system service daemon
#
TURNSERVER_ENABLED=1

We will have a look at the config file of Coturn. It has a lot of lines so I will only go over settings that are relevant in conjunction with Nextcloud’s spreed video calls. Open the turnserver.conf with an editor

vim /etc/turnserver.conf

and have a look at the following lines

#listening-port=3478
#tls-listening-port=5349

Those are the default listening ports coturn will use. In my case I changed them to

listening-port=80
tls-listening-port=443

because I don’t have a webserver running on the VM and I already had the ports open in the firewall. This is important – make sure that the server is reachable on these ports and no firewall is blocking them.
Note that the tls-listening-port is only relevant if you plan on using TLS-encrypted connections.

You’ll find the following line a couple of lines below the tls-listening-port:

#listening-ip=172.17.19.101

If you leave it as a comment then Coturn will listen on all the IP addresses available for this host. I uncommented it and changed it to the actual public IP address of this server

listening-ip=185.XX.XXX.XXX

Further down I did the same for the relay-ip:

relay-ip=185.XX.XXX.XXX

Now look for “fingerprint” and “lt-cred-mech” and uncomment:

fingerprint
lt-cred-mech

A couple of lines below you’ll find

#use-auth-secret

and

#static-auth-secret=north

uncomment both, then open up another shell window and generate a secret for example with

openssl rand -hex 32
751c45cae60a2839711a94c8d6bf0089e78b2149ca602fdXXXXXXXXXXXXXXXXX

copy the generated secret string and paste it into the turnserver.conf

use-auth-secret
static-auth-secret=751c45cae60a2839711a94c8d6bf0089e78b2149ca602fdXXXXXXXXXXXXXXXXX

Enabling “use-auth-secret” and setting a “static-auth-secret” will prevent unauthorized usage of your TURN server and is highly recommended!

Head further down and look for

#realm=mycompany.org

then uncomment and change it to the FQDN of the TURN server

realm=xxxxx.netways.de

The next line to uncomment and change is

total-quota=100

then uncomment

stale-nonce

If you want to use TLS then you should get a SSL certificate and key for example via Letsencrypt and then set the following lines of the turnserver.conf to the path where those files are located, in my case:

cert=/ssl/nws.crt
pkey=/ssl/nws.pem

also set cipher-list to

cipher-list="ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AES:RSA+3DES:!ADH:!AECDH:!MD5"

If you don’t plan on using this TURN server as STUN then you can uncomment

no-stun

Now some last uncommenting

no-loopback-peers
no-multicast-peers

and you should be ready to start your coturn server. Save the file and close the editor.

Start/restart coturn for example with

service coturn restart

or

/etc/init.d/coturn restart

You may want to watch the logfile to see if everthing is fine

tail -f /var/log/turn_YYYY-MM-DD.log
0: log file opened: /var/log/turn_2017-08-15.log
0: pid file created: /var/run/turnserver.pid
0: IO method (main listener thread): epoll (with changelist)
0: WARNING: I cannot support STUN CHANGE_REQUEST functionality because only one IP address is provided
0: Wait for relay ports initialization...
0:   relay 185.XX.XXX.XXX initialization...
0:   relay 185.XX.XXX.XXX initialization done
0: Relay ports initialization done
0: IO method (general relay thread): epoll (with changelist)
0: IO method (general relay thread): epoll (with changelist)
0: turn server id=0 created
0: turn server id=2 created
0: IPv4. TLS/SCTP listener opened on : 185.XX.XXX.XXX:80
0: IPv4. TLS/TCP listener opened on : 185.XX.XXX.XXX:80
0: IO method (general relay thread): epoll (with changelist)
0: IPv4. TLS/SCTP listener opened on : 185.XX.XXX.XXX:443
0: IPv4. TLS/TCP listener opened on : 185.XX.XXX.XXX:443
..
.

So now we are ready to test if it is working.

 
 

How to test my TURN Server

Visit this page and see if you can get a proper response from your Coturn server.

The field for “STUN or TURN URI” should look something like this:

turn:xxxxx.netways.de:443?transport=tcp

but you can also use the IP:

turn:185.XX.XXX.XXX:443?transport=tcp

adding the part “?transport=tcp” is important as I was not able to get my TURN server to respond without TCP only.
Next click on “Gather candidates”.

What you would want as a result should look similar to this:

Time Component  Type Foundation Protocol    Address	 Port	         Priority
0.006	1	host	0	 UDP	10.0.10.144	60925	126 | 32512 | 255
0.009	1	host	1	 TCP	10.0.10.144	63376	125 | 32640 | 255
0.010	1	host	1	 TCP	10.0.10.144	9	125 | 32704 | 255
0.015	2	host	0	 UDP	10.0.10.144	47302	126 | 32512 | 254
0.016	2	host	1	 TCP	10.0.10.144	64892	125 | 32640 | 254
0.016	2	host	1	 TCP	10.0.10.144	9	125 | 32704 | 254
0.031	1	srflx	2	 TCP	XXX.XX.XX.XX	3362	 99 | 32607 | 255
0.051	2	srflx	2	 TCP	XXX.XX.XX.XX	3364	 99 | 32607 | 254
0.069	                                                                     Done

If you get a timeout with “Not reachable?” then probably a firewall is blocking the connection. Check again if the ports for the TURN server are open and if you can reach it externally via Telnet or something similar.

 
If everything works as expected you can continue and enter FQDN, port and shared secret in the video calls settings of your Nextcloud:

Also make sure that “TURN server protocols” is set to “TCP only”.
Finally test if video calls work with participants from different networks, through NAT’s and firewalls.

 
Well, that’s at least how I got it working and our NWS Nextcloud customer confirmed that he was able to make video calls without black screens as soon as he added in the TURN server details that I sent him.
Feel free to check out our Software as a Service platform NWS where you can test Nextcloud 30 days for free.

Gabriel Hartmann

Autor: Gabriel Hartmann

Gabriel freut sich nun in seiner Ausbildung zum Fachinformatiker für Systemintegration bei NETWAYS endlich sein im Informatikstudium gesammeltes Wissen artgerecht anwenden zu können. Wenn er nicht gerade an Servern, PC’s und sonstigem bastelt, vertreibt sich der gebürtige Oberfranke seine Freizeit mit Radfahren, Fotografie und Snowboarden. Vor allem reizen ihn interessante Projekte und das Arbeiten an Open Source basierten Linux-Systemen.