Linux 服务器安全配置:SSH 禁用密码 + 密钥登录 + 改端口教程

服务器挂在公网上,说白了就是把家门开着睡觉。你不知道什么时候有人进来,但你可以确定的是——一定有人在试。我见过太多人觉得"我这服务器没啥重要数据,没人盯着我",然后某天发现机器在挖矿,或者带宽被打满了,账单直接炸。
所以这事不是可选项。
SSH,从这里开始
SSH 是被攻击最多的入口,没有之一。默认配置放在那里,基本等于在门口贴了张纸写着"欢迎进来"。
先把 root 登录关掉:
# /etc/ssh/sshd_configPermitRootLogin no然后是密码登录——这个必须禁掉。密码可以被暴力破解,密钥不行,这是本质区别。不过有个顺序问题,一定要先把密钥配好,再禁密码,别把自己锁外面了,这个坑我见人踩过不止一次。
# 本地生成密钥,ed25519 比老的 rsa 安全ssh-keygen -t ed25519 -C "your_email@example.com"# 传公钥上去ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server传完再改配置:
# /etc/ssh/sshd_configPasswordAuthentication noPubkeyAuthentication yes端口也改一下,22 这个端口每天被扫的次数,你看了日志真的会头皮发麻。改成非标准端口,能过滤掉绝大多数无脑扫描,不是说改了就绝对安全,但能省很多事。
Port 22222还有一个容易被忽略的——限制哪些用户能登录:
AllowUsers deploy admin把这些拼在一起,完整配置大概长这样:
Port 22222PermitRootLogin noPasswordAuthentication noPubkeyAuthentication yesAllowUsers deploy adminMaxAuthTries 3ClientAliveInterval 300ClientAliveCountMax 2X11Forwarding no改完别急着重启,先测一下:
sshd -tsystemctl restart sshd防火墙,默认拒绝一切
这块的核心逻辑就一句话:不需要的端口,一个都不开。很多人装完系统就直接用,防火墙规则乱七八糟,或者干脆没配。
Ubuntu 用 UFW,简单直接:
apt install ufwufw default deny incomingufw default allow outgoing# 注意,先放行 SSH 再启用,顺序别搞反ufw allow 22222/tcpufw allow 80/tcpufw allow 443/tcp# 数据库端口只给特定 IPufw allow from 192.168.1.100 to any port 3306ufw enableufw status verboseCentOS 系用 firewalld:
systemctl start firewalldsystemctl enable firewalldfirewall-cmd --permanent --add-service=httpfirewall-cmd --permanent --add-service=httpsfirewall-cmd --permanent --add-port=22222/tcp# 精细控制,只允许某个 IP 访问 MySQLfirewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port port="3306" protocol="tcp" accept'firewall-cmd --reloadiptables 的话,老系统或者需要精细控制才用,规则写起来麻烦但灵活:
iptables -P INPUT DROPiptables -P FORWARD DROPiptables -P OUTPUT ACCEPTiptables -A INPUT -i lo -j ACCEPTiptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPTiptables -A INPUT -p tcp --dport 22222 -j ACCEPTiptables -A INPUT -p tcp --dport 80 -j ACCEPTiptables -A INPUT -p tcp --dport 443 -j ACCEPTiptables-save > /etc/iptables.rulesecho "iptables-restore < /etc/iptables.rules" >> /etc/rc.localFail2ban,让暴力破解自动凉凉
光有防火墙还不够,Fail2ban 是用来对付那些一直在试密码的人的。原理很简单:盯着日志,某个 IP 短时间失败太多次,直接封。
apt install fail2bancp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local基本配置,SSH 这块我建议封禁时间设长一点,24 小时不过分:
# /etc/fail2ban/jail.local[DEFAULT]bantime = 3600findtime = 600maxretry = 5ignoreip = 127.0.0.1/8 192.168.1.0/24[sshd]enabled = trueport = 22222filter = sshdlogpath = /var/log/auth.logmaxretry = 3bantime = 86400跑 Web 服务的话,Nginx 也加上:
[nginx-http-auth]enabled = truefilter = nginx-http-authport = http,httpslogpath = /var/log/nginx/error.log[nginx-botsearch]enabled = truefilter = nginx-botsearchport = http,httpslogpath = /var/log/nginx/access.logmaxretry = 2还可以自定义过滤规则,专门针对那些乱扫 404 的爬虫:
# /etc/fail2ban/filter.d/nginx-cc.conf[Definition]failregex = ^<HOST> .* "(GET|POST).* HTTP.*" (404|444|403|400) .*$ignoreregex =[nginx-cc]enabled = truefilter = nginx-ccport = http,httpslogpath = /var/log/nginx/access.logmaxretry = 100findtime = 60bantime = 3600常用的管理命令记几个就行:
fail2ban-client status sshd # 看封了哪些 IPfail2ban-client set sshd unbanip 1.2.3.4 # 解封,误封了自己用这个fail2ban-client set sshd banip 1.2.3.4 # 手动封tail -f /var/log/fail2ban.log用户权限,别偷懒
最小权限原则,道理大家都懂,但真正做到的不多。
创建专用部署用户,别什么都用 root 跑:
useradd -m -s /bin/bash deploypasswd deployusermod -aG sudo deploysudo 权限这块,我见过很多人直接给 NOPASSWD:ALL,图省事,但这跟直接用 root 没太大区别。稍微细化一下,只给需要的命令:
# /etc/sudoers.d/deploydeploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginxdeploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart php8.2-fpmdeploy ALL=(ALL) NOPASSWD: /usr/bin/docker-compose *文件权限别乱给,敏感文件 600 就够了:
chown -R www-data:www-data /var/www/htmlchmod -R 755 /var/www/htmlchmod 600 /var/www/html/.envchmod 600 ~/.ssh/authorized_keys系统层面的加固
装完系统默认跑着一堆没用的服务,关掉:
systemctl list-units --type=service --state=running # 先看看有什么systemctl disable cups # 打印服务,服务器用不上systemctl disable avahi-daemonsystemctl disable bluetooth内核参数这块,改一下 sysctl.conf,能防一些常见的网络攻击:
# /etc/sysctl.confnet.ipv4.ip_forward = 0net.ipv4.conf.all.accept_redirects = 0net.ipv4.conf.default.accept_redirects = 0net.ipv4.tcp_syncookies = 1 # 防 SYN 洪水,这个一定要开net.ipv4.conf.all.accept_source_route = 0net.ipv4.icmp_echo_ignore_broadcasts = 1net.ipv4.conf.all.log_martians = 1sysctl -p自动安全更新,Ubuntu 上装一下,至少安全补丁能自动打:
apt install unattended-upgradesdpkg-reconfigure unattended-upgrades# /etc/apt/apt.conf.d/50unattended-upgradesUnattended-Upgrade::Allowed-Origins { "${distro_id}:${distro_codename}-security";};Unattended-Upgrade::Automatic-Reboot "false";Unattended-Upgrade::Mail "admin@example.com";数据库,这块别马虎
MySQL 装完跑一下这个,按提示操作,能解决大部分默认配置的问题:
mysql_secure_installation业务账号单独建,不要用 root 跑应用,权限给够用的就行:
CREATE USER'app'@'localhost'IDENTIFIEDBY'strong_password';GRANTSELECT, INSERT, UPDATE, DELETEON myapp.* TO'app'@'localhost';FLUSHPRIVILEGES;-- root 禁止远程登录DELETEFROM mysql.user WHEREUser='root'AND Host NOTIN ('localhost', '127.0.0.1', '::1');FLUSHPRIVILEGES;Redis 这个,坦白说很多人装完就忘了,默认没密码还绑在 0.0.0.0,暴露在公网上是真的危险:
# /etc/redis/redis.confbind 127.0.0.1requirepass your_strong_passwordrename-command FLUSHDB ""rename-command FLUSHALL ""rename-command CONFIG ""rename-command KEYS ""Nginx 和 PHP 的安全配置
Nginx 加几个安全头,顺手的事:
server_tokens off; # 别让人知道你的版本号add_header X-Frame-Options "SAMEORIGIN" always;add_header X-Content-Type-Options "nosniff" always;add_header X-XSS-Protection "1; mode=block" always;add_header Referrer-Policy "strict-origin-when-cross-origin" always;add_header Content-Security-Policy "default-src 'self'" always;# .git、.env 这些文件绝对不能暴露location ~ /\.(git|env|htaccess) { deny all;}location ~ \.(sql|bak|log)$ { deny all;}PHP 这边,禁掉危险函数,关掉错误显示:
disable_functions = exec,passthru,shell_exec,system,proc_open,popenexpose_php = Offupload_max_filesize = 10Mmax_file_uploads = 5session.cookie_httponly = 1session.cookie_secure = 1session.use_strict_mode = 1display_errors = Offlog_errors = Onerror_log = /var/log/php/error.log审计和监控,别等出事了再看
grep "Failed password" /var/log/auth.log | tail -20grep "sudo" /var/log/auth.log | tail -20文件完整性检查,AIDE 装上,定期跑一下,看有没有文件被动过:
apt install aideaideinitaide --check一键安全检查脚本,加到 crontab 里每天跑一次,有问题早发现:
#!/bin/bashecho"=== 安全检查报告 ==="echo"1. SSH 配置"grep -E "^(PermitRootLogin|PasswordAuthentication|Port)" /etc/ssh/sshd_configecho"2. 开放端口"ss -tulpn | grep LISTENecho"3. 最近登录失败"grep "Failed password" /var/log/auth.log 2>/dev/null | tail -5echo"4. 当前登录用户"whoecho"5. 磁盘使用"df -h | grep -E "^/dev"echo"6. 内存使用"free -hecho"7. 待更新包"apt list --upgradable 2>/dev/null | head -10echo"8. Fail2ban 状态"fail2ban-client status 2>/dev/null || echo"Fail2ban 未安装"最后说一句,安全这事不是配完就完了。定期检查,关注漏洞公告,补丁出来及时打。很多安全事故说到底不是技术问题,是懒。
改个 SSH 端口、禁掉密码登录、装个 Fail2ban,这几步做完,能挡掉绝大多数自动化攻击。剩下的,就是保持习惯。
本文内容仅供参考,不构成任何专业建议。使用本文提供的信息时,请自行判断并承担相应风险。



