Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
How does a TCP Reset Attack work? (robertheaton.com)
127 points by domrdy on April 28, 2020 | hide | past | favorite | 25 comments


GFW rarely adds any new RST rules today, largely because most traffic are encrypted with TLS and it's useless to sniff on port 443 with RST attacks. They just blackhole the IP range completely with Cisco NetFlow if anything is suspicious


Yes, I think most DPIs and Firewalls these days terminate the connections after the ClientHello message which contains the SNI


Companies are dragging their feet with encrypted SNI


Encrypted SNI still has a few years to go before it's deployed. Meanwhile, the Great Firewall continues to block TLS connections with an unwanted SNI via a TCP Reset attack. "news.ycombinator.com is on the list, too.


I mean if we get ESNI faster, the GFW is going to have a hard time keeping up. What do you even do at that point? Just block every CDN?


My opinion is that it's basically a mutually assured destruction game. Either the censor blocks everything and creates significant damages to the national economy and popular support, or it has to allow free access to these websites. I'm optimistic, and to me, both outcomes are good outcomes. I support these aggressive industrial efforts to increase security. Free access is the most desirable result, but a complete block is not really a big issue - it cannot last forever, and the collateral damage will force the censor to eventually back off.

But there are some potential issues. One problem is the assumption that MAD as a forever-lasting situation may be flawed. In the Telegram incident in Russia, the Russian government literally blocked all Amazon servers and created massive disruption, however, Amazon also suffered economic damaged so it surrendered first before the Russian government backed off, and blocked the domain-fronting technique used for censorship circumvention. It's a way that the plan can fail. So the key to a successful ESNI deployment depending on the fact that cloud providers will never surrender after they received a total block.

Another argument says the possibility to bypass censorship is ultimately a dynamic balance - on one hand, the Great Firewall has loophope that allow circumvention, on the other hand, it's effective enough that the censor lack an incentive to implement stricter control. By introducing aggressive web security measures, this balance will be broken. As a result, an process to implement stricter censorship that would take 5 years otherwise, will instead take 2 years, and the result is a net negative, thus it's a terrible idea.

I maintain my own opinion, but I do find these are interesting and persuasive arguments.


I was affected by this sort of interference in the UK when using T-Mobile about 8 years ago. I blogged it up with a solution related to dropping RST packets:

https://www.grepular.com/Punching_through_The_Great_Firewall...


When I'm port scanning my own server through my mobile operator (Bouygues Telecom), I see ports that are open that I know are NOT open on the server. Could it be interception tentatives ? Is there any reason to mascard them as open if they are not ?

Ports that are NOT supposed to be open : 21, 53, 554, 1723


Can you actually fully connect to those ports from the outside? I recently moved to somewhere that is using Virgin Media broadband in the UK, and I noticed that when running "masscan" against my home IP from outside, it started finding ports that weren't actually open.

On closer inspection it seems that either the router or the ISP has some sort of threshold over which it starts responding to all SYN's with SYN-ACK's, completing the second step of the three way TCP handshake. I assume it's some sort of port scanning interference system.


The article starts with GFW and then goes onto RST packet validation.It's great to see people re-learning the classics. Awesome! Extra points for using "scapy".

The injected RST are often easy to drop once you know what you are looking for. For example Netsweeper RST was easy to spot. In past I caught them with simple tcpdump looking for window size=4096. It worked well "tcp[tcpflags] = (tcp-ack|tcp-push|tcp-fin) and tcp[14:2]=4096"

Anyhow, with L3 RST injection systems it's easy to abuse them. For example - they don't have rate limits usually and they don't verify IP's. By sending a spoofed packet in the direction of such netsweeper / GFW you might be able to trick it to .... generate two packets aginst some host. For example

   from scapy.all import *
   payload = "GET / HTTP/1.1\r\nHost: censored.com\r\n\r\n"
   ip = 'b.b.b.b' # the target IP, 
   p = (IP(src=ip, dst=ip)/TCP(sport=9999,dport=80,flags="PA")/payload)[IP]
   p.show()
   send(p, iface="ethx")
If such a packet is directed against an L3 censoring device, it might generate TWO RST packets and send them towards b.b.b.b. The takeaway: L3 packet injecting is hard, and fundamentally flawed. Of course.


The author states:

>"If the sequence number is completely out of range then the receiver ignores the segment entirely. If, however, it is within the window of expected sequence numbers, then the receiver sends back a “challenge ACK”. This is a segment which tells the sender that the RST segment had the wrong sequence number. It also tells the sender actual sequence number that the receiver was expecting. The sender can use the information in the challenge ACK to re-construct and re-send its RST.

Before 2010, the TCP protocol did not impose these additional restrictions on RST segments. RST segments were accepted or rejected according to the same rules as any other segment. However, this made blind TCP reset attacks too easy."

If the "challenge ACK" communicates that sequence number that was expected doesn't this in fact still aid reset attacker? Or am I reading this passage incorrectly and the "challenge ACK" procedure is no longer in more modern TCP stacks?


the author is writing, in that section, about blind (i.e. off path) attacks. Given the attacker in that model is off-path they don't see the challenge ack.


Had the great firewall of china block one of the sites I was building for a customer once many years ago. It could only do it for http and not https so assuming it reads the request from the client works out its a http request to an unauthorized IP and sends the reset packet. You cant read the payload for https so didn't know to send the rst packet i'm assuming. Took a while and some playing with wireshark to work out what was going wrong.

Spoke to someone in the Datacenter we where hosting in and they got us adding to some goverment whitelist and it all started working again.


I guess if it worked at the IP level it wouldn't matter whether or not the transport was encrypted. I'd wager how it worked was by sniffing the Host header in the request, and as this was "many years ago" most likely predated Server Name Indication in TLS so encryption was enough to thwart a host-based blocking approach. Now of course with SNI the host is in clear text in the ClientHello (unless using TLS 1.3 ESNI) so the GFC could still block using hostnames even with TLS.


There's no authentication in IP datagrams. When you receive an IP datagram, your network stack just trusts it.

Therefore anyone can craft an IP datagram with a source address and send it. That affects higher layer protocols like TCP.

Solution? Use a secure alternative to IP, like IPsec or Wireguard.


Why not just use TLS?


You can read the SNI without decrypting[0]. You can see it in the ClientHello when I connect to news.ycombinator.com:

    Internet Protocol Version 4, Src: xxx.xxx.xxx.xxx, Dst: 209.216.230.240
    Transmission Control Protocol, Src Port: 64962, Dst Port: 443, Seq: 1, Ack: 1, Len: 517
    Transport Layer Security
        TLSv1.2 Record Layer: Handshake Protocol: Client Hello
            Content Type: Handshake (22)
            Version: TLS 1.0 (0x0301)
            Length: 512
            Handshake Protocol: Client Hello
                Handshake Type: Client Hello (1)
                Length: 508
                Version: TLS 1.2 (0x0303)
                Extension: server_name (len=25)
                    Type: server_name (0)
                    Length: 25
                    Server Name Indication extension
                        Server Name list length: 23
                        Server Name Type: host_name (0)
                        Server Name length: 20
                        Server Name: news.ycombinator.com
                Extension: padding (len=172)
The server name is right there, in the packets, even for TLS! Since the Great Firewall sits between you and the website, it can know the sequence number and send an RST as soon as the connection is initiated.

For a less destructive use of this packet introspection, I've been using Istio to inspect ClientHello SNIs to control egress traffic from Kubernetes[1]. The SNI extension is useful, but it can leak some metadata to adversaries.

[0]: https://en.wikipedia.org/wiki/Server_Name_Indication

[1]: https://istio.io/docs/tasks/traffic-management/egress/egress...


But that's SNI's fault specifically. For comparison, SSH doesn't do that (to my knowledge at least), but the attacker can still see the destination IP, and might well be able to map that back to the domain.

I agree though that ideally a bad guy intercepting your traffic should not be able to tell where it is headed.


Did you use Tshark for outputting this TLS handshake? I ask because it's so nicely formatted and legible.


Wireshark -> [select the field you want] -> Right Click -> Copy -> All Visible Items


TLS is an Application layer protocol, so it's encapsulated within a TCP connection.

TCP connections themselves are encapsulated within IP - so if you can masquerade an IP packet, the inner TLS segment won't protect against decisions at that level.


Because TLS doesn't operate at TCP level. It encrypts the payload carried by it.

TCP (and IP) headers (source/dst IP, port, flags, etc..) remain unencrypted.

On the other hand, IPsec operates at IP level (which can be tunneled over a clear IP/TCP layer)


> max_seq_no = max_acked_seq_no + window_size

What about the packets below max_acked_seq_no which haven't been ACKed? Shouldn't the total number of those be subtracted from the sum above?


QUIC is considerably more resilient than TCP to RST attacks because it authenticates the transport itself once the handshake is complete.


If you try to up nc tcp server from topic, you need to set port correctly with -p option (nc -nvl -p 8888).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: