What Does Censorship Look Like?

Sarah Fortune
6 min readOct 24, 2019

--

I had the opportunity this year to work with eQualitie on the CeNo project. CeNo is a mobile browser that attempts to evade censorship by distributing blocked content over a peer to peer network.

One of the countries where this kind of technology would be beneficial is Iran. Iran has tough restrictions on internet usage and many huge sites like Facebook and Twitter are blocked, as well as news sites like the BBC, and “inappropriate” content.

I wanted to understand better how censorship is implemented, so I started doing some tests on a desktop machine hosted on a residential ISP in Iran and tried to see what was happening.

Trying to access a blocked site like bbc.co.uk directs you a government page which says that the site is restricted and gives you a list of links to various safe sites. I assume if you live in Iran you see this page frequently.

Seeing this page is actually the best thing that can happen. The majority of the time accessing a blocked site would just time out. I am not sure if this behavior was intentional or just a problem with their network.

If we look a bit closer at what is happening, the DNS requests for bbc.co.uk are returning an IP in the private 10.0.0.0 range.

$ wget --server-response bbc.co.uk
--2019-07-20 04:46:02-- http://bbc.co.uk/
Resolving bbc.co.uk (bbc.co.uk)... 10.10.34.35
Connecting to bbc.co.uk (bbc.co.uk)|10.10.34.35|:80... ^C
$ host bbc.co.uk
bbc.co.uk has address 10.10.34.35

It is really weird to see a 10.0.0.0 IP outside of a LAN. The web server at 10.10.34.35 returns a HTTP status of 403 forbidden with the page above as the content.

It is just the DNS request which is being restricted, access to the actual host is not blocked. For example, I can connect directly to one of the Facebook web servers at 157.240.22.35.

$ wget --server-response http://157.240.22.35/
--2019-07-20 04:49:05-- http://157.240.22.35/
Connecting to 157.240.22.35:80... connected.
HTTP request sent, awaiting response...
HTTP/1.1 301 Moved Permanently
Vary: Accept-Encoding
Location: http://www.facebook.com/
Content-Type: text/html; charset="utf-8"
X-FB-Debug: 3moHSfKXp2BmXfZcBd2coRcSkt9CqqapzE4PXop1Fb6fFHgAhqTHb+MOzOOAMGrcX6oO/zycXh7CSPVakFBrdA==
Date: Sat, 20 Jul 2019 00:19:05 GMT
Connection: keep-alive
Content-Length: 0
Location: http://www.facebook.com/ [following]

So, I tried adding entries for some blocked sites to /etc/hosts so I could avoid this dodgy DNS response. I accessed Facebook again, but the connection would timeout in the middle of the SSL handshake.

$ curl -v https://facebook.com/
* Trying 157.240.22.35...
* TCP_NODELAY set
* Connected to facebook.com (157.240.22.35) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to facebook.com:443
* stopped the pause stream!
* Closing connection 0
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to facebook.com:443

It wasn’t obvious from the curl output what was going wrong, so I captured the packets with tcpdump. Looking at the dump in Wireshark, all the incoming packets after the TLS client hello are dropped.

Unfortunately, the hostname is being sent in cleartext in the SSL Service Name Indicator field and the government filter is using deep packet inspection on this. Let’s try to make the connection using the openssl client which is a generic tool, so it won’t add the SNI field to the request. This is a sort of poor man’s domain fronting. But, it works! After the SSL connection is established, I can manually enter a HTTP request for www.facebook.com and receive back the contents of the Facebook login page.

$ openssl s_client -connect www.facebook.com:443
CONNECTED(00000003)
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 High Assurance Server CA
verify return:1
depth=0 C = US, ST = CA, L = Menlo Park, O = "Facebook, Inc.", CN = *.facebook.com
verify return:1
---
Certificate chain
0 s:/C=US/ST=CA/L=Menlo Park/O=Facebook, Inc./CN=*.facebook.com
i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIGMDCCBRigAwIBAgIQCa2oS7Nau6nwv1WyRNIJnzANBgkqhkiG9w0BAQsFADBw
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
dXJhbmNlIFNlcnZlciBDQTAeFw0xOTA2MDYwMDAwMDBaFw0xOTA5MDQxMjAwMDBa
MGExCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTWVubG8gUGFy
azEXMBUGA1UEChMORmFjZWJvb2ssIEluYy4xFzAVBgNVBAMMDiouZmFjZWJvb2su
Y29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEALPlfjd8gHkIMDeBOFhRt0e
+/3fdm+ZdzdM4s1WIHVbYztgmdEy20PUwDCviYKJX4GG+T9ivT8kJ/vWl1P/YqOC
A54wggOaMB8GA1UdIwQYMBaAFFFo/5CvAgd1PMzZZWRiohK4WXI7MB0GA1UdDgQW
BBTsQZVRTuib7KY9w3FfOYsZHvOC9zCBxwYDVR0RBIG/MIG8gg4qLmZhY2Vib29r
LmNvbYINbWVzc2VuZ2VyLmNvbYILKi5mYmNkbi5uZXSCCCouZmIuY29tghAqLm0u
ZmFjZWJvb2suY29tggZmYi5jb22CDiouZmFjZWJvb2submV0gg4qLnh4LmZiY2Ru
Lm5ldIIOKi54ei5mYmNkbi5uZXSCDyoubWVzc2VuZ2VyLmNvbYILKi5mYnNieC5j
b22CDioueHkuZmJjZG4ubmV0ggxmYWNlYm9vay5jb20wDgYDVR0PAQH/BAQDAgeA
MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAw
hi5odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzYuY3Js
MDSgMqAwhi5odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXIt
ZzYuY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0
dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQICMIGDBggrBgEFBQcB
AQR3MHUwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBNBggr
BgEFBQcwAoZBaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hB
MkhpZ2hBc3N1cmFuY2VTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH/BAIwADCCAQQGCisG
AQQB1nkCBAIEgfUEgfIA8AB1AKS5CZC0GFgUh7sTosxncAo8NZgE+RvfuON3zQ7I
DdwQAAABay5CAaUAAAQDAEYwRAIgMwBM6q+dBwu2mNtMMjTEwJZZxyoUlHUEYO+b
fkId/9MCIAQ2bxhnxrapYv74fzyoTkt9m+ELq6+43OVpivRVKDKTAHcAdH7agzGt
MxCRIZzOJU9CcMK//V5CIAjGNzV55hB7zFYAAAFrLkIA/AAABAMASDBGAiEA0x1x
PWue6RMSE9nbjYBt637CRC86ixrODP/EIlI5mCgCIQCHNdqgOlswd0LqaW4QRii2
JHN4bnoEj/D9j7+kqEB7LjANBgkqhkiG9w0BAQsFAAOCAQEAnRdIVNZ850s7IvLg
g+U9kKxA18kLKVpIF/rJHkXTkymvBHKAGOFNfzqF2YxHFhkDMIuoMO2F+A1E0Eo8
zb1atL6/L59broEHTOH6xFmJAlZW0h6mZg8iRJ9Ae0pTN/fowaoN9aFVRnVr9ccK
hOdqsXYyEZ3Ze39sEwx7Uau9KhzyuJW12Jh3S+ZJYUdBADeeJNL5ZXSUFIyjgkwS
QZPaaWAzSGHZFt3sWhMjdNoBkjRJFlASLDM3m1ZWsKA47vuXvJc/DXT35lC1DJmy
hYb9qNPR71a1hJ8TS7vUwdDd+dEHiJj2wQLV3m7Tn7YvWyJOEyi4n6/rPqT44LZm
gK7HWw==
-----END CERTIFICATE-----
subject=/C=US/ST=CA/L=Menlo Park/O=Facebook, Inc./CN=*.facebook.com
issuer=/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 3284 bytes and written 302 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ECDHE-ECDSA-AES128-GCM-SHA256
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-ECDSA-AES128-GCM-SHA256
Session-ID: 72B5AD4024A642D8A9F1D2998E2492B0B813F13958F322F52B38CDEE2794C0CC
Session-ID-ctx:
Master-Key: A99231AFFFDE2D3BCBF7A9CEDE29911BCE0177F40F67F6C0E3A39597ECBA31941633FFFB4A3E1FECE864DAEDEC1EAFBF
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 172800 (seconds)
TLS session ticket:
0000 - 30 6e d5 1c fd 41 d2 d8-dc ca ec 41 09 64 d5 f0 0n...A.....A.d..
0010 - db 3c d8 06 67 ef 63 90-3c e9 db cf 34 3e fd b7 .<..g.c.<...4>..
0020 - f0 62 26 d0 b2 e6 5d 1b-fa 7e 37 20 b4 fb 76 77 .b&...]..~7 ..vw
0030 - 5b dd d2 b9 c8 d9 a5 05-18 2d aa d0 64 4c 6d 97 [........-..dLm.
0040 - 40 a3 d0 75 8e 49 5e 8e-d2 61 80 15 9c 48 f4 fd @..u.I^..a...H..
0050 - 81 fd 9c 93 ce e1 63 31-23 27 42 ce 79 ad b7 61 ......c1#'B.y..a
0060 - 96 ae 4c 2d 96 11 a3 79-e9 25 f3 f8 c8 f5 bb fc ..L-...y.%......
0070 - a8 54 02 34 9c 85 80 5b-f4 30 6f 6d bc 16 a1 46 .T.4...[.0om...F
0080 - dc bc a5 8c 30 c5 6e f7-5b c7 ba dd dd 48 00 4c ....0.n.[....H.L
0090 - f3 1c 8e 43 fb b2 71 b9-f0 10 60 7a 4a 9d f8 7d ...C..q...`zJ..}
00a0 - 9d 5a c9 39 31 78 a4 20-bb 30 ca e8 9e f7 28 17 .Z.91x. .0....(.
Start Time: 1563681133
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: yes
---
GET / HTTP/1.1
Host: www.facebook.com
User-agent: Mozilla
HTTP/1.1 200 OKSet-Cookie: fr=19JO6iXDLwY18AFNO..BdM-GC.tm.AAA.0.0.BdM-GC.AWVKoxtY; expires=Mon, 20-Jul-2020 03:52:33 GMT; Max-Age=31535999; path=/; domain=.facebook.com; secure; httponlySet-Cookie: sb=guEzXc9HQYZGW-lA-8pu77gi; expires=Tue, 20-Jul-2021 03:52:34 GMT; Max-Age=63072000; path=/; domain=.facebook.com; secure; httponlyCache-Control: private, no-cache, no-store, must-revalidatePragma: no-cacheStrict-Transport-Security: max-age=15552000; preloadVary: Accept-EncodingX-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 0Expires: Sat, 01 Jan 2000 00:00:00 GMTContent-Type: text/html; charset="utf-8"X-FB-Debug: e4bKwCUHDpcfvQPYwVrSRuX+tRDX0W+Y2bgKWG5rWhNkAZnOxDleCPjwAI+SOxHSNtNZ3vp4E0EzUVn+HPKpIQ==Date: Sun, 21 Jul 2019 03:52:34 GMTTransfer-Encoding: chunkedConnection: keep-alive908<!DOCTYPE html>
<html lang="en" id="facebook" class="no_js">
<head><meta charset="utf-8" /><meta name="referrer" content="default" id="meta_referrer" /><script>window._cstart=+new Date();</script><script>function envFlush(a){function b(b) <snip>
db23k=function(a,b){this.piggy_values[a]=b;return this},CavalryLogger.instances={},CavalryLogger.id=0,CavalryLogger.disableArtilleryOnUntilOffLogging=!1,CavalryLogger.getInstance=function(a) <rest of the output truncated>

Requests for HTTP sites are also subject to deep packet inspection. URLs are filtered for suspicious looking words. So for example, any URL with the word porn in it is censored and returns HTTP 403 forbidden.

$ wget --server-response http://example.com/porn
--2019-07-21 09:15:20-- http://example.com/porn
Resolving example.com (example.com)... 93.184.216.34
Connecting to example.com (example.com)|93.184.216.34|:80... connected.
HTTP request sent, awaiting response...
HTTP/1.1 403 Forbidden
Date: Sun, 21 Jul 2019 04:45:20 GMT
Connection: close
2019-07-21 09:15:20 ERROR 403: Forbidden.

$ wget --server-response http://porntraff.com/
--2019-07-21 09:17:14-- http://porntraff.com/
Resolving porntraff.com (porntraff.com)... 162.251.111.237
Connecting to porntraff.com (porntraff.com)|162.251.111.237|:80... connected.
HTTP request sent, awaiting response...
HTTP/1.1 403 Forbidden
Date: Sun, 21 Jul 2019 04:47:15 GMT
Connection: close
2019-07-21 09:17:15 ERROR 403: Forbidden.

In conclusion, there are several blocking mechanisms at work here. DNS requests for sites on a black list return the IP of a government server. Deep packet inspection is used to detect blocked keywords in HTTP requests and blacklisted hostnames in HTTPS requests.

Domain fronting would still allow access to hosts that support it. Encrypting the hostname in the SSL handshake using Encrypted SNI would prevent filtering of HTTPS requests, but this is not widely implemented yet.

--

--