近期,我在阿里云上以学生的身份购买了一年的服务器。我的初心只是纯玩而已,单纯想体验一下服务器环境而已,另外还可以学一些服务器运维的知识。 我在使用Arch Linux的过程中意识到,带着玩心和好奇心去折腾,往往比带着功利的目的学得更快、更扎实。我购买的实例的系统配置是Debian 13.5 64位,主要是因为Debian是真正的“教科书级”纯净系统和其“坚如磐石”的稳定性。在体验服务器系统之前,有一些必要的配置,我在这篇文章中简单地记录一下。
大部分云厂商(包括阿里云)的 Linux 服务器在创建时,默认都是以 root 用户登录的。阿里云通常会给用户一个默认管理员账户 root ,通常会让用户选择或设置 root 用户的密码(或者绑定 SSH 密钥)。然后用户用ssh root@服务器公网IP 登录。此时登录系统后,用户的权限便是最高权限 root ,这会带来一些问题,比如误操作问题,root 拥有系统的最高权限,一个随手的 rm -rf / 或者配错环境变量就可能让系统直接崩溃;还有安全问题,互联网上有无数的脚本在 24 小时无差别扫描云服务器的 22 端口(SSH),并尝试用 root 作为用户名去猜密码,一旦被密码被暴力破解,攻击者进入系统,而且拿到的是最高权限,这是一件多么糟糕的事情!所以,工欲善其事,必先利其器,一些前置的工作还是很有必要做好的。
创建普通用户 + sudo
当我们以 root 身份登入系统后,第一步便是创建新用户。在 Debian 中,有两个命令可以创建用户:useradd 和 adduser ,这里强烈推荐使用 adduser:这是一个交互式的 Perl 脚本,它会自动帮你创建家目录、配置 Shell、并提示你输入密码,非常省心。运行以下命令(将 myuser 替换你想用的用户名,比如你的英文名):
1 | adduser myuser |
命令执行后,终端会提示:
1 | New password: // 输入密码 |
创建好新用户后,便是为新用户安装并配置 sudo 权限。Debian 默认的最小化安装里,可能没有预装 sudo 命令,而且普通用户默认也无法执行系统级命令。首先先检查并确保系统里安装了 sudo:
1 | apt update && apt install sudo |
将新用户加入 sudo 用户组,在 Debian 中,只要用户属于 sudo 组,就自动拥有了管理员权限。执行以下命令:
1 | usermod -aG sudo myuser |
-a 代表 append(追加),-G 代表 group(用户组),合起来就是把用户追加到指定的组里,而不影响他原本所在的组。完成这一步后,另外开一个本地终端窗口(先别关当前的 root 窗口,留作后路),尝试用新用户登录:
1 | ssh myuser@你的服务器公网IP |
登录成功后,测试一下它的 sudo 权限是否正常。比如试着更新一下软件源:
1 | sudo apt update |
系统会提示你输入当前新用户的密码(而不是 root 密码)。如果能正常刷出软件源列表,说明你的普通用户已经配置完成!这还没有结束,接下来我们要完成云服务器安全配置中最关键的“最后一块拼图”——禁用以 root 身份登录。
禁止 root SSH 登录
在上文中,我们了解到在互联网上,云服务器公网 IP 是一片“荒原”。几乎每秒钟都有遍布全球的自动化扫描脚本(Botnets)在疯狂尝试连接所有在线服务器的 22 端口。这些脚本默认的攻击目标就是 root 用户。因为它们知道 root 必然存在,且权限最高。一旦用户禁用了 root 远程登录,攻击者不仅需要破解密码,还得先猜出你的用户名。如果再配合 SSH 密钥(Public Key Authentication),即便攻击者有超级计算机,在没有私钥的情况下也几乎无法进入。
在操作前请务必记住:不要关闭当前已经连上的 root 终端窗口! 这是“救命稻草”,万一配置错了,还可以通过这个窗口改回来。
使用 root 权限打开 SSH 服务配置文件:
1 | sudo vim /etc/ssh/sshd_config |
在文件中找到 PermitRootLogin 这一行。如果前面有 # 号,把 # 去掉,然后将后面的参数改为 no。在重启服务前,建议检查一下语法是否有误:
1 | sudo sshd -t |
如果没有报错,执行重启:
1 | sudo systemctl restart sshd |
然后执行以下命令:
1 | sudo sshd -T | grep permitroot |
如果输出:
1 | login |
说明配置完成。
配置 SSH 公钥登录
配置 SSH 密钥登录是迈向“生产环境运维”最重要的里程碑。SSH 密钥登录完全摒弃了传统的密码传输,改用公钥(Public Key)与私钥(Private Key)机制。服务器只保存你的公钥,只要你能证明你持有对应的私钥,服务器就信任你。在这里,我们只是记录配置过程,对于其深处的密码学原理,我们暂不追究,也许未来我会在另一篇文章中详细说明。
首先,我们需要在本地生成密钥对,在你的个人电脑(本地终端)上执行以下命令(引号中的内容可以根据自己的情况来写):
1 | ssh-keygen -t ed25519 -C "your_email@example.com" |
为什么要用 ed25519? 它是目前最现代、最安全的加密算法。相比老旧的 RSA,它的密钥更短,加解密速度更快,且抗攻击性更强。命令执行后,它会询问保存路径(一路回车即可)。它还会询问 Passphrase(密码短语),这相当于给你本地的私钥加了一层锁,建议设置一个,即使你的电脑丢了,别人也无法直接使用你的私钥。
接下来,我们需要将公钥上传到服务器。推荐使用 ssh-copy-id 自动上传,在本地终端运行以下命令:
1 | ssh-copy-id 用户名@服务器IP |
系统会提示你输入一次服务器的密码,直接输入并回车即可。
如果无法使用上述命令,可以手动复制粘贴公钥内容到服务器,首先先查看并复制本地公钥内容:
1 | cat ~/.ssh/id_ed25519.pub |
正常密码登录服务器,手动将复制的内容追加到服务器的 ~/.ssh/authorized_keys 文件中:
1 | mkdir -p ~/.ssh |
接下来便是测试SSH公钥登录是否配置完成,首先,我们需要新开一个本地终端窗口,尝试登录,如果配置正确,是不需要密码直接就可以进入服务器了。为了彻底防止黑客暴力破解密码,确认公钥登录成功后,建议关闭服务器的密码登录功能。
首先,我们需要在服务器上打开SSH配置文件:
1 | sudo vim /etc/ssh/sshd_config |
找到(或添加)以下两行,确保它们的值为 no 和 yes:
1 | PasswordAuthentication no |
需要注意的是,在较新的 Linux 系统中,/etc/ssh/sshd_config 的顶部通常有一行: Include /etc/ssh/sshd_config.d/*.conf ,这意味着系统会优先或追加读取 /etc/ssh/sshd_config.d/ 文件夹下的配置文件,那里的配置会覆盖主文件。我们需要检查该目录下是否有其他配置文件干扰:
1 | cat /etc/ssh/sshd_config.d/*.conf |
如果发现某个 .conf 文件里写了 PasswordAuthentication yes(比如 50-cloud-init.conf),直接编辑那个文件,将其修改为 no 。保存退出,并重启 SSH 服务生效:
1 | sudo systemctl restart sshd |
接下来,我们需要测试配置是否已经完成,在本地新开一个终端,运行以下命令:
1 | ssh -o PubkeyAuthentication=no 用户名@服务器IP |
如果终端输出是 Permission denied (publickey). ,则说明我们的配置是成功的。
修改SSH端口
将 SSH 的默认 22 端口改为其他端口(如 2222)可以有效减少互联网上绝大多数针对 22 端口的自动化恶意扫描和暴力破解。注意在确认新端口完全畅通之前,绝对不要关闭当前的 SSH 窗口,且建议先让 22 和 2222 端口同时监听。
我们打开SSH配置文件:
1 | sudo vim /etc/ssh/sshd_config |
在文件中找到 #Port 22 这一行(默认可能是被 # 注释掉的),改成以下内容:
1 | Port 22 |
现在,我们需要先保留 22,先同时启用 2222 端口,等测试成功后再删掉 22 端口。如果系统有前面提到的 sshd_config.d/ 干扰文件,需要确保两边配置不要冲突。还有重要的一点是你必须告诉云厂商和系统防火墙放行 2222 端口,这步操作需要在对应的厂商的控制台完成。
接下来,重启 SSH 服务让配置生效:
1 | sudo systemctl restart sshd |
验证端口是否已经成功监听:
1 | ss -ntlp | grep 2222 |
如果终端出现以下输出,则说明 2222 端口已经成功监听。
1 | LISTEN 0 128 0.0.0.0:2222 0.0.0.0:* |
现在我们只需要在本地电脑开新终端进行最后的连通性测试,运行以下命令:
1 | ssh -p 2222 用户名@服务器IP |
如果成功登录,说明 2222 端口已经成功开启。现在可以回到服务器上,放心地把 sshd_config 里的 Port 22 注释掉,只留下 Port 2222,然后重启 sshd 彻底对公网关闭 22 端口。
配置防火墙
防火墙的作用不是让服务器“绝对安全”,而是控制网络入口,减少不必要的暴露,让攻击者只能接触到你明确允许开放的服务。现在我们已经把 SSH 端口改成了 2222,并且彻底关闭了 22 端口,那么现在配置防火墙的核心任务就两个:死守 2222 端口(确保你自己能进去,别把自己锁在外面)和彻底封闭 22 端口以及其他不必要的系统端口。在服务器厂商提供的环境下,防火墙其实分为两层,一层是厂商安全组,另一层是系统内部防火墙。为了保证绝对安全和配置生效,我们需要两层都配置好。
厂商安全组是服务器外面的第一道防线,效率极高,不消耗用户服务器的 CPU。对此的相关配置,我们需要登录厂商提供的控制台界面,修改相应的配置规则(主要是入方向规则的修改)即可。
第二层便是系统内部的防火墙,由于我使用的是debian系统,这里主要介绍 ufw 的配置过程。首先,我们需要安装并检查ufw 的状态,执行以下命令:
1 | sudo apt update && sudo apt install ufw |
如果显示 Status: inactive,说明防火墙目前是关闭的。可能你们的想法是直接开启防火墙服务,但是这不是正确的想法。在开启防火墙之前,我们必须先把 2222 端口放行,否则一旦开启我们就会被立刻踢出服务器。接下来就是配置放行策略的过程,运行以下命令,注意要按照顺序执行。
1 | sudo ufw default deny incoming |
前两条命令的目的是设置默认策略,即拒绝所有入站流量,允许所有出站流量,接下来我们所做的是放行新的SSH端口,对于其他的端口是否开放,在未来用到的时候再考虑就行了。接下来,我们正式启动防火墙,运行命令:
1 | sudo ufw enable |
终端会弹出一个警告:Command may disrupt existing ssh connections. Proceed with operation (y|n)? 不用慌,因为我们已经写了 allow 2222/tcp,敲 y 然后回车。当看到Firewall is active and enabled on system startup 时,说明防火墙已经成功运行。接下来我们来检查结果,运行命令:
1 | sudo ufw status verbose |
输出应该是以下内容:
1 | Status: active |
安装 fail2ban
fail2ban 的工作原理非常硬核且有效:它会实时监控系统的日志文件(如 /var/log/auth.log)。一旦发现某个 IP 在短时间内不断尝试错误的密钥、错误的端口或者密码(即使你禁用了密码,黑客的自动化脚本仍会产生恶意请求日志),fail2ban 就会直接调用系统防火墙,把这个 IP 扔进小黑屋(封禁其 IP 访问),持续几小时甚至几天。在完成了以上配置之后,引入 fail2ban 就是为服务器披上的最后一套主动防御铠甲。
首先,我们需要安装fail2ban ,运行以下命令:
1 | sudo apt update && sudo apt install fail2ban |
安装完成后,fail2ban 会自动创建一个名为 fail2ban 的系统服务,并默认处于启动状态。运行以下命令查看fail2ban 的状态:
1 | systemctl status fail2ban |
接下来就是配置过程了。fail2ban 的默认配置文件位于 /etc/fail2ban/jail.conf。但是,绝对不要直接修改这个文件,因为以后软件更新时它会被覆盖。正确做法是创建一个名为 jail.local 的副本,fail2ban 会自动读取它并覆盖默认设置。运行以下命令创建本地配置文件:
1 | sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local |
编辑配置文件:
1 | sudo vim /etc/fail2ban/jail.local |
修改全局默认配置参数,找到[DEFAULT] 模块,按需调整以下几个核心参数:
1 | bantime = 1h # 违规后的封禁时间(1h表示1小时,也可以设为1d天) |
接着是启用并配置 SSH 监控模块,继续向下滚动,找到 [sshd] 模块(或者直接在文件末尾添加以下内容)。必须将端口改为前面改过的 2222:
1 | [sshd] |
改好后在终端运行以下命令让配置彻底生效:
1 | sudo systemctl restart fail2ban |
运行以下命令,查看当前 sshd 监狱的实时运行状态:
1 | sudo fail2ban-client status sshd |
应该在终端中看到这样的输出:
1 | Status for the jail: sshd |
这样fail2ban 的安装和配置就完成了。
到这里,服务器安全防御体系(普通用户 + 公钥登录 + 隐蔽端口 + 双重防火墙 + Fail2ban 动态封禁)已经全部闭环!对于一位服务器用户来说,一个安全的环境是进行开发不可或缺的条件。在自由度极高的 Linux 世界里,安全不是一个静态的终点,而是一个动态演进的过程。