在第一种场景中,我们应该考虑 SYN 请求没有响应,ACK 请求收到 RST 响应的配置。为了测试它,我们首先应该发送 TCP ACK 封包给目标端口。为了发送 TCP ACK 封包给任何给定的端口,我们首先必须构建请求的层级,我们首先需要构建 IP 层:
```
root@KaliLinux:~# scapy Welcome to Scapy (2.2.0)
>>> i = IP()
>>> i.display()
###[ IP ]###
version= 4
ihl= None
tos= 0x0
len= None
id= 1
flags=
frag= 0
ttl= 64
proto= ip
chksum= None
src= 127.0.0.1
dst= 127.0.0.1
\options\
>>> i.dst = "172.16.36.135"
>>> i.display()
###[ IP ]###
version= 4
ihl= None
tos= 0x0
len= None
id= 1
flags=
frag= 0
ttl= 64
proto= ip
chksum= None
src= 172.16.36.180
dst= 172.16.36.135
\options\
```
为了构建请求的 IP 层,我们需要将`IP`对象赋给变量`i`。通过调用`display`函数,我们可以确定对象的属性配置。通常,发送和接受地址都设为回送地址,`127.0.0.1`。这些值可以通过修改目标地址来修改,也就是设置`i.dst`为想要扫描的地址的字符串值。通过再次调用`dislay`函数,我们看到不仅仅更新的目标地址,也自动更新了和默认接口相关的源 IP 地址。现在我们构建了请求的 IP 层,我们可以构建 TCP 层了。
```
>>> t = TCP()
>>> t.display()
###[ TCP ]###
sport= ftp_data
dport= http
seq= 0
ack= 0
dataofs= None
reserved= 0
flags= S
window= 8192
chksum= None
urgptr= 0
options= {}
>>> t.dport = 22
>>> t.flags = 'A'
>>> t.display()
###[ TCP ]###
sport= ftp_data
dport= ssh
seq= 0
ack= 0
dataofs= None
reserved= 0
flags= A
window= 8192
chksum= None
urgptr= 0
options= {}
```
为了构建请求的 TCP 层,我们使用和 IP 层相同的技巧。在这个立即中,`TCP`对象赋给了`t`变量。像之前提到的那样,默认的配置可以通过调用`display`函数来确定。这里我们可以看到目标端口的默认值为 HTTP 端口 80。对于我们的首次扫描,我们将 TCP 设置保留默认。现在我们创建了 TCP 和 IP 层,我们需要将它们叠放来构造请求。
```
>>> request = (i/t)
>>> request.display()
###[ IP ]###
version= 4
ihl= None
tos= 0x0
len= None
id= 1
flags=
frag= 0
ttl= 64
proto= tcp
chksum= None
src= 172.16.36.180
dst= 172.16.36.135
\options\
###[ TCP ]###
sport= ftp_data
dport= ssh
seq= 0
ack= 0
dataofs= None
reserved= 0
flags= A
window= 8192
chksum= None
urgptr= 0
options= {}
```
我们可以通过以斜杠分离变量来叠放 IP 和 TCP 层。这些层面之后赋给了新的变量,它代表整个请求。我们之后可以调用`dispaly`函数来查看请求的配置。一旦构建了请求,可以将其传递给`sr1`函数来分析响应:
```
>>> response = sr1(request,timeout=1)
..Begin emission:
.........Finished to send 1 packets.
....*
Received 16 packets, got 1 answers, remaining 0 packets
>>> if (ACK_response == None) and (SYN_response == None):
... print "Port is either unstatefully filtered or host is down"
... Port is either unstatefully filtered or host is down
```
这个完成的测试序列之后可以集成到单个功能性脚本中。这个脚本接受两个参数,包括目标 IP 地址和被测试的端口。之后注入 ACK 和 SYN 封包,如果存在响应,响应会储存用于评估。之后执行四个测试来判断是否端口上存在过滤。一开始,会执行测试来判断是否没有受到任何响应。如果是这样,输出会表示远程主机崩溃了,或者端口存在无状态过滤,并丢弃所有流量。如果接收到了任何请求,会执行测试来判断是否接受到了某个注入的响应,而不是全部。如果是这样,输出会表明端口存在状态过滤。最后如果两个注入都接受到了响应,端口会被识别为物过滤,并且会评估 TCP 标志位来判断端口开放还是关闭。