☰
Ajenti 安全加固实战:基于 Fail2ban 的暴力破解防护配置指南
2026/9/27 7:43:49 网站建设 项目流程
  • 后端
  • 运维

【免费下载链接】ajenti

Ajenti Core and stock plugins

项目地址:https://gitcode.com/gh_mirrors/aj/ajenti
点击查看免费下载

Ajenti 是一个基于 Python 的轻量级 Web 管理平台,包含 Ajenti Core(平台本身,含 HTTP 服务器、事件循环与插件容器)与 Ajenti Panel(启动脚本及文件管理器、网络配置、服务管理等内置插件)。本文以官方文档 docs/source/man/security.rst 为主体,深入讲解 Ajenti 的日志记录机制、Fail2ban 过滤器原理,以及完整的防暴力破解配置方案;读完你可以独立为 Ajenti 接入 Fail2ban,并根据自己的部署环境调优封禁策略。

一、为什么需要为 Ajenti 配置 Fail2ban

Ajenti 提供完整的 Web 管理界面,其登录入口/api/core/auth天然暴露在网络上,成为暴力破解攻击的目标。虽然 Ajenti 自身在登录失败时会强制睡眠(gevent.sleep(3),见 plugins/core/views/api.py)以拖慢攻击节奏,但仅靠应用层限速并不能阻止分布式或持续的暴力尝试。

Fail2ban 是业界标准的入侵防御工具:它扫描服务日志,匹配失败尝试的正则规则,对超阈值来源 IP 在防火墙层面进行临时封禁。Ajenti 官方在文档中明确推荐这一方案,并在仓库内提供了配套的过滤器配置 scripts/ajenti.conf。

依据:docs/source/man/security.rst 明确说明 "Failed login attempts are logged in/var/log/ajenti/ajenti.log",并给出了完整的 Fail2ban 接入示例;同时 docs/source/index.rst 的 Feature Overview 也将 "Fail2ban rule" 列为 Ajenti 的安全特性之一。

二、Ajenti 登录失败日志的产生与格式

2.1 日志写入位置

Ajenti 的日志目录与文件名硬编码在核心模块 ajenti-core/aj/log.py 中:

LOG_DIR = '/var/log/ajenti' LOG_NAME = 'ajenti.log' LOG_FILE = os.path.join(LOG_DIR, LOG_NAME)

即失败登录记录写入/var/log/ajenti/ajenti.log。该文件使用TimedRotatingFileHandler按日轮转(when='midnight',保留backupCount=7份),也就是说 Fail2ban 的logpath指向的是每日轮转的活跃日志文件。

2.2 失败登录日志的生成代码

登录接口位于 plugins/core/views/api.py,认证失败时会执行以下逻辑(L170-L183):

# Log failed login for e.g. fail2ban remote_addr = http_context.env.get('REMOTE_ADDR', None) if len(aj.config.data['trusted_proxies']) > 0: if remote_addr in aj.config.data['trusted_proxies']: ip = http_context.env.get('HTTP_X_FORWARDED_FOR', '').split(',')[0] else: ip = remote_addr logging.warning(f"Failed login from {username} at IP : {ip}") gevent.sleep(3)

这段代码揭示了一个关键事实:Ajenti 是主动为 Fail2ban 设计日志格式的(注释 "Log failed login for e.g. fail2ban"),并且会优先从HTTP_X_FORWARDED_FOR中提取客户端真实 IP——前提是你已在 ajenti-panel/config.yml 中配置了trusted_proxies(该参数在 docs/source/man/config.rst 中有说明)。若你的 Ajenti 部署在 Nginx 等反向代理之后,务必配置trusted_proxies,否则 Fail2ban 封禁到的将是代理 IP 而非真实攻击者 IP。

2.3 实际日志行示例

按照 ajenti-core/aj/log.py 的文件日志格式'%(asctime)s %(levelname)-8s: %(message)s',一条失败登录记录大致长这样:

2026-09-26 01:12:33,456 WARNING : Failed login from admin at IP : 203.0.113.7

这就是下文 Fail2ban 正则failregex的匹配对象。日志行以WARNING级别写出,且与过滤器正则中的WARNING字样严格对应。

三、仓库自带的 Fail2ban 过滤器

仓库在 scripts/ajenti.conf 中提供了官方基础过滤器,完整内容如下:

# Fail2Ban basic filter for ajenti # # Author : Arnaud Kientz [Definition] failregex = ^.* WARNING : Failed login from \w+ from at IP : <HOST> ignoreregex = [Init] maxlines = 1

(注:上表为仓库内实际文件内容,其中正则\w+ from at IP与日志生成代码中的Failed login from {username} at IP : {ip}存在细微不匹配,若按原样使用可能导致匹配失败。建议在部署时将其修正为与 plugins/core/views/api.py 输出格式一致的正则:^.* WARNING : Failed login from \w+ at IP : <HOST>。)

对正则各部分的解读:

正则片段含义
^.* WARNING :匹配以任意前缀开头、包含WARNING :的日志行(对应日志轮转文件的 asctime 前缀)
Failed login from \w+匹配用户名(\w+覆盖字母、数字、下划线)
at IP : <HOST><HOST>是 Fail2ban 的占位符,自动匹配并提取 IPv4/IPv6 地址

ignoreregex留空表示不忽略任何匹配行;maxlines = 1表示每次只解析单行日志即可完成匹配(因为一条失败登录就是一行独立日志,无需跨行聚合)。

四、完整的 Fail2ban 配置步骤

4.1 安装与前置条件

  • 确认 Ajenti 正常运行,且能观察到/var/log/ajenti/ajenti.log的写入(Ajenti 的日志目录与文件会在初始化时自动创建并设置为0o640权限,见 ajenti-core/aj/log.py 的init_log_directory/init_log_file);
  • 确认 Fail2ban 已安装(Debian/Ubuntu:apt install fail2ban,RHEL:dnf install fail2ban),并已启动fail2ban服务;
  • 确保 Ajenti 进程对日志文件有写权限,同时 Fail2ban 进程对该文件有读权限。

4.2 安装过滤器

将仓库中的 scripts/ajenti.conf 复制到 Fail2ban 的过滤器目录:

sudo cp /path/to/ajenti/scripts/ajenti.conf /etc/fail2ban/filter.d/ajenti.conf

注意:复制前建议先按上一节的说明修正failregex,使其与当前版本的日志格式完全一致(即Failed login from \w+ at IP : <HOST>),否则过滤器可能永远匹配不到日志。

4.3 定义 Jail(监狱规则)

在/etc/fail2ban/jail.d/ajenti中写入以下内容(即官方文档给出的示例):

[ajenti] enabled = true port = 8000 bantime = 120 maxretry = 3 findtime = 60 logpath = /var/log/ajenti/ajenti.log filter = ajenti

各参数含义与取值说明:

参数示例值含义
enabledtrue启用该 jail
port8000封禁的端口。务必与你 Ajenti 实际监听端口一致(默认 8000,见 ajenti-panel/config.yml 的bind.port);也可写成port = http,https或省略(Fail2ban 会按协议自动推断)
bantime120封禁时长(秒)。示例中为 2 分钟
maxretry3在findtime时间窗口内允许的最大失败次数,超过即触发封禁
findtime60统计窗口(秒)。示例中表示"60 秒内"
logpath/var/log/ajenti/ajenti.log监听的日志文件路径,与 ajenti-core/aj/log.py 中定义一致
filterajenti引用上一步安装的过滤器ajenti.conf

官方文档对该示例的行为解释为:在最近 60 秒(findtime)内出现 3 次(maxretry)失败登录尝试后,来源 IP 将被封禁 2 分钟(bantime)。

4.4 使配置生效

sudo systemctl restart fail2ban # 或 sudo fail2ban-client reload

4.5 验证

# 查看 jail 状态 sudo fail2ban-client status ajenti # 查看封禁列表(应在输出中的 "Banned IP list" 出现目标 IP) sudo fail2ban-client status ajenti | grep Banned

验证思路:从另一个 IP 连续故意输错密码 3 次以上,然后观察fail2ban-client status ajenti是否出现该 IP;同时可tail -f /var/log/ajenti/ajenti.log确认产生了WARNING : Failed login from ... at IP : ...记录。

五、按生产环境调优建议

官方明确说明示例只是基础配置("This is only an example"),你可以根据实际环境调整参数。以下调优方向均围绕原文档参数展开:

  • 降低误封风险:若存在多用户共享出口 IP 的场景,maxretry = 3可能过严。可放宽到maxretry = 5,或增大findtime到600(10 分钟窗口)。
  • 延长封禁时间:将bantime从120提升到3600甚至86400(1 天),并配合 Fail2ban 的递增封禁功能(在 jail 中增加bantime.increment = true,实际封禁时长会随重复违规逐步增加)。
  • 与 Ajenti 自身限速配合:Ajenti 每次失败登录都会gevent.sleep(3)(见 plugins/core/views/api.py),因此单 IP 每秒最多约 0.33 次尝试。Fail2ban 的 60 秒窗口 3 次阈值设计已充分考虑了这一点,无需刻意调低。
  • 反向代理场景:如 2.2 节所述,通过 Nginx 等代理访问时,必须在 ajenti-panel/config.yml 中配置trusted_proxies,否则日志里记录的是代理 IP,Fail2ban 的封禁将失去意义。该参数同时也会影响密码重置邮件等功能的安全性(详见 docs/source/man/config.rst)。
  • 多实例/多端口:如果 Ajenti 监听非默认端口(修改bind.port),记得同步修改 jail 中的port参数。

六、拓展:Ajenti 的其他安全机制

Fail2ban 只是 Ajenti 安全体系的一环。从 docs/source/index.rst 的 Feature Overview 可以看到,Ajenti 还内置了以下安全能力,可与 Fail2ban 组合使用:

  • 可插拔认证:支持 OS 用户、独立用户文件、SSL 客户端证书等多种认证提供者(认证接口定义见 ajenti-core/aj/auth.py 的AuthenticationProvider接口,认证提供者由 ajenti-panel/config.yml 中auth.provider选择:os或users);
  • 非特权会话隔离:登录会话在独立进程中以受限权限运行(restricted_user: nobody参数,见 ajenti-panel/config.yml);
  • HTTPS 与客户端证书认证:ssl配置块支持强制 HTTPS 跳转(ssl.force)与客户端证书认证(ssl.client_auth),详见 docs/source/man/config.rst;
  • Sudo 提权控制:auth.allow_sudo决定是否允许 sudo 组用户提权(plugins/core/views/api.py 中的sudo认证模式)。

七、常见问题排查

  • 日志里根本没有失败记录:确认auth.provider对应认证路径确实走了 plugins/core/views/api.py 的normal模式;且日志文件可写。
  • Fail2ban 一直显示0 failures:优先检查failregex是否与日志实际内容逐字符一致(建议先用fail2ban-regex /var/log/ajenti/ajenti.log /etc/fail2ban/filter.d/ajenti.conf离线测试正则匹配)。
  • 封禁了代理 IP 而非真实客户端:如 2.2 节所述,配置trusted_proxies后再观察日志中的 IP 字段。
  • 重启后配置丢失:确认 jail 文件位于/etc/fail2ban/jail.d/且文件名不以.conf或.local结尾以外的其他后缀干扰加载,并用fail2ban-client reload生效。

结语

为 Ajenti 接入 Fail2ban 只需三步:确认日志写入 → 安装 scripts/ajenti.conf 过滤器 → 在/etc/fail2ban/jail.d/配置 jail 并 reload。通过findtime/maxretry/bantime三个参数,你可以精确控制"多久内几次失败就封禁多久",再结合 Ajenti 自身的登录限速、HTTPS 强制与客户端证书认证,即可构建一套完整的 Web 管理面板防护方案。

关键文件索引

  • 官方安全文档:docs/source/man/security.rst
  • Fail2ban 过滤器:scripts/ajenti.conf
  • 日志路径定义与轮转:ajenti-core/aj/log.py
  • 失败登录日志生成逻辑:plugins/core/views/api.py
  • 配置文件说明:docs/source/man/config.rst
  • 示例配置:ajenti-panel/config.yml
  • 后端
  • 运维

【免费下载链接】ajenti

Ajenti Core and stock plugins

项目地址:https://gitcode.com/gh_mirrors/aj/ajenti
点击查看免费下载
上一篇:从本地模型到生产级API:DeepSeek-R1-Distill-Qwen-32B的FastAPI封装实战
下一篇:5个超实用技巧:让Monaco Editor代码编辑器成为你的网页开发利器 🚀

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询