#前言
朋友借我一台独服,是他们实验室跑机器学习的机器,配置高,还有双路独显。这么好的机器自然要认真保护,趁此机会学习一下 Linux 安全。
#查看登录记录
玩 Linux,有事没事看看日志,了解系统的运行状态。Linux 有 3 个文件记录登录相关的信息,分别是
/var/log/wtmp # 登录成功的日志,倒序
/var/log/btmp # 登录失败的日志,倒序
/var/run/utmp # 当前登录的用户
注意他们三个所在的文件夹不同,当前登录的用户记录在 /var/run/
下。使用last
命令查看这三个文件,last
命令默认查看成功登录的日志,如果想查看其他两个记录,使用 -f
参数指定,例如查看当前登录的用户:
last -f /var/run/utmp
可以加上参数查看指定数量的登录记录,指定用户的登录记录,例如下面这条命令查看最近 3 条 acytoo
的登录记录。
last -i -n 3 acytoo
查看失败的登录记录,除了上指定读取/var/log/btmp
文件,还有一个直接的命令:lastb
默认查看登录失败的日志。有公网 ip 的服务器总有很多登录失败的记录,都是脚本小子爆破服务器密码时留下的足迹,例如查看最近 100 条登录失败的日志:
脚本小子会扫描 vps 服务商的 ip 段,甚至是扫全网。发现设备就用字典爆破,我曾经有一台弱密码的 vps 就被爆破过。
last
的其他参数见附录。
#登录基本防护
#修改 ssh 端口
修改ssh
端口可以挡住大部分碰运气的人,他们扫描很多机器,遇到非默认端口的机器,大概率会跳过,去下一台机器碰运气。
sudo nano /etc/ssh/sshd_config
ssh
默认端口是 22,删除Port 22
前面的注释,在下面添加一条新记录,别急着删除默认的端口号。试试能不能通过新端口连接,能正常连接,再删除默认端口号。
Port 22
Port 23456 # 设置一个端口号
编辑 ssh 配置后要重启 sshd 进程,应用修改:
sudo systemctl restart sshd
修改 ssh 端口可以过滤掉很大一部分试运气的脚本小子(瞎猫),如果你被人针对,nmap 扫到了 ssh 端口,还是会被人不停的尝试。
#修改默认用户名
一些系统可能会提供默认用户名,比如甲骨文的云服务, Ubuntu 系统,密钥登录,但是默认的用户名是 ubuntu。如果有人设置了简单密码,又没仅密钥登录,就很容易被爆破。强烈建议修改默认的用户名,教程在这里
#仅允许密钥登录
有密码就有被爆破的风险,目前普遍的做法是仅允许密钥登录。首先把自己的密钥添加到用户根目录的.ssh/authorized_keys
中,如果没有这个文件夹与文件,要手动建文件夹,添加文件。
mkdir ~/.ssh
cd ~/.ssh
nano authorized_keys
把公钥粘贴进去,保存。然后修改authorized_keys
文件权限为 600
,保护起来。
chmod 600 authorized_keys
这是已经可以通过密钥登录了,尝试一下,不需要密码就可以登录。 接下来修改 sshd 配置,禁止密码登录
sudo nano /etc/ssh/sshd_config
找到PasswordAuthentication
这一行,删除注释,把值改为 no
,重启sshd
服务。注意PasswordAuthentication
默认为yes
,只有显性修改为no
才有效,然后一定记得重启sshd
服务,应用修改。很多人修改了配置却不应用……
如果修改为仅允许密钥登录,那么密钥一定要保护好,同时要备份,如果本地的密钥没了(比如电脑被抢),又没有备份,那可能会永久丢失数据。可以把密钥内容抄到纸上,放进保险箱。或者替换几个字母,混淆加密,存到网盘/GitHub等,都是能接受的做法。
#自动 ban 掉乱试的 ip
密钥登录也有限制,就是只能在存放密钥的电脑上登录,当然,你可以多台电脑共用密钥,或者设置允许多个密钥登录,但是都需要增加额外的步骤。有时候我们不能限制密码登录,比如需要在不同的机器上登录服务器,甚至在服务器登录服务器。一个简单的情境:临时需要在同学的电脑上紧急修复一个 bug。那么,增加密码登录的安全就很重要了。
最基础的操作:不适用默认用户名,禁止 root 登录,不使用弱口令,不同机器使用不同密码。除此之外,还可以使用一些工具 ban 掉疯狂尝试登录的坏 ip。其中一个是fail2ban
。它可以设置在密码输错几次后,禁止某一 ip 一定的时间,增加爆破需要的时间,提高安全等级。
即使设置了仅密钥登录,也建议安装这个工具:有人想撬开你家大门,即使他撬的大门是假的,永远打不开,你也想赶走他。
sudo apt install fail2ban
fail2ban
每次更新时,可能覆盖默认配置,因此先生成一个本地配置,然后再修改
sudo cp /etc/fail2ban/jail.{conf,local}
sudo nano /etc/fail2ban/jail.local
需要关系的几个配置是:
[DEFAULT]
bantime = 1d
maxretry = 3
findtime = 5m
用普通话讲一下,就是,在{findtime}内,某个ip出错{maxretry}次,就禁止他登录{bantime},上面的例子翻译出来就是,在5分钟内,如果一个 ip 出错 3 次,就禁止他登录 1 天。
fail2ban 不仅支持 ssh,还可以应用到其他服务,因此要设置 sshd 的相关设置。
在上述配置文件中找到[sshd]
这一系列,加入enabled = true
,开启针对 ssh 的监狱(jail)
[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
然后重启服务。
sudo systemctl restart fail2ban
然后可以通过 sudo fail2ban-client banned
查看状态
看起来成功了,但是我 ban 了自己,断开全部连接,仍旧可以在 ban 时间段内连接。查看 iptables, 发现确实加入了一条 drop 规则……不知道为什么不好用。可能是有地方设置的不对,或者与ufw
冲突了。
这个 fail2ban 对cpu/ram
的消耗好像有点高,看前几年的 GitHub Issue,有很多关于性能消耗的。如果通过 iptables 来一个个 drop ,那么 ban 很多 ip 的话。的确会损失一些性能,而且因为 ban 时间区间,后台的服务可能要一直判断是不是到时间了,要把 ip 放出来,所以对计算资源的消耗是有的。独服还好,小一点的 vps 还是人工频繁看日志吧。
#附录
#last --help
Usage:
last [options] [<username>...] [<tty>...]
Show a listing of last logged in users.
Options:
-<number> how many lines to show
-a, --hostlast display hostnames in the last column
-d, --dns translate the IP number back into a hostname
-f, --file <file> use a specific file instead of /var/log/wtmp
-F, --fulltimes print full login and logout times and dates
-i, --ip display IP numbers in numbers-and-dots notation
-n, --limit <number> how many lines to show
-R, --nohostname don't display the hostname field
-s, --since <time> display the lines since the specified time
-t, --until <time> display the lines until the specified time
-p, --present <time> display who were present at the specified time
-w, --fullnames display full user and domain names
-x, --system display system shutdown entries and run level changes
--time-format <format> show timestamps in the specified <format>:
notime|short|full|iso
-h, --help display this help
-V, --version display version