sudo-matisch

Mit sudo kann man mit den Rechten eines anderen Users Befehle ausführen. Üblicherweise ist das root und wird gebraucht, um ohne root zu sein, root-Rechte zu bekommen. Andere User gehen aber so auch: sudo -u username <command>

Welche Benutzer mit sudo andere Rechte erlangen dürfen, steht in der Datei /etc/sudoers, die man nur mit dem Befehl visudo bearbeiten sollte. Je nach OS und Distribution findet man hier andere Voreinstellungen. Auf meinem Mac habe ich mir etwa einen unpriviligierten User angelegt (ist sicherer), aber mir in der sudoers-Datei trotzdem alle Rechte zugestanden (ist komfortabler).

# User privilege specification
eliyah ALL=(ALL:ALL) ALL

Aber sudo lässt sich auch für andere Dinge nutzen, etwa Scripte. Man will nicht immer ein Script, das für nur einen Befehl root-Rechte benötigt, komplett als root laufen lassen. Etwa, weil es von einem anderen Prozess, der selbst keine root Rechte besitzt, getriggert wird. Ein Beispiel sind cgi’s für den Webserver. Ein anderes sind per ssh remote ausgeführte Kommandos.

Ausserdem will man in scripten oder remote kein Passwort eintippen müssen, wenn man per sudo Befehle ausführt, will aber in seinem System nicht gleich für alle Tür und Tor öffnen.

Der Trick ist, Befehle zu definieren, die ein User ohne Passwort ausführen darf. Das geht über die Cmnd_Alias Funktion. Hier im Beispiel eine Befehlsdefinition, der es einem User erlaubt, Passworte für andere User zu setzen und einer, der erlaubt, per tcpdump Traffic mitzulesen:

# Cmnd alias specification
Cmnd_Alias PASSWD = /usr/bin/passwd [A-z]*, !/usr/bin/passwd root
Cmnd_Alias TCPDUMP = /usr/sbin/tcpdump

Was man hier schön sehen kann ist, dass man nicht nur Programme, sondern auch Parameter bestimmen kann, die erlaubt sind. Mit dem Ausrufezeichen (!) kann man auch Dinge wieder ausschliessen, hier eben das Ändern des Passwortes für den User root.

Wenn der Befehlalias definiert ist, kann man bestimmten Usern diese Befehle erlauben, sogar ohne Eingabe des Passwortes.

# User privilege specification
eliyah ALL=(ALL:ALL) PASSWD
eliyah ALL=(ALL) NOPASSWD: TCPDUMP

Die verschiedenen ALLs erlauben, von wo aus man das darf. Wie im Detail, weiss ich nicht, interessiert mich auch nicht. Denn ich kann jetzt ein Script schreiben, das als User eliyah läuft und mit Hilfe von sudo ohne Passwortabfrage einen tcpdump machen kann.

Advertisements
sudo-matisch

OS X: Wer lauscht denn da?

Unter GNU Linux gibt es den Befehl netstat, mit dem man sich nicht nur anzeigen lassen kann, welche Ports gerade aktiv sind. Mit dem Parameter -pl (p für Prozess-ID und l für listen) sieht man auch, welcher Prozess gerade eine Tür geöffnet hat. Unter OS X ist das nicht ganz so einfach. Dort gibt es die BSD Variante von netstat, und die funktioniert anders. Mit folgendem Befehl sieht man, welche Ports geöffnet sind:

netstat -a | fgrep LISTEN

Bei mir erscheint da unter anderem etwa folgender Eintrag:

tcp4 0 0 192.168.2.2.54045 *.* LISTEN

Wer macht denn da Port 54045 auf und habe ich das erlaubt? Ich muss feststellen. Ja habe ich:

% lsof -nP -iTCP:54045 -sTCP:LISTEN
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Skype 36967 eliyah 30u IPv4 0xf42576a198a9cfbb 0t0 TCP 192.168.2.2:54045 (LISTEN)

Denn ich habe Skype installiert, und das macht bekanntlich, was es will. Der Befehl lsof (List Open Files) bringt es zum Vorschein.

Ich habe bei meinem Mac auch ssh aktiviert, und wenn ich schaue, welcher Prozess diesen Dienst bereit stellt, kommt überraschendes zu Tage:

% sudo lsof -nP -iTCP:22 -sTCP:LISTEN
Password:
COMMAND PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
launchd   1 root   50u  IPv6 0xf42576a168a5fb6b      0t0  TCP *:22 (LISTEN)
launchd   1 root   51u  IPv4 0xf42576a168a676eb      0t0  TCP *:22 (LISTEN)
launchd   1 root   53u  IPv6 0xf42576a168a5fb6b      0t0  TCP *:22 (LISTEN)
launchd   1 root   54u  IPv4 0xf42576a168a676eb      0t0  TCP *:22 (LISTEN)

Das sudo ist nötig, da hier ein Port unter 1023 abgefragt wird. Der ssh-Dienst wird vom launchd selbst bereitgestellt. Das funktioniert ähnlich wie inetd oder xinetd unter Linux, nur dass launchd deutlich weitreichendere Aufgaben hat, was man schon an seiner Prozess-ID 1 erkennt.

OS X: Wer lauscht denn da?

ssh-Schlüssel generieren

Der Zugriff per ssh auf einen Server ist per Schlüssel nicht nur komfortabler, sondern auch sicherer. Das Generieren des Schlüssels ist auch sehr leicht.

Die Schlüssel landen auf Client und Server jeweils im Verzeichnis .ssh im Heimverzeichnis. Bevor man einen neuen Schlüssel generiert, sollte man nachsehen, ob es schon einen gibt, den man dadurch eventuell überschreibt.

ls -al .ssh

Wenn keine Schlüssel da sind oder das Verzeichnis gar nicht existiert, dann kann man bedenkenlos ein Schlüsselpaar erzeugen. Alte dsa-Schlüssel funktionieren zwar, aber ein sicherer rsa-Schlüssel darf es schon sein:

ssh-keygen -t rsa

Man wird nach einer Passphrase gefragt, mit der man den Schlüssel sichern kann (optional). Wer sich ganz sicher ist, dass niemand den privaten Schlüssel jemals klauen wird, der kann darauf verzichten. Dann kann man sich in Zukunft ohne Passwort einloggen oder ihn für Scripte verwenden, die ohne Benutzerinteraktion auf einem remote-Gerät Befehle ausführen sollen.

Im Verzeichnis .ssh liegen jetzt die Dateien id_rsa und id_rsa.pub. Ersterer ist der private und der zweite der öffentliche Schlüssel. Der Private muss auf dem Client in .ssh abgelegt werden. Wenn man auf dem Client das Schlüsselpaar angelegt hat, dann liegt der private Schlüssel schon an der richtigen Stelle, nämlich: .ssh/id_rsa. Der öffentliche (wesentlich kürzere) wird an die Datei .ssh/authorized_keys angehängt. Diese Datei kann viele Schlüssel gleichzeitig beinhalten. So kann man für ein und den selben Account verschiedene Schlüssel verteilen und natürlich auch wieder löschen.

Der öffentliche Schlüssel ist nicht geheim. Man kann ihn also bedenkenlos per Email an einen Serverbetreiber schicken, damit er ihn auf dem Server hinterlegt. So zeigt man ihn an, damit man ihn per Copy-Paste in eine Email packen kann.

cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCTlNVxtfBK+/l/oJz3LInlxjkpAk7z3LtWJ2wq0akT6V/ckpkVFhT2aLNZfCeSp0j4SOmUN+2v+olilUmiS/6X0vVIIJJxd3ghjA0AO65VY1v/6/bcdrfyLL76wjjGnIefBYWMwGJUDdsIPhlYT8t1MaTXh+HXBkqBSBoxgIi+VUjnTP9LBoFPPatEcS6nmOqMaSelPbwksR5yFCNRTBTBQ/bEsy/Z07GSaWW0w9Uolh9cRilzWEHrgD2KvOIatS+/DTjdPxZXgCKzee3ws1OnfJ6LG72uDKkDzR5hwZjy/TQhHpdR8fMC3SJbCwOQv0qnghv1T/7hqdfzE4mWcoyF eliyah@client

Fertig! Das war es schon.

ssh-Schlüssel generieren

Nach Hause telefonieren!

Ich habe ein Gerät mit Debian aufgesetzt, von dem ich noch nicht weiss, wo es mal landen wird. Also wollte ich, dass es nach Hause telefoniert, sobald es online geht und mir eine Shell gibt.

Das Konzept:

  • Ethernet-Interface(s) auf DHCP
  • ssh Tunnel zu meinem Rechner zuhause mit remote Port forwarding und automatischem ssh-Login über key-authentication
  • Telnet server (doppelt ssh ginge auch, aber warum?)
  • Script, das alle 5 Minuten versucht, nach Hause (feste IP oder dyndns-Hostname) zu telefonieren und es bleiben lässt, wenn der Tunnel steht
  • telnet auf localhost und den getunnelten Port öffnet eine shell auf dem entfernten Gerät

So geht’s:

  • remote tunneling in der sshd_config erlauben (danach sshd neu starten):
# Allow remote port forwarding
GatewayPorts yes
  • Schlüsselpaar auf dem remote host anlegen und verteilen
ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/lalala/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/lalala/.ssh/id_rsa.
Your public key has been saved in /home/lalala/.ssh/id_rsa.pub.
The key fingerprint is:
4a:ad:04:26:3c:ae:df:0d:e7:3b:3c:77:54:45:b3:97
The key's randomart image is:
+--[ RSA 2048]----+
|          .oo.   |
|         .  o.E  |
|        + .  o   |
|     . = = .     |
|      = S = .    |
|     o + = +     |
|    . . o + o .  |
|           . o   |
|                 |
+-----------------+
scp ~/.ssh/id_rsa.pub lalala@callhomeip:.ssh/lalala.pub
    - und dort -
cat .ssh/lalala.pub >> .ssh/authorized_keys
  • telnet server installieren (apt)
  • service telnet2323 TCP auf Port 2323 in /etc/services anlegen
  • inetd oder xinetd anpassen:
telnet2323             stream  tcp     nowait  telnetd /usr/sbin/tcpd  /usr/sbin/in.telnetd
  • script auf dem remote host schreiben
#!/bin/bash
# callhome script

RUNS=$(netstat -p | fgrep 2323 | wc -l)

if [ $RUNS -ge 1 ]; then
   exit 0
fi

ssh -f -nNT -R 2323:localhost:2323 lalala@callhomeip

  • cronjob schreiben, der das script alle 5 Minuten aufruft
  • telnet auf localhost port 2323
  • Ethernet Interface in /etc/network/interfaces (oder wo auch immer das auf Deiner Distri ist) auf hotplug und DHCP stellen

Das gute ist: Das funktioniert auch hinter NAT und man muss wirklich nicht wissen, wo das Gerät aufgebaut wird. Das Script kann man sicher auch schöner bauen, aber es muss ja nur ein Mal funktionieren. Danach kann man eine „normale“ IP-Config und einen ssh-Zugang auf das Gerät konfigurieren.

Nach Hause telefonieren!