网站服务器安全构建策略基础

网站服务器不被攻击是不可能的事,世界上的黑客无时无刻不在惦记着你的服务器,用它来转发攻击、作为肉鸡、甚至用来挖比特币。你或许觉得服务器的安全并没有想的那么严重,谁会在乎你的小站呢?话虽如此,对于黑客而言,只需要用自己的程序自动去扫描完成所有入侵即可,黑客自己或许都不清楚自己到底入侵了多少台服务器。

作为网站的创办者,如何连起码的服务器安全意识都没有,那么当大难来临时,或许只有捶胸顿足。本文简单的讲一些我所遇到的想到的安全策略,以供参考。

登陆安全策略

黑客的90%对服务器的攻击,都是通过尝试破解服务器的登陆账号而实现的。由于我们很多人缺乏经验,所以在购买云服务器之后,往往按照网上的一些教程,搭建起web环境,然后就开始把重点放在web的开发和管理上,而直接无视服务器本身的安全问题。如何换位思考,你作为黑客,如果想搞一个网站,最狠的方法是什么?就是获取该网站所在服务器的登陆账号及密码,登陆之后,把该服务器上的网站代码删掉,数据删掉。所以,保护你的登陆信息至关重要。

创建非root管理员用户

一个系统中只有一个root,但是其他用户却可以随意创建。如果你创建了一个其他用户用来作为管理,而禁用了root,你的系统就会瞬间增加10倍以上的安全系数。因为你所创建的管理员用户名,黑客就很难猜到。你可以用你的名字或昵称作为管理员账号,黑客如何不知道这个账号,就无法登陆到你的服务器干坏事了。

首先,创建非管理员用户及用户组。

groupadd webmaster
useradd -g webmaster administrator

这样,创建了一个webmaster用户组,在这个组中,增加了一个administrator用户。

其次,在sshd的配置文件中修改ssh登陆权限。

vi /etc/ssh/sshd_config

找到PermitRootLogin,将它的值修改为no。这样就禁止了root通过ssh登陆。但是,我们还要再做一个限制,就是找到(如果没有,增加一行)AllowUsers,修改为如下:

AllowUsers administrator

AllowUsers配置项表示,仅运行后面配置的这些用户通过ssh登陆。一旦设置了这个项,其他所有用户都无法通过ssh登陆了,这是我们想要的。

重启sshd服务(先别慌马上去做,往下面读完本节再执行重启)。

service sshd restart

这样,你的服务器仅允许administrator登陆了。等一下,是不是漏了什么?我CAO,administrator的密码没有设置啊!不要慌,sshd重启之后,当前你还是root用户,你还是可以给这个用户设置密码的。不过接着往下读,你会发现好玩的事。

补充:赋予administrator执行sudo的权限

如果是裸机,administrator默认是没有sudo命令的权限的,需要用root用户登录后做如下操作。

chmod u+w /etc/sudoers
vi /etc/sudoers

找到 root ALL=(ALL) ALL,在他下面添加 administrator ALL=(ALL) ALL,这样就允许了administrator可以执行sudo命令了。但是如果你按照上面的方法,不打算为administrator设置密码,那么需要把这行修改为:

administrator ALL=(ALL) NOPASSWD:ALL

因为我们都很熟悉,一般在第一次执行sudo的时候是必须要输入密码的,而如果我们按照上面的方法,没有设置密码的话,就麻烦了,输入密码的时候你根本没有密码可以输入啊,所以这个地方要注意一下。

使用SSH密钥登陆

在《使用SSH证书远程登陆你的服务器》一文中,我大致讲到了使用ssh密钥登陆的过程。不过,本文讲的更简洁好用。前面不是已经提到了,你没有给administrator设置密码吗?如果你使用ssh密钥登陆,就不需要密码了。注意,你当前在服务器上操作的,还是root用户,千万不要退出来,否则你就悲剧了!读罢上面我提到这篇文章,我想你应该懂了了ssh登陆的原理。我们这篇文章就不讲了,直接上操作方法。

首先,生成ssh密钥对。使用ssh-keygen命令即可。如果你本地不是linux系统,那么直接在服务器上面操作也行,我们需要的,是这个密钥对,系统无所谓。

cd ~
ssh-keygen

接下来会让你输入密码。这一点我在上面那篇文章没有讲到。这个密码是用来认证当前密钥是不是你的,是客户端系统干的事情。在详细解释一下:当你准备使用ssh密钥登陆服务器的时候,如果这个密码没有设置,会直接登陆到服务器上,这样很方便。但是如果一旦你的私钥(本地电脑上的)被盗,那么黑客只需要使用这个私钥,直接就可以连到你的服务器上面。那么怎么办呢?ssh在使用你的私钥之前,再对你的身份进行验证,也就是对私钥再进行加密。一旦加密后,你下次再使用ssh登陆服务器时,会让你输入你对私钥进行加密时的密码,而这个密码验证是在你本地电脑上完成的,速度更快,密码也不用在网络上传播,当然也就更安全。说了这么多,我的目的就是让你设置这个私钥。

设置好私钥之后,系统会自动创建一个.ssh目录。

cd .ssh
ls

可以看到有id_rsa和 id_rsa.pub两个文件,第一个是私钥,第二个是公钥,公钥可以公开给任何人看。如果你是在服务器上生成的这两个文件,把它们下载下来。如果不知道怎么下载,直接用vi打开它的内容,在你自己的电脑上建立两个文件名相同的文件,把里面的内容拷贝过来就可以了。一旦得到这两个文件,就在服务器上把它们删掉。

如果你本地是linux系统,把这两个文件放到你当前家目录的.ssh文件夹下面。在服务器上继续操作。

因为你是希望administrator这个用户登陆上去,所以要把id_rsa.pub这个文件上传到administrator用户的家目录下的认证文件夹中,或者直接用vi来创建也可以。

vi /home/administrator/.ssh/authorized_keys

把id_rsa.pub文件的内容拷贝进去,保存退出。

完成上面的操作之后,你就可以实现:1.禁止root通过ssh登陆服务器;2.通过ssh密钥以administrator的身份登陆服务器。在本地测试一下吧:

ssh administrator@192.168.1.111

输入刚才给密钥加密时用的密码。看看是否已经登陆服务器了呢?登陆到服务器上,要善于使用sudo命令哦。你所要保管好的,就是你的私钥,如果你想装逼,用一个只有可读权限的U盘把私钥和公钥装起来,再装一个putty,走到哪儿都不用怕了,U盘一插,很快就能连上服务器。如果你把你的私钥弄丢了,那你就完全悲剧了。所以,私钥还是使用多种比较安全的方式进行备份吧。

访问安全策略

除了让黑客猜不到你的管理员登陆信息之外,修改你的服务器对外提供访问的端口,也是一个安全策略。而这个安全,需要用到防火墙,通过防火墙来控制哪些端口是对外可以访问的,哪些端口是仅对局域网可以访问的,哪些端口是只有本机可以访问的。linux中最常用的防火墙软件就是iptables,我们这里就通过iptables作为防火墙案例进行实操。

iptables的配置规则

关于iptables,这里有一篇参考文献,可以去了解。我们这里简单的对iptables的配置进行介绍,以完成我们本文要实现的访问安全控制。

首先,我们打开iptables的配置文件:vi /etc/sysconfig/iptables,可以先大概了解一些规则的格式。

我们必须要理解iptables中的一个些概念。一个请求指令(术语称为“数据包”),从客户端发出,进入服务器,在服务器中流动,再从服务器流出,服务器在接受到这个指令那一刻开始,就会对它进行监测,并设置了几个重要的关卡,在这些关卡(术语称为“链”)上,就可以对该指令进行拦截、放行或修改。这些关卡包括(按时间顺序):PREROUTING(路由器)、INPUT(进入)、FORWARD(转发)、OUTPUT(流出、服务器去访问外网时)、POSTROUTING(路由后、服务器去访问外网时)。实际上,一个指令流动不一定非得经过这些关卡,大部分情况下不需要经过两个路由关卡,当我们的服务器作为代理服务器的时候,就会要经过路由关卡来处理数据。

我们举一个例子来说明一个指令的情况:在自己的电脑上ping服务器和在服务器上ping自己的电脑。

当我们ping服务器的时候,指令由我们客户端发出,达到服务器的时候,就开始受防火墙监控,我们为了禁止外部用户ping通我们的服务器,我们在INPUT这个关卡上增加一个规则:

-A INPUT -p icmp --icmp-type 0 -j ACCEPT
-A OUTPUT -p icmp --icmp-type 8 -j ACCEPT

防火墙规则被保存在几张(四张)表中,其中我们最常用到的是nat、filter这两张表,在指令到达每一个关卡的时候,防火墙就去从表里面找出该关卡对应的规则序列,从上往下执行(也就是说前面的规则优先级更高,在满足前面的规则之后,后面的规则才能生效),选择用那张表,用-t tablename来确定,例如:

-t filter -A INPUT -p tcp --dport 80 -j ACCEPT

意思就是在filter表中增加一条规则,这条规则作用在INPUT这个关卡上。后面蓝色字就是规则的内容。由于防火墙默认使用的是filter表,所以当写防火墙规则的时候,如果不存在-t,则默认表示往filter这个表增加或删除规则。理解iptables,就必须理解这“四表五链”的概念,理解之后,再深入去研究规则即可。

关于规则的部分,就不予多阐述,在参考文献中有了比较多的解释。要强调的就是,必须认真思考规则的先后顺序,保证这些先后顺序最终实现的防火墙规则是你想要的结果。

参考文献 规则执行顺序

控制外网公开访问规则

我们本文的重点是服务器安全,因此,重点还是来讨论防火墙中各个关卡的一些安全性规则。

首先,一个基本的策略:堵。意思就是,首先,把所有的关卡堵起来,然后再一个一个的打开。

就像我上面展示出来的iptables中一样,我们仅允许22端口和80端口可以被外部访问。22端口是提供ssh登陆的,80端口是提供web访问的。如果你的服务器不需要其他的服务,比如代理、转发,或者对外提供mysql服务或某些图片服务等等,就可以只提供这两个端口可以对外访问。

为了禁止别人ping通我们的服务器?上面好像已经给出了规则。把那两条规则加到DROP前面。

修改默认端口

通过前文,我们已经欺骗黑客,让他无法得知我们的服务器的登陆信息。另外,我们还可以直接隐藏ssh的连接端口,让黑客根本找不到我们的服务器如何去连接。

vi /etc/ssh/sshd_config

找到Port 22,去掉前面的#,把22改为其他端口,比如1452。再重启sshd服务。下次你在连接到服务器的时候,记住使用1452端口去连接,而不是原来的22。

最后是我的/etc/sysconfig/iptables:

# Generated by iptables-save v1.4.7 on Sun Dec 20 16:02:52 2015
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [55:5672]
-A INPUT -i lo -j ACCEPT
# 允许内部通信,本机访问本机,比如访问localhost
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# 接收到的数据包是本机回应后的,或者由于客户端接收到本机回应产生的新包,也就是说该数据包是服务器认证过的包
-A INPUT -p tcp -m tcp --dport 1452 -j ACCEPT
# 允许1452端口被外网访问,也就是ssh连接,如果你调整了ssh端口,那么这里必须修改,否则你就悲剧了
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
# 允许80端口被外网访问
-A INPUT -s 127.0.0.1/32 -p tcp -m tcp --dport 3306 -j ACCEPT
# 允许3306端口被外网中的某个网段访问,这个外网也包括局域网,凡是非本机的,在这里都称为外网,只有在你希望通过外网使用本服务器的mysql时,才使用该规则,否则,如果在本机使用mysql其实可以不需要,只需要使用localhost作为连接地址即可
-A INPUT -p icmp --icmp-type 0 -j ACCEPT
-A OUTPUT -p icmp --icmp-type 8 -j ACCEPT
# 上面两条ping不通
-A INPUT -j DROP
# 不允许其他访问,由于执行顺序是从上往下的,当上面的规则都不满足时,这一条才会执行
-A FORWARD -j DROP
# 不允许转发
COMMIT
# Completed on Sun Dec 20 16:02:52 2015

权限安全策略

我们在服务器上面运行web环境,主要有nginx、apache、mysql、php、redis、php-fpm等几种常用的环境。但是,如果我们安装这些环境的时候,没有注意安全性问题,可能直接就用root去运行这些环境软件了,这个后果比较严重,我曾经就因为redis漏洞,导致服务器被黑,有一个木马进程无限制的重生,害得我只能重装系统。所以,我们尽可能的在权限问题上事先处理好。

用户和用户组

首先,我们可以大概看下自己服务器上面运行的一些软件哪些是提供给外部使用的,或者通过外部调用可以在环境内使用的。其次,我们要为这些软件创建独立的,或者共用权限有限的用户。比如nginx、apache、mysql都用一个www用户去运行,由于前面我们已经只允许administrator用户通过ssh登陆了,所以这个用户是无法登陆的。而且,由于这个用户不是root用户,它无法对自己权限范围内的文件(夹)进行读写操作,比如它无法去修改bin下的软件,它也无法在系统核心文件夹中运行一些程序。

在nginx、apache、mysql的配置文件中可以对此进行配置。在apache的配置文件中还可以配置php能够有权限进行读写的目录,除了这些目录,php无法在其他目录中进行读写。这样,即使黑客黑入了你的网站系统,也仅仅只能对你的网站程序和数据库做手脚,无法对服务器做坏事。

文件及文件夹的权限

网站程序仅可以对规定目录中的文件进行读写。这涉及到两个操作,一个是chown,一个是chmod。chown让用户对某些文件及文件夹有所有权,可以进行读写。chmod修改文件文件夹的读写和可执行权限,所以一般情况下,网站文件和目录都最好保持755的权限。

数据库用户权限

mysql的root用户拥有最高权限,可以对数据库随意修改和删除,因此,在网站运行上线时,最好创建一个只能对某些数据库有部分权限的数据库用户,这个用户能执行增删改查,满足网站数据操作的需要,但是不能对数据库进行管理。这样也可以降低数据库如果被入侵可能带来的风险。

结语

总结起来,核心知识点就包括:

  • 账号及ssh
  • iptables

写了这么多,归结起来其实就一句话,请诸君重视自己的服务器安全。当然,本文仅仅提供了比较简单的安全策略,像服务器安全监测这些知识,我也未曾接触,还需要在后期学习中不断积累。

2016-01-08