Connect scanning with Scapy

Let's perform the following steps to run the connect scan with Scapy:

  1. It can be difficult to run a full connect scan with Scapy because the system kernel remains unaware of your packet meddling with Scapy and attempts to prevent you from establishing a full three-way handshake with the remote system.
  2. You can see this activity in action by sending a SYN request and sniffing the associated traffic with Wireshark or TCP dump.
  3. When you receive a SYN+ACK response from the remote system, the Linux kernel will interpret it as an unsolicited response because it remains unaware of your request made in Scapy, and the system will automatically respond with a TCP RST packet, thereby discontinuing the handshake process. Consider the following example:
        #!/usr/bin/python

import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

response = sr1(IP(dst="172.16.69.128")/TCP(dport=80,flags='S'))
reply = sr1(IP(dst="172.16.69.128")
/TCP(dport=80,flags='A',ack=(response[TCP].seq + 1)))
  1. This Python script can be used as a proof of concept to demonstrate the problem of the system breaking the three-way handshake. The script assumes that you are directing it toward a live system with an open port and therefore assumes that a SYN+ACK reply will be returned in response to the initial SYN request. Even though the final ACK reply is sent to complete the handshake, the RST packet prevents the connection from being established.
  2. We can demonstrate this further by viewing the packets being sent and received:
        #!/usr/bin/python

import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

SYN = IP(dst="172.16.69.128")/TCP(dport=80,flags='S')

print "-- SENT --"
SYN.display()

print "nn-- RECEIVED --"
response = sr1(SYN,timeout=1,verbose=0)
response.display()

if int(response[TCP].flags) == 18:
print "nn-- SENT --"
ACK = IP(dst="172.16.69.128")/
TCP(dport=80,flags='A',ack=(response[TCP].seq + 1))
response2 = sr1(ACK,timeout=1,verbose=0)
ACK.display()
print "nn-- RECEIVED --"
response2.display()
else:
print "SYN-ACK not returned"
  1. In this Python script, each sent packet is displayed prior to transmission, and each received packet is displayed when it arrives. On examining the TCP flags that are activated in each packet, it becomes clear that the three-way handshake has failed. Consider the output that is generated by the script:
  1. In the output from the script, four packets can be seen. The first packet is the sent SYN request, the second packet is the received SYN+ACK reply, the third packet is the sent ACK reply, and an RST packet is then received in response to the final ACK reply. It is this final packet that indicates that a problem was encountered when establishing the connection. It is possible to perform a full three-way handshake with Scapy, but it requires some tampering with the local iptables on the system. Specifically, you can only complete the handshake if you suppress the RST packets that are sent to the remote system that you are trying to connect with. By establishing a filtering rule using iptables, it is possible to drop the RST packets to complete the three-way handshake without interference from the system (this configuration is not recommended for continued functional usage).
  2. To demonstrate the successful completion of the full three-way handshake, we establish a listening TCP service using Netcat and then attempt to connect to the open socket using Scapy:
  1. In the example provided, a listening service was opened on the TCP port 4444. We can then modify the script that was discussed previously to attempt to connect to the Netcat TCP service on the port 4444, as follows:
        #!/usr/bin/python

import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

response = sr1(IP(dst="172.16.36.135")/
TCP(dport=4444,flags='S'))
reply = sr1(IP(dst="172.16.36.135")/
TCP(dport=4444,flags='A',ack=(response[TCP].seq + 1)))
  1. In this script, a SYN request was sent to the listening port, and then an ACK reply was sent in response to the anticipated SYN+ACK reply. To validate that the connection attempt is still interrupted by a system-generated RST packet, this script should be executed while Wireshark is being run to capture the request sequence.
  1. We apply a filter to Wireshark to isolate the connection attempt sequence. The filter used was tcp && (ip.src == 172.16.69.128 || ip.dst == 172.16.69.128). This filter is used to only display the TCP traffic going to or from the system being scanned. This is shown in the following screenshot:
  1. Now that we have identified the exact problem, we can establish a filter that will allow us to suppress this system-generated RST response. This filter can be established by modifying the local iptables, as follows:
Modifying the local iptables in the following manner will impair the way your system handles the TCP/IP transactions with the destination system by blocking all outbound RST responses. Ensure that the created iptables rule is removed upon completion of this recipe, or flush the iptables afterward with the following command: iptables --flush.
  1. In the example provided, the local iptables were modified to suppress all TCP RST packets going to the destination address of our scanned host. The --list option can then be used to view the iptable entries and verify that a configuration change has been made. To perform another connection attempt, we need to ensure that Netcat is still listening on the port 4444 of our target, as follows:
  1. The same Python script that was introduced previously should be run again, with Wireshark capturing the traffic in the background. Using the previously discussed display filter, we can easily focus on the traffic we need. Note that all of the steps of the three-way handshake have now been completed without any interruption by system-generated RST packets, as shown in the following screenshot:
  1. Additionally, if we take a look at our Netcat service, which is running on the target system, we notice that a connection has been established. This is further evidence to confirm that a successful connection was established. 
  2. While this is a useful exercise to understand and troubleshoot TCP connections, it is important not to leave the iptable entry in place. RST packets are an important component of TCP communications, and suppressing these responses altogether can drastically impair proper communication functionality. The following commands can be used to flush our iptables rules and verify that the flush was successful:
  1. As is demonstrated in the example provided, the --flush option should be used to clear the iptable entries that were made. We can verify that the iptable entries have been removed using the --list option one more time.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset