At the beginning of June 2016, direct users in Kazakhstan fell, while bridge users simultaneously rose. Thereafter, bridge users slowly declined.
linklink
The mainly used transport was obfs4.
link
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.
meek is blocked by SNI. [[doc/meek#Howtochangethefrontdomain|Changing the front domain]] circumvents the block. kzblocked didn't try a different TLS fingerprint.
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.
A first segment of 1–15 bytes doesn't work.
A first segment of 16 bytes works.
A first segment of 16 bytes works also for unobfuscated Tor TLS.
A first segment of 17 bytes works.
A first segment of 32 bytes works.
A first segment of 64 bytes is inconclusive (see comment:8)
kzblocked shared a pcap of trying to connect over obfs4 to the bridge Mosaddegh:80. I don't want to upload it without permission but I can summarize the interesting features.
The client sends a SYN with 12 bytes of TCP options: MSS=1460,WScale=8,NOP,NOP,SAckOK.
The server replies with a SYN/ACK and 8 bytes of TCP options: MSS=1351,NOP,NOP,NOP,EOL.
The client sends an empty ACK.
The client sends 5211 bytes of payload across 4 packets: 1351+1351+1351+1158.
The server ACKs the client's payload but sends no payload of its own.
5.2 seconds later, the server sends an ACK with an acknowledgement one less than the one it most recently sent (a TCP keep-alive).
The server sends 5 more keep-alives separated by 5 seconds.
The server's TCP options are weird. MSS=1351,NOP,NOP,NOP,EOL.
MSS=1351 is unusual; there's only once case of it (M547) in nmap-os-db, "HP MSM410 WAP V. 6.2.1.1-18016 (Looks like Linux 2.6.32 --ed.)". MSS=1350 is more common.
The NOP,NOP,NOP,EOL padding at the end isn't needed and it's out of character for a Linux server. TCP options need to be padded to a multiple of 4 bytes but the MSS=1351 option is already 4 bytes.
There's no WScale option, which is unusual for Linux.
dcf connected to the server with ncat from Linux 4.7. His SYN had the options
MSS=1460,SAckOK,Timestamp,NOP,WScale=7 (20 bytes)
The server's SYN/ACK had
MSS=1350,SAckOK,Timestamp,NOP,WScale=6 (20 bytes)
MSS=1351 is unusual...
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
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces_interface-name_\MTU
https://technet.microsoft.com/en-us/library/cc938197.aspx
MSS=1351 is unusual...
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).