<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>saminiir's hacker blog</title>
    <description>Yet Another Hacker Blog (YAHB). UNIX, Networking, Self-Improvement.
</description>
    <link>https://www.saminiir.com/</link>
    <atom:link href="https://www.saminiir.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Thu, 22 Oct 2020 11:33:59 +0000</pubDate>
    <lastBuildDate>Thu, 22 Oct 2020 11:33:59 +0000</lastBuildDate>
    <generator>Jekyll v3.9.0</generator>
    
      <item>
        <title>Paper storage and recovery of GPG keys</title>
        <description>&lt;p&gt;To avoid disastrously losing your private keys, they should be redundantly backed up in a robust manner in a safe location.&lt;/p&gt;

&lt;p&gt;As one possible approach, we will store the GPG keyring as QR codes, print them on paper, and demonstrate recovering the keyring. Do note that this method excludes backing up the trust database.&lt;/p&gt;

&lt;p&gt;For general GPG usage, consult my &lt;a href=&quot;/establish-cryptographic-identity-using-gnupg/&quot;&gt;previous post on handling GPG keys&lt;/a&gt;.&lt;/p&gt;

&lt;h1 class=&quot;no_toc&quot; id=&quot;contents&quot;&gt;Contents&lt;/h1&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#dependencies&quot; id=&quot;markdown-toc-dependencies&quot;&gt;Dependencies&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#exporting-the-key&quot; id=&quot;markdown-toc-exporting-the-key&quot;&gt;Exporting the key&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#backing-up-the-key&quot; id=&quot;markdown-toc-backing-up-the-key&quot;&gt;Backing up the key&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#recovering-the-key&quot; id=&quot;markdown-toc-recovering-the-key&quot;&gt;Recovering the key&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sources&quot; id=&quot;markdown-toc-sources&quot;&gt;Sources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;dependencies&quot;&gt;Dependencies&lt;/h1&gt;

&lt;p&gt;Consult the Internet or your distro’s package mirrors for the following packages:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://gnupg.org/&quot;&gt;gpg2&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ImageMagick/ImageMagick&quot;&gt;ImageMagick&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/fukuchi/libqrencode&quot;&gt;qrencode&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://zbar.sourceforge.net/&quot;&gt;zbar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;exporting-the-key&quot;&gt;Exporting the key&lt;/h1&gt;

&lt;p&gt;First, we’ll peruse gpg’s manual pages about exporting keys:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nt&quot;&gt;--export-secret-keys&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--export-secret-subkeys&lt;/span&gt;
       Same as &lt;span class=&quot;nt&quot;&gt;--export&lt;/span&gt;, but exports the secret keys instead.  The exported keys are written to STDOUT or to the file given with option &lt;span class=&quot;nt&quot;&gt;--output&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;  This &lt;span class=&quot;nb&quot;&gt;command &lt;/span&gt;is often used along with the option  &lt;span class=&quot;nt&quot;&gt;--armor&lt;/span&gt;  to  allow  &lt;span class=&quot;k&quot;&gt;for  &lt;/span&gt;easy
       printing  of  the  key  &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;paper backup&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; however the external tool paperkey does a better job of creating backups on paper.  Note that exporting a secret key can be a security risk &lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;the exported keys are sent over an
       insecure channel.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Important point being, never transmit private keys over an insecure medium.&lt;/p&gt;

&lt;p&gt;Export your private and public keys into a keyring:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--export-secret-keys&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--export-options&lt;/span&gt; export-minimal &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; private-keyring.gpg&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The reason I am not using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;paperkey&lt;/code&gt; is that it requires corresponding public keys to be stored elsewhere. I want both private and public keys stored on the paper for easier retrieval in case of emergency.&lt;/p&gt;

&lt;h1 id=&quot;backing-up-the-key&quot;&gt;Backing up the key&lt;/h1&gt;

&lt;p&gt;Let’s base64 encode the keyring and split it into smaller bytes because of QR code storage limitations&lt;sup id=&quot;fnref:qr-code-storage&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:qr-code-storage&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;base64 &lt;/span&gt;private-keyring.gpg &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; private-keyring.base64
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;split&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; 2500 private-keyring.base64 splitkey-&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then, we’ll use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qrencode&lt;/code&gt;&lt;sup id=&quot;fnref:qrencode&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:qrencode&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; to create QR code pictures:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;i &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;splitkey-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do &lt;/span&gt;qrencode &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.PNG&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Finally, concatenate the pictures into a single photo for printing purposes:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;montage &lt;span class=&quot;nt&quot;&gt;-mode&lt;/span&gt; Concatenate &lt;span class=&quot;nt&quot;&gt;-tile&lt;/span&gt; 2x splitkey-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.PNG keyring-qr-codes.PNG&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then, print this on paper.&lt;/p&gt;

&lt;h1 id=&quot;recovering-the-key&quot;&gt;Recovering the key&lt;/h1&gt;

&lt;p&gt;Now, what to do when this paper backup is your only option left?&lt;/p&gt;

&lt;p&gt;Scan the QR codes from the paper as JPEG, for example (EDIT: Actually, do PNG&lt;sup id=&quot;fnref:png-correction&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:png-correction&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;).&lt;/p&gt;

&lt;p&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zbarimg&lt;/code&gt; to decode the QR codes as data:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zbarimg &lt;span class=&quot;nt&quot;&gt;--raw&lt;/span&gt; qr-codes.jpg &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; keyring.base64&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Your mileage will probably vary on the scan’s success rate. I had to manually crop the QR codes into separate JPEGs in order to construct the resulting base64 in correct order. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zbarimg&lt;/code&gt; also adds newlines to the scanned data, so essentially manual reconstruction of the base64 data is needed.&lt;/p&gt;

&lt;p&gt;Now, you can import it into a gpg instance:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;base64&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; keyring.base64 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; keyring.gpg
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; .gnupg/private-keys-v1.d
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--homedir&lt;/span&gt; .gnupg &lt;span class=&quot;nt&quot;&gt;--import&lt;/span&gt; keyring.gpg
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;-K&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You should now be able to decrypt any private data stored.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;This approach is just one solution for backing up your GPG keys and recovering them in case of emergency. Also, if disaster strikes, it is good to have some routine/documentation on the recovery actions. This article serves as such document.&lt;/p&gt;

&lt;p&gt;If you liked this post, you can
&lt;a href=&quot;https://twitter.com/intent/tweet?url=https://www.saminiir.com/paper-storage-and-recovery-of-gpg-keys/&amp;amp;text=Paper+storage+and+recovery+of+GPG+keys&amp;amp;via=saminiir&quot; target=&quot;_blank&quot;&gt;
  share it with your followers&lt;/a&gt; 
and 
&lt;a href=&quot;https://twitter.com/saminiir&quot;&gt;
  follow me on Twitter&lt;/a&gt;!&lt;/p&gt;

&lt;h1 id=&quot;sources&quot;&gt;Sources&lt;/h1&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:qr-code-storage&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/QR_code#Storage&quot;&gt;https://en.wikipedia.org/wiki/QR_code#Storage&lt;/a&gt; &lt;a href=&quot;#fnref:qr-code-storage&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:qrencode&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/fukuchi/libqrencode&quot;&gt;https://github.com/fukuchi/libqrencode&lt;/a&gt; &lt;a href=&quot;#fnref:qrencode&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:png-correction&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=18228408&quot;&gt;https://news.ycombinator.com/item?id=18228408&lt;/a&gt; &lt;a href=&quot;#fnref:png-correction&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Tue, 16 Oct 2018 10:00:00 +0000</pubDate>
        <link>https://www.saminiir.com/paper-storage-and-recovery-of-gpg-keys/</link>
        <guid isPermaLink="true">https://www.saminiir.com/paper-storage-and-recovery-of-gpg-keys/</guid>
        
        
        <category>gpg</category>
        
        <category>cryptography</category>
        
      </item>
    
      <item>
        <title>Let's code a TCP/IP stack, 5: TCP Retransmission</title>
        <description>&lt;p&gt;At this point we have a TCP/IP stack that is able to communicate to other hosts in the Internet. The implementation so far has been fairly straight-forward, but missing a major feature: Reliability.&lt;/p&gt;

&lt;p&gt;Namely, our TCP does not guarantee the integrity of the data stream it presents to applications. Even establishing the connection can fail if the handshake packets are lost in transit.&lt;/p&gt;

&lt;p&gt;Introducing reliability and control is our next main focus in creating a TCP/IP stack from scratch.&lt;/p&gt;

&lt;h1 class=&quot;no_toc&quot; id=&quot;contents&quot;&gt;Contents&lt;/h1&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#automatic-repeat-request&quot; id=&quot;markdown-toc-automatic-repeat-request&quot;&gt;Automatic Repeat Request&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tcp-retransmission&quot; id=&quot;markdown-toc-tcp-retransmission&quot;&gt;TCP Retransmission&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#karns-algorithm&quot; id=&quot;markdown-toc-karns-algorithm&quot;&gt;Karn’s Algorithm&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#managing-the-rto-timer&quot; id=&quot;markdown-toc-managing-the-rto-timer&quot;&gt;Managing the RTO timer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#requesting-retransmission&quot; id=&quot;markdown-toc-requesting-retransmission&quot;&gt;Requesting retransmission&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#trying-it-out&quot; id=&quot;markdown-toc-trying-it-out&quot;&gt;Trying it out&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sources&quot; id=&quot;markdown-toc-sources&quot;&gt;Sources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;automatic-repeat-request&quot;&gt;Automatic Repeat Request&lt;/h1&gt;

&lt;p&gt;The basis for many reliable protocols is the concept of Automatic Repeat reQuest (ARQ)&lt;sup id=&quot;fnref:arq&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:arq&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;In ARQ, a receiver sends acknowledgments for data it has received, and the sender retransmits data it never received acknowledgements for.&lt;/p&gt;

&lt;p&gt;As we have discussed, TCP keeps the sequence numbers of transmitted data in memory and responds with acknowledgments. The transmitted data is put into a retransmission queue and timers associated with the data are started. If no acknowledgment for the sequence of data is received before the timer runs out, a retransmission occurs.&lt;/p&gt;

&lt;p&gt;As can be seen, TCP builds its reliability on the principles of ARQ. However, detailed implementations of ARQ are involved. Simple questions like “how long should the sender wait for an acknowledgement?” are tricky to answer, especially when maximum performance is desired. TCP extensions like Selective Acknowledgments (SACK)&lt;sup id=&quot;fnref:sack&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:sack&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; alleviate efficiency problems by acknowledging out-of-order data and avoiding unnecessary round-trips.&lt;/p&gt;

&lt;h1 id=&quot;tcp-retransmission&quot;&gt;TCP Retransmission&lt;/h1&gt;

&lt;p&gt;Retransmissions in TCP are described in the original specification&lt;sup id=&quot;fnref:tcp-spec&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:tcp-spec&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; as:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;When the TCP transmits a segment containing data, it puts a copy on a retransmission queue and starts a timer; when the acknowledgment for that data is received, the segment is deleted from the queue.  If the acknowledgment is not received before the timer runs out, the segment is retransmitted.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;However, the original formula for calculating the retransmission timeout was deemed inadequate for different network environments. The current “standard method”&lt;sup id=&quot;fnref:stevens-tcpip&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:stevens-tcpip&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; was described by Jacobson&lt;sup id=&quot;fnref:cong-avoid&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:cong-avoid&quot; class=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; and the latest codified specification can be found from RFC6298&lt;sup id=&quot;fnref:computing-timer&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:computing-timer&quot; class=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;The basic algorithm is relatively straightforward. For a given TCP sender, state variables are defined for calculating the timeout:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;srtt&lt;/code&gt; is &lt;em&gt;smoothed round-trip time&lt;/em&gt; for averaging the round-trip time (RTT) of a segment&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rttvar&lt;/code&gt; holds the &lt;em&gt;round-trip time variation&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rto&lt;/code&gt; eventually holds the &lt;em&gt;retransmission timeout&lt;/em&gt;, e.g. in milliseconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;srtt&lt;/code&gt; acts as a low-pass filter for consecutive RTTs. Due to possible large variation in the RTT, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rttvar&lt;/code&gt; is used to detect those changes and prevent them from skewing the averaging function. Additionally, a clock granularity of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G&lt;/code&gt; seconds is assumed.&lt;/p&gt;

&lt;p&gt;As described in RFC6298&lt;sup id=&quot;fnref:computing-timer:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:computing-timer&quot; class=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;, the steps for computation are as follows:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Before the first RTT measurement:
    &lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;rto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ms&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;On the first RTT measurement &lt;em&gt;R&lt;/em&gt;:
    &lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;srtt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rttvar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;srtt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rttvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;On subsequent measurements:
    &lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.125&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;beta&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.25&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rttvar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rttvar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beta&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;srtt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;srtt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;srtt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;srtt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rttvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;After computing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rto&lt;/code&gt;, if it is less than 1 second, round it up to 1 second. A maximum amount can be provided but it has to be at least 60 seconds&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The clock granularity of TCP implementations has traditionally been estimated to be fairly high, ranging from 500ms to 1 second. Modern systems like Linux, however, use a clock granularity of 1 millisecond&lt;sup id=&quot;fnref:stevens-tcpip:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:stevens-tcpip&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;One thing to note is that the RTO is suggested to always be at least 1 second. This is to guard against &lt;em&gt;spurious retransmissions&lt;/em&gt;, i.e. when a segment is retransmitted too soon, causing congestion in the network. In practice, many implementations go for sub-second rounding: Linux uses 200 milliseconds.&lt;/p&gt;

&lt;h1 id=&quot;karns-algorithm&quot;&gt;Karn’s Algorithm&lt;/h1&gt;

&lt;p&gt;One mandatory algorithm that prevents the RTT measurement from giving false results is &lt;em&gt;Karn’s Algorithm&lt;/em&gt;&lt;sup id=&quot;fnref:karns-algorithm&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:karns-algorithm&quot; class=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;. It simply states that the RTT samples should not be taken for retransmitted packets.&lt;/p&gt;

&lt;p&gt;In other words, the TCP sender keeps track whether the segment it sent was a retransmission and skips the RTT routine for those acknowledgments. This makes sense, since otherwise the sender could not distinguish acknowledgements between the original and retransmitted segment.&lt;/p&gt;

&lt;p&gt;When utilizing the timestamp TCP option, however, the RTT can be measured for every ACK segment. We will deal with the TCP Timestamp option in a separate blog post.&lt;/p&gt;

&lt;h1 id=&quot;managing-the-rto-timer&quot;&gt;Managing the RTO timer&lt;/h1&gt;

&lt;p&gt;Managing the retransmission timer is relatively straightforward. RFC6298 recommends the following algorithm:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;When sending a data segment and the RTO timer is not running, activate it with the timeout value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rto&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;When all outstanding data segments have been acknowledged, turn off the RTO timer&lt;/li&gt;
  &lt;li&gt;When an ACK is received for new data, restart the RTO timer with the value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rto&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And when the RTO timer expires:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Retransmit the earliest unacknowledged segment&lt;/li&gt;
  &lt;li&gt;Back off the RTO timer with a factor of 2, i.e. (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rto = rto * 2&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Start the RTO timer&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Additionally, when the backing off of the RTO value occurs and a subsequent measurement is successfully made, the RTO value can shrink drastically. The TCP implementation may clear &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;srtt&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rttvar&lt;/code&gt; when backing off and waiting for an acknowledgment&lt;sup id=&quot;fnref:computing-timer:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:computing-timer&quot; class=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h1 id=&quot;requesting-retransmission&quot;&gt;Requesting retransmission&lt;/h1&gt;

&lt;p&gt;A TCP is usually not only relying on the TCP sender’s timers to fix lost packets. The receiving side can also inform the sender that segments need to be retransmitted.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Duplicate acknowledgment&lt;/em&gt; is an algorithm where out-of-sequence segments are acknowledged, but by the sequence number of the latest in-order segment. After three duplicate acknowledgments, the TCP sender should realize that it needs to retransmit the segment that was advertised by the duplicate acknowledgments.&lt;/p&gt;

&lt;p&gt;Furthermore, &lt;em&gt;Selective Acknowledgment&lt;/em&gt; (SACK) is a more sophisticated version of the duplicate acknowledgment. It is a TCP option where the receiver is able to encode the received sequences into its acknowledgements. Then the sender immediately notices any lost segments and resends them. We will discuss the SACK TCP option in a later blog post.&lt;/p&gt;

&lt;h1 id=&quot;trying-it-out&quot;&gt;Trying it out&lt;/h1&gt;

&lt;p&gt;Now that we’ve gone through the concepts and general algorithms, let’s see how TCP retransmissions look like on the wire.&lt;/p&gt;

&lt;p&gt;Let’s change the firewall rules to drop packets after the connection is established and try to fetch the front page of HN:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-I&lt;/span&gt; FORWARD &lt;span class=&quot;nt&quot;&gt;--in-interface&lt;/span&gt; tap0 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; conntrack &lt;span class=&quot;nt&quot;&gt;--ctstate&lt;/span&gt; ESTABLISHED &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; DROP
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./tools/level-ip curl news.ycombinator.com
curl: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;56&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; Recv failure: Connection timed out&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Observing the connection traffic we see that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP GET&lt;/code&gt; is retransmitted with roughly a doubling interval:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;saminiir@localhost ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;tcpdump &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; tap0 host 10.0.0.4 &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ttttt&lt;/span&gt;
00:00:00.000000 IP 10.0.0.4.41733 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 104.20.44.44.80: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;S], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;3975419138, win 44477, options &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;mss 1460], length 0
00:00:00.004318 IP 104.20.44.44.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.41733: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;S.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;4164704437, ack 3975419139, win 29200, options &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;mss 1460], length 0
00:00:00.004534 IP 10.0.0.4.41733 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 104.20.44.44.80: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 1, win 44477, length 0
00:00:00.011039 IP 10.0.0.4.41733 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 104.20.44.44.80: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1:85, ack 1, win 44477, length 84: HTTP: GET / HTTP/1.1
00:00:01.094237 IP 104.20.44.44.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.41733: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;S.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;4164704437, ack 3975419139, win 29200, options &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;mss 1460], length 0
00:00:01.094479 IP 10.0.0.4.41733 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 104.20.44.44.80: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 1, win 44477, length 0
00:00:01.210787 IP 10.0.0.4.41733 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 104.20.44.44.80: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1:85, ack 1, win 44477, length 84: HTTP: GET / HTTP/1.1
00:00:03.607225 IP 10.0.0.4.41733 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 104.20.44.44.80: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1:85, ack 1, win 44477, length 84: HTTP: GET / HTTP/1.1
00:00:08.399056 IP 10.0.0.4.41733 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 104.20.44.44.80: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1:85, ack 1, win 44477, length 84: HTTP: GET / HTTP/1.1
00:00:18.002415 IP 10.0.0.4.41733 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 104.20.44.44.80: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1:85, ack 1, win 44477, length 84: HTTP: GET / HTTP/1.1
00:00:37.289491 IP 10.0.0.4.41733 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 104.20.44.44.80: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1:85, ack 1, win 44477, length 84: HTTP: GET / HTTP/1.1
00:01:15.656151 IP 10.0.0.4.41733 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 104.20.44.44.80: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1:85, ack 1, win 44477, length 84: HTTP: GET / HTTP/1.1
00:02:32.590664 IP 10.0.0.4.41733 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 104.20.44.44.80: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1:85, ack 1, win 44477, length 84: HTTP: GET / HTTP/1.1&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Verifying the retransmission back-off and the receiver going silent is easy, but what about the scenario when retransmissions are triggered only for some segments? For optimal performance, the RTO algorithm needs to ‘bounce back’ when the connection is detected as healthy.&lt;/p&gt;

&lt;p&gt;Let’s set the firewall rule to only block the 6th packet for 6000 bytes:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-I&lt;/span&gt; FORWARD &lt;span class=&quot;nt&quot;&gt;--in-interface&lt;/span&gt; tap0 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; connbytes &lt;span class=&quot;nt&quot;&gt;--connbytes&lt;/span&gt; 6 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;--connbytes-dir&lt;/span&gt; original &lt;span class=&quot;nt&quot;&gt;--connbytes-mode&lt;/span&gt; packets &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; quota &lt;span class=&quot;nt&quot;&gt;--quota&lt;/span&gt; 6000 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; DROP&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now, if we try to send some data, our TCP has to recognize the communication blackout and when it ends. Let’s send 6009 bytes:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./tools/level-ip curl &lt;span class=&quot;nt&quot;&gt;-X&lt;/span&gt; POST http://httpbin.org/post &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;payload=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;perl &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;print 'lorem ipsum ' x500&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Let’s step through the connection phases, see when retransmissions are triggered and how the RTO value changes. Below is a modified &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tcpdump&lt;/code&gt; output with inline comments about our TCP socket’s internal state:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;00.000000 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;S], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1, options &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;mss 1460]
00.120709 httpbin.org.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.49951: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;S.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1, ack 1, options &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;mss 8961]
00.120951 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 1

- Connection established, TCP RTO value of 10.0.0.4:49951 is 1000 milliseconds.

00.122686 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1:174, ack 1: POST /post
00.242564 httpbin.org.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.49951: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 174
01.141287 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;174:1634, ack 1: HTTP
01.141386 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1634:3094, ack 1: HTTP
01.141460 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;3094:4554, ack 1: HTTP
01.263301 httpbin.org.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.49951: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 1634
01.265995 httpbin.org.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.49951: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 3094

- So far so good, the remote host has acked our HTTP POST 
  and the start of our payload. RTO value is 336ms.

01.526797 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;3094:4554, ack 1: HTTP
02.259425 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;3094:4554, ack 1: HTTP
03.735553 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;3094:4554, ack 1: HTTP

- The communication blackout caused by our iptables rule has started.
  Our TCP has to retransmit the segment multiple times. 
  The RTO value of the socket keeps increasing:
    01.526797: 618ms
    02.259425: 1236ms
    03.735553: 2472ms

06.692867 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;3094:4554, ack 1: HTTP
06.819115 httpbin.org.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.49951: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 4554

- Finally the remote host responds. Our RTO value has increased to 4944ms.
  Karn&lt;span class=&quot;se&quot;&gt;\'&lt;/span&gt;s Algorithm takes effect here: The new RTO value cannot be measured
  with the retransmitted segment, so we skip it.

06.819356 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;4554:6014, ack 1: HTTP
06.819442 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;6014:6182, ack 1: HTTP
06.948678 httpbin.org.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.49951: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 6014
06.948917 httpbin.org.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.49951: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 6182

- Now we get ACKs on the first try and the network is relatively healthy again.
  Karn&lt;span class=&quot;se&quot;&gt;\'&lt;/span&gt;s Algorithm allows us to measure the new RTO:
    06.948678: 309ms
    06.948917: 309ms
  
06.948942 httpbin.org.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.49951: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1:26, ack 6182: HTTP 100 Continue
06.949014 httpbin.org.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.49951: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;26:1486, ack 6182: HTTP/1.1 200 OK
06.949145 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 26
06.949816 httpbin.org.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.49951: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1486:2946, ack 6182: HTTP
06.949894 httpbin.org.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.49951: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;2946:4406, ack 6182: HTTP
06.950029 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 2946
06.950030 httpbin.org.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.49951: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;4406:5866, ack 6182: HTTP
06.950161 httpbin.org.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.49951: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;5866:6829, ack 6182: HTTP
06.950287 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 5866
06.950435 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 6829
06.958155 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;F.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;6182, ack 6829
07.082998 httpbin.org.80 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.49951: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;F.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;6829, ack 6183
07.083253 10.0.0.4.49951 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; httpbin.org.80: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 6830

- The data communication and connection is finished.
  No significant changes to the RTO measurement occur.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;Retransmissions in TCP are an essential part of a robust implementation. A TCP has to survive and be performant in changing network environments, where for example the latencies can suddenly spike or the network path is blocked for a moment.&lt;/p&gt;

&lt;p&gt;Next time, we will take a look at TCP Congestion Control for achieving maximum performance without degrading the network’s health.&lt;/p&gt;

&lt;p&gt;I’d be happy if you try the project out and give feedback. See &lt;a href=&quot;https://github.com/saminiir/level-ip/blob/master/Documentation/getting-started.md&quot;&gt;Getting Started&lt;/a&gt; on how to use it with cURL and Firefox!&lt;/p&gt;

&lt;p&gt;If you liked this post, you can
&lt;a href=&quot;https://twitter.com/intent/tweet?url=https://www.saminiir.com/lets-code-tcp-ip-stack-5-tcp-retransmission/&amp;amp;text=Let%27s+code+a+TCP%2FIP+stack%2C+5%3A+TCP+Retransmission&amp;amp;via=saminiir&quot; target=&quot;_blank&quot;&gt;
  share it with your followers&lt;/a&gt; 
and 
&lt;a href=&quot;https://twitter.com/saminiir&quot;&gt;
  follow me on Twitter&lt;/a&gt;!&lt;/p&gt;

&lt;h1 id=&quot;sources&quot;&gt;Sources&lt;/h1&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:arq&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Automatic_repeat_request&quot;&gt;https://en.wikipedia.org/wiki/Automatic_repeat_request&lt;/a&gt; &lt;a href=&quot;#fnref:arq&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:sack&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc2018&quot;&gt;https://tools.ietf.org/html/rfc2018&lt;/a&gt; &lt;a href=&quot;#fnref:sack&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:tcp-spec&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://www.ietf.org/rfc/rfc793.txt&quot;&gt;https://www.ietf.org/rfc/rfc793.txt&lt;/a&gt; &lt;a href=&quot;#fnref:tcp-spec&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:stevens-tcpip&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/TCP/IP_Illustrated#Volume_1:_The_Protocols&quot;&gt;https://en.wikipedia.org/wiki/TCP/IP_Illustrated#Volume_1:_The_Protocols&lt;/a&gt; &lt;a href=&quot;#fnref:stevens-tcpip&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:stevens-tcpip:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:cong-avoid&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://ee.lbl.gov/papers/congavoid.pdf&quot;&gt;http://ee.lbl.gov/papers/congavoid.pdf&lt;/a&gt; &lt;a href=&quot;#fnref:cong-avoid&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:computing-timer&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc6298&quot;&gt;https://tools.ietf.org/html/rfc6298&lt;/a&gt; &lt;a href=&quot;#fnref:computing-timer&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:computing-timer:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;#fnref:computing-timer:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:karns-algorithm&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Karn%27s_Algorithm&quot;&gt;https://en.wikipedia.org/wiki/Karn%27s_Algorithm&lt;/a&gt; &lt;a href=&quot;#fnref:karns-algorithm&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 05 Jul 2017 10:00:00 +0000</pubDate>
        <link>https://www.saminiir.com/lets-code-tcp-ip-stack-5-tcp-retransmission/</link>
        <guid isPermaLink="true">https://www.saminiir.com/lets-code-tcp-ip-stack-5-tcp-retransmission/</guid>
        
        
        <category>tcp/ip</category>
        
        <category>tutorial</category>
        
        <category>c programming</category>
        
        <category>ip</category>
        
        <category>networking</category>
        
        <category>linux</category>
        
      </item>
    
      <item>
        <title>Let's code a TCP/IP stack, 4: TCP Data Flow &amp; Socket API</title>
        <description>&lt;p&gt;Previously, we introduced ourselves to the TCP header and how a connection is established between two parties.&lt;/p&gt;

&lt;p&gt;In this post, we will look into TCP data communication and how it is managed.&lt;/p&gt;

&lt;p&gt;Additionally, we will provide an interface from the networking stack that applications can use for network communication. This &lt;em&gt;Socket API&lt;/em&gt; is then utilized by our example application to send a simple HTTP request to a website.&lt;/p&gt;

&lt;h1 class=&quot;no_toc&quot; id=&quot;contents&quot;&gt;Contents&lt;/h1&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#transmission-control-block&quot; id=&quot;markdown-toc-transmission-control-block&quot;&gt;Transmission Control Block&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tcp-data-communication&quot; id=&quot;markdown-toc-tcp-data-communication&quot;&gt;TCP Data Communication&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tcp-connection-termination&quot; id=&quot;markdown-toc-tcp-connection-termination&quot;&gt;TCP Connection Termination&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#socket-api&quot; id=&quot;markdown-toc-socket-api&quot;&gt;Socket API&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#testing-our-socket-api&quot; id=&quot;markdown-toc-testing-our-socket-api&quot;&gt;Testing our Socket API&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sources&quot; id=&quot;markdown-toc-sources&quot;&gt;Sources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;transmission-control-block&quot;&gt;Transmission Control Block&lt;/h1&gt;

&lt;p&gt;It is beneficial to start the discussion on TCP data management by defining the variables that record the data flow state.&lt;/p&gt;

&lt;p&gt;In short, the TCP has to keep track of the sequences of data it has sent and received acknowledgments for. To achieve this, a data structure called the &lt;em&gt;Transmission Control Block&lt;/em&gt; (TCB) is initialized for every opened connection.&lt;/p&gt;

&lt;p&gt;The variables for the outgoing (sending) side are:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;    Send Sequence Variables
	
      SND.UNA - send unacknowledged
      SND.NXT - send next
      SND.WND - send window
      SND.UP  - send urgent pointer
      SND.WL1 - segment sequence number used &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;last window update
      SND.WL2 - segment acknowledgment number used &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;last window update
      ISS     - initial send sequence number&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In turn, the following data is recorded for the receiving side:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;    Receive Sequence Variables
											  
      RCV.NXT - receive next
      RCV.WND - receive window
      RCV.UP  - receive urgent pointer
      IRS     - initial receive sequence number&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Additionally, helper variables of the current segment being processed are defined followingly:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;    Current Segment Variables
	
      SEG.SEQ - segment sequence number
      SEG.ACK - segment acknowledgment number
      SEG.LEN - segment length
      SEG.WND - segment window
      SEG.UP  - segment urgent pointer
      SEG.PRC - segment precedence value&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Together, these variables constitute most of the TCP control logic for a given connection.&lt;/p&gt;

&lt;h1 id=&quot;tcp-data-communication&quot;&gt;TCP Data Communication&lt;/h1&gt;

&lt;p&gt;Once a connection is established, explicit handling of the data flow starts. Three variables from the TCB are important for basic tracking of the state:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SND.NXT&lt;/code&gt; - The sender will track the next sequence number to use in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SND.NXT&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RCV.NXT&lt;/code&gt; - The receiver records the next sequence number to expect in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RCV.NXT&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SND.UNA&lt;/code&gt; - The sender will record the &lt;em&gt;oldest&lt;/em&gt; unacknowledged sequence number in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SND.UNA&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Given a sufficient time period when TCP is managing the data communication and no transmit occurs, all these three variables will be equal.&lt;/p&gt;

&lt;p&gt;For example, when A decides to send a segment with data to B, the following happens:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;TCP A sends a segment and advances &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SND.NXT&lt;/code&gt; in its own records (TCB).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;TCB B receives the segment and acknowledges it by advancing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RCV.NXT&lt;/code&gt; and sends an ACK.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;TCB A receives the ACK and advances &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SND.UNA&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The amount by which the variables are advanced is the length of the data in the segment.&lt;/p&gt;

&lt;p&gt;This is the basis for TCP control logic over the transmit of data. Let’s see how this looks like with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tcpdump(1)&lt;/code&gt;, a popular utility for capturing network traffic:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;saminiir@localhost level-ip]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;tcpdump &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; any port 8000 &lt;span class=&quot;nt&quot;&gt;-nt&lt;/span&gt;
IP 10.0.0.4.12000 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.5.8000: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;S], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1525252, win 29200, length 0
IP 10.0.0.5.8000 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.12000: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;S.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;825056904, ack 1525253, win 29200, options &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;mss 1460], length 0
IP 10.0.0.4.12000 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.5.8000: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 1, win 29200, length 0&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The address 10.0.0.4 (host A) initiates a connection from port 12000 to host 10.0.0.5 (host B) listening on port 8000.&lt;/p&gt;

&lt;p&gt;After the three-way handshake, the connection is established and their internal TCP socket state is set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESTABLISHED&lt;/code&gt;. Initial sequence numbers are 1525252 for A, and 825056904 for B.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;IP 10.0.0.4.12000 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.5.8000: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1:18, ack 1, win 29200, length 17
IP 10.0.0.5.8000 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.12000: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 18, win 29200, length 0&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Host A sends a segment with 17 bytes of data, which host B acknowledges with an ACK segment. Relative sequence numbers are shown by default with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tcpdump&lt;/code&gt; to ease readability. Thus, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ack 18&lt;/code&gt; is actually 1525253 + 17.&lt;/p&gt;

&lt;p&gt;Internally, the TCP of the receiving host (B) has advanced &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RCV.NXT&lt;/code&gt; with the number 17.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;IP 10.0.0.4.12000 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.5.8000: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 1, win 29200, length 0
IP 10.0.0.5.8000 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.12000: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1:18, ack 18, win 29200, length 17
IP 10.0.0.4.12000 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.5.8000: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 18, win 29200, length 0
IP 10.0.0.5.8000 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.12000: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;18:156, ack 18, win 29200, length 138
IP 10.0.0.4.12000 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.5.8000: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 156, win 29200, length 0
IP 10.0.0.5.8000 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.12000: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;P.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;156:374, ack 18, win 29200, length 218
IP 10.0.0.4.12000 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.5.8000: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 374, win 29200, length 0&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The interplay of sending data and acknowledging it continues. As can be seen, the segments with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;length 0&lt;/code&gt; only have the ACK flag set, but the acknowledgement sequence numbers are precisely increment based on the previously received segment’s length.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;IP 10.0.0.5.8000 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.4.12000: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;F.], &lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;374, ack 18, win 29200, length 0
IP 10.0.0.4.12000 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 10.0.0.5.8000: Flags &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;.], ack 375, win 29200, length 0&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Host B informs host A that it has no more data to send by generating a FIN segment. In turn, host A acknowledges this.&lt;/p&gt;

&lt;p&gt;To finish the connection, host A also has to signal that it has no more data to send.&lt;/p&gt;

&lt;h1 id=&quot;tcp-connection-termination&quot;&gt;TCP Connection Termination&lt;/h1&gt;

&lt;p&gt;Closing a TCP connection is likewise an involved operation, and can be forcibly terminated (RST) or finished with a mutual agreement (FIN).&lt;/p&gt;

&lt;p&gt;The basic scenario is as follows:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The &lt;em&gt;active closer&lt;/em&gt; sends a FIN segment.&lt;/li&gt;
  &lt;li&gt;The &lt;em&gt;passive closer&lt;/em&gt; acknowledges this by sending an ACK segment.&lt;/li&gt;
  &lt;li&gt;The &lt;em&gt;passive closer&lt;/em&gt; starts its own close operation (when it has no more data to send) and effectively becomes an &lt;em&gt;active closer&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Once both sides have sent a FIN to each other and they have acknowledged them to both directions, the connection closes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Evidently, the closing of a TCP connection requires four segments, in contrast to the three segments of the TCP connection establishment (three-way handshake).&lt;/p&gt;

&lt;p&gt;Additionally, TCP is a bi-directional protocol, so it is possible to have the other end announce it has no more data to send, but stay online for incoming data. This is called &lt;em&gt;TCP Half-close&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The unreliable nature of packet-switched networks introduce additional complexity to the connection termination - FIN segments can disappear or never intentionally be sent, which leaves the connection in an awkward state. For example, in Linux the kernel parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tcp_fin_timeout&lt;/code&gt; controls how many seconds TCP waits for a final FIN packet, before forcibly closing the connection. This is a violation of the specification, but is needed for Denial of Service (DoS) prevention.&lt;sup id=&quot;fnref:man-tcp&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:man-tcp&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Aborting a connection involves a segment with the RST flag set. Resets can occur because of many reasons, but some usual ones are:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Connection request to a nonexistent port or interface&lt;/li&gt;
  &lt;li&gt;The other TCP has crashed and ends up in a out-of-sync connection state&lt;/li&gt;
  &lt;li&gt;Attempts to disturb existing connections&lt;sup id=&quot;fnref:tcp-rst-attack&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:tcp-rst-attack&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thus, the happy path of TCP data transmission never involves a RST segment.&lt;/p&gt;

&lt;h1 id=&quot;socket-api&quot;&gt;Socket API&lt;/h1&gt;

&lt;p&gt;To be able to utilize the networking stack, some kind of an interface has to be provided for applications. The &lt;em&gt;BSD Socket API&lt;/em&gt; is the most famous one and it originates from the 4.2BSD UNIX release from 1983.&lt;sup id=&quot;fnref:tcp-illustrated-implementation&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:tcp-illustrated-implementation&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; The Socket API in Linux is compatible to the BSD Socket API.&lt;sup id=&quot;fnref:socket-man&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:socket-man&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;A socket is reserved from the networking stack by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;socket(2)&lt;/code&gt;, passing the type of the socket and protocol as parameters. Common values are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AF_INET&lt;/code&gt; for the type and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SOCK_STREAM&lt;/code&gt; as domain. This will default to a TCP-over-IPv4 socket.&lt;/p&gt;

&lt;p&gt;After succesfully reserving a TCP socket from the networking stack, it will be connected to a remote endpoint. This is where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;connect(2)&lt;/code&gt; is used and calling it will launch the TCP handshake.&lt;/p&gt;

&lt;p&gt;From that point on, we can just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write(2)&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read(2)&lt;/code&gt; data from our socket.&lt;/p&gt;

&lt;p&gt;The networking stack will handle queueing, retransmission, error-checking and reassembly of the data in the TCP stream. For the application, the inner acting of TCP is mostly opaque. The only thing the application can rely on is that the TCP has acknowledged the responsibility of sending and receiving the stream of data, and that it will inform the application of unexpected behavior through the socket API.&lt;/p&gt;

&lt;p&gt;As an example, let’s look at the system calls that a simple invocation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl(1)&lt;/code&gt; does:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;strace &lt;span class=&quot;nt&quot;&gt;-esocket&lt;/span&gt;,connect,sendto,recvfrom,close curl &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; example.com &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /dev/null
...
socket&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;AF_INET, SOCK_STREAM, IPPROTO_TCP&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 3
connect&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3, &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sa_family&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;AF_INET, &lt;span class=&quot;nv&quot;&gt;sin_port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;htons&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;80&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;nv&quot;&gt;sin_addr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;inet_addr&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;93.184.216.34&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)}&lt;/span&gt;, 16&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt; EINPROGRESS &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Operation now &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;progress&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
sendto&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3, &lt;span class=&quot;s2&quot;&gt;&quot;GET / HTTP/1.1&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Host: example.co&quot;&lt;/span&gt;..., 75, MSG_NOSIGNAL, NULL, 0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 75
recvfrom&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3, &lt;span class=&quot;s2&quot;&gt;&quot;HTTP/1.1 200 OK&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Cache-Control: &quot;&lt;/span&gt;..., 16384, 0, NULL, NULL&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 1448
close&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;                                &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0
+++ exited with 0 +++&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We observe the Socket API calls with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strace(1)&lt;/code&gt;, a tool for tracing system calls and signals. The steps are:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;A socket is opened with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;socket&lt;/code&gt;, and the type is specified as IPv4/TCP.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;connect&lt;/code&gt; launches the TCP handshake. Destination address and port are passed to the function.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;After the connection is successfully established, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sendto(3)&lt;/code&gt; is used to write data to the socket - in this case, the usual HTTP GET request.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;From that point on, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt; eventually reads the incoming data with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recvfrom&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The astute reader may have noticed that no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write&lt;/code&gt; system calls were placed. This is because the actual socket API does not contain those functions, but normal I/O operations can also be used. From &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man socket(7)&lt;/code&gt;:&lt;sup id=&quot;fnref:socket-man:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:socket-man&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In addition, the standard I/O operations like write(2), writev(2), sendfile(2), read(2), and readv(2) can be used to read and write data.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the end, the Socket API contains multiple functions for just writing and reading data. This is complicated by the I/O family of functions, which can also be used to manipulate the socket’s file descriptor.&lt;/p&gt;

&lt;h1 id=&quot;testing-our-socket-api&quot;&gt;Testing our Socket API&lt;/h1&gt;

&lt;p&gt;Now that our networking stack provides a socket interface, we can write applications against it.&lt;/p&gt;

&lt;p&gt;The popular tool &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt; is used to transmit data with a given protocol. We can replicate the HTTP GET behavior of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt; by writing a minimal implementation:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./lvl-ip curl example.com 80

...
&amp;lt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;doctype html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;&lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
    &amp;lt;title&amp;gt;Example Domain&amp;lt;/title&amp;gt;

    &amp;lt;meta &lt;span class=&quot;nv&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;utf-8&quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;meta http-equiv&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Content-type&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text/html; charset=utf-8&quot;&lt;/span&gt; /&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
&amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;Example Domain&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;This domain is established to be used &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;illustrative examples &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;documents. You may use this
    domain &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;examples without prior coordination or asking &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;permission.&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;&amp;lt;a &lt;span class=&quot;nv&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;http://www.iana.org/domains/example&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;More information...&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In the end, sending a HTTP GET request exercises the underlying networking stack only minimally.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;We have now essentially implemented a rudimentary TCP with simple data management and provided an interface applications can use.&lt;/p&gt;

&lt;p&gt;However, TCP data communication is not a simple problem. The packets can get corrupted, reordered or lost in transit. Furthermore, the data transmit can congest arbitrary elements in the network.&lt;/p&gt;

&lt;p&gt;For this, the TCP data communication needs to include more sophisticated logic. In the next post, we will look into TCP Window Management and TCP Retransmission Timeout mechanisms, to better cope with more challenging settings.&lt;/p&gt;

&lt;p&gt;The source code for the project is hosted at &lt;a href=&quot;https://github.com/saminiir/level-ip&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you liked this post, you can
&lt;a href=&quot;https://twitter.com/intent/tweet?url=https://www.saminiir.com/lets-code-tcp-ip-stack-4-tcp-data-flow-socket-api/&amp;amp;text=Let%27s+code+a+TCP%2FIP+stack%2C+4%3A+TCP+Data+Flow+%26+Socket+API&amp;amp;via=saminiir&quot; target=&quot;_blank&quot;&gt;
  share it with your followers&lt;/a&gt; 
and 
&lt;a href=&quot;https://twitter.com/saminiir&quot;&gt;
  follow me on Twitter&lt;/a&gt;!&lt;/p&gt;

&lt;h1 id=&quot;sources&quot;&gt;Sources&lt;/h1&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:man-tcp&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://linux.die.net/man/7/tcp&quot;&gt;https://linux.die.net/man/7/tcp&lt;/a&gt; &lt;a href=&quot;#fnref:man-tcp&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:tcp-rst-attack&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/TCP_reset_attack&quot;&gt;https://en.wikipedia.org/wiki/TCP_reset_attack&lt;/a&gt; &lt;a href=&quot;#fnref:tcp-rst-attack&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:tcp-illustrated-implementation&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://www.kohala.com/start/tcpipiv2.html&quot;&gt;http://www.kohala.com/start/tcpipiv2.html&lt;/a&gt; &lt;a href=&quot;#fnref:tcp-illustrated-implementation&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:socket-man&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://man7.org/linux/man-pages/man7/socket.7.html&quot;&gt;http://man7.org/linux/man-pages/man7/socket.7.html&lt;/a&gt; &lt;a href=&quot;#fnref:socket-man&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:socket-man:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Tue, 06 Dec 2016 12:00:00 +0000</pubDate>
        <link>https://www.saminiir.com/lets-code-tcp-ip-stack-4-tcp-data-flow-socket-api/</link>
        <guid isPermaLink="true">https://www.saminiir.com/lets-code-tcp-ip-stack-4-tcp-data-flow-socket-api/</guid>
        
        
        <category>tcp/ip</category>
        
        <category>tutorial</category>
        
        <category>c programming</category>
        
        <category>ip</category>
        
        <category>networking</category>
        
        <category>linux</category>
        
      </item>
    
      <item>
        <title>Configuring Arch Linux on Dell XPS 15</title>
        <description>&lt;p&gt;In the &lt;a href=&quot;/installing-arch-linux-on-dell-xps-15/&quot;&gt;previous post&lt;/a&gt;, we’ve successfully booted into Arch Linux from our encrypted root partition.&lt;/p&gt;

&lt;p&gt;Let’s now configure it to our (my) liking.&lt;/p&gt;

&lt;h1 class=&quot;no_toc&quot; id=&quot;contents&quot;&gt;Contents&lt;/h1&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#user-management&quot; id=&quot;markdown-toc-user-management&quot;&gt;User management&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#arch-user-repository&quot; id=&quot;markdown-toc-arch-user-repository&quot;&gt;Arch User Repository&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#x11-and-window-manager-dwm&quot; id=&quot;markdown-toc-x11-and-window-manager-dwm&quot;&gt;X11 and Window Manager: dwm&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#terminal-xterm&quot; id=&quot;markdown-toc-terminal-xterm&quot;&gt;Terminal: xterm&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#input-trackpad-gestures-libinput&quot; id=&quot;markdown-toc-input-trackpad-gestures-libinput&quot;&gt;Input: Trackpad gestures (libinput)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sound&quot; id=&quot;markdown-toc-sound&quot;&gt;Sound&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#storage-nvme-ssd&quot; id=&quot;markdown-toc-storage-nvme-ssd&quot;&gt;Storage: NVMe SSD&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#graphics-nvidia-and-bumblebee&quot; id=&quot;markdown-toc-graphics-nvidia-and-bumblebee&quot;&gt;Graphics: Nvidia and Bumblebee&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#power-management&quot; id=&quot;markdown-toc-power-management&quot;&gt;Power Management&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#powertop&quot; id=&quot;markdown-toc-powertop&quot;&gt;Powertop&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#battery-status&quot; id=&quot;markdown-toc-battery-status&quot;&gt;Battery status&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#backlight&quot; id=&quot;markdown-toc-backlight&quot;&gt;Backlight&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#laptop-mode&quot; id=&quot;markdown-toc-laptop-mode&quot;&gt;Laptop mode&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#suspendhibernate&quot; id=&quot;markdown-toc-suspendhibernate&quot;&gt;Suspend/hibernate&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#debugging-suspendhibernation&quot; id=&quot;markdown-toc-debugging-suspendhibernation&quot;&gt;Debugging suspend/hibernation&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#locking-screen-on-sleep&quot; id=&quot;markdown-toc-locking-screen-on-sleep&quot;&gt;Locking screen on sleep&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#networking-netctl-unbound&quot; id=&quot;markdown-toc-networking-netctl-unbound&quot;&gt;Networking: netctl, Unbound&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#security&quot; id=&quot;markdown-toc-security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#browser-firefox&quot; id=&quot;markdown-toc-browser-firefox&quot;&gt;Browser: Firefox&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#backups-rsnapshot&quot; id=&quot;markdown-toc-backups-rsnapshot&quot;&gt;Backups: rsnapshot&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#password-management-pass&quot; id=&quot;markdown-toc-password-management-pass&quot;&gt;Password Management: pass&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#gaming-steamwine&quot; id=&quot;markdown-toc-gaming-steamwine&quot;&gt;Gaming: Steam/Wine&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#gamepad&quot; id=&quot;markdown-toc-gamepad&quot;&gt;Gamepad&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#iphone&quot; id=&quot;markdown-toc-iphone&quot;&gt;iPhone&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sources&quot; id=&quot;markdown-toc-sources&quot;&gt;Sources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;user-management&quot;&gt;User management&lt;/h1&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Add new user&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;useradd &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-G&lt;/span&gt; wheel saminiir

&lt;span class=&quot;c&quot;&gt;# Uncomment wheel group&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;wheel /etc/sudoers
%wheel &lt;span class=&quot;nv&quot;&gt;ALL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;ALL&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; ALL
&lt;span class=&quot;c&quot;&gt;# %wheel ALL=(ALL) NOPASSWD: ALL&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Harden the root pasword if necessary&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;passwd &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;arch-user-repository&quot;&gt;Arch User Repository&lt;/h1&gt;

&lt;p&gt;The Arch User Repository (AUR) contains community-driven packages. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yaourt&lt;/code&gt; is a popular front-end for it. Enable it by:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; git
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://aur.archlinux.org/package-query.git
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;package-query
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;makepkg &lt;span class=&quot;nt&quot;&gt;-si&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ..
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://aur.archlinux.org/yaourt.git
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;yaourt
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;makepkg &lt;span class=&quot;nt&quot;&gt;-si&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ..&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;x11-and-window-manager-dwm&quot;&gt;X11 and Window Manager: dwm&lt;/h1&gt;

&lt;p&gt;Determine your 3D card:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;lspci | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; VGA &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; 3D
01:00.0 3D controller: NVIDIA Corporation GM107M &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;GeForce GTX 960M] &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;rev a2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Install nvidia proprietary drivers (pulls in xorg as well)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Be sure to select nvidia and libinput if it prompts for the repo extras&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; nvidia

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; xorg-server-utils xorg-xinit
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; openssh slock terminus-font

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://github.com/saminiir/dotfiles.git
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; ~/dotfiles/xorg/xinitrc .xinitrc
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; ~/dotfiles/xorg/Xresources .Xresources&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Configure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dwm&lt;/code&gt; to e.g. use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xterm&lt;/code&gt; as terminal and change the modifier key to Windows key (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mod4Mask&lt;/code&gt;):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://aur.archlinux.org/dwm-git.git
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;dwm-git &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; makepkg

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;define MODKEY&quot;&lt;/span&gt; src/dwm/config.h
&lt;span class=&quot;c&quot;&gt;#define MODKEY Mod4Mask&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;char &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;termcmd&quot;&lt;/span&gt; src/dwm/config.h
static const char &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;termcmd[]  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;xterm&quot;&lt;/span&gt;, NULL &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;makepkg &lt;span class=&quot;nt&quot;&gt;-fi&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;startx&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dwm&lt;/code&gt; should start.&lt;/p&gt;

&lt;h1 id=&quot;terminal-xterm&quot;&gt;Terminal: xterm&lt;/h1&gt;

&lt;p&gt;For some reason, I’m stuck on using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xterm&lt;/code&gt;. Even its manual page says that it needs to be rewritten, so feel free to go find an alternative.&lt;/p&gt;

&lt;p&gt;For the rest of us, at least the following tweaks are useful:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Make bash auto-complete better&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; bash-completion

&lt;span class=&quot;c&quot;&gt;# Install Google's `noto` font package&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; noto-fonts

&lt;span class=&quot;c&quot;&gt;# For easy command-on-key binding&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; xbindkeys&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Finally, use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.Xresources&lt;/code&gt; from my dotfiles:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone git@github.com:saminiir/dotfiles.git
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~ &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; ~/dotfiles/xorg/Xresources .Xresources&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Important things for me is that Caps Lock is mapped as a Control key, and that the Alt (or whatever is left of space bar) acts as Meta. These can be found from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dotfiles&lt;/code&gt;, but I’ll highlight them here too:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# No caps lock - Map it as ctrl instead&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;setxkbmap &lt;span class=&quot;nt&quot;&gt;-option&lt;/span&gt; ctrl:nocaps

&lt;span class=&quot;c&quot;&gt;# Kill X11 with ctrl+alt+backspace&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;setxkbmap &lt;span class=&quot;nt&quot;&gt;-option&lt;/span&gt; terminate:ctrl_alt_bksp

&lt;span class=&quot;c&quot;&gt;# Change keyboard layout on right shift&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;setxkbmap &lt;span class=&quot;nt&quot;&gt;-layout&lt;/span&gt; us,fi &lt;span class=&quot;nt&quot;&gt;-option&lt;/span&gt; grp:rshift_toggle

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;meta~/.Xresources 
xterm&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;metaSendsEscape: &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Furthermore, I like to have my tilde character lower on the keyboard, on the right side of left-shift:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;tilde /usr/share/X11/xkb/symbols/pc
    key &amp;lt;LSGT&amp;gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; grave, asciitilde, grave, asciitilde &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Additionally, increase the Linux console font size:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /etc/vconsole.conf
&lt;span class=&quot;nv&quot;&gt;FONT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ter-i32n&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And apply it to early userspace too:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;consolefont /etc/mkinitcpio.conf
&lt;span class=&quot;nv&quot;&gt;HOOKS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;base udev autodetect modconf block encrypt lvm2 resume filesystems keyboard fsck consolefont&quot;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkinitcpio &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; linux&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;input-trackpad-gestures-libinput&quot;&gt;Input: Trackpad gestures (libinput)&lt;/h1&gt;

&lt;p&gt;I chose to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libinput&lt;/code&gt; over synaptics for the touchpad driver.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; libinput xf86-input-libinput
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;libinput-list-devices
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;xinput list-props &lt;span class=&quot;s2&quot;&gt;&quot;DLL06E4:01 06CB:7A13 Touchpad&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Enable tap-click&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;xinput set-prop &lt;span class=&quot;s2&quot;&gt;&quot;DLL06E4:01 06CB:7A13 Touchpad&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;libinput Tapping Enabled&quot;&lt;/span&gt; 1

&lt;span class=&quot;c&quot;&gt;# Increase pointer acceleration&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;xinput set-prop &lt;span class=&quot;s2&quot;&gt;&quot;DLL06E4:01 06CB:7A13 Touchpad&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;libinput Accel Speed&quot;&lt;/span&gt; 1&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;These can be found from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xutils&lt;/code&gt; in my dotfiles (described above).&lt;/p&gt;

&lt;h1 id=&quot;sound&quot;&gt;Sound&lt;/h1&gt;

&lt;p&gt;Just install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alsa-utils&lt;/code&gt;, and use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alsamixer&lt;/code&gt; to unmute the master channel. Should just work.&lt;/p&gt;

&lt;p&gt;For keyboard hotkeys, add the following to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xbindkeys&lt;/code&gt; configuration:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-A1&lt;/span&gt; amixer ~/.xbindkeysrc
&lt;span class=&quot;s2&quot;&gt;&quot;/usr/bin/amixer set Master 5%+&quot;&lt;/span&gt;
    XF86AudioRaiseVolume
&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&quot;/usr/bin/amixer set Master 5%-&quot;&lt;/span&gt;
    XF86AudioLowerVolume
&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&quot;/usr/bin/amixer set Master toggle&quot;&lt;/span&gt;
    XF86AudioMute&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;storage-nvme-ssd&quot;&gt;Storage: NVMe SSD&lt;/h1&gt;

&lt;p&gt;Trimming is an operation SSDs benefit greatly of. However, enabling it for encrypted drives is a security risk&lt;sup id=&quot;fnref:ssd-trim-security&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ssd-trim-security&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. The options are to enable trim and suffer the weakened security, or at regular intervals take maintenance on the drive.&lt;/p&gt;

&lt;p&gt;One way of minimizing writes, which can especially wear down SSD, is to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;noatime&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;relatime&lt;/code&gt; in the drives mount options. For me, this was enabled by default:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;relatime /etc/fstab

.. relatime ..&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;graphics-nvidia-and-bumblebee&quot;&gt;Graphics: Nvidia and Bumblebee&lt;/h1&gt;

&lt;p&gt;Let’s install bumblebee for smart switching of the integrated and dedicated graphics:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; bumblebee primus bbswitch

&lt;span class=&quot;c&quot;&gt;# Should show the traditional 3D-accelerated gears&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;primusrun glxgears

&lt;span class=&quot;c&quot;&gt;# Reboot. After rebooting, you should see that bbswitch has disabled the card,&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# which is good for saving the battery on the laptop&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /proc/acpi/bbswitch
0000:01:00.0 OFF&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;power-management&quot;&gt;Power Management&lt;/h1&gt;

&lt;h2 id=&quot;powertop&quot;&gt;Powertop&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;powertop&lt;/code&gt; is the best. Install it.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; powertop&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Run calibration as many times as you like. Eventually, powertop will start to show accurate power consumption estimates. Additionally, run it also with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--auto-tune&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;powertop &lt;span class=&quot;nt&quot;&gt;--calibrate&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;powertop &lt;span class=&quot;nt&quot;&gt;--auto-tune&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Also, add a systemd service for autotuning on startup:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /etc/systemd/system/powertop.service
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Unit]
&lt;span class=&quot;nv&quot;&gt;Description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Powertop tunings

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Service]
&lt;span class=&quot;nv&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;oneshot
&lt;span class=&quot;nv&quot;&gt;ExecStart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/bin/powertop &lt;span class=&quot;nt&quot;&gt;--auto-tune&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Install]
&lt;span class=&quot;nv&quot;&gt;WantedBy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;multi-user.target

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;powertop.service&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;battery-status&quot;&gt;Battery status&lt;/h2&gt;

&lt;p&gt;I use the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;acpi -b&lt;/code&gt; for checking battery status. You need the package &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;acpi&lt;/code&gt; for it.&lt;/p&gt;

&lt;h2 id=&quot;backlight&quot;&gt;Backlight&lt;/h2&gt;

&lt;p&gt;The display’s backlight is a huge power drain, and it is often convenient to have a hotkey to adjust it.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; light&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now, add commands to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xbindkeys&lt;/code&gt; for manipulating the backlight:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-A3&lt;/span&gt; light ~/.xbindkeysrc
&lt;span class=&quot;s2&quot;&gt;&quot;/usr/bin/light -U 5&quot;&lt;/span&gt;
    m:0x0 + c:232
    XF86MonBrightnessDown

&lt;span class=&quot;s2&quot;&gt;&quot;/usr/bin/light -A 5&quot;&lt;/span&gt;
    m:0x0 + c:233
    XF86MonBrightnessUp&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;laptop-mode&quot;&gt;Laptop mode&lt;/h2&gt;

&lt;p&gt;Also, activate &lt;em&gt;laptop-mode&lt;/em&gt;&lt;sup id=&quot;fnref:laptop-mode&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:laptop-mode&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /etc/sysctl.d/laptop.conf
vm.laptop_mode &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 5&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;suspendhibernate&quot;&gt;Suspend/hibernate&lt;/h1&gt;

&lt;p&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resume&lt;/code&gt; to the kernel parameters:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vi /boot/loader/entries/arch-encrypted-lvm.conf
options ... &lt;span class=&quot;nv&quot;&gt;resume&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/dev/mapper/MyVol-swap quiet rw&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resume&lt;/code&gt; hook to initramfs.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vi /etc/mkinitcpio.conf
&lt;span class=&quot;nv&quot;&gt;HOOKS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;base ... lvm2 resume ...&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resume&lt;/code&gt; hook should be after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lvm2&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Then, regenerate the initramfs:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkinitcpio &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; linux&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;debugging-suspendhibernation&quot;&gt;Debugging suspend/hibernation&lt;/h2&gt;

&lt;p&gt;If suspend/hibernation does not work at first, debug it by setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pm_test&lt;/code&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /sys/power/pm_test
none core processors platform devices freezer

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;freezer | &lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; /sys/power/pm_test
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;suspend&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl hybrid-sleep&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Go through the different stages (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;freezer&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;devices&lt;/code&gt;..) and watch the output of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;journalctl -r&lt;/code&gt; for what goes wrong.&lt;/p&gt;

&lt;h2 id=&quot;locking-screen-on-sleep&quot;&gt;Locking screen on sleep&lt;/h2&gt;

&lt;p&gt;I want to lock the screen (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slock&lt;/code&gt;) whenever the system is put to sleep.&lt;/p&gt;

&lt;p&gt;This can be achieved by setting systemd units that have the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sleep.target&lt;/code&gt; activated&lt;sup id=&quot;fnref:systemd-sleep-service&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:systemd-sleep-service&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. See more examples from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dotfiles/systemd&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /etc/systemd/system/suspend@saminiir.service
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Unit]
&lt;span class=&quot;nv&quot;&gt;Description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;User &lt;span class=&quot;nb&quot;&gt;suspend &lt;/span&gt;actions
&lt;span class=&quot;nv&quot;&gt;Before&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;sleep.target

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Service]
&lt;span class=&quot;nv&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;%I
&lt;span class=&quot;nv&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;simple
&lt;span class=&quot;nv&quot;&gt;Environment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DISPLAY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;:0
&lt;span class=&quot;nv&quot;&gt;ExecStart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/bin/slock
&lt;span class=&quot;nv&quot;&gt;ExecStartPost&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/bin/sleep 1

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Install]
&lt;span class=&quot;nv&quot;&gt;WantedBy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;sleep.target

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable suspend&lt;/span&gt;@saminiir.service&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;networking-netctl-unbound&quot;&gt;Networking: netctl, Unbound&lt;/h1&gt;

&lt;p&gt;Use whatever network manager that rows your boat. I have experience in NetworkManager, but the default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;netctl&lt;/code&gt; in Arch Linux might be worth using too.&lt;/p&gt;

&lt;p&gt;I’ve used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dnsmasq&lt;/code&gt; in the past, but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unbound&lt;/code&gt; seems like a cool caching DNS resolver that handles DNSSEC as well.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; expat unbound&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;See the documentation how to configure it. Most importantly your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/resolv.conf&lt;/code&gt; should point to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;127.0.0.1&lt;/code&gt; to use your own DNS program.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /etc/resolv.conf
&lt;span class=&quot;c&quot;&gt;# Generated by resolvconf&lt;/span&gt;
domain lan
nameserver 127.0.0.1&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;security&quot;&gt;Security&lt;/h1&gt;

&lt;p&gt;These are the basic steps I took to harden my Arch Linux.&lt;/p&gt;

&lt;p&gt;To lockout a user for ten minutes after three failed login attempts:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;pam_tally /etc/pam.d/system-login
&lt;span class=&quot;c&quot;&gt;#auth       required   pam_tally.so         onerr=succeed file=/var/log/faillog&lt;/span&gt;
auth       required   pam_tally.so &lt;span class=&quot;nv&quot;&gt;deny&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2 &lt;span class=&quot;nv&quot;&gt;unlock_time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;600 &lt;span class=&quot;nv&quot;&gt;onerr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;succeed &lt;span class=&quot;nv&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/log/faillog&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Do not allow SSH login as root:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;PermitRootLogin /etc/ssh/sshd_config
PermitRootLogin no&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Restrict access to dmesg:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /etc/sysctl.d/50-dmesg-restrict.conf

kernel.dmesg_restrict &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 1&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Configure firewall to drop pretty much all incoming connections, but allow outgoing and already established ones:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /etc/iptables/iptables.rules
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;filter
:INPUT DROP &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;0:0]
:FORWARD DROP &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;0:0]
:OUTPUT ACCEPT &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;0:0]
&lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; icmp &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; conntrack &lt;span class=&quot;nt&quot;&gt;--ctstate&lt;/span&gt; RELATED,ESTABLISHED &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; lo &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; REJECT &lt;span class=&quot;nt&quot;&gt;--reject-with&lt;/span&gt; tcp-reset
&lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; udp &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; REJECT &lt;span class=&quot;nt&quot;&gt;--reject-with&lt;/span&gt; icmp-port-unreachable
&lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; REJECT &lt;span class=&quot;nt&quot;&gt;--reject-with&lt;/span&gt; icmp-proto-unreachable
COMMIT&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Do the same for IPv6 (ip6tables). You have to adjust some of the rules to IPv6.&lt;/p&gt;

&lt;p&gt;Harden the Linux TCP/IP stack:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /etc/sysctl.d/51-tcp-ip-stack.conf

net.ipv4.tcp_rfc1337 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 1
net.ipv4.conf.all.log_martians &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 1
net.ipv4.conf.all.send_redirects &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0

&lt;span class=&quot;c&quot;&gt;## ICMP routing redirects (only secure)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;##net.ipv4.conf.all.secure_redirects = 1 (default)&lt;/span&gt;
net.ipv4.conf.default.accept_redirects&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0
net.ipv4.conf.all.accept_redirects&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0
net.ipv6.conf.default.accept_redirects&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0
net.ipv6.conf.all.accept_redirects&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;browser-firefox&quot;&gt;Browser: Firefox&lt;/h1&gt;

&lt;p&gt;I use Firefox. With a high DPI screen, however, you should increase the pixel density. Go to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;about:config&lt;/code&gt; and set the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;layout.css.devPixelsPerPx&lt;/code&gt; to 2.&lt;/p&gt;

&lt;h1 id=&quot;backups-rsnapshot&quot;&gt;Backups: rsnapshot&lt;/h1&gt;

&lt;p&gt;I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsnapshot&lt;/code&gt;&lt;sup id=&quot;fnref:rsnapshot&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:rsnapshot&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. TODO.&lt;/p&gt;

&lt;h1 id=&quot;password-management-pass&quot;&gt;Password Management: pass&lt;/h1&gt;

&lt;p&gt;This is kind of an extra section, since password management is pretty personal. I, however, have liked the utility &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pass&lt;/code&gt;, which is a simplistic bash script for linux utilities like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pwgen&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; pass

&lt;span class=&quot;c&quot;&gt;# Or if you have an existing pass-store, e.g. in a private cloud, symlink the folder ~/.password-store to it&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pass init&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pass&lt;/code&gt; uses your gpg-keys for encrypting/decrypting the files by default. See my earlier &lt;a href=&quot;/establish-cryptographic-identity-using-gnupg/&quot;&gt;blog post&lt;/a&gt; on how to establish GPG.&lt;/p&gt;

&lt;p&gt;Then, synchronize the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.password-store&lt;/code&gt; between computers however you like.&lt;/p&gt;

&lt;h1 id=&quot;gaming-steamwine&quot;&gt;Gaming: Steam/Wine&lt;/h1&gt;

&lt;p&gt;Because Wine uses 32-bit libraries, you have to enable the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;multilib&lt;/code&gt; repo&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Uncomment multilib repo&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vi /etc/pacman.conf

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; wine lib32-alsa-lib lib32-alsa-plugins
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; wine-mono wine_gecko winetricks&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Setup a 32-bit wine environment:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ WINEARCH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;win32 &lt;span class=&quot;nv&quot;&gt;WINEPREFIX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/win32 winecfg

&lt;span class=&quot;c&quot;&gt;# Install .NET Framework 4.0, just for laughs&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ WINEARCH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;win32 &lt;span class=&quot;nv&quot;&gt;WINEPREFIX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/win32 winetricks &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; dotnet45 corefonts&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then, use `winetricks to install Steam:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ WINEARCH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;win32 &lt;span class=&quot;nv&quot;&gt;WINEPREFIX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/win32 winetricks steam&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You should be able to start Steam/Wine. Your mileage may vary. It is easy to have missed lib32 packages on a 64-bit system, so you might have to chase down dependencies.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ WINEARCH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;win32 &lt;span class=&quot;nv&quot;&gt;WINEPREFIX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/wine32 primusrun wine ~/wine32/drive_c/Program&lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;Files/Steam/Steam.exe&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;gamepad&quot;&gt;Gamepad&lt;/h2&gt;

&lt;p&gt;My generic xbox pad just worked out-of-the-box. See the kernel docs for more info&lt;sup id=&quot;fnref:xpad&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:xpad&quot; class=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dmesg | &lt;span class=&quot;nb&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n3&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; 3508.420268] usb 1-1: new full-speed USB device number 5 using xhci_hcd
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; 3508.609392] input: Generic X-Box pad as /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/input/input21
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; 3508.609619] usbcore: registered new interface driver xpad&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can test the pad:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; joyutils
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;jstest /dev/input/js0&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;iphone&quot;&gt;iPhone&lt;/h1&gt;

&lt;p&gt;I like the robustness of iPhones. I tried a Sony Z5 Compact, but the first drop broke the glass. My iPhone 5 of three years has taken a substantial amount of beating and does not have a dent. Go figure.&lt;/p&gt;

&lt;p&gt;Install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libimobiledevice&lt;/code&gt; to access the iPhone in Linux:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; libimobiledevice usbmuxd
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl start usbmuxd&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then, connect your iPhone via USB. Have the screen unlocked. It should be detected:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;Jun 28 18:43:24 localhost kernel: ipheth 1-2:4.2: Apple iPhone USB Ethernet device attached
Jun 28 18:43:24 localhost kernel: usbcore: registered new interface driver ipheth
Jun 28 18:43:24 localhost kernel: ipheth 1-2:4.2 enp0s20f0u2c4i2: renamed from eth0

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;idevicepair pair&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then, you can backup your iPhone:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;idevicebackup2 backup ~/Documents/iphone-backups/&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you liked this post, you can
&lt;a href=&quot;https://twitter.com/intent/tweet?url=https://www.saminiir.com/configuring-arch-linux-on-dell-xps-15/&amp;amp;text=Configuring+Arch+Linux+on+Dell+XPS+15&amp;amp;via=saminiir&quot; target=&quot;_blank&quot;&gt;
  share it with your followers&lt;/a&gt; 
and 
&lt;a href=&quot;https://twitter.com/saminiir&quot;&gt;
  follow me on Twitter&lt;/a&gt;!&lt;/p&gt;

&lt;h1 id=&quot;sources&quot;&gt;Sources&lt;/h1&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:ssd-trim-security&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Dm-crypt/Specialties#Discard.2FTRIM_support_for_solid_state_drives_.28SSD.29&quot;&gt;https://wiki.archlinux.org/index.php/Dm-crypt/Specialties#Discard.2FTRIM_support_for_solid_state_drives_.28SSD.29&lt;/a&gt; &lt;a href=&quot;#fnref:ssd-trim-security&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:laptop-mode&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://www.kernel.org/doc/Documentation/laptops/laptop-mode.txt&quot;&gt;https://www.kernel.org/doc/Documentation/laptops/laptop-mode.txt&lt;/a&gt; &lt;a href=&quot;#fnref:laptop-mode&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:systemd-sleep-service&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Power_management#Suspend.2Fresume_service_files&quot;&gt;https://wiki.archlinux.org/index.php/Power_management#Suspend.2Fresume_service_files&lt;/a&gt; &lt;a href=&quot;#fnref:systemd-sleep-service&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:rsnapshot&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://rsnapshot.org/&quot;&gt;http://rsnapshot.org/&lt;/a&gt; &lt;a href=&quot;#fnref:rsnapshot&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:xpad&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://www.kernel.org/doc/Documentation/input/xpad.txt&quot;&gt;https://www.kernel.org/doc/Documentation/input/xpad.txt&lt;/a&gt; &lt;a href=&quot;#fnref:xpad&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sun, 26 Jun 2016 08:00:00 +0000</pubDate>
        <link>https://www.saminiir.com/configuring-arch-linux-on-dell-xps-15/</link>
        <guid isPermaLink="true">https://www.saminiir.com/configuring-arch-linux-on-dell-xps-15/</guid>
        
        
        <category>linux</category>
        
      </item>
    
      <item>
        <title>Installing Arch Linux on Dell XPS 15</title>
        <description>&lt;p&gt;So after using a Fedora/Macbook for a while, I got a new work laptop. This time I opted for the Dell XPS 15 with all the bells and whistles&lt;sup id=&quot;fnref:dell-xps-15&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:dell-xps-15&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. It has received great reviews and has been compared to the quality of the Macbook Pro’s.&lt;/p&gt;

&lt;p&gt;Installing a UNIX distro is always time-consuming and depending on your desires, the configuration varies a lot. This applies especially to bare-bones distros like Arch Linux: It only provides a compiled kernel and a minimal set of system components (systemd). Rest of the system layout you have to devise yourself.&lt;/p&gt;

&lt;p&gt;The overall layout of the final Arch Linux system will be:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;UEFI for the boot-system&lt;/li&gt;
  &lt;li&gt;GPT for the partition table&lt;/li&gt;
  &lt;li&gt;LUKS for full-disk encryption&lt;/li&gt;
  &lt;li&gt;LVM for managing volumes on top of LUKS&lt;/li&gt;
  &lt;li&gt;root and home logical volumes (ext4) and a swap volume&lt;/li&gt;
  &lt;li&gt;systemd-boot for the boot manager&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 class=&quot;no_toc&quot; id=&quot;contents&quot;&gt;Contents&lt;/h1&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#booting-up-arch-linux&quot; id=&quot;markdown-toc-booting-up-arch-linux&quot;&gt;Booting up Arch Linux&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#partitioning-uefi-gpt-and-esp&quot; id=&quot;markdown-toc-partitioning-uefi-gpt-and-esp&quot;&gt;Partitioning: UEFI, GPT and ESP&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#disk-encryption-luks&quot; id=&quot;markdown-toc-disk-encryption-luks&quot;&gt;Disk encryption: LUKS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#volume-management-lvm&quot; id=&quot;markdown-toc-volume-management-lvm&quot;&gt;Volume management: LVM&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#install-arch-linux&quot; id=&quot;markdown-toc-install-arch-linux&quot;&gt;Install Arch Linux&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#boot-manager-systemd-boot&quot; id=&quot;markdown-toc-boot-manager-systemd-boot&quot;&gt;Boot manager: systemd-boot&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sources&quot; id=&quot;markdown-toc-sources&quot;&gt;Sources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;booting-up-arch-linux&quot;&gt;Booting up Arch Linux&lt;/h1&gt;

&lt;p&gt;My favorite way of booting up a Linux distro is just writing the ISO image to a USB drive.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dd &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4M &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/Downloads/archlinux-2016.06.01-dual.iso &lt;span class=&quot;nv&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/dev/sdX &lt;span class=&quot;nv&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;progress &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sync&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is fast and efficient. The USB drive is ready to be booted from. ‘Nuff said.&lt;/p&gt;

&lt;p&gt;If the system does not detect the bootable USB drive, try disabling Secure Boot if you have UEFI enabled.
Extra note regarding the NVMe-based SSD drive: I had to change SATA configuration to AHCI (not RAID) from BIOS to get it visible as a block device.&lt;/p&gt;

&lt;p&gt;Alternatively, you can check out a way of PXE booting Arch Linux from my &lt;a href=&quot;/boot-arch-linux-from-pxe/&quot;&gt;previous blog post&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;partitioning-uefi-gpt-and-esp&quot;&gt;Partitioning: UEFI, GPT and ESP&lt;/h1&gt;

&lt;p&gt;First, wipe the hard disk. This is important for enhancing the security of the disk encryption, since if the disk is full of random data, info about it is harder to deduce:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cryptsetup open &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; plain /dev/sdXY container &lt;span class=&quot;nt&quot;&gt;--key-file&lt;/span&gt; /dev/random
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dd &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/dev/zero &lt;span class=&quot;nv&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/dev/mapper/container &lt;span class=&quot;nv&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;progress&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now, make sure you have booted with UEFI:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;efivar &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Since we zeroed out the main disk, we need to install a partition table to it. GPT is the recommended approach with UEFI:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdisk /dev/nmve0&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Next, we’ll set up the EFI System Partition (ESP) and the main root partition:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Add a partition of size 512M and change its partition table type to EFI System (1).&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Also, add a second partition that spans the rest of the volume&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;fdisk /dev/nmve0

&lt;span class=&quot;c&quot;&gt;# Should show &quot;esp&quot; in Flags:&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;parted /dev/nvme0n1 print

&lt;span class=&quot;c&quot;&gt;# Initialize it as FAT32&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkfs.fat &lt;span class=&quot;nt&quot;&gt;-F32&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-nESP&lt;/span&gt; /dev/nvme0n1p1

&lt;span class=&quot;c&quot;&gt;# Initialize the root filesystem&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkfs.ext4 /dev/nvme0n1p2&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;disk-encryption-luks&quot;&gt;Disk encryption: LUKS&lt;/h1&gt;

&lt;p&gt;Several methods for achieving full disk encryption are available. I chose to use LUKS (dm-crypt), since it is pretty standard and performant in Linux. LUKS utilizes block device encryption, meaning that it operates below the filesystem and everything written to the device is guaranteed to be encrypted. LUKS also adds ease-of-use into the key management.&lt;/p&gt;

&lt;p&gt;Utilizing full disk encryption is no panacea - you will still be vulnerable to e.g. cold boot attack&lt;sup id=&quot;fnref:cold-boot&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:cold-boot&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, bootloader malware and all other sorts of nasty things. And in the end, if your system is compromized while the disk encryption is unlocked, it is absolutely of no help at that point. I am planning a separate blog post on hardening the boot process.&lt;/p&gt;

&lt;p&gt;Encrypt your root partition. Choose a strong passphrase (I prefer the diceware&lt;sup id=&quot;fnref:diceware&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:diceware&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; method). Also notice, that cryptsetup requires an uppercase ‘yes’ for confirmation. :-)&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cryptsetup luksFormat /dev/nvme0n1p2
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cryptsetup open &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; luks /dev/nvme0n1p2 lvm&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;volume-management-lvm&quot;&gt;Volume management: LVM&lt;/h1&gt;

&lt;p&gt;The Arch Linux wiki puts it more concisely than I ever could:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Logical Volume Management utilizes the kernel’s device-mapper feature to provide a system of partitions independent of underlying disk layout. With LVM you abstract your storage and have “virtual partitions”, making extending/shrinking easier (subject to potential filesystem limitations).&lt;/em&gt;&lt;sup id=&quot;fnref:lvm&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:lvm&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;In other words, it just makes your life easier. I chose the method of using the Logical Volume Manager (LVM) on top of the LUKS-encrypted partition&lt;sup id=&quot;fnref:lvm-on-luks&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:lvm-on-luks&quot; class=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;. No real reason as to why, just that it seemed to be the most simple and robust choice. The major disadvantage of it is that the LVM cannot be used to span multiple physical volumes. For a laptop, this shouldn’t be that much of a problem, however.&lt;/p&gt;

&lt;p&gt;Let’s now create the Physical Volume (pv) and Logical Volumes (lv’s) for the main partition layout (swap, root, home):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pvcreate /dev/mapper/lvm

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vgcreate MyVol /dev/mapper/lvm

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;lvcreate &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; 8G MyVol &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; swap
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;lvcreate &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; 25G MyVol &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; root
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;lvcreate &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; 100%FREE MyVol &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; home

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkfs.ext4 /dev/mapper/MyVol-root
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkfs.ext4 /dev/mapper/MyVol-home
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkswap /dev/mapper

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mount /dev/mapper/MyVol-root /mnt
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; /mnt/home
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mount /dev/mapper/MyVol-home /mnt/home
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;swapon /dev/mapper/MyVol-swap&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;install-arch-linux&quot;&gt;Install Arch Linux&lt;/h1&gt;

&lt;p&gt;Now it is time to install Arch Linux to our root partition.&lt;/p&gt;

&lt;p&gt;First, mount your boot partition that we made earlier:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; /mnt/boot
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mount /dev/nvmen1p1 /mnt/boot&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now let’s install the Arch base system with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pacstrap&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacstrap /mnt base base-devel&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Other configuration, comments inlined:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Generate filesystem information&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;genfstab &lt;span class=&quot;nt&quot;&gt;-U&lt;/span&gt; /mnt &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; /mnt/etc/fstab

&lt;span class=&quot;c&quot;&gt;# Chroot the installation&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;arch-chroot /mnt /bin/bash

&lt;span class=&quot;c&quot;&gt;# Uncomment en_US.UTF-8 and generate the locale&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vi /etc/locale.gen
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;locale-gen

&lt;span class=&quot;c&quot;&gt;# Create locale.conf&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;/etc/locale.conf
&lt;span class=&quot;nv&quot;&gt;LANG&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;en_US.UTF-8

&lt;span class=&quot;c&quot;&gt;# Set timezone&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /usr/share/zoneinfo/Europe/Helsinki /etc/localtime

&lt;span class=&quot;c&quot;&gt;# Sync the hardware clock&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;hwclock &lt;span class=&quot;nt&quot;&gt;--systohc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--utc&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then, configure and regenerate a new initial ramdisk environment:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Change to: HOOKS=&quot;... encrypt lvm2 ... filesystems ...&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vi /etc/mkinitcpio.conf

&lt;span class=&quot;c&quot;&gt;# Generate initramfs&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkinitcpio &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; linux&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;boot-manager-systemd-boot&quot;&gt;Boot manager: systemd-boot&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;systemd-boot&lt;/em&gt; is a boot manager for UEFI systems. It only operates on ESPs and EFI-configured images. The project was previously known as ‘gummiboot’, but was merged into systemd in May 2015&lt;sup id=&quot;fnref:systemd-boot&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:systemd-boot&quot; class=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;The kernels we boot with systemd-boot have to be configured with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFIG_EFI_STUB&lt;/code&gt; enabled. This allows the UEFI firmware to act as a bootloader and start the kernel, without needing a separate boot loader such as GRUB. Luckily, the Arch Linux kernels have already been configured so.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Make sure you're booted into EFI mode and can see efivars:&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;efivar &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Make sure your ESP partition (described earlier) is mounted at /boot&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mount &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;boot

&lt;span class=&quot;c&quot;&gt;# Install systemd-boot&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;bootctl &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;After that, you should have a folder &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/loader/entries&lt;/code&gt;. Add the following boot entry file there:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Get the UUID of your root partition&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;blkid &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; UUID &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; value /dev/nvme0n1p2

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;arch-encrypted-lvm.conf
title Arch Linux Encrypted LVM
linux /vmlinuz-linux
initrd /intel-ucode.img
initrd /initramfs-linux.img
options &lt;span class=&quot;nv&quot;&gt;cryptdevice&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&amp;lt;UUID&amp;gt;:MyVol &lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/dev/mapper/MyVol-root quiet rw&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd /intel-ucode.img&lt;/code&gt; is the microcode for Intel processors - if you have one, install the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;intel-ucode&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;Now you can exit the chroot (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exit&lt;/code&gt;) and reboot. If all went well, you should be asked to unlock the root partition’s encryption and be awarded with a login shell.&lt;/p&gt;

&lt;p&gt;In the &lt;a href=&quot;/configuring-arch-linux-on-dell-xps-15/&quot;&gt;next post&lt;/a&gt;, I’ll describe the steps to configure a straightforward userspace setup for Arch Linux.&lt;/p&gt;

&lt;p&gt;If you liked this post, you can
&lt;a href=&quot;https://twitter.com/intent/tweet?url=https://www.saminiir.com/installing-arch-linux-on-dell-xps-15/&amp;amp;text=Installing+Arch+Linux+on+Dell+XPS+15&amp;amp;via=saminiir&quot; target=&quot;_blank&quot;&gt;
  share it with your followers&lt;/a&gt; 
and 
&lt;a href=&quot;https://twitter.com/saminiir&quot;&gt;
  follow me on Twitter&lt;/a&gt;!&lt;/p&gt;

&lt;h1 id=&quot;sources&quot;&gt;Sources&lt;/h1&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:dell-xps-15&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://www.dell.com/us/p/xps-15-9550-laptop/pd&quot;&gt;http://www.dell.com/us/p/xps-15-9550-laptop/pd&lt;/a&gt; &lt;a href=&quot;#fnref:dell-xps-15&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:cold-boot&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Cold_boot_attack&quot;&gt;https://en.wikipedia.org/wiki/Cold_boot_attack&lt;/a&gt; &lt;a href=&quot;#fnref:cold-boot&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:diceware&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Diceware&quot;&gt;https://en.wikipedia.org/wiki/Diceware&lt;/a&gt; &lt;a href=&quot;#fnref:diceware&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:lvm&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/LVM#LVM_Building_Blocks&quot;&gt;https://wiki.archlinux.org/index.php/LVM#LVM_Building_Blocks&lt;/a&gt; &lt;a href=&quot;#fnref:lvm&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:lvm-on-luks&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system#LVM_on_LUKS&quot;&gt;https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system#LVM_on_LUKS&lt;/a&gt; &lt;a href=&quot;#fnref:lvm-on-luks&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:systemd-boot&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://www.freedesktop.org/wiki/Software/systemd/systemd-boot/&quot;&gt;https://www.freedesktop.org/wiki/Software/systemd/systemd-boot/&lt;/a&gt; &lt;a href=&quot;#fnref:systemd-boot&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 24 Jun 2016 18:00:00 +0000</pubDate>
        <link>https://www.saminiir.com/installing-arch-linux-on-dell-xps-15/</link>
        <guid isPermaLink="true">https://www.saminiir.com/installing-arch-linux-on-dell-xps-15/</guid>
        
        
        <category>linux</category>
        
        <category>arch linux</category>
        
      </item>
    
      <item>
        <title>Let's code a TCP/IP stack, 3: TCP Basics &amp; Handshake</title>
        <description>&lt;p&gt;Now that our userspace TCP/IP stack has minimal implementations for Ethernet and IPv4, it is time to look into the dreaded Transmission Control Protocol (TCP).&lt;/p&gt;

&lt;p&gt;Operating on the fourth OSI networking layer&lt;sup id=&quot;fnref:osi-model&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:osi-model&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, &lt;em&gt;transport&lt;/em&gt;, TCP is responsible for repairing erroneous connections and faults in packet delivery. Indeed, TCP is the workhorse of the Internet, providing reliable communications in virtually all computer networking today.&lt;/p&gt;

&lt;p&gt;TCP is not exactly a new protocol - the first specification came out in 1974&lt;sup id=&quot;fnref:first-tcp-spec&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:first-tcp-spec&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. A lot of has changed since then and TCP has acquired many extensions and corrections&lt;sup id=&quot;fnref:tcp-roadmap&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:tcp-roadmap&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;This post will delve into the basic theory behind TCP and attempts to give motivation for its design. Furthermore, we will look into the TCP header and discuss establishing a connection (TCP handshaking). As the last step, we’ll demonstrate the first functionality of TCP in our networking stack.&lt;/p&gt;

&lt;h1 class=&quot;no_toc&quot; id=&quot;contents&quot;&gt;Contents&lt;/h1&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#reliability-mechanisms&quot; id=&quot;markdown-toc-reliability-mechanisms&quot;&gt;Reliability mechanisms&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tcp-basics&quot; id=&quot;markdown-toc-tcp-basics&quot;&gt;TCP Basics&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tcp-header-format&quot; id=&quot;markdown-toc-tcp-header-format&quot;&gt;TCP Header Format&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tcp-handshake&quot; id=&quot;markdown-toc-tcp-handshake&quot;&gt;TCP Handshake&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tcp-options&quot; id=&quot;markdown-toc-tcp-options&quot;&gt;TCP Options&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#testing-the-tcp-handshake&quot; id=&quot;markdown-toc-testing-the-tcp-handshake&quot;&gt;Testing the TCP Handshake&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sources&quot; id=&quot;markdown-toc-sources&quot;&gt;Sources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reliability-mechanisms&quot;&gt;Reliability mechanisms&lt;/h1&gt;

&lt;p&gt;The problem of sending data reliably may seem superficial, but its actual implementation is involved. Mainly, several questions arise regarding error-repair in a datagram-style network:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How long should the sender wait for an acknowledgement from the receiver?&lt;/li&gt;
  &lt;li&gt;What if the receiver cannot process data as fast as it is sent?&lt;/li&gt;
  &lt;li&gt;What if the network in between (a router, for example) cannot process data as fast as it is sent?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In all of the scenarios, the underlying dangers of packet-switched networks apply - an acknowledgement from the receiver can be corrupted or even lost in transmit, which leaves the sender in a tricky situation.&lt;/p&gt;

&lt;p&gt;To combat these problems, several mechanisms can be used. Perhaps the most common is the &lt;em&gt;sliding window&lt;/em&gt; technique, where both parties keep an account of the transmitted data. The window data is considered to be sequential (like a slice of an array) and that window “slides” forward as data is processed (and acknowledged) by both sides:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;                 Left window edge             Right window edge
                       |                             |
                       |                             |
          &lt;span class=&quot;nt&quot;&gt;---------------------------------------------------------&lt;/span&gt;
          ...|    3    |    4    |    5    |    6    |    7    |...
          &lt;span class=&quot;nt&quot;&gt;---------------------------------------------------------&lt;/span&gt;
                  ^     ^                            ^    ^
                  |      &lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;                         /     |
                  |       &lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;                       /      |
             Sent and           Window size: 3         Cannot be
             ACKed                                     sent yet
            &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The convenient property of using this kind of a sliding window is that it also alleviates the problem of &lt;em&gt;flow control&lt;/em&gt;. Flow control is required, when the receiver cannot process data as fast it is sent. In this scenario, the size of the sliding window would be negotiated to be lower, resulting in throttled output from the sender.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Congestion control&lt;/em&gt;, on the other hand, helps the networking stacks in between the sender and receiver to not get congested. There are two general methods for this: in the explicit version, the protocol has a field for specifically informing the sender about the congestion status. In the implicit version, the sender tries to guess when the network is congested and should throttle its output. Overall, congestion control is a complex, recurrent networking problem with accompanying research still being done to this day.&lt;sup id=&quot;fnref:stevens-tcpip&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:stevens-tcpip&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h1 id=&quot;tcp-basics&quot;&gt;TCP Basics&lt;/h1&gt;

&lt;p&gt;The underlying mechanisms in TCP are much more involved than in other protocols like UDP and IP. Namely, TCP is a &lt;em&gt;connection-oriented&lt;/em&gt; protocol, which means that an unicast communication channel is established between exactly two sides as a first step. This connection is being actively taken care of by both sides: Establishing the connection (Handshaking), informing the other party of the data’s state and possible problems.&lt;/p&gt;

&lt;p&gt;The other important property of TCP is that it is a &lt;em&gt;streaming&lt;/em&gt; protocol. Unlike UDP, TCP does not guarantee applications steady “chunks” of data as they are sent and received. Rather, the TCP implementation has to buffer the data and when packets get lost, reordered or corrupted, TCP has to wait and organize the the data in the buffer. Only when the data is deemed intact, TCP can hand the data over to the application’s socket.&lt;/p&gt;

&lt;p&gt;As TCP operates on data as a stream, the “chunks” from the stream have to be converted into packets that IP can carry. This is called &lt;em&gt;packetization&lt;/em&gt;, where the TCP header contains the sequence number of the current index in the stream. This also has the convenient property that the stream can be broken into many variable-sized segments and TCP then knows how to &lt;em&gt;repacketize&lt;/em&gt; them.&lt;/p&gt;

&lt;p&gt;Similarly to IP, TCP also checks the message for integrity. This is achieved through the same checksum algorithm as in IP, but with added details. Mainly, the checksum is end-to-end, meaning that both the header and the data are included to the checksumming. In addition, a pseudo-header built from the IP header is included.&lt;/p&gt;

&lt;p&gt;If a TCP implementation receives corrupted segments, it discards them and does not notify the sender. This error is corrected by a timer set by the sender, which can be used to retransmit a segment if it was never acknowledged by the receiver.&lt;/p&gt;

&lt;p&gt;TCP is also a &lt;em&gt;full-duplex&lt;/em&gt; system, meaning that traffic can flow simultaneously in both direction. This means that the communicating sides have to keep the sequencing of data to both directions in memory. In more depth, TCP preserves its traffic footprint by including an acknowledgement for the opposite traffic in the segments it sends.&lt;/p&gt;

&lt;p&gt;In essence, the sequencing of the data stream is the main principle of TCP. The problem of keeping it synchronized, however, is not a simple one.&lt;/p&gt;

&lt;h1 id=&quot;tcp-header-format&quot;&gt;TCP Header Format&lt;/h1&gt;

&lt;p&gt;Next, we’ll define the message header and describe its fields. The TCP header is seemingly simple, but contains a lot of information about the communication state.&lt;/p&gt;

&lt;p&gt;The TCP header is 20 octets in size&lt;sup id=&quot;fnref:tcpdump-man&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:tcpdump-man&quot; class=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;        0                            15                              31
       &lt;span class=&quot;nt&quot;&gt;-----------------------------------------------------------------&lt;/span&gt;
       |          &lt;span class=&quot;nb&quot;&gt;source &lt;/span&gt;port          |       destination port        |
       &lt;span class=&quot;nt&quot;&gt;-----------------------------------------------------------------&lt;/span&gt;
       |                        sequence number                        |
       &lt;span class=&quot;nt&quot;&gt;-----------------------------------------------------------------&lt;/span&gt;
       |                     acknowledgment number                     |
       &lt;span class=&quot;nt&quot;&gt;-----------------------------------------------------------------&lt;/span&gt;
       |  HL   | rsvd  |C|E|U|A|P|R|S|F|        window size            |
       &lt;span class=&quot;nt&quot;&gt;-----------------------------------------------------------------&lt;/span&gt;
       |         TCP checksum          |       urgent pointer          |
       &lt;span class=&quot;nt&quot;&gt;-----------------------------------------------------------------&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;em&gt;Source Port&lt;/em&gt; and &lt;em&gt;Destination Port&lt;/em&gt; fields are used to establish multiple connections from and to hosts. Namely, the Berkeley sockets are the prevalent interface for applications to bind to the TCP networking stack. Through ports, the networking stack knows where to direct the traffic to. As the fields are 16 bits in size, the port values range from 0 to 65535.&lt;/p&gt;

&lt;p&gt;Since every byte in the stream is numbered, the &lt;em&gt;Sequence Number&lt;/em&gt; represents the TCP segment’s window index. When handshaking, this contains the &lt;em&gt;Initial Sequence Number&lt;/em&gt; (ISN).&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Acknowledgment Number&lt;/em&gt; contains the window’s index of the next byte the sender expects to receive. After the handshake, the ACK field must always be populated.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Header Length&lt;/em&gt; (HL) field presents the length of the header in 32-bit words.&lt;/p&gt;

&lt;p&gt;Next, several flags are presented. The first 4 bits (&lt;em&gt;rsvd&lt;/em&gt;) are not used.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;Congestion Window Reduced&lt;/em&gt; (C) is used for informing that the sender reduced its sending rate.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;ECN Echo&lt;/em&gt; (E) informs that the sender received a congestion notification.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;Urgent Pointer&lt;/em&gt; (U) indicates that the segment contains prioritized data.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;ACK&lt;/em&gt; (A) field is used to communicate the state of the TCP handshake. It stays on for the remainder of the connection.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;PSH&lt;/em&gt; (P) is used to indicate that the receiver should “push” the data to the application as soon as possible.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;RST&lt;/em&gt; (R) resets the TCP connection.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;SYN&lt;/em&gt; (S) is used to synchronize sequence numbers in the initial handshake.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;FIN&lt;/em&gt; (F) indicates that the sender has finished sending data.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;em&gt;Window Size&lt;/em&gt; field is used to advertise the window size. In other words, this is the number of bytes the receiver is willing to accept. Since it is a 16-bit field, the maximum window size is 65,535 bytes.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;TCP Checksum&lt;/em&gt; field is used to verify the integrity of the TCP segment. The algorithm is the same as for the Internet Protocol, but the input segment also contains the TCP data and also a pseudo-header from the IP datagram.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Urgent Pointer&lt;/em&gt; is used when the U-flag is set. The pointer indicates the position of the urgent data in the stream.&lt;/p&gt;

&lt;p&gt;After the header, several options can be provided. An example of these options is the &lt;em&gt;Maximum Segment Size&lt;/em&gt; (MSS), where the sender informs the other side of the maximum size of the segments.&lt;/p&gt;

&lt;p&gt;After the possible options, the actual data follows. The data, however, is not required. For example, the handshake is accomplished with only TCP headers.&lt;/p&gt;

&lt;h1 id=&quot;tcp-handshake&quot;&gt;TCP Handshake&lt;/h1&gt;

&lt;p&gt;A TCP connection usually undergoes the following phases: connection setup (handshaking), data transfer and closing of the connection. The following diagrams depicts the usual handshaking routine of TCP:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;          TCP A                                                TCP B
    	  
    1.  CLOSED                                               LISTEN
    	
    2.  SYN-SENT    &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &amp;lt;&lt;span class=&quot;nv&quot;&gt;SEQ&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;100&amp;gt;&amp;lt;&lt;span class=&quot;nv&quot;&gt;CTL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;SYN&amp;gt;               &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; SYN-RECEIVED
    	  
    3.  ESTABLISHED &amp;lt;&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &amp;lt;&lt;span class=&quot;nv&quot;&gt;SEQ&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;300&amp;gt;&amp;lt;&lt;span class=&quot;nv&quot;&gt;ACK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;101&amp;gt;&amp;lt;&lt;span class=&quot;nv&quot;&gt;CTL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;SYN,ACK&amp;gt;  &amp;lt;&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; SYN-RECEIVED
    			
    4.  ESTABLISHED &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &amp;lt;&lt;span class=&quot;nv&quot;&gt;SEQ&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;101&amp;gt;&amp;lt;&lt;span class=&quot;nv&quot;&gt;ACK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;301&amp;gt;&amp;lt;&lt;span class=&quot;nv&quot;&gt;CTL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ACK&amp;gt;       &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; ESTABLISHED
    			  
    5.  ESTABLISHED &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &amp;lt;&lt;span class=&quot;nv&quot;&gt;SEQ&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;101&amp;gt;&amp;lt;&lt;span class=&quot;nv&quot;&gt;ACK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;301&amp;gt;&amp;lt;&lt;span class=&quot;nv&quot;&gt;CTL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ACK&amp;gt;&amp;lt;DATA&amp;gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; ESTABLISHED&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Host A’s socket is in a closed state, which means it is not accepting connections. On the contrary, host B’s socket that is bound to a specific port is listening for new connections.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Host A intends to initiate a connection with host B. Thus, A crafts a TCP segment that has its SYN flag set and also the Sequence field populated with a value (100).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Host B responds with a TCP segment that has its SYN and ACK fields set, and acknowledges A’s Sequence number by adding 1 to it (ACK=101). Likewise, B generates a sequence number (300).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The 3-way handshake is finished by an ACK from the originator (A) of the connection request. The Acknowledgement field reflects the sequence number the host next expects to receive from the other side.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Data starts to flow, mainly because both sides have acknowledged each other’s segment numbers.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the common scenario of establishing a TCP connection. However, several questions arise:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;How is the initial Sequence number chosen?&lt;/li&gt;
  &lt;li&gt;What if both sides request a connection for each other at the same time?&lt;/li&gt;
  &lt;li&gt;What if segments are delayed for some time or indefinitely?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;em&gt;Initial Sequence Number&lt;/em&gt; (ISN) is chosen independently by both communication parties at first contact. As it is a crucial part of identifying the connection, it has to be chosen so that it is most likely unique and not easily guessable. Indeed, the &lt;em&gt;TCP Sequence Number Attack&lt;/em&gt;&lt;sup id=&quot;fnref:tcp-seq-num-attack&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:tcp-seq-num-attack&quot; class=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; is the situation where an attacker can replicate a TCP connection and effectively feed data to the target, impersonating as a trusted host.&lt;/p&gt;

&lt;p&gt;The original specification suggests that the ISN is chosen by a counter that increments every 4 microseconds. This, however, can be guessed by an attacker. In reality, modern networking stacks generate the ISN by more complicated methods.&lt;/p&gt;

&lt;p&gt;The situation where both endpoints receive a connection request (SYN) from each other is called a &lt;em&gt;Simultaneous Open&lt;/em&gt;. This is solved by an extra message exchange in the TCP handshake: Both sides send an ACK (without knowing that the other side has done it as well), and both sides SYN-ACK the requests. After this, data transfer commences.&lt;/p&gt;

&lt;p&gt;Lastly, the TCP implementation has to have a timer for knowing when to give up on establishing a connection. Attempts are made to re-establish the connection, usually with an exponential backoff, but once the maximum retries or the time threshold is met, the connection is deemed to be non-existant.&lt;/p&gt;

&lt;h1 id=&quot;tcp-options&quot;&gt;TCP Options&lt;/h1&gt;

&lt;p&gt;The last field in the TCP header segment is reserved for possible TCP options. The original specification provided three options, but later specifications have added many more. Next, we’ll look at the most common options.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Maximum Segment Size&lt;/em&gt; (MSS) option informs the maximum TCP segment size the TCP implementation is willing to receive. The typical value for this is 1460 bytes in IPv4.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Selective Acknowledgment&lt;/em&gt; (SACK) option optimizes the scenario when many packets are lost in transmit and the receiver’s window of data is filled with “holes”. To remedy the resulting degraded throughput, a TCP implementation can inform the sender of the specific packets it did not receive with SACK. Thus, the sender receives information about the state of the data in a more straight-forward manner than with the accumulating acknowledment scheme.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Window Scale&lt;/em&gt; option increases the limited 16-bit window size. Namely, if both sides include this option in their handshake segments, the window size is multiplied with this scale. Having bigger window sizes are mainly important for bulk data transfer.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Timestamps&lt;/em&gt; option allows the sender to place a timestamp into the TCP segment, which then can be used to calculate the RTT for each ACK segment. This information can then be used to calculate the TCP retransmission timeout.&lt;/p&gt;

&lt;h1 id=&quot;testing-the-tcp-handshake&quot;&gt;Testing the TCP Handshake&lt;/h1&gt;

&lt;p&gt;Now that we have the TCP handshake routine mocked and it effectively listens for every port, let’s test it:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;saminiir@localhost ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;nmap &lt;span class=&quot;nt&quot;&gt;-Pn&lt;/span&gt; 10.0.0.4 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 1337

Starting Nmap 7.00 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; https://nmap.org &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; at 2016-05-08 19:02 EEST
Nmap scan report &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;10.0.0.4
Host is up &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0.00041s latency&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
PORT     STATE SERVICE
1337/tcp open  waste

Nmap &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;: 1 IP address &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1 host up&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; scanned &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;0.05 seconds&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Because of the fact that nmap does a SYN-scan (it only waits for the SYN-ACK to decide if the target’s port is open), it is easy to fool it to think we have an application listening on the port by just returning a SYN-ACK TCP segment.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;The minimum viable TCP handshake routine can be done relatively effortless by just picking a Sequence number, setting the SYN-ACK flags and calculating the checksum for the resulting TCP segment.&lt;/p&gt;

&lt;p&gt;Next time, we’ll look into the most important responsibility of TCP: Reliable data transfer. Managing the window of the stream is essential for transmitting data with TCP and the logic for it can get somewhat complex.&lt;/p&gt;

&lt;p&gt;Furthermore, providing applications a way to bind to the TCP implementation is done with &lt;em&gt;sockets&lt;/em&gt;. Thus, we’ll look into the Berkeley Socket API and see if we can mock it for applications, enabling them to use our custom TCP implementation.&lt;/p&gt;

&lt;p&gt;The source code for the project is hosted at &lt;a href=&quot;https://github.com/saminiir/level-ip&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you liked this post, you can
&lt;a href=&quot;https://twitter.com/intent/tweet?url=https://www.saminiir.com/lets-code-tcp-ip-stack-3-tcp-handshake/&amp;amp;text=Let%27s+code+a+TCP%2FIP+stack%2C+3%3A+TCP+Basics+%26+Handshake&amp;amp;via=saminiir&quot; target=&quot;_blank&quot;&gt;
  share it with your followers&lt;/a&gt; 
and 
&lt;a href=&quot;https://twitter.com/saminiir&quot;&gt;
  follow me on Twitter&lt;/a&gt;!&lt;/p&gt;

&lt;h1 id=&quot;sources&quot;&gt;Sources&lt;/h1&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:osi-model&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/OSI_model&quot;&gt;https://en.wikipedia.org/wiki/OSI_model&lt;/a&gt; &lt;a href=&quot;#fnref:osi-model&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:first-tcp-spec&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc675&quot;&gt;https://tools.ietf.org/html/rfc675&lt;/a&gt; &lt;a href=&quot;#fnref:first-tcp-spec&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:tcp-roadmap&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc7414&quot;&gt;https://tools.ietf.org/html/rfc7414&lt;/a&gt; &lt;a href=&quot;#fnref:tcp-roadmap&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:stevens-tcpip&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/TCP/IP_Illustrated#Volume_1:_The_Protocols&quot;&gt;https://en.wikipedia.org/wiki/TCP/IP_Illustrated#Volume_1:_The_Protocols&lt;/a&gt; &lt;a href=&quot;#fnref:stevens-tcpip&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:tcpdump-man&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://www.tcpdump.org/tcpdump_man.html&quot;&gt;http://www.tcpdump.org/tcpdump_man.html&lt;/a&gt; &lt;a href=&quot;#fnref:tcpdump-man&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:tcp-seq-num-attack&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://www.ietf.org/rfc/rfc1948.txt&quot;&gt;http://www.ietf.org/rfc/rfc1948.txt&lt;/a&gt; &lt;a href=&quot;#fnref:tcp-seq-num-attack&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sun, 15 May 2016 09:00:00 +0000</pubDate>
        <link>https://www.saminiir.com/lets-code-tcp-ip-stack-3-tcp-handshake/</link>
        <guid isPermaLink="true">https://www.saminiir.com/lets-code-tcp-ip-stack-3-tcp-handshake/</guid>
        
        
        <category>tcp/ip</category>
        
        <category>tutorial</category>
        
        <category>c programming</category>
        
        <category>ip</category>
        
        <category>networking</category>
        
        <category>linux</category>
        
      </item>
    
      <item>
        <title>Let's code a TCP/IP stack, 2: IPv4 &amp; ICMPv4</title>
        <description>&lt;p&gt;This time in our userspace TCP/IP stack we will implement a minimum viable IP layer and test it with ICMP echo requests (also known as &lt;em&gt;pings&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;We will take a look at the formats of IPv4 and ICMPv4 and describe how to check them for integrity. Some features, such as IP fragmentation, are left as an exercise for the reader.&lt;/p&gt;

&lt;p&gt;For our networking stack IPv4 was chosen over IPv6 since it is still the default network protocol for the Internet. However, this is changing fast&lt;sup id=&quot;fnref:ipv6-adoption&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ipv6-adoption&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; and our networking stack can be extended with IPv6 in the future.&lt;/p&gt;

&lt;h1 class=&quot;no_toc&quot; id=&quot;contents&quot;&gt;Contents&lt;/h1&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#internet-protocol-version-4&quot; id=&quot;markdown-toc-internet-protocol-version-4&quot;&gt;Internet Protocol version 4&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#header-format&quot; id=&quot;markdown-toc-header-format&quot;&gt;Header Format&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#internet-checksum&quot; id=&quot;markdown-toc-internet-checksum&quot;&gt;Internet Checksum&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#internet-control-message-protocol-version-4&quot; id=&quot;markdown-toc-internet-control-message-protocol-version-4&quot;&gt;Internet Control Message Protocol version 4&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#header-format-1&quot; id=&quot;markdown-toc-header-format-1&quot;&gt;Header Format&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#messages-and-their-processing&quot; id=&quot;markdown-toc-messages-and-their-processing&quot;&gt;Messages and their processing&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#testing-the-implementation&quot; id=&quot;markdown-toc-testing-the-implementation&quot;&gt;Testing the implementation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sources&quot; id=&quot;markdown-toc-sources&quot;&gt;Sources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;internet-protocol-version-4&quot;&gt;Internet Protocol version 4&lt;/h1&gt;

&lt;p&gt;The next layer (L3)&lt;sup id=&quot;fnref:osi-model&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:osi-model&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; in our implementation, after Ethernet frames, handles the delivery of data to a destination. Namely, the &lt;em&gt;Internet Protocol&lt;/em&gt; (IP) was invented to provide a base for transport protocols such as TCP and UDP. It is connectionless, meaning that unlike TCP, all of the datagrams are handled independently of each other in the networking stack. This also means that IP datagrams may arrive out-of-order.&lt;sup id=&quot;fnref:stevens-tcpip&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:stevens-tcpip&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Furthermore, IP does not guarantee successful delivery. This is a conscious choice taken by the protocol designers, since IP is meant to provide a base for protocols that likewise do not guarantee delivery. UDP is one such protocol.&lt;/p&gt;

&lt;p&gt;If reliability between the communicating parties is required, a protocol such as TCP is used on top of IP. In that case, the higher level protocol is responsible for detecting missing data and making sure all of it is delivered.&lt;/p&gt;

&lt;h2 id=&quot;header-format&quot;&gt;Header Format&lt;/h2&gt;

&lt;p&gt;The IPv4 header is typically 20 octets in length. The header can contain trailing options, but they are omitted from our implementation. The meaning of the fields is relatively straightforward and can be described as a C struct:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iphdr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ihl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frag_offset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ttl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;csum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;saddr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;daddr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__attribute__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The 4-bit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;version&lt;/code&gt; field indicates the format of the Internet header. In our case, the value will be 4 for IPv4.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Internet Header Length&lt;/em&gt; field &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ihl&lt;/code&gt; is likewise 4 bits in length and indicates the number of 32-bit &lt;em&gt;words&lt;/em&gt; in the IP header. Because the field is 4 bits in size, it can only hold a maximum value of 15. Thus the maximum length of an IP header is 60 octets (15 times 32 divided by eight).&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;type of service&lt;/em&gt; field &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tos&lt;/code&gt; originates from the first IP specification&lt;sup id=&quot;fnref:ipv4-spec&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ipv4-spec&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. It has been divided into smaller fields in later specifications, but for simplicity’s sake, we will treat the field as defined in the original specification. The field communicates the quality of service intended for the IP datagram.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;total length&lt;/em&gt; field &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;len&lt;/code&gt;  communicates the length of the whole IP datagram. As it is a 16-bit field, the maximum length is then 65535 bytes. Large IP datagrams are subject to fragmentation, in which they are split into smaller datagrams in order to satisfy the &lt;em&gt;Maximum Transmission Unit&lt;/em&gt; (MTU) of different communication interfaces.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt; field is used to index the datagram and is ultimately used for reassembly of fragmented IP datagrams. The field’s value is simply a counter that is incremented by the sending party. In turn, the receiving side knows how to order the incoming fragments.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flags&lt;/code&gt; field defines various control flags of the datagram. In specific, the sender can specify whether the datagram is allowed to be fragmented, whether it is the last fragment or that there’s more fragments incoming.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;fragment offset&lt;/em&gt; field, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frag_offset&lt;/code&gt;, indicates the position of the fragment in a datagram. Naturally, the first datagram has this index set to 0.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ttl&lt;/code&gt; or &lt;em&gt;time to live&lt;/em&gt; is a common attribute that is used to count down the datagram’s lifetime. It is usually set to 64 by the original sender, and every receiver decrements this counter by one. When it hits zero, the datagram is to be discarded and possibly an ICMP message is replied back to indicate an error.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proto&lt;/code&gt; field provides the datagram an inherent ability to carry other protocols in its payload. The field usually contains values such as 16 (UDP) or 6 (TCP), and is simply used to communicate the type of the actual data to the receiver.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;header checksum&lt;/em&gt; field, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;csum&lt;/code&gt;, is used to verify the integrity of the IP header. The algorithm for it is relatively simple, and will be explained further down in this tutorial.&lt;/p&gt;

&lt;p&gt;Finally, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;saddr&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;daddr&lt;/code&gt; fields indicate the source and destination addresses of the datagram, respectively. Even though the fields are 32-bit in length and thus provide a pool of approximately 4.5 billion addresses, the address range is going to be exhausted in the near-future&lt;sup id=&quot;fnref:ipv4-exhaustion&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ipv4-exhaustion&quot; class=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;. The IPv6 protocol extends this length to 128 bits and as a result, future-proofs the address range of the Internet Protocol, perhaps permanently.&lt;/p&gt;

&lt;h2 id=&quot;internet-checksum&quot;&gt;Internet Checksum&lt;/h2&gt;

&lt;p&gt;The Internet checksum field is used to check the integrity of an IP datagram. Calculating the checksum is relatively simple and is defined in the original specification&lt;sup id=&quot;fnref:ipv4-spec:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ipv4-spec&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The checksum field is the 16 bit one’s complement of the one’s complement sum of all 16 bit words in the header.  For purposes of computing the checksum, the value of the checksum field is zero.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The actual&lt;sup id=&quot;fnref:internet-checksum-spec&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:internet-checksum-spec&quot; class=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; code for the algorithm is as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;checksum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* Compute Internet Checksum for &quot;count&quot; bytes
     *         beginning at location &quot;addr&quot;.
     * Taken from https://tools.ietf.org/html/rfc1071
     */&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;register&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/*  This is the inner loop */&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/*  Add left-over byte, if any */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/*  Fold 32-bit sum to 16 bits */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xffff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Take the example IP header &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;45 00 00 54 41 e0 40 00 40 01 00 00 0a 00 00 04 0a 00 00 05&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Adding the fields together yields the two’s complement sum &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;01 1b 3e&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Then, to convert it to one’s complement, the carry-over bits are added to the first 16-bits: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1b 3e&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;01&lt;/code&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1b 3f&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Finally, the one’s complement of the sum is taken, resulting to the checksum value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e4c0&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The IP header becomes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;45 00 00 54 41 e0 40 00 40 01 e4 c0 0a 00 00 04 0a 00 00 05&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The checksum can be verified by applying the algorithm again and if the result is 0, the data is most likely good.&lt;/p&gt;

&lt;h1 id=&quot;internet-control-message-protocol-version-4&quot;&gt;Internet Control Message Protocol version 4&lt;/h1&gt;

&lt;p&gt;As the Internet Protocol lacks mechanisms for reliability, some way of informing communicating parties of possible error scenarios is required. As a result, the &lt;em&gt;Internet Control Message Protocol&lt;/em&gt; (ICMP)&lt;sup id=&quot;fnref:icmpv4-spec&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:icmpv4-spec&quot; class=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; is used for diagnostic measures in the network. An example of this is the case where a gateway is not reachable - the network stack that recognizes this sends an ICMP “Gateway Unreachable” message back to the origin.&lt;/p&gt;

&lt;h2 id=&quot;header-format-1&quot;&gt;Header Format&lt;/h2&gt;

&lt;p&gt;The ICMP header resides in the payload of the corresponding IP packet. The structure of the ICMPv4 header is as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;icmp_v4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;csum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__attribute__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type&lt;/code&gt; field communicates the purpose of the message. 42 different&lt;sup id=&quot;fnref:iana-icmp-types&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:iana-icmp-types&quot; class=&quot;footnote&quot;&gt;8&lt;/a&gt;&lt;/sup&gt; values are reserved for the type field, but only about 8 are commonly used. In our implementation, the types 0 (Echo Reply), 3 (Destination Unreachable) and 8 (Echo request) are used.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;code&lt;/code&gt; field further describes the meaning of the message. For example, when the type is 3 (Destination Unreachable), the code-field implies the reason. A common error is when a packet cannot be routed to a network: the originating host then most likely receives an ICMP message with the type 3 and code 0 (Net Unreachable).&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;csum&lt;/code&gt; field is the same checksum field as in the IPv4 header, and the same algorithm can be used to calculate it. In ICMPv4 however, the checksum is &lt;em&gt;end-to-end&lt;/em&gt;, meaning that also the payload is included when calculating the checksum.&lt;/p&gt;

&lt;h2 id=&quot;messages-and-their-processing&quot;&gt;Messages and their processing&lt;/h2&gt;

&lt;p&gt;The actual ICMP payload consists of query/informational messages and error messages. First, we’ll look at the Echo Request/Reply messages, commonly referred to as “pinging” in networking:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;icmp_v4_echo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__attribute__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The message format is compact. The field &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt; is set by the sending host to determine to which process the echo reply is intended. For example, the process id can be set in to this field.&lt;/p&gt;

&lt;p&gt;The field &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;seq&lt;/code&gt; is the sequence number of the echo and it is simply a number starting from zero and incremented by one whenever a new echo request is formed. This is used to detect if echo messages disappear or are reordered while in transit.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; field is optional, but often contains information like the timestamp of the echo. This can then be used to estimate the round-trip time between hosts.&lt;/p&gt;

&lt;p&gt;Perhaps the most common ICMPv4 error message, &lt;em&gt;Destination Unreachable&lt;/em&gt;, has the following format:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;icmp_v4_dst_unreachable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unused&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__attribute__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The first octet is unused. Then, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;len&lt;/code&gt; field indicates the length of the original datagram, in 4-octet units for IPv4. The value of the 2-octet field &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var&lt;/code&gt; depends on the ICMP code.&lt;/p&gt;

&lt;p&gt;Finally, as much as possible of the original IP packet that caused the Destination Unreachable state is placed into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; field.&lt;/p&gt;

&lt;h1 id=&quot;testing-the-implementation&quot;&gt;Testing the implementation&lt;/h1&gt;

&lt;p&gt;From a shell, we can verify that our userspace networking stack responds to ICMP echo requests:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;saminiir@localhost ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ping &lt;span class=&quot;nt&quot;&gt;-c3&lt;/span&gt; 10.0.0.4
PING 10.0.0.4 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;10.0.0.4&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 56&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;84&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; bytes of data.
64 bytes from 10.0.0.4: &lt;span class=&quot;nv&quot;&gt;icmp_seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 &lt;span class=&quot;nv&quot;&gt;ttl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;64 &lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0.191 ms
64 bytes from 10.0.0.4: &lt;span class=&quot;nv&quot;&gt;icmp_seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2 &lt;span class=&quot;nv&quot;&gt;ttl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;64 &lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0.200 ms
64 bytes from 10.0.0.4: &lt;span class=&quot;nv&quot;&gt;icmp_seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;3 &lt;span class=&quot;nv&quot;&gt;ttl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;64 &lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0.150 ms

&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; 10.0.0.4 ping statistics &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
3 packets transmitted, 3 received, 0% packet loss, &lt;span class=&quot;nb&quot;&gt;time &lt;/span&gt;1999ms
rtt min/avg/max/mdev &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0.150/0.180/0.200/0.024 ms&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;A minimum viable networking stack that handles Ethernet frames, ARP and IP can be created relatively easily. However, the original specifications have been extended with many new ones. In this post, we skimmed over IP features such as options, fragmentation and the header DCN and DS fields.&lt;/p&gt;

&lt;p&gt;Furthermore, IPv6 is crucial for the future of the Internet. It is not yet ubiquitous but being a newer protocol than IPv4, it definitely is something that should be implemented in our networking stack.&lt;/p&gt;

&lt;p&gt;The source code for this blog post can be found at &lt;a href=&quot;https://github.com/saminiir/level-ip&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the next blog post we will advance to the transport layer (L4) and start implementing the notorious &lt;em&gt;Transmission Control Protocol&lt;/em&gt; (TCP). Namely, TCP is a connection-oriented protocol and ensures reliability between both communicating sides. These aspects obviously bring about more complexity, and being an old protocol, TCP has its dark corners.&lt;/p&gt;

&lt;p&gt;If you liked this post, you can
&lt;a href=&quot;https://twitter.com/intent/tweet?url=https://www.saminiir.com/lets-code-tcp-ip-stack-2-ipv4-icmpv4/&amp;amp;text=Let%27s+code+a+TCP%2FIP+stack%2C+2%3A+IPv4+%26+ICMPv4&amp;amp;via=saminiir&quot; target=&quot;_blank&quot;&gt;
  share it with your followers&lt;/a&gt; 
and 
&lt;a href=&quot;https://twitter.com/saminiir&quot;&gt;
  follow me on Twitter&lt;/a&gt;!&lt;/p&gt;

&lt;h1 id=&quot;sources&quot;&gt;Sources&lt;/h1&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:ipv6-adoption&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/IPv6_deployment&quot;&gt;https://en.wikipedia.org/wiki/IPv6_deployment&lt;/a&gt; &lt;a href=&quot;#fnref:ipv6-adoption&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:osi-model&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/OSI_model&quot;&gt;https://en.wikipedia.org/wiki/OSI_model&lt;/a&gt; &lt;a href=&quot;#fnref:osi-model&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:stevens-tcpip&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/TCP/IP_Illustrated#Volume_1:_The_Protocols&quot;&gt;https://en.wikipedia.org/wiki/TCP/IP_Illustrated#Volume_1:_The_Protocols&lt;/a&gt; &lt;a href=&quot;#fnref:stevens-tcpip&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:ipv4-spec&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://tools.ietf.org/html/rfc791&quot;&gt;http://tools.ietf.org/html/rfc791&lt;/a&gt; &lt;a href=&quot;#fnref:ipv4-spec&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:ipv4-spec:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:ipv4-exhaustion&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/IPv4_address_exhaustion&quot;&gt;https://en.wikipedia.org/wiki/IPv4_address_exhaustion&lt;/a&gt; &lt;a href=&quot;#fnref:ipv4-exhaustion&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:internet-checksum-spec&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc1071&quot;&gt;https://tools.ietf.org/html/rfc1071&lt;/a&gt; &lt;a href=&quot;#fnref:internet-checksum-spec&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:icmpv4-spec&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://www.ietf.org/rfc/rfc792.txt&quot;&gt;https://www.ietf.org/rfc/rfc792.txt&lt;/a&gt; &lt;a href=&quot;#fnref:icmpv4-spec&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:iana-icmp-types&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml&quot;&gt;http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml&lt;/a&gt; &lt;a href=&quot;#fnref:iana-icmp-types&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sun, 24 Apr 2016 09:00:00 +0000</pubDate>
        <link>https://www.saminiir.com/lets-code-tcp-ip-stack-2-ipv4-icmpv4/</link>
        <guid isPermaLink="true">https://www.saminiir.com/lets-code-tcp-ip-stack-2-ipv4-icmpv4/</guid>
        
        
        <category>tcp/ip</category>
        
        <category>tutorial</category>
        
        <category>c programming</category>
        
        <category>ip</category>
        
        <category>icmp</category>
        
        <category>networking</category>
        
        <category>linux</category>
        
      </item>
    
      <item>
        <title>Let's code a TCP/IP stack, 1: Ethernet &amp; ARP</title>
        <description>&lt;p&gt;Writing your own TCP/IP stack may seem like a daunting task. Indeed, TCP has accumulated many specifications over its lifetime of more than thirty years. The core specification, however, is seemingly compact&lt;sup id=&quot;fnref:tcp-roadmap&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:tcp-roadmap&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; - the important parts being TCP header parsing, the state machine, congestion control and retransmission timeout computation.&lt;/p&gt;

&lt;p&gt;The most common layer 2 and layer 3 protocols, Ethernet and IP respectively, pale in comparison to TCP’s complexity. In this blog series, we will implement a minimal userspace TCP/IP stack for Linux.&lt;/p&gt;

&lt;p&gt;The purpose of these posts and the resulting software is purely educational - to learn network and system programming at a deeper level.&lt;/p&gt;

&lt;h1 class=&quot;no_toc&quot; id=&quot;contents&quot;&gt;Contents&lt;/h1&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#tuntap-devices&quot; id=&quot;markdown-toc-tuntap-devices&quot;&gt;TUN/TAP devices&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ethernet-frame-format&quot; id=&quot;markdown-toc-ethernet-frame-format&quot;&gt;Ethernet Frame Format&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ethernet-frame-parsing&quot; id=&quot;markdown-toc-ethernet-frame-parsing&quot;&gt;Ethernet Frame Parsing&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#address-resolution-protocol&quot; id=&quot;markdown-toc-address-resolution-protocol&quot;&gt;Address Resolution Protocol&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#address-resolution-algorithm&quot; id=&quot;markdown-toc-address-resolution-algorithm&quot;&gt;Address Resolution Algorithm&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sources&quot; id=&quot;markdown-toc-sources&quot;&gt;Sources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;tuntap-devices&quot;&gt;TUN/TAP devices&lt;/h1&gt;

&lt;p&gt;To intercept low-level network traffic from the Linux kernel, we will use a Linux TAP device. In short, a TUN/TAP device is often used by networking userspace applications to manipulate L3/L2 traffic, respectively. A popular example is &lt;a href=&quot;/openvpn-puts-packets-inside-your-packets/#tunneling&quot;&gt;tunneling&lt;/a&gt;, where a packet is wrapped inside the payload of another packet.&lt;/p&gt;

&lt;p&gt;The advantage of TUN/TAP devices is that they’re easy to set up in a userspace program and they are already being used in a multitude of programs, such as &lt;a href=&quot;/openvpn-puts-packets-inside-your-packets/&quot;&gt;OpenVPN&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As we want to build the networking stack from the layer 2 up, we need a TAP device. We instantiate it like so:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * Taken from Kernel Documentation/networking/tuntap.txt
 */&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;tun_alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ifreq&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ifr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/dev/net/tap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;O_RDWR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;print_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Cannot open TUN/TAP dev&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;CLEAR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ifr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/* Flags: IFF_TUN   - TUN device (no Ethernet headers)
     *        IFF_TAP   - TAP device
     *
     *        IFF_NO_PI - Do not provide packet information
     */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ifr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ifr_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IFF_TAP&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IFF_NO_PI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;strncpy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ifr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ifr_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IFNAMSIZ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ioctl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TUNSETIFF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ifr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;print_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERR: Could not ioctl tun: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;strerror&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;errno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;strcpy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ifr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ifr_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;After this, the returned file descriptor &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fd&lt;/code&gt; can be used to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write&lt;/code&gt; data to the virtual device’s ethernet buffer.&lt;/p&gt;

&lt;p&gt;The flag &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IFF_NO_PI&lt;/code&gt; is crucial here, otherwise we end up with unnecessary packet information prepended to the Ethernet frame. You can actually take a look at the kernel’s &lt;a href=&quot;https://github.com/torvalds/linux/blob/v4.4/drivers/net/tun.c#L1306&quot;&gt;source code&lt;/a&gt; of the tun-device driver and verify this yourself.&lt;/p&gt;

&lt;h1 id=&quot;ethernet-frame-format&quot;&gt;Ethernet Frame Format&lt;/h1&gt;

&lt;p&gt;The multitude of different Ethernet networking technologies are the backbone of connecting computers in &lt;em&gt;Local Area Networks&lt;/em&gt; (LANs). As with all physical technology, the Ethernet standard has greatly evolved from its first version&lt;sup id=&quot;fnref:ethernet&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ethernet&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, published by Digital Equipment Corporation, Intel and Xerox in 1980.&lt;/p&gt;

&lt;p&gt;The first version of Ethernet was slow in today’s standards - about 10Mb/s and it utilized half-duplex communication, meaning that you either sent or received data, but not at the same time. This is why a &lt;em&gt;Media Access Control&lt;/em&gt; (MAC) protocol had to be incorporated to organize the data flow. Even to this day, &lt;em&gt;Carrier Sense, Multiple Access with Collision Detection&lt;/em&gt; (CSMA/CD) is required as the MAC method if running an Ethernet interface in half-duplex mode.&lt;/p&gt;

&lt;p&gt;The invention of the &lt;em&gt;100BASE-T&lt;/em&gt; Ethernet standard used twisted-pair wiring to enable full-duplex communication and higher throughput speeds. Additionally, the simultaneous increase in popularity of Ethernet switches made CSMA/CD largely obsolete.&lt;/p&gt;

&lt;p&gt;The different Ethernet standards are maintained by the IEEE 802.3&lt;sup id=&quot;fnref:ieee-802-3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ieee-802-3&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; working group.&lt;/p&gt;

&lt;p&gt;Next, we’ll take a look at the Ethernet Frame header. It can be declared as a C struct followingly:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;linux/if_ether.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eth_hdr&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dmac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;smac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ethertype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__attribute__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dmac&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;smac&lt;/code&gt; are pretty self-explanatory fields. They contain the MAC addresses of the communicating parties (destination and source, respectively).&lt;/p&gt;

&lt;p&gt;The overloaded field, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ethertype&lt;/code&gt;, is a 2-octet field, that depending on its value, either indicates the length or the type of the payload. Specifically, if the field’s value is greater or equal to 1536, the field contains the type of the payload (e.g. IPv4, ARP). If the value is less than that, it contains the length of the payload.&lt;/p&gt;

&lt;p&gt;After the type field, there is a possibility of several different &lt;em&gt;tags&lt;/em&gt; for the Ethernet frame. These tags can be used to describe the &lt;em&gt;Virtual LAN&lt;/em&gt; (VLAN) or the &lt;em&gt;Quality of Service&lt;/em&gt; (QoS) type of the frame. Ethernet frame tags are excluded from our implementation, so the corresponding field also does not show up in our protocol declaration.&lt;/p&gt;

&lt;p&gt;The field &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payload&lt;/code&gt; contains a pointer to the Ethernet frame’s payload. In our case, this will contain an ARP or IPv4 packet. If the payload length is smaller than the minimum required 48 bytes (without tags), pad bytes are appended to the end of the payload to meet the requirement.&lt;/p&gt;

&lt;p&gt;We also include the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if_ether.h&lt;/code&gt; Linux header to provide a mapping between ethertypes and their hexadecimal values.&lt;/p&gt;

&lt;p&gt;Lastly, the Ethernet Frame Format also includes the &lt;em&gt;Frame Check Sequence&lt;/em&gt; field in the end, which is used with &lt;em&gt;Cyclic Redundancy Check&lt;/em&gt; (CRC) to check the integrity of the frame. We will omit the handling of this field in our implementation.&lt;/p&gt;

&lt;h1 id=&quot;ethernet-frame-parsing&quot;&gt;Ethernet Frame Parsing&lt;/h1&gt;

&lt;p&gt;The attribute &lt;em&gt;packed&lt;/em&gt; in a struct’s declaration is an implementation detail - It is used to instruct the GNU C compiler not to optimize the struct memory layout for data alignment with padding bytes&lt;sup id=&quot;fnref:gnu-c-packed&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:gnu-c-packed&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. The use of this attribute stems purely out of the way we are “parsing” the protocol buffer, which is just a type cast over the data buffer with the proper protocol struct:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eth_hdr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hdr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eth_hdr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;A portable, albeit slightly more laborious approach, would be to serialize the protocol data manually. This way, the compiler is free to add padding bytes to conform better to different processor’s data alignment requirements.&lt;/p&gt;

&lt;p&gt;The overall scenario for parsing and handling incoming Ethernet frames is straightforward:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tun_read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BUFLEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;print_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERR: Read from tun_fd: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;strerror&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;errno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eth_hdr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hdr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init_eth_hdr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;handle_frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;netdev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;handle_frame&lt;/code&gt; function just looks at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ethertype&lt;/code&gt; field of the Ethernet header, and decides its next action based upon the value.&lt;/p&gt;

&lt;h1 id=&quot;address-resolution-protocol&quot;&gt;Address Resolution Protocol&lt;/h1&gt;

&lt;p&gt;The &lt;em&gt;Address Resolution Protocol&lt;/em&gt; (ARP) is used for dynamically mapping a 48-bit Ethernet address (MAC address) to a protocol address (e.g. IPv4 address). The key here is that with ARP, multitude of different L3 protocols can be used: Not just IPv4, but other protocols like CHAOS, which declares 16-bit protocol addresses.&lt;/p&gt;

&lt;p&gt;The usual case is that you know the IP address of some service in your LAN, but to establish actual communications, also the hardware address (MAC) needs to be known. Hence, ARP is used to broadcast and query the network, asking the owner of the IP address to report its hardware address.&lt;/p&gt;

&lt;p&gt;The ARP packet format is relatively straightforward:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arp_hdr&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hwtype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;protype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hwsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prosize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opcode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__attribute__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The ARP header (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arp_hdr&lt;/code&gt;) contains the 2-octet &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hwtype&lt;/code&gt;, which determines the link layer type used. This is Ethernet in our case, and the actual value is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x0001&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The 2-octet &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;protype&lt;/code&gt; field indicates the protocol type. In our case, this is IPv4, which is communicated with the value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x0800&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hwsize&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prosize&lt;/code&gt; fields are both 1-octet in size, and they contain the sizes of the hardware and protocol fields, respectively. In our case, these would be 6 bytes for MAC addresses, and 4 bytes for IP addresses.&lt;/p&gt;

&lt;p&gt;The 2-octet field &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opcode&lt;/code&gt; declares the type of the ARP message. It can be ARP request (1), ARP reply (2), RARP request (3) or RARP reply (4).&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; field contains the actual payload of the ARP message, and in our case, this will contain IPv4 specific information:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arp_ipv4&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;smac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dmac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__attribute__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The fields are pretty self explanatory. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;smac&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dmac&lt;/code&gt; contain the 6-byte MAC addresses of the sender and receiver, respectively. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sip&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dip&lt;/code&gt; contain the sender’s and receiver’s IP addresses, respectively.&lt;/p&gt;

&lt;h1 id=&quot;address-resolution-algorithm&quot;&gt;Address Resolution Algorithm&lt;/h1&gt;

&lt;p&gt;The &lt;a href=&quot;https://tools.ietf.org/html/rfc826&quot;&gt;original specification&lt;/a&gt; depicts this simple algorithm for address resolution:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;?Do I have the hardware &lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;ar&lt;span class=&quot;nv&quot;&gt;$hrd&lt;/span&gt;?
Yes: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;almost definitely&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;optionally check the hardware length ar&lt;span class=&quot;nv&quot;&gt;$hln&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  ?Do I speak the protocol &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;ar&lt;span class=&quot;nv&quot;&gt;$pro&lt;/span&gt;?
  Yes:
    &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;optionally check the protocol length ar&lt;span class=&quot;nv&quot;&gt;$pln&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    Merge_flag :&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false
    &lt;/span&gt;If the pair &amp;lt;protocol &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;, sender protocol address&amp;gt; is
        already &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;my translation table, update the sender
        hardware address field of the entry with the new
        information &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;the packet and &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;Merge_flag to true.
    ?Am I the target protocol address?
    Yes:
      If Merge_flag is &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;, add the triplet &amp;lt;protocol &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;,
          sender protocol address, sender hardware address&amp;gt; to
          the translation table.
      ?Is the opcode ares_op&lt;span class=&quot;nv&quot;&gt;$REQUEST&lt;/span&gt;?  &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;NOW look at the opcode!!&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
      Yes:
        Swap hardware and protocol fields, putting the &lt;span class=&quot;nb&quot;&gt;local
            &lt;/span&gt;hardware and protocol addresses &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;the sender fields.
        Set the ar&lt;span class=&quot;nv&quot;&gt;$op&lt;/span&gt; field to ares_op&lt;span class=&quot;nv&quot;&gt;$REPLY&lt;/span&gt;
        Send the packet to the &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;new&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; target hardware address on
            the same hardware on which the request was received.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Namely, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;translation table&lt;/code&gt; is used to store the results of ARP, so that hosts can just look up whether they already have the entry in their cache. This avoids spamming the network for redundant ARP requests.&lt;/p&gt;

&lt;p&gt;The algorithm is implemented in &lt;a href=&quot;https://github.com/saminiir/level-ip/blob/e9ceb08f01a5499b85f03e2d615309c655b97e8f/src/arp.c#L53&quot;&gt;arp.c&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Finally, the ultimate test for an ARP implementation is to see whether it replies to ARP requests correctly:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;saminiir@localhost lvl-ip]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;arping &lt;span class=&quot;nt&quot;&gt;-I&lt;/span&gt; tap0 10.0.0.4
ARPING 10.0.0.4 from 192.168.1.32 tap0
Unicast reply from 10.0.0.4 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;00:0C:29:6D:50:25]  3.170ms
Unicast reply from 10.0.0.4 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;00:0C:29:6D:50:25]  13.309ms

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;saminiir@localhost lvl-ip]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;arp
Address                  HWtype  HWaddress           Flags Mask            Iface
10.0.0.4                 ether   00:0c:29:6d:50:25   C                     tap0&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The kernel’s networking stack recognized the ARP reply from our custom networking stack, and consequently populated its ARP cache with the entry of our virtual network device. Success!&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;The minimal implementation of Ethernet Frame handling and ARP is relatively easy and can be done in a few lines of code. On the contrary, the reward-factor is quite high, since you get to populate a Linux host’s ARP cache with your own make-belief Ethernet device!&lt;/p&gt;

&lt;p&gt;The source code for the project can be found at &lt;a href=&quot;https://github.com/saminiir/level-ip&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the next post, we’ll continue the implementation with ICMP echo &amp;amp; reply (ping) and IPv4 packet parsing.&lt;/p&gt;

&lt;p&gt;If you liked this post, you can
&lt;a href=&quot;https://twitter.com/intent/tweet?url=https://www.saminiir.com/lets-code-tcp-ip-stack-1-ethernet-arp/&amp;amp;text=Let%27s+code+a+TCP%2FIP+stack%2C+1%3A+Ethernet+%26+ARP&amp;amp;via=saminiir&quot; target=&quot;_blank&quot;&gt;
  share it with your followers&lt;/a&gt; 
and 
&lt;a href=&quot;https://twitter.com/saminiir&quot;&gt;
  follow me on Twitter&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Kudos to Xiaochen Wang, whose similar implementation proved invaluable for me in getting up to speed with C network programming and protocol handling. I find his &lt;a href=&quot;https://github.com/chobits/tapip&quot;&gt;source code&lt;/a&gt;&lt;sup id=&quot;fnref:tapip&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:tapip&quot; class=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; easy to understand and some of my design choices were straight-out copied from his implementation.&lt;/em&gt;&lt;/p&gt;

&lt;h1 id=&quot;sources&quot;&gt;Sources&lt;/h1&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:tcp-roadmap&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc7414&quot;&gt;https://tools.ietf.org/html/rfc7414&lt;/a&gt; &lt;a href=&quot;#fnref:tcp-roadmap&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:ethernet&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://ethernethistory.typepad.com/papers/EthernetSpec.pdf&quot;&gt;http://ethernethistory.typepad.com/papers/EthernetSpec.pdf&lt;/a&gt; &lt;a href=&quot;#fnref:ethernet&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:ieee-802-3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/IEEE_802.3&quot;&gt;https://en.wikipedia.org/wiki/IEEE_802.3&lt;/a&gt; &lt;a href=&quot;#fnref:ieee-802-3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:gnu-c-packed&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#Common-Type-Attributes&quot;&gt;https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#Common-Type-Attributes&lt;/a&gt; &lt;a href=&quot;#fnref:gnu-c-packed&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:tapip&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/chobits/tapip&quot;&gt;https://github.com/chobits/tapip&lt;/a&gt; &lt;a href=&quot;#fnref:tapip&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sun, 06 Mar 2016 10:00:00 +0000</pubDate>
        <link>https://www.saminiir.com/lets-code-tcp-ip-stack-1-ethernet-arp/</link>
        <guid isPermaLink="true">https://www.saminiir.com/lets-code-tcp-ip-stack-1-ethernet-arp/</guid>
        
        
        <category>tcp/ip</category>
        
        <category>c programming</category>
        
        <category>networking</category>
        
        <category>tutorial</category>
        
        <category>linux</category>
        
      </item>
    
      <item>
        <title>OpenVPN puts packets inside your packets</title>
        <description>&lt;p&gt;I realized I do not know exactly &lt;em&gt;how&lt;/em&gt; OpenVPN does its magic in Linux.&lt;/p&gt;

&lt;p&gt;I mean, sure, it encrypts and tunnels the packets to another endpoint, but can you describe the exact steps to achieve this? If not, read on. In fact, read on anyway for good measure.&lt;/p&gt;

&lt;p&gt;This is the general idea I had pictured in my mind how OpenVPN works:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Receive packets&lt;/li&gt;
  &lt;li&gt;Encrypt them&lt;/li&gt;
  &lt;li&gt;Tunnel them&lt;/li&gt;
  &lt;li&gt;Send to destination&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Several questions arise, though:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How is tunneling achieved in OpenVPN’s case?&lt;/li&gt;
  &lt;li&gt;What is the mechanism for receiving and sending the packets?&lt;/li&gt;
  &lt;li&gt;How is encryption and decryption of the data achieved?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s delve deeper into these questions.&lt;/p&gt;

&lt;h1 class=&quot;no_toc&quot; id=&quot;contents&quot;&gt;Contents&lt;/h1&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#tunneling&quot; id=&quot;markdown-toc-tunneling&quot;&gt;Tunneling&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#encryption&quot; id=&quot;markdown-toc-encryption&quot;&gt;Encryption&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#openvpn-protocol&quot; id=&quot;markdown-toc-openvpn-protocol&quot;&gt;OpenVPN protocol&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tuntap-devices&quot; id=&quot;markdown-toc-tuntap-devices&quot;&gt;TUN/TAP devices&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sources&quot; id=&quot;markdown-toc-sources&quot;&gt;Sources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;tunneling&quot;&gt;Tunneling&lt;/h1&gt;

&lt;p&gt;What is tunneling? According to the magnificent TCP/IP Illustrated&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Tunneling, generally speaking, is the idea of carrying lower-layer traffic in higher-layer (or equal-layer) packets. For example, IPv4 can be carried in an IPv4 or IPv6 packet; Ethernet can be carried in a UDP or IPv4 or IPv6 packet, and so on.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In other words, tunneling is achieved by injecting packets into the payload of other packets. Reminds me of &lt;a href=&quot;http://www.urbandictionary.com/define.php?term=Yo+Dawg&quot;&gt;a certain meme&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Various protocols for establishing tunnels exist, the prominent ones being &lt;em&gt;Generic Routing Encapsulation&lt;/em&gt; (GRE), Microsoft’s &lt;em&gt;Point-to-Point Tunneling Protocol&lt;/em&gt; (PPTP) and the &lt;em&gt;Layer 2 Tunneling Protocol&lt;/em&gt; (L2TP).&lt;/p&gt;

&lt;p&gt;The result is that virtual links between computers in different networks can be set up. An example of this is a company’s private network, which can be reached from the public network via tunneling.&lt;/p&gt;

&lt;p&gt;Note, however, that tunneling itself does not guarantee secure communications. Encryption has to be applied to the payload, assuming you’ve succeeded to exchange cryptographic keys securely in an insecure environment.&lt;/p&gt;

&lt;h1 id=&quot;encryption&quot;&gt;Encryption&lt;/h1&gt;

&lt;p&gt;When using tunneling, there’s a high chance that the information you transmit is of delicate nature. Hence, cryptographic measures have to be taken into use to prevent anyone from snooping in on the data.&lt;/p&gt;

&lt;p&gt;Since OpenVPN is an userspace application, &lt;em&gt;Transport Layer Security&lt;/em&gt; (TLS) is a natural choice for the security protocol&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. TLS operates in the layers above the networking stack, so implementing it in an application’s scope is easier than more involved lower-level protocols that require specific&lt;sup id=&quot;fnref:swan&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:swan&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; kernel modules. If you’ve ever browsed a site with the protocol HTTPS, then you have used TLS for authentication and encryption.&lt;/p&gt;

&lt;p&gt;The basic steps for secure communication are implemented in OpenVPN as follows&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The X509 PKI (public key infrastructure) for session authentication&lt;/li&gt;
  &lt;li&gt;The TLS protocol for key exchange&lt;/li&gt;
  &lt;li&gt;The OpenSSL cipher-independent EVP interface for encrypting tunnel data&lt;/li&gt;
  &lt;li&gt;The HMAC-SHA1 algorithm for authenticating tunnel data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The X509 Public Key Infrastructure is an ITU-T standard which relies on Certificate Authorities (CA) for digital signatures of certificates. Through this, a client communicating to a server can verify that the server is really who it claims to be.&lt;/p&gt;

&lt;p&gt;The TLS protocol is the ubiquitous privacy protocol suite used to encrypt, well, pretty much anything dealing with Internet. Namely, TLS is responsible of negotiating a secure communication channel between two parties. This mainly consists of certificate and key exchanges, which can be used to authenticate the other party and subsequently encrypt and decrypt the data.&lt;/p&gt;

&lt;p&gt;Key exchange is a fascinating topic as it revolves around the problem of two parties attempting to establish a secure communication channel in an insecure medium. Turns out, the Diffie-Hellman method (DH)&lt;sup id=&quot;fnref:dh&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:dh&quot; class=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; is one such clever approach, where two parties can agree upon a key without revealing that key to outsiders.&lt;/p&gt;

&lt;p&gt;Another option is to use RSA&lt;sup id=&quot;fnref:rsa&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:rsa&quot; class=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; public key cryptography for the key exchange. Whereas DH utilizes finite field arithmetic to achieve secure key exchange, RSA takes advantage of the integer factorization problem. This problem deals with the fact that it is hard to factor the numbers that a semiprime number is a product of.&lt;/p&gt;

&lt;p&gt;To abstract upon the routine cryptographic functions, OpenVPN uses the EVP interface&lt;sup id=&quot;fnref:evp&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:evp&quot; class=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; of the OpenSSL library. It provides encryption/decryption, signing/verifying, key derivation, hash functions and message authentication code (MAC) functions.&lt;/p&gt;

&lt;p&gt;Lastly, Message Authentication Code (MAC) is an important part of secure communications. It is used to verify message integrity, but also to authenticate the message’s origins.&lt;/p&gt;

&lt;h1 id=&quot;openvpn-protocol&quot;&gt;OpenVPN protocol&lt;/h1&gt;

&lt;p&gt;The general view of the TLS handshaking is as follows&lt;sup id=&quot;fnref:tls-spec&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:tls-spec&quot; class=&quot;footnote&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;        Client                                              Server

   ClientHello                      &lt;span class=&quot;nt&quot;&gt;--------&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
                                                               ServerHello
                                                               Certificate&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
                                                         ServerKeyExchange&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
                                                        CertificateRequest&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
                                    &amp;lt;&lt;span class=&quot;nt&quot;&gt;--------&lt;/span&gt;              ServerHelloDone
   Certificate&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
   ClientKeyExchange
   CertificateVerify&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ChangeCipherSpec]
   Finished                         &lt;span class=&quot;nt&quot;&gt;--------&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
                                                        &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ChangeCipherSpec]
                                    &amp;lt;&lt;span class=&quot;nt&quot;&gt;--------&lt;/span&gt;                     Finished

   GenerateTLSBindingKey                             GenerateTLSBindingKey

   Application Data                 &amp;lt;&lt;span class=&quot;nt&quot;&gt;-------&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;             Application Data&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;em&gt;ClientHello&lt;/em&gt; message is pretty self-explanatory. The client is required to send it to the server as its first message. It includes data like the TLS version requested, a randomized struct consisting of the current sender’s UNIX time and a 28-byte securely generated random number, requested cipher suite and requested compression algorithm.&lt;/p&gt;

&lt;p&gt;The server responds with a ServerHello, Certificate, CertificateRequest TLS records.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;ServerHello&lt;/em&gt; record is very much like the ClientHello message, except it has the responsibility of, among other things, choosing the ciphersuite that satisfies both parties’ requirements. In my OpenVPN test session, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TLS_RSA_WITH_AES_256_CBC_SHA&lt;/code&gt; was chosen as the ciphersuite. This means that RSA is used for the key exchange.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Certificate&lt;/em&gt; record is required whenever the key exchange method is anything other than Anonymous Diffie-Hellman. This is because both parties have to validate the identity of each other to prevent Man-in-the-Middle attacks. Finally, the certificate record contains the certificates of the server..&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;ServerKeyExchange&lt;/em&gt; record is only sent when “the server Certificate message (if sent) does not contain enough data to allow the client to exchange a premaster secret.”&lt;sup id=&quot;fnref:tls-spec:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:tls-spec&quot; class=&quot;footnote&quot;&gt;8&lt;/a&gt;&lt;/sup&gt; Thus, when using public-key cryptograpghy, you are unlikely to see this message.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;CertificateRequest&lt;/em&gt; record sent by the server is followed by the &lt;em&gt;ServerHelloDone&lt;/em&gt; message, which indicates to the client that the server has finished its part of the key exchange.&lt;/p&gt;

&lt;p&gt;Next, the client sends a &lt;em&gt;Certificate&lt;/em&gt; TLS record to the server, containing the client’s certificate used for authentication.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;ClientKeyExchange&lt;/em&gt; message is always sent next by the client. It contains either the RSA-encrypted secret or Diffie-Hellman parameters for establishing a shared secret between the two parties.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;CertificateVerify&lt;/em&gt; message is sent by the client if explicit verification of the client’s certificates is needed.&lt;/p&gt;

&lt;p&gt;Finally, the &lt;em&gt;Finished&lt;/em&gt; message is sent by both parties and it is the first encrypted message. Once both parties receive and validate the message, Application Data starts to flow in the encrypted tunnel between the parties. Before the Finished messages, &lt;em&gt;ChangeCipherSpec&lt;/em&gt; message is used to indicate any changes in the cipher specifications.&lt;/p&gt;

&lt;h1 id=&quot;tuntap-devices&quot;&gt;TUN/TAP devices&lt;/h1&gt;

&lt;p&gt;The tunneling of data in OpenVPN is achieved through TUN/TAP devices&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;. Simply put, TUN/TAP devices expose the operating system’s network traffic as virtual interfaces. This traffic can then be operated upon by the userspace application that is bound to the TUN/TAP virtual interface.&lt;/p&gt;

&lt;p&gt;A TUN device operates on IP packets (layer 3), and a TAP device operates on Ethernet frames (layer 2). The distinction is important, since operating on different networking layers enable different use cases. For example, if one wants Ethernet bridging, OpenVPN has to utilize TAP devices. For simple routing of traffic, TUN devices are a cheaper choice. A handy summary of the differences between bridging and routing is presented
&lt;a href=&quot;https://community.openvpn.net/openvpn/wiki/309-what-is-the-difference-between-bridging-and-routing&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With OpenVPN and TUN/TAP devices, the Linux Kernel networking stack is involved and does the heavy-lifting of the traffic. The only purpose of the TUN/TAP device is to allow the user-space application, OpenVPN, to operate on the raw Ethernet frames or IP packets. This is where tunneling and encryption is applied. The Ethernet frame or IP packet is encrypted and wrapped inside another IP packet with appropriate headers for delivery, and vice versa.&lt;/p&gt;

&lt;p&gt;The specific source code for how the TUN/TAP device is opened in OpenVPN is in the source file &lt;a href=&quot;https://github.com/OpenVPN/openvpn/blob/v2.3.10/src/openvpn/tun.c#L1504&quot;&gt;tun.c&lt;/a&gt;. It closely reflects the &lt;a href=&quot;https://www.kernel.org/doc/Documentation/networking/tuntap.txt&quot;&gt;TUN/TAP documentation&lt;/a&gt; of the Linux Kernel.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;Implementing secure communications is a fascinating matter but not a trivial one. The fundamental problem is that the Internet as we know it, is an unsecure medium. Anyone can snoop in on the data flowing through different networks, so establishing a secure communication channel is tricky.&lt;/p&gt;

&lt;p&gt;As a bonus, I found out there’s a module named &lt;a href=&quot;https://github.com/OpenVPN/openvpn/blob/v2.3.10/src/openvpn/gremlin.c&quot;&gt;gremlin&lt;/a&gt; in OpenVPN, which can be enabled with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--gremlin&lt;/code&gt; flag in debug mode. It will wreak havoc on your VPN tunnels, and is probably used to test OpenVPN. :-)&lt;/p&gt;

&lt;h1 id=&quot;sources&quot;&gt;Sources&lt;/h1&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/TCP/IP_Illustrated#Volume_1:_The_Protocols&quot;&gt;https://en.wikipedia.org/wiki/TCP/IP_Illustrated#Volume_1:_The_Protocols&lt;/a&gt; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://community.openvpn.net/openvpn/wiki/WhyChooseTLSAsOpenvpnsUnderlyingAuthenticationAndKeyNegotiationProtocol&quot;&gt;https://community.openvpn.net/openvpn/wiki/WhyChooseTLSAsOpenvpnsUnderlyingAuthenticationAndKeyNegotiationProtocol&lt;/a&gt; &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:swan&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://wiki.strongswan.org/projects/strongswan/wiki/KernelModules&quot;&gt;https://wiki.strongswan.org/projects/strongswan/wiki/KernelModules&lt;/a&gt; &lt;a href=&quot;#fnref:swan&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://community.openvpn.net/openvpn/wiki/OverviewOfOpenvpn&quot;&gt;https://community.openvpn.net/openvpn/wiki/OverviewOfOpenvpn&lt;/a&gt; &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:dh&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://www.ietf.org/rfc/rfc2631.txt&quot;&gt;https://www.ietf.org/rfc/rfc2631.txt&lt;/a&gt; &lt;a href=&quot;#fnref:dh&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:rsa&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://www.ietf.org/rfc/rfc2437.txt&quot;&gt;https://www.ietf.org/rfc/rfc2437.txt&lt;/a&gt; &lt;a href=&quot;#fnref:rsa&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:evp&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://wiki.openssl.org/index.php/EVP&quot;&gt;https://wiki.openssl.org/index.php/EVP&lt;/a&gt; &lt;a href=&quot;#fnref:evp&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:tls-spec&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc5246&quot;&gt;https://tools.ietf.org/html/rfc5246&lt;/a&gt; &lt;a href=&quot;#fnref:tls-spec&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:tls-spec:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://www.kernel.org/doc/Documentation/networking/tuntap.txt&quot;&gt;https://www.kernel.org/doc/Documentation/networking/tuntap.txt&lt;/a&gt; &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sat, 20 Feb 2016 07:00:00 +0000</pubDate>
        <link>https://www.saminiir.com/openvpn-puts-packets-inside-your-packets/</link>
        <guid isPermaLink="true">https://www.saminiir.com/openvpn-puts-packets-inside-your-packets/</guid>
        
        
        <category>networking</category>
        
      </item>
    
      <item>
        <title>Establish your online identity using GnuPG</title>
        <description>&lt;p&gt;I have a confession to make.&lt;/p&gt;

&lt;p&gt;I do not have an online identity. I have Twitter, Facebook (yeah I know) and this homepage, but still, my online presence is undermined by the fact that I or others cannot verify my identity.&lt;/p&gt;

&lt;p&gt;The remedy to this is public-key cryptography&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h1 class=&quot;no_toc&quot; id=&quot;contents&quot;&gt;Contents&lt;/h1&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#about-pgp&quot; id=&quot;markdown-toc-about-pgp&quot;&gt;About PGP&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#using-gpg&quot; id=&quot;markdown-toc-using-gpg&quot;&gt;Using GPG&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#creating-the-master-key&quot; id=&quot;markdown-toc-creating-the-master-key&quot;&gt;Creating the master key&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#key-management&quot; id=&quot;markdown-toc-key-management&quot;&gt;Key management&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#creating-a-revocation-certificate&quot; id=&quot;markdown-toc-creating-a-revocation-certificate&quot;&gt;Creating a revocation certificate&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#creating-subkeys&quot; id=&quot;markdown-toc-creating-subkeys&quot;&gt;Creating subkeys&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#evacuating-the-master-key-to-safety&quot; id=&quot;markdown-toc-evacuating-the-master-key-to-safety&quot;&gt;Evacuating the master key to safety&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#sending-the-public-key-to-a-key-server&quot; id=&quot;markdown-toc-sending-the-public-key-to-a-key-server&quot;&gt;Sending the public key to a key server&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#scenarios&quot; id=&quot;markdown-toc-scenarios&quot;&gt;Scenarios&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#importing-the-primary-secret-key&quot; id=&quot;markdown-toc-importing-the-primary-secret-key&quot;&gt;Importing the primary secret key&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#new-subkey&quot; id=&quot;markdown-toc-new-subkey&quot;&gt;New subkey&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#signing-keys&quot; id=&quot;markdown-toc-signing-keys&quot;&gt;Signing keys&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#extending-the-lifetime-of-a-key&quot; id=&quot;markdown-toc-extending-the-lifetime-of-a-key&quot;&gt;Extending the lifetime of a key&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#revoking-the-master-key&quot; id=&quot;markdown-toc-revoking-the-master-key&quot;&gt;Revoking the master key&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#revoking-a-subkey&quot; id=&quot;markdown-toc-revoking-a-subkey&quot;&gt;Revoking a subkey&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#distributing-an-encryption-subkey&quot; id=&quot;markdown-toc-distributing-an-encryption-subkey&quot;&gt;Distributing an encryption subkey&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#synchronizing-the-keyring-between-computers&quot; id=&quot;markdown-toc-synchronizing-the-keyring-between-computers&quot;&gt;Synchronizing the keyring between computers&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#notes&quot; id=&quot;markdown-toc-notes&quot;&gt;Notes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;about-pgp&quot;&gt;About PGP&lt;/h1&gt;

&lt;p&gt;Using GPG&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, the OpenPGP-compliant&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; cryptographic software suite, you are able to prove your identity online and that of others. The principle behind this is called the web of trust&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;, where users of OpenPGP-compatible software sign each others public signatures (keys) after having verified their identity. This is in contrast to X.509&lt;sup id=&quot;fnref:5&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;, where a Certificate Authority, CA, is the sole party establishing the authenticity of users.&lt;/p&gt;

&lt;p&gt;So in a way, PGP adheres more to the open source philosophy of decentralized mode-of-operation. Plus, &lt;a href=&quot;https://en.wikipedia.org/wiki/Pretty_Good_Privacy#Criminal_investigation&quot;&gt;the story of PGP&lt;/a&gt; is pretty bad-ass.&lt;/p&gt;

&lt;p&gt;In this tutorial, we’ll refer to the OpenPGP specification as “PGP” and “GPG” as the free software implementation by the GNU Project.&lt;/p&gt;

&lt;h1 id=&quot;using-gpg&quot;&gt;Using GPG&lt;/h1&gt;

&lt;p&gt;Creating and managing PGP keys is not a straightforward matter. Many approaches exist and if you are a whistleblower, this tutorial probably does not meet your security standards. In fact, if there’s a chance you’ll be captured, tortured, or killed for the information you’ll encrypt, stop reading this tutorial and pray for the best. You are doing it wrong.&lt;/p&gt;

&lt;p&gt;For others, I think this tutorial serves as a suitable middle ground for the pragmatic daily usage of PGP.&lt;/p&gt;

&lt;h1 id=&quot;creating-the-master-key&quot;&gt;Creating the master key&lt;/h1&gt;

&lt;p&gt;Let’s get started creating your first PGP-based identity:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;
gpg &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;GnuPG&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 2.1.9
libgcrypt 1.6.4

Home: ~/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
        Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
        Compression: Uncompressed, ZIP, ZLIB, BZIP2

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--full-gen-key&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Pay attention to the fact that we’re using GPG v2.1 in this tutorial. The newest version prefers better hash algorithms.&lt;/p&gt;

&lt;p&gt;Select the default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RSA and RSA&lt;/code&gt; for making keys for both signing and encrypting:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;Pleasese &lt;span class=&quot;k&quot;&gt;select &lt;/span&gt;what kind of key you want:
   &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; RSA and RSA &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;default&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; DSA and Elgamal
   &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; DSA &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;sign only&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;4&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; RSA &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;sign only&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Next you will be asked to input the size for the RSA keys. We’ll use 4096 bits for the master key, since it is only meant for signing other keys. The subkeys we’ll use are used for encryption and decryption, so they are &lt;a href=&quot;https://www.gnupg.org/faq/gnupg-faq.html#no_default_of_rsa4096&quot;&gt;better off&lt;/a&gt; with a 2048 bit key size&lt;sup id=&quot;fnref:6&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:6&quot; class=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;RSA keys may be between 1024 and 4096 bits long.
What keysize &lt;span class=&quot;k&quot;&gt;do &lt;/span&gt;you want? &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;2048&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 4096
Requested keysize is 4096 bits&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Set an expiration time for your master key, in case you lose your revokation certificate and the master key is compromised. The downside is that you have to keep extending the lifetime of the key. The expiration time can be altered afterwards, even if a key has expired.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;Please specify how long the key should be valid.
         0 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; key does not expire
      &amp;lt;n&amp;gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; key expires &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;n days
      &amp;lt;n&amp;gt;w &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; key expires &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;n weeks
      &amp;lt;n&amp;gt;m &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; key expires &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;n months
      &amp;lt;n&amp;gt;y &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; key expires &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;n years
Key is valid &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;? &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Input your real name and email. Do not, however, &lt;a href=&quot;https://www.debian-administration.org/users/dkg/weblog/97&quot;&gt;input a comment&lt;/a&gt; when prompted:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;GnuPG needs to construct a user ID to identify your key.

Real name: Sami Niiranen
Email address: saminiir@gmail.com
Comment:
You selected this USER-ID:
    &lt;span class=&quot;s2&quot;&gt;&quot;Sami Niiranen &amp;lt;saminiir@gmail.com&amp;gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Next up, you have to come up with a passphrase for your master key. The Intercept has &lt;a href=&quot;https://theintercept.com/2015/03/26/passphrases-can-memorize-attackers-cant-guess/&quot;&gt;an insighftul article&lt;/a&gt; on the problems of passphrases and how to create robust ones (with Diceware).&lt;/p&gt;

&lt;p&gt;After some dice rolling and as you have entered the passphrase, the master key will be generated. This master key IS your electronic identity, so the point is to handle it with care. Especially the private master key we’ll evacuate to a safe place later on in this tutorial.&lt;/p&gt;

&lt;h2 id=&quot;key-management&quot;&gt;Key management&lt;/h2&gt;

&lt;p&gt;The case is often that one has multiple computers (desktop, laptop) and wants to use the same GPG identity on all devices. One popular scheme for this is creating subkeys, which are then distributed. There are, however, some differing opinions&lt;sup id=&quot;fnref:11&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:11&quot; class=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&quot;fnref:12&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:12&quot; class=&quot;footnote&quot;&gt;8&lt;/a&gt;&lt;/sup&gt; on this approach and whether it is a sane model for the web of trust.&lt;/p&gt;

&lt;p&gt;The alternative is to create master keypairs for every device and sign them with your ultra-secure master-master keypair.&lt;/p&gt;

&lt;p&gt;In this tutorial, the approach of creating subkeys is chosen, mostly because it seems to be the more popular&lt;sup id=&quot;fnref:13&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:13&quot; class=&quot;footnote&quot;&gt;9&lt;/a&gt;&lt;/sup&gt; choice and has the advantage of accumulating trust for your single PGP identity.&lt;/p&gt;

&lt;h2 id=&quot;creating-a-revocation-certificate&quot;&gt;Creating a revocation certificate&lt;/h2&gt;

&lt;p&gt;GnuPG version 2.1 automatically generates a revocation certificate. It will be located under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$GNUPGHOME/openpgp-revocs.d/&lt;/code&gt;. If you’re using an older version, be sure to generate one.&lt;/p&gt;

&lt;p&gt;Store this revocation certificate in a safe place. The revocation certificate is short enough to be handily stored on paper.&lt;/p&gt;

&lt;h2 id=&quot;creating-subkeys&quot;&gt;Creating subkeys&lt;/h2&gt;

&lt;p&gt;Subkeys are your day-to-day keys for signing and encryption. Hence, we’ll generate a subkey to the very computer you are now at.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--list-keys&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$yourid&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--edit-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$yourid&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg&amp;gt; addkey
Please &lt;span class=&quot;k&quot;&gt;select &lt;/span&gt;what kind of key you want:
   &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; DSA &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;sign only&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;4&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; RSA &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;sign only&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;5&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; Elgamal &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;encrypt only&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;6&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; RSA &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;encrypt only&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Your selection? 4&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Choose the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RSA (sign only)&lt;/code&gt; option for generating a signing key only. Use the default 2048-bit keysize if you have no reason to use a larger one. Choose an expiration date. Input a passphrase.&lt;/p&gt;

&lt;p&gt;Repeat the procedure, but this time, create a RSA (encrypt only) key.&lt;/p&gt;

&lt;p&gt;As a final step, trust and save the keys you’ve made:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;gpg&amp;gt; trust
gpg&amp;gt; save&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;After these operations, your keyring should look similar to this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;-k&lt;/span&gt;
/home/saminiir/.gnupg/pubring.kbx
&lt;span class=&quot;nt&quot;&gt;---------------------------------&lt;/span&gt;
pub   rsa4096/XXXXXXXX 2016-01-24 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;expires: 2016-07-22]
uid         &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ultimate] Sami Niiranen &amp;lt;saminiir@gmail.com&amp;gt;
sub   rsa4096/XXXXXXXX 2016-01-24 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;expires: 2016-07-22]
sub   rsa2048/XXXXXXXX 2016-01-24 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;expires: 2016-07-22]
sub   rsa2048/XXXXXXXX 2016-01-24 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;expires: 2016-07-22]&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;evacuating-the-master-key-to-safety&quot;&gt;Evacuating the master key to safety&lt;/h2&gt;

&lt;p&gt;Now you should have a master keypair and a signing/encryption sub-keypair for your personal computer. It is imperative, that the master keypair is now evacuated to safety.&lt;/p&gt;

&lt;p&gt;There are endless possibilities how to store your master keypair, from paper printouts in a safe, to armed guards in your basement. Because I haven’t yet obtained any interesting information to whistleblow, I chose the mundane approach of backing up the master keypair to a USB drive:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--export-secret-keys&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--armor&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$keyid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; privkey
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--export&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--armor&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$keyid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; pubkey
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--export-secret-subkeys&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$keyid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; subkeys
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--delete-secret-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$keyid&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--delete-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$keyid&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--import&lt;/span&gt; subkeys
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;shred &lt;/span&gt;subkeys&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Alternatively, with gpg2, you can delete keys without needing to twiddle with exporting and importing:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Get the keygrip of the key to be deleted&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;-K&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--with-keygrip&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; .gnupg/private-keys-v1.d/&lt;span class=&quot;nv&quot;&gt;$keygrip&lt;/span&gt;.key
&lt;span class=&quot;c&quot;&gt;# Make sure the older gpg format, secring.gpg, is empty and does not contain the key&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; .gnupg/secring.gpg &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can verify that the master secret key should not be in the keyring by detecting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sec#&lt;/code&gt; when listing the secret keys.&lt;/p&gt;

&lt;p&gt;Now, be sure to evacuate your master keypair &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;privkey&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pubkey&lt;/code&gt; with your chosen method to a safe location. I’m storing it in an encrypted USB drive. The short gist of that is as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;lsblk
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mount /dev/sdb /mnt/usb
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dd &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/dev/zero &lt;span class=&quot;nv&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/mnt/usb/disk.img &lt;span class=&quot;nv&quot;&gt;bs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1M &lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;16
&lt;span class=&quot;nv&quot;&gt;$ loopdev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;losetup &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;losetup &lt;span class=&quot;nv&quot;&gt;$loopdev&lt;/span&gt; /mnt/usb/disk.img
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cryptsetup &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; luksFormat &lt;span class=&quot;nv&quot;&gt;$loopdev&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cryptsetup isLuks &lt;span class=&quot;nv&quot;&gt;$loopdev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Success&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cryptsetup open &lt;span class=&quot;nv&quot;&gt;$loopdev&lt;/span&gt; usbkey
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkfs.ext3 /dev/mapper/usbkey
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mount /dev/mapper/usbkey /media/encrypted
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; ~/.gnupg /media/encrypted/
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--homedir&lt;/span&gt; /media/encrypted/.gnupg &lt;span class=&quot;nt&quot;&gt;-K&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;fuser &lt;span class=&quot;nt&quot;&gt;-km&lt;/span&gt; /media/encrypted
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;umount /media/encrypted
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cryptsetup remove usbkey
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;losetup &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$loopdev&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;umount /mnt/usb&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can &lt;a href=&quot;https://help.ubuntu.com/community/GPGKeyOnUSBDrive&quot;&gt;automatize the mounting of the encrypted filesystem&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;sending-the-public-key-to-a-key-server&quot;&gt;Sending the public key to a key server&lt;/h2&gt;

&lt;p&gt;Next, you’ll want your public key to be actually obtainable for other people. Keyservers are a good fit for this, since the gpg tool can be used to query them for other people’s public keys.&lt;/p&gt;

&lt;p&gt;For enhanced security, obtain the CA cert for the keyserver:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget https://sks-keyservers.net/sks-keyservers.netCA.pem&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Set the following as your keyserver configuration in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$GNUGPHOME/dirmngr.conf&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;keyserver hkps://hkps.pool.sks-keyservers.net
hkp-cacert /path/to/CA/sks-keyservers.netCA.pem&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Send your public key to the keyserver pool. Afterwards you and anybody else can find your PGP identity.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpgconf &lt;span class=&quot;nt&quot;&gt;--reload&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--send-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$keyid&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And you’re done setting up your GPG configuration! The following section depicts use cases and how to solve them.&lt;/p&gt;

&lt;h1 id=&quot;scenarios&quot;&gt;Scenarios&lt;/h1&gt;

&lt;h2 id=&quot;importing-the-primary-secret-key&quot;&gt;Importing the primary secret key&lt;/h2&gt;

&lt;p&gt;Since you need the primary secret key for many operations, like signing new keys, it needs to be imported from the safe storage medium back to your keychain:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mount /dev/sdb /mnt/usb
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;losetup &lt;span class=&quot;nt&quot;&gt;--find&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--show&lt;/span&gt; /mnt/usb/disk.img
/dev/loop0
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cryptsetup open /dev/loop0 usb
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mount /dev/mapper/usb /media/encrypted&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Replace the devices file descriptors with the correct ones.&lt;/p&gt;

&lt;p&gt;Then, import the primary secret key:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--homedir&lt;/span&gt; /media/encrypted/.gnupg &lt;span class=&quot;nt&quot;&gt;--export-secret-keys&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--armor&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$KEYID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; privkey
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--import&lt;/span&gt; privkey&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;After finishing with key manipulation, delete the private key from the keychain:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Get the keygrip of the key to be deleted&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;-K&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--with-keygrip&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; .gnupg/private-keys-v1.d/&lt;span class=&quot;nv&quot;&gt;$keygrip&lt;/span&gt;.key
&lt;span class=&quot;c&quot;&gt;# Make sure the older gpg format, secring.gpg, is empty and does not contain the key&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; .gnupg/secring.gpg &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;new-subkey&quot;&gt;New subkey&lt;/h2&gt;

&lt;p&gt;Create a new subkey. You’ll need your master keypair that is stashed away to certify the new subkey.&lt;/p&gt;

&lt;h2 id=&quot;signing-keys&quot;&gt;Signing keys&lt;/h2&gt;

&lt;p&gt;Again, you need the master secret key for this operation.&lt;/p&gt;

&lt;p&gt;Obtain, sign and export somebody’s key:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--search-keys&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$email&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;#Choose the public key to import&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--fingerprint&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$email&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;#Check the fingerprint&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--sign-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$email&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--armor&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--export&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$keyid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; signedkey
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--sign&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--encrypt&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--recipient&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$email&lt;/span&gt; signedkey&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And mail the resulting .gpg file to the person.&lt;/p&gt;

&lt;h2 id=&quot;extending-the-lifetime-of-a-key&quot;&gt;Extending the lifetime of a key&lt;/h2&gt;

&lt;p&gt;The point of setting an expiration date for all of your keys is to have them actually expire if you lose access to the master keys or the revokation key. Besides, checking your keys at least once per year can is a good practice that probably enhances your security.&lt;/p&gt;

&lt;p&gt;Just set the expiration date through the gpg interface:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--edit-key&lt;/span&gt; saminiir@gmail.com
gpg&amp;gt; expire&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Again, you need your master keypair for this operation to succeed.&lt;/p&gt;

&lt;h2 id=&quot;revoking-the-master-key&quot;&gt;Revoking the master key&lt;/h2&gt;

&lt;p&gt;To revoke your key, simply import the revocation certificate and update keyservers:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Read the cert, you need to modify it to prevent accidental revokement &lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vim .gnupg/openpgp-revocs.d/revcert.rev
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--import&lt;/span&gt; revcert.rev
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--send&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$keyid&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Do not delete revoked keys. They are still useful to decrypt data previously encrypted with the old key.&lt;/p&gt;

&lt;h2 id=&quot;revoking-a-subkey&quot;&gt;Revoking a subkey&lt;/h2&gt;

&lt;p&gt;To revoke a subkey, revoke it from gpg’s interface:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--edit-key&lt;/span&gt; saminiir@gmail.com
gpg&amp;gt; list
gpg&amp;gt; key 2
gpg&amp;gt; revkey&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Again, do not delete revoked keys. They are still useful to decrypt data previously encrypted with the old key.&lt;/p&gt;

&lt;h2 id=&quot;distributing-an-encryption-subkey&quot;&gt;Distributing an encryption subkey&lt;/h2&gt;

&lt;p&gt;For distributed usage, a subkey can be created for each usage purpose.&lt;/p&gt;

&lt;p&gt;For example, to encrypt and decrypt your password manager files both in your phone and laptop, transfer the generated encryption subkey to the phone like so:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# generate a strong random password&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--armor&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--gen-random&lt;/span&gt; 1 20
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg2 &lt;span class=&quot;nt&quot;&gt;--armor&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--export-secret-keys&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SUBKEY_ID&lt;/span&gt; | gpg2 &lt;span class=&quot;nt&quot;&gt;--armor&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--symmetric&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--output&lt;/span&gt; encsubkey.sec.asc&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;After that, transfer the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;encsubkey.sec.asc&lt;/code&gt; via a secure mechanism, e.g. a flash storage, to the new device.&lt;/p&gt;

&lt;p&gt;Never transfer private keys through the internet, and strive for isolated environments where the transfer is done.&lt;/p&gt;

&lt;h2 id=&quot;synchronizing-the-keyring-between-computers&quot;&gt;Synchronizing the keyring between computers&lt;/h2&gt;

&lt;p&gt;Synchronizing a GPG keyring between computers may be desired to propagate information about imported key IDs&lt;sup id=&quot;fnref:gpg-synchronizing&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:gpg-synchronizing&quot; class=&quot;footnote&quot;&gt;10&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;On whichever computer, export the keyring and put it on the encrypted USB drive:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--export-secret-keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; my-secret-keyring.gpg
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--export-options&lt;/span&gt; export-local-sigs &lt;span class=&quot;nt&quot;&gt;--export&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; my-public-keyring.gpg&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now, on the other computer, import (merge) the keyring:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--import&lt;/span&gt; my-secret-keyring.gpg
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--import-options&lt;/span&gt; import-local-sigs &lt;span class=&quot;nt&quot;&gt;--import&lt;/span&gt; my-public-keyring.gpg&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Repeat this process the other way around, if needed.&lt;/p&gt;

&lt;p&gt;If you liked this post, you can
&lt;a href=&quot;https://twitter.com/intent/tweet?url=https://www.saminiir.com/establish-cryptographic-identity-using-gnupg/&amp;amp;text=Establish+your+online+identity+using+GnuPG&amp;amp;via=saminiir&quot; target=&quot;_blank&quot;&gt;
  share it with your followers&lt;/a&gt; 
and 
&lt;a href=&quot;https://twitter.com/saminiir&quot;&gt;
  follow me on Twitter&lt;/a&gt;!&lt;/p&gt;

&lt;h1 id=&quot;notes&quot;&gt;Notes&lt;/h1&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Public-key_cryptography&quot;&gt;https://en.wikipedia.org/wiki/Public-key_cryptography&lt;/a&gt; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/GNU_Privacy_Guard&quot;&gt;https://en.wikipedia.org/wiki/GNU_Privacy_Guard&lt;/a&gt; &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc4880&quot;&gt;https://tools.ietf.org/html/rfc4880&lt;/a&gt; &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Web_of_trust&quot;&gt;https://en.wikipedia.org/wiki/Web_of_trust&lt;/a&gt; &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/X.509&quot;&gt;https://en.wikipedia.org/wiki/X.509&lt;/a&gt; &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:6&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://www.gnupg.org/faq/gnupg-faq.html#no_default_of_rsa4096&quot;&gt;https://www.gnupg.org/faq/gnupg-faq.html#no_default_of_rsa4096&lt;/a&gt; &lt;a href=&quot;#fnref:6&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:11&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://futureboy.us/pgp.html#PerfectKeypair&quot;&gt;https://futureboy.us/pgp.html#PerfectKeypair&lt;/a&gt; &lt;a href=&quot;#fnref:11&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:12&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://davidsoergel.com/posts/thoughts-on-gpg-key-management&quot;&gt;http://davidsoergel.com/posts/thoughts-on-gpg-key-management&lt;/a&gt; &lt;a href=&quot;#fnref:12&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:13&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://wiki.debian.org/Subkeys&quot;&gt;https://wiki.debian.org/Subkeys&lt;/a&gt; &lt;a href=&quot;#fnref:13&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:gpg-synchronizing&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://lists.gnupg.org/pipermail/gnupg-users/2011-May/041763.html&quot;&gt;https://lists.gnupg.org/pipermail/gnupg-users/2011-May/041763.html&lt;/a&gt; &lt;a href=&quot;#fnref:gpg-synchronizing&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sun, 24 Jan 2016 19:00:00 +0000</pubDate>
        <link>https://www.saminiir.com/establish-cryptographic-identity-using-gnupg/</link>
        <guid isPermaLink="true">https://www.saminiir.com/establish-cryptographic-identity-using-gnupg/</guid>
        
        
        <category>cryptography</category>
        
      </item>
    
  </channel>
</rss>
