<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Vítor S. Nunes - Blog</title>
    <subtitle>My personal page</subtitle>
    <link rel="self" type="application/atom+xml" href="https://vitorsnunes.com/blog/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://vitorsnunes.com/blog/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-06-28T00:00:00+00:00</updated>
    <id>https://vitorsnunes.com/blog/atom.xml</id>
    <entry xml:lang="en">
        <title>HTTP proxies: A tiny mistake in tinyproxy</title>
        <published>2026-06-28T00:00:00+00:00</published>
        <updated>2026-06-28T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Vítor S. Nunes
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://vitorsnunes.com/blog/http-proxies-2/"/>
        <id>https://vitorsnunes.com/blog/http-proxies-2/</id>
        
        <content type="html" xml:base="https://vitorsnunes.com/blog/http-proxies-2/">&lt;div class=&quot;note&quot;&gt;
  &lt;img src=&quot;&#x2F;assets&#x2F;images&#x2F;info.svg&quot; class=&quot;icon&quot;&gt; This article is the part two of two articles in the &quot;HTTP proxies&quot; series.
Check &lt;a href=&quot;https:&#x2F;&#x2F;vitorsnunes.com&#x2F;blog&#x2F;http-proxies-1&#x2F;&quot;&gt;part one&lt;&#x2F;a&gt; for complete context.
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;proxied-thoughts&quot;&gt;Proxied thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;After realizing the missing &lt;code&gt;CONNECT&lt;&#x2F;code&gt; request on both building options (with and without OpenSSL), I still have one unanswered question in my head: &lt;em&gt;Why did the connection worked for &lt;code&gt;ifconfig.io&lt;&#x2F;code&gt;?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I booted up a container with &lt;code&gt;tinyproxy&lt;&#x2F;code&gt;, &lt;code&gt;busybox wget&lt;&#x2F;code&gt; and &lt;code&gt;tcpdump&lt;&#x2F;code&gt;.
&lt;code&gt;tinyproxy&lt;&#x2F;code&gt; is listening on local port &lt;code&gt;8888&lt;&#x2F;code&gt; and I configured
the proxy environment variables like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;export &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;http_proxy&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;http:&#x2F;&#x2F;localhost:8888
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;export &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;https_proxy&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;http:&#x2F;&#x2F;localhost:8888
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Made the following request while capturing network packages:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; busybox wget&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -O-&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;ifconfig.io
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Connecting&lt;&#x2F;span&gt;&lt;span&gt; to localhost:8888 (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;::1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;:8888)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;writing&lt;&#x2F;span&gt;&lt;span&gt; to stdout
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;MY &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;IP&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;                    100% |&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;**********************&lt;&#x2F;span&gt;&lt;span&gt;|    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;  0:00:00 ETA
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;written&lt;&#x2F;span&gt;&lt;span&gt; to stdout
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;.&#x2F;capture_ifconfig.png&quot;&gt;&lt;img src=&quot;.&#x2F;capture_ifconfig.png&quot; alt=&quot;tcpdump capture of ifconfig.io&quot; width=&quot;100%&quot;&#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We can see that the request was actually made to the port 80 of the destination server.
Although the URL has &lt;code&gt;https&lt;&#x2F;code&gt; as the protocol, both the client (busybox &lt;code&gt;wget&lt;&#x2F;code&gt;) and the proxy (&lt;code&gt;tinyproxy&lt;&#x2F;code&gt;) ignored it and established an HTTP connection to the remote server.&lt;&#x2F;p&gt;
&lt;p&gt;Next, I repeated the experiment by downloading a tarball from &lt;code&gt;busybox.net&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; busybox wget&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -O&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;tmp&#x2F;busybox-1.36.1.tar.bz2 https:&#x2F;&#x2F;busybox.net&#x2F;downloads&#x2F;busybox-1.36.1.tar.bz2
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Connecting&lt;&#x2F;span&gt;&lt;span&gt; to localhost:8888 (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;::1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;:8888)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;wget:&lt;&#x2F;span&gt;&lt;span&gt; too many redirections
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;.&#x2F;capture_busybox.png&quot;&gt;&lt;img src=&quot;.&#x2F;capture_busybox.png&quot; alt=&quot;tcpdump capture of busybox.net&quot; width=&quot;100%&quot;&#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Like in the previous experiment we can see that the request was made to the port 80 of the destination server and the server replied with a &lt;code&gt;301&lt;&#x2F;code&gt;.
The rest we already know.&lt;&#x2F;p&gt;
&lt;p&gt;Both &lt;code&gt;ifconfig.io&lt;&#x2F;code&gt; and &lt;code&gt;busybox.net&lt;&#x2F;code&gt; listen on ports 80 and 443.
While busybox server simply redirects all HTTP to HTTPS requests by sending &lt;code&gt;301&lt;&#x2F;code&gt; responses, ifconfig server actually replies with the requested resource on port 80.
Mistery solved!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;What started as a weird network issue, escalated to a possible server&#x27;s misconfiguration turned out to be an client-side application bug on busybox &lt;code&gt;wget&lt;&#x2F;code&gt;.
Clients should always use &lt;code&gt;CONNECT&lt;&#x2F;code&gt; for HTTPS destinations and proxies should reject malformed requests rather than ignoring the requested protocol in favor of HTTP.
I also opened a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tinyproxy&#x2F;tinyproxy&#x2F;pull&#x2F;620&quot;&gt;merge request in tinyproxy&#x27;s repository&lt;&#x2F;a&gt; with a patch that rejects malformed client requests.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>HTTP proxies: A weird network behavior</title>
        <published>2026-06-10T00:00:00+00:00</published>
        <updated>2026-06-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Vítor S. Nunes
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://vitorsnunes.com/blog/http-proxies-1/"/>
        <id>https://vitorsnunes.com/blog/http-proxies-1/</id>
        
        <content type="html" xml:base="https://vitorsnunes.com/blog/http-proxies-1/">&lt;p&gt;The other day I encountered an interesting network issue when using busybox wget.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;&#x2F;h2&gt;
&lt;p&gt;My setup consists of a minimal Alpine Linux container and a proxy.
The container runs a shell script which uses wget to download a tarball from a remote server.
Internet access is not allowed directly from the container and requires the use of HTTP proxy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;busybox-wget&quot;&gt;Busybox wget&lt;&#x2F;h2&gt;
&lt;p&gt;Busybox wget is a lightweight implementation of wget and it&#x27;s targeted at embedded devices.
It&#x27;s built with minimal features compared with GNU wget.
You can find it available in OpenWRT routers and Alpine Linux containers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-issue&quot;&gt;The issue&lt;&#x2F;h2&gt;
&lt;p&gt;One of my shell scripts downloads a tarball using the following command:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;wget -qO&lt;&#x2F;span&gt;&lt;span&gt; file.tgz https:&#x2F;&#x2F;fastdl.mongodb.org&#x2F;tools&#x2F;db&#x2F;mongodb-database-tools-amazon-x86_64-100.6.1.tgz
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;wget&lt;&#x2F;code&gt; is Busybox wget and the &lt;code&gt;-q&lt;&#x2F;code&gt; is the quiet mode which suppresses any output messages except errors.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s important to mention that the script had been working normally for the past months.
On this day, the script exited with a non-zero exit code and wget printed the error:
&lt;code&gt;wget: too many redirections&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;investigation&quot;&gt;Investigation&lt;&#x2F;h2&gt;
&lt;p&gt;When files or pages are moved, HTTP servers can reply with a &lt;code&gt;301 Moved Permanently&lt;&#x2F;code&gt; along with a new location where the page can be fetched.
Usually, clients by default follow-up on these responses by sending a new HTTP request to the new location provided in the servers&#x27; response.&lt;&#x2F;p&gt;
&lt;p&gt;The error message implies that wget received too many 301 HTTP responses.
I removed the quiet flag, essentially enabling the output to be shown and added the &lt;code&gt;-S&lt;&#x2F;code&gt; option to include the HTTP response from the server in the output.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;wget -SO&lt;&#x2F;span&gt;&lt;span&gt; file.tgz https:&#x2F;&#x2F;fastdl.mongodb.org&#x2F;tools&#x2F;db&#x2F;mongodb-database-tools-amazon-x86_64-100.6.1.tgz
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Connecting&lt;&#x2F;span&gt;&lt;span&gt; to localhost:8888 (127.0.0.1:8888)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;HTTP&#x2F;1.1&lt;&#x2F;span&gt;&lt;span&gt; 301 Moved Permanently
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Via:&lt;&#x2F;span&gt;&lt;span&gt; 1.1 e32df02fcdc72c0a9541c48adde0e3dc.cloudfront.net (CloudFront)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; 1.1 tinyproxy (tinyproxy)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Server:&lt;&#x2F;span&gt;&lt;span&gt; CloudFront
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Date:&lt;&#x2F;span&gt;&lt;span&gt; Wed, 10 Jun 2026 17:53:40 GMT
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Content-Type:&lt;&#x2F;span&gt;&lt;span&gt; text&#x2F;html
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Content-Length:&lt;&#x2F;span&gt;&lt;span&gt; 167
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Location:&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;fastdl.mongodb.org&#x2F;tools&#x2F;db&#x2F;mongodb-database-tools-amazon-x86_64-100.6.1.tgz
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;HTTP&#x2F;1.1&lt;&#x2F;span&gt;&lt;span&gt; 301 Moved Permanently
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Via:&lt;&#x2F;span&gt;&lt;span&gt; 1.1 e32df02fcdc72c0a9541c48adde0e3dc.cloudfront.net (CloudFront)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; 1.1 tinyproxy (tinyproxy)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Server:&lt;&#x2F;span&gt;&lt;span&gt; CloudFront
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Date:&lt;&#x2F;span&gt;&lt;span&gt; Wed, 10 Jun 2026 17:53:40 GMT
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Content-Type:&lt;&#x2F;span&gt;&lt;span&gt; text&#x2F;html
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Content-Length:&lt;&#x2F;span&gt;&lt;span&gt; 167
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Location:&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;fastdl.mongodb.org&#x2F;tools&#x2F;db&#x2F;mongodb-database-tools-amazon-x86_64-100.6.1.tgz
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;HTTP&#x2F;1.1&lt;&#x2F;span&gt;&lt;span&gt; 301 Moved Permanently
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Via:&lt;&#x2F;span&gt;&lt;span&gt; 1.1 491eafc4794fd895b854d7ee08e54d4e.cloudfront.net (CloudFront)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; 1.1 tinyproxy (tinyproxy)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Server:&lt;&#x2F;span&gt;&lt;span&gt; CloudFront
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Date:&lt;&#x2F;span&gt;&lt;span&gt; Wed, 10 Jun 2026 17:53:40 GMT
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Content-Type:&lt;&#x2F;span&gt;&lt;span&gt; text&#x2F;html
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Content-Length:&lt;&#x2F;span&gt;&lt;span&gt; 167
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Location:&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;fastdl.mongodb.org&#x2F;tools&#x2F;db&#x2F;mongodb-database-tools-amazon-x86_64-100.6.1.tgz
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;wget:&lt;&#x2F;span&gt;&lt;span&gt; too many redirections
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I trimmed the output presented above since it was too long and I got 16 &lt;code&gt;301 Moved Permanently&lt;&#x2F;code&gt; responses before wget gave up.
Weirdly, the &lt;code&gt;Location&lt;&#x2F;code&gt; URL is the same for all 16 responses.
My first assumption was a server misconfiguration.
Could a server reply with a &lt;code&gt;301 Moved Permanently&lt;&#x2F;code&gt; and point the new location to the same URL essentially looping the request back to itself?
Possible? Yes but unlikely.
No one implements HTTP servers anymore since projects like Apache httpd and nginx already provide a good and flexible implementations that covers most of the needs.&lt;&#x2F;p&gt;
&lt;p&gt;I opened a shell locally in my laptop and curled the endpoint:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;curl -O&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;tmp&#x2F;file.tgz https:&#x2F;&#x2F;fastdl.mongodb.org&#x2F;tools&#x2F;db&#x2F;mongodb-database-tools-amazon-x86_64-100.6.1.tgz
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I forgot to add the &lt;a href=&quot;https:&#x2F;&#x2F;curl.se&#x2F;docs&#x2F;manpage.html#-L&quot;&gt;&lt;code&gt;-L&lt;&#x2F;code&gt; parameter&lt;&#x2F;a&gt; to curl.
(&lt;code&gt;-L&lt;&#x2F;code&gt; instructs curl to follow any HTTP redirects) &lt;code&gt;curl&lt;&#x2F;code&gt; is one of the tools that won&#x27;t follow the &lt;code&gt;301&lt;&#x2F;code&gt; requests unless you explicit ask for it.
To my surprise, curl didn&#x27;t receive any &lt;code&gt;301&lt;&#x2F;code&gt; and downloaded the file without any issues.&lt;&#x2F;p&gt;
&lt;p&gt;At this point I knew that the debug session needs to switch to the container where this behavior started.
I SSHed into the container and installed &lt;code&gt;curl&lt;&#x2F;code&gt; and GNU &lt;code&gt;wget&lt;&#x2F;code&gt; from Alpine Linux repository to replicate the test.
Surprinsgly, both &lt;code&gt;curl&lt;&#x2F;code&gt; and GNU &lt;code&gt;wget&lt;&#x2F;code&gt; downloaded the file without issues.
Keep in mind that the container is configured to use an http and https proxy through the environment variables &lt;code&gt;http_proxy&lt;&#x2F;code&gt; and &lt;code&gt;https_proxy&lt;&#x2F;code&gt;.
All three applications (&lt;code&gt;curl&lt;&#x2F;code&gt;, GNU &lt;code&gt;wget&lt;&#x2F;code&gt; and busybox &lt;code&gt;wget&lt;&#x2F;code&gt;) support proxies by looking those variables.&lt;&#x2F;p&gt;
&lt;p&gt;I decided to try a different remote server with the tool that had this weird behavior: busybox &lt;code&gt;wget&lt;&#x2F;code&gt;.
My first attempt was to &lt;code&gt;ifconfig.io&lt;&#x2F;code&gt; which replies with the IP address from which your request is arriving:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;wget -O-&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;ifconfig.io
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What was the outcome? &lt;code&gt;wget&lt;&#x2F;code&gt; outputed my IP address correctly.
I&#x27;m almost certain that I&#x27;m chaising a remote server misconfiguration.
One last test to download busybox tarball from their official page and I&#x27;m done with this &quot;issue&quot;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;wget -O&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;tmp&#x2F;busybox-1.36.1.tar.bz2 https:&#x2F;&#x2F;busybox.net&#x2F;downloads&#x2F;busybox-1.36.1.tar.bz2
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Connecting&lt;&#x2F;span&gt;&lt;span&gt; to localhost:8888 (127.0.0.1:8888)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;HTTP&#x2F;1.1&lt;&#x2F;span&gt;&lt;span&gt; 301 Moved Permanently
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Via:&lt;&#x2F;span&gt;&lt;span&gt; 1.1 tinyproxy (tinyproxy)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Date:&lt;&#x2F;span&gt;&lt;span&gt; Wed, 10 Jun 2026 20:46:42 GMT
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Server:&lt;&#x2F;span&gt;&lt;span&gt; Apache
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Location:&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;busybox.net&#x2F;downloads&#x2F;busybox-1.36.1.tar.bz2
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;HTTP&#x2F;1.1&lt;&#x2F;span&gt;&lt;span&gt; 301 Moved Permanently
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Via:&lt;&#x2F;span&gt;&lt;span&gt; 1.1 tinyproxy (tinyproxy)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Date:&lt;&#x2F;span&gt;&lt;span&gt; Wed, 10 Jun 2026 20:46:42 GMT
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Server:&lt;&#x2F;span&gt;&lt;span&gt; Apache
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Location:&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;busybox.net&#x2F;downloads&#x2F;busybox-1.36.1.tar.bz2
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;wget:&lt;&#x2F;span&gt;&lt;span&gt; too many redirections
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ohoo! Same issue!
Either I&#x27;m unlucky and picked two different misconfigured servers or it&#x27;s a bug.
I have to check the &lt;code&gt;wget&lt;&#x2F;code&gt; source code and understand how &lt;code&gt;wget&lt;&#x2F;code&gt; is sending the requests and handling the &lt;code&gt;301&lt;&#x2F;code&gt; replies.
Before jumping to the code we need to understand how proxies work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-proxies-work&quot;&gt;How proxies work&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;(Skip this section if you know how HTTP proxies work.)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A proxy acts as a middle layer between clients and destination servers.
Proxies can be used for security filtering, content caching and network isolation.
POSIX applications look &lt;code&gt;http_proxy&lt;&#x2F;code&gt; and &lt;code&gt;https_proxy&lt;&#x2F;code&gt; environment variables in an attempt to check if a proxy should be used when establishing connections to remote servers.
GNU &lt;code&gt;wget&lt;&#x2F;code&gt;, &lt;code&gt;curl&lt;&#x2F;code&gt; and busybox &lt;code&gt;wget&lt;&#x2F;code&gt; have support for proxies by checking these variables.&lt;&#x2F;p&gt;
&lt;p&gt;Client-proxy interaction differs depending on the protocol used by the remote server.&lt;&#x2F;p&gt;
&lt;div class=&quot;inline&quot;&gt;
  &lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;GET request with proxy&lt;&#x2F;th&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr&gt;
  &lt;td&gt;
  &lt;pre&gt;
    GET http:&#x2F;&#x2F;example.com&#x2F;page HTTP&#x2F;1.1
    Host: example.com
  &lt;&#x2F;pre&gt;
  &lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
&lt;&#x2F;table&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;inline&quot;&gt;
&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;GET request without proxy&lt;&#x2F;th&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr&gt;
  &lt;td&gt;
  &lt;pre&gt;
    GET &#x2F;page HTTP&#x2F;1.1
    Host: example.com
  &lt;&#x2F;pre&gt;
  &lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
&lt;&#x2F;table&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;If the remote server is using HTTP, then a client can issue a GET request to the proxy like the one shown left.
&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;Reference&#x2F;Methods&#x2F;GET&quot;&gt;HTTP reference&lt;&#x2F;a&gt; state that GET requests should use an absolute path in requests to an server and an absolute URL in requests to proxies.
If no proxy is used, then the client issues a GET request directly to the server as shown right.&lt;&#x2F;p&gt;
&lt;p&gt;If the remote server is using HTTPS, then the proxy request (left) won&#x27;t work.
HTTPS uses TLS which requires the client to initiate a handshake with the server to establish a secure channel.
The client has to initiate the handshake directly to the server otherwise it cannot verify the server&#x27;s authenticity.
Proxies, by their nature are effectively man-in-the-middle the connection between both ends.
TLS is going to be disrupted and the connection is going to be terminated.
To address this problem the &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;Reference&#x2F;Methods&#x2F;CONNECT&quot;&gt;HTTP reference&lt;&#x2F;a&gt; has a &lt;code&gt;CONNECT&lt;&#x2F;code&gt; method.
The &lt;code&gt;CONNECT&lt;&#x2F;code&gt; can only be used by clients to request proxies the establish of a blind tunnel to remote destinations.
When accessing a HTTPS server over a proxy, the client starts by issuing a &lt;code&gt;CONNECT&lt;&#x2F;code&gt; request to the proxy:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;CONNECT example.com:443 HTTP&#x2F;1.1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And the server usually replies with:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;HTTP&#x2F;1.1 200 Connection established
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;From this point, the proxy expects to receive raw TCP data from the client.
The traffic is sent unmodified to the server.
Likewise, any traffic sent by the server is forwarded unmodified back to the client until one side closes the connection to the proxy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;scouting-wget-source-code&quot;&gt;Scouting wget source code&lt;&#x2F;h2&gt;
&lt;p&gt;While getting used to the wget source code, I was puzzled that I couldn&#x27;t find the CONNECT request.&lt;&#x2F;p&gt;
&lt;p&gt;wget supports two SSL implementations.
Either through the OpenSSL dependency or, if unavailable, their own SSL implementation.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* openssl (and maybe internal TLS) support is configured *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(server.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;protocol &lt;&#x2F;span&gt;&lt;span&gt;== P_HTTPS) {
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* openssl-based helper
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;          * Inconvenient API since we can&amp;#39;t give it an open fd
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;          *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; fd = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;spawn_https_helper_openssl&lt;&#x2F;span&gt;&lt;span&gt;(server.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;host&lt;&#x2F;span&gt;&lt;span&gt;, server.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;# if&lt;&#x2F;span&gt;&lt;span&gt; ENABLE_FEATURE_WGET_HTTPS
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(fd &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* no openssl? try internal *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;            sfp = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;open_socket&lt;&#x2F;span&gt;&lt;span&gt;(lsa);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;spawn_ssl_client&lt;&#x2F;span&gt;&lt;span&gt;(server.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;host&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fileno&lt;&#x2F;span&gt;&lt;span&gt;(sfp), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;*flags*&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;goto&lt;&#x2F;span&gt;&lt;span&gt; socket_opened;
&lt;&#x2F;span&gt;&lt;span&gt;          }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;spawn_https_helper_openssl&lt;&#x2F;code&gt; is a helper function that wraps and delegates the SSL implementation to OpenSSL.
Interestingly, the function creates a socket pair and forks the process into a child process.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;static int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;spawn_https_helper_openssl&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;host&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsigned &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span&gt;*allocated = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span&gt;*servername;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; sp[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; pid;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;IF_FEATURE_WGET_HTTPS&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;volatile int&lt;&#x2F;span&gt;&lt;span&gt; child_failed = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;socketpair&lt;&#x2F;span&gt;&lt;span&gt;(AF_UNIX, SOCK_STREAM, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, sp) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;  ...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fflush_all&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;	pid = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;xvfork&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(pid == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* Child *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span&gt;*argv[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span&gt;**argp;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;close&lt;&#x2F;span&gt;&lt;span&gt;(sp[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;xmove_fd&lt;&#x2F;span&gt;&lt;span&gt;(sp[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;xdup2&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;xmove_fd&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;xopen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;dev&#x2F;null&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, O_RDWR);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;memset&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;argv, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, sizeof(argv));
&lt;&#x2F;span&gt;&lt;span&gt;		argv[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] = (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt;*)&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;openssl&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;		argv[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;] = (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt;*)&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;s_client&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;		argv[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;] = (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt;*)&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;-quiet&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;		argv[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;] = (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt;*)&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;-connect&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;		argv[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;] = (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt;*)host;
&lt;&#x2F;span&gt;&lt;span&gt;  ...
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;BB_EXECVP&lt;&#x2F;span&gt;&lt;span&gt;(argv[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;], argv);
&lt;&#x2F;span&gt;&lt;span&gt;  ...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The child process redirects &lt;code&gt;stdin&lt;&#x2F;code&gt; and &lt;code&gt;stdout&lt;&#x2F;code&gt; to the socket pair and invokes the OpenSSL binary through &lt;a href=&quot;https:&#x2F;&#x2F;www.man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;execve.2.html&quot;&gt;&lt;code&gt;execve&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
Any data sent from the parent process to the child will end up as input for the OpenSSL process. Likewise, any data outputted by OpenSSL will be read by the parent process.
I&#x27;m still unsure why this implementation was prefered over using an OpenSSL library (libssl).
&lt;em&gt;If you know why, let me know.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;wget is built by default with &lt;code&gt;ENABLE_FEATURE_WGET_OPENSSL&lt;&#x2F;code&gt; enabled and OpenSSL is used if available on the device.
wget simply sends HTTP requests on top of a connection established by OpenSSL and receives the raw HTTP responses back.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t feel like messing with the OpenSSL code (just yet) but I shouldn&#x27;t be the first person having this use case.
A quick look into the &lt;a href=&quot;https:&#x2F;&#x2F;docs.openssl.org&#x2F;3.0&#x2F;man1&#x2F;openssl-s_client&#x2F;#options&quot;&gt;&lt;code&gt;openssl s_client&lt;&#x2F;code&gt; documentation&lt;&#x2F;a&gt; reveals the &lt;code&gt;-proxy&lt;&#x2F;code&gt; argument:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;When used with the &lt;code&gt;-connect&lt;&#x2F;code&gt; flag, the program uses the host and port specified with this flag and issues an HTTP &lt;code&gt;CONNECT&lt;&#x2F;code&gt; command to connect to the desired server.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;A quick test to the &lt;code&gt;-proxy&lt;&#x2F;code&gt; confirms that it solves the bug.
We are delegating the &lt;code&gt;CONNECT&lt;&#x2F;code&gt; request to the OpenSSL binary.&lt;&#x2F;p&gt;
&lt;p&gt;Moving on, I needed to see what happens when OpenSSL is not available or if wget was built without OpenSSL support thus &lt;code&gt;ENABLE_FEATURE_WGET_OPENSSL=0&lt;&#x2F;code&gt;.
In that case, &lt;code&gt;spawn_ssl_client&lt;&#x2F;code&gt; function is used instead and follows the same inter-process communication as the OpenSSL helper.
Instead of OpenSSL binary, a busybox &lt;code&gt;ssl_client&lt;&#x2F;code&gt; application is spawned instead.
It felt so easy having a convenient &lt;code&gt;-proxy&lt;&#x2F;code&gt; OpenSSL argument but the &lt;code&gt;ssl_client&lt;&#x2F;code&gt; doesn&#x27;t have any equivalent argument.
Cool! A proper challenge this time.&lt;&#x2F;p&gt;
&lt;p&gt;After inspecting the code, &lt;code&gt;CONNECT&lt;&#x2F;code&gt; needs to be send before establishing the TLS connection.
The main challenge was to send the &lt;code&gt;CONNECT&lt;&#x2F;code&gt;, check for the proxy&#x27;s reply which should be &lt;code&gt;200 Connection established&lt;&#x2F;code&gt; and only then start the &lt;code&gt;spawn_ssl_client&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;patch-submission&quot;&gt;Patch submission&lt;&#x2F;h2&gt;
&lt;p&gt;I submitted a patch to the &lt;a href=&quot;https:&#x2F;&#x2F;lists.busybox.net&#x2F;pipermail&#x2F;busybox&#x2F;2026-June&#x2F;092348.html&quot;&gt;Busybox mailing list&lt;&#x2F;a&gt;.
Was my first time using the Git over email workflow via &lt;code&gt;git send-email&lt;&#x2F;code&gt;.
The concept wasn&#x27;t new to me, but I never actually used it in the past.
Maybe one day I&#x27;ll understand why some folkes prefer Git email over the usual Issue&#x2F;Pull request approach.
To me, the latter is just more convenient.&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
  &lt;img src=&quot;&#x2F;assets&#x2F;images&#x2F;info.svg&quot; class=&quot;icon&quot;&gt; This article is a part one of two articles in the &quot;HTTP proxies&quot; series.
Follow up on &lt;a href=&quot;https:&#x2F;&#x2F;vitorsnunes.com&#x2F;blog&#x2F;http-proxies-2&#x2F;&quot;&gt;part two&lt;&#x2F;a&gt;.
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Welcome</title>
        <published>2026-05-12T00:00:00+00:00</published>
        <updated>2026-05-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Vítor S. Nunes
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://vitorsnunes.com/blog/welcome/"/>
        <id>https://vitorsnunes.com/blog/welcome/</id>
        
        <content type="html" xml:base="https://vitorsnunes.com/blog/welcome/">&lt;p&gt;Welcome to my blog!&lt;&#x2F;p&gt;
&lt;p&gt;This blog will be about whatever comes to my mind.
It can be about my life or any topics of my interest.&lt;&#x2F;p&gt;
&lt;p&gt;You can subscribe to the Atom feed using your favorite article reader.&lt;&#x2F;p&gt;
&lt;p&gt;The page&#x27;s design is minimal with no major frameworks and no JavaScript.
Why? Since this is a personal page, it should reflect me on both the content and the layout.
Both were designed by me from scratch, following the principle of keeping it simple.
I have nothing against JavaScript, or any other tech stack :).
I might use it in the future, if&#x2F;when I need additional functionality.
For the moment I don&#x27;t need anything more that HTML and CSS.&lt;&#x2F;p&gt;
&lt;p&gt;The font used is the &lt;a href=&quot;&#x2F;assets&#x2F;fonts&#x2F;sansation&#x2F;OFL.txt&quot;&gt;&quot;Sensation&quot; by Bernd Montag&lt;&#x2F;a&gt;.
All icons used are &lt;a href=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;twbs&#x2F;icons&#x2F;refs&#x2F;heads&#x2F;main&#x2F;LICENSE&quot;&gt;Bootstrap Icons by the Bootstrap Authors&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
