Kleine und große Linux AHAs
Beiträge getaggt mit daemon
Simpler Zugang zum Netz, oder nicht? CaptivePortal in einfach
23. Feb
Viele kennen es aus Hotels, Bahnhöfen, Cafes oder öffentlichen Plätzen. Es gibt ein offenes WLAN zum Internet und wenn man sich damit verbindet landet man zuerst einmal auf einer speziellen Seite. Auf dieser muss man sich dann irgendwie registrieren oder halt bezahlen. Aber wie funktioniert sowas und macht das vielleicht auch Sinn für ein Unternehmen intern?
Warum kann das unternehmensintern Sinn machen?
Also hier geht es nicht um Provider oder Firmen die das ganze öffentlich anbieten. Es gibt beispielsweise die Anforderung in Unternehmen die Produktionsstraßen besitzen, Großraumhallen, Fertigungshallen oder ähnliches. Oft gibt es dort viele Geräte verschiedener Hersteller die gewartet werden (nur ein Beispiel). Es kommen also externe Dienstleister um Updates einzuspielen oder Support zu leisten. Diese müssen mittlerweile, um vernünftig arbeiten zu können, Kontakt mit Ihrer Firma haben. Das kann über 3G geschehen, ist allerdings schneller über WLAN. Für solche Dienstleister macht ein WLAN Zugang also Sinn. Das auch für einen “normalen” Besprechungs- oder Schulungsraum schon Sinn machen.
Nun hat man ein Problem. Das WLAN offen zu lassen ist quasi grob fahrlässig. Das WLAN schützen macht es umständlich – je nach Anzahl der verschiedenen Benutzer. Dann haben wir da noch den Aspekt des Loggings. Prinzipiell muss man die Verbindungsdaten mitloggen, da man je nach dem in die Beweispflicht genommen werden kann. Um zu loggen muss ich auch wissen wer zu welchem Gerät gehört, da mir ansonsten die Information nichts bringt. Das alles kann ich mit der Anmeldung quasi erledigen. Ich weiß wer zu welchem Gerät gehört und kann auch mitloggen. Bevor der Nutzer sich über das WLAN mit dem Internet verbindet, muss er einer entsprechenden Nutzungserklärung zustimmen (wegen logging etc.).
Wie kann sich so was mit Linux darstellen?
Diese Portale sind gar nicht so kompliziert wie man denkt. Um so etwas unter Linux zu realisieren kann man sich fertiger Software bedienen oder auch einfach das ganze selbst – relativ schnell – programmieren. Ein Projekt mit einer “CaptivePortal” Funktion ist beispielsweise pfsense. Die meisten CaptivePortal Funktionen befinden sich im Bundle mit Firewalls und bieten weit mehr als eine einfach Authentifizierung für einen Netzzugang.
Um so etwas mit Linux Mitteln darstellen zu können habe ich folgende Komponenten genutzt:
- einen Apache Webserver
- MySQL Datenbank
- iptables
- DHCP Server (Standardkonfig mit Netz 192.168.199.0/24)
Das ganze funktioniert nach folgendem Ablauf:
- Gerät verbindet sich mit dem Netz (dabei ist unerheblich ob per WLAN oder per Kabel)
- das Gerät bekommt eine IP per DHCP
- per Default werden alle Verbindungen geblockt, Verbindungen zu Port 80 (egal wohin) werden auf den Webserver des Gateways umgeleitet, bis das Device registriert ist
Zur Registrierung benötigt man einen Schlüssel (5 Stellen, Alphanumerisch). Diesen kann man sich an eine interne Mailaddresse schicken lassen. Also können nur interne Accounts quasi den Zugriff genehmigen. Wenn man einen Schlüssel besitzt, dann kann man sich über das Portal registrieren (Name, Firma und Schlüssel werden abgefragt). Mit der Registrierung – richtiger Schlüssel vorausgesetzt – wird der Zugang für einen Tag freigegeben.
Genauer??
Der Client bekommt eine IP Adresse vom DHCP Server. Alle Zugriffe ins (bspw.) Internet werden erst einmal geblockt, außer Zugriffen auf Port 80 – diese werden umgeleitet auf den Webserver des Gatewyas – das CaptivePortal erscheint. Hat man noch keinen Schlüssel zum registrieren, so muss dieser angefordert werden. Man trägt eine eMail Adresse ein und sendet die Anfrage. Im Hintergrund wird per Perl Script geprüft ob die Empfängeradresse ok ist (bspw. interne Domain oder in einer Liste) und ein Schlüssel generiert. Dieser Schlüssel inkl. Mailadresse wird in der Datenbank hinterlegt und per Mail an den Empfänger geschickt.
Mit dem Schlüssel registriert sich der Client am Portal (inkl. Name, Firma). Mit dem Klicken des Buttons “registrieren” wird der Schlüssel geprüft und deaktiviert. MAC Adresse, Name und Firma des Anforderers werden in die Datenbank geschrieben. Danach wird ein iptables Befehl abgesetzt, der dem Client mit der betreffenden MAC Adresse den Zugriff zum Netz gewährt. Ebenfalls wird in der Datenbank ein Zeitstempel gespeichert, dadurch ist es möglich über ein iptables-update den Zugriff generell nur für eine gewisse Zeit freizugeben und dann automatisch wieder zu sperren. In der Datenbank gibt es ein Flag um zu definieren, ob dieser Eintrag überhaupt abläuft oder nicht (expires yes/no). Damit kann man also auch das ganze für interne Mitarbeiter statisch freigeben, damit diese sich nicht immer wieder neu registrieren müssen.
Die Komponenten
(Die Scripte liegen bei mir unter /opt/captivePortal – der Pfad ist in manchen Scripten zu finden)
iptables
iptables ist ja quasi auf jedem Linux System vorhanden und muss auch nicht groß konfiguriert werden.
Script 1 (Initiales iptables Script / iptables.sh):
#!/bin/bash # Initial Iptables Script to enable captivePortal # # Ronny Becker, 02.2012 IPTABLES=/sbin/iptables # the interface to authenticate PORTAL_INT=eth2 # the interface where traffic goes through OUTPUT_INT=eth0 # PortalIP (for captivePortal website) PORTAL_IP=192.168.199.201 # clear all rules iptables -F iptables -X iptables -t nat -F iptables -t nat -X iptables -t mangle -F iptables -t mangle -X iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT # Create captivePortal chain $IPTABLES -N captivePortal -t mangle # All traffic goes to this chain $IPTABLES -t mangle -A PREROUTING -j captivePortal ###### captivePortal CHAIN ########## # get allowed MACs out of the database (maybe persistent or in time) /opt/captivePortal/iptablesFromDB.pl # DNS is allowed for all $IPTABLES -t mangle -A captivePortal -i $PORTAL_INT -p udp --dport 53 -j RETURN # Mark packets that are not allowed till here $IPTABLES -t mangle -A captivePortal -i $PORTAL_INT -j MARK --set-mark 99 # redirect port 80 to captivePortal $IPTABLES -t nat -A PREROUTING -m mark --mark 99 -i $PORTAL_INT -p tcp --dport 80 -j DNAT --to-destination $PORTAL_IP # drop all marked with 99 $IPTABLES -t filter -A FORWARD -m mark --mark 99 -j DROP # masquerading (if needed) iptables -t nat -A POSTROUTING -o $OUTPUT_INT -s 192.168.199.0/24 -j MASQUERADE
Das iptables.sh Script muss bei jedem Systemstart ausgeführt werden. Des Weiteren muss ip_forward (/etc/sysctl.conf) gesetzt sein, damit der Server routen kann.
Script 2 (Perl Script zum Auslesen der aktuellen Berechtigungen aus der Datenbank / iptablesFromDB.pl):
#!/usr/bin/perl
# captivePortal
# Script to get registered MACs out of DB
use DBI;
# get Config from central conf file
BEGIN { require "/opt/captivePortal/captivePortal.conf" };
# database connection
$connectionInfo="DBI:mysql:database=$db;$host:$port";
$dbi = DBI->connect($connectionInfo,$userid,$passwd);
# select datasets
$sql="select mac from registered where expires='no' or ((UNIX_TIMESTAMP()-timestamp) < $tte)";
$sth = $dbi->prepare($sql);
$sth->execute() or die("Cannot get MACs");
$sth->bind_columns(undef, \$db_mac);
while ( $sth->fetch() ) {
# and run iptables
`/sbin/iptables -t mangle -A captivePortal -m mac --mac-source "$db_mac" -j RETURN`;
}
$sth->finish();
$dbi->disconnect();
Config (Konfig für die Perl Scripte (s. Script 2 / captivePortal.conf):
# captivePortal - central config # this conf file is used in perl scripts use vars qw( $tte $db $host $port $userid $passwd $iptables_if ); # Time To Expire for dynamic subscriptions $tte="86400"; # Database Information $db="captivePortal"; $host="localhost"; $port="3306"; $userid="portal"; $passwd="captive"; # portal interface $iptables_if="eth2";
Script 3 (Updatescript für iptables um abgelaufene Registrierungen zu löschen / iptables_update.sh):
#!/bin/bash # captivePortal # Update iptables rules to delete expired registrations IPTABLES=/sbin/iptables # the interface to authenticate PORTAL_INT=eth2 # clear the chain $IPTABLES -t mangle -F captivePortal # run the rules out of the db /opt/captivePortal/iptablesFromDB.pl # add default rules (see iptables.sh) $IPTABLES -t mangle -A captivePortal -i $PORTAL_INT -p udp --dport 53 -j RETURN $IPTABLES -t mangle -A captivePortal -i $PORTAL_INT -j MARK --set-mark 99
Das Update Script sollte per cron alle Xmin / Xstunden ausgeführt werden, damit abgelaufene Registrierungen den Zugriff verlieren. Wenn man den cronjob nicht gerade jede Minute laufen lässt, ist damit natürlich nicht gewährleistet dass eine Registrierung genau so lange gültig ist, wie es in der Konfiguration steht. In meinem Fall läuft das Script jede Stunde – das ist für meine Zwecke ausreichend.
MySQL
Die Datenbank besteht aus zwei Tabellen -> captivePortal.sql
Apache
Wir benötigen lediglich ein CGI Script. Auf dieses muss per Default umgeleitet werden sobald der Server eine Anfrage bekommt. Das kann man auf verschiedenste Weisen machen – also nicht schimpfen
Redirect
Damit das ganze mit iPhone und Android funktioniert, habe ich folgende Apache config am Start:
<VirtualHost 192.168.199.201:80>
ServerAdmin webmaster@localhost
Servername captivePortal
DocumentRoot /var/www
Redirect /index.html http://192.168.199.201/cgi-bin/captivePortal.pl
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
AllowOverride None
Options +ExecCGI Indexes -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^/$ http://192.168.199.201/cgi-bin/captivePortal.pl [L,R]
</IfModule>
ErrorLog ${APACHE_LOG_DIR}/error.log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Dem entsprechend liegt das CGI (captivePortal.pl) unter /usr/lib/cgi-bin.
Das CGI
#!/usr/bin/perl
# captivePortal
#
# This is the cgi for the simple captivePortal
#
# Do not forget to change
# line 51: valid domain to send regkey to
# line 58: sender adress
#
#
#
# Ronny Becker, 02.2012
use CGI qw(:all);
use DBI;
# get Config from central conf file
BEGIN { require "/opt/captivePortal/captivePortal.conf" };
# connect to DB
$connectionInfo="DBI:mysql:database=$db;$host:$port";
$dbi = DBI->connect($connectionInfo,$userid,$passwd);
# params
$thisscript=$ENV{'SCRIPT_NAME'};
# cgi params
$para_req_sendto=param('req_sendto');
$para_req_submit=param('req_submit');
$para_reg_company=param('reg_company');
$para_reg_name=param('reg_name');
$para_reg_key=param('reg_key');
$para_reg_submit=param('reg_submit');
# print some headers
print "Content-type: text/html\n\n";
print '
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>WLAN Gastzugang</title>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
</head>
<body style="font-family: courier,courier-new">
<h2>WLAN Gastzugang</h2><br>';
# request for key
if ( $para_req_submit ) {
# address valid?
if ( $para_req_sendto ) {
if ( $para_req_sendto =~ /.*\@mydomain\.de/i || $para_req_sendto =~ /.*\@mydomain2\.de/ ) {
# generate a key
my @chars=('a'..'z','0'..'9');
foreach (1..5) {
$secret.=$chars[rand @chars];
}
# send key to recipient
$result=`export EMAIL="gastzugang\@mydomain.de"; echo "Der Registrierungsschluessel fuer Ihren Gast lautet: $secret" | mail -s "WLAN Gastzugang" $para_req_sendto`;
print "$result";
# Insert Key into DB
$sql="insert into regkeys(regkey,sendto,datetime) values('$secret','$para_req_sendto',NOW())";
$sth = $dbi->prepare($sql);
$sth->execute() or die("Fehler beim schreiben in die Datenbank");
$sth->finish();
print "<div style='background-color: green; color: white'><p><b>Registrierungsschluessel wurde zugeschickt</b></p></div>";
}
}
}
# request for registration
if ( $para_reg_submit ) {
# name given?
if ( length($para_reg_name) <= 5 || length($para_reg_key) != 5 ) {
print "<div style='background-color: red; color: white'><p><b>Sie muessen einen Namen und den Registrierungsschluessel angeben.</b></p></div>";
} else {
# Check DB for regkey
$sql="select sendto from regkeys where regkey='$para_reg_key' and isActive='1'";
$sth = $dbi->prepare($sql);
$sth->execute() or die("DB: Cannot run select");
$sth->bind_columns(undef, \$db_sendto);
$sth->fetch();
$sth->finish();
if ( $db_sendto ) {
# disable key
$sql="update regkeys set isActive='0' where regkey='$para_reg_key'";
$sth = $dbi->prepare($sql);
$sth->execute() or die("DB: Cannot update");
$sth->finish();
# get MAC
open (ARP,"</proc/net/arp");
while (<ARP>) {
$line = $_;
$line =~ s/ */;/g;
($arp_ip,undef,undef,$arp_mac,undef,undef) = split(";",$line);
if ( $arp_ip eq $ENV{'REMOTE_ADDR'} ) {
$mac=$arp_mac;
}
}
close ARP;
# write data into db
$sql="insert into registered(name,guestof,mac,timestamp,expires) values('$para_reg_name, $para_reg_company','$db_sendto','$mac',UNIX_TIMESTAMP(),'yes')";
$sth = $dbi->prepare($sql);
$sth->execute() or die("DB: Cannot insert");
$sth->finish();
$output=`sudo /sbin/iptables -I captivePortal 1 -t mangle -m mac --mac-source $mac -j RETURN`;
print "<div style='background-color: green; color: white'><p><b>erfolgreich registriert</b><br>$output</p></div>";
} else {
print "<div style='background-color: red; color: white'><p><b>Registrierungsschluessel nicht gefunden</b></p></div>";
}
}
}
# disconnect from DB
$dbi->disconnect();
# print form etc.
print '
<form method=get action='.$thisscript.'>
<b>Registrierungsschluessel anfragen</b><br>
senden an: <input type=text name=req_sendto size=40> <input type=submit name=req_submit value=zusenden></form>
<hr><br>
<form method=get action='.$thisscript.'>
<b>Registrieren</b><br>
<b><u>Achtung! Registrieren Sie sich mit dem Geraet, mit dem Sie Zugriff benoetigen</b></u><br>
<table>
<tr><td>Name:</td><td><input type=text name=reg_name size=30></td></tr>
<tr><td>Firma:</td><td><input type=text name=reg_company size=30></td></tr>
<tr><td>Registrierungsschluessel:</td><td><input type=text name=reg_key size=10></td></tr>
<tr><td colspan=2 align=center><font color=red><b><u>Nutzungsbedingungen:</u><br>
Mit klicken auf den Button "registrieren" stimmen Sie zu,dass die ihre Verbindungsdaten (Zeitpunkt und Dauer einer Verbindung, Addressierungsdaten) mitprotokolliert werden.
Dies dient lediglich zur Fehleranalyse und zur Sicherheitsueberpruefung.
Es werden keine Daten an dritte weitergegeben oder weiterverarbeitet.<br><br><br>
Sie haben (per Default) ab dem Zeitpunkt der registrierung Zugriff fuer 24 Stunden.
<input type=submit name=reg_submit value=registrieren></td></tr>
</table>
</form>
</body>
</html>';
Das Webinterface ist recht einfach gehalten damit es auch mit mobilen Endgeräten keine Probleme gibt. Das ganze ist natürlich nach belieben anzupassen oder zu ändern
Ich hoffe ich hab nix vergessen – falls doch einfach fragen.
Unleserliches debuggen, oder: Fehlersuche in verschlüsselten Protokollen
03. Mai
Immer mehr Datenverkehr wird verschlüsselt. Einerseits natürlich richtig und gut. Andererseits ein Problem. Früher konnte man mit Hilfe von Tools wie Wireshark (Ethereal) oder tcpdump relativ schnell Probleme (z.B.) in der Kommunikation zwischen Programm und Server herausfinden. Einfach den Netzwerkverkehr mitschneiden, ansehen / auswerten und es zeigten sich Fehler die man im Programm möglicherweise nicht zu Gesicht bekommen hat.
Mittlerweile sind die Pakete weitestgehend verschlüsselt und man kann nicht mehr einfach so “mit schreiben” – naja, man kann natürlich; aber lesen kann man es nicht. Also fällt ein mitschreiben – einfach mal so – flach.
Eine andere Möglichkeit die Kommunikation zwischen Programmen zu debuggen ist, sich einfach manuell zu verbinden und die Kommandos direkt einzugeben um zu prüfen ob der Server richtig reagiert. Dazu nahm man früher telnet … Auch telnet ist kein Kandidat mehr für verschlüsselte Protokolle.
Verbindung zu einem SSL geschützten Dienst
Eine Möglichkeit sich auf einen solchen Dienst zu verbinden bietet der Befehl
openssl s_client -connect <Zielrechner>:<Port>
Mit diesem Befehl kann man sich beispielsweise direkt auf einen per SSL geschützten IMAP Server (Port 993) verbinden und manuell Kommandos absetzen. Das ganze über eine SSL geschützte Verbindung – die nicht mitgeschnitten werden kann
Ganz wie früher mit telnet *freu*
Openvpn: Tür auf, Tür zu, Tür auf, Tür zu …
20. Aug
Betreibt man einen Openvpn Server – beispielsweise zur Einwahl von Dienstleistern oder auch einfach nur für “normale” Benutzer – so sollte man das ganze mit einem Zertifikat abgesichert haben. Das ganze geht unter Debian/Ubuntu (und auch anderen) recht einfach mit easy-rsa. Jeder Client bekommt seinen eigenen Key und kann damit den Tunnel aufbauen.
Tür zu?
Was nun, wenn man einen Client aussperren möchte? Der Dienstleister ist ab sofort “böse”. Die Zusammenarbeit beendet. Er hat noch seinen Key und kann sich damit per Openvpn verbinden und ins interne Netz (soweit die Firewall den Zugriff zulässt). Eigentlich ganz einfach. Der Key des Benutzers wird “revoked” – das geht auch per easy-rsa recht einfach. Ist der Key revoked, so ist der Key für Openvpn ungültig und die Verbindung kann nicht mehr aufgebaut werden. Fertig.
Tür wieder auf?
Ganz anders sieht das aus, wenn man einen Benutzer hat der sich einwählen können soll, jedoch nur dann wenn man es möchte. Man vereinbart quasi einen Termin an dem irgendetwas gemacht werden soll und zu diesem Termin hat der Client Zugriff. Ist der Key eines Benutzers einmal “revoked”, dann ist das erstmal so. Einen Key wieder freizuschalten ist nicht so einfach zu machen.
Tür zu, Tür auf: Openvpn Switching
Ganz einfach ist das ganze zu machen, indem man den Parameter ccd-exclusive dazu benutzt. Dieser Parameter lässt nur Clients zu, die eine Konfigurationsdatei im sogenannten client-config-dir (Parameter in der openvpn Konfig) besitzen. Man kann diese Dateien nutzen, um Clientkonfigurationen zu setzen. Dazu wird in dem Verzeichnis eine Datei mit dem CN (der eindeutige Name/Zeritifikat) des Benutzers angelegt.
Der Parameter ccd-exclusive bewirkt nun, dass nur Clients sich verbinden dürfen, für die eine Datei im ccd vorhanden ist – mit dem genauen Namen (CN). Ob diese Datei nun gefüllt ist mir einer Clientspezifischen Konfiguration oder leer ist, das macht dabei keinen Unterschied. Um einen Client zu sperren muss man also lediglich die Datei im ccd beispielsweise in “disabled-<CN>” umbenennen. Das ganze funktioniert ohne Neustart des Daemons
Home NAS mit iSCSI – Format, Crypt und gut (Teil 3/3)
12. Apr
Teil I (hier) zeigte die Einrichtung des Servers inkl. iSCSI-Target.
Teil II (hier) zeigte die Einrichtung des Initiators – des Clients.
Teil III zeigt nun die restlichen Arbeiten – verschlüsseln der Platte, formatieren und den “luxuriösen” Zugriff darauf.
Verschlüsseln
Alleine um sich davor zu schützen, irgendwelche Daten aus versehen – z.B. wenn man eine alte Festplatte verkauft – an “unbefugte” weiter zu geben, sollte man seine Daten verschlüsseln. Daher habe ich die Daten auf meinem Laptop verschlüsselt und mache gleiches natürlich auch mit meinem Backup.
Unter Linux gibt es mehrere Möglichkeiten Festplatten, Partitionen oder auch nur Dateien zu verschlüsseln. Ich halte LUKS / Cryptsetup (Homepage) für eine der einfachsten Möglichkeiten.
Unter Ubuntu ist cryptsetup nicht in der Standardinstallation enthalten. Von daher muss das Paket installiert werden ->
apt-get install cryptsetup
Aus dem vorhergehenden Artikel sollten wir eine weitere Festplatte im System sehen. Beispielsweise /dev/sdb. Auf dieser Platte legen wir nun eine Partition an (/dev/sdb1) und verschlüsseln diese:
cryptsetup luksFormat /dev/sdb1
Nach Aufruf dieses Befehls wird nach einer Passphrase gefragt. Diese sollte – wie jedes Passwort – möglichst sicher gewählt werden. Mit Hilfe von LUKS / Cryptsetup werden die Daten während des Schreibens auf die Festplatte verschlüsselt, bzw. während des Lesens entschlüsselt. Dadurch dauert die Initiale Verschlüsselung nicht lange. Wirklich verschlüsselte Daten gelangen erst mit der Formatierung auf den Datenträger.
Formatieren
Die Passphrase für die Platte ist eingegeben. Nun muss die Platte ein Dateisystem bekommen damit wir damit arbeiten können. Dazu muss die Platte zuerst einmal per Luks “geöffnet” werden (wir haben bisher nur den Schlüssel angelegt).
cryptsetup luksOpen /dev/sdb1 SecureISCSI
Dieser Befehl fragt nun nach der Passphrase und legt – bei korrekter Eingabe – ein Device unter /dev/mapper mit Namen “SecureISCSI” an. Dieses ist dann das wirkliche Device, mit dem wir ganz normal arbeiten können.
mkfs.ext3 -L SecureISCSI /dev/mapper/SecureISCSI
Damit ist die Platte formatiert und kann gemountet / beschrieben werden.
Um das ganze zu vervollständigen: nach dem umounten kann das “entsicherte” Device (/dev/mapper/SecureISCSI) mit dem Befehl
cryptsetup luksClose /dev/mapper/SecureISCSI
wieder “verriegelt” werden.
Luxuriöser Zugriff
Was ich mittlerweile wirklich geil finde und vorher so gar nicht gewusst habe ist, wie man diese Festplatte nun unter Ubuntu nutzen kann.
Wenn ich meinen Laptop starte und mein Server ist verfügbar, werden mir die iSCSI Platten in Nautilus (Dateimanager) angezeigt (ich habe mehrere erzeugt). Die verschlüsselten Platten werden dabei als “290 GB verschlüsselt” angezeigt, die anderen mit ihrem Label (s. mkfs.ext3 -L …). Klickt man nun auf die “290 GB verschlüsselt”, so öffnet sich ein Dialog der mich nach der Passphrase fragt. Ich gebe die Passphrase ein und bekomme die Platte gemountet – mit ihrem Label, welches das System nun nach der Entschlüsselung erkannt hat. Ich kann direkt darauf zugreifen und beispielsweise per rsync meine Daten vom Laptop sichern.
fstab
Damit das ganze so einfach funktioniert, ist eine kleine Erweiterung der /etc/fstab notwendig. Macht man das ganze ohne diese Erweiterung, so wird man nach der Passphrase gefragt, zum mounten wird der Admin Zugriff abgefragt und als normaler User hat man dann keinen Zugriff sondern nur als root.
Um das zu umgehen trägt man in der fstab folgendes ein:
LABEL=SecureISCSI /media/SecureISCSI ext3 defaults,user,noauto 0 1
Damit ist der mountpoint bekannt und das wichtigste – es sind Optionen gesetzt. Die interessanteste dabei ist “user”, was so viel bedeutet wie “jeder Benutzer darf dieses Device auf diesem Mountpoint mounten und es auch wieder umounten”.
Wichtig ist hier auch, dass man dem Filesystem ein Label vergibt. Die iSCSI Platten müssen nicht immer den gleichen Gerätenamen (z.B. /dev/sdb) bekommen. Je nach dem ob beispielsweise ein USB Stick eingesteckt ist, kann es auch mal /dev/sd{c,d,e,f…} sein. Hat man jedoch ein Label vergeben, so spielt das eigentliche Device keine Rolle mehr. Alternativ könnte man auch mit der UUID arbeiten.
Ich hoffe dieser Artikel war recht interessant – über Feedback würde ich mich durchaus freuen
.
xdrp: auch ne Möglichkeit für Remote Zugriff
26. Feb
Es gibt unter Linux viele Möglichkeiten sich remote an einem System anzumelden – auch viele das grafisch zu tun. Da gibt es zum Beispiel XDMCP, X11 über einen ssh Tunnel, VNC, freenx oder das kommerzielle Pendant, … All diese Möglichkeiten waren mir bisher bekannt und ich habe sie auch schon mal ausprobiert. Aus irgendeinem Zufall bin ich nun auf was – für mich – neues gestossen: xrdp.
xrdp kann quasi VNC in das RDP Protokoll umschreiben und dadurch VNC über RDP zur Verfügung stellen. Das ganze ist recht interessant, da der RDP Client bekannterweise in einem von mir nicht zu nennenden “Betriebssystem” zur Standardausrüstung gehört und somit von diesen Clients aus keine extra Software / Installation benötigt wird.
Installation
Die Installation unter Ubuntu ist denkbar simpel -> apt-get install xrdp.
Konfiguration
xrdp läuft nach der Installation automatisch. Allerdings muss man um Zugriff auf den Rechner zu gewähren über die Gnome Desktop Einstellungen den VNC Server starten. Das ganze findet sich unter Menü-System-Einstellungen-Entfernter Bildschirm. Dort muss man “Anderen Benutzern erlauben, Ihren Bildschirm anzuzeigen” und “Anderen Benutzern erlauben, Ihren Bildschirm zu steuern” aktivieren. Des Weiteren sollte man ein Passwort setzen. Dieses hat jedoch nichts mit dem Anmeldepasswort des Accounts zu tun.
Anmeldung per RDP
Nun wird der RDP Client mit dem Rechner verbunden. Es erscheint ein Menü, in diesem man den Typ “Console” für die Sitzung wählt und kann dann mit dem vergebenen Passwort auf seine Sitzung zugreifen.
Naja
Also so wie ich es beschrieben habe gefällt es mir an sich selbst nicht. Ein großer Nachteil der Lösung ist, dass der Vino-Server (VNC Server unter Gnome) bei einem gesperrten Bildschirm versagt -> einen schwarzen Bildschirm zeigt. Des Weiteren ist in diesem Szenario der RDP Port als auch der VNC Port auf der Maschine offen. Gepaart mit dem “schwachen” Passwort welches wie oben konfiguriert haben, ist das nicht wirklich Sicher.
Man kann den Vino-Server auch deinstallieren und dafür x11vnc nehmen. Damit funktioniert das ganze auch bei gesperrtem Bildschirm. Leider ist damit die Performance um einiges schlechter. Ich habe keine Einstellung gefunden mit der x11vnc über xrdp so flüssig läuft wie mit dem Vino-Server. Da beißt sich die Katze in den Schwanz.
sftp Server Teil II – “Jail made easy”
08. Feb
Im ersten Teil haben wir das aktuelle openssh Paket für RHEL gebaut und sollten das auch mittlerweile installiert haben. Die Konfiguration des SSH-Servers hat sich nur wenig geändert. Es gibt eigentlich auch nur wenig neue Stellen die hier für uns interessant sind. Aber wir beginnen am Anfang:
Gruppe für sftp
Die Steuerung ob ein Benutzer in einer “gechrooteten” Umgebung landet wird über eine Gruppe gesteuert. Diese könnte man beispielsweise “sftpchroot” nennen. Diese Gruppe wird also angelegt:
groupadd sftpchroot
Benutzer anlegen
Als nächstes muss der Benutzeraccount angelegt werden, der sich auch in der Gruppe sftpchroot befindet:
useradd testuser -G sftpchroot
(Passwort setzen oder disablen, je nach dem ob sich per Key oder Passwort eingeloggt werden soll. Eine Shell benötigt der User auch nicht unbedingt.)
Benutzerhome anpassen
Das Benutzerhome (/home/testuser) muss von den Rechten her angepasst werden, damit das “chrooten” funktioniert. Gleichzeitig legen wir ein Verzeichnis (exchange) an, in welches der Benutzer über sftp schreiben darf.
chown root:sftpchroot /home/testuser mkdir /home/testuser/exchange chown testuser:testuser /home/testuser/exchange
Möchte man die Authentifizierung per Key machen, so muss folgendes ebenfalls eingerichtet werden:
mkdir /home/testuser/.ssh chown testuser:testuser /home/testuser/.ssh
Der Key kommt dann in die authorized_keys; die Rechte werden auf 0600 gesetzt und fertig.
Logging
Wir möchten genau sehen, welche Befehle auf dem SFTP Server abgesetzt werden. Daher muss auch das Logging aufgesetzt werden. Dazu ist es nötig, dass in jedem Home ein dev Verzeichnis angelegt wird (-> mkdir /home/testuser/dev). Dort wird dann vom dem Syslog Server des Vertrauens eine Pipe angelegt und damit ist das Logging im System.
Wir verwenden den syslog-ng (syslog-ng). Die Konfiguration dafür sieht wie folgt aus:
source s_sftpchroot {
# Please add each chrooted environment here
# These logs stay on the local machine; not sended to the syslog-server
unix-stream ("/home/testuser/dev/log");
};
destination d_sftplog { file("/var/log/sftp_chrooted.log"); };
log { source(s_sftpchroot); destination(d_sftplog); };
Jede Chroot Umgebung muss hier im Abschnitt “source” eingetragen werden. Damit fließen alle sftp logs in eine Datei. Alternativ kann natürlich auch für jeden Benutzer ein eigenes Log geschrieben werden. Welche Konfigteile dazu angepasst werden müssen sollte ersichtlich sein
Openssh Chroot
Nun zu dem früher schwierigsten, heute jedoch einfachsten Teil. Das Openssh Chroot. Ich zeige einfach die Konfiguration – it`s that easy !
Subsystem sftp internal-sftp Match group sftpchroot X11Forwarding no AllowTcpForwarding no ForceCommand internal-sftp -l VERBOSE ChrootDirectory /home/%u
Mit dieser Konfiguation am Ende der sshd_config (/etc/ssh) bekommt jeder Benutzer, der sich in der Gruppe sftpchroot befindet, besondere Optionen. Unter anderem wird lediglich der interne sftp-server (internal-sftp) zugelassen, der mit dem Parameter “-l VERBOSE” sämtliche Befehle des Benutzers loggt. Fertig.
perl daemon mit input aus einer named pipe
07. Mai
Auch sowas wo ich lange nach gesucht habe. Möchte man, dass ein Perl Programm den Input einer named pipe verarbeitet, so wird man als erstes auf ein Problem stossen. Das Programm wird sich nach jeder Eingabe beenden. Mein erster Code sah zum Beispiel so aus:
#!/usr/bin/perl -w
open(THISPIPE, ") {
echo $_;
}
close THISPIPE;
So würde wohl jeder erste Versuch aussehen. Das Problem liegt darin, dass sobald Daten über die Pipe ausgetauscht werden, auch ein EOF mitgegeben wird. Dieses EOF wird von Perl als solches auch interpretiert und die Datei wird geschlossen.
Umgehen kann man das, indem man einen Trick anwendet und die Datei nicht nur zum lesen öffnet, sondern zum Lesen und Schreiben. Dadurch wird die Datei nicht nach einem EOF geschlossen und der Daemon lauscht weiterhin auf der Pipe. Das sieht dann so aus:
#!/usr/bin/perl -w
open(THISPIPE, "+) {
echo $_;
}
close THISPIPE;




