如何在 Nginx 上使用 fail2ban 和 Meteor

How to use fail2ban with Meteor on Nginx

我正在设置一个 Digital Ocean droplet 运行 Ubuntu 18.04 以通过 Phusion Passenger / Nginx 托管我的 Meteor 1.8 应用程序。我会将其配置为使用 SSL 和 Lets Encrypt。

fail2ban is a recommended tool to protect against brute force attacks, but I can't work out how to use it with Meteor, or even if it's appropriate. I've read several tutorials 但是有一些基本的东西我不明白。

我在我的 Nginx 配置文件中使用服务器位置块来默认阻止对所有 url 的访问,并且只允许必要的:

# deny all paths by default
location / { deny all; }

# allow sockjs
location /sockjs { }

# allow required paths
location = / { }
location /my-documents { }
location /login { }
location /register { }
...

# serve js and css
location ~* "^/[a-z0-9]{40}\.(css|js)$" {
  root /var/www/myapp/bundle/programs/web.browser;
  access_log off;
  expires max;
}

# serve public folder
location ~ \.(jpg|jpeg|png|gif|mp3|ico|pdf|svg) {
  root /var/www/myapp/bundle/pubilc;
  access_log off;
  expires max;
}

# deny unwanted requests
location ~ (\.php|.aspx|.asp|myadmin) {
  return 404;
}

我的基本问题是:fail2ban 会检测到登录我的 Meteor 应用程序的失败尝试吗?如果是,如何检测?如果不是,那么它的目的是什么?它是否在寻找登录服务器本身的失败尝试?我在 Droplet 上禁用了密码访问 - 你只能通过 ssh 连接到服务器。

这与网站部分的 Nginx password protection 有什么关系?再一次,这是做什么用的,我需要它吗?它如何与 Meteor 应用程序一起使用?

感谢您的帮助。

任何使用 React/Vue/Blaze 作为其呈现引擎的现代单页应用程序都不会向服务器发送 url 对 UI 中每个页面的请求。

Meteor 在初始页面加载时加载其所有资产,其余部分使用 DDP 通过套接字完成。它可能会作为单独的请求加载静态资产。

作为 Meteor 方法实现的任何服务器 API 调用也不会显示在服务器日志中。

所以 fail2ban 会检测到一些暴力攻击,因此可能有助于阻止这些攻击并防止它们淹没服务器,但它不会检测失败的登录尝试。

您可以调整应用程序以检测失败的登录,并调用 fail2ban API 来记录它们(如果可能的话)。否则我不确定它是否完全适合保护流星服务器。

我的结论是,是的,fail2ban 值得与 Meteor 一起使用。据我所知,Nginx 密码保护无关紧要,但您还可以做其他好事。

首先,我认为值得在任何服务器上使用 fail2ban 来阻止暴力攻击。我的测试服务器才上线几天,没有指向它的链接,我已经在 Nginx 日志中看到对 wp-admin 和 robots.txt 等路径的探测。这些探针什么也做不了,因为文件不存在,不过我觉得还是禁止重复调用比较安全

我从 this tutorial 开始为禁止的 url 设置监狱,修改监狱定义以指向我的实际 Nginx 日志文件。

然后,我修改了我的应用程序以记录失败的登录尝试,并编写了一个自定义监狱和过滤器来阻止这些尝试。可能没有人愿意专门编写脚本来攻击 Meteor 站点,而且我的 Meteor 应用程序对登录有限制,但我还是觉得还是多加小心为好。

以下是我修改应用程序的方式:

server/main.js

const buildServerLogText = ((text) => {
    const connection = Meteor.call('auth.getClientConnection');

    return `${moment(new Date()).format('YYYY/MM/DD HH:mm:ss')} ${text}, client: ${connection.clientAddress}, host: "${connection.httpHeaders.host}"`;
});
// log failed login attempts so fail2ban can find them in the Nginx logs
Accounts.onLoginFailure(() => {
    const text = buildServerLogText('[error]: Meteor login failure');
    console.log(text);
});

这会将失败的登录尝试以这种形式写入服务器:

2020/03/10 15:40:20 [error]: Meteor login failure, client: 86.180.254.102, host: "209.97.135.5"

日期格式很重要,fail2ban对此很挑剔

我还必须在我的 Phusion Passenger 配置文件中设置 passenger_disable_log_prefix on; 以停止将前缀添加到日志条目。当我使用 Phusion Passenger 部署我的应用程序时,Nginx 配置在 Passenger 配置文件中。

那么我的fail2ban过滤器是这样的:

/etc/fail2ban/filter.d/nginx-login-failure.conf

[Definition]
failregex = ^ \[error\]:.*Meteor login failure.*, client: <HOST>, .*$

ignoreregex =