<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Igor Bubelov</title>
        <link>https://bubelov.com/tags/computer-networking/</link>
        <description>All posts by Igor Bubelov</description><atom:link href="https://bubelov.com/tags/computer-networking/index.xml" rel="self" type="application/rss+xml" />
        <item>
            <title>Tailscale</title>
            <link>https://bubelov.com/blog/2022/tailscale/</link>
            <pubDate>Wed, 19 Oct 2022 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2022/tailscale/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve been running WireGuard for years and it&amp;rsquo;s been solid. Lately, there&amp;rsquo;s a whole cottage industry of projects trying to slap a shiny GUI on WireGuard to make it &amp;ldquo;easy&amp;rdquo; for non-tech people. Tailscale is the one everyone won&amp;rsquo;t shut up about, so I decided to check it out.&lt;/p&gt;
&lt;p&gt;Verdict: total letdown. It was more annoying to set up than plain WireGuard, and it forces you to use some third-party login. Maybe that makes sense in a corporate hellscape, but certainly not for my self-hosted stuff.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Wi-Fi 6 Router</title>
            <link>https://bubelov.com/blog/2021/wifi-6-router/</link>
            <pubDate>Sat, 17 Apr 2021 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2021/wifi-6-router/</guid>
            <description>&lt;p&gt;First, let me say that Wi-Fi 6 is not a revolutionary change in wireless communications. Yes, it&amp;rsquo;s a bit faster, and it has certain features aimed to make Wi-Fi more efficient in crowded places, but overall, I didn&amp;rsquo;t notice any difference in my home setup. I just saw a banner on my Internet provider&amp;rsquo;s website, and I decided to ask my provider about the possibility of upgrading the router. It uses GPON, so I can&amp;rsquo;t really go shopping and pick any router I like, unfortunately. It turned out, they offer free router upgrades, so I decided to use this opportunity. The router hardware is faster, which allows it to keep latency low under load, and their new firmware finally got advanced enough to allow custom MAC to IP mappings. I really missed that feature. Those improvements have nothing to do with Wi-Fi 6, by the way.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Getting Familiar With nftables</title>
            <link>https://bubelov.com/blog/2020/nftables/</link>
            <pubDate>Fri, 18 Sep 2020 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2020/nftables/</guid>
            <description>&lt;p&gt;The more I experiment with &lt;code&gt;nftables&lt;/code&gt;, the more I like it. It&amp;rsquo;s not high level enough to be a black box Voodoo magic, and it&amp;rsquo;s not low level enough to be a royal pain in the ass.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s look at the following example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/usr/sbin/nft -f
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;flush ruleset
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;### CHAINS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# INPUT - all incoming packets are checked against the rules in this chain&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# OUTPUT - all outgoing packets are checked against the rules in this chain&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# FORWARD - all packets being sent to another computer are checked against the rules in this chain&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;###&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;### CT STATES&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# NEW - the packet has started a new connection&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# ESTABLISHED - the packet is associated with a connection which has seen packets in both directions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# RELATED - the packet is starting a new connection, but is associated with an existing connection&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;###&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;table inet filter &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  chain input &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt; filter hook input priority 0&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; policy drop&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    iif lo accept comment &lt;span class=&#34;s2&#34;&gt;&amp;#34;Accept localhost traffic&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ct state established,related accept comment &lt;span class=&#34;s2&#34;&gt;&amp;#34;Accept traffic originated from here&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    tcp dport ssh accept comment &lt;span class=&#34;s2&#34;&gt;&amp;#34;Accept SSH traffic&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  chain output &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt; filter hook output priority 0&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;# Drop everything, it&amp;#39;s not a router&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  chain forward &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt; filter hook forward priority 0&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; policy drop&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Not much code to describe a firewall ruleset! It&amp;rsquo;s also easy to read and modify. All the action happens in the &lt;code&gt;input&lt;/code&gt; chain which is responsible for filtering all the incoming traffic. It starts with a &lt;code&gt;default-deny&lt;/code&gt; mode which means it doesn&amp;rsquo;t allow any incoming traffic to pass unless you add a special rule that allows certain kinds of traffic under certain conditions.&lt;/p&gt;
&lt;p&gt;First, I wanted to allow any traffic coming from the loopback interface:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;## iif = &amp;#39;if input interface is ...&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;## lo = loopback interface&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;iif lo accept comment &lt;span class=&#34;s2&#34;&gt;&amp;#34;Accept localhost traffic&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, it would be nice to tell the firewall to accept any traffic sent to this computer as a response to locally initiated requests:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;### CT STATES&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# NEW - the packet has started a new connection&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# ESTABLISHED - the packet is associated with a connection which has seen packets in both directions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# RELATED - the packet is starting a new connection, but is associated with an existing connection&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;###&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ct state established,related accept comment &lt;span class=&#34;s2&#34;&gt;&amp;#34;Accept traffic originated from here&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally, it would be nice to have an SSH port open if you&amp;rsquo;re dealing with the remote machine. Shutting yourself from your own server can be a costly mistake, and it&amp;rsquo;s not uncommon. Here is how to allow SSH traffic, assuming your SSH daemon is set to listen on a well known port 22 (which you should change, by the way):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tcp dport ssh accept comment &lt;span class=&#34;s2&#34;&gt;&amp;#34;Accept SSH traffic&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you don&amp;rsquo;t want to get spammed by unwelcome SSH login attempts, just set your SSH daemon to listen to another port. Let&amp;rsquo;s say our SSH daemon is listening on the port 40736. That would mean that we need to add the following rule:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tcp dport &lt;span class=&#34;m&#34;&gt;40736&lt;/span&gt; accept comment &lt;span class=&#34;s2&#34;&gt;&amp;#34;Accept SSH traffic&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you decide to host an HTTP server on this machine, just add http and https ports to that rule:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tcp dport &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; 40736, http, https &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt; accept comment &lt;span class=&#34;s2&#34;&gt;&amp;#34;Accept SSH and HTTP(S) traffic&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s it. Opening additional ports is trivial and the documentation is good. I&amp;rsquo;m just starting with this thing, and I&amp;rsquo;m planning to experiment with the logging and tracing tools in the following weeks.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>IP Forwarding With Nftables</title>
            <link>https://bubelov.com/blog/2020/ip-forwarding-nftables/</link>
            <pubDate>Sun, 23 Aug 2020 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2020/ip-forwarding-nftables/</guid>
            <description>&lt;p&gt;I have a Digital Ocean droplet which I use as a proxy for my self-hosted home server. I&amp;rsquo;ve been using some hacky solution based on &lt;code&gt;iptables&lt;/code&gt; but it was a pain in the ass, so I&amp;rsquo;ve decided to get rid of this piece of technical debt and the first thing that I noticed was the deprecation of &lt;code&gt;iptables&lt;/code&gt; utility itself.&lt;/p&gt;
&lt;p&gt;It certainly looks like &lt;code&gt;nftables&lt;/code&gt; is the future, so I played with it for a while, and I settled with the following config for my proxy:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/usr/sbin/nft -f
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;define &lt;span class=&#34;nv&#34;&gt;wan&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; eth0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;define &lt;span class=&#34;nv&#34;&gt;wg&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; wg0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;define &lt;span class=&#34;nv&#34;&gt;wg_net&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; 10.0.0.0/24
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# TODO Since Linux kernel 5.2, there is support for performing stateful NAT in inet family chains.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;table ip wg &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  chain prerouting &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Priority = NF_IP_PRI_NAT_DST (-100, destination NAT)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt; nat hook prerouting priority -100&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    iif &lt;span class=&#34;nv&#34;&gt;$wan&lt;/span&gt; tcp dport &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; http, https &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt; dnat 10.0.0.2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  chain postrouting &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Priority = NF_IP_PRI_NAT_SRC (100, source NAT)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt; nat hook postrouting priority 100&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Mask WireGuard packets as if they come from this server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    oif &lt;span class=&#34;nv&#34;&gt;$wan&lt;/span&gt; ip saddr &lt;span class=&#34;nv&#34;&gt;$wg_net&lt;/span&gt; masquerade
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  chain input &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt; nat hook input priority 100&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  chain output &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt; nat hook output priority -100&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It looks way cleaner than the &lt;code&gt;iptables&lt;/code&gt; equivalent, and it can certainly be refactored to look even more readable. I really like its declarative way of describing the traffic rules.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;prerouting&lt;/code&gt; chain just redirects all the TCP traffic coming to the ports 80 or 443 to my home-based Raspberry Pi 4. Both DO droplet and RPi share the same WireGuard network between them. The RPi IP address is 10.0.0.2, that&amp;rsquo;s why dnat points there in the config above. I should probably convert this magic number into a variable, thankfully &lt;code&gt;nftables&lt;/code&gt; supports that.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;postrouting&lt;/code&gt; chain is pretty interesting. It allows me to use that DO droplet as a VPN server. It masks all the outgoing traffic with this server&amp;rsquo;s IP address but that traffic can originate from any node in my WireGuard network. Such a VPN won&amp;rsquo;t give you a lot of privacy since most of the mainstream hosting providers know your name, email and even your credit card info, but it can certainly be used to circumvent certain kinds of Internet censorship in your real location.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>WireGuard</title>
            <link>https://bubelov.com/blog/2020/wireguard/</link>
            <pubDate>Sat, 30 May 2020 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2020/wireguard/</guid>
            <description>&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2020/wireguard/og_hu_9e224c19e99dc187.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2020/wireguard/og_hu_e0e15b4417f477c0.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;I have a Nextcloud server in my house, and it works great inside my local network, but it also needs to be reachable from the Internet and that&amp;rsquo;s where it gets a bit tricky. My server has a local IP, but it doesn&amp;rsquo;t have a globally reachable IP, and there are no easy ways to get one from a regular residential ISP.&lt;/p&gt;
&lt;p&gt;The most convenient way to reach a website is by its domain name. Any browser can execute a DNS query to figure out the actual IP addresses behind a particular domain name you&amp;rsquo;re trying to access, and once that address is found, your browser of choice can finally initiate a connection.&lt;/p&gt;
&lt;p&gt;So, my Nextcloud server needs the following things to be globally reachable:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A domain.&lt;/li&gt;
&lt;li&gt;A unique IP address to point that domain to.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I already had a domain and the only thing missing was a unique IP address to put inside an &lt;a href=&#34;https://en.wikipedia.org/wiki/List_of_DNS_record_types&#34;&gt;A record&lt;/a&gt;. It turned out that Digital Ocean has a data center close enough (ping &amp;lt; 30 ms) to my house, and I decided to rent a cheap virtual machine there and use its globally reachable IP address for my local Nextcloud server.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s fair to stop there and ask yourself &amp;ldquo;why didn&amp;rsquo;t this guy just host his stupid Nextcloud on that droplet directly? What&amp;rsquo;s the point of hosting stuff from home?&amp;rdquo;. Those are good questions and the answer is: privacy and cost. I don&amp;rsquo;t want to hold my private data anywhere except in my house, and I also don&amp;rsquo;t want to pay a lot of money for storage space that I already have and can use for free. Even buying a new HDD or an SSD is much, much cheaper than renting the equivalent space in the cloud.&lt;/p&gt;
&lt;p&gt;So, my domain&amp;rsquo;s A record can point all the traffic to that DO droplet, which has a unique and globally reachable IP address, so the only extra thing I needed to do was to connect my home server with that VM somehow. I had heard that setting up OpenVPN is not particularly easy, and I wanted to find an easier solution. A few web searches later, I ended up reading about a tool called &lt;code&gt;autossh&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://blog.wirelessmoves.com/2019/06/how-to-run-a-server-at-home-without-an-ipv4-address.html&#34;&gt;This excellent post&lt;/a&gt; helped me get it up and running in no time but, unfortunately, &lt;code&gt;autossh&lt;/code&gt; is kind of cryptic and sometimes it just stops working without logging any reason why. That&amp;rsquo;s why I had to get rid of &lt;code&gt;autossh&lt;/code&gt; and find a way to set up a proper VPN.&lt;/p&gt;
&lt;p&gt;It turned out that setting up a VPN can be pretty easy, thanks to &lt;a href=&#34;https://www.wireguard.com&#34;&gt;WireGuard&lt;/a&gt;. It&amp;rsquo;s also the &lt;a href=&#34;https://www.wireguard.com/performance&#34;&gt;fastest&lt;/a&gt; out there. I highly recommend using WireGuard if you need a fast and reliable connection between your home computer and some server on the Internet.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Wi-Fi vs Wired Networking on Raspberry Pi 4</title>
            <link>https://bubelov.com/blog/2020/raspberry-pi-4-wifi-vs-wired/</link>
            <pubDate>Mon, 06 Jan 2020 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2020/raspberry-pi-4-wifi-vs-wired/</guid>
            <description>&lt;p&gt;I ran a few tests to find out how to boost network transfer speed on the Raspberry Pi 4, and whether it&amp;rsquo;s worth the hassle.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2020/raspberry-pi-4-wifi-vs-wired/thumb_hu_ae31b57f54588bed.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2020/raspberry-pi-4-wifi-vs-wired/thumb_hu_bb70513815eda101.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#tldr&#34;&gt;TL;DR&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#preface&#34;&gt;Preface&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#test-structure&#34;&gt;Test Structure&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#generating-test-data&#34;&gt;Generating Test Data&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#testing-data-throughput-over-wi-fi-and-ethernet&#34;&gt;Testing Data Throughput Over Wi-Fi and Ethernet&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#results&#34;&gt;Results&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#testing-raspberry-pi-4-throughput-with-iperf&#34;&gt;Testing Raspberry Pi 4 Throughput With iPerf&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Prefer wired connections when it&amp;rsquo;s not too inconvenient. For maximum data throughput, you should also use an SSD because regular SD cards won&amp;rsquo;t let you fully utilize the potential of your wired connection.&lt;/p&gt;
&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;
&lt;p&gt;The Raspberry Pi 4 is a capable SBC that comes with two built-in network interfaces: &lt;a href=&#34;https://en.wikipedia.org/wiki/Gigabit_Ethernet&#34;&gt;Gigabit Ethernet&lt;/a&gt; and &lt;a href=&#34;https://en.wikipedia.org/wiki/IEEE_802.11ac-2013&#34;&gt;IEEE 802.11ac Wi-Fi&lt;/a&gt;. Having options is good, but it&amp;rsquo;s also a common source of confusion. Which interface should we use and why?&lt;/p&gt;
&lt;p&gt;In this article, I compare wired and Wi-Fi interfaces in terms of their maximum data throughput. If you&amp;rsquo;re new to networking, you might also benefit from reading about network latency and its role in the performance of networked software. In short, wired connections usually have an order of magnitude better latency than wireless ones, and that might be more important than the amount of megabytes you can push per second. That said, let&amp;rsquo;s do some tests!&lt;/p&gt;
&lt;p&gt;First, it&amp;rsquo;s good to keep in mind that we can&amp;rsquo;t trust the benchmarks completely. Real-world performance can depend on many factors, and it&amp;rsquo;s always a good idea to reproduce the same tests with your own hardware and in your own environment.&lt;/p&gt;
&lt;h2 id=&#34;test-structure&#34;&gt;Test Structure&lt;/h2&gt;
&lt;p&gt;Here is what my test does:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generate 1 GB of random data on my laptop&lt;/li&gt;
&lt;li&gt;Send this data to my Raspberry Pi and measure the average speed&lt;/li&gt;
&lt;li&gt;Fetch this data from my Raspberry Pi and measure the average speed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I repeated this test with four different configurations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A Raspberry Pi that uses Wi-Fi and stores data on an SD card&lt;/li&gt;
&lt;li&gt;A Raspberry Pi that uses Wi-Fi and stores data on an SSD&lt;/li&gt;
&lt;li&gt;A Raspberry Pi that uses Ethernet and stores data on an SD card&lt;/li&gt;
&lt;li&gt;A Raspberry Pi that uses Ethernet and stores data on an SSD&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That&amp;rsquo;s it. Now, it&amp;rsquo;s time to generate that random data.&lt;/p&gt;
&lt;h2 id=&#34;generating-test-data&#34;&gt;Generating Test Data&lt;/h2&gt;
&lt;p&gt;We can use &lt;code&gt;dd&lt;/code&gt; to generate a new file and &lt;code&gt;/dev/urandom&lt;/code&gt; is a great data source:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;dd if=/dev/urandom of=big.file bs=64M count=16 iflag=fullblock
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s clarify these arguments and their purpose:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;if&lt;/code&gt; - input file. In our case, we attach our input to the stream of random data available on any Linux distribution.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;of&lt;/code&gt; - output file. It&amp;rsquo;s the name of the file we want to create. Feel free to use any name you want.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bs&lt;/code&gt; - in our case, it means that we want to generate our random file piece by piece and there should be &lt;code&gt;count&lt;/code&gt; pieces in it. It also means that we can tweak both arguments; the only important thing is that &lt;code&gt;bs&lt;/code&gt; * &lt;code&gt;count&lt;/code&gt; should be close to our target size (1 GB).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;count&lt;/code&gt; - as mentioned above, it&amp;rsquo;s just a multiplier for &lt;code&gt;bs&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;testing-data-throughput-over-wi-fi-and-ethernet&#34;&gt;Testing Data Throughput Over Wi-Fi and Ethernet&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s send some data to the Raspberry Pi (&lt;code&gt;Laptop --&amp;gt; Pi&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rsync --progress big.file pi@cloud.local:~/big.file
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;big.file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  1,073,741,824 100%   32.10MB/s    0:00:31 (xfr#1, to-chk=0/1)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I used &lt;code&gt;rsync&lt;/code&gt; because it&amp;rsquo;s easy to use, and it reflects my real workloads (syncing a lot of files, doing backups and so on).&lt;/p&gt;
&lt;p&gt;Now we can download that big file from the Raspberry Pi and measure the average transfer speed (&lt;code&gt;Laptop &amp;lt;-- Pi&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rsync --progress pi@cloud.local:~/big.file big.file.back
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;big.file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  1,073,741,824 100%   42.69MB/s    0:00:23 (xfr#1, to-chk=0/1)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s it. I repeated this test for each of the tested setups, and here are the results:&lt;/p&gt;
&lt;h2 id=&#34;results&#34;&gt;Results&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;From&lt;/th&gt;
					&lt;th&gt;To&lt;/th&gt;
					&lt;th&gt;Interface&lt;/th&gt;
					&lt;th&gt;Storage&lt;/th&gt;
					&lt;th&gt;Speed (Mbit/s)&lt;/th&gt;
					&lt;th&gt;Speed (MB/s)&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Wi-Fi&lt;/td&gt;
					&lt;td&gt;SD&lt;/td&gt;
					&lt;td&gt;58.24&lt;/td&gt;
					&lt;td&gt;7.28&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Wi-Fi&lt;/td&gt;
					&lt;td&gt;SSD&lt;/td&gt;
					&lt;td&gt;55.84&lt;/td&gt;
					&lt;td&gt;6.98&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Gigabit Ethernet&lt;/td&gt;
					&lt;td&gt;SD&lt;/td&gt;
					&lt;td&gt;159.60&lt;/td&gt;
					&lt;td&gt;19.95&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Gigabit Ethernet&lt;/td&gt;
					&lt;td&gt;SSD&lt;/td&gt;
					&lt;td&gt;340.56&lt;/td&gt;
					&lt;td&gt;42.57&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Wi-Fi&lt;/td&gt;
					&lt;td&gt;SD&lt;/td&gt;
					&lt;td&gt;80.72&lt;/td&gt;
					&lt;td&gt;10.09&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Wi-Fi&lt;/td&gt;
					&lt;td&gt;SSD&lt;/td&gt;
					&lt;td&gt;82.00&lt;/td&gt;
					&lt;td&gt;10.25&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Gigabit Ethernet&lt;/td&gt;
					&lt;td&gt;SD&lt;/td&gt;
					&lt;td&gt;339.20&lt;/td&gt;
					&lt;td&gt;42.40&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Raspberry Pi 4&lt;/td&gt;
					&lt;td&gt;Dell XPS 13 (2018)&lt;/td&gt;
					&lt;td&gt;Gigabit Ethernet&lt;/td&gt;
					&lt;td&gt;SSD&lt;/td&gt;
					&lt;td&gt;341.52&lt;/td&gt;
					&lt;td&gt;42.69&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Interesting results, but let&amp;rsquo;s try an alternative approach to measuring network throughput before jumping to any conclusions.&lt;/p&gt;
&lt;h2 id=&#34;testing-raspberry-pi-4-throughput-with-iperf&#34;&gt;Testing Raspberry Pi 4 Throughput With iPerf&lt;/h2&gt;
&lt;p&gt;We can easily measure &amp;ldquo;raw&amp;rdquo; network performance by moving as much data as possible between two computers for a certain period of time. One of those computers has to play the role of a client by generating a lot of gibberish and sending it to the second machine, which can simply discard all of that traffic upon arrival.&lt;/p&gt;
&lt;p&gt;There are many ways to perform such a test, but &lt;code&gt;iperf&lt;/code&gt; is something of an industry standard, and it&amp;rsquo;s very easy to use, which makes it a good choice for our quick test.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s make Raspberry Pi 4 a server:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ssh pi@pi.local
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt install iperf
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;iperf --server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Server listening on TCP port 5001
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;TCP window size: 85.3 KByte (default)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we can use &lt;code&gt;iperf&lt;/code&gt; from another computer and instruct it to connect to the Raspberry Pi in order to measure the network throughput between them:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt install iperf
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;iperf --client pi.local
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Client connecting to cloud.local, TCP port 5001
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;TCP window size: 85.0 KByte (default)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[ ID] Interval       Transfer     Bandwidth
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[  3]  0.0-10.0 sec  1.10 GBytes   942 Mbits/sec
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here are my results for wired and Wi-Fi connections:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Interface&lt;/th&gt;
					&lt;th&gt;Speed (Mbit/s)&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Gigabit Ethernet&lt;/td&gt;
					&lt;td&gt;942&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Wi-Fi (IEEE 802.11ac)&lt;/td&gt;
					&lt;td&gt;86&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Both tests point to the same conclusion.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Although using Wi-Fi is more convenient because it gives you more flexibility, don&amp;rsquo;t expect your network transfer speed to be anywhere above 86 Mbit/s if you connect your Raspberry Pi wirelessly. 86 Mbit/s is actually not that bad if you use an SD card because many modern SD cards can&amp;rsquo;t go beyond ~80 Mbit/s when they write data, although they can read a bit faster. Not being able to take advantage of that extra read speed is the main drawback of using Wi-Fi on a Raspberry Pi 4.&lt;/p&gt;
&lt;p&gt;Things get a bit different if you prefer to store your data on an SSD. Modern solid-state drives can move gigabytes in seconds, but your Wi-Fi connection wouldn&amp;rsquo;t let you take advantage of that extra throughput. Switching to a wired connection boosts transfer speed up to about 30-40 MB/s when using &lt;code&gt;rsync&lt;/code&gt;, which is better, but still a far cry from the theoretical limit of 125 MB/s (that&amp;rsquo;s the max speed of a Gigabit Ethernet adapter that is used in Raspberry Pi 4). It might be due to encryption overhead, which puts some pressure on the CPU and makes it a bottleneck. That&amp;rsquo;s precisely why benchmarking is hard: there are many components that might affect the results.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>GL.iNet GL-AR750S-Ext</title>
            <link>https://bubelov.com/blog/2019/gl-ar-750/</link>
            <pubDate>Sun, 27 Oct 2019 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2019/gl-ar-750/</guid>
            <description>&lt;p&gt;I wanted to experiment with &lt;a href=&#34;https://openwrt.org/&#34;&gt;OpenWRT&lt;/a&gt;, so I bought a GL.iNet travel router, mostly out of laziness, since they ship with OpenWRT pre-installed. The choice exceeded my expectations, and I&amp;rsquo;ve had a lot of fun diving into the configuration.&lt;/p&gt;
&lt;p&gt;Having full SSH access to your router is a game-changer for control, though it also comes with the expected slick web interface. But the feature that amused me the most is a &lt;strong&gt;dedicated hardware switch&lt;/strong&gt; on the device itself. Flick it, and it instantly wraps my entire wireless network in a WireGuard VPN tunnel. No software toggles, no app launches, just a physical button for full-network privacy. That&amp;rsquo;s the kind of thoughtful, practical design I didn&amp;rsquo;t know I wanted until I had it.&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>