Discussion:
TCP packets with RST flag set but **not** ACK flag OK??
Christian Seberino
2005-04-11 19:18:41 UTC
Permalink
I think RFC 793 requires TCP stacks to send RSTs if they
get packets not meant for them in some cases. Anyone know which
cases?

For example, I think closed ports must send RSTs if they
get stuff.

This is basis for bare FIN and Xmas tree scans IIRC.

Is this right??

Even if YES, it seems a firewall could drop any RSTs that
don't have ACK set without damage right?

Chris
Chris Brenton
2005-04-11 19:49:21 UTC
Permalink
Post by Christian Seberino
I think RFC 793 requires TCP stacks to send RSTs if they
get packets not meant for them in some cases. Anyone know which
cases?
Pretty much all. The exceptions I can think of off the top of my head:
In response to a RST
In response to a FIN to an open port (MS returns a RST/ACK)
Post by Christian Seberino
For example, I think closed ports must send RSTs if they
get stuff.
Agreed.
Post by Christian Seberino
Even if YES, it seems a firewall could drop any RSTs that
don't have ACK set without damage right?
The only condition I can think of off the top of my head that will
return a RST instead of a RST/ACK is in response to an unsolicited ACK
sent to either an open or closed port. So they do happen in the wild.

HTH,
Chris
Taylor, Grant
2005-04-11 21:57:11 UTC
Permalink
With out doing further reading (as you are reaching my limited knowledge of the TCP flags) I'm going to sate the following and then follow up after I've done some more reading. The TCP RST flag looks like it can be sent with out any other flags set in the packet in such a situation where there is no known on going connection as in "Hay buddy you need to stop and think about what you are doing!" which effectively closes any connection that was falsely open on one end or the other.

As to your question as to whether or not it is acceptable for firewalls to drop packets with just the RST packet set inbound to you? I'd say that you probably should not do that b/c the RST packet is a way to tell your TCP stack that it has done something wrong. This is akin to blocking ICMP error messages. But if you choose to do this there is nothing technically wrong with it that I can see, just sort of like shooting your self in the foot or bouncing a bounce email message stating that your email did not make it to John Doe. So if you would like to do it then by all means do it. I don't think I would do it unless I had a way to ensure that I was only dropping RST packets coming (back) to me that my firewall had not seen outbound to someone else. This is where connection tracking comes to mind. I would probably say something like the following:

iptables -t filter -A FORWARD -i $INet -o $LAN -d $LAN_Subnet -p tcp --tcp-flags RST RST -m state --state INVALID,NEW -m limit ! --limit 1/second -j LOG --log-prefix 'Bogus inbound false TCP packets with RST flag set more than one time per second!'
iptables -t filter -A FORWARD -i $INet -o $LAN -d $LAN_Subnet -p tcp --tcp-flags RST RST -m state --state INVALID,NEW -j DROP
iptables -t filter -A FORWARD -i $INet -o $LAN -d $LAN_Subnet -p tcp --tcp-flags RST RST -m state --state ESTABLISHED,RELATED -j ACCEPT

If I have what I think the states of the connections are correct in my head I would use the above lines to only accept packets with the RST flag set if I had already initiated a connection outbound to the source system. However if I had not initiated a connection then they should be drooped or rejected depending on your site policy (*1). Along the same lines I *might* be tempted to do the same thing on an outbound side of my firewall to my internal systems too. The following rules, very similar to above, would be what I would use to do that.

iptables -t filter -A FORWARD -i $LAN -o $INet -s $LAN_Subnet -p tcp --tcp-flags RST RST -m state --state INVALID,NEW -j DROP
iptables -t filter -A FORWARD -i $LAN -o $INet -s $LAN_Subnet -p tcp --tcp-flags RST RST -m state --state INVALID,NEW -j LOG --log-prefix 'Bogus outbound false TCP packets with the RST flag set!'
iptables -t filter -A FORWARD -i $LAN -o $INet -s $LAN_Subnet -p tcp --tcp-flags RST RST -m state --state ESTABLISHED,REALTED -j ACCEPT

(*1) If your organization would rather REJECT false / incorrect packets that come in to them than DROP then you would replace DROP with REJECT. This is an institutional political decision as some people feel that rejecting packets in some situations confirms your presence on the net vs just dropping them leaves the possible attacker wondering. I personally REJECT on the internal LAN and DROP on the INet connection.



Grant. . . .
Post by Christian Seberino
I think RFC 793 requires TCP stacks to send RSTs if they
get packets not meant for them in some cases. Anyone know which
cases?
For example, I think closed ports must send RSTs if they
get stuff.
This is basis for bare FIN and Xmas tree scans IIRC.
Is this right??
Even if YES, it seems a firewall could drop any RSTs that
don't have ACK set without damage right?
Chris
Chris Brenton
2005-04-12 00:36:54 UTC
Permalink
Post by Taylor, Grant
The TCP RST flag looks like it can be sent with out any other flags set in the packet in such a situation where there is no known on going connection
Actually, you are usually going to see ACK set as well as the RST flab
because the receiving system is acknowledging the receipt of the packet.
The except is in reply to a non-established packet with only ACK set.
The proper response here per the RFC's is RST only.
Post by Taylor, Grant
As to your question as to whether or not it is acceptable for firewalls to drop packets with just the RST packet set inbound to you? I'd say that you probably should not do that b/c the RST packet is a way to tell your TCP stack that it has done something wrong.
The receipt of these packets should be pretty rare. Off the top of my
head, one possible cause would be an established session where the
remote end gets power cycled. You ACK to continue communications and the
remote end sets RST only because it has no knowledge of the session
(because the original session gets cleared during the power cycle). If
you filter out in inbound RST, you system will fail to kill the session
till it times out and issues its own RST/ACK.
Post by Taylor, Grant
But if you choose to do this there is nothing technically wrong with it that I can see, just sort of like shooting your self
Agreed, nor is it really buying you anything. If you are maintaining
state Netfilter will dump the RST unless it matches the state table.
Post by Taylor, Grant
iptables -t filter -A FORWARD -i $INet -o $LAN -d $LAN_Subnet -p tcp --tcp-flags RST RST -m state --state INVALID,NEW -m limit ! --limit 1/second -j LOG --log-prefix 'Bogus inbound false TCP packets with RST flag set more than one time per second!'
iptables -t filter -A FORWARD -i $INet -o $LAN -d $LAN_Subnet -p tcp --tcp-flags RST RST -m state --state INVALID,NEW -j DROP
iptables -t filter -A FORWARD -i $INet -o $LAN -d $LAN_Subnet -p tcp --tcp-flags RST RST -m state --state ESTABLISHED,RELATED -j ACCEPT
Hummm. Not sure this is going to do anything. INVALID will be dropped
normally and a better way to deal with NEW is to mask on SYN in your
permit rules. ESTABLISHED should already be permitted as part of a
general permit rule of the state table.
Post by Taylor, Grant
This is an institutional political decision as some people feel that rejecting packets in some situations confirms your presence on the net vs just dropping them leaves the possible attacker wondering.
<semi-rant>
Actually, this is incorrect. Consider the following:
Port is open = SYN/ACK returned
Port is closed = RST/ACK returned
System down = ICMP type 3, code 1 returned
Net down = ICMP type 3, code 0 returned
Packet blocked = ICMP type 3, code 13 returned
Firewall with drop rule = nothing comes back

Note the *only* time you will see nothing coming back consistently is
when a firewall is in the way. So by dropping packets, you are
confirming the existence of a firewall. As an example, run nmap against
a firewall with a drop policy. It will actually report that a firewall
is in the way when nothing comes back. No head scratching required. ;-)

If you are looking to go stealthy, host unreachables (ICMP type 3, code
1) are a better choice. Now your firewall looks like a simple up stream
router with no filtering in place.

Now, a drop policy does have some benefits. For example it will slow
down a port scanner as the scanner tries to determine if its packets are
getting lost or if there is a firewall in the way. However a default
drop policy also has its drawbacks in that it returns nothing makes the
address space far more appealing to an attacker to spoof as part of a
TCP SYN flood attack (no response from your network allows them to tie
up the connection pool for a longer period of time on the victim's
system). So by implementing a default drop rule you are actually helping
the attacker perform a successful flood. This one of the reasons why the
RFC's define dropping packets as "A Bad Idea" (TM). See RFC 1812 for
more details.
</semi-rant>

HTH,
Chris
Grant Taylor
2005-04-12 02:32:52 UTC
Permalink
Post by Chris Brenton
<semi-rant>
Port is open = SYN/ACK returned
Port is closed = RST/ACK returned
System down = ICMP type 3, code 1 returned
Net down = ICMP type 3, code 0 returned
Packet blocked = ICMP type 3, code 13 returned
Firewall with drop rule = nothing comes back
Note the *only* time you will see nothing coming back consistently is
when a firewall is in the way. So by dropping packets, you are
confirming the existence of a firewall. As an example, run nmap against
a firewall with a drop policy. It will actually report that a firewall
is in the way when nothing comes back. No head scratching required. ;-)
If you are looking to go stealthy, host unreachables (ICMP type 3, code
1) are a better choice. Now your firewall looks like a simple up stream
router with no filtering in place.
Now, a drop policy does have some benefits. For example it will slow
down a port scanner as the scanner tries to determine if its packets are
getting lost or if there is a firewall in the way. However a default
drop policy also has its drawbacks in that it returns nothing makes the
address space far more appealing to an attacker to spoof as part of a
TCP SYN flood attack (no response from your network allows them to tie
up the connection pool for a longer period of time on the victim's
system). So by implementing a default drop rule you are actually helping
the attacker perform a successful flood. This one of the reasons why the
RFC's define dropping packets as "A Bad Idea" (TM). See RFC 1812 for
more details.
</semi-rant>
Hmm, I will probably have to modify my firewall scripts to send back ICMP 3/1 (-j REJECT --reject-with icmp-host-unreacahbel) Responses in this case.

One reason that some institutions decide to DROP verses REJECT is so that someone can not spoof their source IP while performing some sort of attack on the institutions system expecting the REJECT to go to the spoofed source IP thus becoming part of what I think is considered a reflected attack. Some people / institutions say yes to dropping and no to rejecting while others say no to dropping and yes to rejecting.

These issues and many more like them are some of the things that I would like to spend some more time reading about and gaining a better understanding than I presently have. But alas I don't have the time for it unless I make it and at the moment other thing(s) (Asterisk) are higher on my priority list. Though now that you have said something I may have to go do some RFC reading while I'm on the thinking stool.



Grant. . . .
Chris Brenton
2005-04-12 04:06:59 UTC
Permalink
Post by Grant Taylor
One reason that some institutions decide to DROP verses REJECT is so that someone can not spoof their source IP while performing some sort of attack
I don't think I quite follow what you are saying. I'm not sure how using
drop or reject would have any effect on someone's ability to use your
address space as the source IP in a spoofed packet.
Post by Grant Taylor
the institutions system expecting the REJECT to go to the spoofed source IP thus becoming part of what I think is considered a reflected attack.
If I follow what you are saying here, the concern is the returning ICMP
host unreachables may be used as part of a DoS. Is this correct?

If so, the concern is pretty minimal. Packet size is small, only 56
bytes in size, so bandwidth utilization is small. Unsolicited ICMP
errors are going to be quickly discarded by the receiving system, so its
not going to cause much of a CPU hit on the target. Unfortunately there
are far too many other ways of performing a DoS that would be much more
effective and efficient.
Post by Grant Taylor
These issues and many more like them are some of the things that I would like to spend some more time reading about and gaining a better understanding
Ya, geek stuff is cool. :D

Chris
Taylor Grant
2005-04-12 04:01:31 UTC
Permalink
Post by Chris Brenton
If I follow what you are saying here, the concern is the returning ICMP
host unreachables may be used as part of a DoS. Is this correct?
Yes, you are following me there.
Post by Chris Brenton
If so, the concern is pretty minimal. Packet size is small, only 56
bytes in size, so bandwidth utilization is small. Unsolicited ICMP
errors are going to be quickly discarded by the receiving system, so its
not going to cause much of a CPU hit on the target. Unfortunately there
are far too many other ways of performing a DoS that would be much more
effective and efficient.
*nod* I'm not saying that it's one of the most efficient ways to DDoS someone, but I am saying that it is a way and some institutions politically decide that they would rather DROP packets than possibly participate in a DDoS against someone else.
Post by Chris Brenton
Ya, geek stuff is cool. :D
It has gotten me in to trouble too. I tend to spend too much time working on geek stuff. Oh, well I had fun doing it.



Grant. . . .
Taylor Grant
2005-04-12 07:24:11 UTC
Permalink
In short, deciding if the ACK and RST flags to together or not is about like deciphering the English language.

Referencing section 3.9 subsection "Segment Arrives" I've found the following to be true.

Suffice it to say that the logic to this is extremely complex and in depth and thus is rather hard to make a generalized statement about. Also keep in mind that the RFC is talking about things from the opposite direction. Thus my determination is as follows:

If you have sent out a packet with the ACK flag set any corresponding packets with RST flags in them will not hav their ACK flag set. However if you have sent out a packet with out the ACK flag set any corresponding packets with the RST flag in them will have their ACK flag set.

Thus I could argue that you could use the following IPTables rules to drop (or reject with ICMP host unreachable error message(s)) an illegitament TCP packets with the RST flag set.

iptables -t filter -A FORWARD -i $LAN -o $INet -p tcp --tcp-flags ! ACK ACK -m recent --set --rsource --name TCP_ACK_flag_not_set --seconds 60 -j ACCEPT
iptables -t filter -A FORWARD -i $INet -o $LAN -p tcp --tcp-flags ACK,RST ACK,RST -m recent --rcheck --rdest --name TCP_ACK_flag_not_set -j ACCEPT
iptables -t filter -A FORWARD -i $INet -o $LAN -p tcp --tcp-flags ACK,RST ACK,RST -j REJECT --reject-with icmp-host-unreachable

iptables -t filter -A FORWARD -i $LAN -o $INet -p tcp --tcp-flags ACK ACK -m recent --set --rsource --name TCP_ACK_flag_not_set --seconds 60 -j ACCEPT
iptables -t filter -A FORWARD -i $INet -o $LAN -p tcp --tcp-flags ACK,RST RST -m recent --rcheck --rdest --name TCP_ACK_flag_not_set -j ACCEPT
iptables -t filter -A FORWARD -i $INet -o $LAN -p tcp --tcp-flags ACK,RST RST -j REJECT --reject-with icmp-host-unreachable

Now what I think these rules are doing is remembering, via recent match --set, packets that are going outbound with out the ACK flag set to allow corresponding packets back in if the ACK and RST flags are set. Conversely these rules also remember (via recent match --set) packets that are going outbound with the ACK flag set to allow corresponding packets back in if the RST flag is and the ACK flag is not set. Thus in agreement with what I think I found by reading section 3.9 subsection "Segment Arrives". This is after many an hour of trying to decipher the ACK, RST flags relation to each other and I am prone to messing things up. So take it for what it is worth. This is ALL THEORETICAL and UNTESTED. I will have to do that at a later point in time.

One additional point of interest is that I tend to jump out of my filter:FORWARD chain in to sub chains to run my tests and execute a RETURN if I match the rule that way I can have what ever default action I want at the bottom of my subchain. This will also allow me to have much more complex conditionals that have to be meat. You know what subroutines are for in your programs right? Well let's do it to our firewall too. Make a subchain to check source IPs against non routable reserved IPs and the likes for destinations. It's a simple matter of calling the chains in the proper order to have traffic go where you want with out replication of IPTables rules, code.



Grant. . . .
Chris Brenton
2005-04-12 14:41:57 UTC
Permalink
Post by Taylor Grant
In short, deciding if the ACK and RST flags to together or not is about like deciphering the English language.
Luckily I speak native English and Hex. ;-) Try this:

In one terminal window run:
tcpdump -nn -v -i lo

In another terminal window run:
hping -A -c 1 -p 5 127.0.0.1
hping -S -c 1 -p 5 127.0.0.1

You'll see the first packet causes a RST only to be returned. The second
will cause a RST/ACK to be returned. So either condition is a
possibility and a Netfilter rule base needs to handle both of them
appropriately.

HTH,
Chris

Taylor Grant
2005-04-12 04:22:02 UTC
Permalink
Post by Chris Brenton
RFC's define dropping packets as "A Bad Idea" (TM). See RFC 1812 for
more details.
Are you sure that it's RFC 1812 "Requirements for IP Version 4 Routers"? I'm finding more information in RFC 793 "Transmission Control Protocol Functional Specification". Namely it is possible to see packets with the RST flag both with ACK set and ACK unset, depending on the situation. Primarily having to do with what state the TCP conversation is in, established or not.

According to the "Half-Open Connections and Other Anomalies" section of RFC 793 the following seems to be the case. Half-Open Connections are defined as follows, per RFC. Half-Open Connections are defined as one end of the TCP conversation having closed the connection while the other still has it open. Here is the text from the RFC, "An established connection is said to be "half-open" if one of the TCPs has closed or aborted the connection at its end without the knowledge of the other, or if the two ends of the connection have become desynchronized owing to a crash that resulted in loss of memory.".

(Sorry, this could get rather lengthy.)

<RFC 793 - Half-Open Connections - paragraph 3>
...In an attempt to establish the connection, A's TCP will send a segment containing SYN. This scenario leads to the example shown in figure 10. After TCP A crashes, the user attempts to re-open the connection. TCP B, in the meantime, thinks the connection is open.

TCP A TCP B

1. (CRASH) (send 300,receive 100)

2. CLOSED ESTABLISHED

3. SYN-SENT --> <SEQ=400><CTL=SYN> --> (??)

4. (!!) <-- <SEQ=300><ACK=100><CTL=ACK> <-- ESTABLISHED

5. SYN-SENT --> <SEQ=100><CTL=RST> --> (Abort!!)

6. SYN-SENT CLOSED

7. SYN-SENT --> <SEQ=400><CTL=SYN> -->

Half-Open Connection Discovery

Figure 10.

When the SYN arrives at line 3, TCP B, being in a synchronized state,
and the incoming segment outside the window, responds with an
acknowledgment indicating what sequence it next expects to hear (ACK
100). TCP A sees that this segment does not acknowledge anything it
sent and, being unsynchronized, sends a reset (RST) because it has
detected a half-open connection. TCP B aborts at line 5. TCP A will
continue to try to establish the connection; the problem is now
reduced to the basic 3-way handshake of figure 7.

An interesting alternative case occurs when TCP A crashes and TCP B
tries to send data on what it thinks is a synchronized connection.
This is illustrated in figure 11. In this case, the data arriving at
TCP A from TCP B (line 2) is unacceptable because no such connection
exists, so TCP A sends a RST. The RST is acceptable so TCP B
processes it and aborts the connection.



TCP A TCP B

1. (CRASH) (send 300,receive 100)

2. (??) <-- <SEQ=300><ACK=100><DATA=10><CTL=ACK> <-- ESTABLISHED

3. --> <SEQ=100><CTL=RST> --> (ABORT!!)

Active Side Causes Half-Open Connection Discovery

Figure 11.

In figure 12, we find the two TCPs A and B with passive connections
waiting for SYN. An old duplicate arriving at TCP B (line 2) stirs B
into action. A SYN-ACK is returned (line 3) and causes TCP A to
generate a RST (the ACK in line 3 is not acceptable). TCP B accepts
the reset and returns to its passive LISTEN state.



TCP A TCP B

1. LISTEN LISTEN

2. ... <SEQ=Z><CTL=SYN> --> SYN-RECEIVED

3. (??) <-- <SEQ=X><ACK=Z+1><CTL=SYN,ACK> <-- SYN-RECEIVED

4. --> <SEQ=Z+1><CTL=RST> --> (return to LISTEN!)

5. LISTEN LISTEN

Old Duplicate SYN Initiates a Reset on two Passive Sockets

Figure 12.
Loading...