文章目录
- 一、背景
- 二、语法
- 三、案例
- 3.1 命令
- 3.2 系统调用
- 3.3 查找服务是否存在于 chrooted 监禁内
- 四、注意事项
chroot 用来在指定根目录运行命令(即指定 / 的位置),不可操作指定目录之外的地方。其是一种非常简单的资源隔离化操作,类似 Linux 的 Mount Namespace,可实现模拟版的 docker。
一、背景
其好处如下:
- 增强系统安全性,限制用户权利
经 chroot 之后,在新根下将访问不到旧系统的根目录结构和文件,这样就增强了系统的安全性;这个一般是在登录 (login) 前使用 chroot,以此达到用户不能访问一些特定的文件; - 建立一个与原系统隔离的系统目录结构,方便用户的开发;
使用 chroot 后,系统读取的是新根下的目录和文件,这是一个与原系统根下文件不相关的目录结构;在这个新的环境中,可以用来测试软件的静态编译以及一些与系统不相关的独立开发; - 切换系统的根目录位置,引导 Linux 系统启动以及急救系统等;
chroot 的作用就是切换系统的根位置,而这个作用最为明显的是在系统初始引导磁盘的处理过程中使用,从初始 RAM 磁盘 (initrd) 切换系统的根位置并执行真正的 init;另外,当系统出现一些问题时,我们也可以使用 chroot 来切换到一个临时的系统;
如果一个进程/命令运行在一个不能访问外部根目录文件的已修改环境中,这种修改环境通常被称为监禁目录(jail)或是chroot 监禁,只有特权进程和根用户才能使用 chroot 命令;这通常是很有用的:
- 将特权分配给无特权的进程,例如 Web 服务或 DNS 服务;
- 建立测试环境;
- 不使程序或系统崩溃下,运行旧程序或 ABI 兼容的程序;
- 系统恢复;
- 重新安装引导装载程序,例如 Grub 或 Lilo;
- 密码找回,重置一个已丢失的密码等;
二、语法
在现今的 Linux 上,chroot 既是一个 CLI 工具(chroot(8)),又是一个系统调用(chroot(2));命令语法如下:
chroot [OPTION] NEWROOT [COMMAND [ARGS]...]
# 例如:
chroot /path/to/new/root command
# 或
chroot /path/to/new/root /path/to/server
# 或
chroot [options] /path/to/new/root /path/to/server
# 选项
--userspec=USER:GROUP # 使用指定的 用户 和 组 (ID 或 名称)
--groups=G_LIST # 指定补充组 g1,g2,..,gN
--help # 显示帮助并退出
--version # 显示版本信息并退出
- 目录(dir):指定新的根目录;
- 指令(command):指定要执行的指令;
COMMAND 指的是切换 root 目录后需要执行的命令,如果没有指定,默认是 ${SHELL} -i,大部分情况是 /bin/bash;
此外,执行 chroot(8) 需要使用 root 权限;例如,简单地,我们可以这样使用:sudo chroot /path/to/new/root /bin/bash
三、案例
3.1 命令
# 创建对应的新的根目录:
$ J=$HOME/jail
$ mkdir -p $J
$ mkdir -p $J/{bin,lib/x86_64-linux-gnu,lib64,etc,var}
# 将几个必要的命令工具 copy 到 bin/ 下:
$ sudo cp -vf /bin/{bash,ls} $J/bin
# 将步骤 2 中可执行命令依赖的动态库 copy 到 jail/ 下:
$ list=`ldd /bin/ls | egrep -o '/lib.*\.[0-9]'`
$ for i in $list; do sudo cp -vf $i $J/$i; done
$ list=`ldd /bin/bash | egrep -o '/lib.*\.[0-9]'`
$ for i in $list; do sudo cp $i -vf $J/$i; done
# 执行 chroot 命令:
$ sudo chroot $J /bin/bash
bash-4.3# ls
bin etc lib lib64 var
bash-4.3# cd /
bash-4.3# ls
bin etc lib lib64 var
bash-4.3# cd ..
bash-4.3# ls
bin etc lib lib64 var
# 可以看到无论我们如何改变目录,其根目录都被隔离在 $J 中;
# 执行 exit 命令可退出这一环境;
3.2 系统调用
#include <unistd.h>
int chroot(const char *path);
#include <stdio.h>
#include <error.h>
#include <unistd.h>
#include <stdlib.h>
char *const path = "/root/jail"; // 如上文实验所述目录
char *const argv[] = {"/bin/bash", NULL};
int main(void) {
if (chroot(path) != 0) {
perror("chroot error");
exit(1);
}
chdir("/"); // 忽略返回值
execvp("/bin/bash", argv); // 忽略返回值
return 0;
}
编译和运行代码:
$ gcc test_chroot.c -o test_chroot
$ ./test_chroot # 非 root 用户执行命令
chroot error: Operation not permitted
$ sudo ./test_chroot
bash-4.3#
3.3 查找服务是否存在于 chrooted 监禁内
可通过查看进程的 /proc/<pid>/root
来查看对应进程是否处于 chroot 监禁中;如上文,其 chroot 下 bash 的执行进程为 15768,则有:
$ sudo ls -ld /proc/15768/root
lrwxrwxrwx 1 root root 0 Apr 17 22:47 /proc/15768/root -> /root/jail
可见其根目录已经被修改为 /root/jail;
四、注意事项
从上面的例子看出,chroot 是相当简单的,但是最终可能出现几种不同的问题而结束,例如:
- 在 jail 中缺失库文件可能直接导致 jail 崩溃;
- 一些复杂的程序不好被 chroot;
- 正在运行某一程序的 jail 不能再运行其他程序,不能更改任何文件,也不能”假设”另一个用户的身份;放宽这些限制,会降低你的安全性,请根据具体情况使用chroot;
因此要么尝试真正的jail,例如:FreeBSD提供的,要么用虚拟化解决,比如Linux 下的 KVM;还要注意:
- 当你升级本地程序时,不要忘记升级已 chroot 的程序;
- 并非所有程序能够或者应该被 chroot;
- 任何需要 root 权限操作的程序,对其 chroot 是没意义的,因为通常 root 用户都能脱离 chroot;
- Chroot 并不一个高招;更多的可以学习如何保护和加强系统的各个部分;
参考:案例
参考:参数