Warum brauche ich ein tty, um sudo auszuführen, wenn ich sudo ohne Passwort ausführen kann?

226

Ich habe sudodie Ausführung ohne Passwort konfiguriert , aber wenn ich es versuche ssh 'sudo Foo', erhalte ich immer noch die Fehlermeldung sudo: sorry, you must have a tty to run sudo.

Warum passiert das und wie kann ich das umgehen?

merlin2011
quelle

Antworten:

290

Das liegt wahrscheinlich daran, dass Ihre /etc/sudoersDatei (oder eine beliebige darin enthaltene Datei) Folgendes enthält:

Defaults requiretty

... was sudoein TTY erforderlich macht . Es ist bekannt, dass Red Hat-Systeme (RHEL, Fedora ...) ein TTY in der Standarddatei erfordern sudoers. Das bietet keinen wirklichen Sicherheitsvorteil und kann sicher entfernt werden.

Red Hat hat das Problem erkannt und es wird in zukünftigen Versionen entfernt.

Wenn das Ändern der Serverkonfiguration keine Option ist, können Sie zur Umgehung dieser Fehlkonfiguration die Optionen -toder verwenden -tt, mit sshdenen ein Pseudoterminal auf der Remote-Seite erstellt wird. Achten Sie jedoch darauf, dass es mehrere Seiten hat Auswirkungen.

-ttist für den interaktiven Gebrauch gedacht. Dadurch wird das lokale Terminal in den rawModus versetzt, sodass Sie mit dem Remote-Terminal interagieren können. Das bedeutet, dass, wenn sshE / A nicht von / zu einem Terminal ausgeführt wird, dies Nebenwirkungen hat. Beispielsweise können alle so wird der Eingang zurück, Sonderklemme Zeichen Echo werden ( ^?, ^C, ^U) bewirkt , dass eine spezielle Verarbeitung; Bei der Ausgabe wird LFs in CRLFs konvertiert. ( Weitere Informationen finden Sie in der Antwort unter Warum wird diese Binärdatei geändert ? .)

Um die Auswirkungen zu minimieren, können Sie sie folgendermaßen aufrufen:

ssh -tt host 'stty raw -echo; sudo ...' < <(cat)

Dadurch < <(cat)wird die Einstellung des lokalen Terminals (falls vorhanden) im rawModus vermieden. Und wir verwenden stty raw -echo, um die Leitungsdisziplin des Remote-Terminals als Durchgang festzulegen (effektiv verhält es sich so wie die Pipe, die anstelle eines Pseudo-Terminals ohne verwendet wird -tt, obwohl dies nur gilt, nachdem dieser Befehl ausgeführt wurde um das Senden von Eingaben zu verzögern).

Da die Ausgabe des Remote-Befehls an ein Terminal geht, wirkt sich dies nach wie vor auf die Pufferung (die für viele Anwendungen zeilenbasiert TCP_NODELAYist ) und die Bandbreiteneffizienz aus, da sie aktiviert ist. Auch mit -tt, sshsetzt die IPQoS lowdelayim Gegensatz zu throughput. Sie könnten beide umgehen mit:

ssh -o IPQoS=throughput -tt host 'stty raw -echo; sudo cmd | cat' < <(cat)

Beachten Sie außerdem, dass der Remote-Befehl das Dateiende in seiner Standard-ID nicht erkennen kann und die Standard-ID und die Standard-ID des Remote-Befehls zu einem einzigen Stream zusammengeführt werden.

Also doch keine so gute Arbeit.

Wenn Sie ein bekommen eine Art und Weise habe einen Pseudo-Terminal auf dem entfernten Rechner zum Laichen (wie mit expect, zsh, socat, perl‚s IO::Pty...), dann wäre es besser, dass die Verwendung des Pseudo-Terminal zu schaffen , zu befestigen sudo(aber nicht für I / O) und sshohne -t.

Zum Beispiel mit expect:

ssh host 'expect -c "spawn -noecho sh -c {
     exec sudo cmd >&4 2>&5 <&6 4>&- 5>&- 6<&-}
 exit [lindex [wait] 3]" 4>&1 5>&2 6<&0'

Oder mit script(hier unter der Annahme der Implementierung von util-linux):

ssh host 'SHELL=/bin/sh script -qec "
              sudo cmd <&3 >&4 2>&5 3<&- 4>&- 5>&-
            " /dev/null 3<&0 4>&1 5>&2'

(vorausgesetzt (für beide), dass die Anmeldeshell des Remotebenutzers Bourne-ähnlich ist).

Stéphane Chazelas
quelle
30

Standardmäßig ist SUDO so konfiguriert, dass ein TTY erforderlich ist. Das heißt, SUDO wird voraussichtlich über eine Anmeldeshell ausgeführt. Sie können diese Anforderung umgehen, indem Sie den -tSchalter zu Ihrem SSH-Aufruf hinzufügen :

ssh -t someserver sudo somecommand

Die -tZwangszuordnung einer Pseudotty.

Wenn Sie dies global ausführen möchten, ändern Sie es, um /etc/sudoerses anzugeben !requiretty. Dies kann pro Benutzer, pro Gruppe oder auf allen Ebenen erfolgen.

JRFerguson
quelle
5
Nein, das ist nicht die Standardeinstellung. Es ist nur die requirettyRed Hat- Distribution von sudo, die in den Standard-Sudoern enthalten ist. Es wird in neueren Versionen behoben
Stéphane Chazelas
1
@StephaneChazelas +1 für die Aufklärung, dass Red Hat und seine Geschwister größtenteils einheimisch sind, und ein weiteres ++, wenn ich das für den aktuellen Fehlerbericht könnte!
JRFerguson
18

Verwenden Sie das -tFlag, sshum die Tty-Zuordnung zu erzwingen.

$ ssh luci tty
not a tty
$ ssh luci -t tty
/dev/ttys003
$
Kyle Jones
quelle
Fügen Sie eine Sekunde hinzu -t, um die Zuordnung zu erzwingen, wennPseudo-terminal will not be allocated because stdin is not a terminal.
Samveen
11

Ich bin mit Docker und Centos 7 auf dieses Problem gestoßen. Am Ende habe ich Folgendes getan:

yum install -y sudo

sed -i -e 's/Defaults requiretty.*/ #Defaults requiretty/g' /etc/sudoers

Ich habe diesen Hack unter https://hub.docker.com/r/liubin/fluentd-agent/~/dockerfile gefunden

Martin Tapp
quelle
1
Diese Antwort machte für mich am meisten Sinn, auch mit Docker und CentOS 7. Es war leicht zu verstehen sowie kopieren / einfügen freundlich!
DaShaun
1

Eine interessante Alternative ist das Ausführen von FreeIPA oder IdM, um Ihre Benutzer und Sudoer-Regeln zentral zu verwalten. Sie können dann Sudo-Regeln erstellen und die Option zuweisen

! requiretty

in der Regel. Der Befehl wird dann wie erwartet ausgeführt. Sie haben auch die Vorteile, alle Server und Benutzer von einer einzigen Konfiguration aus zu verwalten.

strutschen
quelle
0

Ich hatte das gleiche Problem. In meinem Fall bestand die Lösung aus zwei Zeilen

myscript=$(cat ssh_test.sh)
ssh -t user@host "$myscript"

Erläuterung:

  • Fügen Sie die Befehle, die Sie ausführen möchten (einschließlich sudo-Befehle), in ein Skript ein, z. B. "ssh_test.sh".

  • Lesen Sie das gesamte Skript in eine Variable namens "myscript".

  • Rufen Sie ssh mit nur einem -t auf und geben Sie die Variable anstelle eines Befehls an.

Zuvor hatte ich Probleme mit der Verwendung von Kombinationen aus stdin und heredocs

Gerry Hickman
quelle
-1

Ich habe diese Frage beim Googeln gefunden und bin auf diesen Fehler aus einem ganz anderen Grund gestoßen.

Mein Fix bestand darin, den Aufruf von Downstream-Shell-Skripten zu beenden, wie dies sudobei meinem übergeordneten Shell-Skript der Fall war, als das übergeordnete Shell-Skript bereits mit aufgerufen wurde sudo.

entpnerd
quelle