iprepd-nginx
iprepd OpenResty 模块
$ opm get moz-hwine/iprepd-nginx
iprepd-nginx 模块
iprepd-nginx
是一个用于与 iprepd 集成的 OpenResty 模块。
您可以使用此仓库中的示例配置来进行独立代理,或使用 opm 进行安装并自行集成。
注意:如果 Nginx 位于负载均衡器之后,请确保使用类似 ngx_http_realip_module 的模块。
iprepd-nginx 到底做了什么?
通过在 iprepd-nginx
中使用 iprepd
客户端,您可以配置 Nginx 在 iprepd
中检查传入客户端 IP 的信誉。根据此信誉,iprepd-nginx
将在转发到应用程序的请求上附加最多三个 HTTP 头,并且可以拒绝信誉低于配置阈值的请求。
这三个 HTTP 头是
| 头部 | 值 | 描述 | |---|---|---| | X-Foxsec-IP-Reputation | 整数 (0-100) | iprepd 返回的信誉分数 | | X-Foxsec-IP-Reputation-Below-Threshold | 布尔值 ('true'/'false') | 信誉是否低于配置的阈值 | | X-Foxsec-Block | 布尔值 ('true'/'false') | 请求是否应被阻止的高级指示(此指示的含义可能会发生变化) |
此外,iprepd-nginx
旨在故障开放,并优先考虑性能而非准确性。作为操作员,可以稍微更改性能优先于准确性的偏好,但只能在一定程度上进行更改(将在下面进一步讨论)。
(Mozilla 特定)架构图
!架构图
安装
使用 opm 进行安装
opm get mozilla-services/iprepd-nginx
操作指南
先决条件
iprepd,最好靠近您的
iprepd-nginx
服务器(例如,在 AWS 或 GCP 的同一区域内)一种更新 iprepd 的机制。在 Mozilla,这是通过将来自负载均衡器、应用程序服务器和可能的其他位置的日志馈送到我们的 欺诈检测管道 来完成的。
(可选)一种收集 statsd 指标的机制。
关于性能的说明
iprepd-nginx 的核心要求是,它不会在请求中增加超过 10 毫秒的延迟。为了实现这一点,作为操作员,您应该了解一些机制
大量使用来自 iprepd 的响应缓存
默认情况下,iprepd-nginx 将缓存来自 iprepd 的所有非错误响应 30 秒。在生产环境中缓存错误是一个好主意,这可以通过启用 cache_errors
来完成(将在下面进一步讨论)。此外,您可能希望延长缓存 TTL。
对 iprepd 的严格超时
默认情况下,iprepd-nginx 对 iprepd 的请求将在 10 毫秒后超时。在生产环境中不应增加此值,如果网络设计可以支持,则可能值得减少。
客户端配置
threshold
参数
客户端中的 threshold
值是在 0 到 100 之间的数值,如果客户端 IP 在 iprepd 中的信誉低于此值,则将阻止这些客户端。
您希望将此值设置为多少将高度依赖于您的应用程序和环境,并考虑存在哪些类型的违规行为、客户端激活这些违规行为的可能性、客户端重试的频率等。
一个不错的起始值为 50
,但您需要确保在您的环境中针对已实施的 iprepd 违规行为对其进行测试。
审计参数
客户端中的 audit
值允许配置将被阻止的请求记录到日志中,以用于安全审计目的。审计消息包括请求正文(如果足够小,可以在内存中缓冲),或者如果必须写入磁盘,则包含正文文件的名称。这取决于 nginx 设置 client_body_buffer_size
。
audit_blocked_requests
启用审计,默认情况下它被禁用。
audit_include_headers
在审计消息中包含请求头部。默认情况下,它被禁用。启用后,将删除 Authorization 和 Proxy-Authorization 头部值。
audit_uri_list
是一个应进行审计的 URI 表。启用审计时,此表是必需的。URI 可以是简单的字符串或 Lua 模式。例如,audit_uri_list = {"test", "/test/%d/somethingelse"}
将允许记录对 /test/1/somethingelse
以及 /test
的请求。
示例
-- Parameters within options:
-- Required parameters:
-- api_key - An active API key for authenticating to iprepd
-- threshold - The reputation threshold, where IP's with a reputation below this number will
-- be blocked. There is no default for this, as it will be application specific,
-- but as described above 50 is a good starting place.
--
-- Optional parameters:
-- url - The base URL to iprepd (defaults to "http://localhost:8080/")
-- timeout - The timeout for making requests to iprepd in milliseconds (defaults to 10)
-- cache_ttl - The iprepd response cache ttl in seconds (defaults to 60)
-- cache_buffer_count - Max number of entries allowed in the cache. (defaults to 5000)
-- cache_errors - Enables (1) or disables (0) caching errors. Caching errors is a good
-- idea in production, as it can reduce the average additional latency
-- caused by this module if anything goes wrong with the underlying
-- infrastructure. (defaults to disabled)
-- cache_errors_ttl - The iprepd response cache ttl for error responses (not 200 or 404) in seconds (defaults to 10)
-- statsd_host - Host of statsd collector. Setting this will enable statsd metrics collection
-- statsd_port - Port of statsd collector. (defaults to 8125)
-- statsd_max_buffer_count - Max number of metrics in buffer before metrics should be submitted
-- to statsd (defaults to 100)
-- statsd_flush_timer - Interval for attempting to flush the stats in seconds. (defaults to 5)
-- blocking_mode - Enables (1) or disables (0) blocking within nginx by returning a
-- 403. (defaults to disabled)
-- verbose - Enables (1) or disables (0) verbose logging. Messages are logged with a
-- severity of "ERROR" so that nginx log levels do not need to be changed. (defaults
-- to disabled)
-- whitelist - List of whitelisted IP's and IP CIDR's. (defaults to empty)
-- audit_blocked_requests - records the body and optionally headers of requests that are being blocked within nginx (defaults disabled, if enabled the uris to audit must be given)
-- audit_include_headers - if audit_blocked_requests is enabled, also record the headers (defaults disabled)
-- audit_uri_list - a list of endpoints that will be audited if audit_blocked_requests is enabled (defaults to empty)
--
client = require("resty.iprepd").new({
api_key = os.getenv("IPREPD_API_KEY"),
threshold = 50,
url = "http://127.0.0.1:8080",
timeout = 10,
cache_ttl = 30,
cache_buffer_count = 1000,
cache_errors = 1,
cache_errors_ttl = 10,
statsd_host = "127.0.0.1",
statsd_port = 8125,
statsd_max_buffer_count = 100,
statsd_flush_timer = 10,
blocking_mode = 0,
verbose = 0,
whitelist = {"127.0.0.1", "10.10.10.0/24", "192.168.0.0/16"},
audit_blocked_requests = 0,
audit_include_headers = 0,
audit_uri_list = {}
})
指标 (statsd)
收集的指标
| 名称 | 类型 | 描述 | |---|---|---| | iprepd.status.below_threshold | 计数 | 客户端 IP 的信誉低于配置的阈值。 | | iprepd.status.rejected | 计数 | 请求被阻止(如果 blocking_mode
被禁用,则不会发送)。 | | iprepd.status.accepted | 计数 | 请求被接受。如果 blocking_mode
被禁用,信誉仍然可能低于阈值。 | iprepd.get_reputation | 计数 | 对 iprepd 的请求 | | iprepd.cache_hit | 计数 | 从内部缓存获取信誉 | | iprepd.err.timeout | 计数 | 对 iprepd 的请求超时 | | iprepd.err.500 | 计数 | 从 iprepd 获取 500 响应 | | iprepd.err.401 | 计数 | 从 iprepd 获取 401 响应,通常表示正在使用的 API 密钥无效或 Nginx 发送错误。 | | iprepd.err.dns_timeout | 计数 | iprepd URL 的域名解析超时。请务必检查 nginx 的 resolver_timeout 设置 | | iprepd.err.* | 计数 | 在向 iprepd 发送请求时出现错误。例如,这可能是其他 4xx 或 5xx 状态代码。 |
设置自定义指标
您可以使用 client.statsd
(其中 client = require("resty.iprepd").new({...})
)来提交您自己的自定义指标。请注意,没有前缀,因此它将像任何其他 statsd 客户端一样工作。
可用的 statsd 函数
client = require("resty.iprepd").new({...})
client.statsd.count(name, value)
client.statsd.incr(name) # Increments a count by 1
client.statsd.time(name, value)
client.statsd.set(name, value)
Nginx 配置中的示例
init_by_lua_block {
client = require("resty.iprepd").new({
url = os.getenv("IPREPD_URL"),
api_key = os.getenv("IPREPD_API_KEY"),
statsd_host = os.getenv("STATSD_HOST"),
})
}
init_worker_by_lua_block {
# async flushing of metrics
client:config_flush_timer()
}
server {
...
location / {
...
access_by_lua_block {
client:check(ngx.var.remote_addr)
}
log_by_lua_block {
# This conditional is not required, but can be helpful to not cause problems
# if you want to temporarily disable statsd. This will evaluate to false if
# `statsd_host` is not set.
if client.statsd then
# Here is our custom metric
client.statsd.set("iprepd.ips_seen", ngx.var.remote_addr)
end
}
}
}
常见问题
确保 iprepd-nginx 能够看到真实的客户端 IP。您通常需要使用类似 ngx_http_realip_module 的模块,并确认它已正确配置。
在本地运行
在此仓库中创建一个 .env
文件,其中包含所需的环境变量(文档如下)。
然后运行
$ make build
$ make run_dev
然后您将能够使用以下命令访问此代理:curl http://localhost:80
开发环境变量
注意
env 变量中的引号在 nginx 中很重要。如果您在 Docker 中使用 --env-file
,请不要使用它们。
# required
backend=http://<> # URL to proxy to
IPREPD_URL=http://<> # iprepd url
IPREPD_API_KEY="api-key" # iprepd api key
IPREPD_REPUTATION_THRESHOLD=50 # iprepd reputation threshold, block all IP's with a reputation below the threshold
#
# optional
#
IPREPD_TIMEOUT=10
IPREPD_CACHE_TTL=30
IPREPD_CACHE_ERRORS=0
STATSD_HOST=127.0.0.1
STATSD_PORT=8125
STATSD_MAX_BUFFER_COUNT=200
STATSD_FLUSH_TIMER=2
BLOCKING_MODE=0
AUDIT_BLOCKED_REQUESTS=0
AUDIT_INCLUDE_HEADERS=0
作者
AJ Bahnken (ajvb), Katie Kleemola (kkleemola)
许可证
mozilla2
依赖项
版本
-
iprepd OpenResty 模块 2019-12-13 17:56:04
-
iprepd OpenResty 模块 2019-12-03 21:32:45
-
moz-hwine/iprepd-nginx 0.1.10iprepd OpenResty 模块 2019-12-03 21:08:31
-
iprepd OpenResty 模块 2019-03-13 23:18:12
-
iprepd OpenResty 模块 2019-02-08 21:19:54
-
iprepd OpenResty 模块 2019-01-17 18:32:51
-
iprepd OpenResty 模块 2018-12-17 18:05:19
-
iprepd OpenResty 模块 2018-12-13 19:38:46
-
iprepd OpenResty 模块 2018-12-05 20:00:19
-
iprepd OpenResty 模块 2018-11-08 19:12:40
-
iprepd OpenResty 模块 2018-11-05 17:09:00
-
iprepd OpenResty 模块 2018-11-02 19:39:22
-
iprepd OpenResty 模块 2018-10-29 20:39:45