跳轉至內容

OpenSSH/Cookbook/遠端程序

100% developed
來自 Wikibooks,開放世界中的開放書籍

 

OpenSSH 的主要功能之一是在其他系統上訪問和執行程式。畢竟,這是該程式的主要目的之一。有幾種方法可以擴充套件它,無論是互動式還是作為無人值守指令碼的一部分。因此,除了互動式登入之外,ssh(1) 可用於簡單地執行程式或指令碼。當程式或指令碼完成其過程時,將自動登出。一些組合是顯而易見的。其他需要更仔細的規劃。有時,僅僅知道可以做某事就足夠了,而其他時候則需要更多細節。以下列出了一些使用 OpenSSH 執行遠端任務的有用組合示例。

執行遠端程序

[編輯 | 編輯原始碼]

ssh(1) 的一個明顯的用途是在遠端系統上執行一個程式,然後退出。這通常是一個 shell,但可以是該帳戶可用的任何程式。為了獲得反饋,ssh(1) 傳遞了遠端程序返回的任何退出值。當遠端程序完成時,ssh(1) 將終止並將最後一個完成的遠端程序的退出值傳遞給本地主機。因此,它可以在指令碼中使用,並且客戶端系統可以使用遠端程序的結果。

以下將在遠端系統上執行 true(1) 並將成功(退出程式碼 0)返回到執行 ssh(1) 的本地系統。

$ ssh -l fred server.example.org /bin/true
$ echo $?
0

以下將在遠端系統上執行 false(1) 並將失敗(退出程式碼 1)返回到執行 ssh(1) 的本地系統。

$ ssh -l fred server.example.org /bin/false
$ echo $?
1

如果返回了任何其他值(從 0 到 255),ssh(1) 將從遠端主機將它們傳遞迴本地主機。

執行遠端程序並捕獲本地輸出

[編輯 | 編輯原始碼]

可以使用正常的重定向在本地儲存遠端機器上執行的程式的輸出。這裡我們在遠端機器上執行 dmesg(8)

$ ssh -l fred server.example.org dmesg > dmesg.from.server.log

互動式程序將難以或不可能以這種方式執行,因為看不到任何輸出。對於需要任何使用者輸入的互動式程序,可以將輸出透過管道傳輸到 tee(1),以便將輸出同時傳送到檔案和 stdout。此示例在遠端執行匿名 FTP 會話並將輸出記錄在本地。

$ ssh -l fred server.example.org "ftp -a anotherserver" | tee ftp.log

可能需要強制分配偽終端才能使輸入和輸出都正確可見。

$ ssh -t -l fred server.example.org "ftp -a anotherserver" | tee /home/fred/ftp.log

在讀取一臺機器上的資料並在另一臺機器上處理資料的最簡單方法是使用管道。

$ ssh fred@server.example.org 'cat /etc/ntpd.conf' | diff /etc/ntpd.conf -

執行本地程序並捕獲遠端資料

[編輯 | 編輯原始碼]

資料可以在一臺系統上生成並在另一臺系統上使用。這與 X 隧道不同,在 X 隧道中,程式和資料都駐留在另一臺機器上,只有圖形介面在本地顯示。同樣,在讀取一臺機器上的資料並在另一臺機器上使用資料的最簡單方法是使用管道。

$ cat /etc/ntpd.conf | ssh fred@server.example.org 'diff /etc/ntpd.conf -'

如果本地程式希望從遠端機器讀取檔案,則可以使用命名管道結合重定向來傳輸資料。在以下示例中,建立命名管道作為資料傳輸點。然後,ssh(1) 用於啟動一個遠端程序,該程序將輸出傳送到 stdout,該輸出被本地機器上的重定向捕獲併發送到命名管道,以便本地程式可以透過命名管道訪問資料。

在此特定示例中,必須向 tcpdump(8) 本身新增一個篩選器規則,以防止如果 ssh(1) 透過與正在收集的資料相同的介面連線,則會發生無限反饋迴圈。透過排除 SSH 埠、SSH 連線使用的主機或相應的網路介面來防止此迴圈。

$ mkfifo -m 600 netdata

$ ssh -fq -i /home/fred/.ssh/key_rsa \
        'sudo tcpdump -lqi eth0 -w - "not port 22"' > netdata

$ wireshark -k -i netdata &

tcpdump(8) 的任何 sudo(8) 特權也需要在沒有互動式密碼的情況下執行,因此必須非常小心和精確地寫出 /etc/sudoers 中允許哪些程式和引數,絕不能更多。ssh(1) 的身份驗證也必須以非互動方式進行,例如使用金鑰和金鑰代理。設定完配置後,執行 ssh(1) 並將其連線後傳送到後臺。在 ssh(1) 處於後臺後,將啟動本地應用程式,在本例中為 wireshark(1)(一個圖形網路分析器),該應用程式設定為將命名管道作為輸入讀取。

在某些系統上,可以使用程序替換來簡化兩臺機器之間的資料傳輸。執行程序替換隻需要一行程式碼。

$ wireshark -k -i <( ssh -fq -i /home/fred/.ssh/key_rsa \
        'sudo tcpdump -lqi eth0 -w - "not port 22"' )

但是,程序替換不符合 POSIX 標準,因此不能跨平臺移植。它僅限於 bash(1),在其他 shell 中不存在。因此,為了實現可移植性,請使用命名管道。

連線或斷開連線時執行遠端程序

[編輯 | 編輯原始碼]

有幾種不同的方法可以使遠端機器上的程序保持執行狀態。如果目的是回到程序並定期檢查它,那麼終端多路複用器可能是最佳選擇。對於更簡單的需求,還有其他方法。

斷開連線後在後臺執行遠端程序

[編輯 | 編輯原始碼]

許多例行任務可以在後臺啟動,然後讓它們自行完成,而無需保持登入狀態。在後臺執行遠端程序時,最好為該任務專門啟動一個 shell。

$ ssh -t -l fred server.example.org 'sh -c "tar zcf /backup/usr.tgz /usr/" &'

另一種方法是使用終端多路複用器。使用它們的一個優點是可以重新連線並定期跟蹤進度,或者在連線中斷(例如在旅行時)時簡單地恢復正在進行的工作。這裡,tmux(1) 重新連線到現有會話,或者如果沒有現有會話,則建立一個新會話。

$ ssh -t -l fred server.example.org "tmux a -d || tmux"

在較舊的系統上,screen(1) 通常可用。這裡,它在遠端啟動以建立新的會話(如果不存在),或重新連線到現有會話(如果正在執行)。因此,如果沒有正在執行的 screen(1) 會話,將建立一個新會話。

$ ssh -t -l fred server.example.org "screen -d -R"

當一個 screen(1) 會話執行時,可以將其分離並關閉 SSH 連線,而不會影響它可能正在執行的後臺程序。這在遠端機器上託管某些遊戲伺服器時特別有用。然後可以使用相同的兩個選項重新連線正在進行的終端會話。

$ ssh -t -l fred server.example.org "screen -d -R"

關於使用終端多路複用器 tmux(1) 或下面的內容還有更多資訊。在某些環境中,可能還需要使用 pagsh(1),尤其是在使用 Kerberos 時,請參見下文。或者 nohup(1) 可能有用。

斷開連線後為遠端程序保留身份驗證票證

[edit | edit source]

身份驗證憑據通常在登出時被刪除,因此任何剩餘的程序不再能夠訪問使用身份驗證令牌進行的任何操作。在這種情況下,需要先建立一個新的憑據快取沙箱,以便在斷開連線之前在其中執行獨立程序。

$ pagsh
$ /usr/local/bin/a-slow-script.sh

Kerberos 和 AFS 是兩種需要有效、活動票證的服務示例。使用 pagsh(1) 是這些環境的一種解決方案。

使用 tmux(1) 或 screen(1) 自動重新連線和恢復 SSH 會話

[edit | edit source]

使用終端多路複用器,可以在有意或意外中斷後恢復活動的執行會話。這裡假設 ssh(1) 在無法連線到伺服器的 15 秒(每次嘗試 5 秒,共 3 次)後斷開連線並退出。然後重新連線 tmux(1) 會話,或者如果不存在則建立該會話。

$ while ! ssh -t fred@example.org -o 'ServerAliveInterval 5' \
	'tmux attach -d || tmux new-session'; \
  do true; \
  done

然後每次 ssh(1) 退出時,shell 都會嘗試再次連線,並且當連線成功時,會尋找要連線的 tmux(1) 會話。這樣,如果 TCP 或 SSH 連線斷開,終端多路複用器內部的任何應用程式或會話都不會停止執行。以下是一個在舊系統上使用 screen(1) 的示例。

$ while ! ssh -t fred@example.org -o 'ServerAliveInterval 5' \
	'screen -d -R'; \
  do true; \
  done

上面的示例只是展示了過分簡單的演示,它們在最基本的情況下有助於在 TCP 連線斷開後恢復 shell 的位置。 tmux(1)screen(1) 都有更強大的功能,值得探索,尤其是對於旅行者和遠端工作人員。

另請參閱有關“公鑰身份驗證”的部分,瞭解如何將金鑰整合到自動重新連線過程中。

共享遠端 shell

[edit | edit source]

教學、團隊程式設計、監督和建立文件都是兩個使用者共享 shell 的一些示例。有一些選項可用於只讀檢視,以及多個使用者讀寫。

只讀監控或日誌記錄

[edit | edit source]

管道和重定向是儲存 SSH 會話輸出或允許其他使用者只讀跟蹤的快速方法。

一個示例用例是當路由器需要重新配置並且可以透過序列控制檯訪問時。假設路由器已關閉,並且顧問必須透過另一個使用者的筆記型電腦連線登入以訪問路由器的序列控制檯,並且需要監督執行的操作或在某些階段提供幫助。這在記錄各種活動(包括配置或安裝)方面也非常有用。

使用 tee(1) 進行只讀

[edit | edit source]

將 shell 活動捕獲到日誌檔案,並選擇使用 tail 即時監視它。實用程式 tee(1)(就像管道中的 T 形接頭一樣)用於將輸出傳送到兩個目的地,即 stdout 和檔案。

$ ssh fred@server.example.org | tee /tmp/session.log

可以使用 tail(1) 即時監視生成的檔案,或者事後使用分頁器(如 less(1))監視。

使用 tee(1) 強制序列會話並進行遠端日誌記錄
[edit | edit source]

實用程式 tee(1) 可以捕獲來自任何可以寫入 stdout 的程式的輸出。它非常適合引導遠端站點的人員完成流程、監督或構建文件。

本示例使用 chroot(8) 來儘可能限制操作選擇。實際上構建 chroot 監獄是一個單獨的任務。構建完成後,guest 使用者將成為“consult”組的成員。測試的序列連線位於裝置 ttyUSB0 上,這是一個 USB 到序列轉換器,cu(1) 用於連線。 tee(1) 獲取來自 cu(1) 的輸出,並在使用程式時將副本儲存到檔案中以進行日誌記錄。以下是將放在 sshd_config(5) 中的內容

Match Group consult
        ChrootDirectory /var/chroot-test
        AllowTCPForwarding no
        X11Forwarding no
        ForceCommand cu -s 19200 -l /dev/ttyUSB0 | tee /var/tmp/cu.log

這樣,一個或多個使用者就可以使用 tail(1) 跟蹤 cu(1) 中發生的活動,方法是將其指向遠端伺服器上的日誌檔案。

$ tail -f /var/tmp/cu.log

或者可以編輯日誌並用於文件。 tmux(1)screen(1) 的高階使用者也可以允許只讀觀察者。

指令碼
[edit | edit source]

可以自動化一些連線。建立一個指令碼,例如 /usr/local/bin/screeners,然後使用 ForceCommand 指令使用該指令碼。以下是一個嘗試重新連線到現有會話的指令碼示例。如果不存在任何會話,則建立一個新會話並自動建立與序列裝置的連線。

#!/bin/sh

# try attaching to an existing screen session,
# or if none exist, make a new screen session

/usr/bin/screen -d -R || \
        /usr/bin/screen \
            /bin/sh -c "/usr/bin/cu -s 19200 -l /dev/ttyUSB0 | \
            /usr/bin/tee /tmp/consultant.log"

使用終端多路複用器進行互動式共享

[edit | edit source]

終端多路複用器 tmux(1)screen(1) 可以將兩個或更多使用者連線到同一個會話。[1] 會話可以對某些使用者只讀,也可以對所有參與者讀寫。

tmux(1)
[edit | edit source]

如果同一個帳戶將共享會話,那麼這非常容易。在第一個終端中,啟動 tmux(1),其中“sessionname”是會話名稱

$ tmux new-session -s sessionname

然後在第二個終端中

$ tmux attach-session -t sessionname

如果同一個帳戶從不同的位置登入並共享會話,那麼這些操作就足夠了。對於不同的使用者,您必須設定 tmux(1) 套接字的許可權,以便兩個使用者都可以讀取和寫入它。這將首先需要一個包含兩個使用者的組。

然後,在兩個帳戶都加入共享組後,在第一個終端(包含主帳戶的終端)中,啟動 tmux(1),就像之前一樣,但還要為會話的套接字分配一個名稱。這裡“sessionname”是會話名稱,“sharedsocket”是套接字的名稱

$ tmux -S /tmp/shareddir/sharedsocket new-session -s sessionname

然後將套接字和套接字目錄的組更改為兩個使用者共享的組。確保套接字許可權允許該組寫入套接字。在此示例中,共享組為“foo”,套接字為 /tmp/shareddir/sharedsocket

$ chgrp foo /tmp/shareddir/
$ chgrp foo /tmp/shareddir/sharedsocket
$ chmod u=rwx,g=rx,o= /tmp/shareddir/
$ chmod u=rw,g=rw,o=  /tmp/shareddir/sharedsocket

最後,讓第二個帳戶登入並使用共享套接字連線到指定的會話。

$ tmux -S /tmp/shareddir/sharedsocket attach-session -t sessionname

此時,兩個帳戶都可以讀取和寫入同一個會話。

screen(1)
[編輯 | 編輯原始碼]

如果同一個帳戶要共享一個 screen(1) 會話,那是一個簡單的過程。在一個終端中,啟動一個新會話併為其分配一個名稱。在這個例子中,'sessionname' 是會話的名稱。

$ screen -S sessionname

在另一個終端中,連線到該會話。

$ screen -x sessionname

如果兩個不同的帳戶要共享同一個 screen(1) 會話,則需要執行以下額外步驟。第一個使用者在啟動會話時執行此操作。

$ screen -S sessionname
^A :multiuser on
^A :acladd user2

然後第二個使用者執行此操作。

$ screen -x user1/sessionname

screen(1) 中,如果使用多個使用者帳戶,則可以使用 aclchg 命令來刪除其他使用者的寫入許可權:^A :aclchg user -w "#"。請注意, screen(1) 必須以 SUID 方式執行才能支援多使用者。如果未設定,您在嘗試連線第二個使用者時將收到提醒錯誤訊息。您可能還需要將 /var/run/screen 的許可權設定為 755。

使用 X11 轉發在本地顯示遠端圖形程式

[編輯 | 編輯原始碼]

可以透過轉發 X11(X 視窗系統的當前實現)來在遠端機器上執行圖形程式並將其在本地顯示。X11 用於在許多系統上提供圖形介面。請參閱網站 www.X.org 以瞭解其歷史和技術細節。它內建在大多數桌面作業系統中。它甚至作為 Macintosh OS X 的一部分進行分發,儘管它不是預設的圖形顯示方法。

X11 轉發預設情況下處於關閉狀態,如果要使用它,則必須在 SSH 客戶端和伺服器上都啟用它。

X11 還使用客戶端-伺服器架構,X 伺服器是為終端使用者執行實際顯示的部分,而各種程式充當客戶端並連線到伺服器。因此,透過將客戶端和伺服器放在不同的機器上並轉發 X11 連線,可以在其他計算機上執行程式,但將其顯示和使用起來就像它們在使用者自己的計算機上一樣。

需要注意的是,允許遠端機器轉發 X11 連線將允許它及其應用程式訪問託管 X 伺服器的機器上的許多裝置和資源。無論使用者的意圖如何,這些都是使用者帳戶可以訪問的裝置和其他資源。因此,只有在另一臺機器、該使用者帳戶及其應用程式可靠的情況下才應進行轉發。

在伺服器端,要預設啟用 X11 轉發,請將以下行新增到 sshd_config(5) 中,無論是在主塊中還是在 Match 塊中。

X11Forwarding yes

在客戶端側,X11 的轉發預設情況下也是關閉的,但可以使用三種不同的方法啟用它。可以在 ssh_config(5) 中啟用,或者使用 -X-Y 執行時引數啟用。

$ ssh -l fred -X desk.example.org

但是,連線速度會很慢。如果響應速度是一個因素,則可能需要考慮使用 SOCKS 代理或其他技術,例如 FreeNX。

使用 ssh_config(5) 指定 X11 轉發

[編輯 | 編輯原始碼]

可以透過配置 ssh_config(5)/etc/ssh_config 中為所有帳戶的所有傳出 SSH 連線啟用 X11 轉發,或者僅為特定主機啟用。

X11Forwarding yes

可以將 ssh_config(5) 設定應用於 ~/.ssh/config 中的單個帳戶,以限制預設情況下透過主機名或 IP 號碼對單個主機的轉發。

Host desk.example.org 
        X11Forwarding yes

這裡它透過 IP 號碼為特定機器啟用。

Host 192.168.111.25 
        X11Forwarding yes

同樣,使用受限的模式匹配來允許為子域或 IP 地址範圍轉發。這裡它為 pool.example.org 域中的任何主機、從 192.168.100.100 到 192.168.100.109 的任何主機以及從 192.168.123.1 到 199.168.123.254 的任何主機啟用。

Host *.pool.example.org 
        X11Forwarding yes

Host 192.168.100.10?
        X11Forwarding yes

Host 192.168.123.*
        X11Forwarding yes

再次強調,X11 內建在大多數桌面系統中。OS X 還有一個可選的附加元件,其根源來自 NextStep。但是,一些特別過時、傳統的平臺可能缺少 X11 支援。但即使在那裡,也通常可以使用合適的工具進行改裝,例如 Xming 工具。

無特權 sshd(8) 服務

[編輯 | 編輯原始碼]

可以在高階口上使用無特權帳戶執行 sshd(8)。它將無法派生到其他帳戶,因此登入只能在執行無特權服務的同一帳戶上進行。

在正常、無特權帳戶上執行無特權 SSH 服務通常需要三個步驟。

1) 在無特權帳戶下啟動 SSH 守護程式之前,必須建立一些無特權主機金鑰。這些金鑰將用於向連線的客戶端識別此服務,尤其是在回訪時。它們的建立只需要對每個帳戶進行一次,並且必須將密碼留空。

$ ssh-keygen -q -t ed25519 -N '' \
        -f /home/fred/.ssh/ssh_host_key_ed25519 \
        -C 'unprivileged SSH host key for fred'

如果需要,對 ECDSA 和 RSA 金鑰也進行同樣操作。確保許可權正確。金鑰所在的目錄及其父目錄不應被其他帳戶寫入,並且私有 SSH 主機金鑰本身也不應被任何其他帳戶讀取。

2) 當金鑰就位後,透過手動啟動 SSH 伺服器來測試它們。一種方法是使用 -h 選項來指向這些備用主機金鑰檔案。請注意,由於帳戶沒有特權,因此只有從 1024 開始的埠可用,在這個例子中,使用 -p 選項設定埠 2222。

$ /usr/sbin/sshd -D \
        -h /home/fred/.ssh/ssh_host_key_ed25519 \
        -h /home/fred/.ssh/ssh_host_key_ecdsa -p 2222

驗證從另一個系統是否可以訪問新服務。尤其要確保任何包過濾器(如果存在)都設定為透過正確的埠。傳入連線和任何包過濾器都必須在正常使用中考慮備用埠。另一種方法是將無特權 SSH 服務新增為洋蔥服務。有關這方面的資訊,請參閱關於代理和跳躍主機的章節。

請注意,以上示例使用守護程式的預設配置檔案。如果需要不同的配置檔案用於特殊設定,則將 -f 選項新增到公式中。

$ /usr/sbin/sshd -D -f /home/fred/.ssh/sshd_config

可以使用備用配置檔案為無特權帳戶設定特定配置指令。可以在該檔案中識別無特權主機金鑰,以及指定的備用監聽埠和許多其他自定義項。透過將 SyslogFacility 指令更改為除 AUTH 之外的其他值,可能還有助於將無特權服務與同一系統上已有的任何其他 SSH 服務分別記錄下來,AUTH 是預設值。

3) 自動化啟動(如果這是目標)。

-D 選項使程序不會分離併成為守護程式。在測試期間,這可能很有用,但在實際使用中可能並非如此,這取決於程序的啟動方式。

無特權 sshd(8) 程序的外觀

[編輯 | 編輯原始碼]

由於使用的是無特權帳戶,因此不會發生特權分離,所有子程序將在與原始 sshd(8) 程序相同的帳戶中執行。以下是在無特權帳戶下監聽埠 2222 以接收傳入連線的示例,該示例使用預設配置檔案幷包含一些覆蓋項。

$ pgrep -d , sshd | COLUMNS=200 xargs ps -w -o user,pid,args -p
USER         PID COMMAND
fred     1997992 sshd: /usr/sbin/sshd -h /home/fred/.ssh/ssh_host_key_ed25519 -h /home/fred/.ssh/ssh_host_key_ecdsa -p 2222 [listener] 0 of 10-100 startups

然後,一旦有人連線但尚未完成登入,它可能看起來像這樣。會派生一個監視器,但即使它被標記為 [priv],它也沒有特權,而是仍然在與父程序相同的無特權帳戶中執行。它反過來會派生一個子程序(這裡為程序 1998150)來管理身份驗證。

$ pgrep -d , sshd | COLUMNS=200 xargs ps -w -o user,pid,args -p
USER         PID COMMAND
fred     1997992 sshd: /usr/sbin/sshd -h /home/fred/.ssh/ssh_host_key_ed25519 -h /home/fred/.ssh/ssh_host_key_ecdsa -p 2222 [listener] 1 of 10-100 startups
fred     1998149 sshd: fred [priv]
fred     1998150 sshd: fred [net]

最後,一旦登入成功,該無特權程序就會被丟棄,並且會啟動一個新的無特權程序來管理互動式會話。

$ pgrep -d , sshd | COLUMNS=200 xargs ps -w -o user,pid,args -p
USER         PID COMMAND
fred     1997992 sshd: /usr/sbin/sshd -h /home/fred/.ssh/ssh_host_key_ed25519 -h /home/fred/.ssh/ssh_host_key_ecdsa -p 2222 [listener] 0 of 10-100 startups
fred     1998149 sshd: fred [priv]
fred     1998410 sshd: fred@pts/20

在上面,程序 1998410 正在管理互動式會話。

鎖定受限 Shell

[編輯 | 編輯原始碼]

受限 Shell 設定的環境比標準互動式 Shell 提供的環境更受控制。儘管它的行為與標準 Shell 幾乎相同,但在許多情況下它對已列入白名單的功能存在限制,而其他功能則被停用。這些限制包括但不限於以下內容。

  • SHELL、ENV 和 PATH 變數不可更改。
  • 程式不能使用絕對路徑或相對路徑執行。
  • 不能使用建立檔案的重定向(特別是 >、> |、>>、<>)。

常見的頂級 Shell(如 bash(1)ksh(1)zsh(1))都可以以受限模式啟動。請參閱各個 Shell 的手冊頁以瞭解如何呼叫限制的詳細資訊。

即使有上述限制,仍然可以透過多種方法輕鬆地從受限 shell 中逃脫:如果路徑中任何地方都提供正常的 shell,則可以啟動它們。如果可用路徑中的常規程式提供到完整 shell 的 shell 逃逸,則也可以使用它們。最後,如果sshd(8)配置為允許任意程式獨立於 shell 執行,則可以啟動一個完整的 shell。因此,安全使用受限 shell 的內容不僅僅是將帳戶的 shell 設定為/bin/rbash,然後就萬事大吉。需要採取一些步驟來儘可能地使逃脫限制變得困難,尤其是在 SSH 上。

(以下步驟假設您熟悉適當的系統管理工具及其使用方式。此處未涵蓋其選擇和使用。)

首先,建立一個包含一些指向白名單程式的符號連結的目錄。這些連結指向該帳戶在將目錄新增到 PATH 環境變數後應該能夠執行的程式。這些程式不應具有任何 shell 逃逸功能,並且顯然,它們本身不應該是不受限制的 shell。

如果您想阻止對系統進行大範圍探索,請記住將使用者鎖定在 chroot 或 jail 中。即使沒有 ls(1) 和 cat(1) 等程式,仍然可以進行探索(請參閱下文:“在沒有 ls(1) 和 cat(1) 的情況下進行探索的方法”。

使用符號連結是因為原始檔案(希望)由包管理軟體維護,不應移動。如果原始目錄和白名單目錄位於不同的檔案系統中,則不能使用硬連結。如果您設定了排除原始檔案的 chroot 或 jail,則需要使用硬連結。

$ ls -l /usr/local/rbin/
total 8
lrwxr-xr-x  1 root  wheel    22 Jan 17 23:08 angband -> /usr/local/bin/angband
lrwxr-xr-x  1 root  wheel     9 Jan 17 23:08 date -> /bin/date
-rwxr-xr-x  1 root  wheel  2370 Jan 17 23:18 help
lrwxr-xr-x  1 root  wheel    12 Jan 17 23:07 man -> /usr/bin/man
lrwxr-xr-x  1 root  wheel    13 Jan 17 23:09 more -> /usr/bin/more
lrwxr-xr-x  1 root  wheel    28 Jan 17 23:09 nethack -> /usr/local/bin/nethack-3.4.3
...

接下來,為該帳戶建立一個最小的.profile。將其所有者設定為“root”。也對其父目錄(即使用者的家目錄)執行此操作。然後,允許該帳戶所屬的組讀取檔案和目錄。

$ cd /home/fred

$ cat .profile
PATH=/usr/games:/usr/local/rbin
export PATH HOME TERM

$ ls -ld . .profile
drwxr-xr-x  3 root  fred    512 Jan 17 23:20 .
-rw-r--r--  1 root  fred     48 Jan 17 23:20 .profile

接下來,為鎖定的帳戶建立一個組,並將其填充。此處,該帳戶位於games組中,將透過其在此組中的成員身份進行限制。

$ groups fred
fred games

接下來,透過在伺服器配置中使用ForceCommand指令鎖定該組或帳戶的 SSH 訪問許可權,並將其應用於所選組。這對於防止透過 SSH 客戶端直接呼叫 shell(例如使用ssh -t fred@server.example.org /bin/sh或類似方法)來輕鬆規避限制是必要的。請記住,如果不需要,請停用轉發。例如,以下內容可以附加到sshd_config(5),以便“games”組中的任何帳戶無論使用 SSH 客戶端嘗試什麼操作,都會獲得受限 shell。

Match Group games
        X11Forwarding no
        AllowTcpForwarding no
        ForceCommand rksh -l

請注意,ForceCommand使用-l選項呼叫受限 shell,使其成為登入 shell,如果存在且可讀,則會讀取和執行/etc/profile$HOME/.profile中的內容。這對於設定自定義 PATH 環境變數是必要的。同樣,請確保受限帳戶無法以任何方式編輯或覆蓋$HOME/.profile。還要注意,這會停用該帳戶的 SFTP 訪問許可權,從而阻止許多其他惡意行為。

最後但並非最不重要的一點是,將帳戶的登入 shell 設定為受限 shell。請包含受限 shell 的完整路徑。可能還需要先將其新增到/etc/shells中找到的已批准 shell 列表中。

注意:在沒有 ls(1) 和 cat(1) 的情況下進行探索的方法

[edit | edit source]
# To see a list of files in the current working directory:
$ echo *

# To see the contents of a text file:
$ while IFS= read -r j; do echo "$j"; done < .profile


參考資料

[edit | edit source]
  1. "與 Tmux 和 Screen 共享終端會話". HowToForge. 2012.

 

華夏公益教科書