整理自:http://blog.chinaunix.net/uid-22101889-id-3167454.html

注意:请谨慎使用,到现在为止,使用了,我还没找到改回去的方法。

1.     问题

第一、很多大公司的服务器都不允许直接登录,而是通过一个跳板机才能登录过去。在跳板机中,通常只能执行几个少数命令(如SSH),而其他命令是不允许执行的,那么怎样才能实现这个功能呢?

第二、一些小公司,由于服务器比较少,不需要什么跳板机之类的说法,公司的开发运维人员加起来也就那么十几二十人,通常大家都知道root密码,所有人都是直接root登录上去,但是有时有人由于失误,把什么服务弄挂了,这时是肯定抓不到人的,因为所有人都知道密码,那么怎样才能知道谁都执行过什么命令呢?或者干脆只让他们执行少数允许的命令呢?

2.     解答

这两个需求,看似不同,其实原理都相同,只要在用户与shell之间加入个检测机制就可以了,您可以去网上找些开源软件,但是如果您嫌那些软件太复杂,又不能完全满足您的需求,那么就完全可以像我这样,自己用shell写一个简易的模拟终端。

在模拟终端里,你需要做的,就是向用户提供一个看起来像是真的但实际不是真的、的虚拟终端。而你需要做的,就是读取用户输入的命令,并在替用户执行之前进行记录,这样就实现了上面第二个需求中的记录功能。如果你不想让用户执行哪些命令,那么仅仅echo一句“Permission denied”就可以将用户阻挡在真正的shell大门之外了。

如果用户要执行的命令是你允许的,那么在执行之前,记录个log就行了。如果将这个虚拟终端设置成只能执行ssh这个命令,那么不就实现了第一个问题中的跳板机的功能了吗。

所以以上两个需求,都可以总结为一个需求,那就是:拦截用户的输入,在用户与shell之间加一道门,而脚本的功能,就是根据用户不同的输入采取不同的动作,脚本的长短也就跟需要的命令的多少有关,需要的命令越多,脚本需要判断的就越多,脚本也就越长,但实际并不需要为每个命令都写一个action,只要为每个种类的写一个action就行了,比如:最简单的情形,没有任何参数的命令,如:pwd等,稍复杂些的,如touch、ls等命令,这时需要处理参数,再复杂些的,如rm、mv等命令,不只需要处理参数,还要避免用户误删数据,而以上所有命令,都需要判断用户是否有权限等等,脚本的复杂程度,完全取决于你的需求了,下面的虚拟终端内,实现了用户可以执行cd ls rm mv download upload pwd passwd等等几个命令,如果您只实现ssh命令,那就是跳板机了。

3.     实现脚本

脚本主要技术:

1.echo 显色

2.trap处理信号

3.stty,dd关闭回显并读取一个字符

4.读取密码

5.<<EOF行内输入

6.命令使用日志记录

7.将用户固定在某目录下

8.执行固定的命令

# ~/virtual terminal

# 将此文件放在/etc/profile.d/目录下,并添加可执行权限。

# 如: -rwxr-xr-x 1 root root 7340 Oct 23 18:12 /etc/profile.d/vt.sh

############################################################################

# 本行直至文件末尾的代码,用于实现用户登录使用的虚拟终端

# 请勿删除或更改

# 如有疑问、请联系维护负责人: xiaoxi227(QQ451914397)

############################################################################

# 该文件存放用户名和密码 文件格式为==> 用户名:密码 (每行一个用户)

passwd_file=/etc/user.password

function red()

{

# 以红色显示

echo -e "\033[31;40m$*\033[0m\n"

}

function green()

{

# 以绿色显示

echo -e "\033[32;40m$*\033[0m\n"

}

# 忽略所有信号,以免用户使用Ctrl+C或者Ctrl+Z等操作退出Virtual Terminal(VT)

for signal in `seq 1 64`

do

trap : $signal &> /dev/null

done

clear

function getchar() # 关闭回显,用于输入密码

{

stty cbreak -echo

dd if=/dev/tty bs=1 count=1 2>/dev/null

stty -cbreak echo

}

###############################################################################

green "登录成功。" # 用户通过unix pam认证以后显示“登陆成功”,随后进行身份验证

while :

do

read -p "请输入用户名:" username

echo -n "请输入密码: "

while :

do

ret=$(getchar)

if [ x"$ret" = x"" ];then

echo

break

fi

passwd="$passwd$ret"

echo -n '*'

done

correct_passwd=$(gawk -F: "/$username/{ print \$2 }" $passwd_file)

if [ -z "$username" -o -z "$passwd" ];then

clear

red "用户名或密码不能为空"

continue

fi

input_password=$(echo $passwd | md5sum | gawk '{ print $1 }')

if [ x"$input_password" != x"$correct_passwd" ];then

clear

red "用户名或密码错误,请重新输入"

else

break

fi

done

title="

##################################################################################

############################## Virtual Terminal ##################################

##################################################################################

 "

cat | more <<EOF

$title

使用说明:

欢迎使用虚拟终端(Virtual Terminal,以下简称VT).

在此模式下,用户只能执行少量被允许执行的命令,其他命令将会被拒绝执行。

本模式支持的命令及功能如下:

cd <DIR> 进入<DIR>目录,前提是用户有进入该目录的权限。

ls       功能和系统中的ls命令相同,但是只能显示有读取权限的目录下的文件。

本命令支持参数,系统中ls命令可以使用的选项都可以在VT模式下使用。

mv <SRC> <DST>     将文件<SRC>移至<DST>,如果路径相同则含义为改名。

用户必须同时对<SRC>和<DST>有读写权限。

rm <FILE>     将<FILE>从系统中删除。

当<FILE>是目录时,会递归删除所有子目录及子目录下的文件。

pwd      显示当前的工作路径。

download <FILELIST>

将<FILELIST>下载至本机

运行此命令时,用户使用的终端必须支持ZModem协议,如SecureCRT等。

下载多个文件需将各文件用空格隔开。

如果下载的文件是目录,系统会自动将其打包后再下载。

upload        向系统中上传文件,运行此命令后,终端会弹出一个对话框,按提示选择文件上传即可。

注意:运行此命令时,用户使用的终端必须支持ZModem协议,如SecureCRT等。

passwd        修改自己的登录口令

如需其他功能,请与管理员联系,VT维护负责人:xiaoxi227(QQ:451914397)

$title

EOF

echo -e "当前登录用户是:\033[32;40m$username\033[0m"

logfile=/var/log/vt.log

function run()     # 本函数用于替用户执行命令,并记录log

{

local command="$@"

{

echo -n -e "\033[32;40m$username\033[0m\033[7G -- "

echo -n -e "\033[31;40m`date '+%Y-%m-%d %H:%M:%S'` -- \033[0m$command"

echo

} | sed 's/sz/download/g;s/rz/upload/g' >> $logfile

$command

}

# 通常开发人员需要部署的程序都在同一目录下,所以为其指定根目录,限定仅在该目录有权限。

ROOT_DIR=/usr # 本例中用/usr目录测试

cd $ROOT_DIR  # 进入用户的“根目录”

while :  # 死循环读取用户输入

do

# 这里的主机名写成“localhost”写死了,您也可以写成$HOSTNAME,这样就会显示主机名了。

read -e -p "[${username}localhost ${PWD##*/}]$ " REPLY

# 如上语句模拟产生shell提示符(其实是假的)

# 分隔命令和参数

COMMAND=$(echo $REPLY | gawk '{ print $1 }')

OPTION=$(echo $REPLY | sed -r "s/^$COMMAND//g;s/^[[:space:]]+//g")

# 判断要执行的命令是什么,根据不同命令设置不同的动作。如下是本例中实现的几个命令:

case $COMMAND in

cd|ls)

# 当执行cd命令且参数为空时,默认cd到根目录,行为要与系统中的cd命令保持一致。

if [ x"$OPTION" = x"" -a x"$COMMAND" = x"cd" ];then

cd $ROOT_DIR

continue

fi

# 判断参数的第一个字符是不是"/",如果不是,说明想要cd或ls的是相对路径。

# 也就是当前目录下的文件活目录,此时用户是有权限的。

first_char=${OPTION:0:1}

if [ x"$first_char" != x"/" ];then

run $REPLY

else

# 如果是绝对路径,那么判断路径是否以$ROOT_DIR开头,若否则提示用户没权限。

echo $OPTION | grep -q ^$ROOT_DIR

if [ $? -eq 0 ];then

run $REPLY

else

echo "$COMMAND: Permission denied." >&2

fi

fi

;;

# 其他支持的参数:rm、mv、pwd、passwd等等,就不写注释了,自己理解下吧。

rm|mv)

if [ x"$COMMAND" = x"rm" ];then RM='-rf';else RM='';fi

run='ok'

for _file in $OPTION

do

echo $_file | grep -q '-'

[ $? -eq 0 ] && {

red "本命令在VT模式下不支持参数";

continue;

}

echo $_file | grep -q ^$ROOT_DIR

ret=$?

first_char=${_file:0:1}

if [ x"$first_char" = x"/" ];then

if [ $ret -ne 0 ];then

run='not ok'

fi

fi

done

if [ x"$run" = x"ok" ];then

run $COMMAND $RM $OPTION

else

echo "$COMMAND: Permission denied." >&2

fi

;;

pwd)

run $REPLY

;;

upload)

run rz

;;

download)

for _file in $OPTION

do

if [ ! -d $_file ];then

echo "开始下载文件:$_file"

run sz $_file

[ $? -eq 0 ] && green "下载完成" || red "下载失败"

else

echo "${_file}是目录,正在将其打包成${_file}.tar"

tar -cf ${_file}.tar $_file

[ $? -eq 0 ] && green "打包完成,开始下载${_file}.tar" \

|| { red "打包失败,无法下载";continue; }

run sz ${_file}.tar

[ $? -eq 0 ] && {

green "下载完成"

echo "正在删除打包文件"

rm -rf ${_file}.tar

[ $? -eq 0 ] && green "删除成功" \

|| red "删除失败"

} || red "下载失败"

fi

done

;;

passwd)

read -e -s -p "请输入旧密码:" old_passwd

echo '******'

old_passwd=$(echo $old_passwd | md5sum | gawk '{ print $1 }')

if [ x"$old_passwd" != x"$correct_passwd" ];then

red "密码输入错误"

continue

else

read -e -s -p "请输入新密码:" new_passwd1

echo '******'

read -e -s -p "请重复新密码:" new_passwd2

echo '******'

if [ x"$new_passwd1" != x"$new_passwd2" ];then

red "两次输入的密码不一致"

continue

else

new_passwd=$(echo $new_passwd1 | md5sum | gawk '{ print $1 }')

sed -i "/$username/s/.*/$username:$new_passwd/g" $passwd_file

fi

fi

;;

"")

continue

;;

*)

echo "-bash: $COMMAND: command not found" >&2

;;

esac

done

Shell实现跳板机,为什么用跳板机的更多相关文章

  1. KVM 介绍(8):使用 libvirt 迁移 QEMU/KVM 虚机和 Nova 虚机 [Nova Libvirt QEMU/KVM Live Migration]

    学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分 ...

  2. KVM(八)使用 libvirt 迁移 QEMU/KVM 虚机和 Nova 虚机

    1. QEMU/KVM 迁移的概念 迁移(migration)包括系统整体的迁移和某个工作负载的迁移.系统整理迁移,是将系统上所有软件包括操作系统完全复制到另一个物理机硬件机器上.虚拟化环境中的迁移, ...

  3. shell脚本实例-case实现jumpserver跳板机

    1,先通过ssh-keygen 生成公钥,然后将公钥推送到各个主机ssh-copy-id web1|ip 2简单的代码实现 #!/usr/bin/bash trap "" HUP ...

  4. 在Linux客户机与Windows宿主机之间建立共享(VitrualBox)

    VirtualBox中,如果客户机和宿主机都是Windows的话,共享相对是比较方便的.一般是通过\\vboxsvr\shared 这样的路径访问即可. 但是如果客户机是Linux的话,就略微麻烦一点 ...

  5. C# WPF上位机实现和下位机TCP通讯

    下位机使用北京大华程控电源DH1766-1,上位机使用WPF.实现了电压电流实时采集,曲线显示.上午在公司调试成功,手头没有程控电源,使用TCP服务端模拟.昨天写的TCP服务端正好排上用场. 界面如下 ...

  6. docker从容器里面拷文件到宿主机或从宿主机拷文件到docker容器里面

    1.从容器里面拷文件到宿主机? 答:在宿主机里面执行以下命令 docker cp 容器名:要拷贝的文件在容器里面的路径       要拷贝到宿主机的相应路径 示例: 假设容器名为testtomcat, ...

  7. SAP SQ01怎样从开发机传输到生产机

    确认你的Query是本地的还是全局的(跨Client).假设是后者,会自己主动生成传输请求,用标准传输方式就可以. 假设是本地的Query,有两种方式: 方式1:复制成全局的,让后生成传输请求 方式2 ...

  8. c# 32位机和64位机 读取Excel内容到DataSet

    // ----------------------32位机 //注释说明 //ExclePath 为Excel路径 批号 是指Excel文件中某一列必填项 public static DataSet ...

  9. Docker从容器拷贝文件到宿主机或从宿主机拷贝文件到容器

    1.从容器里面拷文件到宿主机? 答:在宿主机里面执行以下命令 docker cp 容器名:要拷贝的文件在容器里面的路径       要拷贝到宿主机的相应路径 示例: 假设容器名为testtomcat, ...

  10. 虚机centos和本机Windows之间文件的拷贝无法用xftp时用FileZilla也行

    步骤如下: 1.如果Centos没有安装ssh,则需要先安装: 2.查看虚拟机中IP地址,命令如下: ifconfig 3.在windows中安装ftp软件 FileZilla启动软件如图: 6  这 ...

随机推荐

  1. "大账户"时代

    当要下载某文件时,哪怕是免积分,也需要登陆账户才能下载.  当要浏览某论坛时,只有注册账户,才可以浏览帖子.  当要网购商品时,必须注册账户,还要有众多宝宝平台,才可以实现交易.  当要团购时,必须先 ...

  2. 如何实现GridView的选中,编辑,取消,删除功能

    protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e) { string sqlstr = &qu ...

  3. hdu 1269 迷宫城堡

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1269 迷宫城堡 Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个 ...

  4. django-south

    python manage.py schemamigration youappname --initial # --initial在数据库创建models定义的表,以及South需要的south_mi ...

  5. oracle odbc配置

    oracle odbc配置 Win7 64位 下安装oracle odbc 不能使用控制面板中 “管理工具”->“数据源(OBDC)”中安装数据源. 而要在“ 运行” 中输入  C:\Windo ...

  6. Actionform

    Actionform 2013年7月8日 15:08 Reset 用actionform是把数据恢复到初始状态 Getter/setter Validate 验证 已使用 Microsoft OneN ...

  7. [shell基础]——read命令

    read命令:在shell中主要用于读取输入.变量.文本 1. 接受标准输入(键盘)的输入,并将输入的数据赋值给设置的变量      [按回车键——表示输入完毕]      [若输入的数据多于设置的变 ...

  8. 【原创】只用 HTML / CSS 画出一把 UKULELE(夏威夷四弦吉他)

    在线演示:http://abelyao.github.io/ukulele/  源代码: https://github.com/AbelYao/css-ukulele  效果图:   为了熟练 CSS ...

  9. 团队开发(NABC模型)

    1.NEED(需求) 基于铁大目前打电话订水的现状,我们发现了一些问题,例如不能及时送到水,水源不足等问题.本来手机在我们生活中就是非常普及的,尤其是对我们大学生来说,我们似乎患上了“手机依赖症”,没 ...

  10. ELK:kibana使用的lucene查询语法

    kibana在ELK阵营中用来查询展示数据elasticsearch构建在Lucene之上,过滤器语法和Lucene相同 kibana4官方演示页面 全文搜索 在搜索栏输入login,会返回所有字段值 ...