红联Linux门户
Linux帮助

Linux/Unix:chroot命令实例讲解

发布时间:2014-05-31 11:56:20来源:红联作者:velcbo
来源:Linux中国

我是一个刚接触 Linux 和 Unix 的新手。我该如何改变一个命令的根目录?我要怎样改变一个进程的根目录呢,比如用 chroot 命令将web服务与文件系统隔离?我要如何使用 chroot 恢复密码或修复基于 Linux/Unix的受损坏的环境?

在 Linux和类 Unix 系统下每一个进程/命令的当前工作目录称之为进程/命令的根目录(译注:译者以为此处有误,实际上没有进行过chroot的进程,其根目录是系统的根目录,而不是其工作目录)。你可以使用 chroot 命令改变一个命令的根目录,这最终将会改变当前运行的进程及其子进程的根目录。

如果一个进程/命令运行在一个不能访问外部根目录文件的已修改环境中。这种修改环境通常被称为"监禁目录"(jail)或是"chroot 监禁"。只有特权进程和根用户才能使用 chroot 命令。然而这通常是很有用的:
1.将特权分配给无特权的进程,例如 Web 服务或 DNS 服务。
2.建立测试环境。
3.不使程序或系统崩溃下,运行旧程序或 ABI 兼容的程序。
4.系统恢复。
5.重新安装引导装载程序,例如 Grub 或 Lilo。
6.密码找回,重置一个已丢失的密码等。

用途

chroot 命令 改变其当前目录,并将根目录变为指定目录,然后如果提供了命令则运行命令,也可以运行一个用户的交互式shell的副本(译注:即bash等。)。请注意并不是每一个程序都可以使用 chroot 命令。

语法

基本语法如下:
1.chroot /path/to/new/root command

或者
1.chroot /path/to/new/root /path/to/server

或者
1.chroot [options]/path/to/new/root /path/to/server

chroot 命令实例

在这个例子中,建立了一个"迷你监狱"用来测试一个只有 ls 命令的 Bash shell。首先用 mkdir 命令设定好 jail "监狱" 路径。
1.$ J=$HOME/jail

在 $J 内创建目录:
1.$ mkdir -p $J
2.$ mkdir -p $J/{bin,lib64,lib}
3.$ cd $J

用cp 命令将/bin/bash 和 /bin/ls 复制到 $J/bin/ 路径下:
1.$ cp -v /bin/{bash,ls} $J/bin

将所需库文件拷贝到$J。可以用 ldd 命令找到 bash 所依赖的共享库。
1.$ ldd /bin/bash

输出样例:
1.linux-vdso.so.1=>(0x00007fff8d987000)
2.libtinfo.so.5=>/lib64/libtinfo.so.5(0x00000032f7a00000)
3.libdl.so.2=>/lib64/libdl.so.2(0x00000032f6e00000)
4.libc.so.6=>/lib64/libc.so.6(0x00000032f7200000)
5./lib64/ld-linux-x86-64.so.2(0x00000032f6a00000)

直接拷贝上面输出中的库文件到 $J 目录:
1.$ cp -v /lib64/libtinfo.so.5/lib64/libdl.so.2/lib64/libc.so.6/lib64/ld-linux-x86-64.so.2 $J/lib64/

输出样例:
1.`/lib64/libtinfo.so.5' -> `/home/vivek/jail/lib64/libtinfo.so.5'
2.`/lib64/libdl.so.2'->`/home/vivek/jail/lib64/libdl.so.2'
3.`/lib64/libc.so.6' -> `/home/vivek/jail/lib64/libc.so.6'
4.`/lib64/ld-linux-x86-64.so.2' -> `/home/vivek/jail/lib64/ld-linux-x86-64.so.2'

复制 ls 命令所需的库文件到 $J 目录下。用 ldd 命令打印出 ls 命令依赖的共享库:
1.$ ldd /bin/ls

输出样例:
1.linux-vdso.so.1=>(0x00007fff68dff000)
2.libselinux.so.1=>/lib64/libselinux.so.1(0x00000032f8a00000)
3.librt.so.1=>/lib64/librt.so.1(0x00000032f7a00000)
4.libcap.so.2=>/lib64/libcap.so.2(0x00000032fda00000)
5.libacl.so.1=>/lib64/libacl.so.1(0x00000032fbe00000)
6.libc.so.6=>/lib64/libc.so.6(0x00000032f7200000)
7.libdl.so.2=>/lib64/libdl.so.2(0x00000032f6e00000)
8./lib64/ld-linux-x86-64.so.2(0x00000032f6a00000)
9.libpthread.so.0=>/lib64/libpthread.so.0(0x00000032f7600000)
10.libattr.so.1=>/lib64/libattr.so.1(0x00000032f9600000)

你可以一个个的复制库文件,为了更高效的作业,我们也可以使用bash shell 的循环指令实现:
1.list="$(ldd /bin/ls | egrep -o '/lib.*\.[0-9]')"
2.for i in $list;do cp -v "$i""${J}${i}";done

输出样例:
1.`/lib64/libselinux.so.1' -> `/home/vivek/jail/lib64/libselinux.so.1'
2.`/lib64/librt.so.1'->`/home/vivek/jail/lib64/librt.so.1'
3.`/lib64/libcap.so.2' -> `/home/vivek/jail/lib64/libcap.so.2'
4.`/lib64/libacl.so.1' -> `/home/vivek/jail/lib64/libacl.so.1'
5.`/lib64/libc.so.6'->`/home/vivek/jail/lib64/libc.so.6'
6.`/lib64/libdl.so.2' -> `/home/vivek/jail/lib64/libdl.so.2'
7.`/lib64/ld-linux-x86-64.so.2' -> `/home/vivek/jail/lib64/ld-linux-x86-64.so.2'
8.`/lib64/libpthread.so.0'->`/home/vivek/jail/lib64/libpthread.so.0'
9.`/lib64/libattr.so.1' -> `/home/vivek/jail/lib64/libattr.so.1'

最后,chroot 到你的新jail:
1.$ sudo chroot $J /bin/bash

尝试浏览一下 /etc 或 /var:
1.# ls /
2.# ls /etc/
3.# 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 即可
1.$ exit

Gif 动画01: Linux / Unix: Bash Chroot ls 命令演示

查找服务是否存在于 chrooted 监禁内

你可以用下面两个命令[轻松的找出 Postfix 邮件服务是否已经 chrooted]:
1.pid=$(pidof -s master)
2.ls -ld /proc/$pid/root

从基本Linux服务中输出样例:
1.lrwxrwxrwx.1 root root 0Mar911:16/proc/8613/root ->/

PID 8613 指向了 / (root) 也就是说这个程序的根目录并没有被改变或是被 chroot。这个方法非常的快速而又直接,不需要打开配置文件。下面是从已经 chroot 的 ngnix 服务中得到的另一个例子:
1.pid=$(pidof -s master)
2.ls -ld /proc/$pid/root

输出样例:
1.lrwxrwxrwx 1 nginx nginx 0Mar911:17/proc/4233/root ->/nginxjail

程序的根目录已经改为 /nginxjail。
文章评论

共有 0 条评论