
IPS/IDS与WAF系统自动机技术也广泛应用于DPI系统(Deep Packet Inspection,DPI)中,以实现对网络报文的解析与识别。
应用于应用识别的DPI系统
正则表达式与自动机的等价性自动机分为确定型有穷自动机(Deterministic Finite Automata,DFA)和非确定型有穷自动机(Non-Deterministic Finite Automata,NFA)。确定型有穷自动机中,对于给定的确定状态与确定输入,其状态转移关系是确定唯一的,且每一时刻只存在一个激活状态。相反,在非确定型有穷自动机中,对于给定的确定状态与确定输入,其可能存在多个状态转移关系,且某一时刻可能存在多个的激活状态。非确定型有穷自动机又主要分为存在epsilon转移的epsilon-NFA与没有epsilon转移的NFA,其经典代表分别为Thompson NFA与Gluskov NFA。
Thompson NFA上图所示为识别正则表达式(AB|CD)*AFF*的Thompson NFA,可见thompson NFA由基本的子正则表达式NFA单元通过epsilon边连接而成,epsilon边连接的两个状态可以由空字符进行转移,即存在无条件的状态转移关系,由字母标识的边连接的两个状态表明这两个状态之间需要输入对应的字符才能进行激活状态的转移。
Gluskov NFA上图所示为识别正则表达式(AB|CD)*AFF*的Gluskov NFA。显而易见,Gluskov NFA比Thompson NFA要简洁很多,且Glukov NFA中NFA的状态数与正则表达式中出现的字符和字符集总数一致。相比于Thompson NFA,Gluskov NFA状态数更少,结构更紧凑。同时在Gluskov NFA中,状态之间的跳转条件被移到了节点内变成了节点的激活条件,因此Gluskov NFA的运行时处理也会变得更加简单。在运行时读入一个字符c时,便可知道字符c可以激活的状态集reach(c),那么只需在Gluskov NFA当前的激活状态集s的基础上计算其后继状态集succ(s),并取reach(c)与succ(s)的交集,所得的交集即为Gluskov NFA的下一刻激活状态集。对于Thompson NFA,节点的激活条件并不唯一,且需要处理epsilon边连接的状态转移关系,其下一刻的激活状态集的计算会更复杂。对Thompson NFA或Gluskov NFA使用子集构造算法,可以将NFA转化为DFA。DFA相较于NFA最大的优势是性能,而劣势在于空间开销,这是因为DFA状态转移的确定性是通过对NFA不同状态进行组合得到的,因此功能等价的DFA和NFA从理论上来说,DFA状态数的上限是NFA状态数的指数关系。
DFA状态图上图所示为使用子集构造算法将识别正则表达式(AB|CD)*AFF*的thompson NFA转化为DFA后的状态图。图中每个蓝色框的序号集中的序号对应于thompson NFA中状态的序号,体现了DFA中的每个状态对应于NFA状态集的一个子集。2.2 主流的开源自动机相关库目前广泛使用的主流开源自动机相关库主要是Pcre、RE2、Hyperscan:
基于预过滤的正则表达式优化策略上图所示为基于字符串匹配器预过滤的正则表达式匹配优化策略。该方案会在正则表达式的编译过程中提取正则表达式中的字符串信息,并根据提取的字符串构建一个多字符串预匹配器。如针对规则0,提取了字符串SEARCH,针对规则N提取了字符串SUBSCRIBE。在对输入预料进行匹配的过程中,会先使用多字符串匹配器进行字符串的匹配,若匹配过程中匹配到了字符串SERACH但是没有匹配到字符串SUBCRIBE,则会进一步使用根据正则表达式规则0构建的自动机进行第二阶段的正则表达式匹配。可见基于预过滤的正则表达式匹配方案为一个两阶段的匹配过程。基于字符串匹配器的预过滤正则表达式匹配方案虽然能提早过滤掉无法匹配的语料。但仍然存在以下的诸多不足:(1)对正则表达式中的字符串存在重复匹配,即预过滤的字符串匹配组件匹配一次字符串,自动机又重复匹配一次字符串;(2)基于预过滤的匹配方案中的第二阶段,使用自动机对字符串进行匹配难以有效地使用CPU的SIMD指令集进行字符串匹配的并行加速;(3)不合理的关键字符串选择容易拖累整体正则表达式的匹配性能。针对基于字符串匹配器预过滤的正则表达式匹配方案的不足,一种更新颖有效的基于正则表达式分解的正则表达式匹配方案便应运而生了。3.2 基于正则表达式分解的性能优化基于正则表达式分解的正则表达式匹配方案首先会将正则表达式拆解成几个子字符串和子正则表达式。拆解的子字符串会被构建为一个字符串匹配器(字符串匹配器可以有效地使用CPU的SIMD指令集进行并行加速,相比于使用自动机匹进行字符串配具有数量级上的性能优势),而拆解的子正则表达式则会被构建为一个子自动机,如NFA或DFA。在对输入语料进行正则表达式匹配时,该方案会按照一定顺序调用各个匹配器,并尽量优先调用字符串匹配器进行字符串的匹配,只有当前一个匹配器匹配成功后才会调用下一个匹配器进行匹配,并且只有当所有的匹配器都按照既定的顺序匹配成功后,整条拆解的正则表达式才真正匹配成功。
基于规则拆分的正则表达式匹配策略上图所示为使用拆解后的正则表达式.*start[^x]comA+匹配输入字符串AstarZcomA的一个示例。首先,正则表达式被拆解为五个部分,分别对应于自动机部分FA2、FA1、FA0与字符串部分STR2、STR1。拆解后构造的各个子自动机与子字符串匹配器的匹配顺序为STR1->STR2->FA1->FA0->FA2。拆解后构造的各个子自动机与子字符串遵循一下的优先级原则:很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty
我认为我的问题最好用一个例子来描述。假设我有一个名为“Thing”的简单模型,它有一些简单数据类型的属性。像...Thing-foo:string-goo:string-bar:int这并不难。数据库表将包含具有这三个属性的三列,我可以使用@thing.foo或@thing.bar之类的东西访问它们。但我要解决的问题是当“foo”或“goo”不再包含在简单数据类型中时会发生什么?假设foo和goo代表相同类型的对象。也就是说,它们都是“Whazit”的实例,只是数据不同。所以现在事情可能看起来像这样......Thing-bar:int但是现在有一个新的模型叫做“Whazit”,看起来
我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功
我有一个要在我的Rails3项目中使用的数组扩展方法。它应该住在哪里?我有一个应用程序/类,我最初把它放在(array_extensions.rb)中,在我的config/application.rb中我加载路径:config.autoload_paths+=%W(#{Rails.root}/应用程序/类)。但是,当我转到railsconsole时,未加载扩展。是否有一个预定义的位置可以放置我的Rails3扩展方法?或者,一种预先定义的方式来添加它们?我知道Rails有自己的数组扩展方法。我应该将我的添加到active_support/core_ext/array/conversion
我想知道是否可以通过自动创建数组来插入数组,如果数组不存在的话,就像在PHP中一样:$toto[]='titi';如果尚未定义$toto,它将创建数组并将“titi”压入。如果已经存在,它只会推送。在Ruby中我必须这样做:toto||=[]toto.push('titi')可以一行完成吗?因为如果我有一个循环,它会测试“||=”,除了第一次:Person.all.eachdo|person|toto||=[]#with1billionofperson,thislineisuseless999999999times...toto.push(person.name)你有更好的解决方案吗?
参见下面的示例,我想最好使用第二种方法,但第一种也可以。哪种方法最好,使用另一种的后果是什么?classTestdefstartp"started"endtest=Test.newtest.startendclassTest2defstartp"started"endendtest2=Test2.newtest2.start 最佳答案 我肯定会说第二种变体更有意义。第一个不会导致错误,但对象实例化完全过时且毫无意义。外部变量在类的范围内不可见:var="string"classAvar=A.newendputsvar#=>strin
如果我构建了一个应用程序来访问来自Gmail、Twitter和Facebook的一些数据,并且我希望用户只需输入一次他们的身份验证信息,并且在几天或几周后重置,那会怎样是在Ruby中动态执行此操作的最佳方法吗?我看到很多人只是拥有他们客户/用户凭证的配置文件,如下所示:gmail_account:username:myClientpassword:myClientsPassword这看起来a)非常不安全,b)如果我想为成千上万的用户存储此类信息,它就无法工作。推荐的方法是什么?我希望能够在这些服务之上构建一个界面,因此每次用户进行交易时都必须输入凭据是不可行的。