最近帮实验室装了两台服务器,计算用的服务器放在内网,通过一台堡垒机与外界相连。碰到很多小问题,在这里记录一下。
组建内网
这一部分没有太多好说的,堡垒机需要有两块网卡,一块对外一块对内,内网服务器一块就够了。组网的时候根据情况可以手工指定IP也可以DHCP。如果内网只有一台机器的话可以找一根网线直连两台机器,如果机器多的话还是买个路由器吧,最好找高级一点的,可定制的功能多一点,否则会很坑。
端口转发
从外面访问内网服务器的时候有三种方法:
- 最简单的办法是先ssh到堡垒机,再ssh到内网的服务器。这样做的问题是需要同时在堡垒机和内网服务器上创建账号,而有的时候我们并不希望用户访问堡垒机,堡垒机对用户应该是透明的。
- 第二种办法是ssh隧道,我们可以通过堡垒机建立隧道,把外面的请求转发到内网。但建立隧道本身也比较麻烦。这篇博客对于ssh隧道讲得非常清楚。
- 最方便解决办法就是端口转发:将堡垒机上的端口与内网服务器需要访问的端口建立映射关系,例如将堡垒机的1234端口映射到内网服务器的22端口,这时
ssh -p 1234 <bastion server IP>
实际登录到的就是内网服务器。端口转发的本质是把堡垒机当成了路由器。这篇博客对于端口映射讲得非常清楚。
时间校准
一个与世隔绝的服务器时间往往不准,有时候是设置问题,有时候是BIOS上的时钟本来就不准。想要校准的话,最方便的当然是手工设置,但这样无法保证精度,而且过一段时间可能又会产生偏差。比较好的办法是用NTP在线校准时间,但是内网无法访问公共NTP服务器。这时可以把堡垒机配置成一个NTP server,然后让内网的服务器都跟堡垒机校准。
当然我们也可以给内网服务器指定一个网关(堡垒机),然后打开堡垒机的转发功能,这样内网服务器就可以直接上网了。但有时候我们并不想这么做。
用户管理
用户管理涉及到批量添加/删除用户,用户分组,权限控制,磁盘限额,限时登录等等。
批量添加/删除用户
下面是我写的一个小脚本,需要读取一个记载了用户名和登录密码的文本文件,然后依次创建每一个用户。
#!/bin/bash
filename=$1
cat $filename | while read line
do
# cut string
arr=($line)
username=${arr[0]}
password=${arr[1]}
# add user
useradd -g student -p `openssl passwd -crypt $password` $username
chmod 700 /home/${username}
# copy certain files to setup develop environment
cp -r -f /home/vasys/home/students/example/* /home/${username}/
cp -f /home/vasys/.bashrc /home/${username}/
# change owner
chown -R ${username}:student /home/${username}
# disk quota
xfs_quota -x -c "limit bsoft=40G bhard=50G ${username}" /home
done
需要注意,通过useradd
的-p
参数指定密码时候一定要给出crypt加密后的密码,不是原始密码。在CentOS 7上,crypt加密后的密码可以由openssl passwd -crypt $password
生成,$password
代表原始密码。mkpasswd
这个命令似乎也可以。
限制用户磁盘空间
在前面的脚本里也看到了,可以通过quota
命令限制每个用户(或每个用户组)使用的磁盘空间。但如果你的文件系统是xfs,就需要用xfs_quota
。为了支持磁盘限额,首先内核要足够新(Linux 2.4以上),其次分区挂载的时候需要加上usrquota
和grpquota
两个参数(在/etc/fstab
里)。
限制用户登录时间
我们的服务器是教学用的,学生可以通过预约获得使用权限。我们需要控制学生只能在预约的时间段登录,这个时间段之外,不仅不能登录,如果有这个用户的进程还要杀掉。限制用户登录时间有很多办法,例如写一个crontab,预约时间结束就用passwd
或者usermod
把用户账户置为锁定状态,到下一次预约时间再解锁。但这样相当于一次预约要写两行crontab,对于我这种懒人很不友好。
我选择的办法是用PAM里的时间模块,这种办法首先要编辑/etc/security/time.conf
,在里面写入允许(或禁止)用户登录的时间,然后再编辑/etc/pam.d/login
在auth
条目后加入account required pam_time.so
。这种办法有一个局限,只能指定周几,不能指定具体的日期。不过我们的预约正好也是以周为单位,所以无所谓了。
杀死某个用户的所有进程
有两个方便的命令killall
和pkill
。当然也可以用ps
、grep
、kill
等命令组合起来,实现更复杂的功能。