部署背景:

最近有一客户提出这么个需求,要在公司信息机房部署一台登录跳板服务器,让以后用户访问机房内的服务器都必须先登录这台跳板服务器,然后再ssh到其他服务器。具体要求为:
1)安全最大化,普通用户登陆到这台跳板服务器后只能执行ssh,ls等有限的基础命令。
2)把普通用户锁定在特定的目录下,这样即使被hack,也不会影响其他用户。
需求分析:
根据客户所提要求,那么就必须搭建一openssh server,利用ssh+chroot功能来实现。而在openssh 4.8p1以前的版本,要支持chroot,必须使用第三方的修改。但从openssh 4.8p1以后,chroot功能已经被内置了,为此可以直接在服务器系统(CentOS 5.5)上搭建。
系统平台:
CentOS 5.5 i386
openssh 5.6p1
zlib-1.2.5
openssl-1.0.0c  
        

CentOS 5.5中自带的openssh是4.3p2版本的,必须升级到4.8p1以后,我选择升级到目前最高版本5.6p1。具体升级到openssh 5.6p1的方法可以参考我这篇文章:

根据sshd_config的man中所述,实现chroot功能需要配置"ChrootDirectory"这个参数。

ChrootDirectory:定义了用户通过认证以后的chroot目录,此目录及其所有子目录的属主必须是root,且这些目录只有root帐号可以进行写操作,其他任何组和帐号都不可写。chroot以后,sshd会将用户的工作目录转到chroot目录中用户自己的主目录。如果ChrootDirectory定义的目录下没有相应的/home/username目录,则会直接转到chroot的/目录下。

下边是详细的配置过程:
1.新增用户ait(不创建其缺省主目录)

[root@server ~]# useradd -M ait
[root@server ~]# passwd ait 
2.修改/etc/ssh/sshd_config文件
[root@server ~]# vi /etc/ssh/sshd_config    #增加以下内容
Match User ait
ChrootDirectory /var/chroot 
注:这里我指定chroot目录是/var/chroot
[root@server ~]# /etc/init.d/sshd restart    #重启SSH服务
3.搭建基本的chroot环境
小贴士:
一个最基本的chroot环境至少有一个shell(例如sh,bash)和一些必要的系统设备文件(例如/dev/null,/dev/zero),如果要允许用户执行一些命令,那么还要准备相应的命令可执行文件和命令依赖的库文件。

[root@server ~]# mkdir /var/chroot

[root@server ~]# cd /var/chroot
[root@server chroot]# mkdir {bin,dev,lib,lib64,etc,home}
[root@server chroot]# mknod dev/null c 1 3
[root@server chroot]# mknod dev/zero c 1 5
#可选,这两个文件ssh命令需要,如缺少会报告:PRNG is not seeded
[root@server chroot]# mknod dev/random c 1 8
[root@server chroot]# mknod dev/urandom c 1 9
#可选,ssh命令需要,如缺少会报告:Host key verification failed
[root@server chroot]# mknod dev/tty c 5 0 
#修改/var/chroot及其子目录的属主,并修改权限
[root@server chroot]# chown -R root.root /var/chroot
[root@server chroot]# chmod -R 755 /var/chroot
#允许用户写这些设备文件,不可写会有些命令报错
[root@server chroot]# chmod 0666 dev/{null,zero,tty}

然后将要允许用户执行的可执行文件和依赖的库文件复制到相应位置。例如必须给用户一个可用的shell,则我们一般用/bin/bash,那么执行ldd命令查看相关信息:

[root@server chroot]# ldd /bin/bash
       
linux-gate.so.1 =>  (0x00572000)
        libtermcap.so.2 => /lib/libtermcap.so.2 (0x0388b000)
        libdl.so.2 => /lib/libdl.so.2 (0x00839000)
        libc.so.6 => /lib/libc.so.6 (0x006b3000)
        /lib/ld-linux.so.2 (0x0068f000)
说明/bin/bash要正确执行,依赖于如下几个文件:
/lib/libtermcap.so.2
/lib/libdl.so.2
/lib/libc.so.6
/lib/ld-linux.so.2
那么我们必须把/bin/bash和相应的库文件复制到对应的位置。
[root@server chroot]# cp -p /bin/bash /var/chroot/bin
[root@server chroot]# cp -p /lib/libtermcap.so.2 /var/chroot/lib
[root@server chroot]# cp -p /lib/libdl.so.2 /var/chroot/lib
[root@server chroot]# cp -p /lib/libc.so.6 /var/chroot/lib
[root@server chroot]# cp -p /lib/ld-linux.so.2 /var/chroot/lib
类似上边这样,对每个想要允许用户执行的文件都如此操作即可。
这里只是为了说明下具体过程,实际应用时肯定要用脚本来执行的。我从一网站抄来一个脚本(这里我命名为shell.sh),略加修改,内容如下:

# /bin/bash

# 要允许执行的文件列表
cmdlist="/bin/bash /bin/ls /bin/cp /bin/mkdir /bin/mv /bin/rm /bin/rmdir"
# chroot路径
chroot_path="/var/chroot"

# 判断依赖的库文件

lib_1=`ldd $cmdlist | awk '{ print $1 }' | grep "/lib" | sort | uniq`
lib_2=`ldd $cmdlist | awk '{ print $3 }' | grep "/lib" | sort | uniq`

# 复制命令文件

for i in $cmdlist
do
    cp -a $i $chroot_path/bin/ && echo "$i done"
done

# 复制依赖的库文件(因为是i386,所以是lib,如果是x86_64,则是lib64,)

for j in $lib_1
do
    cp -f $j $chroot_path/lib/ && echo "$j done"
done

for k in $lib_2

do
    cp -f $k $chroot_path/lib/ && echo "$k done"
done
 

[root@server chroot]# ll
总计 28
drwxr-xr-x 2 root root 4096 02-25 05:47 bin
drwxr-xr-x 2 root root 4096 02-25 05:36 dev
drwxr-xr-x 2 root root 4096 02-25 05:35 etc
drwxr-xr-x 2 root root 4096 02-25 05:35 home
drwxr-xr-x 2 root root 4096 02-25 05:51 lib
drwxr-xr-x 2 root root 4096 02-25 05:35 lib64
-rw-r--r-- 1 root root  665 02-25 06:50 shell.sh
[root@server chroot]# chmod 755 shell.sh
[root@server chroot]# ./shell.sh
/bin/bash done
/bin/ls done
/bin/cp done
/bin/mkdir done
/bin/mv done
/bin/rm done
/bin/rmdir done
/lib/ld-linux.so.2 done
/lib/libacl.so.1 done
/lib/libattr.so.1 done
/lib/libc.so.6 done
/lib/libdl.so.2 done
/lib/libpthread.so.0 done
/lib/librt.so.1 done
/lib/libselinux.so.1 done
/lib/libsepol.so.1 done
/lib/libtermcap.so.2 done

复制/etc/passwd和/etc/group文件到/var/chroot/etc中,并删除用户自己和root以外的所有帐号。如果没有这两个文件,用户登录以后会报“I have no name!”
[root@server chroot]# cp -p /etc/passwd /var/chroot/etc/
[root@server chroot]# cp -p /etc/group /var/chroot/etc/
4.建立chroot目录中的用户主目录
[root@server chroot]# mkdir /var/chroot/home/ait 
[root@server chroot]# chown -R ait /var/chroot/home/ait
[root@server chroot]# chmod 700 /var/chroot/home/ait
OK,经过以上的配置,现在就可以进行测试了。
用ait帐号ssh登录到系统中,看到ait是被限制在了自己的宿主目录/home/ait下了。测试
执行一些命令,发现只有刚才复制过来的命令可以执行,其他全都不可以。
-bash-3.2$ pwd
/home/ait
-bash-3.2$ ls
-bash-3.2$ mkdir ait_test
-bash-3.2$ ls
ait_test
-bash-3.2$ ll
-bash: ll: command not found