返回文章列表
网络安全

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

七木
2026-02-26
1天前
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 verbose

CentOS 系用 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 --reload

iptables 的话,老系统或者需要精细控制才用,规则写起来麻烦但灵活:

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.local

Fail2ban,让暴力破解自动凉凉

光有防火墙还不够,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 deploy

sudo 权限这块,我见过很多人直接给 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,这几步做完,能挡掉绝大多数自动化攻击。剩下的,就是保持习惯。


本文内容仅供参考,不构成任何专业建议。使用本文提供的信息时,请自行判断并承担相应风险。

分享文章
合作伙伴

本站所有广告均是第三方投放,详情请查询本站用户协议