A system’s security should be tested frequently to ensure that it functions the way it’s intended. This article will demonstrate how to test firewall rules by utilizing hping3 to craft packets and check the target’s responses using tcpdump. Section 1 will begin by showing examples of how a host will respond to different probes. In section 2, we will equip the host with a few firewall rules intended to stop unnecessary responses, and use hping3 to ensure the rules function as expected. Whether setting up a new firewall or testing one already in place, this article will show how to use hping3 to possibly find configuration issues that may have otherwise been missed.
What is hping3?
hping3 is a command-line oriented network tool that allows for assembling and analyzing packets. The construction of customized packets allows the user to perform numerous actions such as: port scanning, firewall testing, network performance testing, and traceroute to name a few. One of the main upgrades from hping2 to hping3 is the implementation of Tcl scripting. If you’re willing to take the time to learn Tcl programming, it allows for more functionality and customization, but the standard commands should be enough for most users, and will be used in this article.
Testing Firewall Rules – Part 1:
Hping3 by default (using no options) sends a null packet with a TCP header to port 0. You can select to use a different protocol by using the numeric option available for each:
Since hping3 uses TCP by default, the absence of the options below will send a TCP segment. When using TCP, we can decide to either omit flags (default), or set a flag using one of the following options:
In the following examples we will be using TCP, UDP, and ICMP. In this first half, we are going to craft packets to test how a system would respond by default. This will give an idea of the numerous amount of data we simply do not need to allow through.
First off, we are going to send a simple PING (ICMP Echo Request) packet to our target.
The –1 in this command tells hping3 to use ICMP, which by default sends an Echo Reply.
The -c 1 states that we only want to send 1 packet, and the 10.0.0.4 is our target. From the command output we see that 1 packet was sent and received. Now, let’s check the response in the tcpdump output.
We can see from this tcpdump output confirms that the command did send an ICMP Echo Request, and our target replied with the appropriate ICMP Echo Reply. From the first packet sent, we can already tell that our target is alive.
SYN, Port 0
Now let’s send another packet and watch how the target responds. This time we will send a TCP header marked with the SYN flag to port 0.
As stated before, the -S marks the SYN flag in our TCP header. We also see a new option here, -s 5151, which chooses a source port to use. Without this option, hping3 would simply choose a random source port. Since port 0 isn’t open, we see a RST-ACK response (marked in the output.) Later we will see how the target will respond to a SYN packet destined for an open port.
Just as expected, the output shows the packet was sent using source port 5151 to our target at port 0 with the SYN flag set. Below that, we can see the Flags [R.] set, and we also have an ‘ack‘ in the output.
Many resources will state that a ‘.’ in the tcpdump output marks the ACK flag, but this is simply incorrect. In the tcpdump flags field, we have 7 options available: S (SYN), F (FIN), P(PUSH), R (RST), W (ECN CWR), E (ECN-Echo) and a ‘.’ (no flags). When the output displays [.], it means that the TCP header does not have a flag set. When combined with another flag, the ‘.’ shows a flag present that is not one of the available options. In many cases, a following ‘.’ will be an ACK flag, but this can only be confirmed by ‘ack‘ in the output.
FIN, Port 0
We are going to send an identical packet, except this time with the FIN flag set.
The only thing we did differently in this command is change the -S to a -F. Again, we have a response. Since this port is closed, we should see the same response as if we sent a SYN packet.
As we should, we see the same RST-ACK response as before, marked by [R.] and ‘ack‘.
SYN, Port 80
In the previous examples we’ve been sending packets to port 0. Now we’ll test a well-known port, port 80 (http). Since SYN is the first step in the three-way handshake of a TCP connection (SYN, SYN-ACK, ACK), if the port is open, we would receive the proper SYN-ACK response due to the target attempting to complete the connection. This is a popular technique used in port-scanning known as a “half-open connection”.
All of these options should look familiar, with the exception of -p 80. This simply specifies the destination port to set in our TCP header. We see that our target has responded, and the output shows “flags=SA” confirming that we have received a SYN-ACK packet .
Since our target responded with a SYN-ACK (marked by [S.] and ‘ack‘), we know that our target’s port 80 is open and accepting connections. Otherwise, we would see [R.] like in our previous packet SYN packet sent to port 0.
ACK, Port 80
We now know that port 80 is open on our target, so let’s see how if and how it responds to different packets. We saw in the last example that when we send a SYN packet to an open port, we receive a SYN-ACK. Let’s see what kind of response we get when we send an ACK packet (the final part of the three-way handshake).
Our target responded, but this time with the RST flag set.
Our tcpdump output shows the packet sent marked with [.] The following ack clarifies that this is an ACK flag. The output also shows the target’s response with a RST packet.
UDP, Port 80
We are gonna send one last packet to our target to see if we get a response. Since port 80 uses TCP as it’s transport layer protocol, it should be interesting to see what kind of response we get when we send it a UDP packet.
By using -2 in this command, we specify to use UDP as our transport layer protocol. We can see in the output that we got ICMP Port Unreachable response, due to that port not being open for UDP traffic. Our tcpdump output would show this same information.
Testing Firewall Rules – Part 2:
In the first section, we saw how a system would respond to different packets by default.
In this section we will see how just a few firewall rules can make a huge difference in our target’s responses. You should deny anything you’re not certain that you need open, and insert rules for anything you need open later. We want to allow only the packets through that are necessary, and deny anything else. Since the only port needed to allow new connections is port 80 using TCP, we will want to drop all other packets to stop the host from responding to them. If configured properly, the firewall on the target we’ve been using shouldn’t respond to anything aside form a SYN packet to port 80.
This can be accomplished by a few iptables commands.
Rule 1: Drop any TCP packet that is starting a new connection and IS NOT marked by a SYN flag
Rule 2: Accept any TCP packet destined for port 80 at 10.0.0.4
Rule 3: Accept any TCP packet that is related to or part of an established connection
Rule 4: Drop all packets
Shown below is the iptables configuration.
This is just a simple example of inbound policies that takes care of the issues from part 1. With this configuration, the target will only respond to TCP packets destined for port 80. Now, let’s take a few of the same commands from before and see how our target responds equipped with these rules.
In part 1 we received an ICMP echo reply, but we can see in our output that this packet has now been dropped. Since this is not a TCP header, the firewall will not respond.
SYN, Port 80
Since the only new connection we need to allow is through TCP on port 80, let’s test the firewall to make sure we still get a response.
As it should, the firewall is still allowing the packet through and giving us a response with an SYN-ACK packet. Due to the first rule in the iptables configuration, if this packet was marked with any other flag it wouldn’t be allowed through since it is the first packet in the new connection.
UDP, Port 80
So far with the iptables configuration we’ve seen that ICMP packets are dropped, and that we can still successfully start a new connection through TCP on port 80. Now for our last packet, let’s test to make sure that our rules work correctly for not allowing any other packets through on port 80.
Here we’ve sent a UDP packet to port 80. Even though port 80 uses TCP as it’s transport layer protocol, in part 1 we actually got a response with an ICMP Port Unreachable. If the packet were to make it through the firewall we would see the same response. Since there was no response, we know the packet was dropped. We have successfully tested a host, setup rules to correct issues we’ve found, and retested for proper functionality.
This article has shown how you should expect a host to respond to various packets, and how to test new firewall rules for differences in those responses. The firewall example should not be copied and used on any system. Instead, assess your system and network needs, and apply security to meet those needs. Once applied, test your security and test it frequently to identify and make any needed changes and additions.