Press left mouse button to continue.

Kategorie: Adminstories (Seite 3 von 4)

Serversynchronisation

Hinweis on: Das ist ein Beitrag aus dem ehemaligen Projekt „adminstories.de“. Bitte hier fuer weitere Informationen schauen.Hinweis off

Wir nutzen zwei Server um eine Vielfalt an Diensten zu nutzen und anzubieten. Die Dienste – Web, Mail, Subversion, WebDav, etc. – haben wir nicht zeitgleich auf beiden Servern laufen. So haben wir Mail beispielsweise auf foo und unsere „privaten“ Webseiten auf bar. Aber unsere Tracs haben wir wieder auf foo und so weiter.

Der Grund fuer zwei Server ist nicht in erster Linie die Verteilung von Last, sondern wir wollen sowas wie erhoete Verfuegbarkeit im Fehlerfall erreichen. Natuerlich muessen wir bei Ausfall einer Maschine noch etwas tun (Namensaufloesung, Dienste hochfahren), aber damit sind wir in der Regel schneller, als einen Server neu aufzusetzen. Denn dafuer muss man auch erst mal die Zeit haben.

Bei der Frage „Wo liegen welche Daten“ orientieren wir uns an dem sogenannten Filesystem Hierarchy Standard, den Dirk schon mal beschrieben hatte. So liegen also alle unsere, nicht fuer den Betrieb der Server benoetigten, Webseiten unterhalb von /srv/www, Mails haben wir in /var/vmail und so weiter. Die genutzte Struktur erlaubt es uns relativ unkompliziert und schnell eine Synchronisation der Daten zwischen beiden Systemen zu etablieren. So synchronisieren wir alle Webseiten alle Stunde von bar nach foo via /usr/bin/rsync -az –delete -b –backup-dir=/srv/bak/rsync/www -e „ssh -c arcfour“ /srv/www/ www-data@foo:/srv/www/. Mit –delete -b –backup-dir=/srv/bak/rsync/www stellen wir sicher, dass am Ursprungsort geloeschte Dateien auch im Ziel geloescht werden, aber auch eine Sicherung der Datei angelegt wird. Man weiss ja nie 🙂

Mail synchronisieren wir ebenfalls alle Stunde, mit im Grunde gleichem Aufruf wie fuer Webseiten. Etwas herausfordernder war die Synchronisation der MySQL-Datenbanken. Auf foo haben wir fuenf Datenbanken und auf bar sind es 21. Vorgabe fuer das zu erstellende Script war unter anderem, dass es ohne Anpassung, sowohl auf foo, als auch auf bar laueffaehig ist. Rausgekommen ist nachfolgendes.

#!/bin/bash
logger -t syncdbs.bash -i „Starting sync“
TIMESTAMP=$(date „+%Y%m%d“)
SOURCE_DIR=“/srv/bak/backup-md2″
DESTINATION_DIR=“/srv/bak/sync“
DB_PREFIX=“db.“
DB_USERNAME=$(awk ‚/user/ {print $3}‘ /etc/mysql/debian.cnf | uniq)
DB_PASSWORD=$(awk ‚/password/ {print $3}‘ /etc/mysql/debian.cnf | uniq)
if [ „`hostname`“ = „foo“ ];then
DB_TO_COPY=“dbbar_01 dbbar_02 dbbar_03 dbbar_04 dbbar_05 dbbar_06 dbbar_07 dbbar_08\
dbbar_09 dbbar_10 dbbar_11 dbbar_12 dbbar_13 dbbar_14 dbbar_15 dbbar_16 dbbar_17\
dbbar_18 dbbar_19 dbbar_20 dbbar_21″
REMOTE_SRV=“bar“
elif [ „`hostname`“ = „bar“ ];then
DB_TO_COPY=“dbfoo_01 dbfoo_02 dbfoo_03 dbfoo_04 dbfoo_05″
REMOTE_SRV=“foo“
else
logger -t syncdbs.bash -i „Aborting syncdbs. no proper hostname found. should be foo or bar.“
exit 9
fi
cd $DESTINATION_DIR
for i in $DB_TO_COPY
do
mysqlshow -u $DB_USERNAME -p$DB_PASSWORD | awk ‚{print $2}‘ | grep ^$i$
if [ $? -eq 0 ]
then
FILENAME=$DB_PREFIX$i-$TIMESTAMP*.sq*
# retrieve file from server
logger -t syncdbs.bash -i „retrieving $FILENAME“
scp -q filecopy@$REMOTE_SRV:$SOURCE_DIR/$FILENAME $DESTINATION_DIR/
# extract file
bzip2 -d $FILENAME
# import database
logger -t syncdbs.bash -i „importing $FILENAME“
mysql -u $DB_USERNAME -p$DB_PASSWORD $i < $FILENAME
rm $FILENAME
else
logger -t syncdbs.bash -i „error: no database $i. skipping $FILENAME“
fi
done
logger -t syncdbs.bash -i „Ending sync“

Basis fuer die Synchronisation ist ein entsprechendes Backup (mysqldump) auf der „gegenueberliegenden“ Seite. Das Script ist, wie man sehen kann, kein Voodoo. Aufwand entsteht, da die Variablen DB_TO_COPY gepflegt werden muessen. Die Anfangsidee „Les‘ doch einfach aus welche Datenbanken auf der anderen Seite sind“ war prima. Das haette man schnell mit einem ssh user@foo mysqlshow -u user -p hinbekommen. Das klappt aber nicht dauerhaft. Laueft der Job auf beiden Servern einmal, habe ich auf beiden Servern alle Datenbanken. Lasse ich den Job dann 12 Stunden spaeter auf foo noch mal laufen, wuerden alle Datenbanken von bar importiert und damit natuerlich auch die fuenf benoetigten Datenbanken auf foo mit einem alten Stand ueberschrieben.

Man koennte, um sich etwas mehr Automatismus zu erhalten, die Datenbanken als bak_* importieren und dann im Fehlerfall umbenennen. Die Idee hat fuer mich aber nicht so viel Charme, da ich beim Umschalten so wenig wie moeglich anfassen moechte.

Nicht zu vergessen ist natuerlich, dass es nur mit der Synchronisation von ein paar Daten und Datenbanken nicht getan ist. Im Ernstfall muss auch sichergestellt sein, dass die genutzten Anwendungen (Maildaemon, Webdaemon, etc.) auch auf der Backupseite verfuegbar sind. Und dann muss man natuerlich auch schauen, dass die Anwendung entsprechend konfiguriert ist. Einfach alle Webseiten kopieren und dann /etc/apache2/sites-enable zu vergessen ist ungeschickt.

Auch sollte nicht vergessen werden, dass die Rechte auf dem Backup gesetzt sind, bzw. noch zu setzen sind. So ist ein Import aller Datenbanken schon mal ein erster Schritt. Aber so lange die Anwendungen keine Rechte auf „ihre“ Datenbank haben bin ich noch nicht am Ziel.

Ja, machnmal waere es leichter einfach irgendwo einen „einfachen Server“ zu mieten. Aber wo bleibt da der Spass?

Migration von WordPress nach s9y

Hinweis on: Das ist ein Beitrag aus dem ehemaligen Projekt „adminstories.de“. Bitte hier fuer weitere Informationen schauen.Hinweis off

Mir ist keine Migration bekannt, bei der es nicht irgendwelche Probleme gab. So auch ein Wechsel von einer Blogsoftware zu einer anderen. Da denkt man „Ach, einfach nur einen Import der Daten und gut“, aber so einfach ist es oft nicht. In vielen Faellen gibt es nicht mal einen gescheiten Importmechanismus. Da ist dann Handarbeit angesagt.

Beim Migrieren meines privaten Blogs von WordPress nach Serendipity (s9y) waren die Vorzeichen etwas besser, da s9y zumindest einen Importer mitbringt (~/include/admin/importers/wordcodess.inc.php). Aber wie oben geschrieben… Migration laueft nicht problemlos. Daher hier mal ein paar Punkte, die ich im Rahmen der Migration zu bewaeltigen hatte. Vorab der Hinweis, dass ein Backup auf jeden Fall Sinn macht. Einmal ein falscher Befehl in der falschen Tabelle und man faengt, im schlimmsten Falle, von vorne an. Ja, ich spreche aus Erfahrung 🙂

Um moeglichen Problemen mit Umlauten (ä, ö, ü) oder bestimmten Sonderzeichen (Halbgeviertstrich, Scharfes S) vorzubeugen macht es Sinn, diese vor dem Import anzupassen. Daher habe ich erst einmal ein Suchen/Ersetzen auf die Tabellen wp_comments und wp_posts gemacht. Hier einmal ein Beispiel fuer das Ersetzen von ä in den Beitraegen und Kommentaren.

UPDATE `wordcodess`.`wp_comments` SET `comment_content` = replace(`comment_content`,’ä‘,’ae‘);
UPDATE `wordcodess`.`wp_posts` SET `post_content` = replace(`post_content`,’ä‘,’ae‘);

Anschliessend habe ich noch, um keine unnoetigten Altlasten mitzunehmen, die Beitraege, die als post_type den Wert revision haben, geloescht. Das sind die Beitraege die sonst spaeter in s9y als Draft auftauchen.

DELETE FROM `wordcodess`.`wp_posts` WHERE `post_type`=’revision‘;

Bitte beachten, dass es auch Werte wie etwa attachment oder page gibt. Somit waere es nicht so prima alles was ungleich revision ist zu loeschen. Der s9y-Importer macht es so, dass er alle Eintraege die nicht den Wert publish haben, als isdraft == true importiert.

Nun habe ich mal – mutig, mutig – einen Import der Daten in sy9 gemacht und geschaut, was es noch zu bereinigen gibt. Zum einen waren das bei mir die Accounts. Diese werden im Rahmen des Imports mitgenommen und es werden auch die Spalten author sowie authorid mit den „alten“ Werten – bei mir ports und 4 – versehen. Ich wollte aber ramon mit der ID 1 haben.

UPDATE `sy9`.`s9y_entries` SET author=’ramon‘;
UPDATE `sy9`.`s9y_entries` SET authorid=1;

Ein weiterer Punkt auf meiner Liste war die Erstellung einer ordentlichen Kategorieliste. Dafuer habe ich erst einmal die entsprechenden Eintraege via TRUNCATE TABLE `s9y_entrycat`; (Welcher Beitrag ist wie kategorisiert) und TRUNCATE TABLE `s9y_category`; (Welche Kategorien gibt es) geleert und neue Kategorien eingepflegt.

INSERT INTO `kl_s9y_ramon`.`s9y_category` (`categoryid`, `category_name`, `category_icon`, \
`category_description`, `authorid`, `category_left`, `category_right`, `parentid`, \
`sort_order`, `hide_sub`) VALUES (NULL, ‚Adminstories‘, “, “, ‚0‘, ‚1‘, ‚2‘, ‚0‘, 0, 0), \
(NULL, ‚Alter Inhalt‘, “, “, ‚0‘, ‚3‘, ‚4‘, ‚0‘, 0, 0),

Das anschliessende kategorisieren musste dann, zumindest bei mir, von Hand erfolgen, da ich mir jeden Beitrag noch mal anschauen musste. Ansonsten koennte man auch etwas wie

INSERT INTO `s9y`.`s9y_entrycat` (`entryid`, `categoryid`) VALUES (‚2‘, ‚2‘);
INSERT INTO `s9y`.`s9y_entrycat` (`entryid`, `categoryid`) VALUES (‚3‘, ‚2‘);

verwenden. Damit wuerde dann der Beitrag mit der ID 2 und 3 der Kategorie mit der ID 2 zugewiesen.

Im Rahmen meiner Migration habe ich mehrfach einen Fehler gemacht, so dass ich den Datenimport auch jedesmal gemacht habe. Da ich nicht jedesmal eine neue Datenbank erstellen wollte habe ich mich darauf beschraenkt, vor jedem neuen Versuch, die fuer mich relevanten Tabellen zu leeren und meinen Benutzer anzulegen.

TRUNCATE TABLE `s9y_authors`;
INSERT INTO `lx_logbuch`.`serendipity_authors` (`realname`, `username`,`password`, \
`authorid`, `mail_comments`, `mail_trackbacks`, `email`,`userlevel`, `right_publish`, \
`hashtype`) VALUES (‚Ramon Kukla‘,’ramon‘, ‚abcdefghijklmnopqrstuvwxyz0123456789abcd‘, \
‚5‘, ‚1‘, ‚1‘, ‚ramon@kukla.info‘, ‚255‘, ‚1‘, ‚1‘);
TRUNCATE TABLE `s9y_category`;
TRUNCATE TABLE `s9y_comments`;
TRUNCATE TABLE `s9y_entries`;
TRUNCATE TABLE `s9y_entrycat`;
TRUNCATE TABLE `s9y_permalinks`;
TRUNCATE TABLE `s9y_references`;
TRUNCATE TABLE `s9y_refs`;

Alles in allem war die Migration, allerdings auch aus weiteren Gruenden, eine sehr zeitintensive Geschichte. Der Grund, warum ich nach einem Wechsel von s9y zu Wordcodess und nun wieder zu s9y zurueck bin, sind ueberschaubar. Ich fuehle mich bei s9y einfach wohler, der Support im Forum ist prima und es ist – nicht gemessen, aber mein subjektiver Eindruck – schneller als WordPress.

Namensschema bei Firewallobjekten

Hinweis on: Das ist ein Beitrag aus dem ehemaligen Projekt „adminstories.de“. Bitte hier fuer weitere Informationen schauen.Hinweis off

Wer aus der Programmierung kommt, oder sich zumindest mal etwas mehr mit der Programmierung beschaeftigt hat, der kennt das. Nach welchem Schema benenne ich Namen, Funktionen und so weiter? Ich persoenlich moechte beispielsweise, wenn moeglich, alleine Anhand des Variablennamens erkennen koennen von welchem Typ die Variable, bzw. deren Wert haben kann oder wird. Im Zusammenhang mit Programmierung gibt es auch verschiedene Empfehlungen und Dokumente. Mir fehlte sowas aber immer fuer den Bereich Firewall.
Was bei vielen richtigen Firewalls zu finden ist, sind so Dinge wie Hosts, Netzwerke Dienste und Gruppen von Zielen oder Diensten. Hier habe ich fuer mich einige Regularien definiert.
Generell versuche ich mich an folgende Punkte zu halten:

• Keine Verwendung von Leerzeichen. Zum trennen ein Unterstrich „_“ verwenden
• Erstes Zeichen keine Ziffer
• Nur Gruppen (mehrere Hosts) bilden, die auch sinnvoll zueinander gehoeren. Alle Domino-Server z.B. nach Gruppe „Domino_Server“.

Die einzelnen Objekte, exklusive Dienste, haben dann folgenden Aufbau: Typkennung_Ortkennung_Name_Nummerierung

Typkennung:
• „h“ = Host
• „n“ = Netz
• „g“ = Gruppe

Ortkennung:
• „cgn“ = Koeln
• „ber“ = Berlin
• „ham“ = Hamburg
• „nbp“ = New York
• „ext“ = extern, also keine Zweigstelle

Name: Name (Kleinschreibung). Bei internen Maschinen der (DNS)Hostname (nicht FQDN). Bei externem Host, wenn aufloesbar, DNS-Name.

Nummerierung: Wenn mehrere Objekte mit identischem Namen angelegt werden muessen.

Bei der Ortkennung erhaelt jede Zweigstelle, die an die Zentrale angebunden ist, einen eigenen „Namen“. Des Weiteren gibt es natuerlich noch externe Ressourcen. Die Kuerzel der Orte sind an die sogenannten IATA-Codes angelehnt. Das sind die Codes, mit denen unter anderem Flughaefen abgekuerzt werden. Das passte bei uns so. Schwer wird es, wenn nicht alle Zweigstellen einen Flughafen in der Naehe haben. Dann kann man, wenn es innerhalb von Deutschland ist, schhauen ob man sich an Autokennzeichen orientiert.

Habe ich nun an der Zentrale einen Host, der abc123 heisst, so wuerde ich das Geraet auf der Firewall wie folgt benennen: h_cgn_abc123. Die abschliessende Nummerierung kann entfallen, da es den Host mit dem Namen nur einmal gibt. Der Host xyz789 in Hamburg wuerden auf der Firewall h_ham_xyz789 genannt. Wer Wert auf eine Sortierung nach Hostnamen legt sollte das Namensschema entsprechend anpassen.

Gerne ignoriert, aber auch nicht unwichtig, sind die angebotenen Kommentarfelder fuer Objekte und Regeln. Vor allem im Hinblick darauf, dass ein Hostname wie h_ext_drt445 nicht wirklich erklaerend ist, darf man diese ruhig nutzen. Hier habe ich in der Regel folgendes Schema: NamenskuerzelDatum_Beschreibung

Als Namenskuerzel, klein geschrieben, kommt immer der Kuerzel, erster Buchstabe des Vornamen und Nachnamen, der Person, die das Objekt bearbeite hat in den Kommentar. Das Datum wird mit YYMMDD angegeben und die Beschreibung ist dann selbst erklaerend. Mein Host, den ich oben angelegt hatte, wuerde ich also mit dem Kommentar rk110508_Host_Kukla versehen. Das macht es Kollegen, oft aber auch einem selber, leichter zu erkennen, was das Objekt fuer einen Zweck hat.

Webserver testen

Hinweis on: Das ist ein Beitrag aus dem ehemaligen Projekt „adminstories.de“. Bitte hier fuer weitere Informationen schauen.Hinweis off

Telnet ist fuer rudimentaere Pruefungen von einzelnen Services immer wieder hilfreich. So nutze ich telnet oft und gerne bei der Einrichtung eines weiteren VirtualHost fuer Apache. Moechte ich beispielsweise pruefen, ob meine Einrichtung von (www).kukla.info erfolgreich war, verbinde ich mich erst einmal via ramon@server:/# telnet 188.40.55.168 80 mit dem Zielsystem. Nach erfolgreichem Connect setzt man ein GET / HTTP/1.1 und Host: www.kukla.info ab.

Trying 188.40.55.168…
Connected to 188.40.55.168.
Escape character is ‚^]‘.
GET / HTTP/1.1
Host: www.kukla.info

HTTP/1.1 200 OK
Date: Wed, 04 May 2011 09:30:42 GMT
Server: Apache/2.2.14 (Ubuntu)
Vary: Accept-Encoding
Content-Length: 918
Content-Type: text/html;charset=UTF-8

Wofuer telnet auch gerne genommen wird, ist die Funktionalitaet eines Proxy-Server zu testen. Hier mal ein Beispiel.

ramon@server ~ $ telnet 10.0.0.194 8080
Trying 10.0.0.194…
Connected to 10.0.0.194.
Escape character is ‚^]‘.
GET http://www.kukla.info HTTP/1.1

HTTP/1.1 200 OK
Date: Wed, 04 May 2011 12:13:12 GMT
Server: Apache/2.2.14 (Ubuntu)
Last-Modified: Tue, 08 Feb 2011 08:16:57 GMT
ETag: „19f619a-b1-49bc0f8cc3040“
Accept-Ranges: bytes
Content-Length: 177
Vary: Accept-Encoding
Content-Type: text/html
X-Pad: avoid browser bug

Was nun noch fehlt ist eine Pruefung, ob ein Server, der „SSL macht“ auch laueft. Dafuer eignet sich, jetzt mal kein telnet, openssl prima. Um zu testen, ob https://foo.ptlx.de ansprechbar ist, kann man wie folgt vorgehen.

ramon@server~ $ openssl s_client -connect foo.ptlx.de:443
CONNECTED(00000003)
depth=1 /C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1…
verify error:num=20:unable to get local issuer certificate
verify return:0

Certificate chain


Server certificate
—–BEGIN CERTIFICATE—–

—–END CERTIFICATE—–
subject=/description=355005-87Ci2G3lTf8AQHQ2/C=DE/O=Persona Not Validated/OU=StartCom…
issuer=/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1…

No client certificate CA names sent

SSL handshake has read 4010 bytes and written 319 bytes

New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Comcodession: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : DHE-RSA-AES256-SHA
Session-ID: 181CA64B905EE437B3131C604B037F54107E6E4F301325DB6F8612EDC4A27AAD
Session-ID-ctx:
Master-Key: 558310FFD416AFF6FFC229663A1C6A3F531ECD6A26FF035D91D433079A003856AB1…
Key-Arg : None
Start Time: 1304511190
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)

GET /index.html HTTP/1.1
Host: foo.ptlx.de

Installation eines Trac-Plugins

Hinweis on: Das ist ein Beitrag aus dem ehemaligen Projekt „adminstories.de“. Bitte hier fuer weitere Informationen schauen.Hinweis off

Wir, Dirk und ich, nutzen in verschiedenen Bereichen Trac um unsere gemeinsame Koordination, Planung und Dokumentation realisieren zu koennen. Wir hatten mal ueberlegt ob wir ein anderes Ticketsystem verwenden, sind aber bei Trac geblieben, weil es einfach das optimalste Tool fuer unsere Aufgaben ist. Und auch toll an Trac ist die Erweiterserverkeit mit Plugins. Und weil das so toll ist, moechte ich nur mal kurz erklaeren, wie man (in der Regel) schnell und unkompliziert ein Plugin installiert.

Ich, der ja so der visuelle Typ bin, wollte man eine ordentliche Theme fuer unser Trac. Voraussetzung fuer die Verwendung der von uns gewuenschten Theme (Tseve Theme) ist das ThemeEnginePlugin.

Zu Anfang holen wir uns erst einmal die aktuellste Version aus dem Repository.

ramon@server ~ $ svn checkout http://trac-hacks.org/svn/themeengineplugin/0.11/

Nun starten wir die Installation des Plugins.

ramon@server ~ $ cd 0.11/
ramon@server ~ $ sudo python setup.py install
[sudo] password for ramon:
running install

Finished processing dependencies for TracThemeEngine==2.0.1

Nach der Installation sollte geprueft werden, dass die Berechtigung fuer das installierte Plugin korrekt gesetzt ist. Ansonsten kann es passieren, dass ihr das Plugin innerhalb von Trac, kommt gleich, konfiguriert, es aber nicht geladen werden kann.

Wir richten nun also das Plugin fuer Trac ein. Dafuer erstellen wir erst einmal einen Symbolischen Link erstellen im entscodechenden Ordner.

ramon@server ~ $ sudo ln -s /usr/local/lib/python2.6/dist-packages/TracThemeEngine-py2.6.egg/ \
/srv/trc/foobar/plugins/TracThemeEngine-py2.6.egg
ramon@server ~ $ ls -l /srv/trc/foobar/plugins/
total 8
lrwxrwxrwx 1 root root 71 2011-03-20 10:34 TracThemeEngine-py2.6.egg \
-> /usr/local/lib/python2.6/dist-packages/TracThemeEngine-py2.6.egg/

Nun muessen wir das Plugin noch aktivieren. Das wird ueber die trac.ini, die in ~/conf/ zu finden ist, erledigt. In dem speziellen Fall erfolgt folgender Eintrag in der Konfigurationsdatei (conf.ini).

[components]
themeengine.* = enabled

Nun kann man, da wir schon mal Fahrt aufgenommen habe, schnell noch die gewuenschte Theme auschecken, installieren Symbolischen Link und fuer Trac konfigurieren.

ramon@server ~ $ svn checkout svn checkout http://trac-hacks.org/svn/tsevetheme/0.11/
Checked out revision 9971.
ramon@server ~ $ cd 0.11/
ramon@server ~ $ sudo python setup.py install
running install
…Finished processing dependencies for TseveTheme==1.0
ramon@server ~ $ sudo ln -s /usr/local/lib/python2.6/dist-packages/0.11-1.0-py2.6.egg/ \
/srv/trc/foobar/plugins/0.11-1.0-py2.6.egg
ramon@server ~ $ ls -l /srv/trc/foobar/plugins/
total 12
lrwxrwxrwx 1 root root 64 2011-03-20 10:40 TseveTheme-1.0-py2.6.egg \
-> /usr/local/lib/python2.6/dist-packages/0.11-1.0-py2.6.egg/
ramon@server ~ $ vi /srv/trc/foobar/conf/trac.ini

Und dort dann folgende einstellen.

# Enable the plugin:

[components]
tsevetheme.* = enabled

# Set the theme as the default theme:

[theme]
theme = Tseve

Ergaenzend noch der Hinweis auf Trac Hacks, wo es viele tolle Erweiterungen fuer Trac zu finden gibt.

Deaktivieren von LAN Sync

Hinweis on: Das ist ein Beitrag aus dem ehemaligen Projekt „adminstories.de“. Bitte hier fuer weitere Informationen schauen.Hinweis off

Dirk hatte vor einiger Zeit mal etwas zu Dropbox und deren Clientinstallation aus der Console heraus geschrieben. Neben dieser gibt es auch eine weitere gute Beschreibung bei dropbox.com selbst. Dirk und ich nutzen Dropbox gerne fuer die Synchronisation von Daten ueber verschiedene Maschinen hinweg. Hierzu haben wir uns unseren Dropbox-Client auch auf unseren Servern installiert. Was uns, aber auch anderen, spaeter aufgefallen war ist, dass nach dem Start von Dropbox ein Listener an Port 17500 gebunden wird. Der Port wird fuer den sogenannten LAN Sync-Mechanismus verwendet. Im Groben geht es darum, die Synchronisationsgeschwindigkeit im LAN zu optimieren. Siehe auch „What is LAN sync?„.

Das mag ein nettes Feature sein, wird auf unseren Servern aber nicht benoetigt. Daher wollten wir das Deaktivieren. Das funktioniert leider nicht wie erwartet ueber eine einfache Konfigurationsdatei. Die Konfiguration fuer Dropbox liegt in einer sqlite3-Datenbank. Bei mir ist das z.B. ~/.dropbox/config.db. Um nun den Listener abzuschalten muss also nun LAN Sync deaktiviert werden. Hierfuer werden die beiden Scripte pyDropboxValues.py und dropbox_set_lansync.py welches beim Start auf Ersteres zugreift) benoetigt. Anschliessend kann, nach dem Beenden von Dropbox, via dropbox_set_lansync.py off LAN Sync deaktiviert werden. Wird Dropbox nun wieder gestartet hat man auch den Port 17500 wieder „frei“.

Datei != Datei

Hinweis on: Das ist ein Beitrag aus dem ehemaligen Projekt „adminstories.de“. Bitte hier fuer weitere Informationen schauen.Hinweis off

Vor einigen Tage wollte ich, wie auch mal in Arbeit auf vielen Servern beschrieben, einige Server auf einen aktuellen Stand bringen. Also eine neue lokale Konsole auf und ein beherztes ramon@zak:~$ for i in $(< server); do ssh $i „sudo aptitude update && sudo aptitude safe-upgrade“; done abgesetzt. Was erhalte ich als Meldung?

: Name or service not knownname srv-cgn-01

Ich gebe zu, ich war etwas verwundert, da in meiner ~/.ssh/config ein Eintrag fuer eben diesen und acht andere Server zu finden ist. Um sicher zu gehen, dass alles klappt, versuche ich mich haendisch mit dem Server zu verbinden.

ramon@zak ~ $ ssh srv-cgn-01
Linux srv-cgn-01 2.6.32-30-server #59-Ubuntu SMP Tue Mar 1 22:46:09 UTC 2011 x86_64 GNU/Linux
Ubuntu 10.04.2 LTS

Welcome to the Ubuntu Server!
* Documentation: http://www.ubuntu.com/server/doc

System information as of Wed Mar 23 10:14:58 CET 2011

System load: 0.21 Processes: 143
Usage of /: 2.4% of 128.80GB Users logged in: 0
Memory usage: 7% IP address for eth0: 87.79.26.35
Swap usage: 0% IP address for eth1: 192.168.100.1
Temperature: 8 C

Graph this data and manage this system at https://landscape.canonical.com/

0 packages can be updated.
0 updates are security updates.

Last login: Tue Mar 22 07:54:16 2011 from foo.ptlx.de
ramon@zak

Klappte soweit. Jetzt wollte ich doch mal schauen, was mir hier mit einem echo angezeigt wird.

ramon@zak ~ $ for i in $(cat server_ptlx); do echo ssh $i ls; done
ls srv-cgn-01
ls srv-cgn-02
ls srv-cgn-03
ls srv-cgn-04
ls srv-cgn-05
ls srv-cgn-06
ls srv-cgn-07
ls srv-cgn-08
ls srv-cgn-09
ramon@zak

Das war definitiv nicht die Ausgabe, die ich erwartet hatte. Viel mehr waere etwas wie ssh srv-cgn-01 ls zu erwarten gewesen. Ich werde es nicht zu Spannend machen, moechte aber sagen, dass ich bei dem Problem sogar angefangen hatte strace in die Loesungssuche mit einzubeziehen. Nach einigen Mails zwischen Dirk und mir kam dann die entscheidende Frage „Deine .ssh/config ist eine Unix-Datei, oder?“.

ramon@zak:~$ file .ssh/config
.ssh/config: ASCII text

Ja, offensichtlich war die Datei „in Ordnung“. Aber was war mit meiner Datei, in der alle Server eingetragen sind?

ramon@zak ~ $ file server
server: ASCII text, with CRLF line terminators

Ja, da muss man erst mal drauf kommen. In der Datei war nicht, wie bei Linux-Dateien typisch, nur ein Line Feed, sondern ein Carriage Return mit anschliessendem Line Feed zu finden. In der Regel kommen Dateien mit einem CRLF aus dem Windows-Umfeld.

Als ich die Datei bereinigt hatte, hat auch mein oben genannte Aufruf endlich funktioniert. Viele Beispiele, wie so eine Bereinigung aussehen kann, finden sich unter HowTo: UNIX / Linux Convert DOS Newlines CR-LF to Unix/Linux Format. Unklar ist mir weiterhin, wieso die Datei bei mir auf einmal mit einem CRLF auftaucht 🙂

Debug SSH

Hinweis on: Das ist ein Beitrag aus dem ehemaligen Projekt „adminstories.de“. Bitte hier fuer weitere Informationen schauen.Hinweis off

Aus gegebenem Anlass etwas „Wiederverwertung“ :). Die Tage wurde ich angesprochen, da ein Kollege ein Problem hatte. Es ging darum, dass eine SSH-Verbindung mit Authentifizierung via SSH-Key nicht funktionieren wollte. Im Detail stellte es sich so dar, dass der Client eine Kennwortabfrage brachte. Frage war nun, was hier der Grund fuer den Effekt war. Also haben wir uns erst mal an den Client gesetzt und die loebliche, aber nur selten verwendete Option -v, genutzt.

ramon@client ~/.ssh $ ssh -vvv ramon@server
debug1: Next authentication method: publickey
debug1: Trying private key: /home/ramon/.ssh/identity
debug3: no such identity: /home/ramon/.ssh/identity
debug1: Trying private key: /home/ramon/.ssh/id_rsa
debug1: read PEM private key done: type RSA
debug3: sign_and_send_pubkey
debug2: we sent a publickey packet, wait for reply
debug3: Wrote 640 bytes for a total of 1767
debug1: Authentications that can continue: publickey,password
debug1: Trying private key: /home/ramon/.ssh/id_dsa
debug3: no such identity: /home/ramon/.ssh/id_dsa
debug2: we did not send a packet, disable method
debug3: authmethod_lookup password
debug3: remaining preferred: ,password
debug3: authmethod_is_enabled password
debug1: Next authentication method: password
ramon@server’s password:

Hier kann man prima sehen, dass versucht wird mit id_dsa sich gegenueber dem Server zu authentifizieren. Allerdings schlaegt das fehl. Das sieht man daran, dass nach einem Kennwort gefragt wird. Schauen wir also mal wie es sich auf dem Server darstellt. Um den laufenden Betrieb nicht zu stoeren starten wir einen weiteren SSH-Daemon inklusive Debug-Option der auf Port 24 lauscht.

root@server:/# /usr/sbin/sshd -p 24 -ddd

Nun versuchen wir uns noch einmal via ssh -p 24 user@server am Server anzumelden und schauen, was der Server ausgibt.

debug1: trying public key file /home/ramon/.ssh/authorized_keys
debug1: fd 4 clearing O_NONBLOCK
Authentication refused: bad ownership or modes for file /home/ramon/.ssh/authorized_keys
debug1: restore_uid: 0/0
debug1: temporarily_use_uid: 1000/1000 (e=0/0)
debug1: trying public key file /home/ramon/.ssh/authorized_keys2
debug1: restore_uid: 0/0
Failed publickey for ramon from 10.0.0.194 port 41962 ssh2

Hier kann man nun prima sehen warum der Zugriff nicht wie geplant funktioniert. Der Ausloeser ist die falsch gesetzte Berechtigung auf der authorized_keys. Entweder setzt man nun also die Rechte „korrekt“, ausser dem Owner darf niemand W(rite) haben, oder man setzt StrictMode no. Letzteres ist allerdings nicht zu empfehlen. Wer interessiert ist findet die Pruefung auch im Quellcode von OpenSSH in der auth.c. Die Funktion nennt sich da secure_filename.

tcpdump im Einsatz

Hinweis on: Das ist ein Beitrag aus dem ehemaligen Projekt „adminstories.de“. Bitte hier fuer weitere Informationen schauen.Hinweis off

Heute gibt es mal was aus meiner „Grabbelkiste“. Aufgrund meiner Taetigkeit als Administrator, der sowohl Infrastruktur sowie auch punktuell Server betreut, muss ich auch immer wieder nach Problemen im Netzwerk suchen. Neben Dingen wie etwa „get flow“ und „snoop“ fuer Juniper kommt da natuerlich auch immer wieder gerne tcpdump zum Einsatz. Die Nutzung von tcpdump macht nicht nur Eindruck bei den Frauen, sondern hilft durchaus auch Probleme im Netzwerkverkehr zu identifizieren.

Da die Auswertung der angezeigten Informationen von tcpdump in Echtzeit nur was fuer die ganze Harten ist, schreibe ich mir die Ausgabe in der Regel in ein File weg.

tcpdump -n -i eth0 -w dump.pcap

Anschliessend schaue ich das Resultat in einem Wireshark an, da man damit die eigentliche Auswertung doch etwas angenehmer gestalten kann. In diesem Beispiel wird man sich moeglicherweise wundern, dass die mitgeschnittenen Pakete nur bis zu einer bestimmen Groesse mitgeschnitten wurden. Der Standard fuer snaplen, so nennt sich der Wert, ist laut manpage fuer IPv4 68 Bytes. Da ich immer Sorge habe etwas zu verpassen rufe ich tcpdump daher immer mit -s 0 auf. Somit werden alle Pakete komplett mitgeschnitten.

In der Regel beschraenke ich meine Filter auf so einfache Dinge wie etwa host a.b.c.d oder (not) port 22. Es geht aber auch feiner. Das ist vor allem dann interessant, wenn man spaeter keine Auswertung via Wireshark machen kann oder moechte.

Auf unserem gemeinsamen Server hatten wir vor einigen Wochen das Problem, dass unser Webserver wegen einer ungewoehnlich hohen Anzahl an Anfragen leiden musste. Alles sah nach einem Spam-Angriff von einigen wenigen Adressen aus. Das konnten wir nicht nur nicht nur an vielen Eintraegen im Log sehen, sondern auch mit Hilfe von tcpdump darstellen.

sudo tcpdump -c 30 -ne -i eth0 dst port 80 and ‚tcp[13] == 2‘ \
| awk ‚{print $10}‘ \
| cut -d. -f1,2,3,4 \
| sort \
| uniq -c \
| sort -n

Mit Hilfe dieses Aufrufes werden 30 Pakete gesammelt, die ausschliesslich das SYN-Flag gesetzt haben. Nach dem Einsammeln der Pakete wird die IP-Adresse mit awk und cut „extrahiert“ und anschliessend wird eine Liste (Aufsteigend) erstellt, in der die Hauefigkeit einer auftretenden IP-Adresse zu sehen ist. Doofer Satz, daher eine Beispielausgabe:

ramon@bar ~ $ sudo tcpdump -c 30 -ne -i eth0 dst port 80 and ‚tcp[13] == 2‘ \
| awk ‚{print $10}‘ \
| cut -d. -f1,2,3,4 \
| sort \
| uniq -c \
| sort -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0:1, link-type EN10MB (Ethernet), capture size 96 bytes
30 packets captured
30 packets received by filter
0 packets dropped by kernel
1 114.64.146.44
1 188.40.55.145
1 218.214.140.146
1 66.244.66.217
1 66.244.72.142
1 67.145.111.246
2 66.244.72.44
2 41.210.106.254
4 66.244.66.44
4 87.150.185.168
14 45.220.250.244

Die IP-Adressen sind randomized (kann man „verzufaelligt“ sagen? ;). Die Liste kann man anschliessend prima nutzen um, nach der Bearbeitung, z.B. via iptables die „fuehrenden“ IP-Adressen zu blockieren.

Arbeit auf vielen Servern

Hinweis on: Das ist ein Beitrag aus dem ehemaligen Projekt „adminstories.de“. Bitte hier fuer weitere Informationen schauen.Hinweis off

Dirk und ich helfen unter anderem ja bei der Betreuung einiger Server fuer den ubuntu Deutschland e.V. Im Detail handelt es sich hierbei um neun Server die in Koeln bei NetCologne in einem Schrank verbaut sind. Ich erwaehne NetCologne deshalb, da man dort so nett war und uns Platz im RZ gesponsert hat.

Der von uns gewaehlte Aufbau stellt sich wie folgt dar:


Wie hier (un)schwer zu erkennen ist, haben wir zwei Server, die von aussen erreichbar sind. Der Rest der Maschinen sitzt in einem privaten Netz und ist von aussen nicht direkt ansprechbar. Nach dem Einbau der Server mussten natuerlich einige Konfigurationen und Einrichtungen durchgefuehrt werden, die auf allen Servern identisch waren. Beispielsweise waere das die Anlage der berechtigten Benutzer, die Aktualisierung der Systeme oder auch die Abfrage von Hardwareinformationen fuer die eigene Dokumentation. Die Frage war nun, wie koennen anstehende Taetigkeiten unkompliziert ausgefuehrt werden? Fuer die beiden direkt von aussen erreichbaren Server bietet sich ad hoc cssh (Central Secure Shell) an. Hiermit ist es moeglich Befehle auf mehreren Systemen zeitgleich abzusetzen. Dirk hatte in seinem Blog hierzu schon mal das ein oder andere geschrieben.

Wie aber frage ich beispielsweise die Plattenkapazitaet aller Server an, die nicht direkt von aussen erreichbar sind?

Hier haben wir mal wieder eine von vielen moeglichen Loesungen. Zu Anfang erstellen wir auf einem der „vorderen“ Server erst einmal eine Liste aller Server, die wir spaeter ansprechen moechten. Liste bedeutet hier, dass in jeder Zeile eine Serveradresse zu finden ist. Anschliessend koennen wir diese Liste nutzen um, mit Hilfe der immer wieder gerne uebersehenen Command-Funktion von ssh, unsere Befehle auf den Maschinen auszufuehren.

ramon@srv-cgn-01:~$ for i in $(< server); do ssh $i df -h; done

Schon wird auf allen in der Liste befindlichen Servern der Befehl df -h ausgefuehrt. Zu beachten ist, dass beispielsweise der Befehl sudo visudo im aktuellen Beispiel nicht funktionieren wuerde. Statt dessen wird man eine Meldung wie „sudo: no tty present and no askpass program specified“ erhalten. Der Grund fuer die Meldung ist, dass sudo eine Konsole fuer die Passwortabfrage benoetigt, die via ssh aber nicht „durchgereicht“ wird. Abhilfe schafft hier die Option -t. Sprich, ein ramon@srv-cgn-01:~$ for i in $(cat server); do ssh -t $i sudo visudo; done bietet einem auch die Passwortabfrage fuer das sudo der entfernten Maschine an.

Das Szenario kann natuerlich an einigen Stellen vereinfacht werden. Aber dazu vielleicht spaeter noch mal mehr.
Was mich interessieren wuerde ist, wie eure Loesung aussieht?

« Ältere Beiträge Neuere Beiträge »

© 2025 Software Failure

Theme von Anders NorénHoch ↑