精华内容
下载资源
问答
  • 常用的四种过滤方法
    千次阅读
    2020-11-16 20:50:31


    在实际工作中,根据某个字段,对一个Spark数据集进行过滤,是一个很常见的场景,举个例子:

    一个存储公司员工信息的数据集A,有以下三个字段:

    id: Integer
    name: String
    age: Integer
    

    现在要过滤出某些员工的id,这些id在B集合(B可能是哈希表,也可能是Spark数据集)中,过滤逻辑为:

    C = A.filter(A.id in B)
    

    有四种方法可以实现,分别为:

    • Filter
    • Map
    • MapPartition
    • Inner Join

    下面详细介绍。

    Filter

    Spark的Filter变换,可以根据条件表达式、返回布尔值的过滤函数、条件字符串,对数据集进行过滤,使用方法如下:

    // 1. 条件表达式
    A1 = A.filter(Column condition)
    // 2. 自定义过滤函数
    A1 = A.filter(FilterFunction<T> func)
    // 3. 条件字符串
    A1 = A.filter(String condition)
    

    Filter 变换比较简单,逐条处理记录不论数据集大小,效率都很高,但需要能够将用来过滤的数据集B广播到所有的executor上。

    Map

    Map变换,对数据集中每条记录调用一个函数,返回值可以是null,也可以是相同类型或不同类型的新记录,使用方法如下:

    // encoder参数用来指定输出类型
    A2 = A.map(MapFunction<T,U> func, Encoder<U> encoder)
    

    通过Map变换实现过滤的话,只需要在Map变换中,将符合条件的记录原样返回,不符合条件的记录返回null即可。

    可以看到,Map变换的语义和Filter变换的语义相似,都是逐条处理记录,但Map需要提供一个额外的Encoder,故没有Filter简单和优雅,且因为输出要过滤null值,所以效率不如Filter。

    MapPartitions

    MapPartitions变换,与Map变换类似,但映射函数不是在每条记录上调用,而是在分区级别调用,使用方法如下:

    // func的输入和输出都是Iterator类型
    A3 = A.map(MapPartitionsFunction<T,U> func, Encoder<U> encoder)
    

    MapPartitions在分区级别进行操作,而不是记录级别,因此比Filter和Map效率更高。缺点的话,首先和Map一样,需要提供一个额外的Encoder,此外,当分区过大,超过executor所能提供的内存时,任务会失败,因此可靠性不如Map和Filter。

    Inner Join

    以员工id相等为Inner Join的条件,然后只要A集合中的字段,同样可以实现过滤,使用方法:

    // join表达式可能为 A("id") === B("id")
    A4 = A.join(Dataset<?> B, Column joinExprs)
    

    Inner Join和Filter一样,效率和可靠性都有保证,且对B集合的类型和大小都没有偏好。

    总结

    在本文描述的过滤场景中,综合考虑效率和可靠性,如果用来过滤的集合比较小,可以广播到所有的executor中,那么选择Filter变换为佳,如果B集合很大,则Inner Join更合适。

    参考链接:

    1. https://towardsdatascience.com/four-ways-to-filter-a-spark-dataset-against-a-collection-of-data-values-7d52625bcf20
    2. https://spark.apache.org/docs/latest/api/java/index.html
    3. https://spark.apache.org/docs/latest/api/scala/org/apache/spark/sql/Dataset.html

    公众号:大数志
    传递最新、最有价值的大数据技术干货和资讯。

    更多相关内容
  • 过滤器的四种拦截方式

    千次阅读 2019-12-10 19:57:52
    四种拦截方式 引言 我们先做一个小测试,新建一个b.jsp: <body> <h1>b.jsp</h1> </body> 再新建一个a.jsp,在里面转发到b.jsp: <body> <h1>a.jsp</h1> <% ...

    四种拦截方式

    引言

    我们先做一个小测试,新建一个b.jsp:

    <body>
    	<h1>b.jsp</h1>
    </body>
    

    再新建一个a.jsp,在里面转发到b.jsp:

    <body>
    	<h1>a.jsp</h1>
    	<%
    		request.getRequestDispatcher("/b.jsp").forward(request, response);
    	%>
    </body>
    

    然后我们配置一个过滤器,指定过滤的资源为b.jsp:

    public class MyFilter implements Filter {
    	public void doFilter(ServletRequest request, ServletResponse response,
    			FilterChain chain) throws IOException, ServletException {
    		System.out.println("MyFilter...");
    		chain.doFilter(request, response);
    	}
    }
    

    xml:

    <filter>
    	<display-name>MyFilter</display-name>
    	<filter-name>MyFilter</filter-name>
    	<filter-class>com.veeja.web.filter.MyFilter</filter-class>
    </filter>
    <filter-mapping>
    	<filter-name>MyFilter</filter-name>
    	<url-pattern>/b.jsp</url-pattern>
    </filter-mapping>
    

    然后我们在浏览器中直接访问b.jsp,显然的是,过滤器是会执行的:
    在这里插入图片描述
    但是,如果我们访问a.jsp呢,我们是知道的,a.jsp会转发到b.jsp,这样过滤器会执行吗?我们试一试:
    在这里插入图片描述
    结果我们发现,这个时候过滤器却没有执行。这是为什么呢?

    这是因为,在默认情况下,只能直接访问目标资源才会执行过滤器,而forward执行目标资源,就不会执行过滤器。

    四种拦截

    其实过滤器有四种拦截方式!分别是:REQUESTFORWARDINCLUDEERROR

    • REQUEST:直接访问目标资源时执行过滤器。包括:在地址栏中直接访问、表单提交、超链接、重定向,只要在地址栏中可以看到目标资源的路径,就是REQUEST;
    • FORWARD:转发访问执行过滤器。包括RequestDispatcher#forward()方法、<jsp:forward>标签都是转发访问;
    • INCLUDE:包含访问执行过滤器。包括RequestDispatcher#include()方法、<jsp:include>标签都是包含访问;
    • ERROR:当目标资源在web.xml中配置为<error-page>中时,并且真的出现了异常,转发到目标资源时,会执行过滤器。

    可以在<filter-mapping>中添加0~n个<dispatcher>子元素,来说明当前访问的拦截方式。

    接下来我们举几个例子,说明一下应用的实际情况:

    <filter-mapping>
    	<filter-name>myfilter</filter-name>
    	<url-pattern>/b.jsp</url-pattern>
    	<dispatcher>REQUEST</dispatcher>
    	<dispatcher>FORWARD</dispatcher>
    </filter-mapping>
    

    这个配置中,b.jsp为目标资源。
    当直接请求b.jsp时,会执行过滤器。
    当转发到b.jsp页面时,会执行过滤器。

    <filter-mapping>
    	<filter-name>myfilter</filter-name>
    	<url-pattern>/b.jsp</url-pattern>
    </filter-mapping>
    

    这里没有给出拦截方式时,那么默认为REQUEST。这也能解释我们在引言中的例子了。

    <filter-mapping>
    	<filter-name>myfilter</filter-name>
    	<url-pattern>/b.jsp</url-pattern>
    	<dispatcher>FORWARD</dispatcher>
    </filter-mapping>
    

    这一个配置中,当转发到b.jsp页面时,会执行过滤器。而且因为已经给出了<dispatcher>FORWARD</dispatcher>了,那么就没有默认的REQUEST了。所以只有在转发到b.jsp时才会执行过滤,而直接访问到b.jsp时,不会执行过滤器。

    接下来,我们再举一个ERROR拦截的例子:

    <filter-mapping>
    	<filter-name>myfilter</filter-name>
    	<url-pattern>/b.jsp</url-pattern>
    	<dispatcher>ERROR</dispatcher>
    </filter-mapping>
    <error-page>
    	<error-code>500</error-code>
    	<location>/b.jsp</location>
    </error-page>
    

    上面里例子中,拦截的方式为ERROR,而且把b.jsp设置为HTTPS 500的错误页面。

    我们写一个jsp,为a.jsp:

    <body>
    	<h1>a.jsp</h1>
    	<%
    		if(true)
    			throw new RuntimeException("hahhaahahaha~");
    	%>
    </body>
    

    这个时候,当用户访问a.jsp页面时会抛出异常,也就是500错误。
    这时服务器会转发到b.jsp,而在这之前会执行上面配置的过滤器。

    其实最为常用的就是REQUEST和FORWARD两种拦截方式,而INCLUDE和ERROR都比较少用。大家多做练习,就能熟练掌握了。


    以上就是全部内容,谢谢你的阅读。

    如有纰漏,请不吝指出,不胜感激。

    如果你不沉下心来认真练习,所有的阅读都是白费的。

    展开全文
  • tcpdump常用与高级过滤方法整理

    千次阅读 2019-05-06 11:27:46
    下面介绍两种过滤方法(第一方法比较操蛋,可忽略): a. 比较第一字节的值是否大于01000101 这可以判断IPv4带IP选项的数据和IPv6的数据。 01000101十进制等于69,计算方法如下(小提示:用计算器更方便) 0 ...

    1.命令格式

    tcpdump [ -adeflnNOpqStvx ] [ -c 数量 ] [ -F 文件名 ][ -i 网络接口 ] [ -r 文件名]
    [ -s snaplen ] [ -T 类型 ] [ -w 文件名 ] [表达式 ]

    2.选项介绍

    参数含义
    -a将网络地址和广播地址转变成名字
    -d将匹配信息包的代码以人们能够理解的汇编格式给出
    -dd将匹配信息包的代码以c语言程序段的格式给出
    -ddd将匹配信息包的代码以十进制的形式给出
    -e在输出行打印出数据链路层的头部信息,包括源mac和目的mac,以及网络层的协议
    -f将外部的Internet地址以数字的形式打印出来
    -l使标准输出变为缓冲行形式
    -n指定将每个监听到数据包中的域名转换成IP地址后显示,不把网络地址转换成名字
    -nn指定将每个监听到的数据包中的域名转换成IP、端口从应用名称转换成端口号后显示
    -t在输出的每一行不打印时间戳
    -v输出一个稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息
    -vv输出详细的报文信息
    -c在收到指定的包的数目后,tcpdump就会停止
    -F从指定的文件中读取表达式,忽略其它的表达式
    -i指定监听的网络接口,后面跟数组“any”表示针对所有接口
    -p将网卡设置为非混杂模式,不能与host或broadcast一起使用
    -r从指定的文件中读取包(这些包一般通过-w选项产生)
    -w直接将包写入文件中,并不分析和打印出来
    -s snaplen表示从一个包中截取的字节数。0表示包不截断,抓完整的数据包。默认的话 tcpdump 只显示68字节数据包
    -T将监听到的包直接解释为指定的类型的报文,常见的类型有rpc (远程过程调用)和snmp(简单网络管理协议
    -X告诉tcpdump命令,需要把协议头和包内容都原原本本的显示出来(tcpdump会以16进制和ASCII的形式显示),这在进行协议分析时是绝对的利器

    使用案例

    参数 -l

    -l选项的作用就是将tcpdump的输出变为“行缓冲”方式,这样可以确保tcpdump遇到的内容一旦是换行符即将缓冲的内容输出到标准输出,以便于利用管道或重定向方式来进行后续处理。

    Linux/UNIX的标准I/O提供了全缓冲、行缓冲和无缓冲三种缓冲方式。
    标准错误是不带缓冲的,终端设备常为行缓冲,而其他情况默认都是全缓冲的。
    例如我们只想提取包的每一行的第一个域(时间域),这种情况下我们就需要-l将默认的全缓冲变为行缓冲了。
    tcpdump -i eth0 port 1111 -l | awk ‘{print $1}’
    在这里插入图片描述
    参数–w -r

    -w 直接将包写入文件中(即原始包,如果使用 重定向 > 则只是保存显示的结果,而不是原始文件),即所谓的“流量保存”—就是把抓到的网络包能存储到磁盘上保存下来,为后续使用。参数-r 达到“流量回放”—就是把历史上的某一时间段的流量,重新模拟回放出来,用于流量分析。

    通过-w选项将流量都存储在cp.pcap(二进制格式)文件中了.可以通过 –r 读取raw packets文件 cp.pcap.
    如:sudo tcpdump i- eth0 ‘port 1111’ -c 3 -r cp.pcap 即可进行流量回放。

    3.常用过滤表达式

    tcpdump支持传入单个或多个过滤表达式,可以通过命令man pcap-filter 来参考过滤表达式的帮助文档
    过滤表达式大体可以分成三种过滤条件,“类型”“方向”“协议”逻辑运算其他关键字,这五种条件的搭配组合就构成了我们的过滤表达式

    3.1 “类型”关键字

    关于类型的关键字,主要包括hostnetport
    例如:
    host 210.45.114.211,指定主机 210.45.114.211
    net 210.11.0.0 指明210.11.0.0是一个网络地址
    port 21 指明端口号是21。如果没有指定类型,缺省的类型是host

    3.2 “方向”关键字

    关于传输方向的关键字,主要包括src,dst,dst or src,dst and src
    举例:
    src 210.45.114.211 ,指明ip包中源地址是210.45.114.211
    dst net 210.11.0.0 指明目的网络地址是210.11.0.0
    如果没有指明方向关键字,则缺省是src or dst关键字。

    3.3 “协议”关键字

    关于协议的关键字,主要包括 ether,ip,ip6,arp,rarp,tcp,udp等类型。
    如果没有指定任何协议,则tcpdump将会监听所有协议的信息包。

    3.4 逻辑运算

    tcpdump还支持三种逻辑运算:

    逻辑运算表示方法
    取与“and”或“&&”
    取或“or”或“ll“”
    取非“not”或“!”

    3.5 其他关键字

    tcpdump还在其他几种关键字:gateway、broadcast、less、greater

    3.6 使用案例

    可以利用这些关键字进行组合,从而组合为比较强大的过滤条件。下面举例说明

    (1)只想查目标机器端口是21或80的网络包,其他端口的我不关注:
    sudo tcpdump -i eth0 -c 10 ‘dst port 21 or dst port 80’

    (2) 想要截获主机172.16.0.11 和主机210.45.123.249或 210.45.123.248的通信,使用命令(注意括号的使用):
    sudo tcpdump -i eth0 -c 3 ‘host 172.16.0.11 and (210.45.123.249 or210.45.123.248)’

    (3)想获取使用ftp端口和ftp数据端口的网络包
    sudo tcpdump ‘port ftp or ftp-data’
    这里 ftp、ftp-data到底对应哪个端口? linux系统下 /etc/services这个文件里面,就存储着所有知名服务和传输层端口的对应关系。如果你直接把/etc/services里的ftp对应的端口值从21改为了3333,那么tcpdump就会去抓端口含有3333的网络包了。

    (4) 如果想要获取主机172.16.0.11除了和主机210.45.123.249之外所有主机通信的ip包,使用命令:
    sudo tcpdump ip ‘host 172.16.0.11 and ! 210.45.123.249’

    (5) 抓172.16.0.11的80端口和110和25以外的其他端口的包
    sudo tcpdump -i eth0 ‘host 172.16.0.11 and! port 80 and ! port 25 and ! port 110’

    4.高级包头过滤

    首先了解如何从包头过滤信息

    proto[x:y] : 过滤从x字节开始的y字节数。比如ip[2:2]过滤出3、4字节(第一字节从0开始排)
    proto[x:y] & z = 0 : proto[x:y]和z的与操作为0
    proto[x:y] & z !=0 : proto[x:y]和z的与操作不为0
    proto[x:y] & z = z : proto[x:y]和z的与操作为z
    proto[x:y] = z : proto[x:y]等于z

    操作符 : >, <, >=, <=, =, !=

    4.1、IP头

    在这里插入图片描述
    本文只针对IPv4。

    4.2、IP选项设置了吗?

    “一般”的IP头是20字节,但IP头有选项设置,不能直接从偏移21字节处读取数据。IP头有个长度字段可以知道头长度是否大于20字节。
    ±±±±±±±±+
    |Version| IHL |
    ±±±±±±±±+
    通常第一个字节的二进制值是:01000101,分成两个部分: 0100 = 4 表示IP版本 0101 = 5 表示IP头32 bit的块数,5 x 32 bits = 160 bits or 20 bytes
    如果第一字节第二部分的值大于5,那么表示头有IP选项。
    下面介绍两种过滤方法(第一种方法比较操蛋,可忽略):
    a. 比较第一字节的值是否大于01000101
    这可以判断IPv4带IP选项的数据和IPv6的数据。
    01000101十进制等于69,计算方法如下(小提示:用计算器更方便)
    0 : 0 \ 1 : 2^6 = 64 \ 第一部分 (IP版本)
    0 : 0 /
    0 : 0 /
    0 : 0
    1 : 2^2 = 4 \ 第二部分 (头长度)
    0 : 0 /
    1 : 2^0 = 1 /
    64 + 4 + 1 = 69

    如果设置了IP选项,那么第一自己是01000110(十进制70),过滤规则:
    tcpdump -i eth1 ‘ip[0] > 69’
    IPv6的数据也会匹配,看看第二种方法。
    b. 位操作

    0100 0101 : 第一字节的二进制
    0000 1111 : 与操作
    <=========
    0000 0101 : 结果
    正确的过滤方法
    tcpdump -i eth1 ‘ip[0] & 15 > 5’
    或者tcpdump -i eth1 ‘ip[0] & 0x0f > 5’

    4.3、分片标记

    当发送端的MTU大于到目的路径链路上的MTU时就会被分片,这段话有点拗口,权威的请参考《TCP/IP详解》。唉,32借我的书没还,只能凑合写,大家记得看书啊。

    分片信息在IP头的第七和第八字节:
    ±±±±±±±±±±±±±±±±+
    |Flags| Fragment Offset |
    ±±±±±±±±±±±±±±±±+
    Bit 0: 保留,必须是0
    Bit 1: (DF) 0 = 可能分片, 1 = 不分片
    Bit 2: (MF) 0 = 最后的分片, 1 = 还有分片
    Fragment Offset字段只有在分片的时候才使用。
    要抓带DF位标记的不分片的包,第七字节的值应该是:
    01000000 = 64
    tcpdump -i eth1 ‘ip[6] = 64’

    4.4、抓分片包

    匹配MF,分片包
    tcpdump -i eth1 ‘ip[6] = 32’
    最后分片包的开始3位是0,但是有Fragment Offset字段。
    匹配分片和最后分片
    tcpdump -i eth1 ‘((ip[6:2] > 0) and (not ip[6] = 64))’
    测试分片可以用下面的命令:
    ping -M want -s 3000 192.168.1.1

    4.5、匹配小TTL

    TTL字段在第九字节,并且正好是完整的一个字节,TTL最大值是255,二进制为11111111。
    可以用下面的命令验证一下:

    $ ping -M want -s 3000 -t 256 192.168.1.200
    ping: ttl 256 out of range
    ±±±±±±±±+
    | Time to Live |
    ±±±±±±±±+
    在网关可以用下面的命令看看网络中谁在使用traceroute
    tcpdump -i eth1 ‘ip[8] < 5’

    4.6、抓大于X字节的包

    大于600字节
    tcpdump -i eth1 ‘ip[2:2] > 600’

    4.7、更多的IP过滤

    首先还是需要知道TCP基本结构,再次推荐《TCP/IP详解》,卷一就够看的了,避免走火入魔。

    TCP头
    0 1 2 3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    | Source Port | Destination Port |
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    | Sequence Number |
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    | Acknowledgment Number |
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    | Data | |C|E|U|A|P|R|S|F| |
    | Offset| Res. |W|C|R|C|S|S|Y|I| Window |
    | | |R|E|G|K|H|T|N|N| |
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    | Checksum | Urgent Pointer |
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    | Options | Padding |
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    | data |
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    抓取源端口大于1024的TCP数据包
    tcpdump -i eth1 ‘tcp[0:2] > 1024’
    匹配TCP数据包的特殊标记
    TCP标记定义在TCP头的第十四个字节

    ±±±±±±±±+
    |C|E|U|A|P|R|S|F|
    |W|C|R|C|S|S|Y|I|
    |R|E|G|K|H|T|N|N|
    ±±±±±±±±+
    重复一下TCP三次握手,两个主机是如何勾搭的:

    源发送SYN
    目标回答SYN, ACK
    源发送ACK
    没女朋友的童鞋要学习一下:

    1. MM,你的手有空吗?–
    2. 有空,你呢?~~
    3. 我也有空 _

    失败的loser是酱紫的:

    1. MM,这是你掉的板砖吗?(SYN)  ̄▽ ̄
    2. 不是,找拍啊?(RST-ACK) ˋ﹏ˊ

    只抓SYN包,第十四字节是二进制的00000010,也就是十进制的2
    tcpdump -i eth1 ‘tcp[13] = 2’
    抓SYN, ACK (00010010 or 18)
    tcpdump -i eth1 ‘tcp[13] = 18’
    抓SYN或者SYN-ACK
    tcpdump -i eth1 ‘tcp[13] & 2 = 2’
    用到了位操作,就是不管ACK位是啥。

    抓PSH-ACK
    tcpdump -i eth1 ‘tcp[13] = 24’
    抓所有包含FIN标记的包(FIN通常和ACK一起,表示幽会完了,回见)
    tcpdump -i eth1 ‘tcp[13] & 1 = 1’
    抓RST(勾搭没成功,伟大的greatwall对她认为有敏感信息的连接发RST包,典型的棒打鸳鸯)
    tcpdump -i eth1 ‘tcp[13] & 4 = 4’
    下图详细描述了TCP各种状态的标记,方便分析。

    tcp_state_machine.jpg

    4.8、大叔注

    tcpdump考虑了一些数字恐惧症者的需求,提供了部分常用的字段偏移名字:

    icmptype (ICMP类型字段)
    icmpcode (ICMP符号字段)
    tcpflags (TCP标记字段)

    ICMP类型值有:
    icmp-echoreply, icmp-unreach, icmp-sourcequench, icmp-redirect, icmp-echo, icmp-routeradvert, icmp-routersolicit, icmp-timxceed, icmp-paramprob, icmp-tstamp, icmp-tstampreply, icmp-ireq, icmp-ireqreply, icmp-maskreq, icmp-maskreply

    TCP标记值:
    tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-push, tcp-ack, tcp-urg
    这样上面按照TCP标记位抓包的就可以写直观的表达式了:

    只抓SYN包
    tcpdump -i eth1 ‘tcp[tcpflags] = tcp-syn’
    抓SYN, ACK
    tcpdump -i eth1 ‘tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack != 0’

    4.9、抓SMTP数据

    tcpdump -i eth1 ‘((port 25) and (tcp[(tcp[12]>>2):4] = 0x4d41494c))’
    抓取数据区开始为"MAIL"的包,"MAIL"的十六进制为0x4d41494c。

    4.10、抓HTTP GET数据

    tcpdump -i eth1 ‘tcp[(tcp[12]>>2):4] = 0x47455420’
    "GET "的十六进制是47455420

    4.11、抓SSH返回

    tcpdump -i eth1 ‘tcp[(tcp[12]>>2):4] = 0x5353482D’
    "SSH-"的十六进制是0x5353482D

    tcpdump -i eth1 ‘(tcp[(tcp[12]>>2):4] = 0x5353482D) and (tcp[((tcp[12]>>2)+4):2] = 0x312E)’
    抓老版本的SSH返回信息,如"SSH-1.99…"

    三、大叔注
    如果是为了查看数据内容,建议用tcpdump -s 0 -w filename把数据包都保存下来,然后用wireshark的Follow TCP Stream/Follow UDP Stream来查看整个会话的内容。

    -s 0是抓取完整数据包,否则默认只抓68字节。
    另外,用tcpflow也可以方便的获取TCP会话内容,支持tcpdump的各种表达式。

    3.1、UDP头
    0 7 8 15 16 23 24 31
    ±-------±-------±-------±-------+
    | Source | Destination |
    | Port | Port |
    ±-------±-------±-------±-------+
    | | |
    | Length | Checksum |
    ±-------±-------±-------±-------+
    | |
    | DATA … |
    ±----------------------------------+
    抓DNS请求数据
    tcpdump -i eth1 udp dst port 53
    3.2、其他
    -c参数对于运维人员来说也比较常用,因为流量比较大的服务器,靠人工CTRL+C还是抓的太多,甚至导致服务器宕机,于是可以用-c参数指定抓多少个包。

    time tcpdump -nn -i eth0 ‘tcp[tcpflags] = tcp-syn’ -c 10000 > /dev/null
    上面的命令计算抓10000个SYN包花费多少时间,可以判断访问量大概是多少。

    使用案例

    下面介绍一些tcpdump中过滤语句比较高级的用法
    想获取172.16.10.11和google.com之间建立TCP三次握手中带有SYN标记位的网络包.

    命令为:sudo tcpdump -i eth0 ‘host 172.16.0.11 andhost google.com and tcp[tcpflags]&tcp-syn!=0’ -c 3 -nn
    在这里插入图片描述
    上面的命令是不是看着有点晕的感觉。 是的。
    下面详细介相关知识。
    其实我们理解这种语法: proto [ expr : size] ,就不难理解上面的语句了。
    下面详细介绍proto [ expr : size]
    Proto即protocol的缩写,它表示这里要指定的是某种协议名称,如ip,tcp,udp等。总之可以指定的协议有十多种,如链路层协议 ether,fddi,tr,wlan,ppp,slip,link,
    网络层协议ip,ip6,arp,rarp,icmp传输层协议tcp,udp等。
    expr用来指定数据报字节单位的偏移量,该偏移量相对于指定的协议层,默认的起始位置是0;而size表示从偏移量的位置开始提取多少个字节,可以设置为1、2、4,默认为1字节。如果只设置了expr,而没有设置size,则默认提取1个字节。比如ip[2:2],就表示提取出第3、4个字节;而ip[0]则表示提取ip协议头的第一个字节。在我们提取了特定内容之后,我们就需要设置我们的过滤条件了,我们可用的“比较操作符”包括:>,<,>=,<=,=,!=,总共有6个。

    举例:想截取每个TCP会话的起始和结束报文(SYN 和 FIN 报文), 而且会话方中有一个远程主机.
    sudo tcpdump ‘tcp[13] & 3 != 0 and not(src and dst net 172.16.0.0)’ -nn
    如果熟悉tcp首部报文格式可以比较容易理解这句话,因为tcp便宜13字节的位置为2位保留位和6位标志位(URG,ACK,PSH,RST,SYN,FIN), 所以与3相与就可以得出SYN,FIN其中是否一个置位1.

    从上面可以看到在写过滤表达式时,需要我们对协议格式比较理解才能把表达式写对。这个比较有难度的…。为了让tcpdump工具更人性化一些,有一些常用的偏移量,可以通过一些名称来代替,比如icmptype表示ICMP协议的类型域、icmpcode表示ICMP的code域,tcpflags 则表示TCP协议的标志字段域。更进一步的,对于ICMP的类型域,可以用这些名称具体指代:icmp-echoreply, icmp-unreach, icmp-sourcequench, icmp-redirect,icmp-echo, icmp-routeradvert, icmp-routersolicit, icmp-timxceed, icmp-paramprob,icmp-tstamp, icmp-tstampreply, icmp-ireq, icmp-ireqreply, icmp-maskreq,icmp-maskreply。

    而对于TCP协议的标志字段域,则可以细分为tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-ack, tcp-urg。
    对于tcpdump 只能通过经常操作来熟练这些语句了。也可以把网络包用tcpdump截获保存到指定文件,然后用wireshark等可视化软件分析网络包。

    参考链接

    https://blog.csdn.net/hzhsan/article/details/43445787
    https://blog.csdn.net/wzx19840423/article/details/50836761

    展开全文
  • Python实现敏感词过滤的4种方法

    千次阅读 2020-12-17 11:23:12
    在我们生活中的一些场合经常会有一些不该出现的敏感词,我们通常会使用*去屏蔽...(我已经尽量把脏话做成图片的形式了,要不然文章发不出去)方法一:replace过滤replace就是最简单的字符串替换,当一串字符串中有可能...

    在我们生活中的一些场合经常会有一些不该出现的敏感词,我们通常会使用*去屏蔽它,例如:尼玛 -> **,一些骂人的敏感词和一些政治敏感词都不应该出现在一些公共场合中,这个时候我们就需要一定的手段去屏蔽这些敏感词。下面我来介绍一些简单版本的敏感词屏蔽的方法。

    (我已经尽量把脏话做成图片的形式了,要不然文章发不出去)

    方法一:replace过滤

    replace就是最简单的字符串替换,当一串字符串中有可能会出现的敏感词时,我们直接使用相应的replace方法用*替换出敏感词即可。

    缺点:

    文本和敏感词少的时候还可以,多的时候效率就比较差了

    import datetime

    now = datetime.datetime.now()

    print(filter_sentence, " | ", now)

    如果是多个敏感词可以用列表进行逐一替换

    for i in dirty:

    speak = speak.replace(i, '*')

    print(speak, " | ", now)

    方法二:正则表达式过滤

    正则表达式算是一个不错的匹配方法了,日常的查询中,机会都会用到正则表达式,包括我们的爬虫,也都是经常会使用到正则表达式的,在这里我们主要是使用“|”来进行匹配,“|”的意思是从多个目标字符串中选择一个进行匹配。写个简单的例子:

    import re

    def sentence_filter(keywords, text):

    return re.sub("|".join(keywords), "***", text)

    print(sentence_filter(dirty, speak))

    方法三:DFA过滤算法

    DFA的算法,即Deterministic Finite Automaton算法,翻译成中文就是确定有穷自动机算法。它的基本思想是基于状态转移来检索敏感词,只需要扫描一次待检测文本,就能对所有敏感词进行检测。(实现见代码注释)

    #!/usr/bin/env python

    # -*- coding:utf-8 -*-

    # @Time:2020/4/15 11:40

    # @Software:PyCharm

    # article_add: https://www.cnblogs.com/JentZhang/p/12718092.html

    __author__ = "JentZhang"

    import json

    MinMatchType = 1 # 最小匹配规则

    MaxMatchType = 2 # 最大匹配规则

    class DFAUtils(object):

    """

    DFA算法

    """

    def __init__(self, word_warehouse):

    """

    算法初始化

    :param word_warehouse:词库

    """

    # 词库

    self.root = dict()

    # 无意义词库,在检测中需要跳过的(这种无意义的词最后有个专门的地方维护,保存到数据库或者其他存储介质中)

    self.skip_root = [' ', '&', '!', '!', '@', '#', '$', '¥', '*', '^', '%', '?', '?', '', "《", '》']

    # 初始化词库

    for word in word_warehouse:

    self.add_word(word)

    def add_word(self, word):

    """

    添加词库

    :param word:

    :return:

    """

    now_node = self.root

    word_count = len(word)

    for i in range(word_count):

    char_str = word[i]

    if char_str in now_node.keys():

    # 如果存在该key,直接赋值,用于下一个循环获取

    now_node = now_node.get(word[i])

    now_node['is_end'] = False

    else:

    # 不存在则构建一个dict

    new_node = dict()

    if i == word_count - 1: # 最后一个

    new_node['is_end'] = True

    else: # 不是最后一个

    new_node['is_end'] = False

    now_node[char_str] = new_node

    now_node = new_node

    def check_match_word(self, txt, begin_index, match_type=MinMatchType):

    """

    检查文字中是否包含匹配的字符

    :param txt:待检测的文本

    :param begin_index: 调用getSensitiveWord时输入的参数,获取词语的上边界index

    :param match_type:匹配规则 1:最小匹配规则,2:最大匹配规则

    :return:如果存在,则返回匹配字符的长度,不存在返回0

    """

    flag = False

    match_flag_length = 0 # 匹配字符的长度

    now_map = self.root

    tmp_flag = 0 # 包括特殊字符的敏感词的长度

    for i in range(begin_index, len(txt)):

    word = txt[i]

    # 检测是否是特殊字符"

    if word in self.skip_root and len(now_map) < 100:

    # len(nowMap)<100 保证已经找到这个词的开头之后出现的特殊字符

    tmp_flag += 1

    continue

    # 获取指定key

    now_map = now_map.get(word)

    if now_map: # 存在,则判断是否为最后一个

    # 找到相应key,匹配标识+1

    match_flag_length += 1

    tmp_flag += 1

    # 如果为最后一个匹配规则,结束循环,返回匹配标识数

    if now_map.get("is_end"):

    # 结束标志位为true

    flag = True

    # 最小规则,直接返回,最大规则还需继续查找

    if match_type == MinMatchType:

    break

    else: # 不存在,直接返回

    break

    if tmp_flag < 2 or not flag: # 长度必须大于等于1,为词

    tmp_flag = 0

    return tmp_flag

    def get_match_word(self, txt, match_type=MinMatchType):

    """

    获取匹配到的词语

    :param txt:待检测的文本

    :param match_type:匹配规则 1:最小匹配规则,2:最大匹配规则

    :return:文字中的相匹配词

    """

    matched_word_list = list()

    for i in range(len(txt)): # 0---11

    length = self.check_match_word(txt, i, match_type)

    if length > 0:

    word = txt[i:i + length]

    matched_word_list.append(word)

    # i = i + length - 1

    return matched_word_list

    def is_contain(self, txt, match_type=MinMatchType):

    """

    判断文字是否包含敏感字符

    :param txt:待检测的文本

    :param match_type:匹配规则 1:最小匹配规则,2:最大匹配规则

    :return:若包含返回true,否则返回false

    """

    flag = False

    for i in range(len(txt)):

    match_flag = self.check_match_word(txt, i, match_type)

    if match_flag > 0:

    flag = True

    return flag

    def replace_match_word(self, txt, replace_char='*', match_type=MinMatchType):

    """

    替换匹配字符

    :param txt:待检测的文本

    :param replace_char:用于替换的字符,匹配的敏感词以字符逐个替换,如"你是大王八",敏感词"王八",替换字符*,替换结果"你是大**"

    :param match_type:匹配规则 1:最小匹配规则,2:最大匹配规则

    :return:替换敏感字字符后的文本

    """

    tuple_set = self.get_match_word(txt, match_type)

    word_set = [i for i in tuple_set]

    result_txt = ""

    if len(word_set) > 0: # 如果检测出了敏感词,则返回替换后的文本

    for word in word_set:

    replace_string = len(word) * replace_char

    txt = txt.replace(word, replace_string)

    result_txt = txt

    else: # 没有检测出敏感词,则返回原文本

    result_txt = txt

    return result_txt

    if __name__ == '__main__':

    dfa = DFAUtils(word_warehouse=word_warehouse)

    print('词库结构:', json.dumps(dfa.root, ensure_ascii=False))

    # 待检测的文本

    msg = msg

    print('是否包含:', dfa.is_contain(msg))

    print('相匹配的词:', dfa.get_match_word(msg))

    print('替换包含的词:', dfa.replace_match_word(msg))

    方法四:AC自动机

    AC自动机需要有前置知识:Trie树(简单介绍:又称前缀树,字典树,是用于快速处理字符串的问题,能做到快速查找到一些字符串上的信息。)

    详细参考:

    https://www.luogu.com.cn/blog/juruohyfhaha/trie-xue-xi-zong-jie

    ac自动机,就是在tire树的基础上,增加一个fail指针,如果当前点匹配失败,则将指针转移到fail指针指向的地方,这样就不用回溯,而可以路匹配下去了。

    详细匹配机制我在这里不过多赘述,关于AC自动机可以参考一下这篇文章:

    https://www.jb51.net/article/128711.htm

    python可以利用ahocorasick模块快速实现:

    # python3 -m pip install pyahocorasick

    import ahocorasick

    def build_actree(wordlist):

    actree = ahocorasick.Automaton()

    for index, word in enumerate(wordlist):

    actree.add_word(word, (index, word))

    actree.make_automaton()

    return actree

    if __name__ == '__main__':

    actree = build_actree(wordlist=wordlist)

    sent_cp = sent

    for i in actree.iter(sent):

    sent_cp = sent_cp.replace(i[1][1], "**")

    print("屏蔽词:",i[1][1])

    print("屏蔽结果:",sent_cp)

    当然,我们也可以手写一份AC自动机,具体参考:

    class TrieNode(object):

    __slots__ = ['value', 'next', 'fail', 'emit']

    def __init__(self, value):

    self.value = value

    self.next = dict()

    self.fail = None

    self.emit = None

    class AhoCorasic(object):

    __slots__ = ['_root']

    def __init__(self, words):

    self._root = AhoCorasic._build_trie(words)

    @staticmethod

    def _build_trie(words):

    assert isinstance(words, list) and words

    root = TrieNode('root')

    for word in words:

    node = root

    for c in word:

    if c not in node.next:

    node.next[c] = TrieNode(c)

    node = node.next[c]

    if not node.emit:

    node.emit = {word}

    else:

    node.emit.add(word)

    queue = []

    queue.insert(0, (root, None))

    while len(queue) > 0:

    node_parent = queue.pop()

    curr, parent = node_parent[0], node_parent[1]

    for sub in curr.next.itervalues():

    queue.insert(0, (sub, curr))

    if parent is None:

    continue

    elif parent is root:

    curr.fail = root

    else:

    fail = parent.fail

    while fail and curr.value not in fail.next:

    fail = fail.fail

    if fail:

    curr.fail = fail.next[curr.value]

    else:

    curr.fail = root

    return root

    def search(self, s):

    seq_list = []

    node = self._root

    for i, c in enumerate(s):

    matched = True

    while c not in node.next:

    if not node.fail:

    matched = False

    node = self._root

    break

    node = node.fail

    if not matched:

    continue

    node = node.next[c]

    if node.emit:

    for _ in node.emit:

    from_index = i + 1 - len(_)

    match_info = (from_index, _)

    seq_list.append(match_info)

    node = self._root

    return seq_list

    if __name__ == '__main__':

    aho = AhoCorasic(['foo', 'bar'])

    print aho.search('barfoothefoobarman')

    以上便是使用Python实现敏感词过滤的四种方法,前面两种方法比较简单,后面两种偏向算法,需要先了解算法具体实现的原理,之后代码就好懂了。(DFA作为比较常用的过滤手段,建议大家掌握一下~)

    最后附上敏感词词库:

    https://github.com/qloog/sensitive_words

    以上就是Python实现敏感词过滤的4种方法的详细内容,更多关于python 敏感词过滤的资料请关注随便开发网其它相关文章!

    展开全文
  • 常用四种大数据分析方法

    万次阅读 多人点赞 2017-09-19 09:32:13
    本文主要讲述数据挖掘分析领域中,最常用四种数据分析方法:描述型分析、诊断型分析、预测型分析和指令型分析。
  • 简单介绍AngularJS过滤器filter用法,每个都将列出用法代码以便加深了解; 内置过滤器: currency(货币)、date(日期)、filter(子串匹配)、json(格式化json对象)、limitTo(限制个数)、lowercase(小写)、...
  • 在推荐系统中常用的技术可大致分为四类:基于内容的过滤、协同过滤、基于规则的方法和混合方法。 一、基于内容过滤  基于内容过滤推荐系统思路如下:  (1)通过在抓取每个商品的一系列特征来构建商品档案;  ...
  • 浅谈SQL注入的四种防御方法

    千次阅读 2022-04-10 09:18:13
    1.限制数据类型 2.正则表达式匹配传入参数 3.函数过滤转义 4.预编译语句
  • 易语言-EXcel 过滤

    2021-06-29 16:18:21
    方法:一、用‘浏览’按钮打开要过滤的表格; 二、在‘设置’处可以选择已储存的常用设置,如果临时应用或没有相同的设置,可以新增设置并保存以便下次使用; 三、将表格中要过滤的列号(如:E)填入‘第一过滤列’...
  • whistle是基于Node实现的抓包调试工具,本文主要介绍 whistle 搜索过滤抓包数据功能,其它详细内容及用法参见 GitHub:github.com/avwo/whistl…whistle 提供了四种搜索及过滤抓包数据的方法,方便大家快速精确获取...
  • 创建JSONArray的常用四种方法

    万次阅读 2018-09-17 21:22:49
    创建JSONArray的常用四种方法  1.从头或者从零开始,创建一个JSONArray(Creating a JSONArray from scratch)  实例1:  Java代码  JSONArray jsonArray = new JSONArray().element("JSON").element(&...
  • java 文件过滤器的6实现方法

    千次阅读 2014-07-10 16:05:32
    注:运行环境 ... * 条件:java中有一个FilenameFilter的接口,能够过滤得到指定类型的文件或者目录,其中必须重写accept(File file,String path)方法  */ import java.io.File; import ja
  • WireShark常用过滤规则

    千次阅读 2021-11-16 15:49:27
    一、地址过滤 对源地址及目的地址过滤 ip.src == 192.168.0.1 ip.dst == 192.168.0.1 对源地址或者目的地址过滤 ip.addr == 192.168.0.1 排除某个地址数据包过滤 !(ip.addr == 192.168.0.1) 二、端口过滤 ...
  • 常用四种大数据分析方法

    千次阅读 2017-09-26 00:00:00
    本文主要讲述数据挖掘分析领域中,最常用四种数据分析方法:描述型分析、诊断型分析、预测型分析和指令型分析。 当刚涉足数据挖掘分析领域的分析师被问及,数据挖掘分析人员最重要的能力是什么时,他们给出了...
  • Spring Cloud Gateway过滤器(GatewayFilter)工厂
  • Spring中常见的全局过滤方式有三:Filter、Conterceptor、Aspect。 三者的执行顺序是:Filter > Conterceptor > Aspect。 Filter在请求到达具体的Controller之前执行,所以无法获取到Controller相关的数据,...
  • wireshark常用协议过滤

    千次阅读 2022-07-12 17:26:44
    wireshark常用协议过滤
  • VUE常用方法整理.pdf

    2020-03-28 22:56:18
    vue的常用方法总结 第一章 Vue核心知识讲解 5 第二节 引包、留坑、实例化 、插值表达式{{}} 5 1. 引包 5 2. 留坑 5 3. 实例化 5 4. 插值表达式{{ }} 5 第三节 熟悉及使用常用指令 5 1. 什么是指令 5 2. 常用的指令有...
  • 但是不同的是他有ruturn,每次循环后都会把本次循环的数据push到一个新数组newArr中,你可以在原数组的基础上做一些处理再赋值进去,不会影响到原数组 三:arr.filter过滤 filter方法的return只有两情况,true/...
  • 教你VUE中的filters过滤器2用法

    千次阅读 2022-04-02 09:46:57
    Vue.js 允许我们自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号({undefined{ }})插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,...
  • .Net 过滤

    千次阅读 2019-07-14 13:32:57
    .Net MVC 常用的4种过滤器:Action过滤器,Result过滤器, Exception过滤器,Authorization过滤器。本篇文章将详细介绍着四种过滤器,并用代码实现演示。
  • 数据挖掘分析方法划分为四种

    千次阅读 2019-04-24 11:09:47
     这是最常见的分析方法。在业务中,这种方法向数据分析师提供了重要指标和业务的衡量方法。 例如,每月的营收和损失账单。数据分析师可以通过这些账单,获取大量的客户数据。了解客户的地理信息,就是“描述型...
  • java过滤

    千次阅读 2021-03-05 19:13:38
    过滤器就是在源数据和目的数据之间起过滤作用的中间件。Web应用中,在处理请求时,经常有一些公共的工作,比如设置字符集。这样的工作需要写在每个页面,这样的写法费力且不好修改。使用过滤器就像在这些流程前加了...
  • 协同过滤算法(Collaborative Filtering) 是比较经典常用的推荐算法,它是一完全依赖用户和物品之间行为关系的推荐算法。我们从它的名字“协同过滤”中,也可以窥探到它背后的原理,就是 “协同大家的反馈、评价...
  • Pandas提供了多种API函数用于支持多种类型数据(如CSV、Excel、SQL等)的读写,其中常用的函数如下表所示。 文件类型 读取函数 写入函数 xls/xlsx read_excel to_excel CSV read_csv to_csv SQL read_...
  • 当刚涉足大数据挖掘分析领域的分析师被问及,大数据挖掘分析人员最重要的...简单地来说在大数据挖掘分析领域中,最常用四种大数据分析方法:描述型分析、诊断型分析、预测型分析和指令型分析。 一、大数据分析...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 204,138
精华内容 81,655
热门标签
关键字:

常用的四种过滤方法