MeterMaid 是一个服务器,可以对连接和事务进行集中测量和管理,方法包括监视 IP 地址和 SMTP 信封地址。就功能而言,MeterMaid 可用来限制某个特定 IP 地址连接到 MTA 的频率。限制特定 IP 地址的连接对于防止拒绝服务攻击中使用的过多连接很有用。MeterMaid 取代了 conn_throttle.so,它提供相似的功能,但通过 Messaging Server 安装扩展了这些功能。尚未计划对 conn_throttle.so 进行新的改进,MeterMaid 是一个更有效的替代选择。
本节包含以下几个部分:
conn_throttle.so 是作为 MTA 映射表中的调用而使用的共享库,该映射表使用内存中的一个外来连接表来确定最近连接的特定 IP 地址何时太频繁,而应暂时转移出去。虽然有一个内存中的表有助于提高性能,但它最大的开销是每个服务器上的每个单独的进程都要维护自己的表。
在大多数情况下,conn_throttle.so 调用是在 PORT_ACCESS 映射中完成的,该映射通过分发程序(每个系统上的单个进程)访问。仅有的开销是每个服务器都有一个单独的表。
MeterMaid 的主要改进是,它维护限制信息的单个系统信息库,该限制信息可以被 Messaging Server 环境下的所有系统和进程访问。它继续维护一个内存中的数据库来存储数据,以获取最佳性能。重新启动 MeterMaid 将丢失所有以前存储的信息,但由于数据的生命周期通常很短,因此这样的重新启动(不是经常发生)所带来的损失也比较小。
MeterMaid 的配置存储在 msg.conf 中,并通过 configutil 维护。
通过使用 check_metermaid.so 的映射表调用从 MTA 访问 MeterMaid。可以从任何 *_ACCESS 表中调用 MeterMaid。当从 PORT_ACCESS 表中调用时,MeterMaid 可基于连接的 IP 地址检查限制,这是实现 MeterMaid(替代原来的 conn_throttle.so)的最常用方法。如果从别的 *_ACCESS 表中调用,MeterMaid 也可用于对其他数据(如信封 From 或信封 To 地址,以及 IP 地址)建立限制。
在 check_metermaid.so 中只定义一个入口点。throttle 例程联系提供两个以逗号分隔的后续参数的 MeterMaid。第一个参数是用于检查数据的表的名称,第二个参数是要检查的数据。
如果探测得到的结果是,被检查的特定数据超过了它在该表中的配额,check_metermaid.so 将返回 "success",以便映射引擎继续处理该条目。该条目的剩余部分则用来处理超出配额的连接。
PORT_ACCESS *|*|*|*|* $C$|INTERNAL_IP;$3|$Y$E *|*|*|*|* $C$:A$[/opt/SUNWmsgsr/lib/check_metermaid.so,throttle,tablename,$3]$N421$ \ Connection$ declined$ at$ this$ time$E * $YEXTERNAL |
请注意,要在调用 check_metermaid.so. 之前处理映射表条目中的 $:A 标志测试,这确保只有在分发程序检查 PORT_ACCESS 时才执行 MeterMaid 探测,因为分发程序将为探测设置 A 标志。
MeterMaid 的配置存储在 msg.conf 中,并通过 configutil 维护。下面是 MeterMaid 当前支持的设置:括号中是默认值。有关 MeterMaid 参数的完整列表,请参见《Sun Java System Messaging Server 6.3 Administration Reference》中的“configutil Parameters”。
local.metermaid.enable 在运行 MeterMaid 守护进程的系统上,该设置必须设置为 yes,以便启动 Watcher 并对 MeterMaid 进行控制。
logfile.metermaid.* 它与 map、pop 和其他服务使用的设置相同。默认情况下,MeterMaid 将日志文件写入 msg-svr-base/data/log/metermaid。
metermaid.config.listenaddr (INADDR_ANY ) MeterMaid 应绑定的地址。在大多数系统中,不需要更改默认值,但对于多穴或 HA 系统,建议指定相应的地址。
metermaid.config.maxthreads (20) MeterMaid 服务器是多线程的,用于维护安排任务的线程池。该值设置了 MeterMaid 将使用的最大线程数。在有 4 个以上 CPU 的系统中,增加该值可能会增加总的吞吐量。
metermaid.config.port (63837) 这是 MeterMaid 侦听连接的端口,MeterMaid 客户端将连接到此端口。
metermaid.config.secret(无默认值,必须提供值) 为了验证外来连接, MeterMaid 使用一个共享机密,该机密在客户端连接到 MeterMaid 后立即发送。
metermaid.config.serverhost(无默认值,必须提供值) 这是客户端将要连接的主机名或 IP 地址。它可能与 metermaid.config.listenaddr 相同,但更可能具有一个特定值将客户端定向到一个系统,特别是 Messaging Server 环境下的系统。
以下设置供 check_metermaid 客户端使用:
metermaid.mtaclient.connectfrequency (15) 每 connectfrequency 秒尝试一次连接。当客户端需要连接到 MeterMaid 时,将使用此设置作为内部限制,以防止在 MeterMaid 不可用的情况下持续尝试连接。在客户端无法与 MeterMaid 通信期间,该设置将向 MTA 映射引擎返回 "fail" 状态,表示 MeterMaid 还没有阻塞该连接。
例如,如果 check_metermaid.so 尝试连接到 MeterMaid,但由于某种原因失败了,那么在接下来的 N 秒(由 metermaid.mtaclient.connectfrequency 指定)内将不再进行其他连接尝试。该设置将防止 check_metermaid.so 在 MeterMaid 无法工作的情况下过于频繁地尝试连接到 MeterMaid。
metermaid.mtaclient.connectwait (5) 当客户端等待 MeterMaid 的连接(初始连接或重用另一个已建立好的连接)时,该设置在返回 "fail" 状态并允许继续连接之前将等待 connectwait 秒。
metermaid.mtaclient.debug (no) 如果启用该选项,客户端中的调试信息将被输入到服务器或 SMTP 服务器的特定于线程的日志文件中。
metermaid.mtaclient.maxconns (3) 为了支持多线程的服务器,客户端将维护一个到 MeterMaid 的连接池。这样做可以增加通信期间的并发性。但是,由于 MeterMaid 执行的内部锁定,对特定表的访问被限制为一次一个请求,因此来自单个进程的多个连接可能会提供一些好处,但比较有限。
metermaid.mtaclient.readwait (10) 在与 MeterMaid 通信时,客户端在 "fail" 状态并允许继续连接之前将等待 readwait 秒。
最后,也会在 msg.conf 中定义限制表,如下所示。 每个配置参数中的 * 是被定义的特定表的名称。例如,对于名为 internal 的表,第一个参数应为 metermaid.table.internal.data_type.
metermaid.table.*.data_type(字符串) MeterMaid 在其表中支持两类数据:字符串和 ipv4。字符串数据被限制为每个条目 255 个字节,并可以使用区分大小写或不区分大小写功能进行比较(请参见下面列出的 metermaid.table.*.options)。
metermaid.table.*.max_entries (1000) MeterMaid 在初始化每个表时,将预分配此数量的条目。MeterMaid 自动回收旧条目,即使这些条目还没有过期。当收到新连接时,MeterMaid 将重新使用最近访问得最少的条目。站点应指定一个足够大的值以缓存 quota_time 期间接收到的连接。
metermaid.table.*.options 是一个以逗号分隔的关键字列表,用于定义表的行为或特征。有效的关键字有:
nocase — 在使用数据时,使用不区分大小写的比较功能来完成所有比较。(此选项仅对字符串数据有效。)
penalize — 在 quota_time 秒之后,限制通常会将连接数重置为 0,如果启用了 penalize 选项,限制将根据配额减少连接数(但不会小于 0),以便其他连接尝试减少以后的 quota_time 周期。例如,如果配额是 5,quota_time 为 60,在第一分钟内系统收到 12 次连接尝试,则头 5 次连接将被接受,而接下来的 7 次连接将被拒绝。过了 60 秒之后,根据特定地址计算的连接数将减少到 7,仍然将其保持在配额之上,并拒绝连接尝试。假定没有进行额外的连接尝试,又经过 60 秒的周期之后,连接数将进一步减为 2,MeterMaid 会重新允许连接尝试。
metermaid.table.*.quota (100) 当收到连接时,它将根据配额计数。如果 quota_time 秒内接收到的连接数超过了该值,MeterMaid 将拒绝连接。(对外来连接的实际影响是由映射表控制的,这可能会导致额外的检查、延迟或拒绝连接。)
metermaid.table.*.quota_time (60) 它指定了连接将根据 quota 进行计数的时间段(秒数)。经过这么多秒后,将根据该表的 type 减少基于外来地址所计算的连接数。
metermaid.table.*storage (hash) MeterMaid 可以使用两种不同的存储方法:hash 和 splay。建议使用默认的散列表,但在某些情况下,splay 树可能会提供更快的查找功能。
metermaid.table.*.type (throttle) 目前,MeterMaid 唯一支持的表类型为 throttle。该类型的表跟踪数据,通常是 IP 地址,并在 quota_time 秒的周期内将外来连接限制为 quota 连接。
本示例使用 MeterMaid 将 IP 地址限制为每分钟 10 次连接。下面给出映射文件中等效的 conn_throttle.so 设置供参考:
PORT_ACCESS *|*|*|*|* $C$|INTERNAL_IP;$3|$Y$E *|*|*|*|* $C$[/opt/SUNWmsgsr/lib/conn_throttle.so,throttle,$3,10]\ $N421$ Connection$ declined$ at$ this$ time$E * $YEXTERNAL |
此 PORT_ACCESS 映射表实现了 conn_throttle.so,将非 INTERNAL 连接限制为每分钟不超过 10 次连接的速率。
这两种技术之间的一个基本区别是,MeterMaid 不是直接将速率限制之类的细节配置到映射表中,而是使用 configutil 参数进行设置。下面介绍了此示例。
指定某一系统为 MeterMaid 服务器主机。
在此系统中,设置以下 configutil 参数:
local.metermaid.enable -v TRUE |
设置一个验证密码,用于验证客户端和 MeterMaid 服务器之间的通信:
configutil -o metermaid.config.secret -v password |
定义一个限制表。
MeterMaid 的限制行为由指定限制表的使用决定,这些表定义了操作特性。定义一个将连接速率限制为每分钟 10 次的表,请设置以下参数:
configutil -o metermaid.table.ext_throttle.data_type -v ipv4 configutil -o metermaid.table.ext_throttle.quota -v 10 |
ext_throttle 是限制表的名称。ipv4 是数据类型 Internet 协议版本 4 地址的表示形式。10 是配额(连接限制)。
在 MeterMaid 系统上, 启动 MeterMaid。
# start-msg metermaid |
在 MTA 将使用 MeterMaid 进行限制的系统上,指定 MeterMaid 主机和密码。
需要进行以下设置:
configutil -o metermaid.config.secret -v MeterMaid_Password configutil -o metermaid.config.serverhost -v name_or_ipaddress_of_MetermaidHost |
设置 MeterMaid PORT_ACCESS 表。
此表类似于等效的 conn_throttle.so 设置:
PORT_ACCESS *|*|*|*|* $C$|INTERNAL_IP;$3|$Y$E *|*|*|*|* $C$:A$[/opt/SUNWmsgsr/lib/check_metermaid.so,throttle,\ ext_throttle,$3] $N421$ Connection$ declined$ at$ this$ time$E * $YEXTERNAL |
第一行检验尝试连接的 IP 地址是否是内部的。如果是,则允许连接。第二行通过 MeterMaid 执行 IP 地址检查,如果该 IP 地址连接过于频繁则减少连接次数。第三行允许任何其他标记为 EXTERNAL 的连接通过。
请注意,此 check_metermaid.so 的调用与 conn_throttle.so 的调用非常相似。check_metermaid.so 中的函数是相同的。throttle 及其参数就是使用 metermaid.table.tablename 配置的表名称和要检查的 IP 地址 ($3)。与 conn_throttle.so 一样,在达到限制(在metermaid.table.ext_throttle.quota 中指定)时,此函数返回 success。这将允许处理映射条目行的剩余部分,向远程 SMTP 客户端发送一则消息(421 SMTP 代码,瞬态负完成,此时不接受连接),并通知分发程序关闭连接。
同时要注意,$:A 确保仅在从分发程序调用时才处理此行。若没有该项,还将在 tcp_smtp_server 进程的上下文中将调用 check_metermaid.so,并探测 PORT_ACCESS 映射表。这将导致 MeterMaid 对每个外来连接计数 2 次。
这就是将 MeterMaid 设置为 conn_throttle.so 的替代方案的基本配置。有关这些主题的信息,请参见10.3.2 映射操作和18.3.4 PORT_ACCESS 映射表。
有两个其他的配置选项在某些环境下可能很有用。conn_throttle.so 共享库还有一个 throttle_p 函数,它通过推算超出 60 秒(基本值)的延长时间段,阻止超过限制的连接。通过在 MeterMaid 服务器系统上配置以下选项,可以在 MeterMaid 中实现相同的行为:
configutil -o metermaid.table.ext_throttle.options -v penalize |
这将更改 ext_throttle 表的行为,以便在连接尝试次数大于为 metermaid.table.ext_throttle.quota 设置的值时,可以阻止连接。
另一个选项与接收大量连接的系统有关。由于 MeterMaid 能够跟踪整个分布式 MTA 环境中的连接,因此 MeterMaid 内部的内存数据库中所保留的连接的数量限制对于 MTA 环境的总体容量可能会不足。 默认值是每个表 1000 个条目,但如果您希望整个 MTA 环境中每分钟的连接数超过 1000,则可以通过以下配置选项增加连接数:
configutil -o metermaid.table.ext_throttle.max_entries -v max_entries |
请注意,即使在 60 秒内达到了 max_entries,MeterMaid 仍会自动丢弃最早的和最少使用的条目。因此,在 MeterMaid 的表中将保留连接较频繁的系统并进行计数,从而保持足够的信息以提供有效的限制。