
Ich habe einen SSH-Tunnel, der auf einem lokalen Port, sagen wir 8888, lauscht und von einem Remote-Computer mit geöffnet wurde ssh -R 8888:localhost:80 myuser@myhost
. Ich muss ein Skript für „myuser“ auf „myhost“ schreiben, das diesen Tunnel schließt.
Das Skript wird von „myuser“ auf „myhost“ ausgeführt. Es wird nicht vom Root ausgeführt und kann auch kein sudo ausführen.
Ein Ansatz wäre, die PID des Prozesses, der auf 8888 lauscht, mit lsof oder netstat zu finden und den Prozess dann zu beenden. Allerdings weigern sich sowohl lsof als auch netstat, mir die PID zu geben, ohne sudo auszuführen. Mit netstat bekomme ich stattdessen nur -
„PID/Programmname“ ohne sudo.
Gibt es eine Möglichkeit, die PID des Prozesses herauszufinden, der auf einem bestimmten Port lauscht, ohne Root-Rechte zu haben? Der Prozess, der auf diesem Port lauscht, läuft unter demselben Benutzer wie wir. Oder gibt es eine andere Möglichkeit, den SSH-Tunnel von außen zu schließen?
Beachten Sie, dass die Verwendung der SSH-Escape-Sequenz zum Zurücksetzen der Verbindung keine Lösung ist, da wirnichtim Tunnel. Unser Skript muss unabhängig vom Tunnel auf demselben Host vom selben Benutzer ausgeführt werden.
Beachten Sie auch, dass das bloße Ausführen killall sshd
keine Lösung ist, da dadurch nicht nur diese, sondern auch alle anderen SSH-Verbindungen beendet werden.
Diese Frage ist kein Duplikat vieler ähnlicher Fragen, da alle akzeptierten Antworten, die ich gefunden habe, Root-Rechte erfordern oder einfach alle SSH-Verbindungen trennen.
Auf dem Host „myhost“ läuft Ubuntu 12.04.5.
Bearbeiten: Diskussionszusammenfassung wie von @Jakuje angefordert:
@Patrick hat einen Ansatz vorgeschlagen, der verwendet
setuid
oder geändert werden kann/etc/sudoers
, um dem Benutzer zu ermöglichen, das Skript mit Root-Rechten auszuführen, ohne über vollständiges Sudo zu verfügen. Allerdingssetuid
müssten wir für dieses eine Binärdatei anstelle des Skripts schreiben. Dem Benutzer jedoch zu erlauben, das Skript mit Root-Rechten auszuführen, könnte ein potenzielles Sicherheitsrisiko darstellen. Und dennoch deckt diese Lösung nicht den Fall ab, dass der Benutzer überhaupt keinen Root-Zugriff hat und daher nicht ändern kann/etc/sudoers
. Wenn @Patrick dies als Antwort schreibt, werde ich es definitiv hochstimmen, aber ich werde es noch nicht als akzeptiert markieren.@EricRenouf hat herausgefunden, dass sshd den Socket dem Benutzer zuweist, sodass der Benutzer ihn nicht verwenden kann,
/proc/*/fd
um den Prozess zu finden, der den Socket hat. Das ist wahrscheinlich der Grund, warum weder lsof noch netstat ihn anzeigen.
Weitere Ideen:
Wie @EricRenouf festgestellt hat, gibt es wahrscheinlich keine Möglichkeit, die SSHD-PID über die geöffnete Socket-Portnummer oder den Inode abzurufen. Aber ich bin neugierig, ob es keinen anderen Trick gibt, wie man diese SSHD-PID findet oder wie man ihr sagt, dass sie die Verbindung schließen soll. Vielleicht irgendwie direkt mit SSHD.
Wenn ich beispielsweise den SSHD-Debugmodus aktiviert habe, sshd -d
wird protokolliert, welcher SSHD-Prozess einen Tunnel zu welchem Port geöffnet hat, /var/log/auth.log
der für den Benutzer lesbar ist. Das Skript könnte also das Protokoll analysieren und dort die PID finden. Aber einen SSHD-Debugmodus auszuführen ist keine gute Idee. Es gibt tatsächlich eineeinfacher Patch für SSHDum geöffnete Tunnel auch ohne Debug-Modus zu protokollieren. Aber ich bin mir nicht sicher, ob es eine gute Idee wäre, ein gepatchtes SSHD auszuführen.
Gibt es noch einen anderen Trick?
Antwort1
Beginnen Sie mit der Einrichtung eines benutzerdefinierten SSH-Schlüssels für die Verbindung mit „myhost“. Bearbeiten Sie dann Ihre Datei .ssh/authorized_keys auf „myhost“, sodass die übergeordnete PID der Shell in eine Datei geschrieben wird:
command="echo $PPID > tunnel.pid; bash" ssh-rsa AAA...
Möglicherweise möchten Sie aus Sicherheitsgründen noch einige andere Einstellungen anpassen und/oder ein benutzerdefiniertes Skript schreiben, das nur die PID schreibt und dann hängen bleibt. Das Prinzip ist in beiden Fällen dasselbe.
Sobald Sie die PID des Prozesses haben, der die SSH-Sitzung offen hält, ist es nur noch eine Frage des Skriptings ...
kill `cat tunnel.pid`
...um den Vorgang zu beenden und damit die SSH-Sitzung zu schließen.
Beachten Sie, dass Sie mit dem -i
Flag des ssh
Befehls einen privaten Schlüssel angeben können, der für die Verbindung verwendet werden soll.
Bearbeiten: Das Beenden des Shell-Prozesses schließt den Tunnel nicht, wenn aktive Verbindungen bestehen, also beenden wir den übergeordneten SSH-Prozess.
Bearbeiten: Obwohl ich bei jeder automatisierten SSH-Verbindung zunächst dazu neige, SSH-Schlüssel zu verwenden, könnte derselbe Vorgang folgendermaßen emuliert werden:
ssh -R 8888:localhost:80 myuser@myhost 'echo $PPID > tunnel.pid; for ((;;)); do sleep 1; done'
Sie können auch ein Skript einsetzen, das nach anderen Kriterien prüft, um zu entscheiden, wann es sich selbst beendet. Das ist wahrscheinlich eine sauberere Art, das Problem zu handhaben.