使用 RootDirectory= 執行 systemd 服務並訪問 /bin 二進製文件
我正在嘗試利用一些 systemd 助手來chroot(2)使用
RootDirectory=
. 這是一個基本的 Python 腳本,位於/srv/http
託管 Web 伺服器的下面。它有一個shebang#!/usr/bin/python
(我也嘗試過不同的組合)服務文件也很簡單:
[Unit] Wants=network-online.target After=network-online.target AssertPathExists=/srv/http [Service] Type=simple Restart=always RestartSec=10 RootDirectory=/srv/http PrivateTmp=true ExecStart=/server.py PIDFile=/run/miniweb.pid [Install] WantedBy=multi-user.target
日誌清楚地表明它找不到執行檔:
Mar 11 19:23:49 bigrigv2 systemd[13213]: testweb.service: Failed to execute /server.py: No such file or directory Mar 11 19:23:49 bigrigv2 systemd[13213]: testweb.service: Failed at step EXEC spawning /server.py: No such file or directory
它被標記為執行檔:
-rwxr-xr-x 1 anton anton 650 Mar 11 19:06 server.py
我也嘗試過
ExecStart=/bin/python /srv/http/server.py
其他變體。我不完全確定我是否理解RootDirectory
以及如何正確執行來自 chroot 服務腳本的 Python 或其他二進製文件的概念。我的假設是,在執行服務之前,它會 chroot:s 進入,/srv/http
之後服務將無法退出並在這種情況下執行 Python。這是有道理的,但是我不太明白為什麼/server.py
找不到。你將如何執行依賴於其他二進製文件的事情?大多數解決方案都提到使用語言(例如 C)chroot
並從應用程序控制它,但是我不明白在服務腳本中提供 chroot 的意義,而不是非常有限的 bash 腳本或獨立二進製文件。可能是一個非常簡單的問題,但我很迷茫,任何幫助將不勝感激!
直接回答你的問題:
如何使用 RootDirectory 在 chroot 之外正確執行具有外部依賴項的服務。
你不能。如果某些東西在 chroot 監獄中,它就無法訪問外部的任何東西,包括二進製文件和庫。但仍有一些方法可以保護您的系統。
採用相對於主機根目錄(即執行服務管理器的系統的根目錄)的目錄路徑。使用 chroot(2) 系統呼叫設置已執行程序的根目錄。如果使用它,則必須確保程序二進製文件及其所有輔助文件在 chroot() jail 中可用。
如果你設置了
RootDirectory=/srv/http
,那麼當/server.py
被呼叫時,它會嘗試執行/usr/bin/python
,但是因為找不到那個路徑而失敗。即使您可以執行類似的操作ExecStartPre=/bin/cp /usr/bin/python /src/http/usr/bin/python
,當您嘗試這樣做時仍然會遇到問題,import flask
或者import pyramid
因為這些庫未安裝在您的 chroot 中。我用像你這樣的設置做了一個測試,沒有一個好的shebang,我得到了和你一樣的錯誤。這裡有三個選項:
- 為您的 chroot 提供所需的一切。如果您使用的是基於 debian 的系統,那麼
debootstrap
設置它的好工具deboostrap buster /srv/http
應該可以工作。它將安裝一個基本系統,然後你可以sudo chroot && apt install python python-flask
在裡面安裝任何你喜歡的東西。- 使用內置選項對您的服務進行沙箱處理,而不是對其進行 chroot。具體來說:
RemoveIPC=true
和PrivateTmp=true
。這些確保了由執行程序創建的 IPC 對象和臨時文件的生命週期綁定到服務的執行時。由於/tmp
並且/var/tmp
通常是系統上唯一的全域可寫目錄,這確保了該單元在終止後不會留下文件。NoNewPrivileges=true
和RestrictSUIDSGID=true
。這些確保呼叫的程序無法受益或創建 SUID/SGID 文件或目錄。ProtectSystem=strict
並ProtectHome=read-only
禁止服務寫入文件系統中的任何位置(例外是/dev/
/proc/
和/sys/
。為了允許服務寫入某些目錄,必須使用ReadWritePaths=
.RuntimeDirectory=
為服務分配一個執行時目錄,該目錄由服務的使用者擁有,並在系統終止時自動刪除。
- 您可以用一行替換我在第二步中所說的所有內容
DynamicUser=true
。這裡有一個很好的開發者解釋無論哪種方式,如果您不使用
User=
或DynamicUser=
應該使用。這將阻止您的服務存在並擁有對其他機密或其他機密root
的讀取權限。/etc/shadow
我真的很喜歡選項 3。啟用它確實可以保護您的系統免受服務的影響。