一些假设
- 绝大部分坏人并不针对你,而是无差别地寻找攻击对象。如果你成为了黑客组织或某国政府的目标,那这篇文章可能就帮不上太大忙了,你需要顶尖安全专家。
- 大部分坏人在地理上离你很远。坏人无法进入 VPS 提供商的机房,这些机房都被严格保护和监视,物理接触的可能性极低。坏人也不能潜入你身边盗窃你的计算机或存储设备。除非你是重要人物,否则坏人在地理上成功接近你的成本太高。当你意外丢失了电脑,手机或存储设备,一定要尽快修改可能泄露的密码。
- 大部分坏人不能窃取你在网络上存储的文件。确保你的网络存储账号被良好保护起来,比如 iCloud,Dropbox,Google Drive,ownCloud,LastPass。手机验证码,两步验证可以增强安全性。不使用那些不可靠的服务,国内的云存储都信不过。对坏人而言,破解一个使用了手机验证码的 Dropbox 账号是一个非常不划算的方式,花一年时间也不一定能有所收获。如果发现网络存储账号被盗,务必迅速修改所有密码。
- 大部分坏人不能在你的计算机上植入病毒。如果你的计算机被植入了病毒,任何文件和通过键盘输入的密码都可能被窃取。请不要安装来源不明的软件。然而大部分坏人不具备这样的能力。具备这些能力的高级罪犯,往往对你的银行账户更感兴趣,而不是 VPS。
总之,大部分坏人都在猜测 SSH 密码(一天尝试登录几千次),检测端口,利用软件漏洞等方式直接攻击你的 VPS。因为这样做低成本,对技术要求低。而且,你的身份越普通,网站越小,越不容易成为高级罪犯的目标。
生成随机密码
不使用任何自己想出来的密码,而采用随机生成的,长度大于 12 位的密码。可以使用这个诺顿的在线密码生成器。
VPS 账号
Linode 账号被盗了就全完了,坏人可以修改 root 密码,删除你的 VPS 或者下载下来破解里面的数据。
单纯的密码通常不保险,建议开启两步验证,通过短信或手机应用获取登录验证码。大部分服务商支持短信验证,有些还支持 Google 验证器这样的应用。
Linode 对 VPS 的事件,比如重启,删除,更改 root 密码,会有邮件通知。若有异动,迅速更换密码。
防火墙 SuSEfirewall2
SuSEfirewall2 默认是没有安装的。安装防火墙可以增大安全性,外界只能访问有限的几个端口。
安装:
sudo zypper install SuSEfirewall2
修改 /etc/sysconfig/SuSEfirewall2
FW_CONFIGURATIONS_EXT="apache2 apache2-ssl sshd"
允许 SSH(22 端口) 和 Apache(HTTP 是 80 端口,HTTPS 是 443 端口) 通过防火墙。
现在,我们只要保护好 SSH 和 HTTP 及 HTTPS 就可以了。
SSH
VPS 都不得不开启 SSH,以进行远程登录,通过 SFTP 传输文件。
SuSEfirewall 限制登录 IP
假设你住在保定,居所固定,一般不出远门。那么其它地方的人要想 SSH 你的服务器,肯定都是坏人!我们可以限制 SSH 只允许你平时 SSH 的地点的 IP。此方法可以阻止几乎所有 SSH 常规攻击了。
实现方式有两种,一种是配置 OpenSSH 的 hosts.allow 和 hosts.deny 让 SSH 拒绝登录。另一种是配置防火墙,在数据包到达 SSH 之前就被屏蔽掉。第一种我试过但是没有作用,可能是配置不对。第二种用 SuSEfirewall 成功了,就给大家介绍这种方法吧。防火墙是在系统网络的最外层,并且有更多防护高级技术,因而后者应该也比前者有效。
1. 编辑 /etc/sysconfig/SuSEfirewall2 删除 SSH 服务的信任。
上一步防火墙设置中,我们允许了 SSH 服务通过防火墙。这一简单的设置无法限制登录 IP,所有人都可以访问 SSH 端口(22)。
找到:
FW_CONFIGURATIONS_EXT="apache2 apache2-ssl sshd"
改成:
FW_CONFIGURATIONS_EXT="apache2 apache2-ssl"
将其删除后,我们再来定义一个复杂的设置。
2. 修改 FW_SERVICES_ACCEPT_EXT 选项,只允许自己的 IP 访问 SSH 。
在配置文件的后半部分找到 FW_SERVICES_ACCEPT_EXT 选项,修改为
FW_SERVICES_ACCEPT_EXT="177.98.230.11/24,tcp,22"
177.98.230.11/24 替换成你的常用 IP 地址或地址段。177.98.230.11/24 是指从177.98.230.1 到 177.98.230.255 的地址段。
要设置多个 IP 地址或地址段,比如家的 IP 和公司的 IP,用空格分隔:
FW_SERVICES_ACCEPT_EXT="177.98.230.11,tcp,22 177.98.230.12,tcp,22 22 129.47.43.23/24,tcp,22"
3. 重启 SuSEfirewall 服务。
sudo systemctl restart SuSEfirewall2
禁用 root 登录并使用难于猜测的用户名
坏人要想 SSH 暴力登录你的服务器,第一要连接上你的服务器,第二要知道一个可以 SSH 的用户名,第三才是破解你的密码。上一个方法限制了不让坏人透过 SSH 连接上你的服务器。但如果你经常跑来跑去, IP 变化太多,没法使用那个方法,还可以尝试换个不容易知道的用户名。
每个 Unix 和类 Unix 系统都有一个 root 用户,坏人最常从这个用户开始突破。如果你的服务器只有一个 root 用户,那它就暴露在危险之中了。
1. 创建一个用户,比如 kaleo 这样和你的名字及网站没什么关系的用户名。
sudo useradd -g users -p <password> -d /home/<username> -m <username>
其中 <password> 和 <username> 分别替换成你想要的密码和用户名。用户密码应该不同于 root 密码,以提高安全性。接下来假设你新建的用户名叫 kaleo 。
2. 将新用户 kaleo 设置为 sudo 用户。
sudo visudo
将会打开一个 sudo 的配置文件。找到:
root ALL=(ALL) ALL
在后面添加一行:
kaleo ALL=(ALL) ALL
这个命令是调用 vi 编辑器的,使用 :wq 命令保存退出。
3. 禁用 root 的 SSH 登录,允许 kaleo 的 SSH 登录。
sudo vi /etc/ssh/sshd_config
找到:
#PermitRootLogin yes
修改为:
PermitRootLogin no
并在末尾添加:
AllowUsers kaleo
4. 重启 SSH。
sudo systemctl restart sshd
如果坏人不知道你的用户名,就更不能破解你的密码了。 SSH 不会告诉坏人用户名不存在或者不可用,所以坏人会一直徒劳地尝试 root 。
我认为在同一个计算机上有太多 SSH 用户也是不妥的,哪一个密码不够强或泄露都有大问题。
定期更换密码
密码一年一换可能比较好。
其他
还有两种强化 SSH 安全的方法,读者可以参考。出于便利考虑,我并没有采用。
- 使用 SSH Key 认证,而非密码。SSH Key 可以被看作是一个超长的随机密码,如果坏人没有 SSH Key 文件,就永远不可能猜到密码。如果你丢失了 SSH Key,也就不能远程访问 VPS。SSH Key 也可以设置密码。如果 Key 有密码,即便坏人得到了 Key 文件,也必须得破解密码才能使用。但这种方式设置比较麻烦,
- 将 SSH 换到另一个端口。攻击者一般会首先检测 22 端口,这是默认的 SSH 端口。如果你把它改到了 9987 端口,坏人就不得不检测几千个端口才能找到的 SSH 端口。然而被找到只是时间问题,频繁换端口也真是一件麻烦事。
- Fail2Ban。Fail2Ban 是一个自动过滤程序,它定期扫描系统日志,如果发现有某个 IP 失败登录次数太多,则通过防火墙封禁此 IP 。此方法后知后觉,如果坏人不停更换 IP,则作用有限。得到一大堆封禁 IP 也着实困扰。
Apache 和 PHP
文件和目录权限
网站目录权限通常 755 或 750。
PHP 可执行文件权限 644 或 640。存有数据库密码的 PHP 文件,比如 WordPress 的 wp-config,应设置为 600 ,除所有者之外,任何人都不能查看。
所有者和组可以设置成 root:root 或 yourname:users 都可以。PHP 通过 Apache 执行时,身份为 wwwrun:www,通常不能修改或上传文件。
文件上传目录必须要将所有者设置为 wwwrun:www,而不是更改权限为 777(永远不要这样做)。WordPress 自动更新功能需要将 wordpress 根目录所有者设置为 wwwrun:www。但注意 wp-config 最好设置成 root:root 或其它用户。这点也有风险,如果有人盗取了你的 WordPress 账号,就可以更改 PHP 代码,破坏整个网站。如果你这样做了,就要更加注意保护 WordPress 账号的安全。
防止被列出目录
除了少数下载文件用的网站目录外,几乎不会有人想用户直接列出一个网络文件夹的内容。这样会暴露出网站结构问题,比如哪里安装了 phpMyAdmin。
方法一(推荐):在 Apache 配置文件里禁用根目录的 Indexes 选项:
<Directory "/srv/www/htdocs"> Options -Indexes +FollowSymLinks ... </Directory>
方法二:确保每个目录下都有一个空的 index.php 或 index.html
保护 phpMyAdmin
因为在防火墙中没有允许 MySQL/MariaDB 服务,坏人一般无法直接危害你的数据库。但很多人会在服务器上安装 phpMyAdmin ,任何人都可以通过网页访问它,坏人可以不断尝试密码。这样很不安全。
phpMyAdmin 是安装在 Apache 的默认 vhost 目录 /srv/www/htdocs/phpMyAdmin/ 中的。我们可以在 此目录下新建一个 .htaccess ,限制访问 IP 只能是你的常用 IP :
Requires all denied Requires ip 177.98.210 Requires ip 177.98.228.172
攻击检测
监测 SSH 攻击
使用 lastb 命令可以查看最近的的失败登录,包括用户名,IP。失败登录大部分都是 SSH 攻击者造成的。大量的 SSH 登录会降低服务器性能,而且很烦人。通过防火墙配置可以封禁单个 IP 地址,御敌于国门之外,请参见下面一节“封禁IP”。
监测 HTTP 攻击
Apache 日志位于 /var/log/apache2/ 文件夹内,文本文件非常长而且阅读困难。可以使用 goaccess 分析日志,生成 HTML 报告。
- 安装软件包。
sudo zypper install goaccess
- goaccess 默认没有设置日志格式,需要手动修改配置文件 /etc/goaccess.conf 。
time-format %T date-format %d/%b/%Y log-format %h %^[%d:%t %^] "%r" %s %b "%R" "%u"
- 进入 /var/log/apache2/ 目录,可能需要 root 权限。开始分析日志文件。
goaccess -f access.log -a > report.html
SuSEfirewall2 封禁 IP
通过 Apache Log 分析和 SSH 失败登录日志可以发现攻击源。我们可以通过防火墙规则来屏蔽这些 IP。
查询 IP 详情可以使用这个网站 What Is My IP Address 。假设 IP 是来自某 ISP 的机房,你可以将整段 IP 全封掉:
FW_SERVICES_REJECT_EXT="61.160.213.33/24,tcp 110.85.80.90/24,tcp 141.255.167.138/24,tcp"
61.160.213.33/24 指的是从 61.160.213.1 到 61.160.213.255 的 IP 段。tcp 指的是封禁 TCP 协议。HTTP,SSH 等都是建立 TCP 协议之上的,封禁了 TCP 协议,也就封禁了 HTTP 访问。
FW_SERVICES_REJECT_EXT 的 REJECT 意思是拒绝访问,EXT 的意思是外部(External),即拒绝从外部来的访问。类似的是 FW_SERVICES_DROP_EXT ,它也能阻止访问,但直接丢弃数据包,不会返回拒绝访问的消息。从用途上来看, FW_SERVICES_REJECT_EXT 明确地告诉攻击者我已经把你屏蔽了,而 FW_SERVICES_DROP_EXT 则把这个端口藏起来。我个人的理解:当坏人是以攻入系统为目的,攻击频率不高时,使用 REJECT 可以使其知难而退;当坏人以极高频率发动 DDOS 攻击,则用 DROP 更合适,因为坏人这时一般是不会收手的。
发表回复