全栈范

互联网 & 技术 & 产品 & 阅读 & 生活

0%

从 0 到 1 搭建应用服务器(一):基于 CentOS 的安全配置

从 0 到 1 搭建应用服务器(一):基于 CentOS 的安全配置

之前的文章介绍了我最近开发的一款工具软件,然而安装包放在华为应用市场上面,如果不安装华为应用市场就无法下载软件,无奈,只能自己从零搭建一个服务器来进行应用的宣传和下载。搭建一个服务器是很简单的,这里我们将服务器的要求提高一些,以对标 “生产” 的标准进行要求,要做的东西比较多,故作此文,加以记录。

首先说下环境,腾讯云,CentOS 7.5 64 位,服务器采用 Java 完成,具体来说就是 Springboot. 大致罗列下要做的事情:

  • 介绍服务器远程连接方式
  • 进行基础的服务器安全配置
    • 禁止 root 用户直接登录服务器
    • 关闭 22 登录端口
    • 警惕空密码账户
    • 设置密码过期时间
    • 设置密码复杂度要求
    • 禁止 ping 服务器
    • 最重要的,防止 rm -rf
  • 搭建生产服务器环境
    • 安装 ftp 服务
    • 连接 ftp 服务器
    • 安装 JDK
    • 搭建 Springboot 环境
  • 发布应用
    • 在服务器中启动 Springboot 程序
    • 指定虚拟机启动参数
    • 编写服务器启动脚本程序
    • 配置域名

1、介绍服务器远程连接方式

对于腾讯云,一种连接方式是直接使用腾讯云提供的在线的 webshell 进行登录,这种登录方式提供的是 ssh 登录。假如我们进行 ftp 登录来上传文件的话比较不方便。腾讯云的 webshell 还是比较好用的,不过一般我们推荐使用 Xshell 进行 ssh 登录,使用 xftp 进行 ftp 登录。可以到我的公众号后台回复 【服务器连接软件】 获取我打包好的软件。

拿到一个新的服务器,我们要做的第一件事情就是到控制台里去重置密码。对于密码,为了系统安全起见,应该选择比较复杂的口令,例如最好使用 8 位长的口令,口令中包含有大写、小写字母和数字,不应该包含单词,应该与姓名、生日等不相同

按照上面的介绍重置密码之后就可以进行登录了,这里使用 Xshell 进行登录,登录方式比较简单,此处略过。

2、进行基础的服务器安全配置

2.1 禁止 root 用户直接登录服务器

为啥要禁止 root 登录呢?首先,root 这个用户是众所周知的,使用 root 用户增加了被攻击的风险。其次,root 权限比较高,不论是服务器拥有者还是服务器的协同开发都不应该直接使用 root 操作服务器。使用 root 用户,一旦出现操作意外,就可能会给服务器带来致命的危害。

禁止 root 登录之前先添加一个新的管理员用户,

1
2
3
4
5
6
# Step 1: 创建新用户 admin
adduser the_xxx_admin
# Step 2: 修改用户密码,密码也应该满足上述要求哦
passwd the_xxx_admin
# Step 3: 赋予该用户 su 执行权限
gpasswd -a the_xxx_admin wheel

这里增加了一个名为 the_xxx_admin (用户名不要太大众化)的管理员用户,并将其用户组设置为 wheel. wheel 在 linux 中是一个特殊的用户组,这个组被设计用来解决 su 指令的授权问题。也就是只有在 wheel 组里面的成员才能使用 su 切换到 root 用户。如果一个用户不在 wheel 组里面,即使使用 su 指令并正确地输入了密码也无法切换到 root 用户。wheel 用户组不仅具有 su 指令的权限,也具有 sudo 的权限,可以通过浏览 /etc/sudoers 文件来了解。

增加了新的用户之后并赋予 sudo 权限之后,我们就可以禁止 root 用户登录了:

  1. 修改 /etc/ssh/sshd_config 文件将 #PermitRootLogin yes 修改为 PermitRootLogin no
  2. 使用 service sshd restart 重启 ssh 服务并验证登录效果即可。

此处修改文件的时候可以使用 vim /etc/ssh/sshd_config 命令,然后输入 /PermitRootLogin 定位到 #PermitRootLogin yes 所在的一行,输入 a 进入编辑模式,修改完毕之后使用 :wq! 退出即可。

重启之后再使用 root 进行登录,立刻显示 “服务器拒绝 ssh 连接”,然后使用新增的用户进行登录即可。

2.2 关闭 22 登录端口

主要是因为 22 端口登录已经是众所周知的了,如果我们使用其它端口实现 22 端口的功能可以减少被攻击的风险。修改登录端口需要修改 /etc/ssh/sshd_config 文件。在该文件中,我们先新增一个端口,推荐使用 10000 号以上的端口。注意这里应该先保留 22 端口,设置完毕并验证新的端口可以登录之后再删除 22 端口。还有需要注意的地方,验证新的接口是否可以登录之前一定要先打开防火墙,防火墙关闭的时候端口可以直接使用,而一旦防火墙打开,而你又没有使用防火墙打开该端口,那么防火墙可能会直接屏蔽该端口,导致你无法登录自己的服务器

这里直接使用 vim 编辑 /etc/ssh/sshd_config 文件的时候应该会出现 Permission Denied。此时,可以通过 sudo 命令来完成,

1
sudo vim /etc/ssh/sshd_config

与 sudo 类似的还有 su 命令。sudosu 功能类似,区别在于 sudo 命令需要输入当前用户的密码,su 命令需要输入要切换到的用户的密码。 sudosu 更合理一些,因为,比如如果希望某个用户切换到 root 用户,使用 su 的方式要求执行者必须知道 root 账户的密码,密码被很多人知道显然不安全。而 sudo 只要求确认当前执行者的身份,如果当前执行的用户在 sudoers 中被授予过访问 root 的权限,则它可以切换到 root 用户,这样我们既赋予了该用户切换到 root 的权限,又无需告知该他 root 账户的密码。此外,我们还可以通过在 sudoers 文件中进行配置来限制用户的权限,记录更多的用户日志等。

进入编辑模式之后找到 Port 22 并在下面新增一行 Port 10022

1
2
Port 22
Port 10022

然后,我们需要按照上述管理端口的逻辑开放 10022 端口。然后,重启 ssh 服务

1
systemctl restart sshd # 或者 service sshd restart

如果验证登录成功,再将上面的 Port 22 注释掉,重启 ssd 服务然后再使用 22 端口登录,验证是否已经禁止。

此时,我再使用 22 端口进行登录,提示 Connection failed,表明禁止 22 端口登录成功。

2.3 警惕空密码账户

空密码账户会增加系统的安全风险。使用如下指令查询:

1
cat /etc/shadow | awk -F: '($2==""){print $1}'

另外,可以通过修改 ssh 配置文件 /etc/ssh/sshd_config 来禁止空密码账户进行登录:

1
PermitEmptyPasswords no

2.4 设置密码过期时间

设置和查询密码有效期会用到指令 chage,该指令格式如下:

1
chage [参数] [数值]

常用参数:

  1. -m : 密码可更改的最小天数。为零时代表任何时候都可以更改密码。
  2. -M : 密码保持有效的最大天数。
  3. -W : 用户密码到期前,提前收到警告信息的天数。
  4. -E : 帐号到期的日期。过了这天,此帐号将不可用。
  5. -d : 上一次更改的日期。
  6. -I : 停滞时期。如果一个密码已过期这些天,那么此帐号将不可用。
  7. -l : 列出当前的设置。由非特权用户来确定他们的密码或帐号何时过期。

一般的使用示例如下。

首先查询用户密码的有效期:

1
chage -l admin

显示信息如下:

1
2
3
4
5
6
7
Last password change                                    : Apr 07, 2020
Password expires : never
Password inactive : never
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 99999
Number of days of warning before password expires : 7

我们可以使用 chage 指令来修改密码的过期时间,比如使用如下指令将密码的最大有效期设置为 99 天:

1
chage -M 99 admin

2.5 设置密码复杂度要求

有两种方式来设置密码复杂度。

一种方式是修改 /etc/login.defs 文件,这里面几个比较重要的选项。可以通过修改选项的值来设置对密码对要求:

1
2
3
4
PASS_MAX_DAYS   90  #密码最长过期天数
PASS_MIN_DAYS 80 #密码最小过期天数
PASS_MIN_LEN 10 #密码最小长度
PASS_WARN_AGE 7 #密码过期警告天数

另外一个方法是,修改 /etc/pam.d/system-auth 文件。编辑该文件,在下面这行进行配置即可:

1
password required pam_pwquality.so dcredit=-1 ucredit=-1 ocredit=-1 lcredit=0

配置的可选参数可以参考 /etc/security/pwquality.conf 文件。常用的参数如下:

  1. retry=N:定义登录/修改密码失败时,可以重试的次数;
  2. Difok=N:定义新密码中必须有几个字符要与旧密码不同。但是如果新密码中有1/2以上的字符与旧密码不同时,该新密码将被接受;
  3. minlen=N:定义用户密码的最小长度;
  4. dcredit=N:定义用户密码中必须包含多少个数字;
  5. ucredit=N:定义用户密码中必须包含多少个大写字母;
  6. lcredit=N:定义用户密码中必须包含多少个小写字母;
  7. ocredit=N:定义用户密码中必须包含多少个特殊字符(除数字、字母之外);

2.6 禁止 ping 服务器

禁止 ping 后,不让别人通过域名 ping 到你的 ip. 禁用后,你在 ping 自己的域名会给你返回服务商的 IP 并提示超时,这样你就可以减少 IP 暴露,增加一点安全。

实现的方式是:编辑 /etc/sysctl.conf 里面配置,如果没有添加上下面一行配置:

1
net.ipv4.icmp_echo_ignore_all=1

然后使用如下命令使配置生效:

1
sysctl -p

这样就禁止了对服务器的 ping 操作。如果要解除,只需要将上面的 1 换成 0 即可。

配置完毕之后在本地的命令行里输入 ping 你的ip 地址,如果显示请求超时,则说明配置成功。

2.7 最重要的,防止 rm -rf

rm -rf 这个梗想必大家都了解,这节我们不是要教你如何在服务器上面执行该操作,来观察它带来的喜剧效果,而是如何避免该操作带来的负面影响。需要注意的地方:下面的操作会使用 source 命令,这个指令也是万分危险的指令,必须慎重! 这个指令用来修改类似于 windows 中的环境变量,假如 source 出现问题,可能会导致几乎所有的命令都无法使用,非常危险。

实现的原理是对 rm 命令进行改写,将其关联到一个自定义脚本。首先,我们在 ~ 目录下面一个隐藏的 .trash 文件和 .tools 文件夹,

1
2
3
4
5
6
# 创建 .trash 文件夹
mkdir .trash
# 创建 .tools 文件夹
mkdir .tools
# 检查创建结果
ls -al

然后,在 .tools 文件夹中创建一个名称为 remove.sh 的脚本,编辑其内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/sh
trash_dir=~/.trash/`date +%Y%m%d`

if [ ! -d ${trash_dir} ] ;then
mkdir -p ${trash_dir}
fi

for i in $*
do
suffix=`date "+%H%M%S"`
if [ ! -d "${i}" ]&&[ ! -f "${i}" ];then # 首先判断是否是合法的文件或者文件夹
if [[ "${i}" != "-rf" && "${i}" != "-f" ]];then # 这里对-rf进行处理,因为mv指令后面没有-rf,-f参数
echo "[${i}] do not exist"
fi
else
file_name=`basename $i` # 取得文件名称
mv ${i} ${trash_dir}/${file_name}_${suffix}_${RANDOM}
echo "[${i}] delete completed"
fi
done

这里简单解释下这个脚本文件的内容吧。这个脚本文件按照文件名拼接的规则,在文件名中增加了日期信息(用来对同名文件进行区别),然后使用 mv 命令将指定对文件夹移动到 ~/.trash 目录下面。应该注意这里对 -rf 参数的处理。之前也看过一些博客的脚本,没有对这两个参数做处理,导致 mv 命令无法执行。

然后,我们修改 ~/.bashrc 文件,在末尾追加下面一行代码。将 rm 命令关联到指定的 Shell 文件:

1
alias rm='sh ~/.tools/remove.sh'

然后,使用如下命令来使我们对修改生效,

1
source ~/.bashrc

最后,在用户根目录下面创建文件夹,并使用 rm -rf 文件夹 指令测试效果。

这里本质上是把要删除的目录移动到了 .trash 目录下面。然后根据操作的日期对移除对文件夹进行管理。这无疑地会导致我们的文件夹越来越大,所以,我们要定期对该文件夹进行删除。这里,我们使用脚本来实现这个目标。

这里我们创建一个定时任务来执行删除操作。在 .tools 文件夹下面添加一个脚本文件 clean.sh ,编辑内容如下。其作用是找到回收站中修改日期大于 3 天的文件,执行真正的删除操作:

1
2
3
#!/bin/sh
trashdir=~/.trash
find ${trashdir} -mtime +3 -exec 'rm' -rf {} \;

然后,我们将该任务添加到 crontab 任务中。

使用 crontab -e 命令进入定时任务编辑界面,在最后面加入

1
0 3 * * * sh ~/.tools/clean.sh     #每天 3:00 执行清理回收站的脚本

使用 service crond restart 重启 crontab 服务,使用 crontab -l 命令如果可以看到刚才添加的那段话,则证明添加成功。这里使用了一段 cron 表达式,Linux 的 cron 表达式和 Springboot 中的表达式起始单位有些不同,需要注意下。

另外,注意到上文中需要使用 source ~/.bashrc 才能使配置的 bash 文件生效。当用户重新登录的时候也必须这么做才能使我们的配置再次生效。作为程序员,这当然是无法容忍的。于是,我们可以用下面的方法来解决这个问题,来让每次登录服务器之后我们的配置自动生效,

1
2
3
4
5
6
7
8
9
10
# 编辑 .profile 文件
vim .profile

# 在文件中增加如下的配置
if [ -s ~/.bashrc ]; then
source ~/.bashrc;
fi

# 或者直接增加下面的代码也行,不过简单粗暴了点
source ~/.bashrc

这样配置之后,每次启动重新登录的时候我们的配置就可以自动生效了。

最后的一个问题,如果用户目录下面不存在 .bashrc 或者 .profile 文件,那么可以从 /etc/skel 文件下面将其拷贝到用户目录下面,然后再做上面的配置即可。

未完,请看下文


-----本文结束 感谢阅读---------

欢迎关注我的其它发布渠道