正常的ssh用户可以直接登录到服务器上,可以浏览服务器的大多数文件,特别是像PHP脚本,一般都不加密,数据库的用户名和密码都是明文的,这会给系统安全造成威胁。
但是网上的资料相对有些乱,大多数文章都直接给出命令,没有给出解释,初学的时候,还要看手册,读源码。本文主要对几个重要的参数做一下解释。
实现目的: 1)test组里面的用户,通过ssh登录到系统后,只能看到自己home里面的内容;
2)可以通过sftp下载和上传文件,包括winsftp。
3可以通过命令行进行文件的复制、删除,移动
4)以下内容,以用户test为例,home目录对应的是/home/test/
重点环节说明: 1)ssh的chroot,最主要的一个配置语句是:ChrootDirectory,后面有两个常用的参数,%h代表是用户的home,一般是/home/用户名。
2)最容易出错的地方就是权限,ssh的chroot要求的文件夹属主必须是root,权限要求是g-w,o-w,也就是组和其他用户都没有写权限,在源代码中,这个判断是用的&&022来判断,所以一般情况下,可以用755或555来设置权限。
3)网上的资料,很多都加入了:ForceCommand internal-sftp,这个参数将导致只能使用sftp,不能用putty或其他系统的ssh命令来登录系统了,这是一定要注意的问题。
4)在chroot后,系统会自动进入home,如果chroot放到用户的home中,最好再建一级home/test,也就是宿主系统中,要有两级home:/home/test/home/test,否则登录或使用scp的时候会出问题,winsftp也不会自动进入到相应的目录。
5)在chroot后,以后所有的文件要以这个目录为根目录了,其中包括最重要的shell以及相应的so文件,所以还要建议一个微型的系统,其中包括三个目录:bin、lib、libexec。其中lib目录下的so文件,主要是ls,cp,mv使用。
sshd主要配置:# vi /etc/ssh/sshd_config
……
Subsystem sftp internal-sftp
Match Group test
ChrootDirectory %h
# ForceCommand internal-sftp
……
你会发现配置非常简单,一共四行还注释掉一行。
先看第一行:Subsystem,这个指定了运行sftp的程序,默认的是/usr/libexec/sftp-server,这个相对于内置的sftp来说,功能比较多,也可以使用scp,但是需要的链接库也多,可以见本文后面的资料,如果你想希望功能多并且有耐心复制对应链接库的话,也可以把这一句注释掉。
第二句定义了一个范围,可以是用户,也可以是IP,这里使用了一个test组,表示仅对test组的用户实行chroot。如果没有这句的话,就连root也限制到/root了,遇到问题你主好亲自跑机房接上键盘显示器操作了。
第三句是个重点,这句就是负责chroot的,没有这句就不chroot了……废话!
第四句是让ssh自动执行一个命令,而忽略掉其他配置文件中指定的程序,也就是说,如果你在这地方指定了一个程序,那么就不再执行其他的命令了,包括ssh本身!这地方指定了运行sftp,那么除了sftp外,你不会得到任何东西,包括sh也没有——最后的结果就是:你只能使用sftp上传下载文件,其他的就别想了(当然sftp中也可以有简单的命令)。
文件路径设置:
在/home/test里,要有以下文件和文件夹:
bin
-sh
-cp
-ls
-mv
lib
-libc.so.7
-libedit.so.7
-libncurses.so.8
-libutil.so.9
libexec
-ld-elf.so.1
-ld-elf32.so.1
home/test
然后设置属主和权限:
# chown -R root /home/test
# chown -R test:test /home/test/home/test
# chmod -R 755 /home/test
其中第二句设置test用户的home,以便test可以对该文件夹下的文件进行操作。
测试:
可以分别使用ssh和sftp进行测试,注意如果使用了internal-sftp,scp命令不能用,会提示找不到scp命令,只能使用sftp来进行文件传输。
附一,sftp-server需要的链接库:
# ldd /usr/libexec/sftp-server
/usr/libexec/sftp-server:
libssh.so.5 => /usr/lib/private/libssh.so.5 (0x800825000)
libcrypt.so.5 => /lib/libcrypt.so.5 (0x800ab2000)
libcrypto.so.7 => /lib/libcrypto.so.7 (0x800cd2000)
libz.so.6 => /lib/libz.so.6 (0x8010c5000)
libc.so.7 => /lib/libc.so.7 (0x8012db000)
libldns.so.5 => /usr/lib/private/libldns.so.5 (0x801684000)
libgssapi.so.10 => /usr/lib/libgssapi.so.10 (0x8018e0000)
libkrb5.so.11 => /usr/lib/libkrb5.so.11 (0x801ae9000)
libhx509.so.11 => /usr/lib/libhx509.so.11 (0x801d61000)
libasn1.so.11 => /usr/lib/libasn1.so.11 (0x801fab000)
libcom_err.so.5 => /usr/lib/libcom_err.so.5 (0x802248000)
libmd.so.6 => /lib/libmd.so.6 (0x80244a000)
libroken.so.11 => /usr/lib/libroken.so.11 (0x80265a000)
libwind.so.11 => /usr/lib/libwind.so.11 (0x80286c000)
libheimbase.so.11 => /usr/lib/libheimbase.so.11 (0x802a94000)
libheimipcc.so.11 => /usr/lib/private/libheimipcc.so.11 (0x802c98000)
libthr.so.3 => /lib/libthr.so.3 (0x802e9a000)
附二,ssh的chroot代码,关键是权限和属主的配置:
/usr/src/crypto/openssh/session.c,1451行:
/*
* Descend the path, checking that each component is a
* root-owned directory with strict permissions.
*/
for (cp = path; cp != NULL;) {
if ((cp = strchr(cp, '/')) == NULL)
strlcpy(component, path, sizeof(component));
else {
cp++;
memcpy(component, path, cp - path);
component[cp - path] = '\0';
}
debug3("%s: checking '%s'", __func__, component);
if (stat(component, &st) != 0)
fatal("%s: stat(\"%s\"): %s", __func__,
component, strerror(errno));
if (st.st_uid != 0 || (st.st_mode & 022) != 0)
fatal("bad ownership or modes for chroot "
"directory %s\"%s\"",
cp == NULL ? "" : "component ", component);
if (!S_ISDIR(st.st_mode))
fatal("chroot path %s\"%s\" is not a directory",
cp == NULL ? "" : "component ", component);
}