Linux中國

Linux / Unix:chroot 命令實例講解

在 Linux和類 Unix 系統下每一個進程/命令的當前工作目錄稱之為進程/命令的根目錄(譯註:譯者以為此處有誤,實際上沒有進行過chroot的進程,其根目錄是系統的根目錄,而不是其工作目錄)。你可以使用 chroot 命令改變一個命令的根目錄,這最終將會改變當前運行的進程及其子進程的根目錄。

如果一個進程/命令運行在一個不能訪問外部根目錄文件的已修改環境中。這種修改環境通常被稱為"監禁目錄"(jail)或是"chroot 監禁"。只有特權進程和根用戶才能使用 chroot 命令。然而這通常是很有用的:

  1. 將特權分配給無特權的進程,例如 Web 服務或 DNS 服務。
  2. 建立測試環境。
  3. 不使程序或系統崩潰下,運行舊程序或 ABI 兼容的程序。
  4. 系統恢復。
  5. 重新安裝引導裝載程序,例如 Grub 或 Lilo。
  6. 密碼找回,重置一個已丟失的密碼等。

用途

chroot 命令 改變其當前目錄,並將根目錄變為指定目錄,然後如果提供了命令則運行命令,也可以運行一個用戶的互動式shell的副本(譯註:即bash等。)。請注意並不是每一個程序都可以使用 chroot 命令。

語法

基本語法如下:

chroot /path/to/new/root command

或者

chroot /path/to/new/root /path/to/server

或者

chroot [options] /path/to/new/root /path/to/server

chroot 命令實例

在這個例子中,建立了一個"迷你監獄"用來測試一個只有 ls 命令的 Bash shell。首先用 mkdir 命令設定好 jail "監獄" 路徑。

$ J=$HOME/jail

在 $J 內創建目錄:

$ mkdir -p $J
$ mkdir -p $J/{bin,lib64,lib}
$ cd $J

cp 命令將/bin/bash 和 /bin/ls 複製到 $J/bin/ 路徑下:

$ cp -v /bin/{bash,ls} $J/bin

將所需庫文件拷貝到$J。可以用 ldd 命令找到 bash 所依賴的共享庫。

$ ldd /bin/bash

輸出樣例:

linux-vdso.so.1 =>  (0x00007fff8d987000)
libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00000032f7a00000)
libdl.so.2 => /lib64/libdl.so.2 (0x00000032f6e00000)
libc.so.6 => /lib64/libc.so.6 (0x00000032f7200000)
/lib64/ld-linux-x86-64.so.2 (0x00000032f6a00000)

直接拷貝上面輸出中的庫文件到 $J 目錄:

$ cp -v /lib64/libtinfo.so.5 /lib64/libdl.so.2 /lib64/libc.so.6 /lib64/ld-linux-x86-64.so.2 $J/lib64/

輸出樣例:

`/lib64/libtinfo.so.5' -> `/home/vivek/jail/lib64/libtinfo.so.5'
`/lib64/libdl.so.2' -> `/home/vivek/jail/lib64/libdl.so.2'
`/lib64/libc.so.6' -> `/home/vivek/jail/lib64/libc.so.6'
`/lib64/ld-linux-x86-64.so.2' -> `/home/vivek/jail/lib64/ld-linux-x86-64.so.2'

複製 ls 命令所需的庫文件到 $J 目錄下。用 ldd 命令列印出 ls 命令依賴的共享庫:

$ ldd /bin/ls

輸出樣例:

linux-vdso.so.1 =>  (0x00007fff68dff000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00000032f8a00000)
librt.so.1 => /lib64/librt.so.1 (0x00000032f7a00000)
libcap.so.2 => /lib64/libcap.so.2 (0x00000032fda00000)
libacl.so.1 => /lib64/libacl.so.1 (0x00000032fbe00000)
libc.so.6 => /lib64/libc.so.6 (0x00000032f7200000)
libdl.so.2 => /lib64/libdl.so.2 (0x00000032f6e00000)
/lib64/ld-linux-x86-64.so.2 (0x00000032f6a00000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00000032f7600000)
libattr.so.1 => /lib64/libattr.so.1 (0x00000032f9600000)

你可以一個個的複製庫文件,為了更高效的作業,我們也可以使用bash shell 的循環指令實現:

list="$(ldd /bin/ls | egrep -o '/lib.*.[0-9]')"
for i in $list; do cp  -v "$i" "${J}${i}"; done

輸出樣例:

`/lib64/libselinux.so.1' -> `/home/vivek/jail/lib64/libselinux.so.1'
`/lib64/librt.so.1' -> `/home/vivek/jail/lib64/librt.so.1'
`/lib64/libcap.so.2' -> `/home/vivek/jail/lib64/libcap.so.2'
`/lib64/libacl.so.1' -> `/home/vivek/jail/lib64/libacl.so.1'
`/lib64/libc.so.6' -> `/home/vivek/jail/lib64/libc.so.6'
`/lib64/libdl.so.2' -> `/home/vivek/jail/lib64/libdl.so.2'
`/lib64/ld-linux-x86-64.so.2' -> `/home/vivek/jail/lib64/ld-linux-x86-64.so.2'
`/lib64/libpthread.so.0' -> `/home/vivek/jail/lib64/libpthread.so.0'
`/lib64/libattr.so.1' -> `/home/vivek/jail/lib64/libattr.so.1'

最後,chroot 到你的新jail:

$ sudo chroot $J /bin/bash

嘗試瀏覽一下 /etc 或 /var:

# ls /
# ls /etc/
# ls /var/

改變了根目錄的 bash 和 ls 程序現在被監禁在$HOME/$J這個特殊目錄中,而且不能再訪問外部的目錄樹,這個目錄可以看做是它們的"/"(root)目錄。如果配置正確的話,這會極大增強安全性。我通常用這種技術鎖定以下的應用程序。

  1. Apache - Red Hat / CentOS: Chroot Apache 2 Web Server
  2. Nginx - Linux nginx: Chroot (Jail) Setup
  3. Chroot Lighttpd web server on a Linux based system
  4. Chroot mail server.
  5. Chroot Bind DNS server 等等

如何退出 chroot 監禁呢?

鍵入 exit 即可

$ exit

上述會話樣例如下:

Animated gif 01: Linux / Unix: Bash Chroot ls Command Demo

Gif 動畫01: Linux / Unix: Bash Chroot ls 命令演示

查找服務是否存在於 chrooted 監禁內

你可以用下面兩個命令[輕鬆的找出 Postfix 郵件服務是否已經 chrooted]:

pid=$(pidof -s master)
ls -ld /proc/$pid/root

從基本Linux服務中輸出樣例:

lrwxrwxrwx. 1 root root 0 Mar  9 11:16 /proc/8613/root -> /

PID 8613 指向了 / (root) 也就是說這個程序的根目錄並沒有被改變或是被 chroot。這個方法非常的快速而又直接,不需要打開配置文件。下面是從已經 chroot 的 ngnix 服務中得到的另一個例子:

pid=$(pidof -s master)
ls -ld /proc/$pid/root

輸出樣例:

lrwxrwxrwx 1 nginx nginx 0 Mar  9 11:17 /proc/4233/root -> /nginxjail

程序的根目錄已經改為 /nginxjail。

用 chroot 救援和修復軟體RAID(磁碟陣列)系統

我先假設基於軟RAID的 Linux 系統無法正常啟動。所以你需要用Live CD或用基於網路的內核應急模式來修復系統。在這個例子中,我用了 Live Linux DVD/CD 啟動一個基於 RHEL 的系統,然後再 chroot 到 /dev/sda1 和 /或 /dev/md0 修復問題:

## 在 Live CD 的提示符下,鍵入以下命令來恢複數據。##
## /dev/sda1 系統主分區##
# 建立 jail 目錄
d=/chroot
mkdir $d

# 掛載 sda1 和其他所需目錄
mount /dev/sda1 $d
mount -o bind /dev $d/dev
mount -o bind /sys $d/sys
mount -o bind /dev/shm $d/dev/shm
mount -o bind /proc $d/proc

# 掛載軟體RAID /dev/md0
mount /dev/md0 $d/data

# Chroot 到我們新建的 jail 中。這將允許我們修復引導裝載系統(bootloader),或者在所有文件被/dev/null吞噬之前抓取數據。
chroot $d

#你能看見嗎?
ls
df

# 將文件置入安全路徑
rsync -avr /path/to/my_precious_data_dir user@safe.location.cyberciti.biz:/path/to/dest

# 退出 jail ,然後重啟或者根據個人所需格式化服務 ;)
exit
umount {dev,sys,[...],}
reboot

別急,還有更精彩的內容!

查看nixCraft下所有其他有關 chroot 命令的文章:

  1. Ubuntu: Mount Encrypted Home Directory (~/.private) From an Ubuntu Live CD
  2. Linux Configure rssh Chroot Jail To Lock Users To Their Home Directories Only
  3. Fix a dual boot MS-Windows XP/Vista/7/Server and Linux problem
  4. Restore Debian Linux Grub boot loader

在 Linux 和 類Unix 系統下 chroot 應用程序的注意事項

你應該在各種情況下都用 chroot 特性嗎?從上面的例子看出,這個程序是相當簡單的,但是最終可能出現幾種不同的問題而結束,例如:

1.在 jail 中缺失庫文件可能直接導致 jail 崩潰。 1.一些複雜的程序不好被 chroot。所以我建議你要麼嘗試真正的jail,例如FreeBSD提供的,要麼用虛擬化解決,比如Linux 下的 KVM。 1.正在運行某一程序的 jail 不能再運行其他程序,不能更改任何文件,也不能"假設"另一個用戶的身份。放寬這些限制,會降低你的安全性,請根據具體情況 chroot。

還要注意:

  1. 當你升級本地程序時,不要忘記升級已 chroot 的程序。
  2. 並非所有程序能夠或者應該被 chroot。
  3. 任何需要 root 許可權操作的程序,對其 chroot 是沒意義的。因為通常 root 用戶都能脫離 chroot。
  4. Chroot 並不一個高招。更多的可以學習如何保護和加強系統的各個部分

choort 部分命令選項

取自 man 幫助頁面chroot(8):

  --userspec=USER:GROUP  使用指定的 用戶 和 組 (ID 或 名稱)
  --groups=G_LIST        指定補充組 g1,g2,..,gN 
      --help     顯示幫助並退出
      --version  顯示版本信息並退出

參見

via: http://www.cyberciti.biz/faq/unix-linux-chroot-command-examples-usage-syntax/

譯者:Luoxcat 校對:wxy

本文由 LCTT 原創翻譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國