ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

CentOS 7服务器SSH安全加固与系统初始化配置实战指南

CentOS 7服务器SSH安全加固与系统初始化配置实战指南

1. 项目概述

最近在整理服务器运维的实战笔记,发现很多新手朋友甚至一些有经验的同行,在拿到一台全新的 CentOS 7 服务器后,直接就开干了。结果没过多久,服务器就被各种扫描脚本盯上,轻则资源被占,重则数据泄露。这让我想起自己刚入行时踩过的坑,所以决定把 SSH 安全加固和 CentOS 7 初始化配置这两个最基础、也最关键的环节,系统地梳理一遍。这不仅仅是改几个配置参数,而是一套从外到内、层层设防的服务器“开箱即用”安全基线。无论你是个人开发者管理 VPS,还是企业运维负责生产环境,这套流程都能帮你快速建立一个稳固的起点,把绝大多数低级攻击挡在门外。接下来,我会结合最新的工具和常见的攻击手法,带你一步步操作,并解释清楚每一步背后的“为什么”。

2. SSH 安全加固:从“门户大开”到“固若金汤”

SSH 是通往服务器的唯一大门,默认配置就像给这道门装了一把家家户户都一样的锁。安全加固的核心,就是换锁、加监控、设门槛,让攻击者无从下手。

2.1 修改默认端口:告别22端口的“扫射”

默认的 22 端口是全世界扫描器的首要目标。修改端口是成本最低、效果最显著的防护措施之一。

操作步骤与原理:

  1. 备份配置文件:这是所有系统修改前的铁律。执行cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
  2. 编辑 SSH 配置文件:使用vim /etc/ssh/sshd_config打开文件。找到#Port 22这一行(通常在文件靠前部分)。
  3. 取消注释并修改:删除行首的#号,并将22改为一个你自定义的端口号,例如Port 23456。这里有个关键点:端口号应在 1024 到 65535 之间,且避免使用像 2222、22222 这样过于常见的替代端口。
  4. 保存并重启服务:按Esc键,输入:wq保存退出。执行systemctl restart sshd重启 SSH 服务使配置生效。

注意:在重启sshd服务前,千万不要关闭当前的 SSH 连接窗口。你应该新开一个终端窗口,用新端口尝试连接,确认成功后再关闭旧会话。否则一旦新端口不通,你将失去服务器连接。

防火墙与安全组配置:修改端口后,必须同步更新防火墙规则。CentOS 7 默认使用firewalld

  • 查看当前防火墙状态:systemctl status firewalld
  • 如果未运行,需启动并设置开机自启:systemctl start firewalld && systemctl enable firewalld
  • 开放新端口:firewall-cmd --permanent --add-port=23456/tcp
  • 移除旧的 22 端口(可选但建议):firewall-cmd --permanent --remove-port=22/tcp
  • 重载防火墙配置:firewall-cmd --reload
  • 验证端口是否开放:firewall-cmd --list-ports

如果你使用的是云服务器(如阿里云、腾讯云、华为云等),还需在云平台的安全组规则中,添加入方向规则,允许你的新 SSH 端口(如 23456/TCP)。切记,在安全组中移除或禁用默认的 22 端口入站规则。

2.2 禁用密码登录,强制使用密钥对:从根本上杜绝暴力破解

密码登录面临暴力破解和密码泄露的风险。SSH 密钥对(公钥加密,私钥解密)在数学上几乎不可破解,是更安全的身份验证方式。

生成密钥对(在本地客户端进行):在你自己常用的电脑(Linux/macOS 终端或 Windows 的 Git Bash/WSL)上操作:

ssh-keygen -t rsa -b 4096 -C “your_email@example.com” -f ~/.ssh/my_centos7_key
  • -t rsa: 指定密钥类型为 RSA。
  • -b 4096: 指定密钥长度为 4096 位,安全性更高。
  • -C: 添加一个注释,通常用邮箱,便于识别。
  • -f: 指定密钥文件的保存路径和名称。

命令会生成两个文件:my_centos7_key(私钥,必须严格保密)和my_centos7_key.pub(公钥,需上传到服务器)。

部署公钥到服务器:

  1. 将公钥内容追加到服务器的~/.ssh/authorized_keys文件中。最安全的方式是使用ssh-copy-id命令(如果本地支持):
    ssh-copy-id -i ~/.ssh/my_centos7_key.pub -p 23456 username@your_server_ip
    如果无法使用ssh-copy-id,可以手动操作:
    • 在服务器上,确保~/.ssh目录存在且权限为700mkdir -p ~/.ssh && chmod 700 ~/.ssh
    • 将本地公钥文件内容,复制粘贴到服务器的~/.ssh/authorized_keys文件中(可使用cat >>命令追加)。
    • 设置authorized_keys文件权限为600chmod 600 ~/.ssh/authorized_keys

配置 SSH 服务端禁用密码登录:再次编辑/etc/ssh/sshd_config

  1. 找到PasswordAuthentication选项,将其改为no
  2. 找到PubkeyAuthentication选项,确保其为yes(默认通常是)。
  3. (可选但推荐)禁用空密码:PermitEmptyPasswords no
  4. (强烈推荐)禁止 root 用户直接登录:找到PermitRootLogin,将其改为noprohibit-password(如果必须密钥登录 root)。日常使用普通用户通过 SSH 登录,再用susudo提权。
  5. 保存并重启 SSH 服务:systemctl restart sshd

测试与故障排查:

  • 测试密钥登录:ssh -i ~/.ssh/my_centos7_key -p 23456 username@your_server_ip
  • 如果失败,检查服务器/var/log/secure日志文件,通常会有详细的错误信息。常见问题包括:authorized_keys文件权限不对、私钥权限太开放(应为600)、sshd_configPubkeyAuthentication未开启。

2.3 使用 Fail2ban 动态封禁攻击者:主动防御

Fail2ban 是一个入侵防御框架,它监控系统日志(如/var/log/secure),当发现同一 IP 在短时间内多次进行失败的 SSH 登录尝试时,会自动调用防火墙规则(如iptablesfirewalld)将该 IP 封禁一段时间。

安装与配置:

  1. 安装 Fail2ban:yum install epel-release -y && yum install fail2ban -y
  2. 创建本地配置文件(避免升级被覆盖):cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
  3. 编辑/etc/fail2ban/jail.local,找到[sshd]段落,进行关键配置:
    [sshd] enabled = true port = 23456 # 这里务必改成你修改后的 SSH 端口! filter = sshd logpath = /var/log/secure maxretry = 5 # 最大重试次数 findtime = 600 # 在10分钟内 bantime = 3600 # 禁止访问1小时 action = firewallcmd-ipset # 使用 firewalld 作为动作
  4. 启动并设置开机自启:systemctl start fail2ban && systemctl enable fail2ban
  5. 查看状态:fail2ban-client status sshd可以查看当前被禁用的 IP 列表。

实操心得:

  • bantime可以设置得长一些,比如86400(一天),对于明显的攻击行为,封禁久一点没关系。
  • 可以将自己的 IP 添加到ignoreip配置项中,防止自己因操作失误被误封。
  • 定期检查/var/log/fail2ban.log了解封禁情况。

2.4 其他高级加固选项

/etc/ssh/sshd_config中,还可以考虑以下设置:

  • Protocol 2: 强制使用 SSH 协议版本 2,禁用不安全的版本 1。
  • LoginGraceTime 30: 设置登录超时时间为 30 秒,防止客户端长时间占用未认证的连接。
  • MaxAuthTries 3: 设置每个连接最大认证尝试次数为 3 次。
  • AllowUsers your_username: 仅允许指定的用户通过 SSH 登录,白名单机制最安全。
  • UseDNS no: 禁用 DNS 反向解析,可以加快 SSH 登录速度,尤其是在 DNS 服务器不佳的环境中。

完成所有 SSH 配置后,务必执行systemctl restart sshd重启服务,并使用新端口和新密钥方式进行登录测试,确保一切正常后再关闭原有连接。

3. CentOS 7 系统初始化配置:打造稳定高效的运行环境

SSH 大门锁好后,我们就要对系统内部进行一番“精装修”,使其更安全、高效、易于管理。

3.1 系统更新与基础工具安装

一个过时的系统是漏洞的温床。第一步永远是更新。

# 更新系统所有包到最新版本 sudo yum update -y # 安装常用的工具集,如网络工具、压缩解压、进程查看等 sudo yum install -y vim wget curl net-tools lsof telnet tree htop iftop iotop ncdu psmisc yum-utils
  • yum update会更新所有已安装的软件包,包括内核。如果涉及内核更新,需要重启生效。
  • 安装的这些工具是日常运维的“瑞士军刀”,htoptop更直观,iftop/iotop用于监控网络/磁盘 IO。

3.2 配置防火墙(Firewalld)策略

CentOS 7 的firewalldiptables配置更动态、易管理。我们配置一个“默认拒绝,按需开放”的策略。

# 1. 设置默认区域为 public,并配置默认策略 sudo firewall-cmd --set-default-zone=public sudo firewall-cmd --runtime-to-permanent # 将运行时配置转为永久配置 # 2. 移除不必要的服务(如果不需要) sudo firewall-cmd --remove-service=dhcpv6-client --permanent # 3. 根据你的服务开放端口(示例) # 假设你运行了 Web 服务 (80, 443) 和自定义的 SSH 端口 23456 sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-service=https sudo firewall-cmd --permanent --add-port=23456/tcp # 4. 重载防火墙使配置生效 sudo firewall-cmd --reload # 5. 查看当前生效的规则 sudo firewall-cmd --list-all

注意事项:

  • 使用--permanent参数使规则永久生效,否则重启后丢失。
  • firewall-cmd --reload会重载配置并保持现有连接,比--complete-reload(中断所有连接)更友好。
  • 对于复杂的规则,可以考虑使用rich-rule,或者直接编写firewalld的 XML 区域文件。

3.3 配置时间同步(NTP/Chrony)

服务器时间不准会导致日志时间错乱、证书验证失败等问题。CentOS 7 默认使用chronyd服务。

# 1. 安装 chrony(通常已预装) sudo yum install -y chrony # 2. 编辑配置文件,使用可靠的 NTP 服务器池 sudo vim /etc/chrony.conf # 可以将 server 开头的行替换为: server ntp.aliyun.com iburst server time1.cloud.tencent.com iburst server pool.ntp.org iburst # 3. 启动并设置开机自启 sudo systemctl start chronyd sudo systemctl enable chronyd # 4. 查看时间同步状态 chronyc sources -v chronyc tracking

iburst选项可以在服务启动时快速进行数次时间同步,加速初始同步过程。

3.4 禁用不必要的服务

最小化原则是安全的重要一环。禁用不需要的服务,减少攻击面。

# 查看所有开机自启的服务 systemctl list-unit-files --type=service | grep enabled # 常见的可考虑禁用的服务(根据实际情况判断): sudo systemctl disable postfix # 邮件服务,若无邮件需求 sudo systemctl disable avahi-daemon # 局域网服务发现,服务器通常不需要 sudo systemctl disable cups # 打印服务 # 注意:不要盲目禁用,需确认服务用途。生产环境建议在测试环境先验证。

3.5 配置系统资源限制与内核参数优化

通过修改/etc/security/limits.conf文件,可以调整用户或进程的资源限制,防止某个用户进程耗尽系统资源。

sudo vim /etc/security/limits.conf # 在文件末尾添加,例如: * soft nofile 65535 # 所有用户打开文件数的软限制 * hard nofile 65535 # 所有用户打开文件数的硬限制 * soft nproc 65535 # 所有用户进程数的软限制 * hard nproc 65535 # 所有用户进程数的硬限制

对于高并发应用(如 Web 服务器),可能还需要调整内核网络参数,编辑/etc/sysctl.conf

# 增加 TCP 连接队列大小 net.core.somaxconn = 65535 # 加快 TCP 连接回收 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_tw_recycle = 1 # 注意:在 NAT 环境下慎用此参数 # 增加系统最大文件描述符数 fs.file-max = 655350

修改后执行sysctl -p使配置生效。

3.6 创建具有 sudo 权限的普通用户

永远不要直接用 root 进行日常操作。创建一个具有sudo权限的普通用户。

# 1. 创建用户 sudo adduser opsuser # 2. 为用户设置密码 sudo passwd opsuser # 3. 将用户添加到 wheel 组(CentOS 中 wheel 组默认有 sudo 权限) sudo usermod -aG wheel opsuser

之后,你就可以使用opsuser登录,在需要执行特权命令时,在命令前加sudo

4. 安全审计与监控基线配置

配置完成后,需要建立简单的审计和监控,以便事后追溯和及时发现异常。

4.1 配置日志轮转与集中管理(可选)

确保系统日志不会无限增长占满磁盘。CentOS 7 使用logrotate

# 查看 SSH 日志的轮转配置 sudo vim /etc/logrotate.d/secure # 通常默认配置是合理的,如每周轮转,保留4周日志。

对于有多台服务器的情况,建议搭建一个集中的日志服务器(如 ELK Stack 或 Graylog),将各服务器的/var/log/secure/var/log/messages等关键日志收集起来,便于统一分析和告警。

4.2 安装并配置入侵检测工具(AIDE)

AIDE(Advanced Intrusion Detection Environment)是一个文件完整性检查工具,它建立一个系统文件的数据库,定期检查是否有文件被篡改、添加或删除。

# 1. 安装 AIDE sudo yum install -y aide # 2. 初始化数据库(在确认系统干净无木马后执行) sudo aide --init # 3. 将初始数据库移为正式数据库 sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz # 4. 手动进行一次检查 sudo aide --check # 5. 配置定时任务,每天自动检查并邮件报警(需配置邮件) sudo crontab -e # 添加一行,例如每天凌晨2点检查 0 2 * * * /usr/sbin/aide --check | mail -s “AIDE Report for $(hostname)” admin@yourdomain.com

首次运行aide --init可能需要几分钟,因为它要扫描大量文件并计算校验和。

4.3 配置系统审计规则(auditd)

auditd是 Linux 内核的审计框架,可以记录非常详细的事件,如文件访问、系统调用、用户命令等。对于安全要求高的环境非常有用。

# 1. 确保 auditd 已安装并运行 sudo systemctl start auditd sudo systemctl enable auditd # 2. 添加审计规则,例如监控 /etc/passwd 文件的写和属性更改 sudo auditctl -w /etc/passwd -p wa -k identity_access # -w 监控路径,-p 权限(r读,w写,x执行,a属性),-k 定义关键词 # 3. 查看审计日志 sudo ausearch -k identity_access

审计规则可以非常复杂,建议从监控关键系统文件(如/etc/passwd/etc/shadow/etc/sudoers)和敏感目录开始。

5. 自动化部署:使用 Ansible 剧本一键初始化

手动操作繁琐且容易出错。我们可以使用 Ansible 将以上所有步骤编写成 Playbook,实现自动化初始化。

5.1 Ansible Playbook 结构设计

创建一个项目目录,结构如下:

centos7-init/ ├── hosts.ini # 定义服务器清单 ├── site.yml # 主剧本入口 ├── roles/ │ ├── common/ # 基础配置角色 │ │ ├── tasks/main.yml │ │ ├── templates/ │ │ └── files/ │ ├── ssh_hardening/ # SSH加固角色 │ │ ├── tasks/main.yml │ │ ├── templates/sshd_config.j2 │ │ └── files/ │ └── security/ # 安全审计角色 │ ├── tasks/main.yml │ └── files/ └── group_vars/ └── all.yml # 定义全局变量

5.2 关键角色任务示例(ssh_hardening)

roles/ssh_hardening/tasks/main.yml内容示例:

--- - name: Backup original sshd_config copy: src: /etc/ssh/sshd_config dest: /etc/ssh/sshd_config.backup-{{ ansible_date_time.date }} remote_src: yes - name: Configure SSH daemon template: src: sshd_config.j2 dest: /etc/ssh/sshd_config owner: root group: root mode: ‘0644’ notify: restart sshd - name: Ensure .ssh directory exists for deploy user file: path: “{{ deploy_user_home }}/.ssh” state: directory owner: “{{ deploy_user }}” group: “{{ deploy_user }}” mode: ‘0700’ - name: Deploy authorized key for deploy user copy: src: files/authorized_keys dest: “{{ deploy_user_home }}/.ssh/authorized_keys” owner: “{{ deploy_user }}” group: “{{ deploy_user }}” mode: ‘0600’ - name: Install fail2ban yum: name: fail2ban state: present when: install_fail2ban | bool - name: Configure fail2ban for SSH template: src: jail.local.j2 dest: /etc/fail2ban/jail.local owner: root group: root mode: ‘0644’ when: install_fail2ban | bool notify: restart fail2ban

对应的sshd_config.j2模板文件(Jinja2格式),其中变量如ssh_portpermit_root_login等在group_vars/all.yml中定义:

Port {{ ssh_port }} Protocol 2 PermitRootLogin {{ permit_root_login }} PasswordAuthentication no PubkeyAuthentication yes UseDNS no MaxAuthTries 3 LoginGraceTime 30

5.3 执行与验证

在控制机上,使用以下命令执行 Playbook:

# 检查语法 ansible-playbook -i hosts.ini site.yml --syntax-check # 模拟运行(Dry-Run) ansible-playbook -i hosts.ini site.yml --check # 实际执行 ansible-playbook -i hosts.ini site.yml

执行完毕后,使用新的 SSH 端口和密钥尝试登录目标服务器,验证所有配置是否生效。通过 Ansible,你可以将这套初始化流程版本化管理,轻松复用到任意数量的新服务器上,确保环境的一致性。

6. 常见问题与排查技巧实录

在实际操作中,你肯定会遇到各种问题。这里记录了几个最典型的“坑”和解决方法。

6.1 SSH 连接失败问题排查流程图

当 SSH 无法连接时,按照以下顺序排查,可以解决 99% 的问题:

  1. 网络层
    • ping server_ip:检查服务器是否在线,网络是否可达。
    • telnet server_ip ssh_portnc -zv server_ip ssh_port:检查目标端口是否开放。如果不通,问题在服务器防火墙或云安全组。
  2. 服务层
    • 登录云控制台,通过 VNC 或救援模式连接服务器。
    • 检查 SSH 服务状态:systemctl status sshd
    • 检查配置文件语法:sshd -t。这个命令非常有用,能在重启前发现配置错误。
    • 查看 SSH 服务日志:journalctl -u sshd -ftail -f /var/log/secure。这里会明确告诉你拒绝连接的原因,如“Permission denied (publickey)”或“Address filtered”。
  3. 认证层
    • 如果是密钥登录失败,检查客户端私钥权限(应为600),以及服务器上对应用户的~/.ssh/authorized_keys文件权限(应为600)和内容是否正确。
    • 检查sshd_configPubkeyAuthentication是否为yesAuthorizedKeysFile路径是否正确。
  4. 防火墙与安全组
    • 确认服务器本地防火墙(firewall-cmd --list-all)和云平台安全组均已放行新的 SSH 端口。
    • 注意:有些云平台(如 AWS Security Group)的规则是无状态的,需同时配置入站和出站规则。

6.2 修改 SSH 端口后,Firewalld 未放行导致连接失败

现象:修改sshd_config并重启服务后,新端口无法连接,但通过控制台或旧端口(如果还开放)可以登录。原因firewalld默认只放行ssh服务(即 22 端口)。修改端口后,需要手动添加规则。解决

# 添加新端口规则(假设新端口为 23456) sudo firewall-cmd --permanent --add-port=23456/tcp # 移除旧的 22 端口规则(可选) sudo firewall-cmd --permanent --remove-service=ssh # 重载防火墙 sudo firewall-cmd --reload # 验证 sudo firewall-cmd --list-ports

教训:任何涉及网络端口的修改,必须同步更新防火墙规则,并且先添加新规则,验证通过后再删除旧规则

6.3 密钥登录提示“Permission denied (publickey)”

这是最令人头疼的问题之一。按以下清单逐一核对:

  • 服务器端
    1. sshd_configPubkeyAuthentication yes
    2. 对应用户家目录.ssh权限必须是700chmod 700 ~/.ssh
    3. authorized_keys文件权限必须是600chmod 600 ~/.ssh/authorized_keys
    4. authorized_keys文件内容完整,且与本地公钥完全一致(注意不要有多余的空格或换行)。
    5. SELinux 可能阻止访问(CentOS 7 默认开启)。可以尝试临时禁用 SELinux 测试:setenforce 0。如果由此解决,则需要调整 SELinux 上下文:restorecon -Rv ~/.ssh
  • 客户端
    1. 使用ssh -v参数查看详细连接过程,寻找错误线索。
    2. 指定正确的私钥路径:ssh -i /path/to/private_key ...
    3. 私钥文件权限不能太开放,应为600

6.4 Fail2ban 误封自己的 IP

现象:配置 Fail2ban 后,自己无法登录服务器。解决

  1. 通过云控制台 VNC 登录服务器。
  2. 查看 Fail2ban 状态和被封 IP:fail2ban-client status sshd
  3. 如果发现自己的 IP 被禁,立即解封:fail2ban-client set sshd unbanip your_ip_address
  4. 永久解决方案:编辑/etc/fail2ban/jail.local,在[sshd]段落下添加ignoreip = 127.0.0.1/8 your_office_ip/32 your_home_ip/32,将你的固定 IP 加入白名单。
  5. 重启 Fail2ban:systemctl restart fail2ban

6.5 系统更新后服务异常

现象:执行yum update更新内核或关键库后,某些服务(如 Docker、特定应用)启动失败。原因:更新可能引入了不兼容的依赖或配置变更。预防与解决

  • 生产环境更新前:务必在测试环境先行验证。使用yum update --downloadonly只下载不安装,查看更新列表。
  • 使用版本锁定:对于关键服务,可以使用yum versionlock插件锁定其版本,避免意外升级。
  • 回滚:如果更新后出现问题,可以尝试回滚到旧内核启动。在 GRUB 启动菜单中,选择上一个内核版本启动。对于非内核的包,回滚较复杂,凸显了备份的重要性。
  • 依赖问题:如果更新后某个服务报依赖库错误,可以尝试安装特定版本:yum install package-name-version

这套从 SSH 加固到系统初始化的流程,是我在多次线上环境部署和应急响应中总结出来的。它不是一个僵化的 checklist,而是一个安全基线的思路。核心思想是:最小权限、纵深防御、持续监控。刚开始可能会觉得步骤繁琐,但一旦用 Ansible 等工具将其自动化,就会发现它带来的稳定性和安全感是值得的。尤其是在今天这个自动化攻击横行的时代,这些基础的安全配置不再是“可选项”,而是“必选项”。最后再分享一个习惯:每次对服务器做任何重要配置变更前,先拍一个快照(如果是虚拟机)或者做好备份。这样,即使操作失误,也能快速回滚,心里不慌。

返回列表