imthenachoman/How-To-Secure-A-Linux-Server

GitHub: imthenachoman/How-To-Secure-A-Linux-Server

一份涵盖 SSH 加固、网络防护、入侵检测和安全审计等内容的 Linux 服务器安全加固完整操作指南,配有可复制粘贴的命令和 Ansible 自动化方案。

Stars: 26957 | Forks: 1772

# 如何保护 Linux 服务器 这是一份不断演进的操作指南,旨在保护 Linux 服务器的安全,同时也希望能在安全概念及其重要性方面给你带来一些启发。 [![CC-BY-SA](https://i.creativecommons.org/l/by-sa/4.0/88x31.png)](#license) ## 目录 - [简介](#introduction) - [指南目标](#guide-objective) - [为什么要保护你的服务器](#why-secure-your-server) - [为什么还要写另一份指南](#why-yet-another-guide) - [其他指南](#other-guides) - [待办 / 待添加](#to-do--to-add) - [指南概述](#guide-overview) - [关于本指南](#about-this-guide) - [我的使用场景](#my-use-case) - [编辑配置文件 - 适合懒人的方法](#editing-configuration-files---for-the-lazy) - [贡献](#contributing) - [在开始之前](#before-you-start) - [明确你的原则](#identify-your-principles) - [选择 Linux 发行版](#picking-a-linux-distribution) - [安装 Linux](#installing-linux) - [安装前/后的要求](#prepost-installation-requirements) - [其他重要注意事项](#other-important-notes) - [使用 Ansible Playbook 保护你的 Linux 服务器](#using-ansible-playbooks-to-secure-your-linux-server) - [SSH 服务器](#the-ssh-server) - [修改 SSH 配置前的重要注意事项](#important-note-before-you-make-ssh-changes) - [SSH 公钥/私钥](#ssh-publicprivate-keys) - [为 AllowGroups 创建 SSH 组](#create-ssh-group-for-allowgroups) - [加固 `/etc/ssh/sshd_config`](#secure-etcsshsshd_config) - [移除较短的 Diffie-Hellman 密钥](#remove-short-diffie-hellman-keys) - [SSH 的 2FA/MFA(多因素认证)](#2famfa-for-ssh) - [基础配置](#the-basics) - [限制可以使用 sudo 的用户](#limit-who-can-use-sudo) - [限制可以使用 su 的用户](#limit-who-can-use-su) - [使用 FireJail 在沙箱中运行应用](#run-applications-in-a-sandbox-with-firejail) - [NTP 客户端](#ntp-client) - [加固 /proc](#securing-proc) - [强制账户使用安全密码](#force-accounts-to-use-secure-passwords) - [自动安全更新和警报](#automatic-security-updates-and-alerts) - [更安全的随机熵池 (编写中)](#more-secure-random-entropy-pool-wip) - [添加紧急/备用/虚假密码登录安全系统](#add-panic-secondary-fake-password-login-security-system) - [网络](#the-network) - [使用 UFW (Uncomplicated Firewall) 配置防火墙](#firewall-with-ufw-uncomplicated-firewall) - [使用 PSAD 进行 iptables 入侵检测与防御](#iptables-intrusion-detection-and-prevention-with-psad) - [使用 Fail2Ban 进行应用层入侵检测与防御](#application-intrusion-detection-and-prevention-with-fail2ban) - [使用 CrowdSec 进行应用层入侵检测与防御](#application-intrusion-detection-and-prevention-with-crowdsec) - [安全审计](#the-auditing) - [使用 AIDE 进行文件/文件夹完整性监控 (编写中)](#filefolder-integrity-monitoring-with-aide-wip) - [使用 ClamAV 进行防病毒扫描 (编写中)](#anti-virus-scanning-with-clamav-wip) - [使用 Rkhunter 进行 Rootkit 检测 (编写中)](#rootkit-detection-with-rkhunter-wip) - [使用 chrootkit 进行 Rootkit 检测 (编写中)](#rootkit-detection-with-chrootkit-wip) - [logwatch - 系统日志分析和报告工具](#logwatch---system-log-analyzer-and-reporter) - [ss - 查看你的服务器正在监听的端口](#ss---seeing-ports-your-server-is-listening-on) - [Lynis - Linux 安全审计](#lynis---linux-security-auditing) - [OSSEC - 主机入侵检测](#ossec---host-intrusion-detection) - [危险地带](#the-danger-zone) - [杂项](#the-miscellaneous) - [配合 Google 使用 MSMTP (简单 Sendmail)](#msmtp-alternative) - [使用 Gmail 和 Exim4 作为支持隐式 TLS 的 MTA](#gmail-and-exim4-as-mta-with-implicit-tls) - [独立的 iptables 日志文件](#separate-iptables-log-file) - [遗留问题](#left-over) - [联系我](#contacting-me) - [有用的链接](#helpful-links) - [致谢](#acknowledgments) - [许可与版权](#license-and-copyright) (目录由 [nGitHubTOC](https://imthenachoman.github.io/nGitHubTOC/) 生成) ## 简介 ### 指南目标 本指南的目的是教你如何保护 Linux 服务器的安全。 保护 Linux 服务器有很多可以做的事情,本指南将尽可能多地涵盖这些内容。随着我的学习或大家的[贡献](#contributing),将会添加更多的主题和材料。 本指南的 Ansible playbook 可由 [moltenbit](https://github.com/moltenbit) 在 [如何使用 Ansible 保护 Linux 服务器](https://github.com/moltenbit/How-To-Secure-A-Linux-Server-With-Ansible) 获取。 ([目录](#table-of-contents)) ### 为什么要保护你的服务器 我假设你使用本指南是因为, Hopefully,你已经理解了良好的安全性的重要性。这是一个沉重的独立话题,将其分解超出了本指南的范围。如果你不知道这个问题的答案,我建议你先研究一下它。 在宏观层面上,当一个设备(如服务器)处于公共领域的那一刻——即对外界可见——它就成了恶意行为者的目标。一个未受保护的设备是恶意行为者的游乐场,他们想要访问你的数据,或者将你的服务器用作他们大规模 DDOS 攻击的另一个节点。 更糟糕的是,如果没有良好的安全性,你可能永远不知道你的服务器是否已被攻破。恶意行为者可能已经未经授权访问了你的服务器并在不更改任何内容的情况下复制了你的数据,因此你永远不会知道。或者你的服务器可能已经是 DDOS 攻击的一部分,而你却不知道。看看新闻报道中的许多大规模数据泄露事件——公司通常在恶意行为者离开很久之后才发现数据泄露或入侵。 与普遍的看法相反,恶意行为者并不总是想改变什么或[为了钱而锁定你的数据](https://en.wikipedia.org/wiki/Ransomware)。有时他们只是想要你服务器上的数据用于他们的数据仓库(大数据中有大钱),或者暗中利用你的服务器达成他们的 nefarious 目的。 ([目录](#table-of-contents)) ### 为什么还要写另一份指南 这份指南可能看起来是多余的或不必要的,因为网上有无数的文章告诉你[如何加固 Linux](https://duckduckgo.com/?q=how+to+secure+linux&t=ffab&atb=v151-7&ia=web),但这些信息分散在不同的文章中,涵盖的内容不同,方式也不同。谁有时间去 scour 数百篇文章呢? 在为我的 Debian 构建进行调研时,我记了笔记。最后我意识到,加上我已经知道的和我正在学习的,我已经具备了制作一份操作指南的条件。我想把它放到网上,希望能帮助他人**学习**并**节省时间**。 我从未找到一份涵盖所有内容的指南——这份指南就是我的尝试。 本指南中涵盖的许多内容可能相当基础/琐碎,但我们大多数人并不是每天都安装 Linux,很容易忘记这些基本的东西。 ([目录](#table-of-contents)) ### 其他指南 有许多由专家、行业领导者以及发行版自身提供的指南。包含这些指南中的所有内容不仅不切实际,有时还会侵犯版权。我建议你在开始阅读本指南之前先查看一下它们。 - [互联网安全中心 (CIS)](https://www.cisecurity.org/) 提供了详尽的、行业可信的、用于加固多种 Linux 发行版的分步说明[基准](https://www.cisecurity.org/cis-benchmarks/)。查看他们的[关于我们](https://www.cisecurity.org/about-us/)页面了解详情。我的建议是先通读本指南(即你正在阅读的这篇),然后再看 CIS 的指南。这样他们的建议将覆盖本指南中的任何内容。 - 对于特定发行版的加固/安全指南,请查看你所使用发行版的文档。 - https://security.utexas.edu/os-hardening-checklist/linux-7 - Red Hat Enterprise Linux 7 加固清单 - https://cloudpro.zone/index.php/2018/01/18/debian-9-3-server-setup-guide-part-1/ - # Debian 9.3 服务器设置指南 - https://blog.vigilcode.com/2011/04/ubuntu-server-initial-security-quick-secure-setup-part-i/ - Ubuntu 服务器初始安全指南 - https://www.tldp.org/LDP/sag/html/index.html - https://seifried.org/lasg/ - https://news.ycombinator.com/item?id=19178964 - https://wiki.archlinux.org/index.php/Security - 许多人也推荐这个 - https://securecompliance.co/linux-server-hardening-checklist/ ([目录](#table-of-contents)) ### 待办 / 待添加 - [ ] [Fail2ban 的自定义 Jails](#custom-jails) - [ ] MAC (强制访问控制) 和 Linux 安全模块 - https://wiki.archlinux.org/index.php/security#Mandatory_access_control - Security-Enhanced Linux / SELinux - https://en.wikipedia.org/wiki/Security-Enhanced_Linux - https://linuxtechlab.com/beginners-guide-to-selinux/ - https://linuxtechlab.com/replicate-selinux-policies-among-linux-machines/ - https://teamignition.us/how-to-stop-being-a-scrub-and-learn-to-use-selinux.html - AppArmor - https://wiki.archlinux.org/index.php/AppArmor - https://security.stackexchange.com/questions/29378/comparison-between-apparmor-and-selinux - http://www.insanitybit.com/2012/06/01/why-i-like-apparmor-more-than-selinux-5/ - [ ] 磁盘加密 - [ ] Rkhunter 和 chrootkit - http://www.chkrootkit.org/ - http://rkhunter.sourceforge.net/ - https://www.cyberciti.biz/faq/howto-check-linux-rootkist-with-detectors-software/ - https://www.tecmint.com/install-rootkit-hunter-scan-for-rootkits-backdoors-in-linux/ - [ ] 传输/备份日志 - https://news.ycombinator.com/item?id=19178681 - [ ] CIS-CAT - https://learn.cisecurity.org/cis-cat-landing-page - [ ] debsums - https://blog.sleeplessbeastie.eu/2015/03/02/how-to-verify-installed-packages/ ([目录](#table-of-contents)) ## 指南概述 ### 关于本指南 本指南... - ...**是**一份正在不断完善的作品。 - ...**专注**于**家用** Linux 服务器。这里所有的概念/建议都适用于更大/更专业的环境,但这些用例需要更高级和专业的配置,超出了本指南的范围。 - ...**不**教你了解 Linux、如何[安装 Linux](#installing-linux)或如何使用它。如果你是 Linux 新手,请查看 https://linuxjourney.com/。 - ...**旨在**做到[与 Linux 发行版无关](#picking-a-linux-distribution)。 - ...**不**教你关于安全所需的所有知识,也不深入探讨系统/服务器安全的所有方面。例如,物理安全不在本指南的讨论范围内。 - ...**不**讨论程序/工具的工作原理,也不深入探讨它们的 nook and crannies。本指南引用的大多数程序/工具都非常强大且高度可配置。目标是涵盖最低限度的需求——足以吊起你的胃口,让你渴望去学习更多。 - ...**旨在**通过提供可以复制粘贴的代码来简化操作。在粘贴之前你可能需要修改命令,所以请把你最喜欢的[文本编辑器](https://notepad-plus-plus.org/)放在手边。 - ...**是**按照对我有逻辑意义的顺序组织的——即在安装防火墙之前先加固 SSH。因此,本指南旨在按照其呈现的顺序进行操作,但并非必须如此。如果你以不同的顺序操作,请小心——某些部分需要前面部分完成后才能进行。 ([目录](#table-of-contents)) ### 我的使用场景 有许多类型的服务器和不同的用例。虽然我希望本指南尽可能通用,但可能有些内容并不适用于所有/其他用例。在阅读本指南时,请运用你最好的判断力。 为了给本指南涵盖的许多主题提供上下文,我的用例/配置是: - 一台桌面级电脑... - 带有单个 NIC... - 连接到消费级路由器... - 获取 ISP 提供的动态 WAN IP... - WAN+LAN 使用 IPV4... - LAN 使用 [NAT](https://en.wikipedia.org/wiki/Network_address_translation)... - 我希望能够从未知的电脑和未知的地点(即朋友家)远程 SSH 到该服务器。 ([目录](#table-of-contents)) ### 编辑配置文件 - 适合懒人的方法 我很懒,如果不需要,我不喜欢手动编辑文件。我也假设其他所有人都和我一样。 :) 所以,在可能的情况下,我提供了 `code` 代码片段来快速完成所需的操作,比如在配置文件中添加或更改一行。 这些 `code` 代码片段使用了基本命令,如 `echo`、`cat`、`sed`、`awk` 和 `grep`。这些 `code` 代码片段是如何工作的,比如每个命令/部分做了什么,超出了本指南的范围——`man` 手册页是你最好的朋友。 **注意**:这些 `code` 代码片段不会验证/确认更改是否成功——即该行是否真的被添加或更改了。我把验证部分留给你那双能干的手。本指南中的步骤确实包含对所有将要更改的文件备份。 并非所有的更改都可以使用 `code` 代码片段自动完成。这些更改需要良好的、老式的手动编辑。例如,你不能只在 [INI](https://en.wikipedia.org/wiki/INI_file) 类型的文件中追加一行。使用你[最喜欢](https://en.wikipedia.org/wiki/Vi)的 Linux 文本编辑器。 ([目录](#table-of-contents)) ### 贡献 我想把这份指南放在 [GitHub](http://www.github.com) 上以便于协作。贡献的人越多,这份指南就会变得越好、越完整。 要做出贡献,你可以 fork 并提交 pull request,或者提交一个[新 issue](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/new)。 ([目录](#table-of-contents)) ## 在开始之前 ### 明确你的原则 在开始之前,你需要明确你的原则是什么。你的[威胁模型](https://en.wikipedia.org/wiki/Threat_model)是什么?需要考虑的一些事情: - 你为什么要保护你的服务器? - 你想要或不想要多少安全性? - 为了安全你愿意牺牲多少便利性,反之亦然? - 你想防范的威胁是什么?你的具体情况有哪些特殊性?例如: - 对你的服务器/网络的物理访问是否是一个可能的攻击媒介? - 你是否会在路由器上开放端口以便从家外访问你的服务器? - 你是否会在服务器上托管一个文件共享,并将其挂载到一台桌面级机器上?桌面机器被感染进而感染服务器的可能性有多大? - 如果你的安全实施将你自己锁在了服务器之外,你是否有恢复的手段?例如,你[禁用了 root 登录](#disable-root-login)或[给 GRUB 设置了密码](#password-protect-grub)。 这些只是需要考虑的**几件事情**。在开始保护你的服务器之前,你需要了解你试图防范什么以及为什么,这样你才知道你需要做什么。 ([目录](#table-of-contents)) ### 选择 Linux 发行版 本指南旨在与发行版无关,以便用户可以使用他们想要的[任何发行版](https://distrowatch.com/)。话虽如此,还是有几件事需要记住: 你想要一个...的发行版: - ...**稳定**。除非你喜欢在凌晨 2 点调试问题,否则你不希望一次[无人值守的升级](#automatic-security-updates-and-alerts)或手动的包/系统更新导致你的服务器无法运行。但这也意味着你可以接受不运行最新、最棒的、最前沿的软件。 - ...**及时更新安全补丁**。你可以加固服务器上的所有东西,但如果核心操作系统或你正在运行的应用程序存在已知漏洞,你将永远不会安全。 - ...**你熟悉的。**如果你不了解 Linux,我建议你在尝试保护它之前先玩一玩。你应该对它感到适应并知道如何操作,比如如何安装软件,配置文件在哪里,等等... - ...**有良好支持的。**即使是最有经验的管理员偶尔也需要帮助。有一个可以寻求帮助的地方将拯救你的理智。 ([目录](#table-of-contents)) ### 安装 Linux 安装 Linux 超出了本指南的范围,因为每个发行版的安装方式都不同,而且安装说明通常都有详细的文档记录。如果你需要帮助,请从你所用发行版的文档开始。无论使用哪种发行版,高层次的流程通常是这样的: 1. 下载 ISO 2. 将其刻录/复制/传输到你的安装介质(例如 CD 或 U 盘) 3. 从你的安装介质启动服务器 4. 按照提示进行安装 在适用的情况下,请使用专家安装选项,以便你可以更严格地控制服务器上运行的内容。**只安装你绝对需要的东西。**就我个人而言,除了 SSH 我不安装任何其他东西。同时,勾选磁盘加密选项。 ([目录](#table-of-contents)) ### 安装前/后的要求 - 如果你要在路由器上开放端口以便从外部访问服务器,请在系统启动并加固之前禁用端口转发。 - 除非你所有的操作都是物理连接到服务器的,否则你将需要远程访问,因此请确保 SSH 正常工作。 - 保持你的系统是最新的(例如,在基于 Debian 的系统上使用 `sudo apt update && sudo apt upgrade`)。 - 确保你执行了针对你的设置的任何特定任务,例如: - 配置网络 - 在 `/etc/fstab` 中配置挂载点 - 创建初始用户账户 - 安装你会需要的核心软件,比如 `man` - 等等... - 你的服务器需要能够发送电子邮件,以便你能收到重要的安全警报。如果你不打算设置邮件服务器,请查看[使用 Gmail 和 Exim4 作为支持隐式 TLS 的 MTA](#gmail-and-exim4-as-mta-with-implicit-tls)。 - 我还建议你在开始阅读本指南之前先**阅读** [CIS 基准](https://www.cisecurity.org/cis-benchmarks/),以消化/理解他们所说的话。我的建议是先通读本指南(即你正在阅读的这篇),然后再看 CIS 的指南。这样他们的建议将覆盖本指南中的任何内容。 ([目录](#table-of-contents)) ### 其他重要注意事项 - 本指南是在 Debian 上编写和测试的。下面的大多数内容应该可以在其他发行版上工作。如果你发现有不工作的内容,请[联系我](#contacting-me)。区分每个发行版的主要特点将是其包管理系统。因为我使用 Debian,我将提供适用于所有[基于 Debian 的发行版](https://www.debian.org/derivatives/)的相应 `apt` 命令。如果有人愿意为其他发行版[提供](#contributing)相应的命令,我会把它们加上。 - 文件路径和设置也可能略有不同——如果你遇到问题,请查看你所使用发行版的文档。 - 在开始之前阅读整个指南。你的用例和/或原则可能要求你不做某些事情或改变顺序。 - 不要在没有理解你粘贴的内容的情况下**盲目**复制粘贴。有些命令在生效前需要根据你的需求进行修改——例如用户名。 ([目录](#table-of-contents)) ### 使用 Ansible Playbook 保护你的 Linux 服务器 本指南的 Ansible playbook 可在 [如何使用 Ansible 保护 Linux 服务器](https://github.com/moltenbit/How-To-Secure-A-Linux-Server-With-Ansible) 获取。 确保根据你的需求编辑变量,并在运行前阅读所有任务,以确认它不会破坏你的系统。运行 playbook 后,确保所有设置都已根据你的需求进行了配置! 1. 安装 [Ansible](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) 2. git clone [如何使用 Ansible 保护 Linux 服务器](https://github.com/moltenbit/How-To-Secure-A-Linux-Server-With-Ansible) 3. [创建 SSH 公钥/私钥](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server#ssh-publicprivate-keys) ``` ssh-keygen -t ed25519 ``` 5. 根据你的需求更改 *group_vars/variables.yml* 中的所有变量。 6. 在运行 playbook 之前启用 SSH root 访问: ``` nano /etc/ssh/sshd_config [...] PermitRootLogin yes [...] ``` 7. 建议:在你的系统上配置静态 IP 地址。 8. 将你的系统 IP 地址添加到 *hosts.yml*。   使用你在安装服务器时指定的 root 密码运行 requirements playbook: ``` ansible-playbook --inventory hosts.yml --ask-pass requirements-playbook.yml ```   使用你在 *variables.yml* 文件中指定的新用户密码运行 main playbook: ``` ansible-playbook --inventory hosts.yml --ask-pass main-playbook.yml ```   如果你需要多次运行 playbook,请记住使用 SSH 密钥和新的 SSH 端口: ``` ansible-playbook --inventory hosts.yml -e ansible_ssh_port=SSH_PORT --key-file /PATH/TO/SSH/KEY main-playbook.yml ``` ([目录](#table-of-contents)) ## SSH 服务器 ### 修改 SSH 配置前的重要注意事项 强烈建议在**进行并应用 SSH 配置更改之前**,为你的服务器保留第二个打开的终端。这样,如果你的第一个终端会话被锁定,你仍然有一个连接的会话,以便修复它。 感谢 [Sonnenbrand](https://github.com/Sonnenbrand) 提供这个[想法](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/56)。 ### SSH 公钥/私钥 #### 为什么 使用 SSH 公钥/私钥比使用密码更安全。这也使得连接到我们的服务器变得更容易、更快捷,因为你不需要输入密码。 #### 工作原理 查看下面的参考链接以获取更多细节,但在高层次上,公钥/私钥是通过使用一对密钥来验证身份的。 1. 一个密钥,即**公钥**,**只能加密数据**,不能解密 2. 另一个密钥,即**私钥**,可以解密数据 对于 SSH,客户端会创建公钥和私钥。你需要保证这两个密钥的安全,尤其是私钥。尽管公钥本意是公开的,但确保这两个密钥都不会落入坏人之手是明智的。 当你连接到 SSH 服务器时,SSH 会在你要连接的服务器上的 `~/.ssh/authorized_keys` 文件中寻找与你连接的客户端相匹配的公钥。请注意,该文件位于你尝试连接的 ID 的**主文件夹**中。因此,在创建公钥之后,你需要将其附加到 `~/.ssh/authorized_keys`。一种方法是将它复制到 U 盘并物理传输到服务器。另一种方法是使用 [`ssh-copy-id`](https://www.ssh.com/ssh/copy-id) 来传输并附加公钥。 在创建密钥并将公钥附加到主机的 `~/.ssh/authorized_keys` 之后,SSH 使用公钥和私钥来验证身份,然后建立安全连接。身份验证是如何进行的是一个复杂的过程,但 [Digital Ocean](https://www.digitalocean.com/community/tutorials/understanding-the-ssh-encryption-and-connection-process) 有一篇关于其工作原理的非常精彩的文章。在高层次上,身份验证的过程是:服务器用公钥加密一条质询消息,然后将其发送给客户端。如果客户端不能用私钥解密该质询消息,则无法验证身份,也不会建立连接。 它们被认为更安全是因为你需要私钥才能建立 SSH 连接。如果你在 `/etc/ssh/sshd_config` 中设置了 [`PasswordAuthentication no`](#PasswordAuthentication),那么 SSH 将不允许你在没有私钥的情况下进行连接。 你还可以为密钥设置密码短语,这将要求你在使用公钥/私钥连接时输入密钥的密码短语。请记住,这样做意味着你不能将该密钥用于自动化,因为你将无法在脚本中发送密码短语。`ssh-agent` 是许多 Linux 发行版中附带的一个程序(通常已经在运行),它允许你在内存中保存未加密的私钥一段可配置的时间。只需运行 `ssh-add`,它就会提示你输入密码短语。在可配置的时间过去之前,你不会被再次要求输入密码短语。 我们将使用 Ed25519 密钥,根据 [https://linux-audit.com/](https://linux-audit.com/using-ed25519-openssh-keys-instead-of-dsa-rsa-ecdsa/) 的说法: #### 目标 - Ed25519 公钥/私钥 SSH 密钥: - 客户端上的私钥 - 服务器上的公钥 #### 注意事项 - 你需要对你将用来连接到服务器的每台计算机和每个账户执行此步骤。 #### 参考 - https://www.ssh.com/ssh/public-key-authentication - https://help.ubuntu.com/community/SSH/OpenSSH/Keys - https://linux-audit.com/using-ed25519-openssh-keys-instead-of-dsa-rsa-ecdsa/ - https://www.digitalocean.com/community/tutorials/understanding-the-ssh-encryption-and-connection-process - https://wiki.archlinux.org/index.php/SSH_Keys - https://www.ssh.com/ssh/copy-id - `man ssh-keygen` - `man ssh-copy-id` - `man ssh-add` #### 步骤 1. 从你将用来连接到服务器的计算机(即**客户端**,而不是服务器本身)上,使用 `ssh-keygen` 创建一个 [Ed25519](https://linux-audit.com/using-ed25519-openssh-keys-instead-of-dsa-rsa-ecdsa/) 密钥: ssh-keygen -t ed25519 **注意**:如果你设置了密码短语,每次使用此密钥连接到服务器时都需要输入它,除非你使用了 `ssh-agent`。 2. 现在你需要将客户端的公钥 `~/.ssh/id_ed25519.pub` **追加**到服务器上的 `~/.ssh/authorized_keys` 文件中。既然我们大概还在家里的局域网中,我们可能不受 [MIM](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) 攻击的威胁,所以我们将使用 `ssh-copy-id` 来传输并附加公钥: ssh-copy-id user@server 现在是[执行特定于你的设置的任何任务](#prepost-installation-requirements)的好时机。 ([目录](#table-of-contents)) ### 为 AllowGroups 创建 SSH 组 #### 为什么 为了方便控制谁可以 SSH 到服务器。通过使用用户组,我们可以快速地向组中添加/删除账户,以快速允许或禁止对服务器的 SSH 访问。 #### 工作原理 我们将在 SSH 的配置文件 [`/etc/ssh/sshd_config`](#secure-etcsshsshd_config) 中使用 [AllowGroups 选项](#AllowGroups),告诉 SSH 服务器只允许属于某个 UNIX 组成员的用户进行 SSH 登录。任何不在该组中的人都将无法通过 SSH 登录。 #### 目标 - 一个 UNIX 组,我们将在[加固 `/etc/ssh/sshd_config`](#secure-etcsshsshd_config) 中使用它来限制谁可以 SSH 到服务器 #### 注意事项 - 这是一个前置步骤,用于支持在[加固 `/etc/ssh/sshd_config`](#secure-etcsshsshd_config) 中设置的 `AllowGroup` 设置。 #### 参考 - `man groupadd` - `man usermod` #### 步骤 1. 创建一个组: sudo groupadd sshusers 2. 将账户添加到该组: sudo usermod -a -G sshusers user1 sudo usermod -a -G sshusers user2 sudo usermod -a -G sshusers ... 你需要为服务器上需要 SSH 访问权限的每个账户执行此操作。 ([目录](#table-of-contents)) ### 加固etc/ssh/sshd_config` #### 为什么 SSH 是进入你服务器的一扇门。如果你在路由器上开放了端口以便从家庭网络外部 SSH 到你的服务器,这一点尤为正确。如果它没有得到适当的保护,恶意行为者可能会利用它来未经授权访问你的系统。 #### 工作原理 `/etc/ssh/sshd_config` 是 SSH 服务器使用的默认配置文件。我们将使用这个文件来告知 SSH 服务器应该使用哪些选项。 #### 目标 - 一个安全的 SSH 配置 #### 注意事项 - 确保你首先完成了[为 AllowGroups 创建 SSH 组](#create-ssh-group-for-allowgroups)。 #### 参考 - Mozilla 的 OpenSSH 6.7+ 指南,位于 https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 - https://linux-audit.com/audit-and-harden-your-ssh-configuration/ - https://www.ssh.com/ssh/sshd_config/ - https://www.techbrown.com/harden-ssh-secure-linux-vps-server/ (链接失效;请尝试 http://web.archive.org/web/20200413100933/https://www.techbrown.com/harden-ssh-secure-linux-vps-server/) - https://serverfault.com/questions/660160/openssh-difference-between-internal-sftp-and-sftp-server/660325 - `man sshd_config` - 感谢 [than0s](https://github.com/than0s) 提供[如何查找重复设置](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/38)。 #### 步骤 1. 备份 OpenSSH 服务器的配置文件 `/etc/ssh/sshd_config` 并删除注释以使其更易于阅读: sudo cp --archive /etc/ssh/sshd_config /etc/ssh/sshd_config-COPY-$(date +"%Y%m%d%H%M%S") sudo sed -i -r -e '/^#|^$/ d' /etc/ssh/sshd_config 2. 编辑 `/etc/ssh/sshd_config`,然后找到并编辑或添加这些无论你的配置/设置如何都应应用的设置: **注意**:SSH 不喜欢重复且冲突的设置。例如,如果你设置了 `ChallengeResponseAuthentication no`,然后又设置了 `ChallengeResponseAuthentication yes`,SSH 将遵循第一个而忽略第二个。你的 `/etc/ssh/sshd_config` 文件可能已经包含了下面的一些设置/行。为了避免出现问题,你需要手动检查你的 `/etc/ssh/sshd_config` 文件,并解决任何重复且冲突的设置。 **注意:** 如果你运行的是 OpenSSH 9.1 或更高版本,请取消下面配置中 `RequiredRSASize 3072` 行的注释。这将强制要求 RSA 密钥的最小长度为 3072 位,并在身份验证期间拒绝较小的 RSA 密钥。这仅影响 RSA 密钥。如果你使用 ED25519 或 ECDSA 密钥,则不受影响。你可以使用 `ssh-keygen -l -f ~/.ssh/id_rsa` 检查你的密钥类型和大小。在较旧的 OpenSSH 版本上,请保持该行被注释掉,否则会阻止 sshd 启动。 ######################################################################################################## # 设置开始于 https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 截至 2019-01-01 ######################################################################################################## # 按偏好顺序支持的 HostKey 算法。 HostKey /etc/ssh/ssh_host_ed25519_key HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_ecdsa_key KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com # LogLevel VERBOSE 会在登录时记录用户的密钥指纹。需要清晰的审计记录来追踪哪个密钥用于登录。 LogLevel VERBOSE # 在非特权进程中尽可能使用内核沙箱机制 # OpenBSD 上的 Systrace,Linux 上的 Seccomp,MacOSX/Darwin 上的 seatbelt,其他地方的 rlimit。 # 注意:此设置在 OpenSSH 7.5 中已弃用 (https://www.openssh.com/txt/release-7.5) # UsePrivilegeSeparation sandbox ######################################################################################################## # 设置结束于 https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 截至 2019-01-01 ######################################################################################################## # 不允许用户设置环境变量 PermitUserEnvironment no # 记录 sftp 级别的文件访问(读/写等),否则这些访问不容易被记录。 Subsystem sftp internal-sftp -f AUTHPRIV -l INFO # 禁用 X11 转发,因为 X11 非常不安全 # 无论如何你真的不应该在服务器上运行 X X11Forwarding no # 禁用端口转发 AllowTcpForwarding no AllowStreamLocalForwarding no GatewayPorts no PermitTunnel no # 如果账户密码为空则不允许登录 PermitEmptyPasswords no # 忽略 .rhosts 和 .shosts IgnoreRhosts yes # 验证主机名是否匹配 IP UseDNS yes Compression no # TCP keepalive 是可欺骗的(在加密通道之外运行) # 改用 ClientAlive(在加密通道内运行) TCPKeepAlive no AllowAgentForwarding no PermitRootLogin no # 不允许 .rhosts 或 /etc/hosts.equiv HostbasedAuthentication no # OpenSSH 9.1 及更高版本 # 强制要求 RSA 密钥最小长度为 3072 位 # https://www.keylength.com/en/compare/ # RequiredRSASize 3072 # https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/115 HashKnownHosts yes 3. 然后**找到并编辑或添加**这些设置,并根据你的要求设置值: |设置|有效值|示例|描述|注意事项| |--|--|--|--|--| |**AllowGroups**|本地 UNIX 组名|`AllowGroups sshusers`|允许 SSH 访问的组|| |**ClientAliveCountMax**|数字|`ClientAliveCountMax 3`|在没有响应的情况下发送的客户端存活消息的最大数量|| |**ClientAliveInterval**|秒数|`ClientAliveInterval 15`|响应请求之前的超时时间(以秒为单位)|| |**ListenAddress**|以空格分隔的本地地址列表|
  • `ListenAddress 0.0.0.0`
  • `ListenAddress 192.168.1.100`
|`sshd` 应该监听的本地地址|重要详情请参见 [Issue #1](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/1)。| |**LoginGraceTime**|秒数|`LoginGraceTime 30`|登录超时之前的秒数|| |**MaxAuthTries**|数字|`MaxAuthTries 2`|允许的最大登录尝试次数|| |**MaxSessions**|数字|`MaxSessions 2`|最大打开会话数|| |**MaxStartups**|数字|`MaxStartups 2`|最大登录会话数|| |**PasswordAuthentication**|`yes` 或 `no`|`PasswordAuthentication no`|是否允许使用密码登录|| |**Port**|任何开放/可用的端口号|`Port 22`|`sshd` 应该监听的端口|| 查看 `man sshd_config` 获取有关这些设置含义的更多细节。 4. 确保没有相互冲突的重复设置。以下命令不应有任何输出。 awk 'NF && $1!~/^(#|HostKey)/{print $1}' /etc/ssh/sshd_config | sort | uniq -c | grep -v ' 1 ' 5. 重启 ssh: sudo service sshd restart 6. 你可以使用 `sshd -T` 检查并验证配置是否生效,并验证输出: sudo sshd -T ([目录](#table-of-contents)) ### 移除较短的 Diffie-Hellman 密钥 #### 为什么 根据 [Mozilla 的 OpenSSH 6.7+ 指南](https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67),“所有正在使用的 Diffie-Hellman 模数长度应至少为 3072 位”。 SSH 使用 Diffie-Hellman 算法来建立安全连接。模数(密钥大小)越大,加密强度越高。 #### 目标 - 移除所有小于 3072 位的 Diffie-Hellman 密钥 #### 参考 - Mozilla 的 OpenSSH 6.7+ 指南,位于 https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 - https://infosec.mozilla.org/guidelines/key_management - `man moduli` #### 步骤 1. 备份 SSH 的 moduli 文件 `/etc/ssh/moduli`: sudo cp --archive /etc/ssh/moduli /etc/ssh/moduli-COPY-$(date +"%Y%m%d%H%M%S") 2. 移除短 moduli: sudo awk '$5 >= 3071' /etc/ssh/moduli | sudo tee /etc/ssh/moduli.tmp sudo mv /etc/ssh/moduli.tmp /etc/ssh/moduli ([目录](#table-of-contents)) ### SSH 的 2FA/MFA(多因素认证) #### 为什么 尽管 SSH 是你门窗的得力保安,但它仍然是一扇可见的门,恶意行为者可以看到并尝试暴力破解。[Fail2Ban](#fail2ban-application-intrusion-detection-and-prevention) 会监控这些暴力破解尝试,但安全这件事再怎么小心也不为过。要求双重因素增加了额外的安全层。 使用双因素认证 (2FA) / 多因素认证 (MFA) 要求任何进入的人必须拥有**两把**钥匙才能进入,这使得恶意行为者更难得逞。这两把钥匙是: 1. 他们的密码 2. 一个每 30 秒更改一次的 6 位数字令牌 如果没有这两把钥匙,他们将无法进入。 #### 为什么不这么做 许多人可能会觉得这种体验很麻烦或令人厌烦。而且,对你系统的访问依赖于生成代码的配套身份验证器应用程序。 #### 工作原理 在 Linux 上,PAM 负责身份验证。PAM 有四个任务,你可以在 https://en.wikipedia.org/wiki/Linux_PAM 阅读相关内容。本节讨论的是身份验证任务。 当你登录到服务器时,无论是直接从控制台还是通过 SSH,你进来的那扇门都会将请求发送到 PAM 的身份验证任务,PAM 将要求并验证你的密码。你可以自定义每扇门使用的规则。例如,你可以有一套直接从控制台登录时的规则,以及另一套通过 SSH 登录时的规则。 本节将更改通过 SSH 登录时的身份验证规则,要求同时提供密码和 6 位数字代码。 我们将使用 Google 的 libpam-google-authenticator PAM 模块来创建和验证 [TOTP](https://en.wikipedia.org/wiki/Time-based_One-time_Password_algorithm) 密钥。https://fastmail.blog/2016/07/22/how-totp-authenticator-apps-work/ 和 https://jemurai.com/2018/10/11/how-it-works-totp-based-mfa/ 有关于 TOTP 工作原理的非常优秀的文章。 我们要做的是告诉服务器的 SSH PAM 配置要求用户提供他们的密码,然后再提供他们的数字令牌。然后 PAM 将验证用户的密码,如果正确,它将把身份验证请求路由到 libpam-google-authenticator,后者将要求并验证你的 6 位数字令牌。当且仅当一切正常时,身份验证才会成功,用户才被允许登录。 #### 目标 - 为所有 SSH 连接启用 2FA/MFA #### 注意事项 - 在执行此操作之前,你应该了解 2FA/MFA 的工作原理,并且你需要手机上有一个身份验证器应用程序才能继续。 - 我们将使用 [google-authenticator-libpam](https://github.com/google/google-authenticator-libpam)。 - 在以下配置下,用户只有在**使用密码**登录时才需要输入他们的 2FA/MFA 代码,而如果他们使用 [SSH 公钥/私钥](#ssh-publicprivate-keys) 则不需要。查看文档以了解如何更改此行为以适应你的需求。 #### 参考 - https://github.com/google/google-authenticator-libpam - https://en.wikipedia.org/wiki/Linux_PAM - https://en.wikipedia.org/wiki/Time-based_One-time_Password_algorithm - https://fastmail.blog/2016/07/22/how-totp-authenticator-apps-work/ - https://jemurai.com/2018/10/11/how-it-works-totp-basedfa/ #### 步骤 1. 安装 libpam-google-authenticator。 在基于 Debian 的系统上: sudo apt install libpam-google-authenticator 2. **确保你已登录为你想要启用 2FA/MFA 的 ID** 并**执行** `google-authenticator` 以创建必要的令牌数据: google-authenticator 注意这是**不以 root 身份运行**的。 对于它提出的所有问题,选择默认选项(在大多数情况下为 y),并记住保存紧急备用码。 3. 备份 PAM 的 SSH 配置文件 `/etc/pam.d/sshd`: sudo cp --archive /etc/pam.d/sshd /etc/pam.d/sshd-COPY-$(date +"%Y%m%d%H%M%S") 4. 现在我们需要通过将以下行添加到 `/etc/pam.d/sshd` 来将其启用为 SSH 的身份验证方法: auth required pam_google_authenticator.so nullok **注意**:在[此处](https://github.com/google/google-authenticator-libpam/blob/master/README.md#nullok)查看 `nullok` 的含义。 [适合懒人的方法](#editing-configuration-files---for-the-lazy): echo -e "\nauth required pam_google_authenticator.so nullok # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/pam.d/sshd 5. 通过在 `/etc/ssh/sshd_config` 中添加或编辑以下行,告诉 SSH 利用它: ChallengeResponseAuthentication yes [适合懒人的方法](#editing-configuration-files---for-the-lazy): sudo sed -i -r -e "s/^(challengeresponseauthentication .*)$/# \1 # commented by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/I" /etc/ssh/sshd_config echo -e "\nChallengeResponseAuthentication yes # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/ssh/sshd_config 6. 重启 ssh: sudo service sshd restart ([目录](#table-of-contents)) ## 基础配置 ### 限制可以使用 sudo 的用户 #### 为什么 sudo 允许账户以其他账户的身份运行命令,包括 **root**。我们要确保只有我们允许的账户才能使用 sudo。 #### 目标 - sudo 权限仅限于我们指定的组中的用户 #### 注意事项 - 你的安装可能已经完成了此操作,或者可能已经有一个专为此目的设置的特殊组,因此请先检查一下。 - Debian 创建了 sudo 组。要查看属于此组的用户(因此具有 sudo 权限): cat /etc/group | grep "sudo" - RedHat 创建了 wheel 组 - 有关某些发行版使 `sudo` 不需要密码的说明,请参见 [https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/39](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/39)。感谢 [sbrl](https://github.com/sbrl) 分享。 #### 步骤 1. 创建一个组: sudo groupadd sudousers 2. 将账户添加到该组: sudo usermod -a -G sudousers user1 sudo usermod -a -G sudousers user2 sudo usermod -a -G sudousers ... 你需要为服务器上需要 sudo 权限的每个账户执行此操作。 3. 备份 sudo 的配置文件 `/etc/sudoers`: sudo cp --archive /etc/sudoers /etc/sudoers-COPY-$(date +"%Y%m%d%H%M%S") 4. 编辑 sudo 的配置文件 `/etc/sudoers`: sudo visudo 5. 通过添加以下行(如果尚未存在)告诉 sudo 只允许 `sudousers` 组中的用户使用 sudo: %sudousers ALL=(ALL:ALL) ALL ([目录](#table-of-contents)) ### 限制可以使用 su 的用户 #### 为什么 su 也允许账户以其他账户的身份运行命令,包括 **root**。我们要确保只有我们允许的账户才能使用 su。 #### 目标 - su 权限仅限于我们指定的组中的用户 #### 参考 - 感谢 [olavim](https://github.com/olavim) 分享[这个想法](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/41) #### 步骤 1. 创建一个组: sudo groupadd suusers 2. 将账户添加到该组: sudo usermod -a -G suusers user1 sudo usermod -a -G suusers user2 sudo usermod -a -G suusers ... 你需要为服务器上需要 sudo 权限的每个账户执行此操作。 3. 设置只有此组中的用户才能执行 `/bin/su`: sudo dpkg-statoverride --update --add root suusers 4750 /bin/su ([目录](#table-of-contents)) ### 使用 FireJail 在沙箱中运行应用 #### 为什么 对于许多应用程序来说,在沙箱中运行绝对是更好的选择。 强烈建议对浏览器(尤其是闭源浏览器)和电子邮件客户端这样做。 #### 目标 - 将应用程序限制在一个沙箱(少数安全目录)中,并阻止访问系统的其余部分 #### 参考 - 感谢 [FireJail](https://firejail.wordpress.com/) #### 步骤 1. 安装软件: sudo apt install firejail firejail-profiles 注意:对于 Debian 10 Stable,建议使用官方 Backport: sudo apt install -t buster-backports firejail firejail-profiles 2. 允许应用程序(安装在 `/usr/bin` 或 `/bin` 中)仅在沙箱中运行(参见下面的一些示例): sudo ln -s /usr/bin/firejail /usr/local/bin/google-chrome-stable sudo ln -s /usr/bin/firejail /usr/local/bin/firefox sudo ln -s /usr/bin/firejail /usr/local/bin/chromium sudo ln -s /usr/bin/firejail /usr/local/bin/evolution sudo ln -s /usr/bin/firejail /usr/local/bin/thunderbird 3. 像往常一样运行应用程序(通过终端或启动器)并检查它是否在沙箱中运行: firejail --list 4. 允许受沙箱保护的应用程序像以前一样再次运行(示例:firefox): sudo rm /usr/local/bin/firefox ([目录](#table-of-contents)) ### NTP 客户端 #### 为什么 许多安全协议都会利用时间。如果你的系统时间不正确,可能会对你的服务器产生负面影响。NTP 客户端可以通过保持你的系统时间与[全球 NTP 服务器](https://en.wikipedia.org/wiki/Network_Time_Protocol)同步来解决这个问题。 #### 工作原理 NTP 代表网络时间协议。在本指南的上下文中,服务器上的 NTP 客户端用于使用从官方服务器提取的官方时间来更新服务器时间。查看 https://www.pool.ntp.org/en/ 了解所有公共 NTP 服务器。 #### 目标 - 安装 NTP 客户端并保持服务器时间同步 #### 参考 - https://cloudpro.zone/index.php/2018/01/27/debian-9-3-server-setup-guide-part-4/ - https://en.wikipedia.org/wiki/Network_Time_Protocol - https://www.pool.ntp.org/en/ - https://serverfault.com/questions/957302/securing-hardening-ntp-client-on-linux-servers-config-file/957450#957450 - https://tf.nist.gov/tf-cgi/servers.cgi #### 步骤 ##### Debian 13 (Trixie) 及更高版本:systemd-timesyncd `systemd-timesyncd` 是一个轻量级的 SNTP 客户端,已经包含在 Debian 中。与完整的 `ntpd` 守护进程不同,它不监听任何端口,这使得它的攻击面更小。就本指南的目的而言——保持你的服务器时钟同步——它已经完全足够了。 1. 启用 NTP 同步: sudo timedatectl set-ntp true 2. 验证其是否正常工作: timedatectl status 你应该在输出中看到 `NTP service: active` 和 `System clock synchronized: yes`。 3. 配置受信任的 NTP 服务器。备份配置文件,然后编辑它: sudo cp --archive /etc/systemd/timesyncd.conf /etc/systemd/timesyncd.conf-COPY-$(date +"%Y%m%d%H%M%S") 编辑 `/etc/systemd/timesyncd.conf` 并取消注释/设置 `[Time]` 部分: [Time] NTP=pool.ntp.org FallbackNTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org [适合懒人的方法](#editing-configuration-files---for-the-lazy): sudo sed -i -r -e "s/^#?NTP=.*$/NTP=pool.ntp.org # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/" /etc/systemd/timesyncd.conf sudo sed -i -r -e "s/^#?FallbackNTP=.*$/FallbackNTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/" /etc/systemd/timesyncd.conf 4. 重启服务以应用更改: sudo systemctl restart systemd-timesyncd 5. 检查同步状态: timedatectl timesync-status ##### Debian 12 (Bookworm) 及更早版本:ntp 包 1. 安装 ntp。 在基于 Debian 的系统上: sudo apt install ntp 2. 备份 NTP 客户端的配置文件 `/etc/ntp.conf`: sudo cp --archive /etc/ntp.conf /etc/ntp.conf-COPY-$(date +"%Y%m%d%H%M%S") 3. 默认配置,至少在 Debian 上,已经非常安全了。我们唯一要确保的是我们使用的是 `pool` 指令,而不是任何 `server` 指令。如果服务器无响应或提供错误的时间,`pool` 指令允许 NTP 客户端停止使用该服务器。通过注释掉所有 `server` 指令并将以下内容添加到 `/etc/ntp.conf` 中来实现这一点。 pool pool.ntp.org iburst [适合懒人的方法](#editing-configuration-files---for-the-lazy): sudo sed -i -r -e "s/^((server|pool).*)/# \1 # commented by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/" /etc/ntp.conf echo -e "\npool pool.ntp.org iburst # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/ntp.conf **`/etc/ntp.conf` 示例**: 4. 重启 ntp: sudo service ntp restart 5. 检查 ntp 服务的状态: sudo systemctl status ntp 6. 检查 ntp 的状态: sudo ntpq -p ([目录](#table-of-contents)) ### 加固 /proc #### 为什么 引用 https://linux-audit.com/linux-system-hardening-adding-hidepid-to-proc/ 的话: **注意**:这在某些 `systemd` 系统上可能会出现问题。详情请参见 [https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/37](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/37)。感谢 [nlgranger](https://github.com/nlgranger) 分享。 #### 目标 - 挂载 `/proc` 时带上 `hidepid=2`,以便用户只能看到有关其自己进程的信息 #### 参考 - https://linux-audit.com/linux-system-hardening-adding-hidepid-to-proc/ - https://likegeeks.com/secure-linux-server-hardening-best-practices/#Hardening-proc-Directory - https://www.cyberciti.biz/faq/linux-hide-processes-from-other-users/ #### 步骤 1. 备份 `/etc/fstab`: sudo cp --archive /etc/fstab /etc/fstab-COPY-$(date +"%Y%m%d%H%M%S") 2. 将以下行添加到 `/etc/fstab` 中,以便挂载带有 `hidepid=2` 的 `/proc`: proc /proc proc defaults,hidepid=2 0 0 [适合懒人的方法](#editing-configuration-files---for-the-lazy): echo -e "\nproc /proc proc defaults,hidepid=2 0 0 # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/fstab 3. 重启系统: sudo reboot now **注意**:或者,你可以使用 `sudo mount -o remount,hidepid=2 /proc` 重新挂载 `/proc` 而无需重启 ([目录](#table-of-contents)) ### 强制账户使用安全密码 #### 为什么 默认情况下,账户可以使用任何他们想要的,包括不好的密码。[pwquality](https://linux.die.net/man/5/pwquality.conf)/[pam_pwquality](https://linux.die.net/man/8/pam_pwquality) 通过提供“一种配置系统密码的默认密码质量要求的方法”并“根据系统字典和一组识别不良选择的规则检查其强度”来解决这一安全漏洞。 #### 工作原理 在 Linux 上,PAM 负责身份验证。PAM 有四个任务,你可以在 https://en.wikipedia.org/wiki/Linux_PAM 阅读相关内容。本节讨论的是密码任务。 当需要设置或更改账户密码时,PAM 的密码任务会处理该请求。在本节中,我们将告诉 PAM 的密码任务将请求的新密码传递给 libpam-pwquality,以确保其符合我们的要求。如果满足要求,则使用/设置它;如果不满足要求,则会报错并通知用户。 #### 目标 - 强制使用强密码 #### 步骤 1. 安装 libpam-pwquality。 在基于 Debian 的系统上: sudo apt install libpam-pwquality 2. 备份 PAM 的密码配置文件 `/etc/pam.d/common-password`: sudo cp --archive /etc/pam.d/common-password /etc/pam.d/common-password-COPY-$(date +"%Y%m%d%H%M%S") 3. 告诉 PAM 使用 libpam-pwquality 来强制使用强密码,编辑文件 `/etc/pam.d/common-password` 并将以这样开头的行: password requisite pam_pwquality.so 改为: password requisite pam_pwquality.so retry=3 minlen=10 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 maxrepeat=3 gecoschec 上述选项是: - `retry=3` = 在返回错误之前提示用户 3 次。 - `minlen=10` = 密码的最小长度,综合以下任何信用(或扣分)计算: - `dcredit=-1` = 必须至少包含**一个数字** - `ucredit=-1` = 必须至少包含**一个大写字母** - `lcredit=-1` = 必须至少包含**一个小写字母** - `ocredit=-1` = 必须至少包含**一个非字母数字字符** - `difok=3` = 新密码中至少有 3 个字符不能在旧密码中出现过 - `maxrepeat=3` = 最多允许 3 个重复字符 - `gecoschec` = 不允许包含账户名称的密码 [适合懒人的方法](#editing-configuration-files---for-the-lazy): sudo sed -i -r -e "s/^(password\s+requisite\s+pam_pwquality.so)(.*)$/# \1\2 # commented by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")\n\1 retry=3 minlen=10 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 maxrepeat=3 gecoschec # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/" /etc/pam.d/common-password ([目录](#table-of-contents)) ### 自动安全更新和警报 #### 为什么 保持服务器更新最新的**关键安全补丁和更新**非常重要。否则,你将面临恶意行为者可能利用已知漏洞获取对你服务器未经授权访问的风险。 除非你打算每天检查你的服务器,否则你需要一种自动更新系统和/或获取有关可用更新电子邮件的方法。 你不会希望进行所有更新,因为每次更新都有破坏某些东西的风险。进行关键更新很重要,但其他所有内容都可以等到你有时间手动操作时再进行。 #### 为什么不这么做 自动和无人值守的更新可能会破坏你的系统,而且你可能不在服务器旁边来修复它。如果它破坏了你的 SSH 访问,这将尤其成问题。 #### 注意事项 - 每个发行版管理包和更新的方式都不同。目前我只有基于 Debian 系统的步骤。 - 你的服务器需要一种发送电子邮件的方式才能使其工作 #### 目标 - 自动、无人值守地更新关键安全补丁 - 自动通过电子邮件发送剩余待处理更新的通知 #### 基于 Debian 的系统 ##### 工作原理 在基于 Debian 的系统上,你可以使用: - unattended-upgrades 自动执行你想要的系统更新(即关键安全更新) - apt-listchanges 在安装/升级包之前获取有关包更改的详细信息 - apticron 获取待处理包更新的电子邮件 我们将使用 unattended-upgrades 来应用**关键安全补丁**。我们还可以应用稳定版更新,因为它们已经经过了 Debian 社区的彻底测试。 ##### 参考 - https://wiki.debian.org/UnattendedUpgrades - https://debian-handbook.info/browse/stable/sect.regular-upgrades.html - https://blog.sleeplessbeastie.eu/2015/01/02/how-to-perform-unattended-upgrades/ - https://www.vultr.com/docs/how-to-set-up-unattended-upgrades-on-debian-9-stretch - https://github.com/mvo5/unattended-upgrades - https://wiki.debian.org/UnattendedUpgrades#apt-listchanges - https://www.cyberciti.biz/faq/apt-get-apticron-send-email-upgrades-available/ - https://www.unixmen.com/how-to-get-email-notifications-for-new-updates-on-debianubuntu/ - `/etc/apt/apt.conf.d/50unattended-upgrades` ##### 步骤 1. 安装 unattended-upgrades、apt-listchanges 和 apticron: sudo apt install unattended-upgrades apt-listchanges apticron 2. 现在我们需要配置 unattended-upgrades 以自动应用更新。这通常是通过编辑由包创建的文件 `/etc/apt/apt.conf.d/20auto-upgrades` 和 `/etc/apt/apt.conf.d/50unattended-upgrades` 来完成的。但是,因为这些文件可能会在未来的更新中被覆盖,所以我们将创建一个新文件。创建文件 `/etc/apt/apt.conf.d/51myunattended-upgrades` 并添加以下内容: // 启用更新/升级脚本 (0=禁用) APT::Periodic::Enable "1"; // 每 n 天自动执行 "apt-get update" (0=禁用) APT::Periodic::Update-Package-Lists "1"; // 每 n 天执行 "apt-get upgrade --download-only" (0=禁用) APT::Periodic::Download-Upgradeable-Packages "1"; // 每 n 天执行 "apt-get autoclean" (0=禁用) APT::Periodic::AutocleanInterval "7"; // 发送报告邮件给 root // 0: 无报告 (或空字符串) // 1: 进度报告 (实际上是任何字符串) // 2: + 命令输出 (移除 -qq,移除 2>/dev/null,添加 -d) // 3: + 启用跟踪 APT::Periodic::Verbose "2"; APT::Periodic::Unattended-Upgrade "1"; // 自动升级来自这些源的包 Unattended-Upgrade::Origins-Pattern { "o=Debian,a=stable"; "o=Debian,a=stable-updates"; "origin=Debian,codename=${distro_codename},label=Debian-Security"; }; // 你可以在这里指定不要自动升级的自定义包 Unattended-Upgrade::Package-Blacklist { }; // 如果检测到不干净的 dpkg 状态,则运行 dpkg --force-confold --configure -a 以设为 true,以确保即使系统在上次运行期间被中断也能安装更新 Unattended-Upgrade::AutoFixInterruptedDpkg "true"; //在机器运行时执行升级,因为我们不会经常关闭服务器 Unattended-Upgrade::InstallOnShutdown "false"; // 将有关已升级包的信息发送到此地址的电子邮件。 Unattended-Upgrade::Mail "root"; // 始终发送电子邮件 Unattended-Upgrade::MailOnlyOnError "false"; // 升级完成后移除所有未使用的依赖项 Unattended-Upgrade::Remove-Unused-Dependencies "true"; // 升级完成后移除任何新的未使用依赖项 Unattended-Upgrade::Remove-New-Unused-Dependencies "true"; // 如果在升级后找到 /var/run/reboot-required 文件,则无需确认自动重启。 Unattended-Upgrade::Automatic-Reboot "true"; // 即使用户已登录也自动重启。 Unattended-Upgrade::Automatic-Reboot-WithUsers "true"; **注意**: - 查看 `/usr/lib/apt/apt.systemd.daily` 了解 `APT::Periodic` 选项的详细信息 - 查看 https://github.com/mvo5/unattended-upgrades 了解 `Unattended-Upgrade` 选项的详细信息 3. 试运行 unattended-upgrades 以确保你的配置文件没有问题: sudo unattended-upgrade -d --dry-run 如果一切正常,你可以让它在预定的时间运行,或者使用 `unattended-upgrade -d` 强制运行一次。 4. 根据你的喜好配置 apt-listchanges: sudo dpkg-reconfigure apt-listchanges 5. 对于 apticron,默认设置已经足够好了,但如果你想更改它们,可以在 `/etc/apticron/apticron.conf` 中查看。例如,我的配置如下所示: ([目录](#table-of-contents)) ### 更安全的随机熵池 (编写中) #### 为什么 编写中 #### 工作原理 编写中 #### 目标 编写中 #### 参考 - 感谢 [branneman](https://github.com/branneman) 在 [issue #33](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/33) 中提交的这个想法。 - https://hackaday.com/2017/11/02/what-is-entropy-and-how-do-i-get-more-of-it/ - https://www.2uo.de/myths-about-urandom - https://www.gnu.org/software/hurd/user/tlecarrour/rng-tools.html - https://wiki.archlinux.org/index.php/Rng-tools - https://www.howtoforge.com/helping-the-random-number-generator-to-gain-enough-entropy-with-rng-tools-debian-lenny - https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/security_guide/sect-security_guide-encryption-using_the_random_number_generator #### 步骤 1. 安装 rng-tools。 在基于 Debian 的系统上: sudo apt-get install rng-tools 2. 现在我们需要通过将以下内容添加到 `/etc/default/rng-tools` 来设置用于生成随机数的硬件设备: HRNGDEVICE=/dev/urandom [适合懒人的方法](#editing-configuration-files---for-the-lazy): echo "HRNGDEVICE=/dev/urandom" | sudo tee -a /etc/default/rng-tools 3. 重启服务: sudo systemctl stop rng-tools.service sudo systemctl start rng-tools.service 4. 测试随机性: - https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/security_guide/sect-security_guide-encryption-using_the_random_number_generator - https://wiki.archlinux.org/index.php/Rng-tools ([目录](#table-of-contents)) ### 添加紧急/备用/虚假密码登录安全系统 #### 为什么 一个极好的工具,可增加额外的密码安全性,防范物理攻击(面对面)勒索/抢劫/袭击方式。 #### 工作原理 pamduress 将为 X 用户添加一个辅助密码(紧急密码),当此密码匹配时,将开始运行一个脚本(此脚本执行你希望用户在使用这些紧急密码登录时执行的操作)。 实际的真实示例: “某个强盗闯入一个家庭,并偷走了服务器(其中包含重要的业务备份,以及个人生活记忆等等)。不存在任何磁盘/启动加密。强盗在他们的‘安全区’启动了服务器并开始暴力破解攻击。他通过 SSH 用 sudoer 用户 'admin' 成功破解了本地密码,是的,一个虚拟密码,而不是那个强效的/主要密码。他开始使用那个被破解的虚拟/紧急密码以 'admin' sudoer 身份进行 SSH 会话/或物理会话。他开始感觉服务器在不到 2 分钟内似乎变得太忙了,直到冻结..‘搞什么鬼!?让我们重启并继续窃取信息..’。抱歉朋友。所有的数据和系统都已被销毁。”。 结论是,强盗破解了虚拟/紧急/辅助密码,而与该密码关联的脚本将执行删除所有文件、配置、系统、启动的操作,随后开始大量占用 RAM 和 CPU 以迫使强盗重启系统。 #### 目标 防止恶意人员在通过暴力方式(袭击、持枪、勒索等)获得密码后访问服务器信息。当然,这在其他情况下也很有用。 #### 参考 - 感谢 [nuvious](https://github.com/nuvious/pam-duress) 提供的工具 - 感谢 [hellresistor](https://gist.github.com/hellresistor/a4c542415a2d437e21afc235260d2366) 提供的懒人工具脚本 #### 步骤 1. 运行此命令。 ``` #!/bin/bash myownscript(){ ####################################################### ## ***** 根据您的需求编辑此脚本 *****# cat > "$ScriptFile" <<-EOF #!/bin/bash sudo rm -rf /home #### 已完成自定义脚本 #### EOF ####################################################### } echo "Lets Config a PANIC PASSWORD ;)" && sleep 1 read -r -p "Want you REALLY configure A PANIC PASSWORD?? Write [ OK ] : " PAMDUR if [[ "$PAMDUR" = "OK" ]]; then echo "Lets Config a PANIC USER, PASSWORD and SCRIPT ;)" && sleep 1 while [ -z "$PANICUSR" ] do read -r -p "WRITE a Panic User to your pam-duress user [ root ]: " PANICUSR PANICUSR=${PANICUSR:=root} done if [ -z "$ScriptLoc" ]; then read -r -p "SET Script Directory with FULL PATH [ /root/.duress ]: " ScriptLoc ScriptLoc=${ScriptLoc:=/root/.duress} ScriptFile="$ScriptLoc/PanicScript.sh" fi else echo "NOT Use PAM DURESS aKa Panic Password!!! Bye" exit 1 fi sudo apt install -y git build-essential libpam0g-dev libssl-dev cd "$HOME" || exit 1 git clone https://github.com/nuvious/pam-duress.git cd pam-duress || exit 1 make sudo make install make clean #make uninstall mkdir -p $ScriptLoc sudo mkdir -p /etc/duress.d myownscript duress_sign $ScriptFile chmod -R 500 $ScriptLoc chmod 400 $ScriptLoc/*.sha256 chown -R $PANICUSR $ScriptLoc sudo cp --preserve /etc/pam.d/common-auth /etc/pam.d/common-auth.bck echo " auth [success=2 default=ignore] pam_unix.so nullok_secure auth [success=1 default=ignore] pam_duress.so auth requisite pam_deny.so auth required pam_permit.so " | sudo tee /etc/pam.d/common-auth read -r -p "Press Key to Finish PAM DURESS Script!" exit 0 ``` ([目录](#table-of-contents)) ## 网络 ### 使用 UFW (Uncomplicated Firewall) 配置防火墙 #### 为什么 说我偏执也好,你也不必同意,但我想拒绝我服务器上的所有进出流量,除非我明确允许。为什么我的服务器会发送我不知道的流量?如果我不知道流量是谁或什么,为什么它要尝试访问我的服务器?在良好的安全性方面,我的意见是默认拒绝/屏蔽,按例外允许。 当然,如果你不同意,那也完全没问题,并且可以配置 UFW 以满足你的需求。 无论哪种方式,确保只允许我们明确允许的流量是防火墙的工作。 #### 工作原理 Linux 内核提供了监控和控制网络流量的功能。这些功能通过防火墙实用程序暴露给最终用户。在 Linux 上,最常见的防火墙是 [iptables](https://en.wikipedia.org/wiki/Iptables)。然而,iptables 相当复杂和令人困惑(IMHO)。这就是 UFW 的用武之地。把 UFW 当作 iptables 的前端。它简化了管理告诉 Linux 内核如何处理网络流量的 iptables 规则的过程。 **UFW** 的工作原理是让你配置以下规则: - **允许** 或 **拒绝** - **入站** 或 **出站** 流量 - **到** 或 **来自** 端口 你可以通过显式指定端口或使用指定端口的应用程序配置来创建规则。 #### 目标 - 所有网络流量,包括入站和出站,都被阻止,除非我们明确允许 #### 注意事项 - 随着你安装其他程序,你需要启用必要的端口/应用程序。 #### 参考 - https://launchpad.net/ufw #### 步骤 1. 安装 ufw。 在基于 Debian 的系统上: sudo apt install ufw 2. 拒绝所有出站流量: sudo ufw default deny outgoing comment 'deny all outgoing traffic' 如果你不像我这样偏执,并且不想拒绝所有出站流量,你可以改为允许: sudo ufw default allow outgoing comment 'allow all outgoing traffic' 3. 拒绝所有入站流量: sudo ufw default deny incoming comment 'deny all incoming traffic' 4. 显然我们希望 SSH 连接进来。使用 limit 代替 allow 将在一个 IP 地址在 30 秒内尝试发起 6 次或更多连接时自动拒绝该连接: sudo ufw limit in ssh comment 'allow SSH connections in' 5. 根据你的需要允许额外的流量。一些常见的用例: # 允许流量出到端口 53 -- DNS sudo ufw allow out 53 comment 'allow DNS calls out' # 允许流量出到端口 123 -- NTP sudo ufw allow out 123 comment 'allow NTP out' # 允许 HTTP、HTTPS 或 FTP 的出站流量 # apt 可能需要这些,具体取决于你使用的源 sudo ufw allow out http comment 'allow HTTP traffic out' sudo ufw allow out https comment 'allow HTTPS traffic out' sudo ufw allow out ftp comment 'allow FTP traffic out' # 允许 whois sudo ufw allow out whois comment 'allow whois' # 允许用于状态通知的邮件 -- 根据你的提供商选择端口 sudo ufw allow out 25 comment 'allow SMTP out' sudo ufw allow out 587 comment 'allow SMTP out' # 允许流量出到端口 68 -- DHCP 客户端 # 只有在使用 DHCP 时才需要此规则 sudo ufw allow out 67 comment 'allow the DHCP client to update' sudo ufw allow out 68 comment 'allow the DHCP client to update' **注意**:你需要允许 HTTP/HTTPS 才能安装包和执行许多其他操作。 6. 启动 ufw: sudo ufw enable 7. 如果你想查看状态: sudo ufw status 或 sudo ufw status verbose 8. 如果你需要删除规则 sudo ufw status numbered [...] sudo ufw delete 3 #你要删除的规则的行号 #### 默认应用程序 ufw 附带了一些默认应用程序。你可以使用以下命令查看它们: ``` sudo ufw app list ``` 要获取有关该应用程序的详细信息(例如它包含哪些端口),请输入: ``` sudo ufw app info [app name] ``` #### 自定义应用程序 如果你不想通过显式提供端口号来创建规则,你可以创建自己的应用程序配置。为此,请在 `/etc/ufw/applications.d` 中创建一个文件。 例如,以下是用于 [Plex](https://support.plex.tv/articles/201543147-what-network-ports-do-i-need-to-allow-through-my-firewall/) 的配置: ``` cat /etc/ufw/applications.d/plexmediaserver ``` 然后你可以像启用任何其他应用程序一样启用它: ``` sudo ufw allow plexmediaserver ``` ([目录](#table-of-contents)) ### 使用 PSAD 进行 iptables 入侵检测与防御 #### 为什么 即使你有防火墙守卫你的大门,仍然有可能尝试暴力破解任何受守卫的大门。我们想要监控所有网络活动以检测潜在的入侵尝试,例如反复尝试进入,并阻止它们。 #### 工作原理 我无法解释得比来自 https://serverfault.com/ 的用户 [FINESEC](https://serverfault.com/users/143961/finesec) 更好,详情请见:https://serverfault.com/a/447604/289829。 并且,由于我们已经在使用 [UFW](#ufw-uncomplicated-firewall),所以我们将遵循 [netson](https://gist.github.com/netson) 在 https://gist.github.com/netson/c45b2dc4e835761fbccc 提供的优秀说明,使 PSAD 与 UFW 一起工作。 #### 参考 - http://www.cipherdyne.org/psad/ - http://www.cipherdyne.org/psad/docs/config.html - https://www.thefanclub.co.za/how-to/how-install-psad-intrusion-detection-ubuntu-1204-lts-server - https://serverfault.com/a/447604/289829 - https://serverfault.com/a/770424/289829 - https://gist.github.com/netson/c45b2dc4e835761fbccc - 感谢 [moltenbit](https://github.com/moltenbit) 发现了 `psadwatchd` 的问题 ([#61](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/61))。 #### 步骤 1. 安装 psad。 在基于 Debian 的系统上: sudo apt install psad 2. 备份 psad 的配置文件 `/etc/psad/psad.conf`: sudo cp --archive /etc/psad/psad.conf /etc/psad/psad.conf-COPY-$(date +"%Y%m%d%H%M%S") 3. 检查并更新 `/etc/psad/psad.conf` 中的配置选项。特别注意以下几点: |设置|设置为 |--|--| |[`EMAIL_ADDRESSES`](http://www.cipherdyne.org/psad/docs/config.html#EMAIL_ADDRESSES)|你的电子邮件地址(多个)| |`HOSTNAME`|你的服务器主机名| |`EXPECT_TCP_OPTIONS`|`EXPECT_TCP_OPTIONS Y;`| |`ENABLE_PSADWATCHD`|`ENABLE_PSADWATCHD Y;`| |[`ENABLE_AUTO_IDS`](http://www.cipherdyne.org/psad/docs/config.html#ENABLE_AUTO_IDS)|`ENABLE_AUTO_IDS Y;`| |`ENABLE_AUTO_IDS_EMAILS`|`ENABLE_AUTO_IDS_EMAILS Y;`| 查看配置文件 psad 的文档 http://www.cipherdyne.org/psad/docs/config.html 获取更多详细信息。 4. 现在我们需要对 ufw 进行一些更改,以便它与 psad 一起工作,方法是告诉 ufw 记录所有流量,以便 psad 可以对其进行分析。通过编辑**两个文件**并将这些行添加在**末尾但在 COMMIT 行之前**来完成此操作。 进行备份: sudo cp --archive /etc/ufw/before.rules /etc/ufw/before.rules-COPY-$(date +"%Y%m%d%H%M%S") sudo cp --archive /etc/ufw/before6.rules /etc/ufw/before6.rules-COPY-$(date +"%Y%m%d%H%M%S") 编辑文件: - `/etc/ufw/before.rules` - `/etc/ufw/before6.rules` 并将此添加在**末尾但在 COMMIT 行之前**: # 记录所有流量以便 psad 分析 -A INPUT -j LOG --log-tcp-options --log-prefix "[IPTABLES] " -A FORWARD -j LOG --log-tcp-options --log-prefix "[IPTABLES] " **注意** UFW 会告诉你的服务器哪些门需要封死以免被人看到,哪些门允许授权用户通过。PSAD 则通过监控网络活动来检测并防止潜在的入侵——即那些反复尝试闯入的行为。 但是,你的服务器上运行的应用程序/服务(比如 SSH 和 Apache)又该如何保护呢?毕竟你的防火墙已经配置为允许对这些服务进行访问。虽然允许访问,但这并不意味着所有的访问尝试都是合法且无害的。如果有人试图对你服务器上运行的 Web 应用进行暴力破解怎么办?这就是 Fail2ban 发挥作用的地方。 #### 工作原理 Fail2ban 通过监控应用程序(如 SSH 和 Apache)的日志来检测并防止潜在的入侵。它会监控网络流量/日志,并通过阻止可疑活动(例如在短时间内连续多次连接失败)来防止入侵。 #### 目标 - 监控网络可疑活动,并自动封禁违规 IP #### 注意事项 - 截至目前,这台服务器上运行的唯一服务就是 SSH,因此我们需要 Fail2ban 监控 SSH 并在必要时进行封禁。 - 随着你安装其他程序,你需要创建/配置相应的监狱并启用它们。 #### 参考资料 - https://www.fail2ban.org/ - https://blog.vigilcode.com/2011/05/ufw-with-fail2ban-quick-secure-setup-part-ii/ - https://dodwell.us/security/ufw-fail2ban-portscan.html - https://www.howtoforge.com/community/threads/fail2ban-and-ufw-on-debian.77261/ #### 步骤 1. 安装 fail2ban。 在基于 Debian 的系统上: sudo apt install fail2ban 2. 我们不希望直接编辑 `/etc/fail2ban/fail2ban.conf` 或 `/etc/fail2ban/jail.conf`,因为未来的更新可能会覆盖它们,所以我们将创建一个本地副本。创建文件 `/etc/fail2ban/jail.local`,在将 `[LAN SEGMENT]` 和 `[your email]` 替换为适当的值后,将以下内容添加到其中: [DEFAULT] # 我们要忽略的 IP 地址范围 ignoreip = 127.0.0.1/8 [LAN SEGMENT] # 电子邮件发送给谁 destemail = [your e-mail] # 电子邮件的发件人是谁 sender = [your e-mail] # 因为我们使用 exim4 发送电子邮件 mta = mail # 获取电子邮件警报 action = %(action_mwl)s **注意**:你的服务器需要具备发送电子邮件的功能,这样 Fail2ban 才能在发现可疑活动或封禁 IP 时通知你。 3. 我们需要为 SSH 创建一个监狱,告诉 fail2ban 查看 SSH 日志,并根据需要使用 ufw 来封禁/解封 IP。通过创建文件 `/etc/fail2ban/jail.d/ssh.local` 并添加以下内容来为 SSH 创建监狱: [sshd] enabled = true banaction = ufw port = ssh filter = sshd logpath = %(sshd_log)s maxretry = 5 [适合懒人](#editing-configuration-files---for-the-lazy): cat << EOF | sudo tee /etc/fail2ban/jail.d/ssh.local [sshd] enabled = true banaction = ufw port = ssh filter = sshd logpath = %(sshd_log)s maxretry = 5 EOF 4. 在上面的配置中,我们告诉 fail2ban 将 ufw 作为 `banaction`。Fail2ban 自带了针对 ufw 的操作配置文件。你可以在 `/etc/fail2ban/action.d/ufw.conf` 中查看它。 5. 启用 fail2ban: sudo fail2ban-client start sudo fail2ban-client reload sudo fail2ban-client add sshd # 如果默认已添加 sshd 监狱,此命令在某些系统上可能会失败 6. 检查状态: sudo fail2ban-client status sudo fail2ban-client status sshd #### 自定义监狱 我暂时还不需要创建自定义监狱。一旦我需要并且弄清楚如何操作后,我会更新本指南。或者,如果你知道如何操作,请帮助[贡献](#contributing)。 #### 解封 IP 要解封 IP,请使用以下命令: ``` fail2ban-client set [jail] unbanip [IP] ``` `[jail]` 是封禁了该 IP 的监狱名称,`[IP]` 是你想要解封的 IP 地址。例如,要从 SSH 中解封 `192.168.1.100`,你可以这样做: ``` fail2ban-client set sshd unbanip 192.168.1.100 ``` ([目录](#table-of-contents)) ### 使用 CrowdSec 进行应用入侵检测与防御 #### 原因 UFW 会告诉你的服务器哪些门需要封死以免被人看到,哪些门允许授权用户通过。PSAD 则通过监控网络活动来检测并防止潜在的入侵——即那些反复尝试闯入的行为。 CrowdSec 与 Fail2Ban 类似,它通过监控应用程序(如 SSH 和 Apache)的日志来检测并防止潜在的入侵。然而,CrowdSec 结合了一个社区,该社区将威胁情报回传给 CrowdSec,然后将社区封锁列表分发给所有用户。 #### 工作原理 CrowdSec 通过监控应用程序(如 SSH 和 Apache)的日志来检测并防止潜在的入侵。它会监控网络流量/日志,并通过阻止可疑活动(例如在短时间内连续多次连接失败)来防止入侵。一旦检测到恶意 IP,该 IP 将被添加到你的本地决策列表中,并且威胁信息会与 CrowdSec 共享,以更新有关恶意 IP 地址的社区封锁列表。一旦某个 IP 地址的恶意活动达到一定阈值,它将被自动传播给所有其他 CrowdSec 用户以进行主动拦截。 #### 目标 - 监控网络可疑活动,并自动封禁违规 IP #### 注意事项 - 截至目前,这台服务器上运行的唯一服务就是 SSH,因此我们需要 CrowdSec 监控 SSH 并在必要时进行封禁。 - 随着你安装其他程序,你需要安装额外的集合并配置相应的数据获取源。 #### 参考资料 - https://www.crowdsec.net/ - [了解 CrowdSec 如何管理社区封锁列表](https://www.crowdsec.net/our-data) - [了解哪些威胁情报会与 CrowdSec 共享](https://docs.crowdsec.net/docs/next/central_api/intro#signal-meta-data) - https://docs.crowdsec.net/ #### 步骤 1. 安装 CrowdSec 安全引擎。(IDS) 在任何 Linux 发行版(包括基于 Debian 的系统)上 安装 CrowdSec 仓库: curl -s https://install.crowdsec.net | sudo sh 安装 CrowdSec 安全引擎: sudo apt install crowdsec 默认情况下,CrowdSec 在安装安全引擎时会自动发现你已安装的应用程序,并为它们安装相应的解析器和场景。由于我们知道大多数 Linux 服务器开箱即用都在运行 SSH,CrowdSec 会自动为你完成配置。 2. 安装补救组件。(IPS) CrowdSec 本身是一个检测引擎,因为在大多数现代基础设施中,你可能拥有上游防火墙或 WAF,所以 CrowdSec 不会自行拦截 IP 地址。你可以安装一个补救组件来拦截由 CrowdSec 检测到的 IP 地址。 sudo apt install crowdsec-firewall-bouncer-iptables 默认情况下,在安装补救组件时,如果它部署在同一主机上(并且安全引擎不在容器环境中),它将自动配置必要的设置以与安全引擎协同工作。 3. 检查检测和补救功能是否按预期工作: CrowdSec 软件包附带了一个 CLI 工具,用于检查安全引擎和补救组件的状态。 sudo cscli metrics 采集指标: ╭────────────────────────┬────────────┬──────────────┬────────────────┬────────────────────────┬───────────────────╮ │ 来源 │ 读取行数 │ 已解析行数 │ 未解析行数 │ 倾倒至桶的行数 │ 白名单行数 │ ├────────────────────────┼────────────┼──────────────┼────────────────┼────────────────────────┼───────────────────┤ │ file:/var/log/auth.log │ 5 │ 4 │ 1 │ 10 │ - │ │ file:/var/log/syslog │ 30 │ - │ 30 │ - │ - │ ╰────────────────────────┴────────────┴──────────────┴────────────────┴────────────────────────┴───────────────────╯ 本地 API 决策: ╭────────────────────────────────────────────┬────────┬────────┬───────╮ │ 原因 │ 来源 │ 动作 │ 计数 │ ├────────────────────────────────────────────┼────────┼────────┼───────┤ │ crowdsecurity/http-backdoors-attempts │ CAPI │ ban │ 73 │ │ crowdsecurity/http-bad-user-agent │ CAPI │ ban │ 4836 │ │ crowdsecurity/http-path-traversal-probing │ CAPI │ ban │ 87 │ │ crowdsecurity/http-probing │ CAPI │ ban │ 2010 │ │ crowdsecurity/thinkphp-cve-2018-20062 │ CAPI │ ban │ 88 │ │ crowdsecurity/CVE-2019-18935 │ CAPI │ ban │ 7 │ │ crowdsecurity/CVE-2023-49103 │ CAPI │ ban │ 5 │ │ crowdsecurity/http-admin-interface-probing │ CAPI │ ban │ 91 │ │ ltsich/http-w00tw00t │ CAPI │ ban │ 3 │ │ crowdsecurity/apache_log4j2_cve-2021-44228 │ CAPI │ ban │ 18 │ │ crowdsecurity/nginx-req-limit-exceeded │ CAPI │ ban │ 280 │ │ crowdsecurity/ssh-slow-bf │ CAPI │ ban │ 3412 │ │ crowdsecurity/spring4shell_cve-2022-22965 │ CAPI │ ban │ 1 │ │ crowdsecurity/ssh-cve-2024-6387 │ CAPI │ ban │ 24 │ │ crowdsecurity/CVE-2023-22515 │ CAPI │ ban │ 2 │ │ crowdsecurity/http-cve-2021-41773 │ CAPI │ ban │ 172 │ │ crowdsecurity/netgear_rce │ CAPI │ ban │ 14 │ │ crowdsecurity/ssh-bf │ CAPI │ ban │ 2000 │ │ crowdsecurity/CVE-2022-35914 │ CAPI │ ban │ 1 │ │ crowdsecurity/http-cve-2021-42013 │ CAPI │ ban │ 2 │ │ crowdsecurity/jira_cve-2021-26086 │ CAPI │ ban │ 9 │ │ crowdsecurity/http-sensitive-files │ CAPI │ ban │ 166 │ │ crowdsecurity/http-wordpress-scan │ CAPI │ ban │ 272 │ │ crowdsecurity/CVE-2022-26134 │ CAPI │ ban │ 5 │ │ crowdsecurity/http-generic-bf │ CAPI │ ban │ 7 │ │ crowdsecurity/http-open-proxy │ CAPI │ ban │ 948 │ │ crowdsecurity/http-crawl-non_statics │ CAPI │ ban │ 339 │ │ crowdsecurity/http-cve-probing │ CAPI │ ban │ 5 │ │ crowdsecurity/CVE-2017-9841 │ CAPI │ ban │ 117 │ │ crowdsecurity/CVE-2022-37042 │ CAPI │ ban │ 1 │ │ crowdsecurity/fortinet-cve-2018-13379 │ CAPI │ ban │ 5 │ ╰────────────────────────────────────────────┴────────┴────────┴───────╯ 本地 API 指标: ╭──────────────────────┬────────┬──────╮ │ 路由 │ 方法 │ 命中 │ ├──────────────────────┼────────┼──────┤ │ /v1/alerts │ GET │ 2 │ │ /v1/decisions/stream │ GET │ 5 │ │ /v1/usage-metrics │ POST │ 2 │ │ /v1/watchers/login │ POST │ 4 │ ╰──────────────────────┴────────┴──────╯ 本地 API Bouncer 指标: ╭────────────────────────────────┬──────────────────────┬────────┬──────╮ │ Bouncer │ 路由 │ 方法 │ 命中 │ ├────────────────────────────────┼──────────────────────┼────────┼──────┤ │ cs-firewall-bouncer-1729025592 │ /v1/decisions/stream │ GET │ 5 │ ╰────────────────────────────────┴──────────────────────┴────────┴──────╯ 本地 API 机器指标: ╭──────────────────────────────────────────────────┬────────┬────────┬──────╮ │ 机器 │ 路由 │ 方法 │ 命中 │ ├──────────────────────────────────────────────────┼────────────┼────────┼──────┤ │ │ /v1/alerts │ GET │ 2 │ ╰──────────────────────────────────────────────────┴────────────┴────────┴──────╯ 解析器指标: ╭─────────────────────────────────┬──────┬────────┬──────────╮ │ 解析器 │ 命中 │ 已解析 │ 未解析 │ ├─────────────────────────────────┼──────┼────────┼──────────┤ │ child-crowdsecurity/sshd-logs │ 41 │ 4 │ 37 │ │ child-crowdsecurity/syslog-logs │ 35 │ 35 │ - │ │ crowdsecurity/dateparse-enrich │ 4 │ 4 │ - │ │ crowdsecurity/sshd-logs │ 5 │ 4 │ 1 │ │ crowdsecurity/syslog-logs │ 35 │ 35 │ - │ ╰─────────────────────────────────┴──────┴────────┴──────────╯ 场景指标: ╭─────────────────────────────────────┬───────────────┬───────────┬──────────────┬────────┬─────────╮ │ 场景 │ 当前计数 │ 溢出 │ 实例化 │ 倾倒数 │ 过期数 │ ├─────────────────────────────────────┼───────────────┼───────────┼──────────────┼────────┼─────────┤ │ crowdsecurity/ssh-bf │ 1 │ - │ 1 │ 4 │ - │ │ crowdsecurity/ssh-bf_user-enum │ 1 │ - │ 1 │ 1 │ - │ │ crowdsecurity/ssh-slow-bf │ 1 │ - │ 1 │ 4 │ - │ │ crowdsecurity/ssh-slow-bf_user-enum │ 1 │ - │ 1 │ 1 │ - │ ╰─────────────────────────────────────┴───────────────┴───────────┴──────────────┴────────┴─────────╯ 上面的输出可能看起来有点吓人,但这是检查安全引擎是否正在读取日志以及补救组件是否正在拦截 IP 地址的好方法。以下是各个部分的简要说明: - **采集指标**:此部分显示安全引擎正在读取和解析的日志。如果你在 `未解析行数` 列中看到有日志,这意味着安全引擎无法解析这些日志。这可能是由于配置错误或日志格式不符合预期造成的。 - **本地 API 决策**:此部分显示安全引擎在数据库中保存的决策。如果你在 `计数` 列中看到数字,这意味着安全引擎已检测到恶意活动并拦截了该 IP 地址。 - 来源:这是决策的来源。在这种情况下,它来自 Central API (CAPI)。 - **本地 API 指标**:此部分显示本地 API 的命中数量。这是安全引擎用来与补救组件通信的 API。 - **本地 API Bouncer 指标**:此部分显示补救组件对本地 API 的命中数量。 - **本地 API 机器指标**:此部分显示安全引擎对本地 API 的命中数量(如果你在集中式设置中运行多个安全引擎,你可以在这里看到多个 ID)。 - **解析器指标**:此部分显示安全引擎正在使用的解析器。如果你在 `未解析` 列中看到日志,这意味着安全引擎无法解析这些日志。这可能是由于配置错误或日志格式不符合预期造成的。 - **场景指标**:此部分显示安全引擎正在使用的场景。如果你在 `当前计数` 列中看到数字,这意味着安全引擎已检测到恶意活动并正在跟踪该 IP 地址。 #### 解封 IP 要解封 IP,请使用以下命令: ``` cscli decisions delete --ip [IP] ``` `[IP]` 是你想要解封的 IP 地址。例如,要从 SSH 中解封 `192.168.1.100`,你可以这样做: ``` cscli decisions delete --ip 192.168.1.100 ``` ## 审计部分 ### 使用 AIDE 进行文件/文件夹完整性监控 (WIP) #### 原因 WIP #### 工作原理 WIP #### 目标 WIP #### 参考资料 - https://aide.github.io/ - https://www.hiroom2.com/2017/06/09/debian-8-file-integrity-check-with-aide/ - https://blog.rapid7.com/2017/06/30/how-to-install-and-configure-aide-on-ubuntu-linux/ - https://www.stephenrlang.com/2016/03/using-aide-for-file-integrity-monitoring-fim-on-ubuntu/ - https://www.howtoforge.com/how-to-configure-the-aide-advanced-intrusion-detection-environment-file-integrity-scanner-for-your-website - https://www.tecmint.com/check-integrity-of-file-and-directory-using-aide-in-linux/ - https://www.cyberciti.biz/faq/debian-ubuntu-linux-software-integrity-checking-with-aide/ - https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/83 #### 步骤 1. 安装 AIDE。 在基于 Debian 的系统上: sudo apt install aide aide-common 2. 备份 AIDE 的默认文件: sudo cp -p /etc/default/aide /etc/default/aide-COPY-$(date +"%Y%m%d%H%M%S") 3. 查看 `/etc/default/aide` 并根据你的要求设置 AIDE 的默认值。如果你希望 AIDE 每天运行并发送电子邮件给你,请确保将 `CRON_DAILY_RUN` 设置为 `yes`。 4. 备份 AIDE 的配置文件: sudo cp -pr /etc/aide /etc/aide-COPY-$(date +"%Y%m%d%H%M%S") 5. 在基于 Debian 的系统上: - AIDE 的配置文件位于 `/etc/aide/aide.conf.d/`。 - 你需要查阅 AIDE 的文档和配置文件,并根据你的要求进行设置。 - 如果你需要新的设置,例如监控一个新文件夹,你需要将它们添加到 `/etc/aide/aide.conf` 或 `/etc/aide/aide.conf.d/`。 - 备份原始配置文件:`sudo cp -pr /etc/aide /etc/aide-COPY-$(date +"%Y%m%d%H%M%S")`。 6. 创建一个新数据库,并安装它。 在基于 Debian 的系统上: sudo aideinit 7. 在没有进行任何更改的情况下测试一切是否正常。 在基于 Debian 的系统上: sudo aide.wrapper --check 8. 在进行一些更改后测试一切是否正常。 在基于 Debian 的系统上: sudo touch /etc/test.sh sudo touch /root/test.sh sudo aide.wrapper --check sudo rm /etc/test.sh sudo rm /root/test.sh sudo aideinit -y -f 9. 大功告成。如果你在 `/etc/default/aide` 中将 `CRON_DAILY_RUN` 设置为 `yes`,那么 cron 将每天执行 `/etc/cron.daily/aide` 并通过电子邮件将输出发送给你。 #### 更新数据库 每次你更改 AIDE 监控的文件/文件夹时,你都需要更新数据库以记录这些更改。要在基于 Debian 的系统上执行此操作: ``` sudo aideinit -y -f ``` ([目录](#table-of-contents)) ### 使用 ClamAV 进行防病毒扫描 (WIP) #### 原因 WIP #### 工作原理 - ClamAV 是一个病毒扫描程序 - ClamAV-Freshclam 是一个保持病毒定义更新的服务 - ClamAV-Daemon 保持 `clamd` 进程运行以加快扫描速度 #### 目标 WIP #### 注意事项 - 这些说明**不会**告诉你如何启用 ClamAV 守护进程服务以确保 `clamd` 一直运行。`clamd` 仅在你运行邮件服务器时才需要,它不提供文件的实时监控。相反,你需要手动扫描文件或按计划进行扫描。 #### 参考资料 - https://www.clamav.net/documents/installation-on-debian-and-ubuntu-linux-distributions - https://wiki.debian.org/ClamAV - https://www.osradar.com/install-clamav-debian-9-ubuntu-18/ - https://www.lisenet.com/2014/automate-clamav-to-perform-daily-system-scan-and-send-email-notifications-on-linux/ - https://www.howtoforge.com/tutorial/configure-clamav-to-scan-and-notify-virus-and-malware/ - https://serverfault.com/questions/741299/is-there-a-way-to-keep-clamav-updated-on-debian-8 - https://askubuntu.com/questions/250290/how-do-i-scan-for-viruses-with-clamav - https://ngothang.com/how-to-install-clamav-and-configure-daily-scanning-on-centos/ #### 步骤 1. 安装 ClamAV。 在基于 Debian 的系统上: sudo apt install clamav clamav-freshclam clamav-daemon 2. 备份 `clamav-freshclam` 的配置文件 `/etc/clamav/freshclam.conf`: sudo cp --archive /etc/clamav/freshclam.conf /etc/clamav/freshclam.conf-COPY-$(date +"%Y%m%d%H%M%S") 3. `clamav-freshclam` 的默认设置可能已经足够好了,但如果你想更改它们,你可以编辑文件 `/etc/clamav/freshclam.conf` 或使用 `dpkg-reconfigure`: sudo dpkg-reconfigure clamav-freshclam **注意**:默认设置会在一天内更新定义 24 次。要更改间隔时间,请检查 `/etc/clamav/freshclam.conf` 中的 `Checks` 设置或使用 `dpkg-reconfigure`。 4. 启动 `clamav-freshclam` 服务: sudo service clamav-freshclam start 5. 你可以确认 `clamav-freshclam` 是否正在运行: sudo service clamav-freshclam status **注意**:不用担心 `Local version` 这一行。查看 https://serverfault.com/questions/741299/is-there-a-way-to-keep-clamav-updated-on-debian-8 了解更多详情。 6. 备份 `clamav-daemon` 的配置文件 `/etc/clamav/clamd.conf`: sudo cp --archive /etc/clamav/clamd.conf /etc/clamav/clamd.conf-COPY-$(date +"%Y%m%d%H%M%S") 7. 你可以通过编辑文件 `/etc/clamav/clamd.conf` 或使用 `dpkg-reconfigure` 来更改 `clamav-daemon` 的设置: sudo dpkg-reconfigure clamav-daemon #### 扫描文件/文件夹 - 要扫描文件/文件夹,请使用 `clamscan` 程序。 - `clamscan` 以执行它的用户身份运行,因此它需要对正在扫描的文件/文件夹具有读取权限。 - 以 `root` 身份使用 `clamscan` 是危险的,因为如果某个文件确实是病毒,就有风险它会利用 root 权限。 - 扫描单个文件:`clamscan /path/to/file`。 - 扫描目录:`clamscan -r /path/to/folder`。 - 你可以使用 `-i` 开关仅打印受感染的文件。 - 查看 `clamscan` 的 `man` 手册页了解其他开关/选项。 ([目录](#table-of-contents)) ### 使用 Rkhunter 进行 Rootkit 检测 (WIP) #### 原因 WIP #### 工作原理 WIP #### 目标 WIP #### 参考资料 - http://rkhunter.sourceforge.net/ - https://www.cyberciti.biz/faq/howto-check-linux-rootkist-with-detectors-software/ - https://www.tecmint.com/install-rootkit-hunter-scan-for-rootkits-backdoors-in-linux/ #### 步骤 1. 安装 Rkhunter。 在基于 Debian 的系统上: sudo apt install rkhunter 2. 备份 rkhunter 的默认文件: sudo cp -p /etc/default/rkhunter /etc/default/rkhunter-COPY-$(date +"%Y%m%d%H%M%S") 3. rkhunter 的配置文件是 `/etc/rkhunter.conf`。与其直接修改它,不如创建并使用文件 `/etc/rkhunter.conf.local`: sudo cp -p /etc/rkhunter.conf /etc/rkhunter.conf.local 4. 查看 `/etc/rkhunter.conf.local` 配置文件并根据你的要求进行设置。我的建议: |设置|说明| |--|--| |`UPDATE_MIRRORS=1`|| |`MIRRORS_MODE=0`|| |`MAIL-ON-WARNING=root`|| |`COPY_LOG_ON_ERROR=1`|在出现错误时保存日志副本| |`PKGMGR=...`|根据文档设置为适当的值| |`PHALANX2_DIRTEST=1`|阅读文档了解| |`WEB_CMD=""`|这是为了解决 Debian 软件包中禁用 rkhunter 自我更新功能的问题。| |`USE_LOCKING=1`|防止 rkhunter 多次运行引起的问题| |`SHOW_SUMMARY_WARNINGS_NUMBER=1`|查看发现的警告的实际数量| 5. 你可能希望 rkhunter 每天运行并将结果通过电子邮件发送给你。你可以编写自己的脚本,或者查看 https://www.tecmint.com/install-rootkit-hunter-scan-for-rootkits-backdoors-in-linux/ 获取你可以使用的示例 cron 脚本。 在基于 Debian 的系统上,rkhunter 自带了 cron 脚本。要启用它们,请检查 `/etc/default/rkhunter` 或使用 `dpkg-reconfigure` 并对所有问题回答 `Yes`: sudo dpkg-reconfigure rkhunter 6. 完成所有更改后,确保所有设置均有效: sudo rkhunter -C 7. 更新 rkhunter 及其数据库: sudo rkhunter --versioncheck sudo rkhunter --update sudo rkhunter --propupd 8. 如果你想进行手动扫描并查看输出: sudo rkhunter --check ([目录](#table-of-contents)) ### 使用 chrootkit 进行 Rootkit 检测 (WIP) #### 原因 WIP #### 工作原理 WIP #### 目标 WIP #### 参考资料 - http://www.chkrootkit.org/ - https://www.cyberciti.biz/faq/howto-check-linux-rootkist-with-detectors-software/ - https://askubuntu.com/questions/258658/eth0-packet-sniffer-sbin-dhclient #### 步骤 1. 安装 chkrootkit。 在基于 Debian 的系统上: sudo apt install chkrootkit 2. 进行手动扫描: sudo chkrootkit 3. 备份 chkrootkit 的配置文件 `/etc/chkrootkit.conf`: sudo cp --archive /etc/chkrootkit.conf /etc/chkrootkit.conf-COPY-$(date +"%Y%m%d%H%M%S") 4. 你希望 chkrootkit 每天运行并将结果通过电子邮件发送给你。 在基于 Debian 的系统上,chkrootkit 自带了 cron 脚本。要启用它们,请检查 `/etc/chkrootkit.conf` 或使用 `dpkg-reconfigure` 并对第一个问题回答 `Yes`: sudo dpkg-reconfigure chkrootkit ([目录](#table-of-contents)) ### logwatch - 系统日志分析器和报告器 #### 原因 你的服务器会生成大量可能包含重要信息的日志。除非你计划每天检查服务器,否则你需要一种方法来获取服务器日志的电子邮件摘要。为了实现这一点,我们将使用 [logwatch](https://sourceforge.net/projects/logwatch/)。 #### 工作原理 logwatch 会扫描系统日志文件并对其进行汇总。你可以直接从命令行运行它,或者将其安排为定期运行。logwatch 使用服务文件来了解如何读取/汇总日志文件。你可以在 `/usr/share/logwatch/scripts/services` 中查看所有内置的服务文件。 logwatch 的配置文件 `/usr/share/logwatch/default.conf/logwatch.conf` 指定了默认选项。你可以通过命令行参数覆盖它们。 #### 目标 - 配置 Logwatch 每天发送包含所有服务器状态和日志的电子邮件摘要 #### 注意事项 - 你的服务器需要能够发送电子邮件才能实现此功能 - 以下步骤将使得 logwatch 每天运行。如果你想更改计划,请根据喜好修改 cronjob。你还需要更改 `range` 选项以覆盖你的执行周期。请参阅 https://www.badpenguin.org/configure-logwatch-for-weekly-email-and-html-output-format 获取示例。 - 如果由于电子邮件行过长导致 logwatch 无法发送邮件,请查阅 [issue #29](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/29) 中记录的 https://blog.dhampir.no/content/exim4-line-length-in-debian-stretch-mail-delivery-failed-returning-message-to-sender 。如果你已经按照 [Gmail 和 Exim4 使用隐式 TLS 作为 MTA](#gmail-and-exim4-as-mta-with-implicit-tls) 进行了操作,那么我们在第 7 步中已经解决了这个问题。 #### 参考资料 - 感谢 [amacheema](https://github.com/amacheema) 修复了步骤中的一些问题,并告知了 exim4 长行 bug,正如 [issue #29](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/29) 中所记录的那样。 - https://sourceforge.net/projects/logwatch/ - https://www.digitalocean.com/community/tutorials/how-to-install-and-use-logwatch-log-analyzer-and-reporter-on-a-vps #### 步骤 1. 安装 logwatch。 在基于 Debian 的系统上: sudo apt install logwatch 2. 要查看 logwatch 收集内容的示例,你可以直接运行它: sudo /usr/sbin/logwatch --output stdout --format text --range yesterday --service all 3. 在继续之前,请仔细阅读 logwatch 的自带说明配置文件 `/usr/share/logwatch/default.conf/logwatch.conf`。这里无需更改任何内容,但请特别注意 `Output`、`Format`、`MailTo`、`Range` 和 `Service`,因为这些是我们将要使用的选项。出于我们的目的考虑,与其在配置文件中指定我们的选项,我们不如在执行 logwatch 的每日 cron 作业中以命令行参数的形式传递它们。这样一来,如果配置文件被修改(例如在更新期间),我们的选项仍然会保留。 4. 备份 logwatch 的每日 cron 文件 `/etc/cron.daily/00logwatch` 并取消执行权限位: sudo cp --archive /etc/cron.daily/00logwatch /etc/cron.daily/00logwatch-COPY-$(date +"%Y%m%d%H%M%S") sudo chmod -x /etc/cron.daily/00logwatch-COPY* 5. 默认情况下,logwatch 会输出到 `stdout`。既然目标是获取每日电子邮件,我们需要更改 logwatch 使用的输出类型,使其改为发送电子邮件。我们可以通过上面的配置文件来做到这一点,但这将应用于每次运行——甚至在我们手动运行并希望将输出显示在屏幕上时也是如此。相反,我们将更改执行 logwatch 的 cron 作业以发送电子邮件。这样一来,手动运行时,我们仍然会将输出到 `stdout`,而当由 cron 运行时,它会发送电子邮件。我们还要确保它检查所有服务,并将输出格式更改为 html,以便更容易阅读,而无论配置文件中写了什么。在文件 `/etc/cron.daily/00logwatch` 中找到执行行并将其更改为: /usr/sbin/logwatch --output mail --format html --mailto root --range yesterday --service all [适合懒人](#editing-configuration-files---for-the-lazy): sudo sed -i -r -e "s,^($(sudo which logwatch).*?),# \1 # commented by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")\n$(sudo which logwatch) --output mail --format html --mailto root --range yesterday --service all # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")," /etc/cron.daily/00logwatch 6. 你可以通过执行来测试 cron 作业: sudo /etc/cron.daily/00logwatch **注意**:如果由于电子邮件行过长导致 logwatch 无法发送邮件,请查阅 [issue #29](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/29) 中记录的 https://blog.dhampir.no/content/exim4-line-length-in-debian-stretch-mail-delivery-failed-returning-message-to-sender 。如果你已经按照 [Gmail 和 Exim4 使用隐式 TLS 作为 MTA](#gmail-and-exim4-as-mta-with-implicit-tls) 进行了操作,那么我们在第 7 步中已经解决了这个问题。 ([目录](#table-of-contents)) ### ss - 查看你的服务器正在监听的端口 #### 原因 端口是应用程序、服务和进程之间相互通信的方式——可以是在服务器本地进行,也可以是与网络上的其他设备进行。当你在服务器上运行应用程序或服务(如 SSH 或 Apache)时,它们会监听特定端口上的请求。 显然,我们不希望服务器在我们不知道的端口上进行监听。我们将使用 `ss` 查看服务正在监听的所有端口。这将帮助我们追踪并停止那些无赖的、具有潜在危险的服务。 #### 目标 - 找出非本地主机上哪些端口是开放的并正在监听连接 #### 参考资料 - https://www.reddit.com/r/linux/comments/arx7st/howtosecurealinuxserver_an_evolving_howto_guide/egrib6o/ - https://www.reddit.com/r/linux/comments/arx7st/howtosecurealinuxserver_an_evolving_howto_guide/egs1rev/ - https://www.tecmint.com/find-open-ports-in-linux/ - `man ss` #### 步骤 1. 要查看所有正在监听流量的端口: sudo ss -lntup **开关说明**: - `l` = 显示监听套接字 - `n` = 不尝试解析服务名称 - `t` = 显示 TCP 套接字 - `u` = 显示 UDP 套接字 - `p` = 显示进程信息 2. 如果你发现任何可疑内容,比如你不知道的端口或你不了解的进程,请进行调查并根据需要进行修复。 ([目录](#table-of-contents)) ### Lynis - Linux 安全审计 #### 原因 来自 [https://cisofy.com/lynis/](https://cisofy.com/lynis/): #### 目标 - Lynis 已安装 #### 注意事项 - CISOFY 为许多发行版提供软件包。请查看 https://packages.cisofy.com/ 获取特定于发行版的安装说明。 #### 参考资料 - https://cisofy.com/documentation/lynis/get-started/ - https://packages.cisofy.com/community/#debian-ubuntu - https://thelinuxcode.com/audit-lynis-ubuntu-server/ - https://www.vultr.com/docs/install-lynis-on-debian-8 #### 步骤 1. 安装 lynis。https://cisofy.com/lynis/#installation 包含有关如何为你的发行版安装它的详细说明。 在基于 Debian 的系统上,使用 CISOFY 的社区软件仓库: sudo apt install ca-certificates host sudo mkdir -p /etc/apt/keyrings wget -O - https://packages.cisofy.com/keys/cisofy-software-public.key | sudo gpg --dearmor -o /etc/apt/keyrings/cisofy-lynis.gpg echo "deb [signed-by=/etc/apt/keyrings/cisofy-lynis.gpg] https://packages.cisofy.com/community/lynis/deb/ stable main" | sudo tee /etc/apt/sources.list.d/cisofy-lynis.list sudo apt update sudo apt install lynis 2. 更新它: sudo lynis update info 3. 运行安全审计: sudo lynis audit system 这将扫描你的服务器,报告其审计结果,并在最后给出建议。花一些时间查看输出并根据需要解决差距。 ([目录](#table-of-contents)) ### OSSEC - 主机入侵检测 #### 原因 来自 [https://github.com/ossec/ossec-hids](https://github.com/ossec/ossec-hids) #### 目标 - OSSEC-HIDS 已安装 #### 参考资料 - https://www.ossec.net/docs/ #### 步骤 1. 从源代码安装 OSSEC-HIDS sudo apt install -y libz-dev libssl-dev libpcre2-dev build-essential libsystemd-dev wget https://github.com/ossec/ossec-hids/archive/3.7.0.tar.gz tar xzf 3.7.0.tar.gz cd ossec-hids-3.7.0/ sudo ./install.sh 2. 有用的命令: **代理信息** ``` sudo /var/ossec/bin/agent_control -i ``` `AGENT_ID` 默认为 `000`,为了确保无误可以使用命令 `sudo /var/ossec/bin/agent_control -l`。 **运行完整性/rootkit 检查** OSSEC 默认每 2 小时运行一次 rootkit 检查。 ``` sudo /var/ossec/bin/agent_control -u -r ``` **警报** - 全部: tail -f /var/ossec/logs/alerts/alerts.log - 完整性检查: sudo cat /var/ossec/logs/alerts/alerts.log | grep -A4 -i integrity - Rootkit 检查: sudo cat /var/ossec/logs/alerts/alerts.log | grep -A4 "rootcheck," ([目录](#table-of-contents)) ## 危险区域 ### 后果自负 本部分涵盖的高风险操作,因为它们有可能导致你的系统无法使用,或者被许多人认为是不必要的,因为风险大于任何回报。 **!! 后果自负 !!**
!! 后果自负 !! ([目录](#table-of-contents)) ### 目录 - [Linux Kernel sysctl 加固](#linux-kernel-sysctl-hardening) - [为 GRUB 设置密码保护](#password-protect-grub) - [禁用 Root 登录](#disable-root-login) - [更改默认 umask](#change-default-umask) - [孤立的软件](#orphaned-software) ([目录](#table-of-contents)) ### Linux Kernel sysctl 加固
!! 后果自负 !! #### 原因 内核是 Linux 系统的大脑。保护它是理所当然的。 #### 为什么不 使用 sysctl 更改内核设置是有风险的,可能会导致服务器崩溃。如果你不知道自己在做什么,没有时间调试问题,或者只是不想承担风险,我建议不要遵循这些步骤。 #### 免责声明 我对加固/保护 Linux 内核的了解并没有达到我期望的程度。尽管我很不愿意承认,但我并不清楚所有这些设置的作用。我的理解是,其中大部分是常规的内核加固和性能优化,其他则是为了防止欺骗和 DOS 攻击。 事实上,由于我不是 100% 确定每个设置的具体作用,我从众多网站(均在下面的参考资料中列出)提取了推荐的设置,并将它们结合起来以确定应该设置什么。我认为如果多个信誉良好的网站都提到了相同的设置,那它可能就是安全的。 如果你对这些设置的作用有更好的理解,或者对它们有任何其他反馈/建议,请[告诉我](#contacting-me)。 我不会在本节中提供[适合懒人](#editing-configuration-files---for-the-lazy)的代码。 #### 注意事项 - 关于所有 sysctl 设置/键的文档严重匮乏。[我能找到的文档](https://github.com/torvalds/linux/tree/master/Documentation)似乎引用的是 2.2 版本的内核。我找不到更新的内容。如果你知道我在哪里可以找到,请[告诉我](#contacting-me)。 - 下面列出的参考网站对每个设置的作用有更多注释。 #### 参考资料 - https://github.com/torvalds/linux/tree/master/Documentation - https://www.cyberciti.biz/faq/linux-kernel-etcsysctl-conf-security-hardening/ - https://geektnt.com/sysctl-conf-hardening.html - https://linoxide.com/how-tos/linux-server-protection/ - https://github.com/klaver/sysctl/blob/master/sysctl.conf - https://cloudpro.zone/index.php/2018/01/30/debian-9-3-server-setup-guide-part-5/ #### 步骤 1. sysctl 设置可以在本仓库的 [linux-kernel-sysctl-hardening.md](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/blob/master/linux-kernel-sysctl-hardening.md) 文件中找到。 2. 在永久进行内核 sysctl 更改之前,你可以使用 sysctl 命令对其进行测试: sudo sysctl -w [key=value] 示例: sudo sysctl -w kernel.ctrl-alt-del=0 **注意**:`key=value` 中没有空格,包括等号前后。 3. 一旦你测试了某个设置,并确保它在不破坏服务器的情况下正常工作,你可以通过将这些值添加到 `/etc/sysctl.conf` 中来使其永久生效。例如: $ sudo cat /etc/sysctl.conf kernel.ctrl-alt-del = 0 fs.file-max = 65535 ... kernel.sysrq = 0 4. 更新文件后,你可以重新加载设置或重新启动。重新加载请执行: sudo sysctl -p **注意**:如果 sysctl 在写入任何设置时遇到问题,`sysctl -w` 或 `sysctl -p` 会将错误写入 stderr。你可以使用此方法快速找出 `/etc/sysctl.conf` 文件中的无效设置: ``` sudo sysctl -p >/dev/null ```

([目录](#table-of-contents)) ### 为 GRUB 设置密码保护
!! 后果自负 !! #### 原因 如果恶意攻击者可以物理访问你的服务器,他们可能会利用 GRUB 获得对你系统的未经授权的访问。 #### 为什么不 如果你忘记了密码,你将不得不通过[一些操作](https://www.cyberciti.biz/tips/howto-recovering-grub-boot-loader-password.html)来恢复密码。 #### 目标 - 自动引导默认的 Debian 安装,并为其他任何操作要求输入密码 #### 注意事项 - 这只会保护 GRUB 及其背后的所有内容,如你的操作系统。请查阅主板文档以了解如何密码保护你的 BIOS,从而防止恶意攻击者绕过 GRUB。 #### 参考资料 - https://selivan.github.io/2017/12/21/grub2-password-for-all-but-default-menu-entries.html - https://help.ubuntu.com/community/Grub2/Passwords - https://computingforgeeks.com/how-to-protect-grub-with-password-on-debian-ubuntu-and-kali-linux/ - `man grub` - `man grub-mkpasswd-pbkdf2` #### 步骤 1. 创建你的密码的 [Password-Based Key Derivation Function 2 (PBKDF2)](https://en.wikipedia.org/wiki/PBKDF2) 哈希: grub-mkpasswd-pbkdf2 -c 100000 以下输出是使用 `password` 作为密码生成的: 2. 复制 `PBKDF2 hash of your password is ` **之后**的所有内容,**从 `grub.pbkdf2.sha512...` 开始并包括它**直到末尾。你将在下一步中用到它。 3. `update-grub` 程序使用脚本来生成它将用于 GRUB 设置的配置文件。创建文件 `/etc/grub.d/01_password` 并在将 `[hash]` 替换为你从第一步复制的哈希后添加以下代码。这告诉 `update-grub` 将此用户名和密码用于 GRUB。 #!/bin/sh set -e cat << EOF set superusers="grub" password_pbkdf2 grub [hash] EOF 例如: 4. 设置文件的执行权限位,以便 `update-grub` 在更新 GRUB 的配置时包含它: sudo chmod a+x /etc/grub.d/01_password 5. 备份我们将要修改的 GRUB 配置文件 `/etc/grub.d/10_linux`,并取消其执行权限位,以便 `update-grub` 不会尝试运行它: sudo cp --archive /etc/grub.d/10_linux /etc/grub.d/10_linux-COPY-$(date +"%Y%m%d%H%M%S") sudo chmod a-x /etc/grub.d/10_linux.* 6. 要使默认的 Debian 安装不受限制(**无需**密码),同时保持其他所有内容都受限(**需要**密码),请修改 `/etc/grub.d/10_linux` 并在 `CLASS` 变量中添加 `--unrestricted`。 [适合懒人](#editing-configuration-files---for-the-lazy): sudo sed -i -r -e "/^CLASS=/ a CLASS=\"\${CLASS} --unrestricted\" # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" /etc/grub.d/10_linux 7. 使用 `update-grub` 更新 GRUB: sudo update-grub

([目录](#table-of-contents)) ### 禁用 Root 登录
!! 后果自负 !! #### 原因 如果你已经[正确配置了 sudo](#limit-who-can-use-sudo),那么 **root** 账户基本上永远不需要直接登录——无论是在终端还是远程。 #### 为什么不 **请注意,这可能会导致某些配置出现问题!** 如果你的安装使用 [`sulogin`](https://linux.die.net/man/8/sulogin)(如 Debian)在启动失败时进入 **root** 控制台,那么锁定 **root** 账户将阻止 `sulogin` 打开 **root** shell,你将收到此错误: ``` Cannot open access to console, the root account is locked. See sulogin(8) man page for more details. Press Enter to continue. ``` 要解决此问题,你可以为 `sulogin` 使用 `--force` 选项。某些发行版已经包含此或其他替代方法。 锁定 **root** 账户的替代方法是设置一个长/复杂的 **root** 密码,并将其存储在安全的非数字格式中。这样在你需要时就可以使用它。 #### 目标 - 锁定的 **root** 账户,任何人都不能用它以 **root** 身份登录 #### 注意事项 - 某些发行版默认禁用 **root** 登录(例如 Ubuntu),因此你可能不需要执行此步骤。请查看你的发行版文档。 #### 参考资料 - https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=806852 - https://github.com/systemd/systemd/issues/7115 - https://github.com/karelzak/util-linux/commit/7ff1162e67164cb4ece19dd809c26272461aa254 - https://github.com/systemd/systemd/issues/11596 - https://www.reddit.com/r/selfhosted/comments/aoxd4l/new_guide_created_by_me_how_to_secure_a_linux/eg4rkfi/ - `man systemd` #### 步骤 1. 锁定 **root** 账户: sudo passwd -l root

([目录](#table-of-contents)) ### 更改默认 umask
!! 后果自负 !! #### 原因 umask 控制文件/文件夹创建时的**默认**权限。不安全的文件/文件夹权限会授予其他账户对你数据的潜在未经授权访问权限。这可能包括进行配置更改的能力。 - 对于**非 root** 账户,其他账户**默认**不需要对该账户的文件/文件夹有任何访问权限。 - 对于 **root** 账户,文件/文件夹所属主组或其他账户**默认**不需要对 **root** 的文件/文件夹有任何访问权限。 当其他账户需要访问文件/文件夹时,你希望通过结合文件/文件夹权限和所属主组来明确授予它。 #### 为什么不 更改默认 umask 可能会产生意想不到的问题。例如,如果你将 **root** 的 umask 设置为 `0077`,那么**非 root** 账户将**无法**访问 `/etc/` 中的应用程序配置文件/文件夹,这可能会破坏不以 **root** 权限运行的应用程序。 #### 工作原理 为了解释 umask 的工作原理,我必须解释 Linux 文件/文件夹权限是如何工作的。由于这是一个相当复杂的问题,我将请你参考下面的参考资料以进行进一步阅读。 #### 目标 - 将**非 root** 账户的默认 umask 设置为 **0027** - 将 **root** 账户的默认 umask 设置为 **0077** #### 注意事项 - umask 是一个 Bash 内置命令,这意味着用户可以更改自己的 umask 设置。 #### 参考资料 - https://www.linuxnix.com/umask-define-linuxunix/ - https://serverfault.com/questions/818783/which-umask-is-more-secure-in-linux-022-or-027 - https://www.cyberciti.biz/tips/understanding-linux-unix-umask-value-usage.html - `man umask` #### 步骤 1. 备份我们将要编辑的文件: sudo cp --archive /etc/profile /etc/profile-COPY-$(date +"%Y%m%d%H%M%S") sudo cp --archive /etc/bash.bashrc /etc/bash.bashrc-COPY-$(date +"%Y%m%d%H%M%S") sudo cp --archive /etc/login.defs /etc/login.defs-COPY-$(date +"%Y%m%d%H%M%S") sudo cp --archive /root/.bashrc /root/.bashrc-COPY-$(date +"%Y%m%d%H%M%S") 2. 通过将以下行添加到 `/etc/profile` 和 `/etc/bash.bashrc` 中,将**非 root** 账户的默认 umask 设置为 **0027**: umask 0027 [适合懒人](#editing-configuration-files---for-the-lazy): echo -e "\numask 0027 # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/profile /etc/bash.bashrc 3. 我们还需要将此行添加到 `/etc/login.defs` 中: UMASK 0027 [适合懒人](#editing-configuration-files---for-the-lazy): echo -e "\nUMASK 0027 # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/login.defs 4. 通过将以下行添加到 `/root/.bashrc` 中,将 **root** 账户的默认 umask 设置为 **0077**: umask 0077 [适合懒人](#editing-configuration-files---for-the-lazy): echo -e "\numask 0077 # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /root/.bashrc

([目录](#table-of-contents)) ### 孤立的软件
!! 后果自负 !! #### 原因 随着你使用系统,以及你安装和卸载软件,你最终会得到孤立的或未使用的软件/包/库。你不必移除它们,但如果你不需要它们,为什么要保留呢?当安全性是首要任务时,任何不明确需要的东西都是潜在的安全威胁。你希望保持服务器尽可能精简和干净。 #### 注意事项 - 每个发行版管理软件/包/库的方式都不同,因此你如何查找和移除孤立包的方法也会有所不同。目前我只有基于 Debian 系统的步骤。 #### 基于 Debian 的系统 在基于 Debian 的系统上,你可以使用 [deborphan](http://freshmeat.sourceforge.net/projects/deborphan/) 来查找孤立的包。 ##### 为什么不 请记住,deborphan 查找的是**没有软件包依赖项**的包。这并不意味着它们没有被使用。你完全可能每天都在使用一个没有依赖项的包,而你肯定不希望将其移除。而且,如果 deborphan 找错了任何东西,那么移除关键包可能会破坏你的系统。 ##### 步骤 1. 安装 deborphan。 sudo apt install deborphan 2. 以 **root** 身份运行 deborphan 以查看孤立包列表: sudo deborphan 3. [假设你想要移除 deborphan 找到的所有包](#orphaned-software-why-not),你可以将其输出传递给 `apt` 来移除它们: sudo apt --autoremove purge $(deborphan)

([目录](#table-of-contents)) ## 其他设置 ### 使用 MSMTP 的简单方法 (#msmtp-alternative) #### 原因 嗯,我将简化这个方法,仅使用 Google Mail 账户(和其他账户)发送电子邮件。真正的简单! :) ``` bash #!/bin/bash ###### 请....进行编辑... USEREMAIL="usernameemail" DOMPROV="gmail.com" PWDEMAIL="passwordStrong" ## ATTENTION DONT USE Special Chars.. like as SPACE # and some others not all. Feel free to test ;) MAILPROV="smtp.google.com:583" MYMAIL="$USRMAIL@$DOMPROV" USERLOC="root" ####### apt install -y msmtp ln -s /usr/bin/msmtp /usr/sbin/sendmail #wget http://www.cacert.org/revoke.crl -O /etc/ssl/certs/revoke.crl #chmod 644 /etc/ssl/certs/revoke.crl touch /root/.msmtprc cat < .msmtprc defaults account gmail host $MAILPROV port $MAILPORT #proxy_host 127.0.0.1 #proxy_port 9001 from $MYEMAIL timeout off protocol smtp #auto_from [(on|off)] #from envelope_from #maildomain [domain] auth on user $USRMAIL passwordeval "gpg -q --for-your-eyes-only --no-tty -d /root/msmtp-mail.gpg" #passwordeval "gpg --quiet --for-your-eyes-only --no-tty --decrypt /root/msmtp-mail.gpg" tls on tls_starttls on tls_trust_file /etc/ssl/certs/ca-certificates.crt #tls_crl_file /etc/ssl/certs/revoke.crl #tls_fingerprint [fingerprint] #tls_key_file [file] #tls_cert_file [file] tls_certcheck on #tls_priorities [priorities] #dsn_notify (off|condition) #dsn_return (off|amount) #domain argument #keepbcc off logfile /var/log/mail.log syslog on account default : gmail EOF chmod 0400 /root/.msmtprc ## In testing .. auto command # echo -e "1\n4096\n\ny\n$MYUSRMAIL\n$MYEMAIL\nmy key\nO\n$PWDMAIL\n$PWDMAIL\n" | gpg --full-generate-key ## gpg --full-generate-key gpg --output revoke.asc --gen-revoke $MYEMAIL echo -e "$PWDEMAIL\n" | gpg -e -o /root/msmtp-mail.gpg --recipient $MYEMAIL echo "export GPG_TTY=\$(tty)" >> .baschrc chmod 400 msmtp-mail.gpg echo "Hello there" | msmtp --debug $MYEMAIL echo"###################### ## MSMTP 已配置 ## ######################" ``` 搞定!! ;) ([目录](#table-of-contents)) ### Gmail 和 Exim4 使用隐式 TLS 作为 MTA #### 原因 除非你计划设置自己的邮件服务器,否则你需要一种从服务器发送电子邮件的方法。这对于系统警报/消息非常重要。 你可以使用任何 Gmail 账户。我建议你为此服务器专门创建一个。这样一来,如果你的服务器**被**攻破,恶意攻击者也不会获得你主账户的任何密码。诚然,如果你启用了 2FA/MFA 并使用了应用专用密码,仅凭应用专用密码恶意攻击者做不了什么,但为什么要冒险呢? 网上有许多指南介绍了如何使用 STARTTLS 将 Gmail 配置为 MTA,包括[本指南的先前版本](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/tree/cc5edcae1cf846dd250e76b121e721d836481d2f#configure-gmail-as-mta)。使用 STARTTLS 时,首先会建立一个**未加密的**连接,然后将其升级为加密的 TLS 或 SSL 连接。相反,通过下面概述的方法,加密的 TLS 连接是从一开始就建立的。 此外,正如在 [issue #29](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/29) 和[这里](https://blog.dhampir.no/content/exim4-line-length-in-debian-stretch-mail-delivery-failed-returning-message-to-sender)所讨论的,exim4 在处理长行消息时会失败。我们也将在这个部分修复这个问题。 ** **重要提示** ** 如 [#106](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/106) 中所述,Google 不再允许你使用账户密码进行身份验证。你必须启用 2FA,然后使用应用专用密码。 #### 目标 - `mail` 配置为使用 [Gmail](https://mail.google.com/) 从你的服务器发送电子邮件 - exim4 支持长行 #### 参考资料 - 感谢 [remyabel](https://github.com/remyabel) 想出了如何使其与 TLS 协同工作的方法,正如 [issue #24](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/24) 和 [pull request #26](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/pull/26) 中所记录的那样。 - https://wiki.debian.org/Exim - https://wiki.debian.org/GmailAndExim4 - https://www.exim.org/exim-html-current/doc/html/spec_html/ch-encrypted_smtp_connections_using_tlsssl.html - https://php.quicoto.com/setup-exim4-to-use-gmail-in-ubuntu/ - https://www.fastmail.com/help/technical/ssltlsstarttls.html - exim4 因长行消息而失败 - [issue #29](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/29) 和 https://blog.dhampir.no/content/exim4-line-length-in-debian-stretch-mail-delivery-failed-returning-message-to-sender - https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/106 #### 步骤 1. 安装 exim4。你还需要 openssl 和 ca-certificates。 在基于 Debian 的系统上: sudo apt install exim4 openssl ca-certificates 2. 配置 exim4: 对于基于 Debian 的系统: sudo dpkg-reconfigure exim4-config 你将会被问到一些问题: |提示|回答| |--:|--| |General type of mail configuration|`mail sent by smarthost; no local mail`| |System mail name|`localhost`| |IP-addresses to listen on for incoming SMTP connections|`127.0.0.1; ::1`| |Other destinations for which mail is accepted|(默认)| |Visible domain name for local users|`localhost`| |IP address or host name of the outgoing smarthost|`smtp.gmail.com::465`| |Keep number of DNS-queries minimal (Dial-on-Demand)?|`No`| |Split configuration into small files?|`No`| 3. 备份 `/etc/exim4/passwd.client`: sudo cp --archive /etc/exim4/passwd.client /etc/exim4/passwd.client-COPY-$(date +"%Y%m%d%H%M%S") 4. 在 `/etc/exim4/passwd.client` 中添加类似这样的行 smtp.gmail.com:yourAccount@gmail.com:yourPassword *.google.com:yourAccount@gmail.com:yourPassword **注意**: - 将 `yourAccount@gmail.com` 和 `yourPassword` 替换为你的详细信息。如果你在 Gmail 上启用了 2FA/MFA,那么你需要在此处创建并使用应用专用密码。 - 始终检查 `host smtp.gmail.com` 以获取要列出的最新域名。 5. 此文件包含你的 Gmail 密码,因此我们需要锁定其权限: sudo chown root:Debian-exim /etc/exim4/passwd.client sudo chmod 640 /etc/exim4/passwd.client 6. 下一步是创建一个 TLS 证书,供 exim4 用于建立到 `smtp.gmail.com` 的加密连接。你可以使用自己的证书,比如来自 [Let's Encrypt](https://letsencrypt.org/) 的证书,或者使用 openssl 自己创建一个。我们将使用 exim4 附带的一个调用 openssl 的脚本来生成我们的证书: sudo bash /usr/share/doc/exim4-base/examples/exim-gencert 7. 通过创建文件 `/etc/exim4/exim4.conf.localmacros` 并添加以下内容,指示 exim4 使用 TLS 和端口 465,并[修复 exim4 的长行问题](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/29): MAIN_TLS_ENABLE = 1 REMOTE_SMTP_SMARTHOST_HOSTS_REQUIRE_TLS = * TLS_ON_CONNECT_PORTS = 465 REQUIRE_PROTOCOL = smtps IGNORE_SMTP_LINE_LENGTH_LIMIT = true [适合懒人](#editing-configuration-files---for-the-lazy): cat << EOF | sudo tee /etc/exim4/exim4.conf.localmacros MAIN_TLS_ENABLE = 1 REMOTE_SMTP_SMARTHOST_HOSTS_REQUIRE_TLS = * TLS_ON_CONNECT_PORTS = 465 REQUIRE_PROTOCOL = smtps IGNORE_SMTP_LINE_LENGTH_LIMIT = true EOF 8. 备份 exim4 的配置文件 `/etc/exim4/exim4.conf.template`: sudo cp --archive /etc/exim4/exim4.conf.template /etc/exim4/exim4.conf.template-COPY-$(date +"%Y%m%d%H%M%S") 9. 在 `.ifdef REMOTE_SMTP_SMARTHOST_HOSTS_REQUIRE_TLS ... .endif` 块之后,将以下内容添加到 `/etc/exim4/exim4.conf.template` 中: .ifdef REQUIRE_PROTOCOL protocol = REQUIRE_PROTOCOL .endif [适合懒人](#editing-configuration-files---for-the-lazy): sudo sed -i -r -e '/^.ifdef REMOTE_SMTP_SMARTHOST_HOSTS_REQUIRE_TLS$/I { :a; n; /^.endif$/!ba; a\# added by '"$(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")"'\n.ifdef REQUIRE_PROTOCOL\n protocol = REQUIRE_PROTOCOL\n.endif\n# end add' -e '}' /etc/exim4/exim4.conf.template 10. 将以下内容添加到 `/etc/exim4/exim4.conf.template` 中的 `.ifdef MAIN_TLS_ENABLE` 块内: .ifdef TLS_ON_CONNECT_PORTS tls_on_connect_ports = TLS_ON_CONNECT_PORTS .endif [适合懒人](#editing-configuration-files---for-the-lazy): sudo sed -i -r -e "/\.ifdef MAIN_TLS_ENABLE/ a # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")\n.ifdef TLS_ON_CONNECT_PORTS\n tls_on_connect_ports = TLS_ON_CONNECT_PORTS\n.endif\n# end add" /etc/exim4/exim4.conf.template 11. 更新 exim4 配置以使用 TLS,然后重启服务: sudo update-exim4.conf sudo service exim4 restart 12. 如果你正在使用 [UFW](#ufw-uncomplicated-firewall),你需要允许端口 465 上的出站流量。为此,我们将创建一个自定义的 UFW 应用程序配置文件,然后启用它。创建文件 `/etc/ufw/applications.d/smtptls`,添加以下内容,然后运行 `ufw allow out smtptls comment 'open TLS port 465 for use with SMPT to send e-mails'`: [SMTPTLS] title=SMTP through TLS description=This opens up the TLS port 465 for use with SMPT to send e-mails. ports=465/tcp [适合懒人](#editing-configuration-files---for-the-lazy): cat << EOF | sudo tee /etc/ufw/applications.d/smtptls [SMTPTLS] title=SMTP through TLS description=This opens up the TLS port 465 for use with SMPT to send e-mails. ports=465/tcp EOF sudo ufw allow out smtptls comment 'open TLS port 465 for use with SMPT to send e-mails' 13. 添加一些邮件别名,以便我们可以通过在 `/etc/aliases` 中添加类似这样的行来向本地账户发送电子邮件: user1: user1@gmail.com user2: user2@gmail.com ... 你需要添加你的服务器上存在的所有本地账户。 14. 测试你的设置: echo "test" | mail -s "Test" email@gmail.com sudo tail /var/log/exim4/mainlog ([目录](#table-of-contents)) ### 独立的 iptables 日志文件 #### 原因 总有一天你需要查看你的 iptables 日志。将所有 iptables 日志存放到它们自己的文件中,会让你更容易找到你要找的内容。 #### 参考资料 - https://blog.shadypixel.com/log-iptables-messages-to-a-separate-file-with-rsyslog/ - https://gist.github.com/netson/c45b2dc4e835761fbccc - https://www.rsyslog.com/doc/v8-stable/configuration/actions.html #### 步骤 1. 第一步是告诉你的防火墙为所有日志条目添加某个唯一字符串作为前缀。如果你直接使用 iptables,你会为所有规则执行类似 `--log-prefix "[IPTABLES] "` 的操作。我们在[安装 psad 的第 4 步](#psad_step4)中已经处理了这个问题。 2. 在你为防火墙日志添加前缀之后,我们需要告诉 rsyslog 将这些行发送到它自己的文件中。通过创建文件 `/etc/rsyslog.d/10-iptables.conf` 并添加以下内容来完成此操作: :msg, contains, "[IPTABLES] " /var/log/iptables.log & stop 如果你预期防火墙会记录大量数据,请在文件名前加上一个 `-` ["以便在每次记录后省略同步"](https://www.rsyslog.com/doc/v8-stable/configuration/actions.html#regular-file)。例如: :msg, contains, "[IPTABLES] " -/var/log/iptables.log & stop **注意**:请记住将前缀更改为你使用的内容。 [适合懒人](#editing-configuration-files---for-the-lazy): cat << EOF | sudo tee /etc/rsyslog.d/10-iptables.conf :msg, contains, "[IPTABLES] " /var/log/iptables.log & stop EOF 3. 既然我们将防火墙消息记录到了不同的文件中,我们需要告诉 psad 新文件的位置。编辑 `/etc/psad/psad.conf` 并将 `IPT_SYSLOG_FILE` 设置为日志文件的路径。例如: IPT_SYSLOG_FILE /var/log/iptables.log; **注意**:请记住将前缀更改为你使用的内容。 [适合懒人](#editing-configuration-files---for-the-lazy): sudo sed -i -r -e "s/^(IPT_SYSLOG_FILE\s+)([^;]+)(;)$/# \1\2\3 # commented by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")\n\1\/var\/log\/iptables.log\3 # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/" /etc/psad/psad.conf 4. 重启 psad 和 rsyslog 以激活更改(或重新启动): sudo psad -R sudo psad --sig-update sudo psad -H sudo service rsyslog restart 5. 我们要做的最后一件事是告诉 logrotate 轮换新日志文件,以免它变得过大并填满我们的磁盘。创建文件 `/etc/logrotate.d/iptables`添加以下内容: /var/log/iptables.log { rotate 7 daily missingok notifempty delaycompress compress postrotate invoke-rc.d rsyslog rotate > /dev/null endscript } [适合懒人](#editing-configuration-files---for-the-lazy): cat << EOF | sudo tee /etc/logrotate.d/iptables /var/log/iptables.log { rotate 7 daily missingok notifempty delaycompress compress postrotate invoke-rc.d rsyslog rotate > /dev/null endscript } EOF ([目录](#table-of-contents)) ## 杂项 ### 联系我 如有任何问题、评论、担忧、反馈或疑虑,请提交一个[新问题](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/new)。 ([目录](#table-of-contents)) ### 有用的链接 - [https://github.com/pratiktri/server_init_harden](https://github.com/pratiktri/server_init_harden) - 一个 Bash 脚本,可自动执行你在新的 Linux 服务器上需要执行的一些任务,以为其提供基本的安全防护。 ([目录](#table-of-contents)) ### 致谢 - https://www.reddit.com/r/linuxquestions/comments/aopzl7/new_guide_created_by_me_how_to_secure_a_linux/ - https://www.reddit.com/r/selfhosted/comments/aoxd4l/new_guide_created_by_me_how_to_secure_a_linux/ - https://news.ycombinator.com/item?id=19177435#19178618 - https://www.reddit.com/r/linuxadmin/comments/arx7xo/howtosecurealinuxserver_an_evolving_howto_guide/ - https://www.reddit.com/r/linux/comments/arx7st/howtosecurealinuxserver_an_evolving_howto_guide/ - https://github.com/moltenbit/How-To-Secure-A-Linux-Server-With-Ansible ([目录](#table-of-contents)) ### 许可证和版权 [![CC-BY-SA](https://i.creativecommons.org/l/by-sa/4.0/88x31.png)](http://creativecommons.org/licenses/by-sa/4.0/) [如何保护 Linux 服务器](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server) 由 [Anchal Nigam](https://github.com/imthenachoman) 提供,采用 [知识共享署名-相同方式共享 4.0 国际许可协议](http://creativecommons.org/licenses/by-sa/4.0) 进行授权。 有关完整的许可证,请参阅 [LICENSE](LICENSE.txt)。 ([目录](#table-of-contents))
标签:2FA, Ansible, DNS解析, Firejail, Linux加固, MFA, NTP, osquery, SSH, sudo, Web归档检索, 双因素认证, 子域名变形, 子域名枚举, 安全基线, 安全指南, 开源项目, 教学环境, 教程, 沙箱, 漏洞防护, 系统安全, 系统提示词, 网络安全, 运维安全, 隐私保护