{"id":17120,"date":"2019-12-06T14:40:02","date_gmt":"2019-12-06T22:40:02","guid":{"rendered":"https:\/\/www.palada.net\/index.php\/2019\/12\/06\/news-10856\/"},"modified":"2019-12-06T14:40:02","modified_gmt":"2019-12-06T22:40:02","slug":"news-10856","status":"publish","type":"post","link":"http:\/\/www.palada.net\/index.php\/2019\/12\/06\/news-10856\/","title":{"rendered":"Dissecting Tor Bridges and Pluggable Transport \u2013 Part II:  How Obfs4 Bridges Defeats Censorship"},"content":{"rendered":"<div class=\"aem-Grid aem-Grid--12 aem-Grid--default--12\">\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p><b><i>A FortiGuard Labs Threat Research Report<\/i><\/b><\/p>\n<h2>Background<\/h2>\n<p>This is the second half of my two-part series on \u201cDissecting Tor Bridges and Pluggable Transport\u201d. In the <a href=\"https:\/\/www.fortinet.com\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport.html\">first blog<\/a>, I went into great detail in explaining how the Tor browser\u2019s built-in bridges were passed through three processes (\u201cfirefox.exe\u201d, \u201ctor.exe,\u201d and \u201cobfs4proxy.exe\u201d), how Tor Browser communicates with the Obfs4 Bridge client, as well as the relationship between those three processes. In this blog, I will continue to explain how Tor uses Obfs4 Bridge to circumvent censorship.<\/p>\n<h2>Traffic Flow When Using Tor \u2013 With and Without Obfs4 Bridge<\/h2>\n<p>Before talking about Obfs4 Bridge, I would like to explain what the difference is between the Tor Browser enabling Obfs4 Bridge and operating without it. To make it clear and easy to understand, I drew two Tor traffic flow charts, shown as Figures 1 and 2, below.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn--default--9 aem-GridColumn aem-GridColumn--offset--default--1\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image.img.png\/1575578249146\/tor-ii-one.png\" alt=\"Figure 1. Normal Tor traffic flow without Obfs4 Bridge\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 1. Normal Tor traffic flow without Obfs4 Bridge<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>Figure 1 shows a normal Tor communication flow without Obfs4 Bridge. The brief process is as follows: The Tor client obtains three Tor relays from the Tor main directory as the entry relay, middle relay, and exit relay. Once the user accesses a website, the Tor client receives a request packet from Tor Browser (firefox.exe). It then encrypts the packet three times with the session keys from the exit, middle, and entry relays. This multiple-encrypted packet is then sent to the entry relay, middle relay, and exit relay. After being decrypted by them, the exit relay gets the original packet and sends it to a destination server, like \u201cwww.google.com\u201d. This is pretty much the way Tor transmits an original packet from Tor Browser to its destination website.<\/p>\n<p>However, the Tor-encrypted traffic, shown by the red arrow in Figure 1, is easily identified and blocked by censorship. <\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn--default--9 aem-GridColumn aem-GridColumn--offset--default--1\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image_2086028807.img.png\/1575578230249\/tor-ii-two.png\" alt=\"Figure 2. Tor traffic flow changed with Obfs4 Bridge\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 2. Tor traffic flow changed with Obfs4 Bridge<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>Figure 2 shows a new communication path using Obfs4 Bridge. You can clearly see that once Obfs4 Bridge is enabled, the Tor traffic goes down to the Obfs4 client (obfs4proxy.exe) to be transformed and transported to the bridge relay. The Bridge relay is now the entry relay instead of the old Tor entry relay. And as a result, the total number of relays of any given Tor circuit is always three for good performance.<\/p>\n<p>The Obfs4 Bridge client takes the Tor-encrypted payload and seals it up with the Obfs4 function. The sealed packets are then sent to the Obfs4 Bridge relay. Unsealing them, the Bridge relay gets the Tor encrypted packets and forwards them to the next Tor relay of the Tor circuit. A similar thing happens on reverse direction packets.<\/p>\n<p>This is a brief explanation of how the Obfs4 Bridge works. Next, I\u2019ll talk about what techniques Obfs4 Bridge uses to make the traffic harder to be identified.<\/p>\n<h2>The SETCONF Command and Bridge Configuration Line<br \/> <\/h2>\n<p>Tor Browser (\u201cfirefox.exe\u201d) sends the command \u201cSETCONF\u201d with built-in Obfs4 Bridge information to \u201ctor.exe\u201d via the control TCP port 9151. The command format is like the one below:\u00a0<\/p>\n<\/p><\/div>\n<div class=\"raw-import aem-GridColumn aem-GridColumn--default--12\">\n<div class=\"text-container\"><body>  <\/p>\n<pre style=\"margin: 0in 0in 12pt; line-height: 115%; font-size: 10pt; font-family: 'Courier New';\"><strong><span style=\"font-size: 11.0pt; line-height: 115%; color: #7f0000; background: #FBEDED;\">SETCONF<\/span><\/strong><span style=\"font-size: 11.0pt; line-height: 115%; color: #7f0000; background: #FBEDED;\"> <strong><span style=\"background: aqua;\">UseBridges=1<\/span><\/strong> <strong><span style=\"background: yellow;\">Bridge=\"obfs4 109.105.109.165:10527<br \/>8DFCD8FB3285E855F5A55EDDA35696C743ABFC4E<br \/>cert=Bvg\/itxeL4TWKLP6N1MaQzSOC6tcRIBv6q57DYAZc3b2AzuM+\/TfB7mqTFEf<br \/>XILCjEwzVA iat-mode=1\"<\/span><\/strong> Bridge=\"obfs4 85.17.30.79:443 &hellip;&hellip;<\/span><\/pre>\n<p>  <\/body><\/div>\n<\/p><\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>\u201cSETCONF\u201d at the beginning of the command is the command name. \u201cUseBridges=1\u201d tells Tor that the Bridge feature is enabled by the user. The following data includes entire built-in Obfs4 Bridge blocks, which are called bridge configuration lines on the Tor website. Each bridge node must be saved in one bridge configuration line. Here I only kept the first one for an example. Each bridge configuration line starts with \u201cBridge=\u201d. Let\u2019s look at what content is inside.<\/p>\n<p>It contains:<\/p>\n<ul>\n<li>Bridge type: obfs4, tells the bridge type.<\/li>\n<li>Bridge server IP and port: 109.105.109.165:10527.<\/li>\n<li>Bridge ID: 14H long hexadecimal.<\/li>\n<li>Bridge cert: base64 encoded nodeID, IdPublicKey of an Obfs4 relay.<\/li>\n<\/ul>\n<p>Bridge IAT-mode: The IAT mode flag can be set to \u201c0\u201d, \u201c1\u201d, or \u201c2\u201d.<\/p>\n<p>Tor handles this command and then starts a child process of \u201cobfs4proxy.exe\u201d, which is the Obfs4 Bridge client. \u201cobfs4proxy.exe\u201d uses the same procedure, transferring packets through TCP ports on the loopback interface\u00a0between\u00a0the Obfs4 Bridge client\u00a0and the Tor client.<\/p>\n<h2>Tor Client Communicating with Obfs4 Client<\/h2>\n<p>The Tor client separately sends Obfs4 Bridges to \u201cobfs4proxy.exe\u201d and asks it to make a connection with an Obfs4 Bridge relay. Tor uses the SOCKS5 protocol to transport data with the Obfs4 Bridge client.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn--default--9 aem-GridColumn aem-GridColumn--offset--default--1\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image_1788382350.img.png\/1575578652596\/tor-ii-three.png\" alt=\"Figure 3. \u201ctor.exe\u201d sends one instance of Obfs4 Bridge information to \u201cobfs4proxy.exe\u201d\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 3. \u201ctor.exe\u201d sends one instance of Obfs4 Bridge information to \u201cobfs4proxy.exe\u201d<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>Figure 3 is a screenshot of the communication packets between \u201ctor.exe\u201d and \u201cobfs4proxy.exe\u201d in WireShark. The packets in red are from \u201ctor.exe\u201d to \u201cobfs4proxy.exe\u201d (through the random TCP port on the loopback interface). The response packets are in blue. As you can see, it also uses the SOCKS5 protocol.<\/p>\n<p>First, Obfs4 Bridge information containing base64-encoded \u201ccert=\u201d and IAT-mode was sent to \u201cobfs4proxy.exe\u201d from \u201ctor.exe\u201d. Later, \u201ctor.exe\u201d continued to send the binary IP address and Port of the Obfs4 Bridge relay in a SOCKS 5 \u201cConnect (1)\u201d packet (starting with \u201c|05 01 00 01|\u201d). \u201cobfs4proxy.exe\u201d then connected to this Obfs4 Bridge relay with the IP address and Port. Once the connection was successfully established, it sent a \u201cSucceeded (0)\u201d packet (\u201c|05 00 00 01 00 00 00 00 00 00|\u201d) back to \u201ctor.exe\u201d. That means that the Obfs4 handshake was successfully completed (I\u2019ll explain the handshake process in the next section). Afterwards, \u201ctor.exe\u201d can send and receive all packets to be transformed and transported by the Obfs4 Bridge over this connection.<\/p>\n<h2>Obfs4 Client Starting a Handshake with Obfs4 Bridge<\/h2>\n<p>Connecting Obfs4 Bridge requires a handshake process, the purpose of which is to transport public keys and to verify each other.<\/p>\n<p>Before explaining the handshake packet, I will take a moment to talk about the cryptography algorithm that Obfs4 uses and the structure of a \u201cKeypair\u201d.<\/p>\n<p>Obfs4 Bridge uses ECC (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Elliptic-curve_cryptography\">Elliptic-Curve\u00a0Cryptography<\/a>) algorithm to encrypt the Tor payload to ensure secure communications between the Obfs4 client and the relay. As we know, ECC is a public key encryption technique based on elliptic curve theory. The ECC that Obfs4 uses is implemented in a Go language package called \u201ccurve25519\u201d, which offers two important functions: ScalarBaseMult() and ScalarMult().<\/p>\n<p>This is the definition of the Keypair structure, whose primary function is to save the public and private keys:<\/p>\n<\/p><\/div>\n<div class=\"raw-import aem-GridColumn aem-GridColumn--default--12\">\n<div class=\"text-container\"><body>  <\/p>\n<pre style=\"margin: 0in 0in 12pt 0.5in; line-height: 115%; font-size: 10pt; font-family: 'Courier New';\"><em><span style=\"font-family: Calibri, sans-serif; color: #00b050; background: #D9D9D9;\">\/\/ Keypair is a Curve25519 keypair with an optional Elligator representative.<\/span><\/em><\/pre>\n<pre style=\"margin: 0in 0in 12pt 0.5in; line-height: 115%; font-size: 10pt; font-family: 'Courier New';\"><em><span style=\"font-family: Calibri, sans-serif; color: #00b050; background: #D9D9D9;\">\/\/ As only certain Curve25519 keys can be obfuscated with Elligator, the<\/span><\/em><\/pre>\n<pre style=\"margin: 0in 0in 12pt 0.5in; line-height: 115%; font-size: 10pt; font-family: 'Courier New';\"><em><span style=\"font-family: Calibri, sans-serif; color: #00b050; background: #D9D9D9;\">\/\/ representative must be generated along with the keypair.<\/span><\/em><\/pre>\n<pre style=\"margin: 0in 0in 12pt 0.5in; line-height: 115%; font-size: 10pt; font-family: 'Courier New';\"><strong><em><span style=\"font-family: Calibri, sans-serif; color: #c00000; background: #D9D9D9;\">type<\/span><\/em><\/strong><strong><em><span style=\"font-family: Calibri, sans-serif; color: black; background: #D9D9D9;\"> Keypair <\/span><\/em><\/strong><strong><em><span style=\"font-family: Calibri, sans-serif; color: red; background: #D9D9D9;\">struct <\/span><\/em><\/strong><strong><em><span style=\"font-family: Calibri, sans-serif; color: black; background: #D9D9D9;\">{<\/span><\/em><\/strong><\/pre>\n<pre style=\"margin: 0in 0in 12pt 0.5in; line-height: 115%; font-size: 10pt; font-family: 'Courier New';\"><strong><em><span style=\"font-family: Calibri, sans-serif; color: black; background: #D9D9D9;\">&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;&nbsp;&nbsp;&nbsp; *PublicKey<\/span><\/em><\/strong><\/pre>\n<pre style=\"margin: 0in 0in 12pt 0.5in; line-height: 115%; font-size: 10pt; font-family: 'Courier New';\"><strong><em><span style=\"font-family: Calibri, sans-serif; color: black; background: #D9D9D9;\">&nbsp;&nbsp;&nbsp;&nbsp; private&nbsp;&nbsp;&nbsp; *PrivateKey<\/span><\/em><\/strong><\/pre>\n<pre style=\"margin: 0in 0in 12pt 0.5in; line-height: 115%; font-size: 10pt; font-family: 'Courier New';\"><strong><em><span style=\"font-family: Calibri, sans-serif; color: black; background: #D9D9D9;\">&nbsp;&nbsp;&nbsp;&nbsp; representative *Representative <\/span><\/em><\/strong><\/pre>\n<pre style=\"margin: 0in 0in 12pt 0.5in; line-height: 115%; font-size: 10pt; font-family: 'Courier New';\"><strong><em><span style=\"font-family: Calibri, sans-serif; color: black; background: #D9D9D9;\">}<\/span><\/em><\/strong><\/pre>\n<p>  <\/body><\/div>\n<\/p><\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>Both the client and server must have their own Keypair instances. Let me explain the relationship between them. The Private Key is randomly generated in a certain range according to a definition in the curve25519 package. As per the ECC, a public key is computed from a private key by calling curve25519.ScalarBaseMult(). A representative key is then transformed from a public key, which can also be easily restored to a public key whenever needed by calling the function extra25519.RepresentativeToPublicKey(). The definition and initialization of this Keypair is implemented in the NewKeypair() function defined in source file \u201cntor.go\u201d. <\/p>\n<p>Each side of the client and server should keep their private key, and send their public key in a representative key to each other.<\/p>\n<p>The Obfs4 client starts the connection from a handshake packet, so let\u2019s see what this client handshake packet looks like. Here is an overview of the packet structure:<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn--default--9 aem-GridColumn aem-GridColumn--offset--default--1\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image_1590549375.img.png\/1575579860423\/screen-shot-2019-12-05-at-1.03.56-pm.png\" alt=\"Table 1. Client\u2019s handshake packet structure\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Table 1. Client\u2019s handshake packet structure<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>The first part of the Client\u2019s Handshake packet is the Keypair.representative, which is 20h bytes long. On the server side, it can be used to restore the client\u2019s public key.<\/p>\n<p>The second part is padding data filled with random bytes, whose data size can range from 4Dh to 1FC0h. This padding data can obfuscate the handshake packet size, which makes it harder to be identified. <\/p>\n<p>The third part is called \u201cmark\u201d in Obfs4 source code, which is a HMAC value of the first part \u2014Keypair.representative. Obfs4 uses SHA-256 to generate HMAC, which is 20h bytes long. Obfs4 only keeps the first 10h bytes as HMAC, so the rest of the 10h bytes are discarded.<\/p>\n<p>Obfs4 uses the current system time to compute an hour value of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Unix_time\">UNIX Epoch time<\/a> (it\u2019s a time since 00:00:00 Thursday, 1 January 1970 UTC). In a period, the client and server should run out an identical hour value from their different local times. It then computes a HMAC value of all three parts in the packet out lined above, plus the hour value in a string. Similarly, the resulting value is 20h bytes long, and the first 10h bytes are used as the fourth part of the packet.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn--default--9 aem-GridColumn aem-GridColumn--offset--default--1\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image_1177377939.img.png\/1575580009952\/tor-ii-four.png\" alt=\"Figure 4. \u201cobfs4proxy.exe\u201d sends client\u2019s handshake packet\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 4. \u201cobfs4proxy.exe\u201d sends client\u2019s handshake packet<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>Figure 4 is a screenshot of Ollydbg showing the client\u2019s handshake packet. I have split the memory portion of the image into four parts, each with different colors. In this case, the padding data is 52h byte long. The third part (\u201cmark\u201d) and last part (\u201cHMAC of Entire Data\u201d) can be used to verify the client\u2019s handshake packet at server side.<\/p>\n<p>Even if you used all of the data outlined above correctly, your Obfs4 Bridge would still fail the handshake process if your system is using an incorrect system time. Figure 5 shows that exact situation because my test system\u2019s time was not up to date, causing the TCP session to close in packet #6 after the server received the client handshake in packet #4.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn--default--9 aem-GridColumn aem-GridColumn--offset--default--1\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image_1786214207.img.png\/1575580160498\/tor-ii-five.png\" alt=\"Figure 5. Server side authentication fail due to incorrect system time\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 5. Server side authentication fail due to incorrect system time<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>Once a connection request is established, the Obfs4 relay starts a new thread to process the communication with the client, which is where the client\u2019s handshake packet gets processed as well. The server side does the same thing as the client side \u2013 that is, it generates the server\u2019s Keypair instance corresponding to the client\u2019s Keypair. It computes out a representative and public key from a randomly chosen private key by calling its curve25519.ScalarBaseMult().<\/p>\n<p>The server side then parses and verifies the client\u2019s handshake packet. After ensuring everything in the packet is correct, it restores the client\u2019s public key from the representative value, which is in the first part of the handshake packet, by calling the function extra25519.RepresentativeToPublicKey().<\/p>\n<p>The next step is crucial for the ECC algorithm\u2019s \u201cscalar multiplication\u201d (the function curve25519.ScalarMult()). Scalar multiplication is a one-way function and there is no scalar division function, which keeps the ECC algorithm very strong.<\/p>\n<p>It performs scalar multiplication using the server\u2019s private key and the client\u2019s public key. Similarly, the client will perform the same operation when it receives the server\u2019s handshake packet. At the end of the process, the two results of the scalar multiplication must be the same, which leads to this equation shown in figure 6.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--7 aem-GridColumn--offset--default--2\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image_782665855.img.png\/1575580298823\/tor-ii-six.png\" alt=\"Figure 6. Equation of the ECC Algorithm\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 6. Equation of the ECC Algorithm<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>The equation is an essential part of the ECC algorithm, ensuring the two sides are equal to each other. As you can see, the left part is computed on the server side, and the right one is on client side.<\/p>\n<p>BTW, these randomly generated public and private keys are only valid in one TCP connection session, so they are called session public\/private keys. They are different from ID public\/private keys, which are fixed for one Obfs4 relay.<\/p>\n<p>Next, do you remember the IdPublicKey and nodeID that were extracted from the base64 encoded \u201ccert\u201d in a bridge configuration line, that I discussed earlier? Do you know where that IdPrivateKey is??? In fact, it is always kept in the Obfs4 relay.<\/p>\n<p>When an Obsf4 relay is installed and starts, it generates an IdPrivateKey\/IdPublicKey pair.\u00a0It keeps the IdPrivateKey and then publishes the IdPublicKey in the bridge configuration line that the Obfs4 client will be using. These are fixed to one Obfs4 relay. Both of these keys are ECC concept private\/public keys, just like the session keys.<\/p>\n<p>Next, both the client and the server call ScalarMult() twice to generate two common results. Let\u2019s first look at how the server does it:<\/p>\n<p>The server calls ScalarMult() with the server\u2019s session private key and the client\u2019s session public key, and then calls it again with the IdPrivateKey and the client\u2019s session public key. We have now produced two function results. They are then put together with the nodeID and some constant strings to generate a common \u201ckeySeed\u201d and the server\u2019s \u201cauth\u201d.<\/p>\n<p>Now, it\u2019s time to create the server\u2019s handshake packet. It contains all the components of the client handshake packet, and it has the server\u2019s auth element tucked between the representative and some padding data and a different padding data size range, as you can see in Table 2.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn--default--9 aem-GridColumn aem-GridColumn--offset--default--1\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image_654224671.img.png\/1575580500303\/screen-shot-2019-12-05-at-1.14.07-pm.png\" alt=\"Table 2. Server\u2019s handshake packet structure\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Table 2. Server\u2019s handshake packet structure<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>The server\u2019s auth element is used for the authentication of the client. The padding data size ranges from 0h ~ 1F73h, which keep the packet size random across a large range. This packet is then sent back to the client (obsf4proxy.exe) for verification. Remember, the server now has the common \u201ckeySeed\u201d for the current TCP connection session.<\/p>\n<p>When the server\u2019s handshake packet gets back to the client, it verifies the last two parts of the packet to ensure the packet is valid. It then extracts the server\u2019s session public key from the first part of the packet (i.e. server.representative).<\/p>\n<p>Now the client can call ScalarMult() twice, just like the server did. It calls ScalarMult() with the client\u2019s session private key and server\u2019s session public key, and then calls it again with the client\u2019s session private key and the IdPublicKey.<\/p>\n<p>Once again, we have two function results. The client then puts them together, and adds the nodeID and some constant strings that are same to the server\u2019s to generate a common \u201ckeySeed\u201d and \u201cauth\u201d data. The client then compares the just generated \u201cauth\u201d data with the one from server\u2019s handshake packet to complete the verification.<\/p>\n<p>The common \u201ckeySeed\u201d client just generated should be exactly the same as the server\u2019s. Using this common \u201ckeySeed\u201d, both the client and the server can proceed to generate their own final Encryption\/Decryption keys for Tor-payload\u2019s encryption and decryption. The client\u2019s encryption key is same as the server\u2019s decryption key, and the client\u2019s decryption key is same as the server\u2019s encryption key.<\/p>\n<p>This is the entire Obfs4 client and bridge handshake process. As a result, the packet size becomes random because it has a large range, and the data looks random too \u2013 which makes the handshake packets harder to be recognized by censors.<\/p>\n<h2>Obfs4 Sealing the Tor Payload<\/h2>\n<p>Both the client and the server initialize their Encoder and Decoder instances using the just-generated encryption key and decryption key derived from the common \u201ckeySeed\u201d. Obfs4 then uses these two instances to implement the sealing and unsealing of the Tor payload. The encoder instance is used for encryption, while the decoder instance is used for decryption.<\/p>\n<p>For now, the obfs4 client has two connections; one is for data being exchanged between Tor (\u201ctor.exe\u201d) and the Obfs4 client (\u201cobfs4proxy.exe\u201d), and the other one is for the Tor payload transfer between the Obfs4 Bridge client and the Bridge relay. Once the handshake process is completed, the Obfs4 client will bind the two connections. Figure 7 shows the code of the function copyLoop (in source file obfs4proxy.go) binding the two connections, where arguments \u201ca\u201d and \u201cb\u201d are instances of the two connections.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--11 aem-GridColumn--offset--default--0\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image_508526405.img.png\/1575580637971\/tor-ii-seven.png\" alt=\"Figure 7. Source code of the function copyLoop\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 7. Source code of the function copyLoop<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>The function \u201cio.Copy(destination, source)\u201d copies data from the source to the destination. The process is as follows: it calls the source.Read() function first and extracts specific data from it and then it calls destination.Write() with that extracted data in the parameter. <\/p>\n<p>The Obfs4 client overrides both Write() and Read(). The Write() function encrypts the Tor payload packets (called Sealing) and sends that sealed data out to the Obfs4 relay. Accordingly, the Read() function is in charge of receiving the packets from the Obfs4 relay and then decrypting them (called Unsealing). \u201cio.Copy\u201d then transfers the decrypted Tor packets to Tor.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--7 aem-GridColumn--offset--default--2\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image_108731547.img.png\/1575580761510\/tor-ii-eight.png\" alt=\"Figure 8. Overwritten Write() and Read() functions\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 8. Overwritten Write() and Read() functions<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>Let me detail how these two functions do this. As you can see in Figure 8, in Write(), it calls the function makePacket(), where it then calls another function, Encoder.Encode(), to encrypt the Tor payload. Decoder.Decode() is then called in the function \u201creadPackets()\u201d, which is called in Read(). <\/p>\n<p>Encoder.Encode() finally calls secretbox.Seal() to encrypt and make a MAC of the Tor payload. Correspondingly, Decoder.Decode() calls secretbox.Open() to decrypt the payload received from the Obfs4 relay.<\/p>\n<p>The encrypted data encrypted is not only the Tor payload. That payload is also copied into a data buffer at offset+3 because the first 3 bytes is sort of a header structure containing the packet type and size of the Tor payload just copied. This is all the data that Encoder.Encode() encrypts. <\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn--default--9 aem-GridColumn aem-GridColumn--offset--default--1\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image_1824762390.img.png\/1575580864797\/tor-ii-nine.png\" alt=\"Figure 9. Tor payload to be encrypted\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 9. Tor payload to be encrypted<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>Figure 9 shows an example of when the Obfs4 client is about to call Encoder.Encode(). One of its parameters points to the data buffer in memory, where the first byte is the packet type (00 means it\u2019s a payload packet), and the followed one word 0x00BF is the size of the Tor payload in network byte order. The data starting from offset+3 is the Tor payload, which comes from \u201ctor.exe\u201d.<\/p>\n<p>Obfs4 also obfuscates the packet size by appending a random size of padding data to the encrypted data. This is also a way to resist censorship.<\/p>\n<h2>Obfs4 Splitting Packets with IAT-Mode<br \/> <\/h2>\n<p>Besides the random padding of data, Obfs4 supports another anti-detection technique to resist censorship. That is the IAT-mode.<\/p>\n<p>In earlier sections of this analysis, \u201cIAT-mode\u201d was mentioned when describing Obfs4 Bridge information. IAT-mode is short for Inter-Arrival Timing, which can split a large packet (a packet size of more than 1448 bytes) into MTU size (Maximum Transmission Unit) or smaller packets.<\/p>\n<p>MTU is defined as the largest packet or frame size that can be used to transmit data. Network drivers split large packets into MTU size packets (negotiated in the TCP handshake), which can easily be reassembled \u2013 and identified by censors as well. That\u2019s why Obfs4 introduced IAT mode.<\/p>\n<p>The values of IAT-mode can be \u201c0\u201d, \u201c1\u201d, or \u201c2\u201d in obfs4.<\/p>\n<p>\u201c0\u201d means that the IAT-mode is disabled and that large packets will be split by the network drivers, whose network fingerprints could be detected by censors.<\/p>\n<p>\u201c1\u201d means splitting large packets into MTU-size packets instead of letting the network drivers do it. Here, the MTU is 1448 bytes for the Obfs4 Bridge. This means the smaller packets cannot be reassembled for analysis and censoring.\u00a0Figure 10 shows the code snippet of Obfs4 used to compute the MTU size.<\/p>\n<p>\u201c2\u201d means splitting large packets into variable size packets. The sizes are defined in Obfs4.\u00a0<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn--default--9 aem-GridColumn aem-GridColumn--offset--default--1\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image_160201608.img.png\/1575580949179\/tor-ii-ten.png\" alt=\"Figure 10. MTU size for Obfs4\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 10. MTU size for Obfs4<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>The smaller split packets will be sent to the Obsf4 relay separately. In this way, it can obfuscate any network fingerprinting and make Obfs4 traffic harder to be recognized.<\/p>\n<p>Figure 11 shows an example of Obfs4 traffic, with its IAT-mode set to \u201c1\u201d. Each red rectangle shows a large packet split by IAT-mode. The packets with a blue dot are the small split packets. For the first one, the original packet size is 2719, which was split into 2 smaller packets according to the Obfs4 MTU size (1448).<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn--default--9 aem-GridColumn aem-GridColumn--offset--default--1\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image_1731012720.img.png\/1575581028877\/tor-ii-eleven.png\" alt=\"Figure 11. IAT-mode enabled Obfs4 traffic\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 11. IAT-mode enabled Obfs4 traffic<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<h2>Getting Obfs4 Bridges Through Other Means<\/h2>\n<p>Tor users can get the Obfs4 Bridges three ways: The Tor Network Setting, The Tor website, and via email. Every time, you obtain three Obfs4 bridge configuration lines. Figure 12 is a screenshot of the Tor bridge website used for obtaining Obfs4 bridge configuration lines.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--7 aem-GridColumn--offset--default--2\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image_1667714274.img.png\/1575581108885\/tor-ii-twelve.png\" alt=\"Figure 12. Tor website for obtaining Obfs4 bridges\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 12. Tor website for obtaining Obfs4 bridges<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>Once you have obtained the Obfs4 Bridges, you next need to copy and paste them to get them working, as shown in Figure 13. <\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn--default--9 aem-GridColumn aem-GridColumn--offset--default--1\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image_1056216605.img.png\/1575581167895\/tor-ii-thirteen.png\" alt=\"Figure 13. Copy &amp; Paste three Obfs4 bridges\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 13. Copy &amp; Paste three Obfs4 bridges<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<h2>Conclusion<\/h2>\n<p>Through the analysis of the Obfs4 Bridge, we have learned that it can protect Tor traffic from being identified and blocked by censorship because:<\/p>\n<ul>\n<li>Obfs4 encrypts Tor traffic and obfuscates packet sizes by adding padding data, including in the handshake packets.<\/li>\n<li>Large Obfs4 packets can be split by IAT-mode to obfuscate the network fingerprint.<\/li>\n<li>Besides the built-in Obfs4 Bridges, Tor provides three other ways to obtain additional private Obfs4 Bridges.<\/li>\n<\/ul>\n<p><i>Learn more about\u00a0<a href=\"https:\/\/www.fortinet.com\/fortiguard\/threat-intelligence\/threat-research.html?utm_source=nreleaseblog&amp;utm_campaign=2018-q2-fortiguardlabs-cta\">FortiGuard Labs<\/a>\u00a0and the FortiGuard Security Services\u00a0<a href=\"https:\/\/www.fortinet.com\/support-and-training\/support-services\/fortiguard-security-subscriptions.html?utm_source=blog&amp;utm_campaign=2018-blog-security-services\">portfolio<\/a>.\u00a0<a href=\"https:\/\/www.fortinet.com\/fortiguard\/threat-intelligence\/threat-research.html?utm_source=nreleaseblog&amp;utm_campaign=2018-q2-fortiguardlabs-cta\">Sign up<\/a>\u00a0for our weekly FortiGuard Threat Brief.<\/i><\/p>\n<p><i>Read about the FortiGuard\u00a0<a href=\"https:\/\/www.fortinet.com\/support-and-training\/support-services\/fortiguard-security-subscriptions\/security-rating.html?utm_source=blog&amp;utm_campaign=2018-blog-security-rating-service\">Security Rating Service<\/a>, which provides security audits and best practices.<\/i><\/p>\n<\/p><\/div>\n<div class=\"raw-import aem-GridColumn aem-GridColumn--default--12\">\n<div class=\"text-container\">\n<div id=\"om-qxx1b0gslklfu2kjckea-holder\"><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<p><a href=\"http:\/\/feedproxy.google.com\/~r\/fortinet\/blog\/threat-research\/~3\/3KwghtUyOCs\/dissecting-tor-bridges-pluggable-transport-part-2.html\" target=\"bwo\" >http:\/\/feeds.feedburner.com\/fortinet\/blog\/threat-research<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p><img decoding=\"async\" src=\"\/blog\/threat-research\/dissecting-tor-bridges-pluggable-transport-part-2\/_jcr_content\/root\/responsivegrid\/image.img.png\/1575578249146\/tor-ii-one.png\"\/><br \/>In part two of this series on dissecting tor bridges and pluggable transport, our FortiGuard Labs researcher explores how Tor uses Obfs4 Bridge to circumvent censorship. Learn more.&lt;img src=&#8221;http:\/\/feeds.feedburner.com\/~r\/fortinet\/blog\/threat-research\/~4\/3KwghtUyOCs&#8221; height=&#8221;1&#8243; width=&#8221;1&#8243; alt=&#8221;&#8221;\/&gt;<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[10424,10378],"tags":[],"class_list":["post-17120","post","type-post","status-publish","format-standard","hentry","category-fortinet","category-security"],"_links":{"self":[{"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts\/17120","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/comments?post=17120"}],"version-history":[{"count":0,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts\/17120\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/media?parent=17120"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/categories?post=17120"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/tags?post=17120"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}