SSH – Der Schlüssel zum Erfolg

Seal of ApprovalOder wie man das meiste aus SSH herauskitzelt.

SSH wird von den meisten Sysadmins genutzt, aber selten so wie es genutzt werden sollte.
Die meisten Administratoren verwenden das folgende Kommando Tag ein Tag aus.

ssh-keygen -t rsa -b 4096 -C "dummy_user@fqdn_dummy.com"

Zerlegen wir das Kommando mal in seine Einzelteile und versuchen zu verstehen was diese eigentlich tun.

Der Parameter '-t' gibt an welchen Key-Typ wir rsa/dsa/ecdsa/ecdsa-sk/ed25519 erstellen wollen. Hierbei wird von kleineren RSA-Keys unter 4096 Bits inzwischen abgeraten. DSA ist als unsicher deklariert und sollte auch seit Version 7 von OpenSSH auch nicht verwendet werden. ECDSA ist wegen der NSA ggf. problematisch zum nachlesen hier. So bleibt nur ED25519 welchen ich bei meiner täglichen Arbeit kaum sehe. Dies sollte aber heutzutage der De-Facto-Standard-Key sein, mit dem das obige Kommando aufgerufen wird.

'-b' für die Bits welche verwendet werden sollen. Wenn nun an dieser Stelle die Frage aufkommt mit welcher Bits-Anzahl ED25519 erstellt werden sollte, sei gesagt dass dieser eine festgelegte Länge hat und damit diesen Parameter ignoriert.

'-C' steht für Comment und dieser kann beliebig sein. Zumeist wird hier aber zur besseren Nachvollziehbarkeit von den Admins dieser Welt das Pattern Username@Hostname verwendet, damit man sehen kann für wen dieser Key erstellt wurde.

Im obigen Beispiel fehlt der Parameter '-N' welcher für new_passphrase bzw. das Passwort steht, wenn man den fehlenden Parameter '-N' mit "" ohne Zeichenkette angibt erhält man einen passwortlosen, privaten SSH-Schlüssel. Zusätzlich wird ein öffentlicher Schlüssel erstellt.

Verbessern wir das obige Kommando: ssh-keygen -t ed25519 -N'' -C 'dummy_user@fqdn_dummy.com'

Der Output des Beispiels:

ssh-keygen -t ed25519 -N'' -C'dummy_user@fqdn_dummy.com'
Generating public/private ed25519 key pair.
Enter file in which to save the key (/root/.ssh/id_ed25519): /root/.ssh/dummy
Created directory '/root/.ssh'.
Your identification has been saved in /root/.ssh/dummy.
Your public key has been saved in /root/.ssh/dummy.pub.
The key fingerprint is:
SHA256:14RQXbFyQCtEZfnGN8O7hV4h9hAEY0SYQN9Y0+9TRp8
root@fqdn_dummy.com The key's randomart image is:
+--[ED25519 256]--+
|      .oooO%O+o. |
|        .==o== ..|
|         oo.+o*.o|
|           + *+E=|
|        S . o.=+*|
|         .    .=o|
|             . .+|
|              .. |
|                 |
+----[SHA256]-----+
[root@fqdn_dummy.com .ssh]# ll
total 8
-rw-------. 1 root root 464 Nov 14 22:45 dummy
-rw-r--r--. 1 root root 108 Nov 14 22:45 dummy.pub

Damit hätten wir einen Standard-SSH-Schlüsselpaar, welches zumeist in den Unternehmen vergessen wird, wenn Mitarbeiter das Unternehmen verlassen oder die Abteilungen wechseln und auch durch automatisierte Deployments wird es oft als Karteileiche liegen gelassen.

Wie wäre es wenn wir ablaufende SSH-Schlüsselpaare hätten, welche nach einer gewissen Zeit ablaufen und zwar von selbst?

Was vielen nicht bewusst ist, ist dass dies SSH eigentlich schon von ganz allein kann, nur nutzt es kaum jemand.

Beginnen wir mit dem ersten Schritt und generieren uns eine CA (Certificate Authority).

ssh-keygen -t ed25519 -N '' -C 'ca' -f ca

Da diese CA unser Dreh- und Angelpunkt ist bedarf es Achtsamkeit, damit diese nie in falsche Hände gelangt.

Dank dieser CA können wir nun Zertifikate von Hosts und Benutzern signieren.

Als Beispiel nehmen wir einen Benutzer 'test' welcher sich per SSH an den Host namens ColdMoon anmelden soll.

Wir brauchen also für beide Zertifikate und einen SSH Schlüssel.

Bevor wir es vergessen müssen wir unsere vorher erstellte CA auf unserem SSH Server in der sshd_config als 'TrustedUserCAKeys /etc/ssh/ca.pub' eintragen.

Nun nehmen wir von unserem Benutzer 'test' auf seinem Laptop und den dort bereits erstellten öffentlichen Schlüssel mit dem wir ihm begrenzten Zugriff auf unsere Infrastruktur geben wollen in diesem Fall unser Rechner ColdMoon.

Im Vorfeld haben wir schon den Benutzer auf dem Rechner angelegt, und der Kollege 'test' hat uns seinen öffentlichen Schlüssel per Email geschickt.
Von unserem Vorgesetzten wissen wir das der Kollege 'test' nur 1 Woche ein Praktikum bei uns vornimmt und danach das Unternehmen wieder verlässt.

Auf gehts wir erstellen einen zeitlich begrenzten Zugang:

ssh-keygen -s ca -I Azubi_auf_Zeit -n test -V +1w -z 1 test.pub
Signed user key test-cert.pub: id "Azubi_auf_Zeit" serial 1 for test valid from 2019-11-13T09:00:00 to 2019-11-20T09:00:00

Das Resultat dieses Kommandos ist das wir ein signiertes 'test-cert.pub' erhalten mit eine Lebenszeit von 1 Woche.
Dieses senden wir umgehend unseren Praktikanten zu mit dem Hinweis das er sich mit dem folgenden Kommando nun an dem Rechner ColdMoon anmelden kann.

ssh -i ~/.ssh/test -i ~/.ssh/test-cert.pub test@ColdMoon -v

Ich habe mal den Verbose-Schalter genommen um zu zeigen wie das Zertifikat sich dann gegen ColdMoon anmeldet.

...
debug1: SSH2_MSG_EXT_INFO received
debug1: kex_input_ext_info: server-sig-algs=<rsa-sha2-256,rsa-sha2-512>
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password
debug1: Next authentication method: publickey
debug1: Offering public key: test ED25519 SHA256:4A3ab2/7dq0klERi9IevmSnTZd7dkOuuP8yrWCZ24gI explicit
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password
debug1: Offering public key: test ED25519-CERT SHA256:4A3ab2/7dq0klERi9IevmSnTZd7dkOuuP8yrWCZ24gI explicit
debug1: Server accepts key: test ED25519-CERT SHA256:4A3ab2/7dq0klERi9IevmSnTZd7dkOuuP8yrWCZ24gI explicit
debug1: Authentication succeeded (publickey).
Authenticated to 192.168.242.67 ([192.168.242.67]:22).
debug1: channel 0: new [client-session]
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug1: pledge: network
debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0
debug1: Requesting authentication agent forwarding.
debug1: Sending environment.
debug1: Sending env LC_CTYPE = UTF-8
Last login: Thu Nov 14 11:00:14 2019 from 192.168.242.225
[test@coldmoon ~]$

Die Authentifizierung wird nun die gesamte Woche lang funktionieren in der der Praktikant Zugriff auf dem Rechner braucht, danach weil es nur zeitlich begrenzt ist nicht mehr. Damit ist für den Praktikanten kein Zugriff auf unserer Infrastruktur mehr möglich. Dies funktioniert auch mit anderen Hosts oder Services, welchen man nur für einen Zeitraum einen begrenzten Zugriff per SSH geben möchte.

Der Parameter '-V' gibt den Validity_Interval an, also den Zeitraum der Gültigkeit, und der Parameter '-z' eine Serialnumber, welche von uns frei gewählt werden kann.

Dies kann mit den üblichen Systemmitteln automatisiert werden oder per Ansible/Puppet auch auf Systeme verteilt werden.
Schöner ist es noch wenn es ohne viel manuelle Arbeit geht. Dies zeige ich in meinem nächsten Blogpost welcher Vault aus dem Hause Hashicorp zeigt.

Gruss

David

David Okon
David Okon
Support Engineer

Weltenbummler David hat aus Berlin fast den direkten Weg zu uns nach Nürnberg genommen. Bevor er hier anheuerte, gab es einen kleinen Schlenker nach Irland, England, Frankreich und in die Niederlande. Alles nur, damit er sein Know How als IHK Geprüfter DOSenöffner so sehr vertiefen konnte, dass er vom Apple Consultant den Sprung in unser Professional Services-Team wagen konnte. Er ist stolzer Papa eines Sohnemanns und bei uns mit der Mission unterwegs, unsere Kunden zu...

Wie bekomme ich bessere Informationen über Züge als die DB

marudor.de screenshotAls reisender Consultant mit Bahncard 100 verbringe ich sehr viel Zeit in Zügen der Deutschen Bahn. Das ist auf der einen Seite erfreulich, denn ich verbringe die Zeit nicht auf der Autobahn. Auf der anderen Seite macht es die Bahn einem manchmal schwer, sinnvoll von A nach B zu kommen. Es soll ja schon einmal vorgekommen sein, dass Züge ausfallen oder zu spät kommen. Möglicherweise ist auch mal ein Zug überfüllt, Klima defekt, Bier alle oder sonst etwas.

Die DB selber bietet für so etwas ja seit einiger Zeit den DB Navigator. Die wichtigsten Daten bekommt man hier auch. Allerdings weiß die Bahn eigentlich über ihre Züge viel mehr als sie uns sagt. Dieses Problem löst sehr gut und schon seit einiger Zeit die Seite marudor.de

Man sieht auf der Seite, wenn man nach einem Bahnhof, einem Zug oder einer Route sucht, ein gute Übersicht über den gewünschten Zug. Hier sieht man auf einen Blick:

  • Reihenfolge der Waggons mit EXAKTER Positon am Bahnsteig
  • ICE Baureihe inkl. Revision (dadurch weiß man auch, ob man alte bequeme oder neue unbequeme Sitze bekommt)
  • Die Postition der Comfortsitze im Zug, so dass man direkt da einsteigen kann (roter Punkt)
  • Die Position von Bordrestaurant, Kinderabteil, Behindertenbereich und -toilette
  • Ruhe und Handy-abteil
  • Wifi Accespoints (und ob er funktioniert)
  • Aktuelle UND vergangene Störungen auf der Fahrt

Teilweise bekommt man diese Infos auch woanders, allerdings sind sie bei marudor meistens aktueller und vor allem alles in einem Rutsch. Und nicht zuletzt: Verspätungen und Verspätungsprognosen sind besser und zuverlässiger.

Warum das alles so ist und wieso der marudor das alles macht kann man hier erfahren. Das Video kommt von der GPN 19 und ist sehr interessant anzuschauen.

Christoph Niemann
Christoph Niemann
Senior Consultant

Christoph hat bei uns im Bereich Managed Service begonnen und sich dort intensiv mit dem internen Monitoring auseinandergesetzt. Seit 2011 ist er nun im Consulting aktiv und unterstützt unsere Kunden vor Ort bei größeren Monitoring-Projekten und PERL-Developer-Hells.

OSMC 2019 – Day 2

OSMC Logo
The social event yesterday evening was a blast and the late lounge afterwards also a must. So while some were still recovering, the room for the first talk was already quite full. This showed the interest in Jochen Kressin‘s talk about “Zero Trusted Networks – why Perimeter Security is dead”. He explained the (old) assumption of perimeter security “I am behind a firewall, so my traffic is secure” and asked the question if this is still true. Showing examples proving it is not true anymore because if it would be, none of these data breaches would have been happen. He explained what has changed in the last years leading to “Zero Trusted Networks” where every system has to be treated as untrusted and how to adopt for it. As one of the developers he used Search Guard as example which adds security to Elasticsearch, one of the great tools that had no security by itself for a long time, being not ready for the zero trusted approach.
Zero Trusted NetworksFluentD
Toshaan Bravani was talking about “Monitoring your Logs with Fluent”. FluentD and the client component FluentBit is an alternative to Logstash I see more and more at customer environments, so I was happy to get a deeper look into it. In addition he showed the complete tool stack to get most out of your data and the automation used to get it up and running.

Open Source landscape for APM
Third one for today was “Improved Observability Using Automated, OpenCensus-based Application Monitoring Solutions” by Tobias Angerstein. He started with a nice overview of the Open Source landscape for Application Performance Management before focusing on inspectIT. Its latest incarnation inspectIT Ocelot focuses on Open Standards like Open Metrics, Open Tracing and Open Census which are forming a new one called Open Telemetry which allows integration with all the well-known tools like Telegraf, Prometheus, Grafana. It also provides End User Monitoring using Boomerang, a javascript agent, and an EUM Server which transforms data to the Open Standards. In his demo he showed the capability of it and my only thought was how helpful something like this would have been to me in my early IT days being a Java developer.

Afterwards we could enjoy another great lunch break and perhaps also an massage, before starting into the afternoon sessions.
Lunch breakLunch BreakLunch Break

Database observability
Charles Judith gave a talk about “How to improve database Observability”. In his job he is responsible for reliability of the company’s databases and told the crowd the problems he started with like having no backup and monitoring at all. So it was his personal goal to have no hidden issues anymore and get transparency into their environment. His way from zero to hero was quite interesting and he compared it with a roller coaster. In the end having metrics to tell users that they are right or wrong with their feeling of the database is slow and having logs and monitoring telling were the real problem lies instead of guessing has improved his daily work already. But he still has some more steps to do like publishing SLA. The WIP version of his toolkit can be found on Github.

Why BOFH is toxic
Second last one I attended was Jan Doberstein with a non technical talk about behaviour and how it influences your daily life and work, titled “Idiot! – or: Why BOFH is toxic”. He touched the same topic like the open discussion yesterday and I think it is great to get people think about and reflect their behaviour. While most of his examples were matched to the crowd and perhaps people working in IT do communicate much more in electronic fashion than others, it is a topic that everyone should care about.

High available setup
Last but not least Marcel Weinberg showed the high available setup he built for Digital Ocean. He included some very helpful small tips and tricks to increase performance and avoid pitfalls while diving deep into the configuration. Indeed it were too much for me to list them all here.

Pictures are taken again from the OSMC stream at Twitter, thanks to everyone for sharing their impressions. I hope everyone enjoyed the conference like I did. Thanks to everyone who made OSMC such a great experience again this year, starting with my colleagues organizing the event, the sponsors and speakers but this includes every attendee forming this nice community. Save travels for everyone leaving today or see you tomorrow if you join the Hackathon or Open Source Camp on Foreman. I hope I will see everyone next year at the same place on November 16th to 19th for OSMC 2020 or in Amsterdam for IcingaConf on May 12th to 14th.

Dirk Götz
Dirk Götz
Principal Consultant

Dirk ist Red Hat Spezialist und arbeitet bei NETWAYS im Bereich Consulting für Icinga, Puppet, Ansible, Foreman und andere Systems-Management-Lösungen. Früher war er bei einem Träger der gesetzlichen Rentenversicherung als Senior Administrator beschäftigt und auch für die Ausbildung der Azubis verantwortlich wie nun bei NETWAYS.

C++Go. Halb C++ – halb Go.

Scherz beiseite, die Go-Entwickler bieten noch keine Möglichkeit, C++-Bibliotheken ohne weiteres anzusprechen. Aber es geht ja auch mit weiteres. Das weitere besteht darin, dass C++-Funktionen mittels C-Bibliotheken gewrapped werden können. Und in meinem letzten Blogpost zu diesem Thema habe ich bereits erklärt, wie C-Bibliotheken in Go angesprochen werden können. Sprich, es braucht nur eine hauchdünne C-Schicht zwischen C++ und Go.

Multilingual++ in der Praxis

Wie auch letztes mal habe ich schon mal was vorbereitet – eine Schnittstelle für die Boost.Regex-Bibliothek. Diese findet sich in diesem GitHub-Repo und besteht aus folgenden Komponenten:

  • Ein Struct, das boost::basic_regex<char> wrapped
  • Eine C-Bibliothek, die den C++-Teil wrapped
  • Die Go-Bibliothek, die die C-Bibliothek verwendet

Wrapper-Struct

Dieses Struct ist Notwendig, da die Größe von boost::basic_regex<char> zwar C++ bekannt ist, aber nicht Go. Das Wrapper-Struct hingegen hat eine feste Größe (ein Zeiger).

libcxx/regex.hpp

#pragma once

#include <boost/regex.hpp>
// boost::basic_regex
// boost::match_results
// boost::regex_search

#include <utility>
// std::forward
// std::move

template<class Char>
struct Regex
{
	template<class... Args>
	inline
	Regex(Args&&... args) : Rgx(new boost::basic_regex<Char>(std::forward<Args>(args)...))
	{
	}

	Regex(const Regex& origin) : Rgx(new boost::basic_regex<Char>(*origin.Rgx))
	{
	}

	Regex& operator=(const Regex& origin)
	{
		Regex copy (origin);
		return *this = std::move(copy);
	}

	inline
	Regex(Regex&& origin) noexcept : Rgx(origin.Rgx)
	{
		origin.Rgx = nullptr;
	}

	inline
	Regex& operator=(Regex&& origin) noexcept
	{
		this->~Regex();
		new(this) Regex(std::move(origin));
		return *this;
	}

	inline
	~Regex()
	{
		delete this->Rgx;
	}

	template<class Iterator>
	bool MatchesSomewhere(Iterator first, Iterator last) const
	{
		boost::match_results<Iterator> m;
		return boost::regex_search(first, last, m, *(const boost::basic_regex<Char>*)this->Rgx);
	}

	boost::basic_regex<Char>* Rgx;
};

Eine C-Bibliothek, die den C++-Teil wrapped

Die folgenden Funktionen sind zwar waschechte C++-Funktionen, aber dank dem extern "C" werden sind sie in der Bibliothek als C-Funktionen sichtbar und können von Go angesprochen werden.

libcxx/regex.cpp

#include "regex.hpp"
// Regex

#include <boost/regex.hpp>
using boost::bad_expression;

#include <stdint.h>
// uint64_t

#include <utility>
using std::move;

extern "C" unsigned char CompileRegex(uint64_t pattern_start, uint64_t pattern_end, uint64_t out)
{
	try {
		*(Regex<char>*)out = Regex<char>((const char*)pattern_start, (const char*)pattern_end);
	} catch (const boost::bad_expression&) {
		return 2;
	} catch (...) {
		return 1;
	}

	return 0;
}

extern "C" void FreeRegex(uint64_t rgx)
{
	try {
		Regex<char> r (move(*(Regex<char>*)rgx));
	} catch (...) {
	}
}

extern "C" signed char MatchesSomewhere(uint64_t rgx, uint64_t subject_start, uint64_t subject_end)
{
	try {
		return ((const Regex<char>*)rgx)->MatchesSomewhere((const char*)subject_start, (const char*)subject_end);
	} catch (...) {
		return -1;
	}
}

libcxx/regex.h

#pragma once

#include <stdint.h>
// uint64_t

unsigned char CompileRegex(uint64_t pattern_start, uint64_t pattern_end, uint64_t out);

void FreeRegex(uint64_t rgx);

signed char MatchesSomewhere(uint64_t rgx, uint64_t subject_start, uint64_t subject_end);

Go-Bibliothek

Diese spricht letztendlich die C-Funktionen an. Dabei übergibt sie die Zeiger als Ganzzahlen, um gewisse Sicherheitsmaßnahmen von CGo zu umgehen. Das Regex-Struct entspricht dem Regex-Struct aus dem C++-Teil.

regex.go

package boostregex2go

import (
	"io"
	"reflect"
	"runtime"
	"unsafe"
)

/*
#include "libcxx/regex.h"
// CompileRegex
// FreeRegex
// MatchesSomewhere
*/
import "C"

type OOM struct {
}

var _ error = OOM{}

func (OOM) Error() string {
	return "out of memory"
}

type BadPattern struct {
}

var _ error = BadPattern{}

func (BadPattern) Error() string {
	return "bad pattern"
}

type Regex struct {
	rgx unsafe.Pointer
}

var _ io.Closer = (*Regex)(nil)

func (r *Regex) Close() error {
	C.FreeRegex(rgxPtr64(r))
	return nil
}

func (r *Regex) MatchesSomewhere(subject []byte) (bool, error) {
	defer runtime.KeepAlive(subject)
	start, end := bytesToCharRange(subject)

	switch C.MatchesSomewhere(rgxPtr64(r), start, end) {
	case 0:
		return false, nil
	case 1:
		return true, nil
	default:
		return false, OOM{}
	}
}

func NewRegex(pattern []byte) (*Regex, error) {
	rgx := &Regex{}

	defer runtime.KeepAlive(pattern)
	start, end := bytesToCharRange(pattern)

	switch C.CompileRegex(start, end, rgxPtr64(rgx)) {
	case 0:
		return rgx, nil
	case 2:
		return nil, BadPattern{}
	default:
		return nil, OOM{}
	}
}

func bytesToCharRange(b []byte) (C.uint64_t, C.uint64_t) {
	sh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
	return C.uint64_t(sh.Data), C.uint64_t(sh.Data + uintptr(sh.Len))
}

func rgxPtr64(p *Regex) C.uint64_t {
	return C.uint64_t(uintptr(unsafe.Pointer(p)))
}

Fazit++

Wenn etwas abgedrehtes mal nicht zu gehen scheint, dann gebe ich doch nicht auf, sondern ich mache es einfach noch abgedrehter. Impossible is nothing.

Wenn Du auch lernen willst, wie man unmögliches möglich macht, komm auf unsere Seite der Macht.

Alexander Klimov
Alexander Klimov
Developer

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...

Einmal lokaler Mirror? Kommt sofort!

RPM Logo

Wer mich kennt, weiß dass ich gerne zu großen umfangreichen Lösungen neige. Daher ist meine bevorzugte Lösung für einen lokalen Mirror Katello, aber es gibt auch Situationen in denen man nur eine Version ohne Staging braucht. Beispiel aus dieser Woche ein “Icinga 2”-Satellite in China, der einfach nicht die Pakete von packages.icinga.com beziehen möchte. Auf seinem übergeordneten Satelliten in Singapur hat noch alles gut funktioniert und auch die Kommunikation zwischen beiden funktioniert auch gut. Also ist nach kurzer Überlegung der Plan gefasst, es soll ein lokaler Mirror her von dem in China installiert werden soll.

Um den Mirror aufzusetzen, setze ich auf die Kommandos reposync und createrepo, welche recht schnell installiert sind und keine Konfiguration benötigen.

yum install -y yum-utils createrepo

Mit reposync kann nur ein bereits konfiguriertes Repository gespiegelt werden. Da in diesem Fall auf beiden Systemen die gleiche Betriebssystemversion installiert ist, für mich kein Problem und es kann gleich weitergehen. Auch ist auf dem Satelliten bereits ein Webserver installiert um Icinga Web 2 als separates Webinterface für die asiatischen Kollegen anzubieten, also auch hier kein Handlungsbedarf. Der Mirror ist also schnell aufgesetzt.

mkdir -p /var/www/html/repo
reposync -r icinga-stable-release -p /var/www/html/repo/ -n
createrepo /var/www/html/repo/icinga-stable-release

Die Optionen bei reposync sind mit -r die Repository-ID aus der Yum-Konfiguration, -p das Zielverzeichnis und -n um nur die jeweils neuste Version herunterzuladen. reposync lädt allerdings nur die Pakete herunter und legt sie in der entsprechenden Struktur ab ohne die benötigten Metadaten. Diese werden dann mit createrepo erzeugt und schon kann mit der neu zur Verfügung gestellten URL das Repository eingebunden werden.

In vielen Fällen ist dies ausreichend, aber hier noch ein paar Tipps wenn es dann doch etwas mehr sein darf.

  • Zum regelmäßigen Updaten einfach die beiden Kommandos reposync und createrepo in einem Cronjob hinterlegen.
  • Ein Repository kann noch weitere Metadaten enthalten, beispielsweise die comps.xml mit Gruppeninformationen. Diese wird durch der Option --downloadcomps von reposync mit heruntergeladen und im aktuellen Arbeitsverzeichnis abgelegt. Bei createrepo wird diese wiederum mit -g comps.xml eingebunden.
  • Die Errata-Informationen können nicht mit reposync heruntergeladen werden, aber beispielsweise yum list-sec lädt diese lokal in den Cache. Kopiert man die updateinfo.xml dann aus dem Repository-Cache in /var/cache/yum/ in das synchronisierte Repository und führt modifyrepo /var/www/html/repo-id/repodata/updateinfo.xml /var/www/html/repo-id/repodata aus, wird diese Teil der Metadaten.
  • Sollen Repositories für ein anderes Betriebssystem zur Verfügung gestellt werden, kann eine Konfiguration erstellt werden, die aber nicht aktiv ist, also enabled=0 enthält. Bei reposync kann dann mit --enablerepo repo-id das Repository nur für die Synchronisation aktiviert werden.

Ich hoffe dieser kleine Artikel hilft dem ein oder anderen. Wem das schnelle einfache Repository nicht genug ist, der kann auch versuchen mit rsync einen vollständigen Mirror aufzusetzen oder mit Katello sogar ein Staging einbauen, damit Updates erst in Entwicklung und Test laden bevor sie in Produktion vielleicht Probleme verursachen. Bei letzterem unterstützen gerne ich oder ein Kollege im Rahmen eines Foreman-Consultings.

Dirk Götz
Dirk Götz
Principal Consultant

Dirk ist Red Hat Spezialist und arbeitet bei NETWAYS im Bereich Consulting für Icinga, Puppet, Ansible, Foreman und andere Systems-Management-Lösungen. Früher war er bei einem Träger der gesetzlichen Rentenversicherung als Senior Administrator beschäftigt und auch für die Ausbildung der Azubis verantwortlich wie nun bei NETWAYS.

STARFACE 6.7.0.22 – SIP Probleme beheben

Mit der neuen STARFACE Version 6.7.0.22 sind einige neue Funktionen und Verbesserungen in die Telefonanlage eingezogen. Leider hat sich hier aber ein kleiner Fehler eingeschlichen, welcher Benutzer mit einem SIP-Anschluss betrifft.

Das Problem tritt auf, wenn im SIP Benutzernamen ein “+” beinhaltet ist. Mit der neuen Version der Software, wird dieses durch “%2B” ersetzt, wodurch eine Anmeldung beim SIP-Provider nicht mehr möglich ist. Die Leitung steckt dadurch im Status “Not registered” fest. Ob man von diesem Fehler betroffen ist, kann man im PBX-Log in der Telefonanlage im Webfrontend unter

Admin > Server > Log-Datei > PBX

einsehen. Hier tritt dann eine Fehlermeldung auf, die bspw. wie folgt aussieht:

[Oct 24 11:40:34] WARNING[362] chan_sip.c: Probably a DNS error for registration to %2B499119288544@+499119288544, trying REGISTER again (after 20 seconds)

Das Problem ist STARFACE bekannt und wird in einer nächsten Version behoben. Als Workaround findet man auf dem STARFACE-Support GitHub Account ein Shell-Script, welches die Einträge in der Datenbank ändert, die Asterisk-Konfiguration anpasst und den Dienst neu startet:

#!/bin/bash

# Revert URLencode in the database
/usr/bin/psql asterisk -c “UPDATE providerconfig SET register = REPLACE(register,’%2B’,’+’);”
/usr/bin/psql asterisk -c “UPDATE providerconfig SET username = REPLACE(username,’%2B’,’+’);”

# Replace all instanced of “%2B” in the sip.conf, while creating a backup (“_SC3960.bak”)
/bin/sed -i_SC3960.bak “s/%2B/+/g” /etc/asterisk/sip.conf

# Show the difference
echo “Here’s what we’ve done:”
/usr/bin/diff -U0 /etc/asterisk/sip.conf_SC3960.bak /etc/asterisk/sip.conf

# Reload the Asterisk SIP config to reregister all lines
/usr/sbin/asterisk -r -x “sip reload”

Damit der Vorgang dann beschleunigt wird, kann die STARFACE anschließend neu gestartet werden. Nun sollte die Anlage sich wieder ordnungsgemäß verbinden können.

Wichtig dabei ist jedoch, dass die Konfiguration über das Web für die Leitungen nicht angepasst wird – danach besteht das Problem wieder und der Workaround muss erneut angewendet werden.

Bei Fragen hierzu steht unser Shop-Team natürlich gerne zur Verfügung und freut sich auf Ihre Kontaktaufnahme!

Christian Stein
Christian Stein
Lead Senior Account Manager

Christian kommt ursprünglich aus der Personalberatungsbranche, wo er aber schon immer auf den IT Bereich spezialisiert war. Bei NETWAYS arbeitet er als Senior Sales Engineer und berät unsere Kunden in der vertrieblichen Phase rund um das Thema Monitoring. Gemeinsam mit Georg hat er sich Mitte 2012 auch an unserem Hardware-Shop "vergangen".