I was talking to someone on IRC today (I'll call them kzblocked) who provided some information. As I understand them:

Vanilla Tor, obfs3, obfs4, and meek are blocked.

The blocking is unreliable and seems to depend on load. Sometimes traffic gets through that you would think would get blocked. This makes it harder to test. The firewall is also blocking tumblr.com (by SNI) but sometimes it loads.

Secret obfs4 bridges from bridges.torproject.org are also blocked. It seems to be dynamic detection, not a static blacklist. Setting iat-mode=1 on the client doesn't help.

obfs2 isn't blocked; kzblocked speculates it's because the initial packet is too short to get a good entropy estimate.

The blocking of vanilla started on June 2, 2016. Bridges were somehow lagged or degraded so people gradually stopped using them.

Behavior differs across ISPs. Some ISPs in Kazakhstan are ​Alma TV, ​KZ Telecom, and ​Transtelecom. Someone said that in one case it's a Fortinet FortiGuard firewall.

kzblocked wrote a Windows program that allows obfs4 connections to succeed, by shrinking the server's TCP window so the client's first packet is smaller. Like ​brdgrd but on the client side. They seem to think that only the first segment is being looked at.

dcf connected to the server with ncat from Linux 4.7. The server's SYN/ACK had

MSS=1350,SAckOK,Timestamp,NOP,WScale=6 (20 bytes)

This might be the key. When reached over an uncensored link, the bridge reports its MSS as 1350. I.e., the largest TCP segment it can handle on its inbound link is 1350 bytes. But when contacted over the censored kz link, the "bridge" reports an MSS of 1351, one byte too big to fit through the link.

A middlebox might have injected the SYN/ACK with MSS=1351. That then causes the client to send segments with 1351 bytes of payload, which then get dropped somewhere between the middlebox and the server.

That would explain why the blocking is intermittent—the middlebox might have limited injection capability. It would seem the middlebox can also drop packets, as well as ACKing the client's data (and sending keep-alive ACKs). It doesn't seem like this trick would work when the server has an MSS greater than or equal to the client's, though, hmm.

kzblocked, if you're reading this, please try reducing your OS's MTU; that should make a spoofed MSS ineffective. It looks like you can change it by setting the registry key

dcf connected to the server with ncat from Linux 4.7. The server's SYN/ACK had

MSS=1350,SAckOK,Timestamp,NOP,WScale=6 (20 bytes)

This might be the key. When reached over an uncensored link, the bridge reports its MSS as 1350. I.e., the largest TCP segment it can handle on its inbound link is 1350 bytes. But when contacted over the censored kz link, the "bridge" reports an MSS of 1351, one byte too big to fit through the link.

A middlebox might have injected the SYN/ACK with MSS=1351. That then causes the client to send segments with 1351 bytes of payload, which then get dropped somewhere between the middlebox and the server.

Someone on IRC commented on the TCP options, saying they are weird but not related to the blocks. They said that the options did not depend on the ISP, rather something in the middle. Testing outside of kz was "all ok".

IRC user, what did you mean by that? Did you mean that outside of kz, you saw the same weird server TCP options MSS=1351,NOP,NOP,NOP,EOL?

Did you mean that outside of kz, you saw the same weird server TCP options MSS=1351,NOP,NOP,NOP,EOL?

Yes, this and weird acks, it's all about vpn transport to box. The same software (server and client side) was tested outside of kz and shows the same weirdness but no traffic to/from obfs4 with 80 port was blocked/stalled. It's independence weirdness, actual blockage happens silently.

kzblocked reports that testing the iat-mode=0 and iat-mode=1 bridges worked. Even setting iat-mode=0 on the client with iat-mode=1 on the server worked. But also a default bridge worked, so the result may have been a random result of net load.

Can't reproduce blockage for 6B9D0823F14A53EE4283DD5A98C8364B09FD77CD (server iat-mode=0) while getting stall traffic for default bridge.
6B9D0823F14A53EE4283DD5A98C8364B09FD77CD vs. some default bridge (!80 and !443)
git master vs. unknown version
new bridge vs. old known bridge heavily used by users around world

First segment used as source for entropy test to decide if stat analysis for stream need. But it's somehow too complex.
Tested with a first segment of 256 bytes. For non modified obfs4 it triggers detection reliably. If to replace random padding with zeroes (segment contains elligator-2 and zeroes then) then no detection happens. But if to keep size of segment (still with elligator-2 as non zero bytes only) to mss then detection happens (thought not so reliably).

We can't fight directly with dictators, but we can to fight with humans (?) who assist dictators directly or indirectly. Humans (?) who lives in peaceful and free states yet and helps to oppress, to censor, to kill people in KZ, etc.

kzblocked investigated obfs4proxy and found some potential explanations for how obfs4 is being blocked. I'll try to summarize what I read on IRC.

As we've seen above, some kind of DPI is blocking obfs4. The blocking seems probabilistic, not total, and default bridges are more likely to be blocked than custom bridges. kzblocked suspects that the DPI is reading about 50 KB of data and then building a timing signature of about 6 data points: 2 from the obfs4 handshake and 4 from the TLS handshake. Each data point is a sequence of segments terminated by one with the PSH flag set.

The delay can be up to 10 ms. Why this may be a problem is the sleep happens during thr round trip between client and server. If the round-trip time is greater than the delay, then it is as if there was no delay. Delays happen only once per write (i.e. obfs4 doesn't split up writes to insert delays). So the timing obfuscation may be less effective during the handshake phase than during the steady state, which can have consecutive writes not bound by latency.

// Write the pending data onto the network. Partial writes are fatal,
// because the frame encoder state is advanced, and the code doesn't keep
// frameBuf around. In theory, write timeouts and whatnot could be
// supported if this wasn't the case, but that complicates the code.

It sounds like kzblocked has actually gotten it to happen, maybe on a slow link. They were going to find out what err is when a short write happens.

On 2016-11-11 kzblocked reported that something had changed on at least some of the DPI boxes in Kazakhstan. A first segment of 16 to 32 bytes doesn't work anymore. The detection seems to happen more often now, sometimes even before a Tor circuit is built.

It sounds like kzblocked has actually gotten it to happen, maybe on a slow link.

This is something about conn.Conn.Write(frameBuf.Bytes()), if frameBuf is too long (say 4-7 frames) then everything broken. Can't reproduce short write exactly, as log and tcpdump show everything goes to wire, but server dislikes result anyway. If to conn.Conn.Write every frame separately then server dislike data anyway, but if to delay every conn.Conn.Write then everything works ok. I'm lost

It sounds like kzblocked has actually gotten it to happen, maybe on a slow link.

This is something about conn.Conn.Write(frameBuf.Bytes()), if frameBuf is too long (say 4-7 frames) then everything broken. Can't reproduce short write exactly, as log and tcpdump show everything goes to wire, but server dislikes result anyway. If to conn.Conn.Write every frame separately then server dislike data anyway, but if to delay every conn.Conn.Write then everything works ok. I'm lost

It might be a race condition... Can you try compiling the obfs4proxy code with the race detector?

The delay can be up to 10 ms. Why this may be a problem is the sleep happens during thr round trip between client and server. If the round-trip time is greater than the delay, then it is as if there was no delay. Delays happen only once per write (i.e. obfs4 doesn't split up writes to insert delays). So the timing obfuscation may be less effective during the handshake phase than during the steady state, which can have consecutive writes not bound by latency.

// Write the pending data onto the network. Partial writes are fatal,
// because the frame encoder state is advanced, and the code doesn't keep
// frameBuf around. In theory, write timeouts and whatnot could be
// supported if this wasn't the case, but that complicates the code.

It sounds like kzblocked has actually gotten it to happen, maybe on a slow link. They were going to find out what err is when a short write happens.

Unless they're messing with the send socket buffer size and setting it to something pathologically low, this should basically never happen (to my knowledge, no one has complained about it). I think this is a red herring.

(And if they are, why. There's better ways to regulate write size.)

The correct way to fix this sort of attack is to switch to a model where the transport schedules writes on it's own regardless of if it has data queued or not. I was going to do something like that for my obfs4 successor, but development on that is on hold for now, and I don't know when I'll get back to it. There's easier distinguishers for obfs4 traffic than this sort of analysis anyway....

OBFS4 is blocked behind both filters. Cyberoam is doing some sort of timing attack, but I’m not sure what. When a bridge is used by lots of people, then it doesn’t work. Even enabling Iat mode=1 or 2 doesn’t fix the issue. When I tried a bridge with not many users, it worked no matter what Iat mode was set at. Behind iBoss, they are fingerprinting Packet Interarrival times. Iat mode 1 and 2 worked no matter how much load the bridges had on them.

kzblocked, I saw you on IRC asking about the ExtORPort and rate limiting. I seem to understand that the firewall might be detecting bridges because they detect the bridge reaching its capacity? Can you explain more about that?

The USERADDR stuff from that proposal is implemented, but the RATE_LIMITED stuff is not implemented—so if there's any rate limiting, it's being done by tor, not by the PT.

Your experiments and ​https://lists.torproject.org/pipermail/tor-talk/2016-November/042586.html show that default bridges are getting blocked, but non-default bridges are less likely to get blocked. There must be something different about the default bridge. One possibility is that their timing characteristics are altered, because they are under a lot of load. Another possibility is that (maybe) firewalls around the world are colluding and counting connections, in order to identify popular destinations that also receive high-entropy traffic—this would probably be good against VPNs too.

I made some visualizations of packet timing. The source code for these is in https://www.bamsoftware.com/git/garden.git.

The orange lines above the axis are sent packets and the blue lines below the axis are received packets. I let the tor client bootstrap to 100% and then cut off the graphs at 6 seconds. I repeated each bootstrap 3 times.

The main observation is that the initial obfs4 handshake and TLS handshake are not really affected by the iat-mode, because the round-trip time swallows all the added delays.

non-obfuscated

For comparison, this is a non-obfuscated, non-default bridge. The first little blip at 0 seconds is the client SYN. The three lines after that are the TLS handshake. What follows after that is TLS application data, the Tor protocol.

obfs4 iat-mode=0

This is the default bridge riemann with iat-mode=1. The first blip at 0 seconds it the client SYN. The one after that is the client obfs4 handshake including padding. The one after that is the server obfs4 handshake plus padding, and the Client Hello.

You can see that even though the obfs4 padding is a lot of bytes, it doesn't affect the timing signature much, which is dominated by latency. The same pattern from the vanilla graph is visible, just offset a bit.

This is the non-default iat-mode=0 bridge from comment:10. It looks about the same as riemann. In try #1 there was a little delay (a similar thing appears in some other graphs below), maybe caused by a dropped packet or something.

obfs4 iat-mode=1

This is the default bridge ndnop3 from comment:47 with iat-mode=1. What we see here is that the first part—the obfs4 handshake and the TLS handshake—isn't changed much, as suspected in comment:32. It's a bit more spaced out because of a higher latency to this particular bridge. Only when the client starts downloading a big chunk of data does the extra padding and timing obfuscation start to have an effect.

This is the non-default iat-mode=1 bridge from comment:10. The first part of the diagram is again not much changed. Once the real data transfer starts, the extra padding and timing obfuscation starts to have an effect and increases bootstrap time from 2 seconds to 3 seconds.

obfs4 iat-mode=2

This is the default bridge ndnop5 from comment:47 with iat-mode=2. The signature of the first few packets is again not much changed. Once the download begins, you can see that iat-mode=2 is a lot more expensive than iat-mode=1 (the edge of the blue lines is ragged because it doesn't try to fill the MTU).

overloaded obfs4 iat-mode=0

Finally, here is the default bridge Lisbeth from comment:51. It has iat-mode=0, but it doesn't seem blocked yet. kzblocked guessed in comment:64 that it might be due to load on the bridge. Indeed, its timing signature looks a lot different from the other iat-mode=1 bridges—it's slower and more irregular.

Or they measures (tunes result) rtt somehow different or all three should be blocked in kz.

There could be another cause: for example suppose all the DPI boxes count connections to each IP address and upload the logs to a central place, then the firewalls only apply their timing/entropy heuristics to popular destinations. It wouldn't surprise me if a firewall vendor were uploading customer connection logs in order to do data mining on them.

There could be another cause: for example suppose all the DPI boxes count connections to each IP address and upload the logs to a central place, then the firewalls only apply their timing/entropy heuristics to popular destinations. It wouldn't surprise me if a firewall vendor were uploading customer connection logs in order to do data mining on them

I still don't have access to a test box in kz with which to test any of these ideas personally. Let me know if it would be helpful to you to have anything special running on one of the default bridges.

What if to delay all empty acks for several ms to get non-default comment:10 bridges detected by kz. any ideas how to do that? maybe not, it still seems like kz and rtt for high load link is matter, but timings for "up" packets from local pov can't be used for anything.

btw, Lisbeth report it observes less bytes than before, wonder if some limits to eth/cpu was installed. interesting if timings changed too.

The operator of Lisbeth says that they enabled iat-mode=1 on November 18, which is after your first test (comment:53), and the same day as your second test (comment:64). Do you remember if it was reachable between November 18 and when you noticed it was blocked on November 27 (comment:85)?

There could be another cause: for example suppose all the DPI boxes count connections to each IP address and upload the logs to a central place, then the firewalls only apply their timing/entropy heuristics to popular destinations. It wouldn't surprise me if a firewall vendor were uploading customer connection logs in order to do data mining on them.

They no need to send it to central place, box can to count connections locally to skip all new addr:port. But then why need to count entropy every time for already known addr:port? Why so complex?

Secret obfs4 bridges from bridges.torproject.org are also blocked. It seems to be dynamic detection, not a static blacklist.

That was wrong generalization it seems, or something changed, or something something. Some bridges was tested for sure, and they was "detected" but I can't recall used addr:port and exact result of "detection". Fresh tested secret obfs4 bridges from bridges.torproject.org are works now, (all tested do reports of solid bandwidth and wasn't listen on 80 port).

Was GreenBelt:5881 result of DNAT too? How can I test two DNATs for the same bridge with one public and another private ports?

They are set up with iptables forwarding rules, yes. For example, GreenBelt:60873 is the actual listening obfs4port, and GreenBelt:1984 and GreenBelt:5881 forward to it. Mosaddegh:41835 is the actual obfs4port, and Mosaddege:1984 and Mosaddegh:80 forward to it.

The reason there are so many forwarding rules is we have been rotating port the past few releases: #20092#20296.

There could be another cause: for example suppose all the DPI boxes count connections to each IP address and upload the logs to a central place, then the firewalls only apply their timing/entropy heuristics to popular destinations. It wouldn't surprise me if a firewall vendor were uploading customer connection logs in order to do data mining on them.

They no need to send it to central place, box can to count connections locally to skip all new addr:port. But then why need to count entropy every time for already known addr:port? Why so complex?

The reason I mentioned sending logs to a central place is that the tor-talk commenter said that for them, too, well-used bridges were detected and unused bridges were not detected. I assumed that they did not have a lot of other users behind the firewall that were increasing connection counts for the default bridges, but I could be wrong about that assumption.​https://lists.torproject.org/pipermail/tor-talk/2016-November/042592.html

It might be just a blacklist that all firewalls share. Even then, I can't explain why they would seemingly be checking entropy and doing a lot of work, rather than just blocking the endpoints.

Vendor changes code on a fly, maybe. When this ticket started kz used to detect all connections, then updated and now it waits for some thresholds (global or local) to do stat analysis and then to apply simplified tests for known addr:port to prevent false positive based on addr:port only. It's has nothing to do with DLP or anything but perfect for mass censorship.

Cyberoam automatically synchronizes at regular intervals with the Cyberoam Update Server or the CCC by which it is managed (if configured from System > Administration > Central Management) and updates the IPS Signatures

So they using data from around world to detect if addr:port is about tor to add it with some signature or somethhing to every cyberoam box. Lisbeth first worked, then detected and stalled, and works again for a while. It was iat=0, and iat=1 now. It was cpu < 100% on some time since active usage (normal timings), 100% cpu (abnormal timings). Some of that + lag detection + lag new signature is about blockage Lisbeth in kz. Is it easy to disable iat or to fix cpu load for norm timings? Lets test!

It wouldn't surprise me if a firewall vendor were uploading customer connection logs in order to do data mining on them

It would be funny if all meta-data from kz leaked to cyberoam office. KZ busted network privacy/security for everyone (include dictator, directly or indirectly with big data lol) in the name of something (whatever they planned to get), if true.

Some initial testing seems to reproduce what's already been described: bootstrapping stalls around 25%. I set up an hourly cron job to try bootstrapping various obfs4 bridges through the kz exit and through a control exit (tor in tor). I want to see how often the connection fails, whether there's correlation with time of day, etc.

Web caches store popular content on servers that have the greatest demand for the content requested. These shared network appliances reduce bandwidth requirements, reduce server load, and improve the client response times for content stored in the cache.
We have 22 points of presence (PoPs) in the major telecommunications centers
Kazakhstan
Almaty

Kazakh's censorship are invisible, no strings, no captive portals. User must to guess if site down itself or dictator blocked it. Only exception for net route over ru, that censors transit traffic too and some ru isp show warnings, and this is not about kz censorship.

I can't visit change.org (this is a site of international petitions - wtf the Government of Kazakhstan have about the freedom of speech?) I can't even download Tor browser (link to ​​https://www.tpo), Browsec addon doesn't work (installing ok and nothing works with it), zetmate doesn't work too. Honestly, I was in China and was able to circumvent block of FB and YT with little efforts. kz is a real nightmare.

(Google translated from popular forum, which block visit from tor now)

Another way to do it is to make a list of what URLs are blocked, and compare them to the blocking categories of each hardware vendor. Of course, this only works if the censors are using the vendor-provided categories. I haven't ever done this kind of experiment myself, but I think some people have.

Even if the DPI boxes are transparent, they might expose a web interface over an IP address or something. Even a transparent HTTP proxy will have implementation-specific differences in the way it treats strange HTTP headers, for example. I think there are ways to fingerprint the censorship device if we try.

The DPI box might have changed or been updated; you can't bypass it by sending short segments.

But you can bypass it by putting HTTP-like bytes inside the random padding of the obfs4 client handshake. The padding is ordinarily filled with random bytes. Filling the padding with zeroes does not bypass as reliably.

kzblocked pasted traceroutes to a blocked and an unblocked bridge, but the pastes expired before I could see them. The traces to default bridges included a hop—82.200.243.106—that wasn't in the traces to non-default bridges. However a trace to an online game server also went through 82.200.243.106.

But you can bypass it by putting HTTP-like bytes inside the random padding of the obfs4 client handshake. The padding is ordinarily filled with random bytes. Filling the padding with zeroes does not bypass as reliably.

Depends net load or something it seems, at 5am of local time no non-random random padding is matter Like it counts bytes as long as cpu time left, with some mandatory minimum it seems.

The firewall changed its method of website blocking in November. Sites are blocked by DNS and HTTP. Blocked sites are redirected to http://92.63.88.128/?NTDzLZ, which in turn redirects to a nonexistent http://90.263.11.193/. The NTDzLZ part is important; without it, the first server redirects somewhere else. It could be an encoding of the destination address. The redirect happens across different KZ ISPs. The server (90.263.11.193?) was used long ago as a crawler with User-Agent Mozilla/4.0 (compatible; MSIE 5.0; Windows 99; BBOT 1.0). kzblocked also says that the server is about some malware they used to redirect to.

It's a combination of a "meta-refresh" redirect and a JavaScript redirect. The header has a few noteworthy characteristics:

Server: nginx.

Date and Last-Modified are equal (and reflect the correct time).

expires=Mon, 16-Jan-2017 17:01:22 GMT in the cookie. The date and time are the same as in Date and Last-Modified, but the day of the week is wrong: Mon should be Fri.

Expires: Thu, 21 Jul 1977 07:30:00 GMT; stayed the same even when the request was repeated.

Sets a cookie. After removing URL quoting, the cookie is cfb9f={"streams":[1481907682],"campaigns":{"1":1481907682},"time":1481907682}; expires=Mon, 16-Jan-2017 17:01:22 GMT; Max-Age=2678400; path=/'. The number 1481907682 changes if you make repeated requests.

A few minutes later I tried downloading it again, and now the result is a 404.

Without the ?NTDzLZ part, I get a rather different HTTP reponse. It's a 302 redirect rather than a meta-refresh or JavaScript redirect, and the IP address is different. Note also the capitalization on LOCATION.

Using Wget again, I also got a slightly different response (302 Found instead of 302 Moved Temporarily, different order of headers, Location instead of LOCATION). I only got this kind of response once, despite repeated requests.

tl;dr: Nmap identifies a host with this signature as a Netgear wireless access point, by sending an HTTP request without a Host header. What do you see when you send GET / HTTP/1.0\r\n\r\n to the server that sent you this response?

I ran a program​ to search ​Project Sonar scans of port 80 (I used 20160830-http.gz) for the HTTP signatures in comment:149 and comment:159. The signature in comment:159 has many many matches, redirecting to various URLs, mostly under subdomains of telcom.co.id, but also afrihost.com, 2090000.ru. Many of them are offline or have changed signature now, but by trying a few at random I found one that worked.

Nmap found this result using its GetRequest probe, which is just GET / HTTP/1.0\r\n\r\n and doesn't include a Host header. Indeed, if I probe it manually with a Host header, I get a similar 302 as in comment:159, but without a Host header I get a 401 with Server: uhttpd/1.0.0 (note: doesn't seem to be the ​uHTTPd from OpenWRT).

The response looks like an in-band injection to me, for two reasons. The first is that the TTLs differ in the SYN/ACK (ttl 50) and the HTTP response (ttl 58). The second is that there are TCP options in the SYN/ACK ([mss 1304,sackOK,TS val 845116384 ecr 17593903,nop,wscale 7]) but none in the HTTP response. Particularly the TS option should oblige the server to include timestamps in all its subsequent segments.

The server sets the FIN bit when it sends the HTTP response. For some reason, though, the client RSTs the connection at the end.

Here are Nmap scans of 92.63.88.128 and 92.62.192.41. 92.63.88.128 is the server that blocked sites are redirected to (comment:145, comment:149) and 92.62.192.41 is the IP address to which 92.63.88.128 redirects when it doesn't get the ?NTDzLZ part.

I tried traceroute to IP addresses of www.torproject.org. All but one of the five addresses (138.201.14.197) got no response past the gateway. 138.201.14.197 reached all the way to the server (I suppose it would be blocked by SNI after that).

I would guess this server is redirecting to some malware or spam. In common with the response from comment:149, it has Expires: Thu, 21 Jul 1977 07:30:00 GMT. (To be fair, there are lots of other servers with that particular value of the header, that don't have the same peculiar redirects.)

Today, the server is still serving redirects, but they look different (note for example the time of 0 rather than 1 in the meta-refresh redirect and \r\n rather than \n in the body.

It seems kz redirects inbound requests too (unless it's some complex routing). megaonline.kz hosted in kz net, and if to request it from outside (not tor, as it seems blocked) then it redirects to the same NTDzLZ

In comment:161 I found an ISP in Russia (2090000.ru) that had an almost identical injection as the Kazakh firewall, with only the redirected-to URL differing. kzblocked found that the same ISP also injects responses for censorship purpose: you get an iframe with a block page if you request a forbidden Host. Ordinary site (example.com) takes you to a payment page:

"zapret" = ​запрет = "prohibition, interdiction, ban". The block page has a cute matryoshka doll and a link to ​http://blocklist.rkn.gov.ru/. The 2090000.ru responses have the same TTL and TCP option anomalies as in comment:166. This ISP uses the same tech for both payment enforcement and censorship, and all indications are that it is the same tech as in Kazakhstan.

Tor 5.5.5 mode= obfs4 wasn’t blocked in some specific flows
TOR might not be identified correctly when running with Skype in the background
Orbot mode obfs4 wasn’t blocked on Android 5.0.1
Some HTTPS based services weren’t accessible due to false positive Phison identification

In some edge use cases TOR Scramblesuit custom bridges cannot be blocked.

The material contained herein is proprietary, privileged, and confidential and owned by <cut> or its third party licensors. This information herein is provided to the person or entity to which it is addressed, for its own use only and evaluation of this document, therefore no disclosure of the content of this document will be made to third parties, including without limitation <cut> competitors, without the express written permission of <cut>

Summary of information about Allot Communications

kzblocked found some evidence that at least part of the Kazakh firewall is provided by ​Allot Communications, which seems to be some firewall/DPI vendor.

As I understand it, the main evidence that Allot hardware is in use is comment:177, import applications (I think that's what they are) dated 2014-11-07 that show АО "Казахтелеком" (​JSC Kazakhtelekom) asking to import equipment from "Allot Communications LTD" in Israel.

The other piece is from comment:175, in which a past 0.2090000.ru blockpage, which we previously found to have the same HTTP signature as a Kazakhstan block page, explicitly said "Allot" on it.

They call their DPI tech ​DART. It's unclear how much is their own and how much is integration of other companies' such as Sophos and Kaspersky. Their page of ​supported protocols (​https://archive.is/AuA8b) explicitly mentions Tor, ScrambleSuit, obfs4, and meek, among others:

June 13, 2016

Private VPN services provided by the Tor project are used by millions the world over, including IT professionals, law enforcement, journalists, bloggers, business execs, researchers and everyday users who want to protect their privacy. A number of applications, like bridges and pluggable transports have sprouted up around Tor to improve the privacy and the experience. Some Tor browsers provide bridges by default. And if not, these tools can be downloaded at any time. A bridge is a tool that makes Tor traffic look like any other traffic, such that censors and other monitors do not identify it as Tor per se. In Allot’s latest DART Protocol Pack, we refined our signature for the Tor obfs4 safe transport, to assure accruate identification of this kind of traffic on your network:

Tor Obfs4

April 4th, 2016

Online anonymity is often viewed as counter-productive and there is a vigorous and ongoing debate regarding the unprecedented anonymity enabled by the Internet. The creators of the Tor project are understandably pro-anonymity, arguing in favor of the many positive and productive uses of TOR by all kinds of people, including IT professionals, law enforcement, journalists, bloggers, business execs, researchers and everyday users who want to protect their privacy. In Allot’s latest DART Protocol Pack we revisited and refined these TOR transport protocols to assure accurate detection of their use:

TOR ScrambleSuit (pluggable proxy transport protocol)

TOR Obfs4 (TCP obfuscation layer)

TOR

February 2nd, 2016

TOR is popular anonymizer application that uses the “onion router.” Onion Router is a website that takes requests for web-pages and routes them through other onion router nodes, until your requested page reaches you. Onion routers encrypt the traffic which means no one can see what you’re asking for, and the layers of the onion don’t know who they’re working for. In Allot’s latest DART Protocol Pack we added signatures that identify these TOR transport protocols that use the Onion Router network:

TOR ScrambleSuit (pluggable proxy transport protocol)

TOR Obfs4 (TCP obfuscation layer)

April 27th, 2015

In recent weeks we announced the new anonymizer applications that were added to Allot’s signature library. This week we focused on updating and refining existing DART signatures for these popular VPN and encryption protocols:

TOR (default mode, 3 available bridge modes, CDN meek)

Psiphon

January 26th, 2015

Allot’s latest DART Protocol Pack helps you identify traffic from users of the Psiphon circumvention system, which has becoming a popular way to bypass content-filtering systems in order to access sites that have been blocked due to geographical or regulatory restrictions. It’s also used to add a layer of identity protection. In this pack, we refined the Psiphon signature to cover all operation modes, including SSH, SSH+ and VPN. We also added two new Psiphon signatures for identifying traffic to and from:

Psiphon Proxy Server

Psiphon CDN (Meek mode)

Allot's LinkedIn pages are what you would expect from a DPI firm, and one mentions Tor and domain fronting:

I uploaded several months worth of data of bridge connection attempts from the U.S. and Kazakhstan over several months (since December 2016). I haven't done much analysis of this yet. For each of the connection attempts there is a tor log and for some of them there is additionally a pcap. The file bridgetest/bridgetest.csv is probably what you want to look at first; it's timestamps of tor connection bootstrap percentages per attempt.

Using the data from comment:192, here is a visualization of bridge bootstrapping from US and KZ over the past few months. For each bridge, there is one connection attempt per hour. The dots on the graph show the maximum bootstrap percentage reached in each attempt (10% = no connectivity, 100% = complete bootstrapping, percentages in the middle mean some connectivity but bootstrap didn't complete).

When the blue dot and the red dot are in the same place, it means that there was no extra blocking in KZ. When the blue dot is lower than the red dot, it means there was some additional blocking in KZ.

There are three gaps in the KZ data where there are no measurements: Dec 28 to January 12, April 8 to April 26, and after May 2.

This table shows the average maximum bootstrap percentage reached during the times when both the US and KZ sites were taking measurements (i.e., excluding the gaps mentioned above). What we see from this is that the majority of measured bridges are not in fact blocked. The only bridges where the KZ rate is lower than the US rate are ndnop3, ndnop5, GreenBelt, Lisbeth, and NX01. Bridges that were added more recently, or were never used, are not more blocked in KZ. This makes me think that the firewall's blocking is based more on a blacklist than on dynamic timing detection.

I am more and more convinced that what we are dealing with, with respect to obfs4 blocking, is mainly a blacklist. It is not just a simple firewall rule, because connection are allowed initially but not allowed to persist. Perhaps it also takes into account some timing-based features, but primarily it seems to be a blacklist.

See, for example, the graphs for Lisbeth and NX01:443 in comment:193. There is a visible change around 2017-01-26 (actually it must have occurred during an outage of the VPN, between 2017-01-25 16:33:55 and 2017-01-27 00:29:43). Before this date the bridges virtually always bootstrap 100%; after that they usually reach 25% and occasionally 100%. If 2017-01-26 is the date when the bridges were blacklisted, it means that Kazakhstan's reaction time is much slower than China's. China blocked Lisbeth on 2016-10-19 (22 days after #19838 merged) and NX01:443 on 2016-12-04 (68 days after #19838 merged, 2 days after #20838 merged). Kazakhstan was 100 days slower to block Lisbeth, and 54 days slower to block NX01:443.

Part of the confusion we've had in detecting whether blocking was occurring might have been caused by failures on the bridge side. As you can see from the graph in comment:193, some of the default bridges were down (even from the U.S.) at various times. ndnop3 and ndnop5 (from comment:47) are interesting cases, because they have been failing connections even from the U.S. about 40% of the time. In communication with the bridges' operator, we tracked the problem down to a file descriptor limit. This may explain some of the irregular results we were seeing early on.

Doing a web search for "NTDzLZ" found a few threads with other people noticing the blocks. The latest is dated December 25, 2016, which is slightly later than the latest injection I saw myself, which was December 21, 2016 (comment:173).

Translated: "Hello, I'm here for the first time. In general, here's the problem: I can not go to some sites (xvideos.com, redtube.com) (the problem is certainly not in them) but still want to fix them. When I come, I throw it at http://92.63.88.128/?NTDzLZ and there it is empty"

Translated: "I'm trying to go to the site newgrounds.com, it does not enter and I throw it on the link http://92.63.88.128/?NTDzLZ , but before it stopped . Kaspersky swears, writes a virus site, there are no viruses on the computer, it was checked by another web, Kaspersky"

Looks like a spam presentation with HTML in the description that refers to Kaspersky antivirus. Puts a = at the end of the URL, unlike other sources.
"<b>Веб-адрес:</b><br><br><div title="http://92.63.88.128/?NTDzLZ=">http://92.63.88.128/?NTDzLZ=<br><br> </div><b>Заблокирован Веб-Антивирусом</b><br><br> Причина: опасный веб-адрес <br><br><a href="http://touch.kaspersky.com/kfa_cup_f8f731b4-629f-4b7c-923c-495d87bf7e09/1481884315">Нажмите здесь, если считаете, что веб-страница заблокирована ошибочно.</a><br>"

I just noticed something weird about this response. The Content-Length: 210 header is wrong. The body is actually 224 bytes.

You can see the same when you open attachment:youporn.com.pcap​ in Wireshark. The "Line-based text data: text/html" is cut off after </BO. The remaining "File Data: 14 bytes" appears as 44593e3c2f48544d4c3e0d0a0d0a.

The header is rather different; also notice 302 Moved rather than 302 Found in the HTML body.

I thought that this google.co.in response was a fluke; but it seems to be representative of Google's geolocation redirects. I just now captured one for www.google.nl by requesting www.google.com through Tor:

Now, this response is quite similar to the injected KZ censorship response from comment:159, including whitespace and capitalization quirks, but there are some differences. Here is a diff of the two responses.