Tại sao tôi cần một tty để chạy sudo nếu tôi có thể sudo mà không cần mật khẩu?


226

Tôi đã cấu hình sudođể chạy mà không cần mật khẩu, nhưng khi tôi cố gắng ssh 'sudo Foo', tôi vẫn nhận được thông báo lỗi sudo: sorry, you must have a tty to run sudo.

Tại sao điều này xảy ra và làm thế nào tôi có thể làm việc xung quanh nó?

Câu trả lời:


290

Điều đó có thể là do /etc/sudoerstệp của bạn (hoặc bất kỳ tệp nào có trong đó) có:

Defaults requiretty

... Điều này sudođòi hỏi phải có TTY. Các hệ thống Red Hat (RHEL, Fedora ...) đã được biết là yêu cầu TTY trong sudoerstệp mặc định . Điều đó cung cấp không có lợi ích bảo mật thực sự và có thể được gỡ bỏ một cách an toàn.

Red Hat đã thừa nhận vấn đề và nó sẽ được gỡ bỏ trong các phiên bản tương lai.

Nếu thay đổi cấu hình của máy chủ không phải là một tùy chọn, vì cách khắc phục cấu hình sai đó, bạn có thể sử dụng -thoặc -ttcác tùy chọn để sshsinh ra một thiết bị đầu cuối giả ở phía xa, nhưng hãy cẩn thận rằng nó có một số mặt Các hiệu ứng.

-ttcó nghĩa là để sử dụng tương tác. Nó đặt thiết bị đầu cuối cục bộ ở rawchế độ để bạn tương tác với thiết bị đầu cuối từ xa. Điều đó có nghĩa là nếu sshI / O không từ / đến thiết bị đầu cuối, điều đó sẽ có tác dụng phụ. Ví dụ, tất cả các đầu vào sẽ được lặp lại, nhân vật bị đầu cuối đặc biệt ( ^?, ^C, ^U) sẽ gây ra chế biến đặc biệt; trên đầu ra, LFs sẽ được chuyển đổi thành CRLFs ... (xem câu trả lời này tại sao tệp nhị phân này bị thay đổi? để biết thêm chi tiết.

Để giảm thiểu tác động, bạn có thể gọi nó là:

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

Các < <(cat)sẽ tránh được các thiết lập của nhà ga địa phương (nếu có) trong rawchế độ. Và chúng tôi đang sử dụng stty raw -echođể thiết lập kỷ luật dòng của thiết bị đầu cuối từ xa khi đi qua (vì vậy nó hoạt động giống như đường ống sẽ được sử dụng thay vì thiết bị đầu cuối giả mà không có -tt, mặc dù điều đó chỉ áp dụng sau khi lệnh đó được chạy, vì vậy bạn cần để trì hoãn việc gửi một cái gì đó cho đầu vào cho đến khi điều đó xảy ra).

Lưu ý rằng vì đầu ra của lệnh từ xa sẽ đi đến một thiết bị đầu cuối, điều đó vẫn sẽ ảnh hưởng đến bộ đệm của nó (sẽ dựa trên dòng cho nhiều ứng dụng) và hiệu quả băng thông kể từ khi TCP_NODELAYbật. Ngoài ra -tt, sshđặt IPQoS lowdelaytrái ngược với throughput. Bạn có thể làm việc xung quanh cả hai với:

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

Ngoài ra, lưu ý rằng điều đó có nghĩa là lệnh từ xa không thể phát hiện tập tin cuối trên stdin của nó và thiết bị xuất chuẩn và thiết bị xuất chuẩn của lệnh từ xa được hợp nhất thành một luồng.

Vì vậy, không phải là một công việc tốt xung quanh sau khi tất cả.

Nếu bạn đã một có một cách để đẻ trứng một pseudo-thiết bị đầu cuối trên máy chủ từ xa (giống như với expect, zsh, socat, perl's IO::Pty...), sau đó nó sẽ là tốt hơn để sử dụng để tạo ra các giả thiết bị đầu cuối để đính kèm sudo(nhưng không cho I / O), và sử dụng sshmà không có -t.

Ví dụ expect: với :

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'

Hoặc với script(ở đây giả sử việc thực hiện từ 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'

(giả sử (cho cả hai) rằng vỏ đăng nhập của người dùng từ xa giống như Bourne).


30

Theo mặc định, SUDO được cấu hình để yêu cầu TTY. Đó là, SUDO dự kiến ​​sẽ được chạy từ shell đăng nhập. Bạn có thể đánh bại yêu cầu này bằng cách thêm công -ttắc vào lệnh gọi SSH của bạn:

ssh -t someserver sudo somecommand

Các -tlực lượng phân bổ một giả.

Nếu bạn muốn thực hiện điều này trên toàn cầu, hãy sửa đổi /etc/sudoersđể chỉ định !requiretty. Điều này có thể được thực hiện aa trên mỗi người dùng, mỗi nhóm hoặc mức độ bao gồm tất cả.


5
Không, đó không phải là mặc định. Đây chỉ là bản phân phối sudo có requirettytrong sudoers mặc định của nó. Nó sẽ được sửa trong các bản phát hành mới hơn
Stéphane Chazelas

1
@StephaneChazelas +1 vì đã khai sáng cho tôi rằng nó phần lớn là bản địa của Red Hat và anh chị em của nó và một ++ khác nếu tôi có thể cho báo cáo lỗi hiện tại!
JRFerguson

18

Sử dụng -tcờ sshđể buộc phân bổ tty.

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

Thêm một giây -tđể phân bổ lực lượng khiPseudo-terminal will not be allocated because stdin is not a terminal.
Samveen

11

Tôi gặp vấn đề này khi sử dụng Docker và Centos 7. Cuối cùng tôi đã làm như sau:

yum install -y sudo

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

Tôi tìm thấy bản hack này tại https://hub.docker.com/r/liubin/fluentd-agent/~/dockerfile


1
Câu trả lời này có ý nghĩa nhất đối với tôi, sử dụng Docker và CentOS 7. Thật dễ hiểu cũng như sao chép / dán thân thiện!
DaShaun

1

Một thay thế thú vị là chạy FreeIPA hoặc IdM để quản lý người dùng của bạn và các quy tắc sudoer tập trung. Sau đó, bạn có thể tạo quy tắc sudo và gán tùy chọn

!

trong quy tắc. Lệnh sau đó sẽ chạy như mong đợi. Bạn cũng sẽ có những lợi ích của việc quản lý tất cả các máy chủ và người dùng từ một bộ cấu hình duy nhất.


0

Tôi gặp vấn đề tương tự. Trong trường hợp của tôi, giải pháp là hai dòng

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

Giải trình:

  • Đặt các lệnh bạn muốn chạy (bao gồm các lệnh sudo) vào một tập lệnh, ví dụ: "ssh_test.sh".

  • Đọc toàn bộ tập lệnh thành một biến gọi là "myscript".

  • Gọi ssh chỉ với một -t và cung cấp biến thay vì lệnh.

Trước đó, tôi gặp vấn đề khi sử dụng kết hợp đọc từ stdin và sử dụng heredocs


-1

Tôi tìm thấy câu hỏi này trong khi Googling và tôi gặp phải lỗi này vì một lý do hoàn toàn khác.

Cách khắc phục của tôi là dừng việc gọi các tập lệnh shell xuôi dòng như sudotừ tập lệnh shell cha, khi tập lệnh shell cha đã được gọi bằng sudo.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.