Die Tastatur meines Dell Latitude D530 erzeugte Zeichen, die nie getippt wurden. Das geschah vor allem in bestimmten Neigungswinkeln des Notebooks, was mich eine Art Kurzschluß, eine ungewünschte Kontaktbrücke aufgrund Verschmutzung oder sowas vermuten ließ. Ich wollte die Tastatur ausbauen und prüfen und zu meiner Überraschung findet sich sogar eine detaillierte Anleitung dazu auf den Seiten des Herstellers. Nachdem Hinge Cover und Keyboard herausgelöst waren, konnte ich es reinigen und seit dem Wiedereinbau ist mein Ghostwriter im Ruhestand.
110
Die Tastatur meines Dell Latitude D530 erzeugte Zeichen, die nie getippt wurden. Das geschah vor allem in bestimmten Neigungswinkeln des Notebooks, was mich eine Art Kurzschluß, eine ungewünschte Kontaktbrücke aufgrund Verschmutzung oder sowas vermuten ließ. Ich wollte die Tastatur ausbauen und prüfen und zu meiner Überraschung findet sich sogar eine detaillierte Anleitung dazu auf den Seiten des Herstellers. Nachdem Hinge Cover und Keyboard herausgelöst waren, konnte ich es reinigen und seit dem Wiedereinbau ist mein Ghostwriter im Ruhestand.
Bcc Pro Queue in OTRS
Die Antworten auf Tickets einer bestimmten Queue im OTRS sollen per Bcc an eine weitere Adresse gesendet werden. Das sieht OTRS bisher nicht vor; die einzige Option ist ein generelles Bcc für alle Queues.
Um hier Abhilfe zu schaffen, habe ich Kernel/Modules/AgentTicketCompose.pm
ein wenig erweitert. Etwa bei Zeile 400 findet sich folgende Methode, bei der die mit Bcc beginnende Zeile wie folgt geändert wird.
-Bcc => $GetParam{Bcc},
Bcc => $Ticket{QueueID} == 83 ? ('bcc@example.com') : $GetParam{Bcc},
Die QueueID (im Beispiel 83) und die Zieladresse müssen selbstverständlich angepaßt werden.
# send email
my $ArticleID = $Self->{TicketObject}->ArticleSend(
ArticleType => 'email-external',
SenderType => 'agent',
TicketID => $Self->{TicketID},
HistoryType => 'SendAnswer',
HistoryComment => "%%$Recipients",
From => $GetParam{From},
To => $GetParam{To},
Cc => $GetParam{Cc},
# Dirty hack to Bcc (forward) answers of tickets from queue id=83.
#Bcc => $GetParam{Bcc},
Bcc => $Ticket{QueueID} == 83 ? ('bcc@example.com') : $GetParam{Bcc},
Subject => $GetParam{Subject},
UserID => $Self->{UserID},
Body => $GetParam{Body},
InReplyTo => $GetParam{InReplyTo},
Charset => $Self->{LayoutObject}->{UserCharset},
Type => 'text/plain',
Attachment => @AttachmentData,
%ArticleParam,
);
Mit ein bisschen mehr Aufwand ließe sich das auch auf mehrere Queues ausweiten sowie die Definition der QueueIDs und Bcc-Adressen in die Konfigurationsdatei auslagern. Das überlasse ich dem geneigten Leser als Hausaufgabe.
109
Zugangsdaten für den Router Siemens ADSL SL2-141-I im Auslieferungszustand (von Alice DSL):
- IP-Adresse: 192.168.1.1
- Benutzername: alice@13184
- Passwort: hnto$mgmt@lice
Konsistenz Einer MySQL-Replikation Testen
Einen einfachen und schnellen Weg, die Datenkonsistenz einer Replikation in MySQL zu überprüfen, bietet mk-table-checksum aus Maatkit. Das Perl-Skript erstellt Prüfsummen der Tabellen und schreibt diese in eine eigene Tabelle. Durch die Replikation wird diese Tabelle auf den Slave übertragen und dort ebenfalls die Prüfsummen ermittelt. Hinterher lassen sich auf dem Slave die Prüfsummen vergleichen und eventuelle Veränderungen der Datenbestände feststellen. Diese lassen sich dann beispielsweise mit mk-table-sync aus der selben Tool-Sammlung wieder synchronisieren.
Bevor es losgeht, muß auf dem Master eine neue Datenbank (hier test
) und die folgende Tabelle erstellt werden.
CREATE TABLE checksum (
db char(64) NOT NULL,
tbl char(64) NOT NULL,
chunk int NOT NULL,
boundaries char(100) NOT NULL,
this_crc char(40) NOT NULL,
this_cnt int NOT NULL,
master_crc char(40) NULL,
master_cnt int NULL,
ts timestamp NOT NULL,
PRIMARY KEY (db, tbl, chunk)
);
Danach wird das Skript ausgeführt.
mk-table-checksum --replicate=test.checksum h=localhost,u=username,p=password,S=/data/db/mysql.sock
Ist das Programm durchgelaufen, kann man hinterher auf dem Slave prüfen, ob die Prüfsummen von Master und Slave abweichend sind.
SELECT db, tbl, chunk, this_cnt-master_cnt AS cnt_diff,
this_crc master_crc OR ISNULL(master_crc) ISNULL(this_crc)
AS crc_diff
FROM checksum
WHERE master_cnt this_cnt OR master_crc this_crc
OR ISNULL(master_crc) ISNULL(this_crc);
108
Die Vorratsdatenspeicherung Umgedreht
Wer im Internet unterwegs ist, hinterläßt dabei seine Spuren unter anderem in Form der IP-Adresse des verwendeten Zugangs. Diese Adressen werden von den Providern zum Zweck der Strafverfolgung gespeichert (siehe Vorratsdatenspeicherung). Außerdem kann die IP-Adresse vom Kommunikationspartner, also Webservern, Chatkontakten, Teilnehmern von P2P-Netzwerken usw. gespeichert werden.
Am Wochenende las ich einen haarsträubenden Bericht über den Umgang mit IP-Adressen in straf- und zivilrechtlichen Prozessen, wodurch Unschuldige wegen unbeweisbarer Behauptungen und Übertragungsfehlern zu Unrecht unschöner Dinge verdächtigt wurden. Dabei kam mir die Idee, die Vorratsdatenspeicherung umzudrehen und die von mir benutzten IP-Adressen selbst zu speichern. Sollte ich einmal in die unangenehme Situation kommen, solchen Verdächtigungen ausgesetzt zu sein, kann ich wenigstens für mich selbst überprüfen, ob es wirklich von meinem Anschluß geschah. Ob das juristisch von Bedeutung und bei der eigenen Verteidigung verwertbar ist, weiß ich nicht. Aber es würde wenigstens die eigenen Zweifel ausräumen.
Daher habe ich also eine kleine Lösung entwickelt. Benötigt wird in diesem Fall ein Linux-System mit Perl und MySQL sowie ein Webserver, der CGIs (ebenfalls Perl) ausführen kann.
Zunächst wird ein Datenbankschema mit einer Tabelle angelegt. Die Tabelle wird später zur Speicherung der IP-Adressen und Start- sowie Enddatum deren Nutzung gebraucht.
CREATE DATABASE `remote_addr_logger` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `remote_addr_logger`;
CREATE TABLE IF NOT EXISTS `remote_addr` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`remote_addr` int(10) unsigned NOT NULL COMMENT 'Remote ip address. Use INET_NTOA() to convert.',
`date_start` datetime NOT NULL COMMENT 'Address used between ...',
`date_end` datetime NOT NULL COMMENT 'and ...',
PRIMARY KEY (`id`),
KEY `remote_addr` (`remote_addr`),
KEY `date_start` (`date_start`),
KEY `date_end` (`date_end`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Für den Zugriff auf die Datenbank wird noch ein Benutzer angelegt.
GRANT SELECT , INSERT , UPDATE ON `remote_addr_logger` . * TO 'remote_addr'@'localhost' IDENTIFIED BY '***';
Als Nächstes braucht es eine Möglichkeit, die IP-Adresse seines Gateways (DSL-Router etc.) zu ermitteln. Hier gibt es viele Möglichkeiten mit verschiedenen Vor- und Nachteilen. Ich entschied mich kurzerhand für ein winziges CGI-Skript, das später vom Hauptprogramm via HTTP request aufgerufen werden soll und die eigene remote address in einem kleinen XML output ausgibt.
#!/usr/bin/perl
my $remote_addr = $ENV{'REMOTE_ADDR'};
print "Content-type: text/htmlnn";
print "n";
print "$remote_addrn";
Nun fehlt nur noch das Hauptprogramm, das das CGI-Skript aufruft, die XML-Datei empfängt und auswertet und die IP-Adresse samt Datum in die Datenbank schreibt. Hier sind zu Beginn die URL des CGI-Skripts sowie die Zugangsdaten zur Datenbank einzutragen.
#!/usr/bin/perl
use strict;
use warnings;
use LWP::Simple;
use DBI;
my $get_remote_addr_cgi_url = 'http://example.com/cgi-bin/get_remote_addr.cgi';
my $db_name = 'remote_addr_logger';
my $db_host = 'localhost';
my $db_user = 'remote_addr';
my $db_pass = 'yoursecretpassword';
sub parse_xml_data {
my $xml_data = shift;
my $tag = 'remote_addr';
my $inet_addr = '(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)';
my $pattern = "($inet_addr)";
if ( $xml_data =~ /$pattern/ ) {
my $remote_addr = $1;
return $remote_addr;
} else {
return -1;
}
}
sub get_remote_addr {
my $xml_data = get($get_remote_addr_cgi_url);
if ( defined( $xml_data )) {
my $remote_addr = parse_xml_data( $xml_data );
return $remote_addr;
} else {
return -1;
}
}
my $remote_addr = get_remote_addr();
unless ( $remote_addr eq -1 ) {
my $dsn = "dbi:mysql:$db_name:$db_host";
my $dbh = DBI->connect($dsn, $db_user, $db_pass);
my ($id) = $dbh->selectrow_array("SELECT `id` FROM `remote_addr` WHERE `remote_addr` = INET_ATON( '$remote_addr' ) AND `id` IN ( SELECT MAX(`id`) FROM `remote_addr`);");
if ( defined($id) and $id gt 0 ) {
$dbh->do("UPDATE `remote_addr` SET `date_end` = NOW() WHERE `id`=$id;");
} else {
$dbh->do("INSERT INTO `remote_addr` ( `remote_addr`, `date_start`, `date_end` ) VALUES ( INET_ATON( '$remote_addr'), NOW(), NOW() );");
}
$dbh->disconnect;
}
Die Funktionsweise ist recht simpel. Die IP-Adresse wird mit der des letzten Eintrags in der Tabelle verglichen. Hat sie sich nicht geändert, wird das Enddatum mit der aktuellen Zeit aktualisiert. Ist es eine andere Adresse, wird ein neuer Eintrag eingefügt.
Jetzt muß das Skript nur noch regelmäßig aufgerufen werden. Sinnvollerweise erledigt das cron.
*/1 * * * * /usr/local/bin/remote_addr_logger
Die Einträge können wie folgt aus der Datenbank ausgelesen werden:
SELECT INET_NTOA(`remote_addr`), `date_start`, `date_end` FROM `remote_addr`;
Und jetzt bin ich mal gespannt…
107
The weird sense of duty really good sysadmins have can border on the sociopathic, but it’s nice to know that it stands between the forces of darkness and your cat blog’s servers. (xkcd)
105
Der von T-Home ausgelieferte Speedport W 920V kann nicht mit anderen DSL-Providern verwendet werden. Es ist jedoch möglich, die Firmware durch die einer FRITZ!Box Fon WLAN 7270 zu ersetzen. Das Gerät kann danach auch mit anderen Providern benutzt werden und bietet zusätzliche Features. Wie das funktioniert, erklärt diese Anleitung.