비밀번호없이 sudo를 수행 할 수있는 경우 sudo를 실행하기 위해 tty가 필요한 이유는 무엇입니까?


226

sudo암호없이 실행되도록 구성 했지만 시도 할 때 ssh 'sudo Foo'여전히 오류 메시지가 표시 sudo: sorry, you must have a tty to run sudo됩니다.

왜 이런 일이 발생하며 어떻게 해결할 수 있습니까?

답변:


290

아마도 /etc/sudoers파일 (또는 포함 된 모든 파일)에 다음이 있기 때문일 수 있습니다.

Defaults requiretty

... sudoTTY 가 필요합니다. Red Hat 시스템 (RHEL, Fedora ...)은 기본 sudoers파일에 TTY가 필요한 것으로 알려져 있습니다. 이는 실질적인 보안 이점을 제공하지 않으며 안전하게 제거 할 수 있습니다.

Red Hat은이 문제를 인정 했으며 향후 릴리스에서 제거 될 것입니다.

서버 구성을 변경하는 것이 옵션이 아닌 경우 잘못된 구성 의 해결 방법으로 원격 측에 의사 터미널을 생성하는 -t또는 -tt옵션을 사용할 수 ssh있지만 서버 측에 여러 측면이 있음을주의하십시오 효과.

-tt대화식 사용을위한 것입니다. raw원격 터미널과 상호 작용할 수 있도록 로컬 터미널을 모드로 설정합니다. 즉, sshI / O가 터미널을 오가지 않으면 부작용이 발생합니다. 예를 들면, 모든 입력이 다시 반향 될 특수 문자 단말기 ( ^?, ^C, ^U) 특수 가공 발생할; 출력시 LFs는 s로 변환됩니다 CRLF... 자세한 내용 은이 바이너리 파일이 왜 변경됩니까?에 대한 답변을 참조하십시오.

영향을 최소화하기 위해 다음과 같이 호출 할 수 있습니다.

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

< <(cat)있는 로컬 단말 설정 (존재하는 경우) 피할 raw모드. 그리고 우리는 stty raw -echo원격 터미널의 회선 규율을 통과로 설정하는 데 사용 하고 있습니다 (효과적으로 의사 터미널 대신 의사 파이프 대신 사용되는 파이프처럼 작동 -tt하지만 명령이 실행 된 후에 만 ​​적용됩니다. 입력 될 때까지 무언가를 보내는 것을 지연시키기 위해).

원격 명령의 출력은 터미널로 이동하기 때문에 버퍼링 (많은 응용 프로그램에 대한 라인 기반)과 계속 TCP_NODELAY켜져있는 대역폭 효율성에 영향을 미칩니다 . 또한으로 -tt, ssh에은 IPQoS 설정 lowdelay에 반대를 throughput. 다음을 사용하여 둘 다 해결할 수 있습니다.

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

또한 이는 원격 명령이 stdin에서 파일 끝을 감지 할 수 없으며 원격 명령의 stdout 및 stderr이 단일 스트림으로 병합됨을 의미합니다.

그래서 결국 좋은 일이 아닙니다.

당신이 원격 호스트에 가상 단말기를 생성하는 방법을 가지고있는 경우에 (와 같은을 expect, zsh, socat, perlIO::Pty...), 다음은 의사 터미널 부착 만들 것을 사용하는 것이 더 좋을 것이다 sudo(에를하지만, I / O 용이 아님) ssh없이 사용하십시오 -t.

예를 들면 다음과 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'

또는 script(여기서 구현을 가정 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'

(원격 사용자의 로그인 쉘이 Bourne과 같다고 가정).


30

기본적으로 SUDO는 TTY를 요구하도록 구성되어 있습니다. 즉, SUDO는 로그인 쉘에서 실행될 것으로 예상됩니다. -tSSH 호출에 스위치를 추가하여이 요구 사항을 무시할 수 있습니다 .

ssh -t someserver sudo somecommand

-t의사 -tty 의 강제 할당.

이 작업을 전체적으로 수행 /etc/sudoers하려면을 지정하여 수정하십시오 !requiretty. 이것은 사용자, 그룹 또는 모든 포괄 수준에서 수행 될 수 있습니다.


5
아니요, 기본값이 아닙니다. requiretty기본 sudoers에있는 sudo의 redhat 배포판 만 입니다. 새로운 릴리즈에서 수정 될 예정입니다
Stéphane Chazelas

1
@StephaneChazelas +1 : Red Hat과 그 형제 자매 및 현재 버그 보고서에 대해 가능하다면 다른 ++에 크게 영향을 미친다는 것을 깨달았습니다.
JR 페 거슨

18

tty 할당을 강제 하려면 -t플래그를 사용하십시오 ssh.

$ ssh luci tty
not a tty
$ ssh luci -t tty
/dev/ttys003
$

다음 시간에 -t할당을 강제로 추가Pseudo-terminal will not be allocated because stdin is not a terminal.
Samveen

11

Docker와 Centos 7을 사용 하여이 문제에 부딪 쳤습니다.

yum install -y sudo

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

https://hub.docker.com/r/liubin/fluentd-agent/~/dockerfile 에서이 핵을 발견했습니다.


1
이 답변은 Docker 및 CentOS 7을 사용하는 것이 가장 적합했습니다. 복사 / 붙여 넣기는 물론 이해하기 쉬웠습니다!
DaShaun

1

흥미로운 대안은 FreeIPA 또는 IdM을 실행하여 사용자 및 sudoer 규칙을 중앙에서 관리하는 것입니다. 그런 다음 sudo 규칙을 작성하고 옵션을 지정할 수 있습니다

! 요구 사항

규칙적으로. 그런 다음 명령이 예상대로 실행됩니다. 또한 단일 구성 세트에서 모든 서버와 사용자를 관리 할 수 ​​있다는 이점이 있습니다.


0

나는 같은 문제가 있었다. 제 경우에는 해결책이 두 줄이었습니다.

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

설명:

  • 실행하려는 명령 (sudo 명령 포함)을 "ssh_test.sh"와 같은 스크립트에 넣으십시오.

  • 전체 스크립트를 "myscript"라는 변수로 읽으십시오.

  • 하나의 -t만으로 ssh를 호출하고 명령 대신 변수를 제공하십시오.

이 전에 stdin에서 읽는 조합과 heredocs를 사용하여 문제가 발생했습니다.


-1

인터넷 검색 중에이 질문을 발견했으며 완전히 다른 이유로이 오류가 발생했습니다.

sudo부모 셸 스크립트가 이미로 호출되었을 때 부모 셸 스크립트에서 와 같이 다운 스트림 셸 스크립트 호출을 수정하지 못했습니다 sudo.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.