8. 组件中的包过滤

8.1. 包过滤器API

Tigase服务器提供了一个API来过滤每个组件内的数据包流量。您可以分别过滤传入和传出的数据包。

通过过滤,我们的意思是拦截一个数据包,并可能对数据包进行一些更改,或者只是完全阻止数据包。阻塞是指停止任何进一步的处理并丢弃数据包。

包过滤基于 PacketFilterIfc 接口。有关所有详细信息,请查看此接口的JavaDoc文档。主要的过滤方法是 Packet filter(Packet packet); ,它将数据包作为输入,对其进行处理,可能会警告数据包内容(可能会添加或删除一些有效负载)并返回一个 Packet 以进行进一步处理。如果它返回 null 这意味着数据包被阻止并且不允许进一步处理,否则它返回一个 Packet 对象,该对象是它作为参数接收的相同对象或原始对象的修改副本。

请注意,虽然 Packet 对象不是不可修改的实例,但建议不要对现有对象进行更改。同一个 Packet 可能会被其他组件或线程同时处理,因此修改 Packet 可能会导致不可预知的结果。

请参考 PacketCounter 中的示例代码,这是一个非常简单的过滤器计算不同类型的数据包。此过滤器默认加载到所有组件,这可能对评估新部署安装的流量形状非常有帮助。您可以获得所有类型的数据包的计数器,它们是在哪里生成的,它们在哪里流动,它们在哪个组件上负载最多。

这是因为数据包过滤器还可以生成和呈现自己的统计信息,这些统计信息可以通过正常的统计监控机制访问。为了利用统计功能,包过滤器必须实现 void getStatistics(StatisticsList list); 方法。通常,该方法为空。但是,您可以从过滤器生成统计信息并将其添加到列表中。示例实现代码请参考 PacketCounter

8.2. 配置

包过滤器是可配置的,即可以在Tigase服务器的配置中为每个组件和每个流量方向单独配置包过滤器实例。这为您提供了极大的灵活性和对Tigase服务器内部数据流的控制。

例如,您可以将特定的数据包过滤器加载到所有连接管理器,以阻止特定流量或特定数据包源向服务器上的用户发送消息。您还可以通过从所有数据包中删除某些有效负载来减少服务器的整体负载。这有无限的可能性。

默认配置以这样一种方式生成,即每个组件加载单个数据包过滤器 - 每个流量方向的 PacketCounter

bosh {
    incomingFilters (class: tigase.server.filters.PacketFiltersBean$IncomingPacketFiltersBean) {
        packetCounter (class: tigase.server.filters.PacketCounter) {}
    }
    outgoingFilters (class: tigase.server.filters.PacketFiltersBean$OutgoingPacketFiltersBean) {
        packetCounter (class: tigase.server.filters.PacketCounter) {}
    }
    seeOtherHost {}
}
c2s {
    incomingFilters (class: tigase.server.filters.PacketFiltersBean$IncomingPacketFiltersBean) {
        packetCounter (class: tigase.server.filters.PacketCounter) {}
    }
    outgoingFilters (class: tigase.server.filters.PacketFiltersBean$OutgoingPacketFiltersBean) {
        packetCounter (class: tigase.server.filters.PacketCounter) {}
    }
    seeOtherHost {}
}
'message-router' {
    incomingFilters (class: tigase.server.filters.PacketFiltersBean$IncomingPacketFiltersBean) {
        packetCounter (class: tigase.server.filters.PacketCounter) {}
    }
    outgoingFilters (class: tigase.server.filters.PacketFiltersBean$OutgoingPacketFiltersBean) {
        packetCounter (class: tigase.server.filters.PacketCounter) {}
    }
}
muc {
    incomingFilters (class: tigase.server.filters.PacketFiltersBean$IncomingPacketFiltersBean) {
        packetCounter (class: tigase.server.filters.PacketCounter) {}
    }
    outgoingFilters (class: tigase.server.filters.PacketFiltersBean$OutgoingPacketFiltersBean) {
        packetCounter (class: tigase.server.filters.PacketCounter) {}
    }
}
s2s {
    incomingFilters (class: tigase.server.filters.PacketFiltersBean$IncomingPacketFiltersBean) {
        packetCounter (class: tigase.server.filters.PacketCounter) {}
    }
    outgoingFilters (class: tigase.server.filters.PacketFiltersBean$OutgoingPacketFiltersBean) {
        packetCounter (class: tigase.server.filters.PacketCounter) {}
    }
}
'sess-man' () {
    incomingFilters (class: tigase.server.filters.PacketFiltersBean$IncomingPacketFiltersBean) {
        packetCounter (class: tigase.server.filters.PacketCounter) {}
    }
    outgoingFilters (class: tigase.server.filters.PacketFiltersBean$OutgoingPacketFiltersBean) {
        packetCounter (class: tigase.server.filters.PacketCounter) {}
    }
}

现在,假设您在类中实现了一个数据包过滤器:com.company.SpamBlocker。您希望在大多数组件上禁用PacketCounter,仅将其留在消息路由器组件中,并且您希望在所有连接管理器中安装SpamBlocker。

请注意,连接管理器的’incoming’和 ‘outgoing’流量可能与您通常的预期相反。

  • incoming 是由消息路由器提交给组件的流量,必须进一步处理。对于连接管理器,此进一步处理意味着将其发送到网络。

  • outgoing 是由组件’生成’并流出组件的流量。这样的数据包被提交给消息路由器,然后由路由器决定将其发送到何处以进行进一步处理。对于连接管理器,传出 流量是刚从网络收到的所有数据包。

据此,我们必须将SpamBlocker过滤器应用于所有连接管理器中的所有’传出‘流量。您可能还认为比较Bosh连接和标准XMPP c2s连接之间的流量形状实际上可能很有用。因此,让我们也为这些组件保留数据包计数器。

这是我们将SpamBlocker应用于连接管理器并将PacketCounter应用于其他一些组件的新配置:

bosh {
    incomingFilters () {
        packetCounter () {}
    }
    outgoingFilters () {
        packetCounter (active: false) {}
        spamBlocker (class: com.company.SpamBlocker, active: true) {}
    }
    seeOtherHost {}
}
c2s {
    incomingFilters () {
        packetCounter () {}
    }
    outgoingFilters () {
        packetCounter (active: false) {}
        spamBlocker (class: com.company.SpamBlocker, active: true) {}
    }
    seeOtherHost {}
}
'message-router' {
    incomingFilters () {
        packetCounter () {}
    }
    outgoingFilters () {
        packetCounter () {}
    }
}
muc {
    incomingFilters () {
        packetCounter (active: false) {}
    }
    outgoingFilters () {
        packetCounter (active: false) {}
    }
}
s2s {
    incomingFilters () {
        packetCounter (active: false) {}
    }
    outgoingFilters () {
        packetCounter (active: false) {}
        spamBlocker (class: com.company.SpamBlocker, active: true) {}
    }
}
'sess-man' () {
    incomingFilters () {
        packetCounter (active: false) {}
    }
    outgoingFilters () {
        packetCounter (active: false) {}
    }
}

incomingFilters outgoingFilterspacketCounter 的情况下,我们能够跳过提供 class 参数,因为这些类正确地使用了 @Bean 注释。

应用新配置的最简单方法是通过 Admin Guide 中详细描述的 config.tdsl 文件。