<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2025-01-26T15:13:35+00:00</updated><id>/feed.xml</id><title type="html">TechTales by Marcel</title><subtitle>A blog covering insights, technical explorations, and updates in IT, with a focus on security and software engineering. Topics range from industry news to in-depth technical descriptions  of concepts and tools I encounter.</subtitle><entry><title type="html">Install Podman Desktop on Ubuntu 22.04 LTS</title><link href="/container/2025/01/26/Ubuntu-Podman-setup.html" rel="alternate" type="text/html" title="Install Podman Desktop on Ubuntu 22.04 LTS" /><published>2025-01-26T10:21:10+00:00</published><updated>2025-01-26T10:21:10+00:00</updated><id>/container/2025/01/26/Ubuntu-Podman-setup</id><content type="html" xml:base="/container/2025/01/26/Ubuntu-Podman-setup.html"><![CDATA[<p><img src="https://github.com/ItsAMeMarcel/blog-resources/blob/main/images/2025-01-26-Ubuntu-Podman-setup/title.png?raw=true" width="600" height="600" alt="" /></p>

<p>Podman is a daemonless container engine for developing, managing, and running OCI Containers on your Linux system. In this guide, we will walk you through the steps to install Podman Desktop on Ubuntu 22.04 LTS.</p>

<h1 id="install-podman">Install Podman</h1>

<p>First, update your package list and install Podman:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt-get update
<span class="nb">sudo </span>apt-get <span class="nt">-y</span> <span class="nb">install </span>podman
</code></pre></div></div>
<h1 id="install-podman-compose">Install Podman Compose</h1>

<p>To install <code class="language-plaintext highlighter-rouge">podman-compose</code>, follow these steps:</p>

<h2 id="1-install-python3-pip">1. Install <code class="language-plaintext highlighter-rouge">python3-pip</code>:</h2>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt-get <span class="nt">-y</span> <span class="nb">install </span>python3-pip
</code></pre></div></div>
<h2 id="2-install-podman-compose-using-pip3">2. Install <code class="language-plaintext highlighter-rouge">podman-compose</code> using <code class="language-plaintext highlighter-rouge">pip3</code>:</h2>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>pip3 <span class="nb">install </span>podman-compose
</code></pre></div></div>
<h1 id="install-podman-desktop">Install Podman Desktop</h1>

<p>To install Podman Desktop, we will use Flatpak. First, install Flatpak:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install </span>flatpak
</code></pre></div></div>
<p>Then, install Podman Desktop from Flathub:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>flatpak <span class="nb">install</span> <span class="nt">--user</span> flathub io.podman_desktop.PodmanDesktop
</code></pre></div></div>
<p>Finatlly you can run Podman Desktop with:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>flatpak run io.podman_desktop.PodmanDesktop
</code></pre></div></div>
<h1 id="fix-cni-plugin-problem">Fix CNI Plugin Problem</h1>

<p>It can be that you are facing the following problem with Podman Compose:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>WARN[0000] Error validating CNI config file /home/mike/.config/cni/net.d/cni-podman1.conflist: [plugin bridge does not support config version "1.0.0" plugin portmap does not support config version "1.0.0" plugin firewall does not support config version "1.0.0" plugin tuning does not support config version "1.0.0"]
</code></pre></div></div>
<p>It can be fixed with the following installation:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>snap <span class="nb">install </span>curl

curl <span class="nt">-O</span> https://archive.ubuntu.com/ubuntu/pool/universe/g/golang-github-containernetworking-plugins/containernetworking-plugins_1.1.1+ds1-3build1_amd64.deb

<span class="nb">sudo </span>dpkg <span class="nt">-i</span> containernetworking-plugins_1.1.1+ds1-3build1_amd64.deb
</code></pre></div></div>
<p>More infomation about the background you can found in <a href="https://www.michaelmcculley.com/updating-cni-plugins-for-podman-a-step-by-step-guide/">this blog post</a> and in this <a href="https://bugs.launchpad.net/ubuntu/+source/libpod/+bug/2024394">bug report</a></p>

<h1 id="optional-create-desktop-entry-for-podman-desktop">Optional: Create Desktop Entry for Podman Desktop</h1>

<p>To create a desktop entry for Podman Desktop, create a symbolic link to the application:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">ln</span> <span class="nt">-s</span> ~/.local/share/flatpak/exports/share/applications/io.podman_desktop.PodmanDesktop.desktop ~/.local/share/applications/
</code></pre></div></div>
<p>As you can see, Flatpak already offers a <code class="language-plaintext highlighter-rouge">.desktop</code> file; we just need to link it to the correct folder. This step creates a symbolic link to the Podman Desktop application in your local applications directory. This allows your desktop environment to recognize and display the Podman Desktop application in your application menu, making it easier to launch.</p>

<p>Edit the desktop entry to set the correct icon path:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vim ~/.local/share/applications/io.podman_desktop.PodmanDesktop.desktop
</code></pre></div></div>
<p>Change the <code class="language-plaintext highlighter-rouge">Icon=</code> line to:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">Icon</span><span class="o">=</span>&lt;your_home_path&gt;/.local/share/flatpak/exports/share/icons/hicolor/128x128/apps/io.podman_desktop.PodmanDesktop.png
</code></pre></div></div>
<p>Finally, restart your desktop environment to apply the changes. For X11, you can do this by pressing <code class="language-plaintext highlighter-rouge">[ALT] + [F2]</code>, entering <code class="language-plaintext highlighter-rouge">r</code>, and pressing enter.</p>

<h1 id="further-resources">Further Resources</h1>
<ul>
  <li>
    <p><strong><a href="https://podman.io/docs/installation">Podman Installation Documentation</a></strong></p>
  </li>
  <li>
    <p><strong><a href="https://github.com/containers/podman-compose">Podman Compose Repository</a></strong></p>
  </li>
  <li>
    <p><strong><a href="https://podman-desktop.io/docs/installation/linux-install">Podman Desktop Installation</a></strong></p>
  </li>
</ul>]]></content><author><name></name></author><category term="container" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Creating Memory Dumps with gcore or gdb: A Practical Example</title><link href="/c++/security/2025/01/18/Memory-dumps.html" rel="alternate" type="text/html" title="Creating Memory Dumps with gcore or gdb: A Practical Example" /><published>2025-01-18T16:22:15+00:00</published><updated>2025-01-18T16:22:15+00:00</updated><id>/c++/security/2025/01/18/Memory-dumps</id><content type="html" xml:base="/c++/security/2025/01/18/Memory-dumps.html"><![CDATA[<p><img src="https://github.com/ItsAMeMarcel/blog-resources/blob/main/images/2024-12-18-Memory-dumps/title.png?raw=true" alt="Alt-Text" /></p>

<p>Memory dumps are a crucial tool for analyzing the state of a program. With tools like <strong>gcore</strong> or <strong>gdb</strong>, developers can save the memory of a running process for debugging or to understand unexpected behavior. However, memory dumps can also expose sensitive information, such as passwords or cryptographic keys, if these are present in memory at the time of the dump. In this article, I’ll show you how to create memory dumps using gcore, analyze them, and highlight the importance of handling them securely.</p>

<h1 id="what-is-gcore">What is gcore?</h1>

<p><code class="language-plaintext highlighter-rouge">gcore</code> is a simple command-line tool that is part of the GNU Debugger (gdb). It allows you to create <strong>core dumps</strong>, which are snapshots of a process’s memory, without terminating the process itself. These dumps contain:</p>

<ul>
  <li>The state of the heap, stack, and other memory segments.</li>
  <li>Information about variables and data used by the program during runtime.</li>
</ul>

<h1 id="example-creating-a-dump-with-gcore">Example: Creating a Dump with gcore</h1>

<h2 id="step-1-create-a-test-program"><strong>Step 1: Create a Test Program</strong></h2>

<p>Let’s create a simple program that holds sensitive information, such as a password, in memory. The program will display its PID and remain active for a few minutes to allow analysis.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;thread&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;unistd.h&gt;</span><span class="c1"> </span><span class="cp">
#include</span> <span class="cpf">&lt;chrono&gt;</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">password</span> <span class="o">=</span> <span class="s">"SuperSecret123"</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Program is running... PID: "</span> <span class="o">&lt;&lt;</span> <span class="n">getpid</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>

    <span class="c1">// Keep the program running</span>
    <span class="n">std</span><span class="o">::</span><span class="n">this_thread</span><span class="o">::</span><span class="n">sleep_for</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">chrono</span><span class="o">::</span><span class="n">minutes</span><span class="p">(</span><span class="mi">5</span><span class="p">));</span>

    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Compile the program:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>g++ <span class="nt">-o</span> memory_test memory_test.cpp
</code></pre></div></div>
<p>Run it:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./memory_test
</code></pre></div></div>
<p>The program will display the PID and remain active for 5 minutes.</p>

<h2 id="step-2-create-a-dump-with-gcore"><strong>Step 2: Create a Dump with gcore</strong></h2>

<p>While the program is running, you can create a memory dump using <code class="language-plaintext highlighter-rouge">gcore</code>:</p>

<ol>
  <li>Find the process ID (PID) if you don’t already have it from the program’s output:</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ps aux | <span class="nb">grep </span>memory_test
</code></pre></div></div>
<ol>
  <li>Create a dump with <code class="language-plaintext highlighter-rouge">gcore</code>:</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gcore <span class="nt">-o</span> dumpfile &lt;PID&gt;
</code></pre></div></div>
<p>This generates a file named dumpfile.<PID>, which contains the entire memory content of the process.</PID></p>

<h2 id="step-3-analyze-the-dump"><strong>Step 3: Analyze the Dump</strong></h2>

<p>Use tools like strings to inspect the contents of the dump:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>strings dumpfile.&lt;PID&gt; | <span class="nb">grep</span> <span class="s2">"SuperSecret123"</span>
</code></pre></div></div>
<p>If the password was not securely erased from memory, it will appear in the dump.</p>

<h1 id="alternatively-creating-the-dump-with-gdb">Alternatively: Creating the dump with GDB</h1>

<h2 id="step-1-attach-to-a-running-process"><strong>Step 1: Attach to a Running Process</strong></h2>

<p>To analyze a specific process, you need to attach gdb to it using its process ID (PID). For example:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gdb <span class="nt">-p</span> &lt;PID&gt;
</code></pre></div></div>
<p>Replace <PID> with the actual process ID of the target process. Once attached, gdb will pause the process, allowing you to debug or inspect it.</PID></p>

<h2 id="step-2-focus-on-specific-memory-regions"><strong>Step 2: Focus on Specific Memory Regions</strong></h2>

<p>Use the info proc mappings command to identify memory regions, such as the heap, stack, or code segments. For example:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(gdb) info proc mappings
</code></pre></div></div>
<p>This command displays memory regions with their start and end addresses, permissions, and associated paths. You can use this information to select the regions you want to analyze or dump.</p>

<h2 id="step-4-combine-interactive-debugging-with-memory-dumping"><strong>Step 4: Combine Interactive Debugging with Memory Dumping</strong></h2>

<p>After inspecting the memory, you can dump specific memory regions to a file. For example, to dump the heap region:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(gdb) dump memory heap_dump.bin 0xheap_start 0xheap_end
</code></pre></div></div>
<p>Replace 0xheap_start and 0xheap_end with the actual addresses of the heap region obtained from info proc mappings</p>

<h1 id="why-does-this-matter">Why Does This Matter?</h1>

<p>This example demonstrates how easily sensitive data like passwords or tokens can be extracted from memory if they are not securely cleared. In security-critical applications, developers should:</p>

<ul>
  <li>Securely erase data immediately after use (see this <a href="https://itsamemarcel.micro.blog/2024/12/06/securely-erasing-memory.html">article</a>)</li>
  <li>Disable dumps when they’re not needed.</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">ulimit</span> <span class="nt">-c</span> 0
</code></pre></div></div>
<h1 id="conclusion">Conclusion</h1>

<p><code class="language-plaintext highlighter-rouge">gcore</code> and <code class="language-plaintext highlighter-rouge">gdb</code> are powerful tools for analyzing the state of a program, but it also highlights potential security risks if sensitive data remains in memory. By securely clearing data and disabling unnecessary dumps, developers can better protect their applications from data leaks.</p>

<h1 id="further-resources">Further Resources</h1>

<ul>
  <li><a href="https://man7.org/linux/man-pages/man1/gcore.1.html">gcore Documentation</a></li>
  <li><a href="https://linux.die.net/man/3/dbg">GNU Debugger Documentation</a></li>
  <li><a href="https://man7.org/linux/man-pages/man5/core.5.html">Core Dumps on Linux (Linux Manual)</a></li>
</ul>]]></content><author><name></name></author><category term="C++" /><category term="Security" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Load Balancing with HAProxy</title><link href="/loadbalancing/haproxy/2025/01/18/HAProxy-basic-setup.html" rel="alternate" type="text/html" title="Load Balancing with HAProxy" /><published>2025-01-18T16:22:15+00:00</published><updated>2025-01-18T16:22:15+00:00</updated><id>/loadbalancing/haproxy/2025/01/18/HAProxy-basic-setup</id><content type="html" xml:base="/loadbalancing/haproxy/2025/01/18/HAProxy-basic-setup.html"><![CDATA[<p>This article is a follow-up to my previous article about <strong>load balancing</strong> with <strong>NGINX</strong>. The example code is also based on the micro-learning project mentioned earlier.</p>

<h1 id="haproxy-vs-nginx">HAProxy vs. NGINX</h1>

<p>In one of my previous posts, I talked about a simple <strong>load balancing</strong> setup with <strong>NGINX</strong>. This article will shed more light on the usage of the <strong>NGINX</strong> alternative, <strong>HAProxy</strong>.</p>

<p>While <strong>NGINX</strong> was mainly developed as a high performance web server, <strong>HAProxy</strong>  focused primarily on <strong>load balancing</strong> and <strong>traffic management</strong>.</p>

<p>The following table shows the key aspects of <strong>HAProxy</strong> compared to <strong>NGINX</strong>.</p>

<table>
  <thead>
    <tr>
      <th><strong>Aspect</strong></th>
      <th><strong>HAProxy</strong></th>
      <th><strong>NGINX</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Purpose</strong></td>
      <td>Designed for <strong>load balancing</strong> and high-performance traffic management.</td>
      <td>Initially a <strong>web server</strong>, later extended with reverse proxy and load balancing features.</td>
    </tr>
    <tr>
      <td><strong>Performance</strong></td>
      <td>Optimized for pure load balancing; handles millions of concurrent connections efficiently.</td>
      <td>High-performance, but slightly less efficient for large-scale traffic due to additional features (e.g., caching).</td>
    </tr>
    <tr>
      <td><strong>Protocol Support</strong></td>
      <td>Native support for <strong>HTTP</strong>, <strong>HTTPS</strong>, and <strong>TCP</strong>; limited support for <strong>UDP</strong>. Best for Layer 4 and Layer 7 balancing.</td>
      <td>Supports <strong>HTTP</strong>, <strong>HTTPS</strong>, <strong>TCP</strong>, <strong>UDP</strong>, WebSockets, and more, offering broader versatility.</td>
    </tr>
    <tr>
      <td><strong>SSL/TLS</strong></td>
      <td>Supports SSL/TLS termination but requires more manual configuration; limited automation for certificates.</td>
      <td>Fully integrated SSL/TLS support with features like SSL offloading and automated certificate management (e.g., Let’s Encrypt).</td>
    </tr>
    <tr>
      <td><strong>Configuration</strong></td>
      <td>Simplified configuration for load balancing; focuses on traffic management, health checks, and connection handling.</td>
      <td>Highly flexible for complex routing, URL rewriting, caching, and serving static/dynamic content alongside load balancing.</td>
    </tr>
    <tr>
      <td><strong>Primary Use Cases</strong></td>
      <td>Ideal for <strong>high-performance load balancing</strong> and advanced traffic management.</td>
      <td>Best for setups needing a combination of <strong>web server</strong>, reverse proxy, and load balancer.</td>
    </tr>
    <tr>
      <td><strong>Are They Competitors?</strong></td>
      <td>Not entirely; HAProxy is better for pure load balancing, while NGINX excels as a web server with additional reverse proxy and load balancing capabilities.</td>
      <td>Not entirely; NGINX is better suited for web server tasks with added proxy and caching functionality.</td>
    </tr>
  </tbody>
</table>

<h1 id="haproxy-example">HAProxy Example</h1>

<h2 id="setup">Setup</h2>

<p>The following example is based on the <strong>NGINX</strong> example. To set up the containers, we use <em>Podman</em>. Alternatively <em>Docker</em> can also be used.</p>

<p>The project structure looks as follows:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.
├── app
│   ├── Dockerfile
│   └── index.php
├── compose.yaml
└── haproxy
    └── haproxy.cnf
</code></pre></div></div>

<p>As architecture, we use an <strong>HAProxy</strong> server that employs the <strong>Round Robin</strong> pattern to connect the frontend to three PHP servers that are providing a simple website. The website includes the hostname of the server we are connected to. With that, we can easily verify that our setup works.</p>

<p>The diagram below shows the basic architecture:</p>

<p><img src="https://github.com/ItsAMeMarcel/blog-resources/blob/main/images/2025-01-18-HAProxy-basic-setup/architecture.png?raw=true" alt="HAProxy architecture" /></p>

<h2 id="configuration">Configuration</h2>

<p>A simple <strong>Round Robin</strong> configuration looks like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>global
    log /dev/log local0
    log /dev/log local1 notice
    maxconn 200

defaults
    log     global
    option  httplog
    timeout connect 5000ms
    timeout client  50000ms
    timeout server  50000ms

frontend http_front
    bind *:8080
    mode http

    default_backend backend_servers

backend backend_servers
    mode http

    balance roundrobin
    server app1 app1:80 check
    server app2 app2:80 check
    server app3 app3:80 check

    http-request set-header X-Backend-Hostname %[src]
</code></pre></div></div>

<p>Below you can find a short explanation of each part of the configuration.</p>

<p><strong>Global Section</strong></p>
<ul>
  <li><strong>log /dev/log local0 &amp; local1 notice</strong>: Logs to system log with specified facilities and priority.</li>
  <li><strong>maxconn 200</strong>: Limits concurrent connections to 200.</li>
</ul>

<p><strong>Defaults Section</strong></p>
<ul>
  <li><strong>log global</strong>: Uses global logging settings.</li>
  <li><strong>option httplog</strong>: Enables detailed HTTP request logging.</li>
  <li><strong>timeout connect 5000ms</strong>: 5-second timeout for connections.</li>
  <li><strong>timeout client/server 50000ms</strong>: 50-second timeout for client/server interactions.</li>
</ul>

<p><strong>frontend (<code class="language-plaintext highlighter-rouge">http_front</code>)</strong></p>
<ul>
  <li><strong>bind :8080</strong>: Listens on port 8080 for all IPs.</li>
  <li><strong>mode http</strong>: Operates in HTTP mode.</li>
  <li><strong>default_backend backend_servers</strong>: Routes traffic to the backend <code class="language-plaintext highlighter-rouge">backend_servers</code>.</li>
</ul>

<p><strong>Backend (<code class="language-plaintext highlighter-rouge">backend_servers</code>)</strong></p>
<ul>
  <li><strong>mode http</strong>: Operates in HTTP mode.</li>
  <li><strong>balance roundrobin</strong>: Distributes traffic evenly among servers.</li>
  <li><strong>server app1/app2/app3</strong>: Defines backend servers on port 80 with health checks.</li>
  <li><strong>http-request set-header X-Backend-Hostname %[src]</strong>: Adds client source address as a header (<code class="language-plaintext highlighter-rouge">X-Backend-Hostname</code>).</li>
</ul>

<h1 id="conclusion">Conclusion</h1>

<p>After setting up <strong>NGINX</strong> and <strong>HAProxy</strong>, I conclude that, in this context, both <strong>load balancers</strong> perform well. The differences in the setup is quite small. I plan to continue testing more complex setups, such as those involving <strong>SSL/TLS</strong>, with both <strong>load balancers</strong>.</p>]]></content><author><name></name></author><category term="loadbalancing" /><category term="HAProxy" /><summary type="html"><![CDATA[This article is a follow-up to my previous article about load balancing with NGINX. The example code is also based on the micro-learning project mentioned earlier.]]></summary></entry><entry><title type="html">Load Balancing with NGINX</title><link href="/loadbalancing/nginx/2025/01/10/NGINX-basic-setup.html" rel="alternate" type="text/html" title="Load Balancing with NGINX" /><published>2025-01-10T16:22:15+00:00</published><updated>2025-01-10T16:22:15+00:00</updated><id>/loadbalancing/nginx/2025/01/10/NGINX-basic-setup</id><content type="html" xml:base="/loadbalancing/nginx/2025/01/10/NGINX-basic-setup.html"><![CDATA[<p><img src="https://github.com/ItsAMeMarcel/blog-resources/blob/main/images/2025-01-10-NGINX-basic-setup/architecture.png?raw=true" width="531" height="401" alt="" /></p>

<p>In this guide, we will walk through the steps to set up a simple load balancing environment using NGINX and Podman. This setup will distribute traffic across multiple instances of a PHP web application in round robin mode.</p>

<h1 id="prerequisites">Prerequisites</h1>

<ul>
  <li>Podman installed</li>
  <li>Podman compose installed</li>
</ul>

<p>An instruction for Ubuntu 22.04 can be found <a href="https://itsamemarcel.github.io/container/2025/01/26/Ubuntu-Podman-setup.html">here</a>.</p>

<h1 id="setup">Setup</h1>

<p>The complete example can be found on <a href="https://github.com/ItsAMeMarcel/blog-loadbalancer-nginx">GitHub</a>.</p>

<p>First, let’s structure our project directory as follows:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.
├── app
│   ├── Dockerfile
│   └── index.php
├── compose.yaml
└── nginx
    └── nginx.conf
</code></pre></div></div>
<h2 id="the-app-simple-php-web-interface">The App: Simple php Web Interface</h2>

<p>Create a simple PHP web interface that shows the current hostname in <code class="language-plaintext highlighter-rouge">app/index.php</code>:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;!DOCTYPE html&gt;</span>
<span class="nt">&lt;html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">&gt;</span>
<span class="nt">&lt;head&gt;</span>
    <span class="nt">&lt;meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;title&gt;</span>Hostname Example<span class="nt">&lt;/title&gt;</span>
<span class="nt">&lt;/head&gt;</span>
<span class="nt">&lt;body&gt;</span>
    <span class="nt">&lt;h1&gt;</span>Welcome to the Server<span class="nt">&lt;/h1&gt;</span>
    <span class="nt">&lt;p&gt;</span>Served from: <span class="nt">&lt;strong&gt;</span><span class="cp">&lt;?php</span> <span class="k">echo</span> <span class="nb">gethostname</span><span class="p">();</span> <span class="cp">?&gt;</span><span class="nt">&lt;/strong&gt;&lt;/p&gt;</span>
<span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span>
</code></pre></div></div>
<h2 id="the-app-dockerfile">The App: Dockerfile</h2>

<p>Create a Dockerfile in <code class="language-plaintext highlighter-rouge">app/Dockerfile</code> to build the PHP application:</p>

<div class="language-docker highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">FROM</span><span class="s"> php:8.2-apache</span>
<span class="k">COPY</span><span class="s"> index.php /var/www/html/</span>
</code></pre></div></div>
<h2 id="nginx-configuration">NGINX Configuration</h2>

<p>Create an NGINX configuration file in <code class="language-plaintext highlighter-rouge">nginx/nginx.conf</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>events {}

http {
    upstream backend {
        server app1:80;
        server app2:80;
        server app3:80;
    }

    server {
        listen 80;

         location / {
            proxy_pass http://backend;

            # Backend-Hostname als Header übergeben
            proxy_set_header X-Backend-Hostname $upstream_addr;
        }
    }
}
</code></pre></div></div>
<h2 id="compose-everything">Compose everything</h2>

<p>Create a <code class="language-plaintext highlighter-rouge">compose.yaml</code> file to define the services:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">version</span><span class="pi">:</span> <span class="s2">"</span><span class="s">3.9"</span>

<span class="na">networks</span><span class="pi">:</span>
  <span class="na">default</span><span class="pi">:</span>
    <span class="na">name</span><span class="pi">:</span> <span class="s">loadbalancer1_default</span>

<span class="na">services</span><span class="pi">:</span>
  <span class="na">app1</span><span class="pi">:</span>
    <span class="na">build</span><span class="pi">:</span>
      <span class="na">context</span><span class="pi">:</span> <span class="s">./app</span>
    <span class="na">container_name</span><span class="pi">:</span> <span class="s">app1</span>
    <span class="na">hostname</span><span class="pi">:</span> <span class="s">app1</span>
    <span class="na">ports</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s2">"</span><span class="s">8081:80"</span>

  <span class="na">app2</span><span class="pi">:</span>
    <span class="na">build</span><span class="pi">:</span>
      <span class="na">context</span><span class="pi">:</span> <span class="s">./app</span>
    <span class="na">container_name</span><span class="pi">:</span> <span class="s">app2</span>
    <span class="na">hostname</span><span class="pi">:</span> <span class="s">app2</span>
    <span class="na">ports</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s2">"</span><span class="s">8082:80"</span>

  <span class="na">app3</span><span class="pi">:</span>
    <span class="na">build</span><span class="pi">:</span>
      <span class="na">context</span><span class="pi">:</span> <span class="s">./app</span>
    <span class="na">container_name</span><span class="pi">:</span> <span class="s">app3</span>
    <span class="na">hostname</span><span class="pi">:</span> <span class="s">app3</span>
    <span class="na">ports</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s2">"</span><span class="s">8083:80"</span>

  <span class="na">loadbalancer</span><span class="pi">:</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s">docker.io/nginx:alpine</span>
    <span class="na">container_name</span><span class="pi">:</span> <span class="s">loadbalancer</span>
    <span class="na">ports</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s2">"</span><span class="s">8080:80"</span>
    <span class="na">volumes</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">./nginx/nginx.conf:/etc/nginx/nginx.conf</span>
    <span class="na">depends_on</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">app1</span>
      <span class="pi">-</span> <span class="s">app2</span>
      <span class="pi">-</span> <span class="s">app3</span>
</code></pre></div></div>
<h1 id="start-and-test">Start and test</h1>

<p>To start the environment, run:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>podman-compose up
</code></pre></div></div>
<p>Then, open your browser and navigate to <code class="language-plaintext highlighter-rouge">http://localhost:8080/</code>. You should see the PHP web interface served from different backend servers, demonstrating the load balancing setup.</p>

<h1 id="conclusion-and-key-learnings">Conclusion and Key Learnings</h1>

<p>In this guide, we have set up a basic load balancing environment using NGINX and Podman. Here are the key learnings from this exercise:</p>

<ol>
  <li><strong>Containerization with Podman</strong>: We learned how to containerize a simple PHP application using Podman.</li>
  <li><strong>Load Balancing with NGINX</strong>: We configured NGINX to distribute traffic across multiple instances of our PHP application.</li>
  <li><strong>Service Composition with Podman Compose</strong>: We used Podman Compose to define and manage multiple services, making it easier to orchestrate our application and load balancer.</li>
  <li><strong>Practical Networking</strong>: We explored how to set up networking between containers to enable communication and load balancing.</li>
</ol>

<p>With these steps, you have a foundational understanding of how to set up load balancing for containerized applications using NGINX and Podman. This setup can be expanded and customized further based on your requirements.</p>]]></content><author><name></name></author><category term="loadbalancing" /><category term="nginx" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Securely Erasing Memory in C/C++: Why It’s Important and How to Do It Right</title><link href="/c++/security/2024/12/06/Secure-Memory-Erasing.html" rel="alternate" type="text/html" title="Securely Erasing Memory in C/C++: Why It’s Important and How to Do It Right" /><published>2024-12-06T19:30:45+00:00</published><updated>2024-12-06T19:30:45+00:00</updated><id>/c++/security/2024/12/06/Secure-Memory-Erasing</id><content type="html" xml:base="/c++/security/2024/12/06/Secure-Memory-Erasing.html"><![CDATA[<p><img src="https://raw.githubusercontent.com/ItsAMeMarcel/blog-resources/refs/heads/main/images/2024-12-06-Secure-Memory-Erasing/title.webp" width="600" height="600" alt="" /></p>

<p>In software development, it is often necessary to securely erase sensitive data from memory as soon as it is no longer needed. This is especially true for passwords, tokens, or other confidential information in security-critical applications. While the concept sounds straightforward, there are some important nuances to consider. In this article, I’ll explain why a simple <code class="language-plaintext highlighter-rouge">memset</code> is not sufficient to securely erase memory and provide an overview of alternatives.</p>

<hr />

<h1 id="the-problem-why-erasing-isnt-always-secure">The Problem: Why Erasing Isn’t Always Secure</h1>

<p>A developer might assume that overwriting memory with a function like <code class="language-plaintext highlighter-rouge">memset</code> is enough to erase sensitive data. 
A naive implementation might look like this:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">insecure_clean</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">ptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">memset</span><span class="p">(</span><span class="n">ptr</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>However, the issue lies in compiler optimizations. Modern compilers such as <code class="language-plaintext highlighter-rouge">gcc</code> or <code class="language-plaintext highlighter-rouge">clang</code> analyze code and may detect that the memory cleared by <code class="language-plaintext highlighter-rouge">memset</code> is no longer being used. Based on this analysis, the compiler could remove the <code class="language-plaintext highlighter-rouge">memset</code> operation entirely to optimize runtime performance.</p>

<hr />

<h1 id="attack-vectors">Attack Vectors</h1>

<p>Sensitive data that is not properly erased can be compromised in several ways:</p>

<ol>
  <li><strong>Memory Dumps:</strong> An attacker could create a core dump or analyze the memory using debugging tools like <code class="language-plaintext highlighter-rouge">gdb</code>.</li>
  <li><strong>Unsafe Memory Deallocation:</strong> If memory is freed without being cleared, other programs or threads may access the leftover data.</li>
</ol>

<p>For example, a password that remains in memory after authentication could be discovered and exploited by an attacker.</p>

<hr />

<h1 id="the-solution-how-to-securely-erase-memory">The Solution: How to Securely Erase Memory</h1>

<p>There are various approaches to securely clear memory. These methods can be general-purpose, platform-specific, or depend on the compiler version. A comprehensive and robust solution is also offered by the external library <strong>Libsodium</strong>.</p>

<hr />

<h2 id="1-using-volatile">1. Using <code class="language-plaintext highlighter-rouge">volatile</code></h2>

<p>The <code class="language-plaintext highlighter-rouge">volatile</code> keyword prevents the compiler from optimizing out memory-clearing operations. By marking the memory pointer as <code class="language-plaintext highlighter-rouge">volatile</code>, the compiler is forced to perform each write operation, even if it considers them redundant. Here’s how it can be used:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">secure_clean</span><span class="p">(</span><span class="k">volatile</span> <span class="kt">void</span><span class="o">*</span> <span class="n">ptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">volatile</span> <span class="kt">unsigned</span> <span class="kt">char</span><span class="o">*</span> <span class="n">p</span> <span class="o">=</span> <span class="p">(</span><span class="k">volatile</span> <span class="kt">unsigned</span> <span class="kt">char</span><span class="o">*</span><span class="p">)</span><span class="n">ptr</span><span class="p">;</span>
    <span class="k">while</span> <span class="p">(</span><span class="n">size</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span>
        <span class="o">*</span><span class="n">p</span><span class="o">++</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> 
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<hr />

<h2 id="2-using-specialized-platform-functions">2. Using Specialized Platform Functions</h2>

<p>Many operating systems or standard libraries provide specialized functions for securely erasing memory. These functions use internal mechanisms to ensure that neither the compiler nor the hardware skips the clearing operation.</p>

<h3 id="unix">Unix</h3>

<p>The explicit_bzero function securely erases memory and guarantees that the operation will not be removed by the compiler.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span>
<span class="n">explicit_bzero</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">b</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">);</span>
</code></pre></div></div>
<h3 id="windows">Windows</h3>
<p>The SecureZeroMemory function ensures that memory is securely cleared.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;windows.h&gt;</span><span class="cp">
</span>
<span class="n">PVOID</span> <span class="nf">SecureZeroMemory</span><span class="p">(</span><span class="n">_In_</span> <span class="n">PVOID</span>  <span class="n">ptr</span><span class="p">,</span> <span class="n">_In_</span> <span class="n">SIZE_T</span> <span class="n">cnt</span><span class="p">);</span>
</code></pre></div></div>
<h3 id="c23">C23</h3>
<p>The new memset_explicit function can also be used to securely overwrite memory.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span>
<span class="n">memset_explicit</span><span class="p">(</span> <span class="kt">void</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="kt">int</span> <span class="n">ch</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">count</span> <span class="p">);</span>
</code></pre></div></div>
<hr />

<h2 id="3-leveraging-external-libraries">3. Leveraging External Libraries</h2>

<p>Libraries like <strong>Libsodium</strong> provide robust and platform-independent methods for secure memory erasure. These libraries are designed to securely remove sensitive data from memory while leveraging platform-specific optimizations.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;sodium.h&gt;</span><span class="cp">
</span>
<span class="n">sodium_memzero</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span> <span class="k">const</span> <span class="n">pnt</span><span class="p">,</span> <span class="k">const</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">);</span>
</code></pre></div></div>
<hr />

<h2 id="4-additional-security-measures">4. Additional Security Measures</h2>

<p>In addition to securely erasing memory, consider these practices to further protect sensitive data:</p>

<ul>
  <li><strong>Erase memory immediately:</strong> Clear data as soon as it’s no longer needed, rather than keeping it in memory longer than necessary.</li>
  <li><strong>Avoid unnecessary copies:</strong> Minimize copies of sensitive data to reduce the number of locations that need to be cleared.</li>
  <li><strong>Prevent memory dumps:</strong> Disable core dumps in security-critical applications. For example on Unix:
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">ulimit</span> <span class="nt">-c</span> 0
</code></pre></div>    </div>
    <hr />
  </li>
</ul>

<h1 id="best-practices">Best Practices</h1>

<ol>
  <li>Prefer platform-specific or library-specific functions like <code class="language-plaintext highlighter-rouge">explicit_bzero</code> or <code class="language-plaintext highlighter-rouge">sodium_memzero</code>.</li>
  <li>Use <code class="language-plaintext highlighter-rouge">volatile</code> if no specialized function is available.</li>
  <li>Erase sensitive data immediately once it’s no longer needed.</li>
  <li>Implement platform-specific mechanisms to protect memory from unauthorized access.</li>
</ol>

<hr />

<h1 id="conclusion">Conclusion</h1>

<p>Securely erasing memory is an often-overlooked but critical aspect of software development. Attackers can exploit leftover data in memory if it is not properly erased. Fortunately, there are a variety of proven methods to address this issue. By combining secure memory-clearing functions with best practices, you can ensure that sensitive data is reliably removed from memory.</p>

<hr />

<h1 id="further-resources">Further Resources</h1>

<ul>
  <li><strong><a href="https://libsodium.gitbook.io/doc/">Libsodium Documentation</a></strong></li>
  <li><strong><a href="https://man7.org/linux/man-pages/man3/explicit_bzero.3.html">explicit_bzero(3) - Linux Manual Page</a></strong></li>
  <li><strong><a href="https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa366877(v=vs.85)">SecureZeroMemory (Microsoft Docs)</a></strong></li>
  <li><strong><a href="https://en.cppreference.com/w/c/string/byte/memset">memset_explicit Documentation</a></strong></li>
</ul>]]></content><author><name></name></author><category term="C++" /><category term="Security" /><summary type="html"><![CDATA[]]></summary></entry></feed>