<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>stv0g&apos;s weblog | Blog</title><description>Thoughts, stories and ideas about of a code poet, bit juggler &amp; logic wizard.</description><link>https://0l.de/</link><language>en</language><item><title>A New Home for My Open Source Projects: Embracing Codeberg</title><link>https://0l.de/blog/2025/12/codeberg-migration/</link><guid isPermaLink="true">https://0l.de/blog/2025/12/codeberg-migration/</guid><pubDate>Thu, 18 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/codeberg-migration.Dq0Jcz7N_Z1GfNsm.svg&quot; srcset=&quot;/_astro/codeberg-migration.Dq0Jcz7N_Z1GfNsm.svg 509w&quot; alt=&quot;Codeberg Migration&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 509px) 509px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;509&quot; height=&quot;139&quot;&gt; &lt;button aria-label=&quot;Zoom image: Codeberg Migration&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://0l.de/blog/2011/07/github-migration&quot;&gt;More than 14 years ago&lt;/a&gt;, I migrated my 26 open source code project to GitHub.
Back then GitHub was a fresh and modern platform pushing the boundaries of collaborative software development.
Over the years, however, my perspective on GitHub has changed significantly.&lt;/p&gt;
&lt;p&gt;I have recently migrated my by now 79 repositories from &lt;a href=&quot;https://github.com&quot;&gt;GitHub&lt;/a&gt; to &lt;a href=&quot;https://codeberg.org&quot;&gt;Codeberg&lt;/a&gt;, a decision driven by several significant factors.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;concerns-regarding-generative-ai&quot;&gt;Concerns Regarding Generative AI&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The pervasive trend of generative AI is impacting many corporations, including Microsoft and by extension, GitHub.
There are widespread concerns about the disregard for existing copyrights held by creators, artists, and scientists, as well as the substantial environmental footprint of these technologies.
While generative AI may offer some legitimate applications, it is frequently being employed for less constructive purposes: degrading existing services, exacerbating data harvesting, and increasing surveillance.
I view the current trajectory of “AI” development with significant apprehension.
GitHub’s own offering, CoPilot, exemplifies these concerns.
By incorporating code from numerous developers without regard for licensing terms, it generates output that is often suboptimal and may infringe on original authorship and licensing.
This has led to the emergence of “AI Policies” within projects to manage the influx of automated, low-quality contributions.
I am unwilling to have my code used in this manner, particularly without proper attribution or respect for open source principles like the GPL.
This is fundamentally at odds with the spirit of open source collaboration.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;prioritizing-data-privacy&quot;&gt;Prioritizing Data Privacy&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;GitHub’s ownership by Microsoft places it within the sphere of potential US government influence.
This means that data held by Microsoft could be subject to disclosure orders from the US government, regardless of the legality or ethical implications.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;a-stance-against-authoritarianism&quot;&gt;A Stance Against Authoritarianism&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;My aim is to minimize my reliance on US-based products and services as a personal protest against what I perceive as authoritarian tendencies.
While I can generally accept services from various nations, the US stands out due to perceived hostility towards European values, freedoms, rights, and ways of life.
Furthermore, major tech corporations, including Amazon, Microsoft, and Google, appear to align themselves with and financially support the current political climate, which I view as problematic.
Consequently, I am hesitant to utilize services associated with such entities.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;supporting-open-source-alternatives&quot;&gt;Supporting Open Source Alternatives&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;GitHub’s proprietary, closed-source infrastructure undermines data sovereignty by locking users into systems they cannot audit, modify, or self-host.
Users have no control over how their data is processed, stored, or potentially exploited for profit-driven features, creating dependency on a single corporate entity’s decisions and practices.
Codeberg, on the other hand, is built on &lt;a href=&quot;https://forgejo.org&quot;&gt;Forgejo&lt;/a&gt;, an open source code forge that emphasizes user privacy and data sovereignty.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;the-transition-to-codeberg&quot;&gt;The Transition to Codeberg&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;As a result of these concerns, I have moved my projects to Codeberg: &lt;a href=&quot;https://codeberg.org/stv0g&quot;&gt;codeberg.org/stv0g&lt;/a&gt;.
For already two years, I am supporting &lt;a href=&quot;https://codeberg.org/Codeberg-e.V.&quot;&gt;Codeberg e.V.&lt;/a&gt; as a regular member.
By now migrating my projects Codeberg, I am aligning my open source work with a platform that shares my values regarding privacy, data sovereignty, and respect for open source principles.&lt;/p&gt;
&lt;p&gt;Codeberg’s provides a reliable and privacy-respecting source code hosting for open source projects.
While in most cases still accepted, this excludes private repositories, or projects not licensed under an open-source license, such as this blog’s source code.
For this reason I also operate a self-hosted Forgejo instance at &lt;a href=&quot;https://git.0l.de&quot;&gt;git.0l.de&lt;/a&gt; for my private and non-open source projects.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.theatlantic.com/podcasts/archive/2025/09/ai-and-the-fight-between-democracy-and-autocracy/684095/&quot;&gt;AI and the Rise of Techno-Fascism in the United States&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.kuketz-blog.de/unplugtrump-free-yourself-digitally-from-trump-and-big-tech/&quot;&gt;#UnplugTrump: Free Yourself Digitally from Trump and Big Tech&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Open Source</category><category>Infrastructure</category><category>UnplugTrump</category><category>GitHub</category><category>Codeberg</category></item><item><title>Freeing a Xiaomi Humidifier from the Cloud</title><link>https://0l.de/blog/2025/11/xiaomi-humidifier/</link><guid isPermaLink="true">https://0l.de/blog/2025/11/xiaomi-humidifier/</guid><pubDate>Fri, 28 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/ha_logo.Cos3TBAy_1v0uk9.svg&quot; srcset=&quot;/_astro/ha_logo.Cos3TBAy_1v0uk9.svg 462w&quot; alt=&quot;Home Assistant Logo&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 462px) 462px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;462&quot; height=&quot;456&quot;&gt; &lt;button aria-label=&quot;Zoom image: Home Assistant Logo&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt;
&lt;p&gt;I recently moved into a new apartment which I used as an opportunity to make our home a little smarter.
As a big open source supporter I built my smart home platform with &lt;a href=&quot;https://www.home-assistant.io/&quot;&gt;Home Assistant&lt;/a&gt; of course.&lt;/p&gt;
&lt;p&gt;Unfortunately, there are still far too few products that are directly compatible with Home Assistant.
Especially in the area of humidifiers where I only found products that rely on a proprietary app or cloud from the manufacturer.
Something that I would like to avoid at all costs.
For one thing, such dependence is a certain form of &lt;a href=&quot;https://en.wikipedia.org/wiki/Planned_obsolescence&quot;&gt;planned obsolescence&lt;/a&gt;, as the product becomes useless as soon as the app loses its compatibility with new smartphone operating system versions or the manufacturer’s cloud is no longer operated.&lt;/p&gt;
&lt;br&gt;
&lt;p&gt;Therefore, it was important for me to find a smart humidifier that integrates directly with my Home Assistant setup.
To achieve this goal, I identified two options:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add sensors / actuators to a classic humidifier to make it smart.&lt;/li&gt;
&lt;li&gt;Replace the firmware of a smart humidifier with my own source code.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I decided to use the second approach, because it required less effort, since I would have had to implement my own firmware anyway.&lt;/p&gt;


&lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/esphome-logo.DEBynjiy_Z233Hc6.svg&quot; srcset=&quot;/_astro/esphome-logo.DEBynjiy_Z233Hc6.svg 399w&quot; alt=&quot;ESPHome Logo&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 399px) 399px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;399&quot; height=&quot;73&quot;&gt; &lt;button aria-label=&quot;Zoom image: ESPHome Logo&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt;
&lt;p&gt;Next, I was faced with the task of finding a suitable humidifier whose firmware I could easily replace.
I specifically looked for devices that contained an ESP8266 or ESP32 microcontroller from &lt;a href=&quot;https://www.espressif.com/&quot;&gt;Espressif&lt;/a&gt;, because for these I could easily create a new firmware with &lt;a href=&quot;https://esphome.io/&quot;&gt;ESPHome&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;ESPHome is a system that allows you to control your ESP8266/ESP32 through simple but powerful configuration files and remotely control it through home automation systems.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/xiaomi-humidifier.CBLqLRea_1QK3k2.webp&quot; srcset=&quot;/_astro/xiaomi-humidifier.CBLqLRea_2ejyRF.webp 640w, /_astro/xiaomi-humidifier.CBLqLRea_1QK3k2.webp 727w&quot; alt=&quot;Xiaomi Mi Smart Antibacterial Humidifier&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 727px) 727px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;727&quot; height=&quot;970&quot;&gt; &lt;button aria-label=&quot;Zoom image: Xiaomi Mi Smart Antibacterial Humidifier&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Xiaomi Mi Smart Antibacterial Humidifier.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;Thanks to Sören Beye &lt;a href=&quot;https://github.com/Hypfer&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .3a12 12 0 0 0-3.8 23.38c.6.12.83-.26.83-.57L9 21.07c-3.34.72-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.08-.74.09-.73.09-.73 1.2.09 1.83 1.24 1.83 1.24 1.08 1.83 2.81 1.3 3.5 1 .1-.78.42-1.31.76-1.61-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.14-.3-.54-1.52.1-3.18 0 0 1-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.29-1.23 3.29-1.23.64 1.66.24 2.88.12 3.18a4.65 4.65 0 0 1 1.23 3.22c0 4.61-2.8 5.63-5.48 5.92.42.36.81 1.1.81 2.22l-.01 3.29c0 .31.2.69.82.57A12 12 0 0 0 12 .3Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/Hypfer&lt;/span&gt; &lt;/a&gt; , I quickly became aware of the &lt;a href=&quot;https://www.mi.com/de/product/mi-smart-antibacterial-humidifier/&quot;&gt;Xiaomi Mi Smart Antibacterial Humidifier&lt;/a&gt;, as Sören himself wrote his own firmware for this humidifier.&lt;/p&gt;
&lt;p&gt;Unfortunately, his original version of the customized firmware (&lt;a href=&quot;https://github.com/Hypfer/esp8266-deerma-humidifier&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .3a12 12 0 0 0-3.8 23.38c.6.12.83-.26.83-.57L9 21.07c-3.34.72-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.08-.74.09-.73.09-.73 1.2.09 1.83 1.24 1.83 1.24 1.08 1.83 2.81 1.3 3.5 1 .1-.78.42-1.31.76-1.61-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.14-.3-.54-1.52.1-3.18 0 0 1-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.29-1.23 3.29-1.23.64 1.66.24 2.88.12 3.18a4.65 4.65 0 0 1 1.23 3.22c0 4.61-2.8 5.63-5.48 5.92.42.36.81 1.1.81 2.22l-.01 3.29c0 .31.2.69.82.57A12 12 0 0 0 12 .3Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/Hypfer/esp8266-deerma-humidifier&lt;/span&gt; &lt;/a&gt; ) is no longer compatible with the current version of the producr, as Xiaomi has modified the internal communication protocol.&lt;/p&gt;
&lt;p&gt;Therefore, I decided to re-implement the firmware based on ESPHome as an “external component”.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You can find the code for this component here:&lt;/strong&gt; &lt;a href=&quot;https://codeberg.org/stv0g/esphome-config/src/master/components/xiaomi_deerma_humidifier&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/esphome-config/components/xiaomi_deerma_humidifier&lt;/span&gt; &lt;/a&gt; &lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;how-to-hack-your-own-humidifier&quot;&gt;How to Hack your own Humidifier&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This section is going to walk you through the process of modifying your own Xiaomi Humidifier.&lt;/p&gt;


&lt;ol role=&quot;list&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Find the correct model&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The internal Mi Model ID of the supported device is &lt;code dir=&quot;auto&quot;&gt;deerma.humidifier.jsq&lt;/code&gt;.
The Model on the packaging being &lt;code dir=&quot;auto&quot;&gt;ZNJSQ01DEM&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Disassembly&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There are 4 Philips-head screws hidden under the rubber foot ring which can be easily pealed of.
Its usually find to remove the rubber only in areas where the screws are located.
That way you can easily reattach it later.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/humidifier-inside.B6D-LQ_p_1AFO4w.webp&quot; srcset=&quot;/_astro/humidifier-inside.B6D-LQ_p_ZbLW0Y.webp 640w, /_astro/humidifier-inside.B6D-LQ_p_rD5mv.webp 750w, /_astro/humidifier-inside.B6D-LQ_p_2tkmU.webp 828w, /_astro/humidifier-inside.B6D-LQ_p_2pMoPO.webp 1080w, /_astro/humidifier-inside.B6D-LQ_p_1AFO4w.webp 1229w&quot; alt=&quot;Internals of the Humidifier&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1229px) 1229px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1229&quot; height=&quot;1277&quot;&gt; &lt;button aria-label=&quot;Zoom image: Internals of the Humidifier&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Internals of the Humidifier.&lt;/figcaption&gt; &lt;/figure&gt;&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/humidifier-bottom.CjcuyanY_tWOrG.webp&quot; srcset=&quot;/_astro/humidifier-bottom.CjcuyanY_JbAjO.webp 640w, /_astro/humidifier-bottom.CjcuyanY_Z14Ns4r.webp 750w, /_astro/humidifier-bottom.CjcuyanY_oT4EE.webp 828w, /_astro/humidifier-bottom.CjcuyanY_24kWdB.webp 1080w, /_astro/humidifier-bottom.CjcuyanY_tWOrG.webp 1081w&quot; alt=&quot;Bottom view of Humidifier. Screws are behind rubber foot ring&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1081px) 1081px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1081&quot; height=&quot;1277&quot;&gt; &lt;button aria-label=&quot;Zoom image: Bottom view of Humidifier. Screws are behind rubber foot ring&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Bottom view of Humidifier. Screws are behind rubber foot ring.&lt;/figcaption&gt; &lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In the inside, you will find a small Wifi module attached to the back of the housing.
Remove the module and solder on the wires as shown in the picture below.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Wire UART&lt;/strong&gt;&lt;/p&gt;
&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/humidifier-wifi.Csw5RgQW_Z2nYTUv.webp&quot; srcset=&quot;/_astro/humidifier-wifi.Csw5RgQW_17vfGG.webp 640w, /_astro/humidifier-wifi.Csw5RgQW_Z3JaAL.webp 750w, /_astro/humidifier-wifi.Csw5RgQW_kb6F7.webp 828w, /_astro/humidifier-wifi.Csw5RgQW_Z2nYTUv.webp 962w&quot; alt=&quot;Wifi board featuring an ESP-WROOM-02 module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 962px) 962px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;962&quot; height=&quot;1280&quot;&gt; &lt;button aria-label=&quot;Zoom image: Wifi board featuring an ESP-WROOM-02 module&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Wifi board featuring an ESP-WROOM-02 module.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;In the last picture, the colors of the wires correspond to the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Orange:&lt;/strong&gt; GND&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Grey:&lt;/strong&gt; VCC (3.3 Volt!)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Yellow:&lt;/strong&gt; GPIO0&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Brown:&lt;/strong&gt; RX&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Red:&lt;/strong&gt; TX&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In order to flash the module, you will need to tie &lt;code dir=&quot;auto&quot;&gt;GPIO0&lt;/code&gt; to GND and attach a &lt;strong&gt;3.3V&lt;/strong&gt; serial adapter to the &lt;code dir=&quot;auto&quot;&gt;RX&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;TX&lt;/code&gt; pins.
I recommend to also to disconnect the module from the humidifier and power it via your Serial to USB adapter via the &lt;code dir=&quot;auto&quot;&gt;VCC&lt;/code&gt; pin.&lt;/p&gt;
&lt;p&gt;To flash the ESP8266 chip you can either use ESPHome’s build-in web flasher or &lt;code dir=&quot;auto&quot;&gt;esptool.py&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create backup of original firmware&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;But before we flash the new firmware, I recommend to first make a backup of the original Xiaomi firmware by running:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esptool.py&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--chip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;esp8266&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--baud&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;230400&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--port&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/dev/tty.usbserial-31310&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;read_flash&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0x0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0x200000&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;xiaomi-deerma-humidfier-original-2mb.bin&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Flash new firmware&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Afterwards, we can flash the new firmware:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esptool.py&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--chip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;esp8266&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--baud&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;230400&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--port&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/dev/tty.usbserial-31310&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;write_flash&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0x0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deerma.bin&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;</content:encoded><category>ESPHome</category><category>Xiaomi</category><category>Smart Home</category><category>English</category></item><item><title>This blog has joined the Fediverse</title><link>https://0l.de/blog/2023/10/blog-fediverse/</link><guid isPermaLink="true">https://0l.de/blog/2023/10/blog-fediverse/</guid><pubDate>Wed, 18 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;aside aria-label=&quot;Outdated Information&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Outdated Information &lt;/p&gt; &lt;div&gt; &lt;p&gt;Since, this post was published, I have migrated my blog from WordPress to a static site generator (SSG).
Due to this migration the ActivityPub integration described in this post is no longer functional.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/activity_pub_logo.CSNMhmPP_Z1J81EA.svg&quot; srcset=&quot;/_astro/activity_pub_logo.CSNMhmPP_Z1J81EA.svg 433w&quot; alt=&quot;ActivityPub Logo&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 433px) 433px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;433&quot; height=&quot;69&quot;&gt; &lt;button aria-label=&quot;Zoom image: ActivityPub Logo&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;ActivityPub Logo.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;div&gt;&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;My blog noteblok.net has joined the Fediverse.
You can follow my posts via this new handle: &lt;a href=&quot;https://noteblok.net/author/stv0g&quot;&gt;stv0g@noteblok.net&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This has been made possible by the &lt;a href=&quot;https://de.wordpress.org/plugins/activitypub/&quot;&gt;Wordpress ActivityPub Plugin&lt;/a&gt;.
With the ActivityPub plugin installed, the WordPress blog functions as a federated profile, along with profiles for each author.
For example, my blog-wide profile can be found at @&lt;a href=&quot;mailto:example.com@example.com&quot;&gt;blog@&lt;/a&gt;noteblok.net.
Authors like myself, on the other hand, would have their individual profiles at @&lt;a href=&quot;mailto:jane@example.com&quot;&gt;stv0g@noteblok.net&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The integration allows following the blog from your own Fediverse platform and account like Mastodon.
I return you can also react and comment to my blog posts via simply replying with your existing Fediverse account.&lt;/p&gt;</content:encoded><category>Meta</category><category>Blog</category><category>Decentralization</category><category>English</category></item><item><title>Fritz!DNS - An authoritative DNS server for AVM FRITZ!Box routers</title><link>https://0l.de/blog/2023/01/fritz-dns/</link><guid isPermaLink="true">https://0l.de/blog/2023/01/fritz-dns/</guid><pubDate>Sun, 08 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/image.DPUevTJL_56YK.webp&quot; srcset=&quot;/_astro/image.DPUevTJL_56YK.webp 640w&quot; alt=&quot;Fritz!Box&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 640px) 640px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;640&quot; height=&quot;400&quot;&gt; &lt;button aria-label=&quot;Zoom image: Fritz!Box&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Fritz!Box.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;In my home network, I am using an AVM FRITZ!Box Cable 6690.
It handles DHCP, DNS, Wifi and &lt;a href=&quot;https://en.avm.de/news/the-latest-news-from-fritz/2022/wireguard-vpn-has-never-been-so-easy/&quot;&gt;recently also interfaces my home network via WireGuard to my servers&lt;/a&gt;.&lt;/p&gt;
&lt;br&gt;
&lt;p&gt;Just like the venerable &lt;a href=&quot;https://thekelleys.org.uk/dnsmasq/doc.html&quot;&gt;Dnsmasq&lt;/a&gt; AVM’s FRITZ!OS uses hostnames learned from its DHCP leases and makes them resolvable via its internal DNS server.&lt;/p&gt;
&lt;p&gt;Unfortunately, this feature in FRITZ!OS has some limitations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The name of the DNS Zone is hard coded to &lt;code dir=&quot;auto&quot;&gt;fritz.box&lt;/code&gt; and can not be adjusted. Hence, the resolvable names have the following schema: &lt;code dir=&quot;auto&quot;&gt;myhostname.fritz.box&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The internal DNS server only supports recursive DNS looks. It does not act as an authoritative DNS server. Hence the local zone can not be delegated.&lt;/li&gt;
&lt;li&gt;AXFR zone transfers are not supported.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;My solution to these shortcomings is &lt;em&gt;Fritz-DNS&lt;/em&gt; which:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is a small tool written in the Go programming language.&lt;/li&gt;
&lt;li&gt;Is a small authoritative DNS server which serves A / AAAA resource records for local hosts connected to an AVM Fritz Box home WiFi router.&lt;/li&gt;
&lt;li&gt;Can be used in a hidden master configuration as it supports AXFR zone transfers.&lt;/li&gt;
&lt;li&gt;Uses the custom extension (&lt;code dir=&quot;auto&quot;&gt;X_AVM-DE_GetHostListPath&lt;/code&gt;) of the TR-064 Hosts SOAP-API &lt;a href=&quot;https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/hostsSCPD.pdf&quot;&gt;as documented here&lt;/a&gt; to retrieve a list of local hosts.&lt;/li&gt;
&lt;li&gt;Supports the generation of AAAA (IPv6) resource records based on the hosts MAC addresses using 64-Bit Extended Unique Identifier (EUI-64) and a configured unique local address (ULA) prefix.&lt;/li&gt;
&lt;li&gt;Does not yet support PTR resource records (to be implemented…)&lt;/li&gt;
&lt;li&gt;Is licensed under the &lt;a href=&quot;https://www.apache.org/licenses/LICENSE-2.0&quot;&gt;Apache 2.0 license&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can find Fritz-DNS at Codeberg: &lt;a href=&quot;https://codeberg.org/stv0g/fritz-dns&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/fritz-dns&lt;/span&gt; &lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;Here is a small figure illustrating the interaction of Fritz-DNS with the Fritz!Box and other DNS servers / clients:&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/fritz-dns.DrETJs7-_Z16UdUf.svg&quot; srcset=&quot;/_astro/fritz-dns.DrETJs7-_1CF42D.svg 640w, /_astro/fritz-dns.DrETJs7-_Z16UdUf.svg 701w&quot; alt=&quot;Fritz!DNS Architecture&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 701px) 701px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;701&quot; height=&quot;209&quot;&gt; &lt;button aria-label=&quot;Zoom image: Fritz!DNS Architecture&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Fritz!DNS Architecture.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;div&gt;&lt;h2 id=&quot;cli-usage&quot;&gt;CLI Usage&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fritz-dns&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Usage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fritz-dns&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-ipv6-ula-prefix&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;Fritz&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Box&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;IPv6&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ULA&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Prefix&lt;/span&gt;&lt;span&gt; (default &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;fd00::/64&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-pass&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;FritzBox&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;password&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-port&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;Listen&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;port&lt;/span&gt;&lt;span&gt; (default &lt;/span&gt;&lt;span&gt;53&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-soa-expire&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;duration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;SOA&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;expire&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; (default &lt;/span&gt;&lt;span&gt;744h0m0s&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-soa-mbox&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;SOA&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mailbox&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-soa-minttl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;duration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;SOA&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;minimum&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TTL&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; (default &lt;/span&gt;&lt;span&gt;1h0m0s&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-soa-ns&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;Authorative&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DNS&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;the&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;zone&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-soa-refresh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;duration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;SOA&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;refresh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; (default &lt;/span&gt;&lt;span&gt;2h0m0s&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-soa-retry&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;duration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;SOA&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;retry&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; (default &lt;/span&gt;&lt;span&gt;1h0m0s&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-ttl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;duration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TTL&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;values&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;records&lt;/span&gt;&lt;span&gt; (default &lt;/span&gt;&lt;span&gt;5m0s&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-url&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;FritzBox&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;URL&lt;/span&gt;&lt;span&gt; (default &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;http://fritz.box/&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-user&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;FritzBox&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;username&lt;/span&gt;&lt;span&gt; (default &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;admin&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-zone&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;DNS&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Zone&lt;/span&gt;&lt;span&gt; (default &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;fritz.box.&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;</content:encoded><category>Go</category><category>Software</category><category>Fritz!Box</category><category>Networking</category><category>English</category><category>Project</category></item><item><title>Aachen wird Transparent!</title><link>https://0l.de/blog/2022/08/aachen-transparent/</link><guid isPermaLink="true">https://0l.de/blog/2022/08/aachen-transparent/</guid><pubDate>Tue, 02 Aug 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Ich möchte Stadtpolitik in Aachen für alle verständlich machen.
Mein aktuellstes Projekt &lt;strong&gt;&lt;a href=&quot;https://web.archive.org/web/20230909010337/https://aachen-transparent.de/&quot;&gt;aachen-transparent.de&lt;/a&gt; ermöglicht es, die öffentlichen Informationen aus dem städtischen Ratsinformationssystem modern und benutzerfreundlich aufzubereiten.
Dazu habe ich das bereits existieren Open-Source Projekt &lt;a href=&quot;https://meine-stadt-transparent.de&quot;&gt;Meine-Stadt-Transparent&lt;/a&gt;&lt;/strong&gt; erweitert und für die Bedürfnisse in Aachen angepasst.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/screenshot.BNLwBw4m_Z1WYtIV.webp&quot; srcset=&quot;/_astro/screenshot.BNLwBw4m_1T2g70.webp 640w, /_astro/screenshot.BNLwBw4m_oMR1H.webp 750w, /_astro/screenshot.BNLwBw4m_9IOGs.webp 828w, /_astro/screenshot.BNLwBw4m_1FcsB4.webp 1080w, /_astro/screenshot.BNLwBw4m_2kv17W.webp 1280w, /_astro/screenshot.BNLwBw4m_Z21cFvh.webp 1668w, /_astro/screenshot.BNLwBw4m_A3Nir.webp 2048w, /_astro/screenshot.BNLwBw4m_1keX8L.webp 2560w, /_astro/screenshot.BNLwBw4m_Z1WYtIV.webp 2568w&quot; alt=&quot;Screenshot von aachen-transparent.de&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 2568px) 2568px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;2568&quot; height=&quot;1572&quot;&gt; &lt;button aria-label=&quot;Zoom image: Screenshot von aachen-transparent.de&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Screenshot von aachen-transparent.de.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;Aachen Transparent ist ein Projekt, dass ich ehrenamtlich im Rahmen des &lt;a href=&quot;https://0l.de/blog/2022/06/open-data-lab-aachen&quot;&gt;Open Data Labs Aachen&lt;/a&gt; ins Leben gerufen habe.
Es versucht einige der Unzulänglichkeiten des Ratsinformationssystems der Stadt Aachen zu umgehen.
Dazu nutzt es dessen &lt;a href=&quot;https://offenedaten.aachen.de/dataset/oparl-schnittstelle-zum-ratsinformationsystem-der-stadt-aachen&quot;&gt;öffentliche OParl Schnittstelle&lt;/a&gt; um die dort hinterlegten Informationen über eine moderne Oberfläche zugänglich zu machen.&lt;/p&gt;

&lt;p&gt;Dies ist besonders deshalb von Interesse, da das Aachener Ratsinformationssystem leider keine Indexierung von Suchmaschinen wie Google zulässt und Bürger daher bisher nur die recht beschränkte Suchfunktion der AllRis Software nutzen konnten.
Aachen Transparent unterstützt und fördert explizit die Indizierung aller Anträge, Dokumente, Tagesordnungspunkte und Beschlüsse durch gängige Suchmaschinen und stellt auch eine eigene Volltextsuche zu Verfügung.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;funktionalität&quot;&gt;Funktionalität&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Durch Meine Stadt Transparent erfahren Bürgerinnen und Bürger, wer für sie im Stadtrat sitzt, wann der Stadtrat tagt und welche Themen besprochen werden.
Da alle Dokumente räumlich auf einer Karte verortet werden, sind leicht jene Themen erkennbar, die sich auf das unmittelbare Lebensumfeld beziehen.&lt;/p&gt;
&lt;p&gt;Großen Wert habe ich auf eine intuitive und flexible Suche gelegt: Mit einer zentralen Suche lässt sich die gesamte Seite - Sitzungsvorlagen, Tagesordnungen, und vieles mehr - im Volltext durchsuchen, genauso wie gewählte Stadtratsmitglieder oder Ausschüsse.
Um auch dauerhaft auf dem Laufenden zu bleiben, bietet „Aachen Transparent“ verschiedene Anschlusspunkte: Nutzer können sich E-Mail-Benachrichtigungen anlegen, die über neue Dokumente zu abonnierten Suchbegriffen informiere.
Termine und Terminreihen lassen sich per iCal in eigene Kalendersysteme einbetten, die aktuellen Dokumente lassen sich auch im eigenen RSS-Reader lesen.&lt;/p&gt;
&lt;p&gt;Aachen Transparent ist kein isoliertes System, sondern greift auf das existierende &lt;a href=&quot;https://ratsinfo.aachen.de/bi/allris.net.asp&quot;&gt;Ratsinformationssysteme der Stadt Aachen&lt;/a&gt; zurück, um von dort Daten automatisch zu beziehen und aufzubereiten.
Die Verwaltung von Dokumenten erfolgt weiterhin über ein klassisches Ratsinformationssystem, zu dem Aachen Transparent eine moderne Oberfläche bietet.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;im-überblick&quot;&gt;Im Überblick&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Volltextsuche durch alle Dokumente&lt;/li&gt;
&lt;li&gt;Texterkennung in gescannten Dokumenten&lt;/li&gt;
&lt;li&gt;Geo Referenzierung von Dokumenten&lt;/li&gt;
&lt;li&gt;iCal Kalender für Integration in Outlook, Google und andere Kalender&lt;/li&gt;
&lt;li&gt;RSS Feeds für Ausschüsse und Personen&lt;/li&gt;
&lt;li&gt;Abonnierbare Suchen mit E-Mail Benachrichtigungen und RSS Feeds&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;geo-referenzierte-dokumente&quot;&gt;Geo-referenzierte Dokumente&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Interessant ist auch die Verortung von Dokumenten und Anträgen.
Aachen Transparent durchsucht alle indizierten Text auf Straßennamen im Aachener Stadtgebiet und nutzt diese zur Georeferenzierung.
Wie im folgenden Bild zu sehen kann dadurch eine Karte generiert werden, welche einen Überblick über die aktuellen Themen in der Stadtpolitik gibt.
Diese Georeferenzierung ist zudem auch über die Suchfunktion nutzbar, sodass zum Beispiel eine Suche auf einen Stadtteil oder Straße eingeschränkt werden kann.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/map.DY5DxMYP_1jwKjb.webp&quot; srcset=&quot;/_astro/map.DY5DxMYP_Z2txpu5.webp 640w, /_astro/map.DY5DxMYP_1Q4mfq.webp 750w, /_astro/map.DY5DxMYP_vRVoy.webp 828w, /_astro/map.DY5DxMYP_2sHuuw.webp 1080w, /_astro/map.DY5DxMYP_Z3wOxN.webp 1280w, /_astro/map.DY5DxMYP_1jwKjb.webp 1608w&quot; alt=&quot;Karte mit verorteten Anträgen&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1608px) 1608px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1608&quot; height=&quot;1116&quot;&gt; &lt;button aria-label=&quot;Zoom image: Karte mit verorteten Anträgen&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Karte mit verorteten Anträgen.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;div&gt;&lt;h3 id=&quot;informationen-zu-rats--und-ausschussmitgliedern&quot;&gt;Informationen zu Rats- und Ausschussmitgliedern&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Des Weiteren stellt Aachen Transparent eine Übersicht aller aktuellen Rats und Ausschussmitglieder bereit, die deren Mitgliedschaft in Ausschüssen zusammengefasst.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/profile-page.DvWlUVuq_Nisws.webp&quot; srcset=&quot;/_astro/profile-page.DvWlUVuq_ZUmqBU.webp 640w, /_astro/profile-page.DvWlUVuq_ZgARjO.webp 750w, /_astro/profile-page.DvWlUVuq_155vzH.webp 828w, /_astro/profile-page.DvWlUVuq_Z1xWN6p.webp 1080w, /_astro/profile-page.DvWlUVuq_Z1uhmrt.webp 1280w, /_astro/profile-page.DvWlUVuq_Nisws.webp 1580w&quot; alt=&quot;Personen Übersichtsseite&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1580px) 1580px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1580&quot; height=&quot;1746&quot;&gt; &lt;button aria-label=&quot;Zoom image: Personen Übersichtsseite&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Personen Übersichtsseite.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;div&gt;&lt;h3 id=&quot;offene-schnittstellen&quot;&gt;Offene Schnittstellen&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Aachen Transparent unterstützt auch bereits existierende offene Schnittstellen um Daten aus dem Ratsinformationssystem auch über andere Kanäle zu verarbeiten.&lt;/p&gt;
&lt;p&gt;So unterstützen wir z.B einen iCal Export des es ermöglicht Sitzungskalender in andere Kalendersoftware (z.B Outlook oder Android Kalender) zu integrieren und diese kontinuierlich zu synchronisieren.&lt;/p&gt;
&lt;p&gt;Neue Anträge und Beschlusssachen können zudem über RSS Feeds abonniert werden.
Interessant ist dabei auch die Möglichkeit individualisierte Feeds basierend auf Suchanfragen zu erstellen.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;häufige-fragen&quot;&gt;Häufige Fragen&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;wer-steckt-hinter-aachen-transparent&quot;&gt;Wer steckt hinter Aachen Transparent?&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Aachen Transparent&lt;/strong&gt; ist Angebot das auf ehrenamtlicher Basis von mir im Umfeld des &lt;a href=&quot;https://odlabac.de&quot;&gt;Open Data Labs Aachen&lt;/a&gt; betrieben wird.
Es ist daher kein offizielles Angebot der Stadt Aachen.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;kann-ich-aachen-transparent-auch-in-meiner-stadtgemeinde-einsetzen&quot;&gt;Kann ich &lt;strong&gt;Aachen Transparent&lt;/strong&gt; auch in meiner Stadt/Gemeinde einsetzen?&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Ja! Aachen Transparent basiert auf der Open Source Software &lt;a href=&quot;https://meine-stadt-transparent.de&quot;&gt;Meine Stadt Transparent&lt;/a&gt;, die gemeinschaftlich von mehreren Open Data Labs und interessierten Privatpersonen entwickelt wird.
Daher ist es prinzipiell auch möglich eine separate Instanz der Software für ihre Gemeinde aufzusetzen.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;aktuelle-statistiken-aus-aachen&quot;&gt;Aktuelle Statistiken aus Aachen&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dateien:&lt;/strong&gt; 11.628&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sitzungen:&lt;/strong&gt; 3.439&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gremien:&lt;/strong&gt; 165&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vorlagen:&lt;/strong&gt; 18.367&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Personen:&lt;/strong&gt; 1.370&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(Stand: 2. August 2022)&lt;/p&gt;</content:encoded><category>Software</category><category>Webdesign</category><category>Aachen</category><category>Ehrenamt</category><category>Open Data</category><category>Project</category></item><item><title>A highly available WireGuard VPN setup</title><link>https://0l.de/blog/2022/07/wireguard-ha/</link><guid isPermaLink="true">https://0l.de/blog/2022/07/wireguard-ha/</guid><pubDate>Thu, 28 Jul 2022 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/Logo_of_WireGuard.DAM1CYIc_1GeaYm.svg&quot; srcset=&quot;/_astro/Logo_of_WireGuard.DAM1CYIc_uF0gv.svg 640w, /_astro/Logo_of_WireGuard.DAM1CYIc_Z1nKtdb.svg 750w, /_astro/Logo_of_WireGuard.DAM1CYIc_Z1I6jkQ.svg 828w, /_astro/Logo_of_WireGuard.DAM1CYIc_Z1LFtMf.svg 1080w, /_astro/Logo_of_WireGuard.DAM1CYIc_Z21IEVG.svg 1280w, /_astro/Logo_of_WireGuard.DAM1CYIc_BdERp.svg 1668w, /_astro/Logo_of_WireGuard.DAM1CYIc_1GeaYm.svg 1874w&quot; alt=&quot;WireGuard Logo&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1874px) 1874px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1874&quot; height=&quot;333&quot;&gt; &lt;button aria-label=&quot;Zoom image: WireGuard Logo&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://wireguard.com/&quot;&gt;WireGuard&lt;/a&gt; is a communication protocol and free and open-source software that implements encrypted virtual private networks (VPNs), and was designed with the goals of ease of use, high speed performance, and low attack surface.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;my-journey-to-wireguard&quot;&gt;My Journey to WireGuard&lt;/h2&gt;&lt;/div&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/tinclogo.DaT4EzD__Z2iddrR.webp&quot; srcset=&quot;/_astro/tinclogo.DaT4EzD__Z2iddrR.webp 244w&quot; alt=&quot;Tinc Logo&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 244px) 244px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;244&quot; height=&quot;87&quot;&gt; &lt;button aria-label=&quot;Zoom image: Tinc Logo&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Tinc Logo.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;I’ve been using it in my home lab setup since about 2020.
When, in the end of 2021, it was finally merged into the Linux mainline with release 5.9, I started to replace my former &lt;a href=&quot;https://tinc-vpn.org/&quot;&gt;Tinc-VPN&lt;/a&gt; setup with it.
Tinc-VPN is another great open source VPN solution.
Unfortunately, its development has stalled over the last years which motivated me to look for alternatives.
In contrast to WireGuard, Tinc runs as a user-space daemon and uses tun / tap devices which adds a significant processing overhead.
Like WireGuard, it is also using UDP for tunneling data, but falls back to TCP in situations where direct datagram connectivity is not feasible.
Another big advantage of Tinc is its ability to form a mesh of nodes and to route traffic within it when direct P2P connections are not possible due to firewall restrictions.
At the same time, this mesh is also used for facilitating direct connections by signaling endpoint addresses of &lt;a href=&quot;https://nl.wikipedia.org/wiki/Network_address_translation&quot;&gt;NATed&lt;/a&gt; hosts.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/tinc_mesh.BtkhiVQG_ZbYpXH.webp&quot; srcset=&quot;/_astro/tinc_mesh.BtkhiVQG_2iTEad.webp 640w, /_astro/tinc_mesh.BtkhiVQG_jsNzS.webp 750w, /_astro/tinc_mesh.BtkhiVQG_1p9SRU.webp 828w, /_astro/tinc_mesh.BtkhiVQG_ZbYpXH.webp 950w&quot; alt=&quot;Tinc&amp;#x27;s mesh capability&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 950px) 950px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;950&quot; height=&quot;557&quot;&gt; &lt;button aria-label=&quot;Zoom image: Tinc&amp;#x27;s mesh capability&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Tinc&apos;s mesh capability.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;This mesh functionality made Tinc quite robust against the failure of single nodes as usually we could route traffic via other paths.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;highly-available-wireguard-server-setup&quot;&gt;Highly Available WireGuard server setup&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;To counteract this shortcoming, this blog post will present a highly available WireGuard setup using the &lt;a href=&quot;https://en.wikipedia.org/wiki/Virtual_Router_Redundancy_Protocol&quot;&gt;Virtual Router Redundancy Protocol (VRRP)&lt;/a&gt; as implemented by the &lt;a href=&quot;https://keepalived.readthedocs.io/&quot;&gt;keepalived&lt;/a&gt; daemon.&lt;/p&gt;
&lt;p&gt;That said, it is worth noting that this setup does will not bring back some of the beloved features of Tinc.
Both meshing, the peer and and endpoint discovery features of Tinc are currently and will never be supported by WireGuard.
Jason A. Donenfeld the author of WireGuard focused the design of WireGuard on simplicity, performance and auditability.
Hence advanced features like the ones mentioned will only be available to WireGuard by additional agents / daemons which control and configure WireGuard for you.
Examples for such are &lt;a href=&quot;https://tailscale.com/&quot;&gt;Tailscale&lt;/a&gt;, &lt;a href=&quot;https://www.netmaker.io/&quot;&gt;Netmaker&lt;/a&gt; and &lt;a href=&quot;https://netbird.io/&quot;&gt;Netbird&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The setup presented in this post is a so called active / standby configuration consisting of two almost equal configured Linux servers running both WireGuard and the keepalived daemon.
As the name suggest only one of those two servers will by actively handling WireGuard tunneling traffic while the other one stands by for the event of a failure or maintenance of the active node.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/wg_vrrip.BeFA9NiG_Z28SaSs.svg&quot; srcset=&quot;/_astro/wg_vrrip.BeFA9NiG_Z21yS5z.svg 640w, /_astro/wg_vrrip.BeFA9NiG_Z28SaSs.svg 642w&quot; alt=&quot;VRRP Wireguard Setup&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 642px) 642px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;642&quot; height=&quot;521&quot;&gt; &lt;button aria-label=&quot;Zoom image: VRRP Wireguard Setup&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;VRRP Wireguard Setup.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;div&gt;&lt;h3 id=&quot;requirements&quot;&gt;Requirements&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Before get started some requirements for the setup:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2 Servers running Linux 5.9 or newer.&lt;/li&gt;
&lt;li&gt;A working Wireguard configuration.&lt;/li&gt;
&lt;li&gt;A local L2 network segment two which both servers are connected.&lt;/li&gt;
&lt;li&gt;Upstream connectivity without NATing via gateway connected to the network segment (usually provided by your internet or hosting provider).&lt;/li&gt;
&lt;li&gt;An unused address to be used as &lt;em&gt;Virtual IP&lt;/em&gt; (VIP) which roamed between the two servers by VRRP.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An important point is here the assumption that we are running both servers in the same &lt;em&gt;switched&lt;/em&gt; network segment as this is a requirement for VRRP.
We are also assuming that the upstream gateway performs no NATing.
This guide covers only IPv6 addressing.
However all steps can be also adapted or repeated for a dual stack or IPv4-only setup.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;detailed-steps&quot;&gt;Detailed steps&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Here are some of the specifics for my setup which need to be adapted by you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Server Key&lt;/strong&gt; (same use by both servers)
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Private&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;YIEDx+A2ONo5+uv3mrk/p7ileL3T5QQ8hleQK0IYEEI=&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Public:&lt;/strong&gt; &lt;code dir=&quot;auto&quot;&gt;XGubrkGtuECdvoykKeUiNMigk2onfLCPfEo9Im+vmx8=&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Peer Key&lt;/strong&gt; (In this example we only have a single peer)
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Private:&lt;/strong&gt; &lt;code dir=&quot;auto&quot;&gt;OIbpWVIVVBOtWfwkmXkFRN7Q/jBdfYtsGt7j97aHx1Q=&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Public:&lt;/strong&gt; &lt;code dir=&quot;auto&quot;&gt;3NGl6gTOGs6ai0RE91VmVFgF+N4gw1EBG11KOeiKJAg=&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Public Server Subnet:&lt;/strong&gt; 2001:DB8:1::/64
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Gateway:&lt;/strong&gt; 2001:DB8:1::1&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Virtual IP:&lt;/strong&gt; 2001:DB8:1::2&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server A:&lt;/strong&gt; 2001:DB8:1:::3&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server B:&lt;/strong&gt; 2001:DB8:1::4&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WireGuard Tunnel Subnet:&lt;/strong&gt; 2001:DB8:2::1/64
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Server:&lt;/strong&gt; 2001:DB8:2::1 (same used by both servers)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Peer:&lt;/strong&gt; 2001:DB8:2::2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interface names&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Wireguard:&lt;/strong&gt; wg1&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Upstream:&lt;/strong&gt; eno1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;ol role=&quot;list&quot;&gt;
&lt;li&gt;
&lt;p&gt;Prepare servers&lt;/p&gt;
&lt;p&gt;We start of preparing the two servers by installing WireGuard and keepalived:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keepalived&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;wireguard-tools&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;iproute2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Next we configure a WireGuard interface on both servers using exactly the &lt;strong&gt;same&lt;/strong&gt; configuration file at &lt;code dir=&quot;auto&quot;&gt;/etc/wireguard/wg1.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;Interface&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Address&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 2001:DB8:2::1/64&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;PrivateKey&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; YIEDx+A2ONo5+uv3mrk/&lt;/span&gt;&lt;span&gt;p7ileL3T5QQ8hleQK0IYEEI&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ListenPort&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 51800&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;Peer&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;PublicKey&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 3NGl6gTOGs6ai0RE91VmVFgF+&lt;/span&gt;&lt;span&gt;N4gw1EBG11KOeiKJAg&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;AllowedIPs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 2001:DB8:2::2/128&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;PersistentKeepalive&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 25&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Similarly, a reciprocal configuration file is needed on the client side which skip here for brevity.
Before proceeding, we activate the interface on &lt;strong&gt;both&lt;/strong&gt; servers:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;enable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--now&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;wg-quick@wg1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;wg&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;show&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;wg1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# Check if interface is up&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configuring Keepalived&lt;/p&gt;
&lt;p&gt;Create a configuration file for keepalived at &lt;code dir=&quot;auto&quot;&gt;/etc/keepalived/keepalived.conf&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;global_defs {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;enable_script_security&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;script_user root&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Check if the server the WireGuard interface configured&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;vrrp_script check_wg {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;script &quot;/usr/bin/wg show wg1&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;user root&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;vrrp_instance wg_v6 {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;interface eno1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;virtual_router_id 52&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;notify /usr/local/bin/keepalived-wg.sh&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;state BACKUP # use BACKUP for Server B&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;priority 99 # use 100 for Server B&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;virtual_ipaddress {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;2001:DB8:1::1/64&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;track_script {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;check_wg&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a notification script for keepalived at &lt;code dir=&quot;auto&quot;&gt;/usr/local/bin/keepalived-wg.sh&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#!/usr/bin/env bash&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;TYPE&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;$1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;NAME&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;$2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;STATE&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;$3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;PRIO&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;$4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WGIF&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;wg1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;STATE&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;MASTER&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;link&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;up&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dev&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;WGIF&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;BACKUP&lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt;FAULT&lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt;STOP&lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt;DELETED&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;link&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;down&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dev&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;WGIF&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;*)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;echo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;unknown state&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;exit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esac&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Now start the keepalived daemon:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;chmod&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/usr/local/bin/keepalived-wg.sh&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;enable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--now&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keepalived&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Testing the fail over&lt;/p&gt;
&lt;p&gt;In our configuration, Server A has a higher VRRP priority and as such will be preferred if both servers are healthy.
To test our setup, we simply bring down the WireGuard interface on Server A and observe how the VIP gets moved to Server B.
From the WireGuard peers perspective not much changes.
In fact no connections will be dropped during the fail-over.
Internally, the clients WireGuard interface renegotiate the handshake.
However, that step is actually not observable by the user.&lt;/p&gt;
&lt;p&gt;Run the following commands on Server A while alongside test the connectivity from the client side through the tunnel via &lt;code dir=&quot;auto&quot;&gt;ping -i0.2 2001:DB8:2::1&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Check that keepalived has moved the VIP to interface eno1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;addr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;show&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dev&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;eno1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Bring down the Wireguard interface&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;wg-quick&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;down&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;wg1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Keepalived should now have moved the VIP to Server B&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;addr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;show&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dev&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;eno1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;going-further&quot;&gt;Going further&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In my personal network, I operate a &lt;a href=&quot;https://en.wikipedia.org/wiki/Interior_gateway_protocol&quot;&gt;Interior Gateway Protocol (IGP)&lt;/a&gt; to dynamically route traffic within and also towards other networks.
Common IGPs are OSPF, ISIS or BGP.
In my specific case, both Servers A &amp;#x26; B run the Bird2 routing daemon with interior and exterior BGP sessions.&lt;/p&gt;
&lt;p&gt;So how does the WireGuard HA setup interoperates with my interior routing? Quite well actually.
As my notify script (&lt;code dir=&quot;auto&quot;&gt;keepalive-wg.sh&lt;/code&gt;) will automatically bring up / down the interface, the routes attached to the interface will be picked up by &lt;a href=&quot;https://bird.network.cz/?get_doc&amp;#x26;v=20&amp;#x26;f=bird-6.html#ss6.5&quot;&gt;Bird’s direct protocol&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I am also planning to extend my WireGuard agent cunīcu (&lt;a href=&quot;https://codeberg.org/cunicu/cunicu&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/cunicu/cunicu&lt;/span&gt; &lt;/a&gt; ) to support the synchronization of WireGuard interface configurations between multiple servers.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Surprisingly, the setup works by using Keepalived and does not require any iptables or nftables magic to rewrite source IP addresses.
I’ve seen some people mentioning that SNAT / DNAT would be required to convince WireGuard to use the virtual IP instead of the server addresses.
However, in my experience this was not necessary.&lt;/p&gt;
&lt;p&gt;Another concern has been that the backup Wireguard interface still might attempt to establish a handshake with its peers.
This would quite certainly interfere with the handshakes originated by the current master server.
However, also this has not been proven to be the case.
I assume the fact that our notify script brings down the WireGuard interface on the backup server causes them to cease all communication with its peers.&lt;/p&gt;</content:encoded><category>English</category><category>Software</category><category>Linux</category><category>VPN</category><category>Wireguard</category></item><item><title>SSH Access for Netgear&apos;s Nighthawk M5 Mobile LTE/Router</title><link>https://0l.de/blog/2022/07/netgear-m5-ssh-access/</link><guid isPermaLink="true">https://0l.de/blog/2022/07/netgear-m5-ssh-access/</guid><pubDate>Sun, 03 Jul 2022 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/ssh_logo.DHmiGAXb_1tb4Ux.webp&quot; srcset=&quot;/_astro/ssh_logo.DHmiGAXb_1tb4Ux.webp 512w&quot; alt=&quot;SSH Logo&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 512px) 512px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;512&quot; height=&quot;512&quot;&gt; &lt;button aria-label=&quot;Zoom image: SSH Logo&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt;
&lt;p&gt;In my previous post, I demonstrated how to &lt;a href=&quot;https://0l.de/blog/2022/06/netgear-m5-root-access&quot;&gt;gain root access by enabling a Telnet daemon via the routers AT-over-TCP interface&lt;/a&gt;.
In this post I will close this gasping security hole by replacing the Telnet with a Secure Shell (SSH) daemon.
Netgear’s firmware does not ship with a SSH daemon itself.
So we first build a statically linked &lt;a href=&quot;https://matt.ucc.asn.au/dropbear/dropbear.html&quot;&gt;Dropbear&lt;/a&gt; instead of the rather heavy OpenSSH daemon.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;building-dropbear-ssh&quot;&gt;Building Dropbear SSH&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I’ve build a statically linked version of Dropbear using a Debian-based Docker image as it allows us to use the packaged cross-compiler toolchains by Debian:&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;dockerfile&quot;&gt;Dockerfile&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; debian:bullseye&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;RUN&lt;/span&gt;&lt;span&gt; apt-get update &amp;#x26;&amp;#x26; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;apt-get -y install \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;wget tar bzip2 build-essential \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gcc-arm-linux-gnueabihf \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;binutils-arm-linux-gnueabihf&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;RUN&lt;/span&gt;&lt;span&gt; wget https://matt.ucc.asn.au/dropbear/releases/dropbear-2022.82.tar.bz2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;RUN&lt;/span&gt;&lt;span&gt; tar xvf dropbear-2022.82.tar.bz2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WORKDIR&lt;/span&gt;&lt;span&gt; /dropbear-2022.82&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ENV&lt;/span&gt;&lt;span&gt; CC=arm-linux-gnueabihf-gcc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ENV&lt;/span&gt;&lt;span&gt; CFLAGS=&lt;/span&gt;&lt;span&gt;&quot;-DDROPBEAR_SVR_PASSWORD_AUTH=0&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;RUN&lt;/span&gt;&lt;span&gt; ./configure --host=arm-linux-gnueabhf \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--disable-zlib \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--disable-shadow \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--disable-syslog \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--disable-lastlog \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;--enable-static&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;RUN&lt;/span&gt;&lt;span&gt; make PROGRAMS=&lt;/span&gt;&lt;span&gt;&quot;dropbear scp&quot;&lt;/span&gt;&lt;span&gt; MULTI=1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;RUN&lt;/span&gt;&lt;span&gt; arm-linux-gnueabihf-strip dropbearmulti&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;With this Dockerfile we can build the image, create a temporary container and copy the resulting binary from the image to your local folder:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dropbear&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;=$(&lt;/span&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dropbear&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;:/dropbear-2022.82/dropbearmulti&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;./&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;installing-dropbear&quot;&gt;Installing Dropbear&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Now that we have a statically linked version of the SSH daemon, we will need to copy it to our target.
I accomplished this by using netcat (&lt;code dir=&quot;auto&quot;&gt;nc&lt;/code&gt;):&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;on-the-target&quot;&gt;On the target&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/data/mod/bin&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;pushd /data/mod/bin&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;nc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-l&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1234&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dropbearmulti&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;chmod&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dropbearmulti&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ln&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-s&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dropbearmulti&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dropbear&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ln&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-s&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dropbearmulti&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;scp&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;on-the-machine-which-builds-dropbear&quot;&gt;On the machine which builds Dropbear&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;nc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;ip-of-target&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1234&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dropbearmulti&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This is followed by installing a SystemD service which start the SSH daemon on system boot:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/systemd/system/dropbear.service&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Unit]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Description=Dropbear SSH server&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;After=network.target&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Service]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Type=forking&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ExecStart=/data/mod/bin/dropbear -R&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;PIDFile=/var/run/dropbear.pid&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Install]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WantedBy=multi-user.target&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;daemon-reload&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;enable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--now&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dropbear.service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Before you will be able to connect to the target, you will need to install an authorized_keys file.
Password login is not supported.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/home/root/.ssh&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/home/root/.ssh/authorized_keys&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ssh-rsa AAAAB3NzaC1...GaoxPrQ== # replace by your SSH key&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;All that remains is a quick test:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ssh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;root@&amp;#x3C;ip-of-target&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;disable-ssh-daemon&quot;&gt;Disable SSH daemon&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In order to restore the security of the device we must also disable the Telnet daemon.
There are in principle two options to achieve this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reverse the steps &lt;a href=&quot;https://0l.de/blog/2022/06/netgear-m5-root-access&quot;&gt;from my first blog post&lt;/a&gt; via the AT-over-TCP interface.&lt;/li&gt;
&lt;li&gt;Use the iptables firewall to block access to the Telnet port&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ve decided to go for the second option:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/systemd/system/block-telnet.service&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Unit]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Description=Block Telnet access&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;After=network.target&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Service]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Type=simple&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ExecStart=/usr/sbin/iptables -I INPUT -p tcp --dport telnet -j DROP&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ExecStop=/usr/sbin/iptables -D INPUT -p tcp --dport telnet -j DROP&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[Install]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;WantedBy=multi-user.target&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;daemon-reload&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;enable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--now&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;block-telnet.service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;</content:encoded><category>Hacking</category><category>Networking</category><category>English</category><category>Netgear Nighhawk M5</category></item><item><title>Having a detailed look at the Netgear Nighthawk M5 Mobile LTE/Router</title><link>https://0l.de/blog/2022/06/netgear-m5-reveng/</link><guid isPermaLink="true">https://0l.de/blog/2022/06/netgear-m5-reveng/</guid><pubDate>Wed, 29 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/dr_watson.Cf2RFviJ_YfqEY.webp&quot; srcset=&quot;/_astro/dr_watson.Cf2RFviJ_YfqEY.webp 346w&quot; alt=&quot;Dr. Watson&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 346px) 346px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;346&quot; height=&quot;321&quot;&gt; &lt;button aria-label=&quot;Zoom image: Dr. Watson&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt;
&lt;p&gt;After &lt;a href=&quot;https://0l.de/blog/2022/06/netgear-m5-root-access&quot;&gt;gaining root access to the device in the first post&lt;/a&gt; of this series, we will have a closer look at the device and its firmware.&lt;/p&gt;
&lt;p&gt;This post is documenting some internals of the device which is not the most exciting stuff to read.
I mainly collected it here for documentation purposes.&lt;/p&gt;
&lt;p&gt;All information in this post has been collected from a device running firmware version &lt;code dir=&quot;auto&quot;&gt;NTGX55_12.04.12.00&lt;/code&gt;.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;software&quot;&gt;Software&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Netgear’s firmware is Linux-based and uses quite a lot of common open-source tools.
They provide all modifications to GPL licensed code via their support area: &lt;a href=&quot;https://kb.netgear.com/2649/NETGEAR-Open-Source-Code-for-Programmers-GPL&quot;&gt;NETGEAR Open Source Software for Programmers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From what I can tell only their user interface and configuration management is developed by Netgear themself apart from a bunch of binary blobs provided by Qualcomm which contains the modem firmware which gets loaded to the baseband processor.&lt;/p&gt;
&lt;p&gt;One curiosity caught my eye: there is a running X server on the device.
It is used by the front-panel display of the device.
A custom application developed by Netgear uses Webkit’s engine to render the touch screen interface which just like the web UI is based on HTML and Javascript.&lt;/p&gt;
&lt;p&gt;Here is an almost complete list of open source software components which I found on the device:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;atk (v2.28)&lt;/li&gt;
&lt;li&gt;Avahi (v0.7)&lt;/li&gt;
&lt;li&gt;bash (v4.4.23)&lt;/li&gt;
&lt;li&gt;base-files (v3.0.14)&lt;/li&gt;
&lt;li&gt;BusyBox (v1.29.3)&lt;/li&gt;
&lt;li&gt;conntrack-tools (v1.0.1)&lt;/li&gt;
&lt;li&gt;D-Bus (v1.12.10)&lt;/li&gt;
&lt;li&gt;ddclient (v3.8.1)&lt;/li&gt;
&lt;li&gt;dhcpcd (v5.2.10)&lt;/li&gt;
&lt;li&gt;DiG (v9.11.5-P4)&lt;/li&gt;
&lt;li&gt;Dnsmasq (v2.85)&lt;/li&gt;
&lt;li&gt;ethtool (v4.19)&lt;/li&gt;
&lt;li&gt;font-config (v2.12.6)&lt;/li&gt;
&lt;li&gt;freetype (v2.9.1)&lt;/li&gt;
&lt;li&gt;glib (v2.58.0)&lt;/li&gt;
&lt;li&gt;hostapd (v2.8-devel)&lt;/li&gt;
&lt;li&gt;iproute2 (iproute2-ss140804)&lt;/li&gt;
&lt;li&gt;iptables (v1.6.2)&lt;/li&gt;
&lt;li&gt;iw (v4.14)&lt;/li&gt;
&lt;li&gt;libcap (v2.25)&lt;/li&gt;
&lt;li&gt;libnfnetlink (v1.0.0)&lt;/li&gt;
&lt;li&gt;Linux Kernel (v4.14.117)&lt;/li&gt;
&lt;li&gt;miniupnpd&lt;/li&gt;
&lt;li&gt;mtd-utils (v2.0.2)&lt;/li&gt;
&lt;li&gt;nettle (v3.4)&lt;/li&gt;
&lt;li&gt;OpenSSL (v1.1.1b)&lt;/li&gt;
&lt;li&gt;pimd (v2.1.8)&lt;/li&gt;
&lt;li&gt;pppd (v2.4.7)&lt;/li&gt;
&lt;li&gt;strace (v4.24)&lt;/li&gt;
&lt;li&gt;SystemD (v239)&lt;/li&gt;
&lt;li&gt;tinyproxy (v1.8.3)&lt;/li&gt;
&lt;li&gt;util-linux (v2.32.1)&lt;/li&gt;
&lt;li&gt;wireless-tools (v30)&lt;/li&gt;
&lt;li&gt;wpa_supplicant (v2.9)&lt;/li&gt;
&lt;li&gt;Xorg (v1.20.1)&lt;/li&gt;
&lt;li&gt;xz (v5.2.4)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;basic-facts&quot;&gt;Basic facts&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Lets first have a look at the Kernel version:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;uname&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-a&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Linux&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sdxprairie&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;4.14.117&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#1 PREEMPT Thu Aug 19 23:42:26 UTC 2021 armv7l GNU/Linux&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# cat /proc/version&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Linux&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;4.14.117&lt;/span&gt;&lt;span&gt; (oe-user@oe-host) (&lt;/span&gt;&lt;span&gt;clang&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;6.0.9&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Android&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NDK&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;#1 PREEMPT Thu Aug 19 23:42:26 UTC 2021&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Apparently the firmware has been built by &lt;a href=&quot;https://www.openembedded.org/&quot;&gt;Open Embedded&lt;/a&gt; as indicated by the kernel notice “&lt;code dir=&quot;auto&quot;&gt;oe-user&lt;/code&gt;”.&lt;/p&gt;
&lt;p&gt;There is also a /target file lying around.
I assume that “&lt;code dir=&quot;auto&quot;&gt;sdxprairie&lt;/code&gt;” is Qualcomm’s name for the SDK / BSP which is used by Netgear.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/target&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;sdxprairie&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The application processor of the Snapdragon X55 is a fairly low powered single-core ARM v7:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/proc/cpuinfo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;processor&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ARMv7&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Processor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rev&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt; (v7l)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;BogoMIPS&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;38.40&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Features&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;half&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;thumb&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fastmult&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;vfp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;edsp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;neon&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;vfpv3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tls&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;vfpv4&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;idiva&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;idivt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;vfpd32&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lpae&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;evtstrm&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;CPU&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;implementer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0x41&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;CPU&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;architecture:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;CPU&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;variant&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0x0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;CPU&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;part&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0xc07&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;CPU&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;revision&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Hardware&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Qualcomm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Technologies,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Inc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SDXPRAIRIE&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Revision&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0000&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Serial&lt;/span&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0000000000000000&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;With around 780 MB of RAM:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;free&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-m&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;             &lt;/span&gt;&lt;span&gt;total&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;used&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;free&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;shared&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;buffers&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;cached&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Mem:&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;781&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;387&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;393&lt;/span&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;142&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;-/+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;buffers/cache:&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;245&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;535&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Swap:&lt;/span&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;109&lt;/span&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;109&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;soc-details&quot;&gt;SoC details&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Within the SysFS we can find some details about the SoC.
More details about the meaning can be found &lt;a href=&quot;https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-soc&quot;&gt;in the Kernel documentation&lt;/a&gt;:&lt;/p&gt;

































































































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;SysFS Entry&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/accessory_chip&lt;/code&gt;&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/chip_family&lt;/code&gt;&lt;/td&gt;&lt;td&gt;0x5e&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/chip_name&lt;/code&gt;&lt;/td&gt;&lt;td&gt;SDX55&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/family&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Snapdragon&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/foundry_id&lt;/code&gt;&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/hw_platform&lt;/code&gt;&lt;/td&gt;&lt;td&gt;MTP&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/image_crm_version&lt;/code&gt;&lt;/td&gt;&lt;td&gt;:ntgrbc-fwbuild6&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/image_variant&lt;/code&gt;&lt;/td&gt;&lt;td&gt;MAATANAZA&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/image_version&lt;/code&gt;&lt;/td&gt;&lt;td&gt;00:BOOT.SBL.4.1-00231&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/machine&lt;/code&gt;&lt;/td&gt;&lt;td&gt;SDXPRAIRIE&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/ncluster_array_offset&lt;/code&gt;&lt;/td&gt;&lt;td&gt;0xb0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/ndefective_parts_array_offset&lt;/code&gt;&lt;/td&gt;&lt;td&gt;0xb4&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/nmodem_supported&lt;/code&gt;&lt;/td&gt;&lt;td&gt;0xffffffff&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/nproduct_id&lt;/code&gt;&lt;/td&gt;&lt;td&gt;0x410&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/num_clusters&lt;/code&gt;&lt;/td&gt;&lt;td&gt;0x1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/num_defective_parts&lt;/code&gt;&lt;/td&gt;&lt;td&gt;0xd&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/platform_subtype&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Invalid&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/platform_subtype_id&lt;/code&gt;&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/platform_version&lt;/code&gt;&lt;/td&gt;&lt;td&gt;65536&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/pmic_die_revision&lt;/code&gt;&lt;/td&gt;&lt;td&gt;131072&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/pmic_model&lt;/code&gt;&lt;/td&gt;&lt;td&gt;65568&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/raw_device_family&lt;/code&gt;&lt;/td&gt;&lt;td&gt;0x6&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/raw_device_number&lt;/code&gt;&lt;/td&gt;&lt;td&gt;0xb&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/raw_id&lt;/code&gt;&lt;/td&gt;&lt;td&gt;207&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/raw_version&lt;/code&gt;&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/revision&lt;/code&gt;&lt;/td&gt;&lt;td&gt;2.0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/select_image&lt;/code&gt;&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/serial_number&lt;/code&gt;&lt;/td&gt;&lt;td&gt;27453XXXX&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/soc_id&lt;/code&gt;&lt;/td&gt;&lt;td&gt;357&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;/sys/devices/soc0/vendor&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Qualcomm&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/sys/devices/soc0/images&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;0:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;CRM:&lt;/span&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;00:BOOT.SBL.4.1-00231&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Variant:&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;MAATANAZA&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Version:&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;:ntgrbc-fwbuild6&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;1:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;CRM:&lt;/span&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;01:TZ.FU.5.9-00147&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Variant:&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;EATAANBAA&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Version:&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;:CRM&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;11:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;CRM:&lt;/span&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;11:MPSS.HI.2.0.c3.5-00010-SDX55_CPEALL_PACK-1.403198.3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Variant:&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;sdx55.gennatch.prod&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Version:&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;:ntgrbc-fwbuild6&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;kernel-command-line&quot;&gt;Kernel command line&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/proc/cmdline&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;noinitrd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rw&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rootwait&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;console=ttyMSM0,115200,n8&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;androidboot.hardware=qcom&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;msm_rtb.filter=&lt;/span&gt;&lt;span&gt;0x237&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;androidboot.console=ttyMSM0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lpm_levels.sleep_disabled=&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;firmware_class.path=/lib/firmware/updates&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;service_locator.enable=&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;net.ifnames=&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;atlantic_fwd.rx_ring_size=&lt;/span&gt;&lt;span&gt;1024&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pci=pcie_bus_perf&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rootfstype=ubifs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rootflags=bulk_read&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;root=ubi0:rootfs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ubi.mtd=&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;androidboot.serialno=105d0dc7&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;androidboot.baseband=msm&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;kernel-log&quot;&gt;Kernel log&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Unfortunately, I was not able to capture early kernel log messages.
I assume those are only printed via a serial port and lost as the circular buffer for the kernel log has not been set up.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Full log:&lt;/strong&gt; &lt;a href=&quot;https://codeberg.org/stv0g/netgear-nighthawk-mobile/src/master/reveng/dmesg.txt&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/netgear-nighthawk-mobile/reveng/dmesg.txt&lt;/span&gt; &lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;more-details&quot;&gt;More details&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Network interfaces:&lt;/strong&gt; &lt;a href=&quot;https://codeberg.org/stv0g/netgear-nighthawk-mobile/src/master/reveng/interfaces.txt&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/netgear-nighthawk-mobile/reveng/interfaces.txt&lt;/span&gt; &lt;/a&gt;  (&lt;code dir=&quot;auto&quot;&gt;ip address show&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Devices:&lt;/strong&gt; &lt;a href=&quot;https://codeberg.org/stv0g/netgear-nighthawk-mobile/src/master/reveng/devices.txt&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/netgear-nighthawk-mobile/reveng/devices.txt&lt;/span&gt; &lt;/a&gt;  (&lt;code dir=&quot;auto&quot;&gt;ls -l /dev&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kernel modules:&lt;/strong&gt; &lt;a href=&quot;https://codeberg.org/stv0g/netgear-nighthawk-mobile/src/master/reveng/modules.txt&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/netgear-nighthawk-mobile/reveng/modules.txt&lt;/span&gt; &lt;/a&gt;  (&lt;code dir=&quot;auto&quot;&gt;lsmod&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Running processes:&lt;/strong&gt; &lt;a href=&quot;https://codeberg.org/stv0g/netgear-nighthawk-mobile/src/master/reveng/processes.txt&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/netgear-nighthawk-mobile/reveng/processes.txt&lt;/span&gt; &lt;/a&gt;  (&lt;code dir=&quot;auto&quot;&gt;ps aux&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mounted filesystems:&lt;/strong&gt; &lt;a href=&quot;https://codeberg.org/stv0g/netgear-nighthawk-mobile/src/master/reveng/mounts.txt&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/netgear-nighthawk-mobile/reveng/mounts.txt&lt;/span&gt; &lt;/a&gt;  (&lt;code dir=&quot;auto&quot;&gt;mount&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flash partitions:&lt;/strong&gt; &lt;a href=&quot;https://codeberg.org/stv0g/netgear-nighthawk-mobile/src/master/reveng/mtd.txt&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/netgear-nighthawk-mobile/reveng/mtd.txt&lt;/span&gt; &lt;/a&gt;  (&lt;code dir=&quot;auto&quot;&gt;cat /proc/mtd&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Open ports:&lt;/strong&gt; &lt;a href=&quot;https://codeberg.org/stv0g/netgear-nighthawk-mobile/src/master/reveng/ports.txt&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/netgear-nighthawk-mobile/reveng/ports.txt&lt;/span&gt; &lt;/a&gt;  (&lt;code dir=&quot;auto&quot;&gt;netstat -plnt&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ubi devices &amp;#x26; volumes:&lt;/strong&gt; &lt;a href=&quot;https://codeberg.org/stv0g/netgear-nighthawk-mobile/src/master/reveng/ubinfo.txt&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/netgear-nighthawk-mobile/reveng/ubinfo.txt&lt;/span&gt; &lt;/a&gt;  (&lt;code dir=&quot;auto&quot;&gt;ubinfo -a&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kernel config:&lt;/strong&gt; &lt;a href=&quot;https://codeberg.org/stv0g/netgear-nighthawk-mobile/src/master/reveng/config.txt&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/netgear-nighthawk-mobile/reveng/config.txt&lt;/span&gt; &lt;/a&gt;  (&lt;code dir=&quot;auto&quot;&gt;zcat /proc/config.gz&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Devicetree source:&lt;/strong&gt; &lt;a href=&quot;https://codeberg.org/stv0g/netgear-nighthawk-mobile/src/master/reveng/device-tree.dts&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/netgear-nighthawk-mobile/reveng/device-tree.dts&lt;/span&gt; &lt;/a&gt;  (&lt;code dir=&quot;auto&quot;&gt;dtc -I fs -O dts /proc/device-tree&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Feel free to &lt;a href=&quot;https://0l.de/contact&quot;&gt;contact&lt;/a&gt; me if I missed any particular detail which is interesting to you.&lt;/p&gt;</content:encoded><category>English</category><category>Hardware</category><category>Review</category><category>Networking</category><category>Reverse Engineering</category><category>Netgear Nighhawk M5</category></item><item><title>A 3D-printed wall mount for Netgear Nighthawk mobile 5G/LTE routers</title><link>https://0l.de/blog/2022/06/netgear-m5-wall-mount/</link><guid isPermaLink="true">https://0l.de/blog/2022/06/netgear-m5-wall-mount/</guid><pubDate>Sat, 25 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I have recently designed and printed a wall mount for Netgear’s Nighthawk mobile 5G/LTE routers.
More specifically a Nighthawk M5 (MR5200).&lt;/p&gt;
&lt;p&gt;I have been inspired by an &lt;a href=&quot;https://www.fts-hennig.de/antennenkabel/adapter/antennenadapter-nighthawk-m5.html&quot;&gt;existing commercial wall mount for the Nighthawk M-series routers by FTS Hennig GmbH&lt;/a&gt;:&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/M5-Antennenadapter-2_large.D3UyZCVI_tv7jT.webp&quot; srcset=&quot;/_astro/M5-Antennenadapter-2_large.D3UyZCVI_tv7jT.webp 600w&quot; alt=&quot;My inspiration: the wall-mount and antenna adapter from FTS Hennig&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 600px) 600px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;600&quot; height=&quot;400&quot;&gt; &lt;button aria-label=&quot;Zoom image: My inspiration: the wall-mount and antenna adapter from FTS Hennig&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;My inspiration: the wall-mount and antenna adapter from FTS Hennig.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;Unfortunately, the mount is with a price tag of around 50 € rather expensive.
So I decided to use our new lab 3D-printer and try do design it myself usings AutoDesk’s Fusion 360 software.&lt;/p&gt;
&lt;p&gt;My own 3D printed holder is released under a creative commons license at Codeberg: &lt;a href=&quot;https://codeberg.org/stv0g/3d-printing/src/master/netgear-m5-wall-mount&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/3d-printing/netgear-m5-wall-mount&lt;/span&gt; &lt;/a&gt; &lt;/p&gt;

&lt;p&gt;The mount contains two three mounting holes which can be used for screwing it against a wall as well as some cutouts at the bottom for the accessibility of the TS9 antenna, USB-C and Ethernet ports.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/m5.BDzR6uXq_Z2ozJHJ.webp&quot; srcset=&quot;/_astro/m5.BDzR6uXq_1NxOI1.webp 640w, /_astro/m5.BDzR6uXq_Z2bieHB.webp 750w, /_astro/m5.BDzR6uXq_Z1R5wuT.webp 828w, /_astro/m5.BDzR6uXq_u5l8Y.webp 1080w, /_astro/m5.BDzR6uXq_1XIy1m.webp 1280w, /_astro/m5.BDzR6uXq_Z2ozJHJ.webp 1395w&quot; alt=&quot;My model rendered by AutoDesk Fusion 360&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1395px) 1395px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1395&quot; height=&quot;931&quot;&gt; &lt;button aria-label=&quot;Zoom image: My model rendered by AutoDesk Fusion 360&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;My model rendered by AutoDesk Fusion 360.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;For the TS9 antenna ports, I am using the following TS-9 to SMA adapters which can be screwed into the respective holes of the mount.
This allows a permanent installation of an external 5G/LTA antenna while the router can be easily removed as the adapters align right with the connectors of the router.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/ts9-sma.DmtD-T8y_D4jL.webp&quot; srcset=&quot;/_astro/ts9-sma.DmtD-T8y_2jM43u.webp 640w, /_astro/ts9-sma.DmtD-T8y_Z1W34BS.webp 750w, /_astro/ts9-sma.DmtD-T8y_ZSkSj2.webp 828w, /_astro/ts9-sma.DmtD-T8y_D4jL.webp 1061w&quot; alt=&quot;Screw-in TS-9 to SMA Adapters&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1061px) 1061px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1061&quot; height=&quot;591&quot;&gt; &lt;button aria-label=&quot;Zoom image: Screw-in TS-9 to SMA Adapters&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Screw-in TS-9 to SMA Adapters.&lt;/figcaption&gt; &lt;/figure&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/netgear-m5-holder-1.CoHXk0KE_QFSo8.webp&quot; srcset=&quot;/_astro/netgear-m5-holder-1.CoHXk0KE_4jRGq.webp 640w, /_astro/netgear-m5-holder-1.CoHXk0KE_Z1MHLDs.webp 750w, /_astro/netgear-m5-holder-1.CoHXk0KE_Z8UQIz.webp 828w, /_astro/netgear-m5-holder-1.CoHXk0KE_1bQHQ5.webp 1080w, /_astro/netgear-m5-holder-1.CoHXk0KE_ZymNNc.webp 1280w, /_astro/netgear-m5-holder-1.CoHXk0KE_Z11tXRu.webp 1668w, /_astro/netgear-m5-holder-1.CoHXk0KE_QFSo8.webp 1798w&quot; alt=&quot;Final print&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1798px) 1798px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1798&quot; height=&quot;1842&quot;&gt; &lt;button aria-label=&quot;Zoom image: Final print&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Final print.&lt;/figcaption&gt; &lt;/figure&gt;</content:encoded><category>3D Printing</category><category>3D</category><category>Networking</category><category>English</category><category>Netgear Nighhawk M5</category></item><item><title>Gaining Root Access on Netgear Nighthawk Mobile 5G/LTE Routers</title><link>https://0l.de/blog/2022/06/netgear-m5-root-access/</link><guid isPermaLink="true">https://0l.de/blog/2022/06/netgear-m5-root-access/</guid><pubDate>Sat, 25 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This blog posts covers the required steps to gain root access via Telnet on Netgear Nighthawk Mobile 5G/LTE Routers. Its the first post in a small series covering my experiences playing around with this device.&lt;/p&gt;
&lt;p&gt;Last month I obtained one of Netgear’s latest mobile 5G routers, the &lt;a href=&quot;https://www.netgear.com/home/mobile-wifi/hotspots/mr5200/&quot;&gt;Netgear Nighthawk M5&lt;/a&gt; (model MR5200-100EUS) . Being one of the most expensive consumer 5G routers, I was lucky to get a fairly good second hand deal from eBay.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/Netgear-Nighthawk-M5-mobile-router-copy.Dt9FC3GW_Z2u6pLR.webp&quot; srcset=&quot;/_astro/Netgear-Nighthawk-M5-mobile-router-copy.Dt9FC3GW_Z2jHNFh.webp 640w, /_astro/Netgear-Nighthawk-M5-mobile-router-copy.Dt9FC3GW_Z2u6pLR.webp 700w&quot; alt=&quot;Netgear Nighthawk M5 mobile 5G/LTE Router&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 700px) 700px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;700&quot; height=&quot;500&quot;&gt; &lt;button aria-label=&quot;Zoom image: Netgear Nighthawk M5 mobile 5G/LTE Router&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Netgear Nighthawk M5 mobile 5G/LTE Router.&lt;/figcaption&gt; &lt;/figure&gt;

&lt;p&gt;The router is powered by &lt;a href=&quot;https://www.qualcomm.com/products/technology/modems/snapdragon-x55-5g-modem&quot;&gt;Qualcomm’s® Snapdragon™ X55 5G Modem-RF system&lt;/a&gt;. Looking closer at the internals of the device by checking the &lt;a href=&quot;https://fccid.io/PY319400469/&quot;&gt;FCC filing for the closely related American model MR5100&lt;/a&gt;, we can see that the system consists of a Qualcomm SDX55 chipset which combines both the mobile baseband and application processors.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;gaining-root-access&quot;&gt;Gaining Root Access&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Gaining root access to the device is actually fairly simple in comparison to rooting modern Android-based devices. The router exposes an open TCP port providing an AT command interface. However, this port is only accessible via a tethered USB connection, &lt;strong&gt;not via Wifi&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Using this AT command interface, we can interact with the modem, unlock an extended command set which allows us enable a Telnet daemon.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;detailed-steps&quot;&gt;Detailed Steps&lt;/h3&gt;&lt;/div&gt;

&lt;ol role=&quot;list&quot;&gt;
&lt;li&gt;
&lt;p&gt;Install the Sierra Wireless debug tools from bkerler (&lt;a href=&quot;https://github.com/bkerler/edl&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .3a12 12 0 0 0-3.8 23.38c.6.12.83-.26.83-.57L9 21.07c-3.34.72-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.08-.74.09-.73.09-.73 1.2.09 1.83 1.24 1.83 1.24 1.08 1.83 2.81 1.3 3.5 1 .1-.78.42-1.31.76-1.61-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.14-.3-.54-1.52.1-3.18 0 0 1-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.29-1.23 3.29-1.23.64 1.66.24 2.88.12 3.18a4.65 4.65 0 0 1 1.23 3.22c0 4.61-2.8 5.63-5.48 5.92.42.36.81 1.1.81 2.22l-.01 3.29c0 .31.2.69.82.57A12 12 0 0 0 12 .3Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/bkerler/edl&lt;/span&gt; &lt;/a&gt; )&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;python3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;git&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;clone&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://github.com/bkerler/edl.git&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;edl&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;python&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;setup.py&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;(More detailed installation instructions are covered in the README file of the repo.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Connect your machine via USB-C to the Netgear router&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make sure to disconnect from the Netgear Wifi&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open a terminal an connect to the AT command interface via netcat (nc)&lt;/p&gt;
&lt;p&gt;(Make sure not to miss the -c option as it will the enable nc to use the proper CRLF line-endings which are required for the AT interface).&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;nc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-c&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;192.168.1.1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;5510&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Once connected to the AT command interface, you need to request a unlock challenge code by sending&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;AT!OPENLOCK?&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The previous command will return a challenge code which we use to generate a corresponding response code via the previously installed &lt;code dir=&quot;auto&quot;&gt;sierrakeygen.py&lt;/code&gt; tool:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;sierrakeygen.py&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-l&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;replace_with_challenge_code&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SDX55&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The previous command will print out another &lt;code dir=&quot;auto&quot;&gt;AT+OPENLOCK&lt;/code&gt; command which you need to copy verbatim back to your AT command session.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the following AT commands to enable the Telnet daemon&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;AT!TELEN=1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;AT!CUSTOM=&quot;RDENABLE&quot;, 1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;AT!CUSTOM=&quot;TELNETENABLE&quot;, 1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;You can now close the AT command session by pressing Ctrl+C.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Power-cycle the Netgear Router to start the Telnet daemon&lt;/p&gt;
&lt;p&gt;Voila, you can now telnet into the device via both the tethered USB-C cable or Wifi.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;nc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-c&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;172.23.156.129&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;��������&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;mdm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1623&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sdxprairie&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# uname -a&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;uname&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-a&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Linux&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sdxprairie&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;4.14.117&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#1 PREEMPT Thu Aug 19 23:42:26 UTC 2021 armv7l GNU/Linux&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; Please be aware that the device security is now breached as all devices connected to the Wifi or USB can gain root access to the device. The root Telnet login requires no password.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Before proceeding we should make sure that we can bring the device back to a secure state &lt;a href=&quot;https://0l.de/blog/2022/07/netgear-m5-ssh-access&quot;&gt;by replacing the Telnet by an Secure Shell (SSH) daemon&lt;/a&gt;. In one of the next posts of this series, I will be building a statically linked version of the Dropbear SSH server to replace Telnet.&lt;/p&gt;
&lt;p&gt;Before continuing my reverse engineering efforts on the device, I would like to ensure that I will not brick the router while doing so &lt;a href=&quot;https://0l.de/blog/2022/06/netgear-m5-reveng&quot;&gt;by dumping the firmware and extract all the details from it&lt;/a&gt;. This will allow us to hopefully restore the device by flashing the original firmware. Maybe we will be able to run OpenWRT on it.&lt;/p&gt;
&lt;p&gt;I have also designed &lt;a href=&quot;https://0l.de/blog/2022/06/netgear-m5-wall-mount&quot;&gt;a wall mount for the router&lt;/a&gt; which allows me to mount it permanently into by van.&lt;/p&gt;</content:encoded><category>Hacking</category><category>Linux</category><category>Networking</category><category>English</category><category>Netgear Nighhawk M5</category></item><item><title>Open-Data Lab Aachen</title><link>https://0l.de/blog/2022/06/open-data-lab-aachen/</link><guid isPermaLink="true">https://0l.de/blog/2022/06/open-data-lab-aachen/</guid><pubDate>Wed, 22 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/rathaus.3co7jTyp_Z2btJoM.webp&quot; srcset=&quot;/_astro/rathaus.3co7jTyp_StnFz.webp 640w, /_astro/rathaus.3co7jTyp_1GdDI7.webp 750w, /_astro/rathaus.3co7jTyp_Z10xajG.webp 828w, /_astro/rathaus.3co7jTyp_hvsq3.webp 1080w, /_astro/rathaus.3co7jTyp_Z2og3Js.webp 1280w, /_astro/rathaus.3co7jTyp_Z1q0XjO.webp 1668w, /_astro/rathaus.3co7jTyp_1tnI1i.webp 2048w, /_astro/rathaus.3co7jTyp_pUGz5.webp 2560w, /_astro/rathaus.3co7jTyp_Z2btJoM.webp 5184w&quot; alt=&quot;Aachener Rathaus&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 5184px) 5184px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;5184&quot; height=&quot;3456&quot;&gt; &lt;button aria-label=&quot;Zoom image: Aachener Rathaus&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Aachener Rathaus.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/odlabac.DwyG3ioB_Z2ffY51.webp&quot; srcset=&quot;/_astro/odlabac.DwyG3ioB_Z2ffY51.webp 88w&quot; alt=&quot;Logo des Open Data Lab Aachen&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 88px) 88px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;88&quot; height=&quot;88&quot;&gt; &lt;button aria-label=&quot;Zoom image: Logo des Open Data Lab Aachen&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Logo des Open Data Lab Aachen.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;Im September letzten Jahres hat sich in Aachen das Open Data Lab mit einer virtuellen Kick-off Veranstaltung gegründet.&lt;/p&gt;
&lt;p&gt;Im Open Data Lab wollen wir ehrenamtlich Projekte rund um Offene Daten in Aachen voranbringen.
Wir suchen dazu Personen, die daran generell interessiert sind, ob Entwickler*innen, Designer*innen, Datenjournalist*innen aus Verwaltung, Politik und Gesellschaft.&lt;/p&gt;
&lt;p&gt;Wir wollen Daten und Ideen zusammenbringen und daraus Projekte generieren.&lt;/p&gt;
&lt;br&gt;

&lt;div&gt;&lt;h2 id=&quot;was-ist-open-data&quot;&gt;Was ist Open Data?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Als &lt;strong&gt;Open Data&lt;/strong&gt; werden Daten bezeichnet, die von jedermann zu jedem Zweck genutzt, weiterverbreitet und weiterverwendet werden dürfen.
Einschränkungen der Nutzung sind nur erlaubt, um Ursprung und Offenheit des Wissens zu sichern, beispielsweise durch Nennung des Urhebers.
Ausgenommen sind personenbezogene Daten sowie Daten, die anderweitig schutzwürdig sind.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;wer-kann-mitmachen&quot;&gt;Wer kann Mitmachen?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Im Prinzip ist jeder bei uns willkommen.
Egal ob du bereits Vorkenntnisse hast oder nicht 😊.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bürgerinnen&lt;/li&gt;
&lt;li&gt;(Kommunal) Politikerinnen&lt;/li&gt;
&lt;li&gt;Mitarbeiterinnen der Verwaltung&lt;/li&gt;
&lt;li&gt;Wissenschaftlerinnen&lt;/li&gt;
&lt;li&gt;Unternehmerinnen&lt;/li&gt;
&lt;li&gt;Open Knowledge Labs &amp;#x26; Digitales Ehrenamt&lt;/li&gt;
&lt;li&gt;Datenjournalisteninnen&lt;/li&gt;
&lt;li&gt;Studierende, SchülerInnen und LehrerInnen&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;aktuelle-projekte&quot;&gt;Aktuelle Projekte&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Die folgende Liste ist eine Übersicht aktueller Projekte, die in Aachen im Umfeld des Open Data Labs mit offenen Daten entwickelt werden:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://oecher.info&quot;&gt;https://oecher.info&lt;/a&gt; (@mrtopf)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://baustellen.offenes-aachen.de&quot;&gt;https://baustellen.offenes-aachen.de&lt;/a&gt; (@mrtopf)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://unserac.de&quot;&gt;https://unserac.de&lt;/a&gt; (ALLRIS-Import, @mrtopf + @Unser_AC)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lokalpetition.de&quot;&gt;https://lokalpetition.de&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;https://codeberg.org/stv0g/cfac&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/cfac&lt;/span&gt; &lt;/a&gt; 
&lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;https://github.com/tapwork/AachenMobDashboard&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .3a12 12 0 0 0-3.8 23.38c.6.12.83-.26.83-.57L9 21.07c-3.34.72-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.08-.74.09-.73.09-.73 1.2.09 1.83 1.24 1.83 1.24 1.08 1.83 2.81 1.3 3.5 1 .1-.78.42-1.31.76-1.61-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.14-.3-.54-1.52.1-3.18 0 0 1-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.29-1.23 3.29-1.23.64 1.66.24 2.88.12 3.18a4.65 4.65 0 0 1 1.23 3.22c0 4.61-2.8 5.63-5.48 5.92.42.36.81 1.1.81 2.22l-.01 3.29c0 .31.2.69.82.57A12 12 0 0 0 12 .3Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/tapwork/AachenMobDashboard&lt;/span&gt; &lt;/a&gt; 
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://regionaachenrettet.de&quot;&gt;https://regionaachenrettet.de&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://owi19.adfc-ac.de&quot;&gt;https://owi19.adfc-ac.de&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://verkehr.aachen.de&quot;&gt;https://verkehr.aachen.de&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://aachen-transparent.de&quot;&gt;https://aachen-transparent.de&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.aachen-app.de&quot;&gt;https://www.aachen-app.de&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;mach-mit&quot;&gt;Mach mit&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Interessierst du dich für offene Daten? Macht mit und lerne uns beim nächste Treffen kennen.
Dieses findet bereits nächste Woche statt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Datum:&lt;/strong&gt; 12. April 2022&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Uhrzeit:&lt;/strong&gt; 19:00&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ort:&lt;/strong&gt; Virtuell via &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12.000 23.802L12.000 23.802Q8.808 23.802 6.078 22.185Q3.348 20.568 1.752 17.838L1.752 17.838Q0.114 15.024 0.198 11.748L0.198 11.748Q0.240 8.598 1.836 5.952Q3.432 3.306 6.078 1.794L6.078 1.794Q8.850 0.198 12.126 0.198L12.126 0.198Q15.318 0.198 18.027 1.815Q20.736 3.432 22.290 6.162L22.290 6.162Q23.886 8.976 23.802 12.252L23.802 12.252Q23.760 15.360 22.143 18.027Q20.526 20.694 17.880 22.206L17.880 22.206Q15.150 23.802 12.000 23.802ZM7.800 4.650L7.800 4.650L7.800 19.224L7.926 19.224L18.552 12.126L18.678 12Q18.678 12 18.552 12L18.552 12Q11.496 7.254 7.800 4.902L7.800 4.902Q7.884 4.818 7.884 4.734Q7.884 4.650 7.800 4.650Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt; Zoom&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Weiterhin kannst du uns auch online über folgende Kanäle erreichen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://odlabac.de/&quot;&gt;Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href=&quot;https://github.com/odlabac&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .3a12 12 0 0 0-3.8 23.38c.6.12.83-.26.83-.57L9 21.07c-3.34.72-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.08-.74.09-.73.09-.73 1.2.09 1.83 1.24 1.83 1.24 1.08 1.83 2.81 1.3 3.5 1 .1-.78.42-1.31.76-1.61-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.14-.3-.54-1.52.1-3.18 0 0 1-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.29-1.23 3.29-1.23.64 1.66.24 2.88.12 3.18a4.65 4.65 0 0 1 1.23 3.22c0 4.61-2.8 5.63-5.48 5.92.42.36.81 1.1.81 2.22l-.01 3.29c0 .31.2.69.82.57A12 12 0 0 0 12 .3Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/odlabac&lt;/span&gt; &lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/opendataaachen&quot;&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://join.slack.com/t/opendatalabaachen/shared_invite/zt-ty9hompt-MoihC9SXkzqHWJvEEhQz0g&quot;&gt;Slack Workspace&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Aachen</category><category>Open Data</category><category>Open Source</category><category>German</category></item><item><title>GoSƐ - A terascale file-uploader</title><link>https://0l.de/blog/2022/04/gose/</link><guid isPermaLink="true">https://0l.de/blog/2022/04/gose/</guid><pubDate>Sun, 03 Apr 2022 00:00:00 GMT</pubDate><content:encoded>&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/gose-logo.C5zLi8lM_1Gu6A1.svg&quot; srcset=&quot;/_astro/gose-logo.C5zLi8lM_1Gu6A1.svg 360w&quot; alt=&quot;GoSƐ Logo&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 360px) 360px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;360&quot; height=&quot;375&quot;&gt; &lt;button aria-label=&quot;Zoom image: GoSƐ Logo&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;GoSƐ Logo.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://codeberg.org/stv0g/gose&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;GoSƐ&lt;/span&gt; &lt;/a&gt;  is a modern and scalable file-uploader focusing on scalability and simplicity.&lt;/p&gt;
&lt;p&gt;It is a little hobby project I’ve been working on over the last weekends.&lt;/p&gt;
&lt;p&gt;The only requirement for GoSƐ is a S3 storage backend which allows to it to scale horizontally without the need for additional databases or caches.
Uploaded files a divided into equally sized chunks which are hashed with a MD5 digest in the browser for upload.
This allows GoSƐ to skip chunks which already exist.
Seamless resumption of interrupted uploads and storage savings are the consequence.&lt;/p&gt;
&lt;p&gt;And either way both upload and downloads are always directed directly at the S3 server so GoSƐ only sees a few small HTTP requests instead of the bulk of the data.
Behind the scenes, GoSƐ uses many of the more advanced S3 features like &lt;a href=&quot;https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html&quot;&gt;Multi-part Uploads&lt;/a&gt; and &lt;a href=&quot;https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html&quot;&gt;Pre-signed Requests&lt;/a&gt; to make this happen.&lt;/p&gt;
&lt;p&gt;Users have a few options to select between multiple pre-configured S3 buckets or enable browser &amp;#x26; mail notifications about completed uploads.
A customizable retention / expiration time for each upload is also selectable by the user and implemented by &lt;a href=&quot;https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lifecycle-mgmt.html&quot;&gt;S3 life-cycle policies&lt;/a&gt;.
Optionally, users can also opt-in to use an external service to shorten the URL of the uploaded file.&lt;/p&gt;
&lt;p&gt;Currently a single concurrent upload of a single file is supported.
Users can observe the progress via a table of details statistics, a progress-bar and a chart showing the current transfer speed.&lt;/p&gt;
&lt;p&gt;GoSƐ aims at keeping its deployment simple and by bundling both front- &amp;#x26; backend components in a single binary or Docker image.
GoSƐ has been tested with AWS S3, Ceph’s RadosGW and Minio.
Pre-built binaries and Docker images of GoSƐ are available for all major operating systems and architectures at the release page: &lt;a href=&quot;https://codeberg.org/stv0g/gose/releases&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/gose (Releases)&lt;/span&gt; &lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;GoSƐ is open-source software licensed under the Apache 2.0 license.&lt;/p&gt;

&lt;center&gt;&lt;a href=&quot;https://gose.0l.de&quot;&gt;  Live Demo  &lt;/a&gt; &lt;/center&gt;
&lt;div&gt;&lt;h2 id=&quot;screencast&quot;&gt;Screencast&lt;/h2&gt;&lt;/div&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/gose_demo.Bak98gkQ_djO6a.webp&quot; srcset=&quot;/_astro/gose_demo.Bak98gkQ_djO6a.webp 604w&quot; alt=&quot;GoSƐ Demo&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 604px) 604px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;604&quot; height=&quot;1176&quot;&gt; &lt;button aria-label=&quot;Zoom image: GoSƐ Demo&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;GoSƐ Demo.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;div&gt;&lt;h2 id=&quot;features&quot;&gt;Features&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;De-duplication of uploaded files based on their content-hash
&lt;ul&gt;
&lt;li&gt;Uploads of existing files will complete in no-time without re-upload&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;S3 Multi-part uploads
&lt;ul&gt;
&lt;li&gt;Resumption of interrupted uploads&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Drag &amp;#x26; Drop of files&lt;/li&gt;
&lt;li&gt;Browser notifications about failed &amp;#x26; completed uploads&lt;/li&gt;
&lt;li&gt;User-provided object expiration / retention time&lt;/li&gt;
&lt;li&gt;Copy URL of uploaded file to clip-board&lt;/li&gt;
&lt;li&gt;Detailed transfer statistics and progress-bar / chart&lt;/li&gt;
&lt;li&gt;Installation via single binary or container
&lt;ul&gt;
&lt;li&gt;JS/HTML/CSS Frontend is bundled into binary&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Scalable to multiple replicas
&lt;ul&gt;
&lt;li&gt;All state is kept in the S3 storage backend&lt;/li&gt;
&lt;li&gt;No other database or cache is required&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Direct up &amp;#x26; download to Amazon S3 via presigned-URLs
&lt;ul&gt;
&lt;li&gt;Gose deployment does not see an significant traffic&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;UTF-8 filenames&lt;/li&gt;
&lt;li&gt;Multiple user-selectable buckets / servers&lt;/li&gt;
&lt;li&gt;Optional link shortening via an external service&lt;/li&gt;
&lt;li&gt;Optional notification about new uploads via &lt;a href=&quot;https://containrrr.dev/shoutrrr/v0.5/&quot;&gt;shoutrrr&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Mail notifications to user-provided recipient&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cross-platform support:
&lt;ul&gt;
&lt;li&gt;Operating systems: Windows, macOS, Linux, BSD&lt;/li&gt;
&lt;li&gt;Architectures: arm64, amd64, armv7, i386&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;roadmap&quot;&gt;Roadmap&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I consider the current state of GoSƐ to be production ready.
Its basic functionality is complete.
However, there are still some ideas which I would like to work on in the future:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://bittorrent.org/beps/bep_0017.html&quot;&gt;BEP-17&lt;/a&gt; and &lt;a href=&quot;http://bittorrent.org/beps/bep_0019.html&quot;&gt;BEP-19&lt;/a&gt; Torrent Web-seeding&lt;/li&gt;
&lt;li&gt;Uploading to &lt;a href=&quot;https://ipfs.io/&quot;&gt;Interplanetary File System&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Support End-to-End or Server-Side-Encryption&lt;/li&gt;
&lt;li&gt;Better access control
&lt;ul&gt;
&lt;li&gt;Limit by number of up/downloads&lt;/li&gt;
&lt;li&gt;Limit by token&lt;/li&gt;
&lt;li&gt;Limit by IP ranges / Geographical origin&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Add End-to-End testing with &lt;a href=&quot;https://www.selenium.dev/documentation/webdriver/&quot;&gt;Selenium Web-driver&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also checkout the Codeberg Issue Tracker &lt;a href=&quot;https://codeberg.org/stv0g/gose/issues&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/gose (Issues)&lt;/span&gt; &lt;/a&gt;  for a detailed overview.&lt;/p&gt;</content:encoded><category>Development</category><category>Software</category><category>Webdesign</category><category>English</category><category>Project</category><category>Javascript</category></item><item><title>Running a Xilinx hw_server as Docker Container</title><link>https://0l.de/blog/2022/02/dockerized-xilinx-hw-server/</link><guid isPermaLink="true">https://0l.de/blog/2022/02/dockerized-xilinx-hw-server/</guid><pubDate>Wed, 23 Feb 2022 00:00:00 GMT</pubDate><content:encoded>&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/setup.C7tu0nxW_1bnRrI.webp&quot; srcset=&quot;/_astro/setup.C7tu0nxW_ZjYqER.webp 640w, /_astro/setup.C7tu0nxW_ZaMlwz.webp 750w, /_astro/setup.C7tu0nxW_Z1SRp6k.webp 828w, /_astro/setup.C7tu0nxW_Z1HOvHM.webp 1080w, /_astro/setup.C7tu0nxW_2vyAw1.webp 1280w, /_astro/setup.C7tu0nxW_Z1xmnpD.webp 1668w, /_astro/setup.C7tu0nxW_1p8HPL.webp 2048w, /_astro/setup.C7tu0nxW_1bnRrI.webp 2090w&quot; alt=&quot;Dockerized Xilinx hw_server Setup&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 2090px) 2090px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;2090&quot; height=&quot;1172&quot;&gt; &lt;button aria-label=&quot;Zoom image: Dockerized Xilinx hw_server Setup&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Dockerized Xilinx hw_server Setup.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;This article describes the necessary steps to run a Xilinx &lt;code dir=&quot;auto&quot;&gt;hw_server&lt;/code&gt; as a Docker container.&lt;/p&gt;
&lt;p&gt;Xilinx’s &lt;code dir=&quot;auto&quot;&gt;hw_server&lt;/code&gt; is a command line utility which handles JTAG communication between a Xilinx FPGA board and usually the Vivado IDE.
It can be used to configure the FPGA bitstream, connect to the embedded logic analyzer cores (ILA) or perform debugging of processor cores via &lt;a href=&quot;https://www.sourceware.org/gdb/&quot;&gt;GDB&lt;/a&gt; and the Xilinx System Debugger (XSDB).
The &lt;code dir=&quot;auto&quot;&gt;hw_server&lt;/code&gt; is usually used when those tasks shall performed remotely as the connection between Vivado or XSDB is established via TCP connection and allows us to run it on a remote system.&lt;/p&gt;
&lt;p&gt;Running the &lt;code dir=&quot;auto&quot;&gt;hw_server&lt;/code&gt; as a Docker container has the benefit that its installation is simplified to starting a Docker container by running:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--restart&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unless-stopped&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--privileged&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--volume&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/dev/bus/usb:/dev/bus/usb&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--publish&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3121:3121&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--detach&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ghcr.io/stv0g/hw_server:v2021.2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;It also allows us to run the &lt;code dir=&quot;auto&quot;&gt;hw_server&lt;/code&gt; on architectures which are not natively supported by Xilinx such as the commonly used Aarch / ARM64 and ARMv7 architectures found in Raspberry Pis.&lt;/p&gt;
&lt;p&gt;This is enabled by Dockers support for running container images for non-native architectures.
I am using the &lt;code dir=&quot;auto&quot;&gt;aptman/qus&lt;/code&gt; Docker image (&lt;a href=&quot;https://github.com/dbhi/qus&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .3a12 12 0 0 0-3.8 23.38c.6.12.83-.26.83-.57L9 21.07c-3.34.72-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.08-.74.09-.73.09-.73 1.2.09 1.83 1.24 1.83 1.24 1.08 1.83 2.81 1.3 3.5 1 .1-.78.42-1.31.76-1.61-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.14-.3-.54-1.52.1-3.18 0 0 1-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.29-1.23 3.29-1.23.64 1.66.24 2.88.12 3.18a4.65 4.65 0 0 1 1.23 3.22c0 4.61-2.8 5.63-5.48 5.92.42.36.81 1.1.81 2.22l-.01 3.29c0 .31.2.69.82.57A12 12 0 0 0 12 .3Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/dbhi/qus&lt;/span&gt; &lt;/a&gt; ) to setup this user-mode emulation.
The &lt;em&gt;qemu-user-static&lt;/em&gt; (&lt;strong&gt;qus&lt;/strong&gt;) image is a compilation of utilities, examples and references to build and execute OCI images (aka &lt;a href=&quot;https://www.docker.com/&quot;&gt;docker&lt;/a&gt; images) for foreign architectures using &lt;a href=&quot;https://www.qemu.org/&quot;&gt;QEMU&lt;/a&gt;’s &lt;a href=&quot;https://qemu-project.gitlab.io/qemu/user/index.html&quot;&gt;user-mode emulation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Run the following commands to run the &lt;code dir=&quot;auto&quot;&gt;hw_server&lt;/code&gt; on a embedded device:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Install docker&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apt-get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apt-get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;upgrade&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-sSL&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://get.docker.com&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sh&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Start Docker&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;enable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--now&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;docker&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Enable qemu-user emulation support for running amd64 Docker images&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# *Note:* only required if your system arch is not amd64!&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--rm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--privileged&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aptman/qus&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-s&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x86_64&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Run the hw_server&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--restart&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unless-stopped&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--privileged&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--volume&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/dev/bus/usb:/dev/bus/usb&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--publish&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3121:3121&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--detach&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ghcr.io/stv0g/hw_server:v2021.2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This setup has been tested with a Raspberry Pi 4 running the new 64-bit Debian Bullseye Raspberry Pi OS.&lt;/p&gt;
&lt;p&gt;The pre-built Docker image for the &lt;code dir=&quot;auto&quot;&gt;hw_server&lt;/code&gt; of Vivado 2021.2 is available via:&lt;/p&gt;
&lt;center&gt;&lt;a href=&quot;https://codeberg.org/stv0g/xilinx-hw-server-docker/packages&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;b&gt;/stv0g/xilinx-hw-server-docker (Packages)&lt;/b&gt;  &lt;/a&gt; &lt;/center&gt;
&lt;p&gt;Detailed instructions can be found at Codeberg: &lt;a href=&quot;https://codeberg.org/stv0g/xilinx-hw-server-docker&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/xilinx-hw-server-docker&lt;/span&gt; &lt;/a&gt; .&lt;/p&gt;</content:encoded><category>Development</category><category>Docker</category><category>Linux</category><category>Xilinx</category><category>English</category><category>Project</category></item><item><title>Encrypted credentials for Amazon AWS command line client</title><link>https://0l.de/blog/2015/09/awscli-credentials-tfa/</link><guid isPermaLink="true">https://0l.de/blog/2015/09/awscli-credentials-tfa/</guid><pubDate>Wed, 09 Sep 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In this quick post I will show you how to use the password manager “&lt;a href=&quot;http://www.passwordstore.org&quot;&gt;password-store&lt;/a&gt;”&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; to securely store your credentials used by the Amazon Webservices &lt;a href=&quot;https://aws.amazon.com/cli/&quot;&gt;command line client&lt;/a&gt;.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/aws_cli.C_euehf4_Zu6JGY.webp&quot; srcset=&quot;/_astro/aws_cli.C_euehf4_Zu6JGY.webp 544w&quot; alt=&quot;AWS CLI Logo&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 544px) 544px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;544&quot; height=&quot;150&quot;&gt; &lt;button aria-label=&quot;Zoom image: AWS CLI Logo&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;AWS CLI Logo.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;The installation for Mac and Linux system is fairly easy:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;pip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;awscli&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The credentials are stored as key-value pairs inside a PGP-encrypted file.
Every time you call the AWS CLI tool, your keys will be decrypted and directly passed to the &lt;code dir=&quot;auto&quot;&gt;aws&lt;/code&gt; tool.&lt;/p&gt;
&lt;p&gt;Use &lt;code dir=&quot;auto&quot;&gt;pass&lt;/code&gt; to add your keys in the store:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;pass&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;edit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;providers/aws&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;An editor opens.
Use the following format:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;User: stv0g&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Access-Key: AKB3ASJGBS3GOMXK6KPSQ&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Secret-Key: vAAABn/PMAksd235gAs/FSshhr42dg2D4EY3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Add the following snippet to your &lt;code dir=&quot;auto&quot;&gt;~/.bashrc&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PASS&lt;/span&gt;&lt;span&gt;=$(&lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;providers/aws&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;AWS&lt;/span&gt;&lt;span&gt;=$(&lt;/span&gt;&lt;span&gt;which&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Start original aws executable with short-lived keys&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span&gt;=$(&lt;/span&gt;&lt;span&gt;sed&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-En&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;s/^Access-Key: (.*)/\1/p&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;$PASS&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;AWS_SECRET_ACCESS_KEY=&lt;/span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span&gt;sed&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-En&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;s/^Secret-Key: (.*)/\1/p&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;$PASS&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$AWS&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$@&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Then use the cli tool &lt;code dir=&quot;auto&quot;&gt;aws&lt;/code&gt; as usual:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;iam&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;list-access-keys&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;AccessKeyMetadata&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [ &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;UserName&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;stv0g&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;section data-footnotes=&quot;&quot;&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;I covered password-store already a few times earlier: &lt;a href=&quot;https://0l.de/blog/2015/06/ansible-credentials-tfa&quot;&gt;Use YubiKey and Password-store for Ansible credentials&lt;/a&gt;, &lt;a href=&quot;https://0l.de/blog/2015/06/hardware-security-token&quot;&gt;Workshop: Security Token&lt;/a&gt;. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>Linux</category><category>Script</category><category>TFA</category><category>English</category></item><item><title>Use Yubikey and Password-store for Ansible credentials</title><link>https://0l.de/blog/2015/06/ansible-credentials-tfa/</link><guid isPermaLink="true">https://0l.de/blog/2015/06/ansible-credentials-tfa/</guid><pubDate>Wed, 24 Jun 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I spent some time over the last months to improve the security of servers and passwords.
In doing so, I started to orchestrate my servers using a configuration management tool called &lt;strong&gt;&lt;a href=&quot;https://www.ansible.com/home&quot;&gt;Ansible&lt;/a&gt;&lt;/strong&gt;.
This allows me to spin-up fresh servers in a few seconds and to get rid of year-old, polluted and insecure system images.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/ansible_loves_yubico.uOhjQpqw_Z1Lg7T3.webp&quot; srcset=&quot;/_astro/ansible_loves_yubico.uOhjQpqw_2oMb2z.webp 640w, /_astro/ansible_loves_yubico.uOhjQpqw_ZTcEQI.webp 750w, /_astro/ansible_loves_yubico.uOhjQpqw_Z1Lg7T3.webp 789w&quot; alt=&quot;Ansible loves Yubico&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 789px) 789px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;789&quot; height=&quot;297&quot;&gt; &lt;button aria-label=&quot;Zoom image: Ansible loves Yubico&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Ansible loves Yubico.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;My ‘single password for everything’ has been replaced by a new password policy which enforces individual passwords for every single service.
This was easier than I previously expected:&lt;/p&gt;
&lt;p&gt;To unlock the ‘paranoid’ level, I additionally purchased a &lt;strong&gt;&lt;a href=&quot;https://www.yubico.com/products/yubikey-hardware/&quot;&gt;Yubikey&lt;/a&gt;&lt;/strong&gt; Neo token to handle the decryption of my login credentials in tamper-proof hardware.
‘&lt;strong&gt;&lt;a href=&quot;https://www.passwordstore.org/&quot;&gt;pass&lt;/a&gt;&lt;/strong&gt;’ is just a small shell script to glue several existing Unix tools together: Bash, pwgen, Git, xclip &amp;#x26; GnuPG (obeying the Unix philosophy).
The passwords are stored in simple text files which are encrypted by PGP and stored in a directory structure which is managed in a Git repository.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/IMG_20150526_121142.BxqbqHBT_ZIFDyz.webp&quot; srcset=&quot;/_astro/IMG_20150526_121142.BxqbqHBT_Seigi.webp 640w, /_astro/IMG_20150526_121142.BxqbqHBT_Z1a6ViP.webp 750w, /_astro/IMG_20150526_121142.BxqbqHBT_Zs9MTK.webp 828w, /_astro/IMG_20150526_121142.BxqbqHBT_Zf1M8G.webp 1080w, /_astro/IMG_20150526_121142.BxqbqHBT_Z1I60vU.webp 1280w, /_astro/IMG_20150526_121142.BxqbqHBT_ZT0X2B.webp 1668w, /_astro/IMG_20150526_121142.BxqbqHBT_ZoFD7M.webp 2048w, /_astro/IMG_20150526_121142.BxqbqHBT_ZIFDyz.webp 2448w&quot; alt=&quot;Yubikey Neo und Neo-n&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 2448px) 2448px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;2448&quot; height=&quot;3264&quot;&gt; &lt;button aria-label=&quot;Zoom image: Yubikey Neo und Neo-n&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Yubikey Neo und Neo-n.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;There are already a tons of tutorials which present the tools I describes above.
I do not want to repeat all of it.
So, this post is dedicated to solve some smaller issues I encountered.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;use-one-time-passwords-across-multiple-servers&quot;&gt;Use One-Time passwords across multiple servers&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The Yubikey Neo can do much more than decrypting static passwords via GnuPG:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generate passwords:
&lt;ul&gt;
&lt;li&gt;fixed string (&lt;strong&gt;insecure!&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;with Yubico OTP algorithm&lt;/li&gt;
&lt;li&gt;with OATH-HOTP algorithm&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Do challenge response authentication
&lt;ul&gt;
&lt;li&gt;via FIDO’s U2F standard&lt;/li&gt;
&lt;li&gt;with HMAC-SHA1 algorithm&lt;/li&gt;
&lt;li&gt;with Yubico OTP algorithm&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some third-party services already support FIDO U2F standard or traditional OATH-{H,T}OTP TFA, like used by the Google authenticator app.
I suggest to have a look at: &lt;a href=&quot;https://twofactorauth.org&quot;&gt;https://twofactorauth.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For private servers there are several PAM modules available to integrate OTP’s or Challenge Response (CR) methods.
Unfortunately, support for CR is not widespread across different SSH- and mail clients.&lt;/p&gt;
&lt;p&gt;So, you want to use OTP’s which leds to another problem: OTP’s rely on a synchronized counter between the hardware token and the server.
Once you use multiple servers, those must be synchronized as well.
I’m using a central Radius server to facilitate this.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;integrate-pass-into-your-ansible-workflow&quot;&gt;Integrate &lt;code dir=&quot;auto&quot;&gt;pass&lt;/code&gt; into your Ansible workflow&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Ansible uses SSH and Python scripts to manage several remote machines in parallel.
You must use key-based SSH authentication, because you do not want to type every password manually!
Additionally you need to get super user privileges for most of your administrative tasks on the remote machine.&lt;/p&gt;
&lt;p&gt;The SSH authentication is handled by gpg-agents &lt;code dir=&quot;auto&quot;&gt;--enable-ssh-support&lt;/code&gt; option and a PGP key on your token.&lt;/p&gt;
&lt;p&gt;To get super user privileges, I use the following variable declaration my Ansible &lt;code dir=&quot;auto&quot;&gt;group_vars/all&lt;/code&gt; file:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ansible_sudo_pass&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;{{ lookup(&apos;pipe&apos;, &apos;pass servers/&apos; + inventory_hostname) }}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;There is a separate root password for every server (e.g. &lt;code dir=&quot;auto&quot;&gt;pass servers/lian.0l.de&lt;/code&gt;).
I wrote some Ansible roles to easily and periodically rotate these passwords.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;integrate-pass-into-os-x&quot;&gt;Integrate ‘pass’ into OS X&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;There are already several plugins and extensions to integrate the &lt;code dir=&quot;auto&quot;&gt;pass&lt;/code&gt; password store into other Programs like Firefox and Android.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/pass_osx_prompt.D9qNhijV_57ekQ.webp&quot; srcset=&quot;/_astro/pass_osx_prompt.D9qNhijV_Z2ihHoS.webp 640w, /_astro/pass_osx_prompt.D9qNhijV_Z1Cif35.webp 750w, /_astro/pass_osx_prompt.D9qNhijV_Z18p3Ho.webp 828w, /_astro/pass_osx_prompt.D9qNhijV_57ekQ.webp 896w&quot; alt=&quot;A prompt for the password you want&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 896px) 896px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;896&quot; height=&quot;374&quot;&gt; &lt;button aria-label=&quot;Zoom image: A prompt for the password you want&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;A prompt for the password you want.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;I added support for OS X by writing a small AppleScript which can be found here: &lt;a href=&quot;https://github.com/zx2c4/password-store/blob/master/contrib/pass.applescript&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .3a12 12 0 0 0-3.8 23.38c.6.12.83-.26.83-.57L9 21.07c-3.34.72-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.08-.74.09-.73.09-.73 1.2.09 1.83 1.24 1.83 1.24 1.08 1.83 2.81 1.3 3.5 1 .1-.78.42-1.31.76-1.61-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.14-.3-.54-1.52.1-3.18 0 0 1-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.29-1.23 3.29-1.23.64 1.66.24 2.88.12 3.18a4.65 4.65 0 0 1 1.23 3.22c0 4.61-2.8 5.63-5.48 5.92.42.36.81 1.1.81 2.22l-.01 3.29c0 .31.2.69.82.57A12 12 0 0 0 12 .3Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/zx2c4/password-store/contrib/pass.applescript&lt;/span&gt; &lt;/a&gt; .&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/pass_osx_notification.Cyj1-no0_1gvijK.webp&quot; srcset=&quot;/_astro/pass_osx_notification.Cyj1-no0_3SHk8.webp 640w, /_astro/pass_osx_notification.Cyj1-no0_1gvijK.webp 684w&quot; alt=&quot;A notification with countdown&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 684px) 684px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;684&quot; height=&quot;162&quot;&gt; &lt;button aria-label=&quot;Zoom image: A notification with countdown&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;A notification with countdown.&lt;/figcaption&gt; &lt;/figure&gt;</content:encoded><category>Software</category><category>Linux</category><category>English</category><category>TFA</category></item><item><title>Workshop: Security Token</title><link>https://0l.de/blog/2015/06/hardware-security-token/</link><guid isPermaLink="true">https://0l.de/blog/2015/06/hardware-security-token/</guid><pubDate>Mon, 15 Jun 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Der Open Source Arbeitskreis (OSAK) der Fachschaft FSMPI, &lt;a href=&quot;https://osak.fsmpi.rwth-aachen.de/posts/2015-06-11-cryptoparty-programm.html&quot;&gt;veranstaltet nun zum zweiten Mal eine Crypto Party&lt;/a&gt; auf der sich Interessierte über Verschlüsselung und verwandte Themen informieren können.&lt;/p&gt;
&lt;p&gt;Ich möchte hier die Gelegenheit nutzen um etwas Werbung für diese Veranstaltung zu machen.
Genaue Infos findet Ihr unten im Flyer.&lt;/p&gt;
&lt;p&gt;Dieses Mal wird es auch einen kleinen Workshop von mir geben:&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;hardware-crypto-tokens&quot;&gt;Hardware Crypto Tokens&lt;/h2&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;„I know none of my passwords“&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ich werde in circa 20 Min eine kurze Übersicht über Security Tokens wie beispielsweise den &lt;a href=&quot;https://www.yubico.com/products/yubikey-hardware/yubikey-neo/&quot;&gt;Yubikey&lt;/a&gt; oder die &lt;a href=&quot;http://g10code.com/p-card.html&quot;&gt;OpenPGP Smartcard&lt;/a&gt; geben.
Dabei wird der Fokus auf verschiedenen Anwendungsszenarien wie One-Time-Passwords, Logins, sowie E-Mail Verschlüsselung liegen.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Hier sind die Vortragsfolien und das Handout:&lt;/p&gt;
&lt;center&gt; &lt;a download href=&quot;https://0l.de/blog/2015/06/hardware-security-token/HardwareCryptoTokens.pdf&quot;&gt;   &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M8.29 13.29a1 1 0 0 0 0 1.42l3 3a1 1 0 0 0 1.42 0l3-3a1 1 0 0 0-1.42-1.42L13 14.59V3a1 1 0 0 0-2 0v11.59l-1.29-1.3a1 1 0 0 0-1.42 0ZM18 9h-2a1 1 0 0 0 0 2h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-7a1 1 0 0 1 1-1h2a1 1 0 0 0 0-2H6a3 3 0 0 0-3 3v7a3 3 0 0 0 3 3h12a3 3 0 0 0 3-3v-7a3 3 0 0 0-3-3Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;b&gt;Download:&lt;/b&gt;Präsentation  &lt;/a&gt;  &lt;/center&gt;
&lt;center&gt; &lt;a download href=&quot;https://0l.de/blog/2015/06/hardware-security-token/HardwareCryptoTokens_Handout.pdf&quot;&gt;   &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M8.29 13.29a1 1 0 0 0 0 1.42l3 3a1 1 0 0 0 1.42 0l3-3a1 1 0 0 0-1.42-1.42L13 14.59V3a1 1 0 0 0-2 0v11.59l-1.29-1.3a1 1 0 0 0-1.42 0ZM18 9h-2a1 1 0 0 0 0 2h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-7a1 1 0 0 1 1-1h2a1 1 0 0 0 0-2H6a3 3 0 0 0-3 3v7a3 3 0 0 0 3 3h12a3 3 0 0 0 3-3v-7a3 3 0 0 0-3-3Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;b&gt;Download:&lt;/b&gt;Handout  &lt;/a&gt;  &lt;/center&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/cryptoparty-ss2015.B9DmGU_M_ZJlh5o.webp&quot; srcset=&quot;/_astro/cryptoparty-ss2015.B9DmGU_M_1u2IhS.webp 640w, /_astro/cryptoparty-ss2015.B9DmGU_M_fmCH2.webp 750w, /_astro/cryptoparty-ss2015.B9DmGU_M_ZX99nI.webp 828w, /_astro/cryptoparty-ss2015.B9DmGU_M_Z8Hlqw.webp 1080w, /_astro/cryptoparty-ss2015.B9DmGU_M_ZJlh5o.webp 1169w&quot; alt=&quot;Cryptoparty im Sommersemester 2015&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1169px) 1169px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1169&quot; height=&quot;1653&quot;&gt; &lt;button aria-label=&quot;Zoom image: Cryptoparty im Sommersemester 2015&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Cryptoparty im Sommersemester 2015.&lt;/figcaption&gt; &lt;/figure&gt;</content:encoded><category>crypto-party</category><category>Event</category><category>Workshop</category><category>Talk</category><category>Study</category><category>German</category><category>TFA</category></item><item><title>Casting between Qt and OpenCV primitives</title><link>https://0l.de/blog/2015/06/casting-qt-opencv/</link><guid isPermaLink="true">https://0l.de/blog/2015/06/casting-qt-opencv/</guid><pubDate>Sat, 13 Jun 2015 00:00:00 GMT</pubDate><content:encoded>&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/opencv_qt.BKsQG-Cw_Z1YSd02.webp&quot; srcset=&quot;/_astro/opencv_qt.BKsQG-Cw_Z1YSd02.webp 400w&quot; alt=&quot;OpenCV &amp;#x26; QT&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 400px) 400px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;400&quot; height=&quot;227&quot;&gt; &lt;button aria-label=&quot;Zoom image: OpenCV &amp;#x26; QT&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;OpenCV &amp;#x26; QT.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;As a follow-up to the previous post, I’d like to present some code which I think might be helpful for other Qt / OpenCV projects as well.&lt;/p&gt;
&lt;p&gt;This code was written for Pastie.
&lt;a href=&quot;https://codeberg.org/stv0g/pastie&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;Pastie&lt;/span&gt; &lt;/a&gt;  is a piece of software I wrote as part my &lt;a href=&quot;https://0l.de/blog/2015/05/seminar&quot;&gt;image processing seminar&lt;/a&gt;.
It makes use of the well known libraries:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;http://www.qt.io/&quot;&gt;Qt&lt;/a&gt;&lt;/strong&gt; for the graphical user interface&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;http://opencv.org/&quot;&gt;OpenCV&lt;/a&gt;&lt;/strong&gt; for image processing and computer vision&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wrote a C++ header file to facilitate the co-operation of those two libraries.
This file enables the conversion / casting of OpenCV and Qt types e.g.:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;QImage&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;cv/core.hpp&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;QImage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;qimg&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;filename.png&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;cv&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;Mat cvimg &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;toCv&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;qimg&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The source code is available at Codeberg: &lt;a href=&quot;https://codeberg.org/stv0g/snippets/src/master/c/qcv_cast.h&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/snippets/c/qcv_cast.h&lt;/span&gt; &lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;The following conversions are supported:&lt;/p&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qimage.html&quot;&gt;QImage&lt;/a&gt;&lt;/th&gt;&lt;th&gt;⇆&lt;/th&gt;&lt;th&gt;&lt;a href=&quot;http://docs.opencv.org/modules/core/doc/basic_structures.html#mat&quot;&gt;cv::Mat&lt;/a&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qtransform.html&quot;&gt;QTransform&lt;/a&gt;&lt;/td&gt;&lt;td&gt;⇆&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;http://docs.opencv.org/modules/core/doc/basic_structures.html#mat&quot;&gt;cv::Mat&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qpoint.html&quot;&gt;QPoint&lt;/a&gt;&lt;/td&gt;&lt;td&gt;⇆&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;http://docs.opencv.org/modules/core/doc/basic_structures.html#point&quot;&gt;cv::Point2i&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qpointf.html&quot;&gt;QPointF&lt;/a&gt;&lt;/td&gt;&lt;td&gt;⇆&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;http://docs.opencv.org/modules/core/doc/basic_structures.html#point&quot;&gt;cv::Point2f&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qrect.html&quot;&gt;QRect&lt;/a&gt;&lt;/td&gt;&lt;td&gt;⇆&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;http://docs.opencv.org/modules/core/doc/basic_structures.html#rect&quot;&gt;cv::Rect2i&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qrectf.html&quot;&gt;QRectF&lt;/a&gt;&lt;/td&gt;&lt;td&gt;⇆&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;http://docs.opencv.org/modules/core/doc/basic_structures.html#rect&quot;&gt;cv::Rect2f&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qsize.html&quot;&gt;QSize&lt;/a&gt;&lt;/td&gt;&lt;td&gt;⇆&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;http://docs.opencv.org/modules/core/doc/basic_structures.html#size&quot;&gt;cv::Size&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;You can find some examples in the real code here: &lt;a href=&quot;https://codeberg.org/stv0g/pastie/src/commit/8cca486a2caa000ea59fe76ee11626fbda880a0f/filters/pattern.cpp#L215&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/pastie/filters/pattern.cpp&lt;/span&gt; &lt;/a&gt;  and here &lt;a href=&quot;https://codeberg.org/stv0g/pastie/src/master/cast.h&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/pastie/cast.h&lt;/span&gt; &lt;/a&gt; .&lt;/p&gt;</content:encoded><category>Software</category><category>C++</category><category>Development</category><category>OpenCV</category><category>Qt</category><category>English</category></item><item><title>Seminar: Camera-based PCB Analysis for Solder Paste Dispensing</title><link>https://0l.de/blog/2015/05/seminar/</link><guid isPermaLink="true">https://0l.de/blog/2015/05/seminar/</guid><pubDate>Tue, 26 May 2015 00:00:00 GMT</pubDate><content:encoded>&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/mini_kossel_printer.az2u6P9R_Z12VP2W.webp&quot; srcset=&quot;/_astro/mini_kossel_printer.az2u6P9R_Z2eRdE9.webp 640w, /_astro/mini_kossel_printer.az2u6P9R_2sBus0.webp 750w, /_astro/mini_kossel_printer.az2u6P9R_2eNzeP.webp 828w, /_astro/mini_kossel_printer.az2u6P9R_Z19xljs.webp 1080w, /_astro/mini_kossel_printer.az2u6P9R_26tyMy.webp 1280w, /_astro/mini_kossel_printer.az2u6P9R_Z12VP2W.webp 1500w&quot; alt=&quot;Mini Kossel 3D Printer&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1500px) 1500px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1500&quot; height=&quot;1500&quot;&gt; &lt;button aria-label=&quot;Zoom image: Mini Kossel 3D Printer&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Mini Kossel 3D Printer.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;The lectures during my last semester were largely focused on digital image processing.
Combining this with the inspiration for 3D printing, I gathered through my trip though South Korea, resulted in the following seminar paper.
Seminars are a compulsory part of our curriculum which I like due the self-contained work and the ability to pick an individual topic.&lt;/p&gt;
&lt;p&gt;Over the past year, I’ve built my own Kossel 3D printer.
The Mini Kossel is based on a novel parallel delta kinematic which was developed by Johann C. Rocholl, a Google engineer from Germany.&lt;/p&gt;
&lt;p&gt;This paper is targeting the automation of solder paste dispensing onto printed circuit boards by using computer vision and RepRap robots.&lt;/p&gt;

&lt;center&gt; &lt;a download href=&quot;https://0l.de/blog/2015/05/seminar/Camera-based_Solder_Paste_Dispensing-Vogel-2014_Presentation_full.pdf&quot;&gt;   &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M8.29 13.29a1 1 0 0 0 0 1.42l3 3a1 1 0 0 0 1.42 0l3-3a1 1 0 0 0-1.42-1.42L13 14.59V3a1 1 0 0 0-2 0v11.59l-1.29-1.3a1 1 0 0 0-1.42 0ZM18 9h-2a1 1 0 0 0 0 2h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-7a1 1 0 0 1 1-1h2a1 1 0 0 0 0-2H6a3 3 0 0 0-3 3v7a3 3 0 0 0 3 3h12a3 3 0 0 0 3-3v-7a3 3 0 0 0-3-3Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;b&gt;Download:&lt;/b&gt;Presentation Slides  &lt;/a&gt;  &lt;/center&gt;
&lt;center&gt; &lt;a download href=&quot;https://0l.de/blog/2015/05/seminar/Camera-based_Solder_Paste_Dispensing-Vogel-2015_Docu.pdf&quot;&gt;   &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M8.29 13.29a1 1 0 0 0 0 1.42l3 3a1 1 0 0 0 1.42 0l3-3a1 1 0 0 0-1.42-1.42L13 14.59V3a1 1 0 0 0-2 0v11.59l-1.29-1.3a1 1 0 0 0-1.42 0ZM18 9h-2a1 1 0 0 0 0 2h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-7a1 1 0 0 1 1-1h2a1 1 0 0 0 0-2H6a3 3 0 0 0-3 3v7a3 3 0 0 0 3 3h12a3 3 0 0 0 3-3v-7a3 3 0 0 0-3-3Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;b&gt;Download:&lt;/b&gt;Full Paper  &lt;/a&gt;  &lt;/center&gt;
&lt;center&gt;&lt;a href=&quot;https://codeberg.org/stv0g/pastie&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;b&gt;Source Code&lt;/b&gt;  &lt;/a&gt; &lt;/center&gt;

&lt;div&gt;&lt;h2 id=&quot;seminar-image-processing-and-content-analysis&quot;&gt;Seminar: Image Processing and Content Analysis&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;camera-based-pcb-analysis-for-solder-paste-dispensing&quot;&gt;Camera-based PCB Analysis for Solder Paste Dispensing&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; Steffen Vogel (&lt;a href=&quot;mailto:steffen.vogel@rwth-aachen.de&quot;&gt;steffen.vogel@rwth-aachen.de&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Academic Advisor:&lt;/strong&gt; Wei Li (&lt;a href=&quot;mailto:wei.li@lfb.rwth-aachen.de&quot;&gt;wei.li@lfb.rwth-aachen.de&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Institute of Imaging &amp;#x26; Computer Vision (LfB)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Rheinisch-Westfälische Technische Hochschule (RWTH), 52056 Aachen&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;1-abstract&quot;&gt;1 Abstract&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Two of the main challenges for PCB prototyping are the time-consuming setup of involved machines and their economic feasibility for small laboratories and hobbyists.
This paper tries to offer solutions for both of these issues:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The complex setup process of industrial machines can be accelerated by computer vision. It is preferable to automate this process as far as possible to enable the operation by untrained personnel and hobbyists. The workflow can be further simplified by not relying on external CAD data. This includes: detection of components, pads and footprints; mapping between available components and footprints and planning of shortest tool paths.&lt;/li&gt;
&lt;li&gt;The adaption of proven 3D printers allows to lower the costs for such machines. The lightweight and fast kinematics of parallel 3D-delta robots like the RepRap Mini Kossel are perfectly suited for the assembly of PCBs. Only the print head has to be exchanged between the individual steps of the process.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This work presents a workflow to control DIY 3D printers for the purpose of PCB assembly.
By using cheap and easy-obtainable parts like proven RepRap 3D printers, this technique is viable for small laboratories, FabLabs and hobbyists.
During the seminar, a analysis and control software for RepRap printers was written.
Hence, we focus on the overall workflow and tools and less on algorithms and theory.
Here, the task of solder paste dispensing was chosen to be explored in detail.
This work establishes the groundwork for more complex task like the pick and placing of electronic components.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;2-motivation&quot;&gt;2 Motivation&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The ongoing miniaturization of electronic products like smartphones and Ultra Books has led to a new form factor for electronic components.
Surface-mounted devices (SMD) are already widespread in electronic design and production.
As a result, previously used through-hole components are gradually phased out.
This miniaturization of SMD components is an ongoing trend and raises the barrier for hobbyists to produce PCBs themselves.
Soldering and placement of 0401-sized resistors or BGA packages is not possible by hand any longer.&lt;/p&gt;
&lt;p&gt;This work is motivated by the vision to build an all-in-one machine for the complete process of prototype PCB assembly (PCBA).
To accelerate the development process and to reduce the costs, all of these tasks can be handled by a single workbench 3D printer / CNC mill.
The PCB production process roughly can consists of the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Isolation milling or pen plotting of PCB traces&lt;/li&gt;
&lt;li&gt;Drilling of holes and contours&lt;/li&gt;
&lt;li&gt;Solder paste dispensing for SMD pads with a syringe&lt;/li&gt;
&lt;li&gt;Pick-and-place of SMT components with vacuum&lt;/li&gt;
&lt;li&gt;Soldering with hot air, a hot plate or by a laser&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For the scope of this paper, the process of solder paste dispensing was chosen.
This task offers the biggest margin to profit from computer vision.
Industrial mass production uses stencils to apply solder paste onto the PCB.
For small prototype assemblies the fabrication of stencils is not worthwhile.
Therefore, solder paste is applied manually with a pressurized syringe, which is hold by hand.
The dispensing of solder paste requires the knowledge exact solder pad positions and dimensions.
Traditionally, this information is exported by CAD design tools and is required to produce the stencils.
But sometimes the CAD data is not available or stored in an inaccessible proprietary format.
This paper presents techniques to gather the pad locations and dimensions by means of computer vision.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/alternative_methods.wK4tsz8O_1pPAS1.webp&quot; srcset=&quot;/_astro/alternative_methods.wK4tsz8O_9c84E.webp 640w, /_astro/alternative_methods.wK4tsz8O_Z2ld1er.webp 750w, /_astro/alternative_methods.wK4tsz8O_23GOId.webp 828w, /_astro/alternative_methods.wK4tsz8O_2w3djK.webp 1080w, /_astro/alternative_methods.wK4tsz8O_Z2w1Jus.webp 1280w, /_astro/alternative_methods.wK4tsz8O_1pPAS1.webp 1504w&quot; alt=&quot;Figure 1: Solder paste dispensing techniques&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1504px) 1504px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1504&quot; height=&quot;582&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 1: Solder paste dispensing techniques&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 1: Solder paste dispensing techniques.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/smd0805.CBRuhIQc_YKVl8.webp&quot; srcset=&quot;/_astro/smd0805.CBRuhIQc_Z209xnI.webp 640w, /_astro/smd0805.CBRuhIQc_ZAU0Qx.webp 750w, /_astro/smd0805.CBRuhIQc_Z1MTJNz.webp 828w, /_astro/smd0805.CBRuhIQc_Z1tNSpi.webp 1080w, /_astro/smd0805.CBRuhIQc_1OFF7m.webp 1280w, /_astro/smd0805.CBRuhIQc_YKVl8.webp 1376w&quot; alt=&quot;Figure 2: 0805-sized resistor&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1376px) 1376px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1376&quot; height=&quot;398&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 2: 0805-sized resistor&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 2: 0805-sized resistor.&lt;/figcaption&gt; &lt;/figure&gt;

&lt;div&gt;&lt;h3 id=&quot;3-workflow&quot;&gt;3 Workflow&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The task of solder paste dispensing can be further separated in several sub stages, which are explained in the following sections.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/workflow.2wqIiMPF_LDzvO.webp&quot; srcset=&quot;/_astro/workflow.2wqIiMPF_CUK8f.webp 640w, /_astro/workflow.2wqIiMPF_ZRNuSi.webp 750w, /_astro/workflow.2wqIiMPF_ZB5FEY.webp 828w, /_astro/workflow.2wqIiMPF_1icL7M.webp 1080w, /_astro/workflow.2wqIiMPF_ZLV3TM.webp 1280w, /_astro/workflow.2wqIiMPF_Z2vGJdH.webp 1668w, /_astro/workflow.2wqIiMPF_LDzvO.webp 2004w&quot; alt=&quot;Workflow steps&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 2004px) 2004px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;2004&quot; height=&quot;1194&quot;&gt; &lt;button aria-label=&quot;Zoom image: Workflow steps&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Workflow steps.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;div&gt;&lt;h4 id=&quot;31-imaging&quot;&gt;3.1 Imaging&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;In the original proposal, a webcam was planed be used to capture images for further analysis.
But using other image sources like scanners or digital cameras has proven to provide superior image quality (see Table 1).
The resolution of a webcam is insufficient to capture the complete PCB in a single image.
Even with a high resolution webcam&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; satisfying results were only achievable by stitching several detailed shots together.
This issue can easily be resolved by using a professional digital camera (see Figure 3d).
However, this prevents the direct attachment of the camera to the print head of the printer, because the weight of a camera would increase the inertia and thereby limit the maximum speed of the printer.
The workflow does not require the image acquisition to be done on top of the working area of the printer.
By using cameras, all images are subject to distortion caused by lenses and perspective projection.
This issue can be solved by calibrating the camera and by applying the inverse perspective transformation.
These disadvantages can be avoided by using an imaging method which does not impose these distortions like a flatbed scanner.
First tests showed biased results (see Figure 3c and 3a).
The previous methods do not rely on the existence of CAD layout data.
In the end, best results can be achieved by directly using available CAD data (see Figure 3b).
The industry uses a widespread format called Gerber for exchanging PCB layouts used for production.
Almost every CAD tool can export PCB layouts as a Gerber file.
This Gerber format stores every part of the design (silkscreen, pads, board contour, milling, coper) in a separate layer.
Basically it is a vector graphic format, whose layers are built out of basic geometric shapes.
This allows them to be rendered to raster images of arbitrary resolutions&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/imaging_examples.sKykrAUI_Z2eokIX.webp&quot; srcset=&quot;/_astro/imaging_examples.sKykrAUI_Z23eweb.webp 640w, /_astro/imaging_examples.sKykrAUI_dsHA.webp 750w, /_astro/imaging_examples.sKykrAUI_nTVYO.webp 828w, /_astro/imaging_examples.sKykrAUI_ZiAQod.webp 1080w, /_astro/imaging_examples.sKykrAUI_qWqWh.webp 1280w, /_astro/imaging_examples.sKykrAUI_Z1f6PFE.webp 1668w, /_astro/imaging_examples.sKykrAUI_Z2eokIX.webp 1772w&quot; alt=&quot;Figure 3: Imaging methods for PCBs&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1772px) 1772px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1772&quot; height=&quot;1440&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 3: Imaging methods for PCBs&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 3: Imaging methods for PCBs.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/imaging_sources.BIF6Bvx6_1N1aXm.webp&quot; srcset=&quot;/_astro/imaging_sources.BIF6Bvx6_Zx7H8c.webp 640w, /_astro/imaging_sources.BIF6Bvx6_1dTrX4.webp 750w, /_astro/imaging_sources.BIF6Bvx6_wKG1h.webp 828w, /_astro/imaging_sources.BIF6Bvx6_4sJvU.webp 1080w, /_astro/imaging_sources.BIF6Bvx6_Z1jYFhD.webp 1280w, /_astro/imaging_sources.BIF6Bvx6_1N1aXm.webp 1668w&quot; alt=&quot;Table 1: Image sources for PCB analysis&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1668px) 1668px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1668&quot; height=&quot;256&quot;&gt; &lt;button aria-label=&quot;Zoom image: Table 1: Image sources for PCB analysis&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Table 1: Image sources for PCB analysis.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;div&gt;&lt;h4 id=&quot;32-undistortion&quot;&gt;3.2 Undistortion&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;Camera-based imaging methods are subject to distortions caused by optical lenses.
These non-linear distortions must be compensated by camera calibration.
During the camera calibration, a set of distortion parameters and a camera matrix is determined.
Usually, a set of different views of a known pattern is used to measure the distortion coefficients.
In this seminar, both chessboard and circle patterns were used.
But it has become apparent, that non-linear distortions are mostly negligible when using recent DSLRs because most of them already compensate them by their internal image processing pipeline.
The workflow involves several different coordinate systems (&lt;strong&gt;C&lt;/strong&gt;, &lt;strong&gt;U&lt;/strong&gt;, &lt;strong&gt;R&lt;/strong&gt;, &lt;strong&gt;S&lt;/strong&gt;, &lt;strong&gt;P&lt;/strong&gt;).
This stage transforms the source image from the camera coordinate system &lt;strong&gt;C&lt;/strong&gt; to the system of undistorted images &lt;strong&gt;U&lt;/strong&gt;.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/coordinate-systems-transparent.D4YCnPWm_Z2oufwX.webp&quot; srcset=&quot;/_astro/coordinate-systems-transparent.D4YCnPWm_ZACMfA.webp 640w, /_astro/coordinate-systems-transparent.D4YCnPWm_1g1Hk2.webp 750w, /_astro/coordinate-systems-transparent.D4YCnPWm_Z1BBXgL.webp 828w, /_astro/coordinate-systems-transparent.D4YCnPWm_Z17zify.webp 1080w, /_astro/coordinate-systems-transparent.D4YCnPWm_6rLb6.webp 1280w, /_astro/coordinate-systems-transparent.D4YCnPWm_Z2hPhwS.webp 1668w, /_astro/coordinate-systems-transparent.D4YCnPWm_Z2oufwX.webp 1688w&quot; alt=&quot;Figure 6: Coordinates systems and transformations&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1688px) 1688px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1688&quot; height=&quot;1034&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 6: Coordinates systems and transformations&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 6: Coordinates systems and transformations.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;div&gt;&lt;h4 id=&quot;33-perspective-correction&quot;&gt;3.3 Perspective Correction&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;Camera-based imaging methods are also subject to perspective projection.
The following analysis demands a top view onto the PCB.
Thus, the perspective projection is turned into a two-dimensional euclidean plane.
To simplify the correction, we assume that the PCB has a rectangular shape with known dimensions (w × h).
This can be realized by enclosing the PCB with a set of four markers which are arranged in a rectangle as shown in Figure 9a.
The camera projection warps this rectangle into a quadrilateral shape.
Mathematically, this is described by a perspective transformation between two coordinate systems.
The undistorted image with coordinate system &lt;strong&gt;U&lt;/strong&gt; has to be mapped to the reference system &lt;strong&gt;R&lt;/strong&gt;.
The required transformation matrix is obtained by solving equation 1 with four points x of the image plane and their matching counterparts x′ of the object plane.
The points of the object plane are given by the known dimensions and spacings of the markers or PCB&lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot; id=&quot;user-content-fnref-3&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.
In other words, respective markers are used to describe basis vectors for the reference coordinate system.
Figure 9a shows the original image with the detected markers.
Figure 9b shows the same image after the correction.
Note that the markers are still partially visible in the corners of the warped image.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/equation1.Dzz4t1Fg_1wM3iv.webp&quot; srcset=&quot;/_astro/equation1.Dzz4t1Fg_1aV8hV.webp 640w, /_astro/equation1.Dzz4t1Fg_ZcTOR3.webp 750w, /_astro/equation1.Dzz4t1Fg_Z1nbk9J.webp 828w, /_astro/equation1.Dzz4t1Fg_1BLCpj.webp 1080w, /_astro/equation1.Dzz4t1Fg_Z1phOi2.webp 1280w, /_astro/equation1.Dzz4t1Fg_ZLlcxT.webp 1668w, /_astro/equation1.Dzz4t1Fg_1wM3iv.webp 1764w&quot; alt=&quot;Gleichungen 1&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1764px) 1764px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1764&quot; height=&quot;818&quot;&gt; &lt;button aria-label=&quot;Zoom image: Gleichungen 1&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt;  &lt;/figure&gt;
&lt;div&gt;&lt;h4 id=&quot;34-preprocessing&quot;&gt;3.4 Preprocessing&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;The previous steps are mandatory for camera based imaging methods.
Scans or CAD imported Gerber files already provide a top view onto the PCB, and therefore, allow skipping the previous stages.
Before starting with the segmentation of PCB solder joints, several preprocessing steps have to be executed.
They improve the results of the following steps or allow saving computational time.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Blurring:&lt;/strong&gt; The segmentation relies on clustering and thresholding to detect solder joints. A prior smoothing of the image helps to cope with noise in the source image.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scaling:&lt;/strong&gt; To reduce the required computational time, the source image is restricted to a sufficient resolution. In rare cases the resolution of the source image is too low for further analysis. In this case, the image is scaled up. This way the following algorithms can work with sub-pixel accuracy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alignment:&lt;/strong&gt; Subsequent steps are using morphological image operations to improve the results. These operations are using square-shaped kernels. By aligning the orientation of the PCB and its pads to the shape of the kernel, details and sharp edges of PCB pads are preserved. Furthermore, certain algorithms like the Harris edge detector can profit from known orientations of the vertices. The alignment can be identified by evaluation of Hough lines or the polar magnitude spectrum of and FFT (see [BreierLfB]).&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h4 id=&quot;35-segmentation&quot;&gt;3.5 Segmentation&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;To separate the solder pads from the remaining PCB and the background, a color-based segmentation method is used.
The K-Means clustering algorithm reduces the color space to k clusters.
Usually, these classes correspondent to four portions of the PCB.
These portions are ordered according to their occurrences in the image.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Image background&lt;/li&gt;
&lt;li&gt;PCB base material (solder mask)&lt;/li&gt;
&lt;li&gt;Solder pads&lt;/li&gt;
&lt;li&gt;Silkscreen&lt;sup&gt;&lt;a href=&quot;#user-content-fn-4&quot; id=&quot;user-content-fnref-4&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hence, it makes sense to use k = 4 for the algorithm.
Figure 10a shows the result of the K-Means algorithm.
The correct selection of the solder pad class is crucial for valid results.
Therefore, it is advisable to make use of more criteria for its selection.
The current implementation only consults the frequency of each class.
Additionally, the amount of connected objects per class might be used.
The background and base material classes often only consist of a few connected objects.
The solder pad class in contrast often has hundreds of individual objects.
Once a class has been selected (potentially by hand), a binary image is created.
The resulting binary image is shown in Figure 10b.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;36-pad-detection--filtering&quot;&gt;3.6 Pad Detection &amp;#x26; Filtering&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;For solder paste dispensing, solder pad coordinates must be exactly located onto the PCB.
In this paper, the detection is limited to pads with a rectangular shape as shown in Figure 2b.
This limitation is negligible for most SMD packages, as they generally are using rectangular pads like shown in Figure 4.
The previous segmentation step produces in a binary image.
This image is used to find contours, which are then used to analyze the shape of the individual objects.
These contours are filtered and classified by the following criteria:&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/smd_pads.DSwhzXfn_Z1w3D0K.webp&quot; srcset=&quot;/_astro/smd_pads.DSwhzXfn_rCWmu.webp 640w, /_astro/smd_pads.DSwhzXfn_Z1NXMNW.webp 750w, /_astro/smd_pads.DSwhzXfn_2IcDk.webp 828w, /_astro/smd_pads.DSwhzXfn_ZvOB4.webp 1080w, /_astro/smd_pads.DSwhzXfn_Z15cAEc.webp 1280w, /_astro/smd_pads.DSwhzXfn_Z68Fjw.webp 1668w, /_astro/smd_pads.DSwhzXfn_1bVr14.webp 2048w, /_astro/smd_pads.DSwhzXfn_Z1w3D0K.webp 2148w&quot; alt=&quot;Figure 4: Footprints of various SMD packages&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 2148px) 2148px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;2148&quot; height=&quot;536&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 4: Footprints of various SMD packages&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 4: Footprints of various SMD packages.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/bounding_rect.JwCeixEL_Z1JrDr1.webp&quot; srcset=&quot;/_astro/bounding_rect.JwCeixEL_1Q3liy.webp 640w, /_astro/bounding_rect.JwCeixEL_13YXc1.webp 750w, /_astro/bounding_rect.JwCeixEL_Z1JrDr1.webp 770w&quot; alt=&quot;Figure 5: Pad contour with minimum bounding rectangle&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 770px) 770px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;770&quot; height=&quot;638&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 5: Pad contour with minimum bounding rectangle&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 5: Pad contour with minimum bounding rectangle.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;In a first attempt, polygons were used to approximate the contour.
The Ramer-Douglas-Peucker algorithm finds a polygon with as little as possible vertices.
At the same time, the maximum deviation to the original contour is limited by a threshold.
To qualify the contour as a solder pad, the approximated polygon must be a quadrangle, convex and the angles must be close to 90 degrees.
This approach only delivered unsatisfying results because of the low resolution and random starting points of the contours, which do not coincide with the corners of the rectangle.
Better results can be achieved by comparing the enclosed area of a contour with the area of its minimal bounding rectangle (see Figure 5).
A ratio above 0.8 usually yields a usable hit rate.
Figure 10c shows the found rectangles (magenta frames).
Subsequently, the rectangles are filtered by their absolute area and aspect ratio.
Overlapping rectangles are not allowed and are filtered out as well.
Figure 10d shows the pads after these plausibility checks.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;37-tool-path-planning&quot;&gt;3.7 Tool Path Planning&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;To speed-up the execution, the pads have to be arrange in an order which results in a path with the minimum length.
To find an optimal tool path, a Hamiltonian path with minimum length must be determined.
A Hamiltonian path connects all vertices of a graph.
We can think of the set of detected pads as a fully connected graph.
Each edge is weighted by the euclidean distance between the connected edges.
This problem description is a little different to other well known problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Traveling Salesman Problem:&lt;/strong&gt; The TSP looks for the shortest Hamiltonian cycle (equal start end end nodes). For apply the solder paste, this constraint is dispensable. Apart from that, the TSP describes the problem quiet well. Most TSP solvers are designed for huge problem sizes (&gt; 1000). This does not fit to our problem where usually 100-400 pads must be visited.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shortest Path Problem:&lt;/strong&gt; There is a large amount of algorithms which find the shortest path between two vertices of a graph. This problem usually is faced for navigation. The Dijkstra algorithm is a well known representative in this category. The shortest path problem only describes the shortest path between two vertices of a graph and is therefore not suitable for the described case.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For this task, a simple nearest neighbor heuristic (NNR) was implemented.
This heuristic starts with a random vertex and successively travels along the edge with the lowest weight, which corresponds to the nearest neighbor.
However, this procedure will not result in an optimal path.
The results can be easily improved by repeating the heuristic with different start vertices.
Finally, the one which results in the minimal length is selected.
This is known as the repetitive nearest neighbor (RNNR).
Figure 10e shows the final result with the found path as an overlay.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;38-robot-control&quot;&gt;3.8 Robot Control&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;Equation 1 shows the transformation between the undistorted camera images and reference coordinates.
Similarly, another transformation between the reference system and the robot coordinate system is necessary.&lt;/p&gt;
&lt;p&gt;Both the reference system &lt;strong&gt;R&lt;/strong&gt; and the printer system &lt;strong&gt;P&lt;/strong&gt; are two dimensional euclidean planes.
We can map points (pads) from the reference system by scaling, rotating and translating them.
Mathematically, this can be modeled by an affine transformation&lt;sup&gt;&lt;a href=&quot;#user-content-fn-5&quot; id=&quot;user-content-fnref-5&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/equation2.CaUc0QM9_1q30EV.webp&quot; srcset=&quot;/_astro/equation2.CaUc0QM9_ZNN0I1.webp 640w, /_astro/equation2.CaUc0QM9_OdYHv.webp 750w, /_astro/equation2.CaUc0QM9_1x7srD.webp 828w, /_astro/equation2.CaUc0QM9_1nGSED.webp 1080w, /_astro/equation2.CaUc0QM9_Z2emYs3.webp 1280w, /_astro/equation2.CaUc0QM9_1q30EV.webp 1428w&quot; alt=&quot;Gleichungen 2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1428px) 1428px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1428&quot; height=&quot;718&quot;&gt; &lt;button aria-label=&quot;Zoom image: Gleichungen 2&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt;  &lt;/figure&gt;
&lt;p&gt;The coordinates of the reference markers xi are given by the corners of the processed image.
The robot calibration points x′i have to be determined manually by aligning the printhead with markers of on the PCB, which is positioned on its working area.
Once the print head is positioned over the marker (or corner of the PCB), the related printer coordinates are requested from the printer controller.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;4-system-description&quot;&gt;4 System Description&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;This section shortly describes the overall system design and used hardware.
The system consists of a modified 3D printer which is capable to extrude solder paste&lt;sup&gt;&lt;a href=&quot;#user-content-fn-6&quot; id=&quot;user-content-fnref-6&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; and a common digital camera.
Additionally, a laptop, PC or embedded system is used to carry out the computation.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;41-camera-olympus-om-d-e-m10&quot;&gt;4.1 Camera: Olympus OM-D E-M10&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;As shown in Table 1, digital cameras offer the best image quality and flexibility.
Good lighting is crucial for satisfactory results.
Shadows, uneven exposure and reflexions are the main issues during the analysis.
The results in this paper we produced with a dedicated flash to provide indirect and diffuse illumination.
For enhanced usability, the camera can be connected via WiFi to the PC.
This allows remote control and image retrieval from the camera.
A dedicated library called libqt-omd&lt;sup&gt;&lt;a href=&quot;#user-content-fn-7&quot; id=&quot;user-content-fnref-7&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; is currently developed by the author.
Integration in the analysis software is planned.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;42-software-pastie&quot;&gt;4.2 Software: Pastie&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;The previously described workflow has been implemented in a graphical application named ”Pastie”&lt;sup&gt;&lt;a href=&quot;#user-content-fn-8&quot; id=&quot;user-content-fnref-8&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;.
For adequate performance, the tool was developed by using C++11 and specialized libraries.
The graphical user interface (GUI) is based on Qt 5.4. Computer vision and image processing is handled by OpenCV 3.0.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/pastie_screenshot_1.C7VJu2CV_FBWw9.webp&quot; srcset=&quot;/_astro/pastie_screenshot_1.C7VJu2CV_1wC1f5.webp 640w, /_astro/pastie_screenshot_1.C7VJu2CV_Z1T02YV.webp 750w, /_astro/pastie_screenshot_1.C7VJu2CV_2lbR61.webp 828w, /_astro/pastie_screenshot_1.C7VJu2CV_Zm630z.webp 1080w, /_astro/pastie_screenshot_1.C7VJu2CV_Zqu4px.webp 1280w, /_astro/pastie_screenshot_1.C7VJu2CV_4pgDz.webp 1668w, /_astro/pastie_screenshot_1.C7VJu2CV_UHwtp.webp 2048w, /_astro/pastie_screenshot_1.C7VJu2CV_1aDr0w.webp 2560w, /_astro/pastie_screenshot_1.C7VJu2CV_FBWw9.webp 2880w&quot; alt=&quot;Pastie Screenshot 1&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 2880px) 2880px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;2880&quot; height=&quot;1666&quot;&gt; &lt;button aria-label=&quot;Zoom image: Pastie Screenshot 1&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Pastie Screenshot 1.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/pastie_screenshot_7.CjCtQw7C_gmm9.webp&quot; srcset=&quot;/_astro/pastie_screenshot_7.CjCtQw7C_ZxAkaf.webp 640w, /_astro/pastie_screenshot_7.CjCtQw7C_ZJbBYR.webp 750w, /_astro/pastie_screenshot_7.CjCtQw7C_Z1zbPHQ.webp 828w, /_astro/pastie_screenshot_7.CjCtQw7C_1C9hU.webp 1080w, /_astro/pastie_screenshot_7.CjCtQw7C_11iUlr.webp 1280w, /_astro/pastie_screenshot_7.CjCtQw7C_s8sW4.webp 1668w, /_astro/pastie_screenshot_7.CjCtQw7C_flVjp.webp 2048w, /_astro/pastie_screenshot_7.CjCtQw7C_Z1yyfG4.webp 2560w, /_astro/pastie_screenshot_7.CjCtQw7C_gmm9.webp 2880w&quot; alt=&quot;Pastie Screenshot 2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 2880px) 2880px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;2880&quot; height=&quot;1664&quot;&gt; &lt;button aria-label=&quot;Zoom image: Pastie Screenshot 2&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Pastie Screenshot 2.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/pastie_screenshot_6.CMBqzLkM_pIq0G.webp&quot; srcset=&quot;/_astro/pastie_screenshot_6.CMBqzLkM_2fkq6B.webp 640w, /_astro/pastie_screenshot_6.CMBqzLkM_23J8gY.webp 750w, /_astro/pastie_screenshot_6.CMBqzLkM_1dITy0.webp 828w, /_astro/pastie_screenshot_6.CMBqzLkM_r5cVs.webp 1080w, /_astro/pastie_screenshot_6.CMBqzLkM_1qKXYY.webp 1280w, /_astro/pastie_screenshot_6.CMBqzLkM_RAwAB.webp 1668w, /_astro/pastie_screenshot_6.CMBqzLkM_ENYWW.webp 2048w, /_astro/pastie_screenshot_6.CMBqzLkM_Z196c2w.webp 2560w, /_astro/pastie_screenshot_6.CMBqzLkM_pIq0G.webp 2880w&quot; alt=&quot;Pastie Screenshot 3&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 2880px) 2880px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;2880&quot; height=&quot;1664&quot;&gt; &lt;button aria-label=&quot;Zoom image: Pastie Screenshot 3&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Pastie Screenshot 3.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;Thanks to Qt and OpenCV as the only dependencies, the tool is portable and can run on many architectures.
The implementation was tested on Windows, Linux and Mac OS X.
Theoretically it should be capable to run on Android and iOS as well.
The software offers a front-end to most common OpenCV algorithms.
It allows creating a filter pipeline and interactively adjusting parameters of the involved algorithms.
Processing an image with the presented pipeline takes about 5-10 seconds depending on the resolution.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;43-printer-reprap-mini-kossel&quot;&gt;4.3 Printer: RepRap Mini Kossel&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;The RepRap project is a community effort to develop cheap and self-replicating 3D printers using commonly available parts and tools.
In this work a relatively new style of printer called Mini Kossel was used.
This printer consist of three towers which are arranged in an equilateral triangle.
This delta kinematic allows movements of the tool center point (TCP) in all three directions with an accuracy of 100 steps/mm.
This is perfectly sufficient for placing even tiny 0603 components.
The RepRap project develops printer hardware as well as electronics and controller firmware.
For the purpose of this work only the toolhead must exchanged.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/mini_kossel.BW8w-HOE_ZS9H3v.webp&quot; srcset=&quot;/_astro/mini_kossel.BW8w-HOE_1RW6Lu.webp 640w, /_astro/mini_kossel.BW8w-HOE_2uGstk.webp 750w, /_astro/mini_kossel.BW8w-HOE_Z1N1rr7.webp 828w, /_astro/mini_kossel.BW8w-HOE_LQccU.webp 1080w, /_astro/mini_kossel.BW8w-HOE_m8Q0q.webp 1280w, /_astro/mini_kossel.BW8w-HOE_DcdVs.webp 1668w, /_astro/mini_kossel.BW8w-HOE_ZS9H3v.webp 1820w&quot; alt=&quot;RepRap Kossel Mini 3D printer&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1820px) 1820px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1820&quot; height=&quot;1038&quot;&gt; &lt;button aria-label=&quot;Zoom image: RepRap Kossel Mini 3D printer&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;RepRap Kossel Mini 3D printer.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;Similar to the camera, recent printer electronics allow a wireless connection over WiFi to schedule prints, adjusting settings or for visual inspection of the process with a webcam&lt;sup&gt;&lt;a href=&quot;#user-content-fn-9&quot; id=&quot;user-content-fnref-9&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;The printer is controlled with G-Code, a human readable language to control CNC mills, lathes, 3D printers and laser cutters.
Listing 8 shows a typical excerpt of a G-Code program.
Every line correspondents to one instruction and consists of at least one tuple.
The first tuple of every line describes the operation (move, stop, set settings).
Following tuples are optional parameters whose meaning is depending on the operation.
Every class of machine has their of dialect of G-Code.
The RepRep community agreed on a dialect for 3D printers&lt;sup&gt;&lt;a href=&quot;#user-content-fn-10&quot; id=&quot;user-content-fnref-10&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;10&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;figure width=&quot;200&quot;&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;M204  S1000 Z100 E500 ; set acceleration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;G28                   ; home all axes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;G29                   ; calibrate bed&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;GO X10 Y-5 F100       ¡ move to x=10, y=-5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;M112                  ; emergency stop&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;figcaption&gt;Figure 8: Excerpt of a G-Code program.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;div&gt;&lt;h3 id=&quot;5-results&quot;&gt;5 Results&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The following images are showing the intermediate steps of the processing pipeline which is described in Section 3.
The results have been produces with the Pastie tool.
It comes with a variety of more PCB images, scans and Gerber files which have been collected during this seminar.&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/omd2_P1110001_2.DB5Kmk_c_fe05m.webp&quot; srcset=&quot;/_astro/omd2_P1110001_2.DB5Kmk_c_Z4hO9I.webp 640w, /_astro/omd2_P1110001_2.DB5Kmk_c_2pBCiu.webp 750w, /_astro/omd2_P1110001_2.DB5Kmk_c_Z1UXz1P.webp 828w, /_astro/omd2_P1110001_2.DB5Kmk_c_53x1u.webp 1080w, /_astro/omd2_P1110001_2.DB5Kmk_c_10h4RD.webp 1280w, /_astro/omd2_P1110001_2.DB5Kmk_c_1h4Ds1.webp 1668w, /_astro/omd2_P1110001_2.DB5Kmk_c_Z2eSxDn.webp 2048w, /_astro/omd2_P1110001_2.DB5Kmk_c_Z2qnyIg.webp 2560w, /_astro/omd2_P1110001_2.DB5Kmk_c_fe05m.webp 4608w&quot; alt=&quot;Figure 9a: Source image with detected pattern&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 4608px) 4608px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;4608&quot; height=&quot;3456&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 9a: Source image with detected pattern&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 9a: Source image with detected pattern.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/omd2_P1110001_3.D0KVR72l_ZcqTdt.webp&quot; srcset=&quot;/_astro/omd2_P1110001_3.D0KVR72l_NR2p5.webp 640w, /_astro/omd2_P1110001_3.D0KVR72l_Z2pYtFn.webp 750w, /_astro/omd2_P1110001_3.D0KVR72l_ZQokz6.webp 828w, /_astro/omd2_P1110001_3.D0KVR72l_ZY7VWY.webp 1080w, /_astro/omd2_P1110001_3.D0KVR72l_Z58Ayp.webp 1280w, /_astro/omd2_P1110001_3.D0KVR72l_Z1NGlD5.webp 1668w, /_astro/omd2_P1110001_3.D0KVR72l_1Rw2wC.webp 2048w, /_astro/omd2_P1110001_3.D0KVR72l_1HePHH.webp 2560w, /_astro/omd2_P1110001_3.D0KVR72l_ZcqTdt.webp 3522w&quot; alt=&quot;Figure 9b: Perspective correction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 3522px) 3522px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;3522&quot; height=&quot;2279&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 9b: Perspective correction&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 9b: Perspective correction.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/omd2_P1110001_4_rotated.BYVygxmU_Z1M8EaC.webp&quot; srcset=&quot;/_astro/omd2_P1110001_4_rotated.BYVygxmU_Z1zkR70.webp 640w, /_astro/omd2_P1110001_4_rotated.BYVygxmU_1QWgtr.webp 750w, /_astro/omd2_P1110001_4_rotated.BYVygxmU_1H0Sm0.webp 828w, /_astro/omd2_P1110001_4_rotated.BYVygxmU_JEuyp.webp 1080w, /_astro/omd2_P1110001_4_rotated.BYVygxmU_bqYe5.webp 1280w, /_astro/omd2_P1110001_4_rotated.BYVygxmU_12UTks.webp 1668w, /_astro/omd2_P1110001_4_rotated.BYVygxmU_2x5xk9.webp 2048w, /_astro/omd2_P1110001_4_rotated.BYVygxmU_ngyBW.webp 2560w, /_astro/omd2_P1110001_4_rotated.BYVygxmU_Z1M8EaC.webp 3192w&quot; alt=&quot;Figure 10a: K-Means color clustering (ROI, k=4)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 3192px) 3192px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;3192&quot; height=&quot;540&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 10a: K-Means color clustering (ROI, k=4)&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 10a: K-Means color clustering (ROI, k=4).&lt;/figcaption&gt; &lt;/figure&gt;
&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/omd2_P1110001_5_rotated.CbVSJXgd_1g3kaS.webp&quot; srcset=&quot;/_astro/omd2_P1110001_5_rotated.CbVSJXgd_2rRcai.webp 640w, /_astro/omd2_P1110001_5_rotated.CbVSJXgd_NXbVN.webp 750w, /_astro/omd2_P1110001_5_rotated.CbVSJXgd_E1NOm.webp 828w, /_astro/omd2_P1110001_5_rotated.CbVSJXgd_Z1fEV6N.webp 1080w, /_astro/omd2_P1110001_5_rotated.CbVSJXgd_Z1NSrr8.webp 1280w, /_astro/omd2_P1110001_5_rotated.CbVSJXgd_ZKaQOB.webp 1668w, /_astro/omd2_P1110001_5_rotated.CbVSJXgd_IXLa5.webp 2048w, /_astro/omd2_P1110001_5_rotated.CbVSJXgd_Z1pPcx7.webp 2560w, /_astro/omd2_P1110001_5_rotated.CbVSJXgd_1g3kaS.webp 3188w&quot; alt=&quot;Figure 10b: Color/class filter (ROI)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 3188px) 3188px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;3188&quot; height=&quot;540&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 10b: Color/class filter (ROI)&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 10b: Color/class filter (ROI).&lt;/figcaption&gt; &lt;/figure&gt;
&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/omd2_P1110001_6_rotated.DgjyKZq6_ZxQjwC.webp&quot; srcset=&quot;/_astro/omd2_P1110001_6_rotated.DgjyKZq6_Z140Twl.webp 640w, /_astro/omd2_P1110001_6_rotated.DgjyKZq6_2nhe46.webp 750w, /_astro/omd2_P1110001_6_rotated.DgjyKZq6_2dkPVE.webp 828w, /_astro/omd2_P1110001_6_rotated.DgjyKZq6_1BquJ5.webp 1080w, /_astro/omd2_P1110001_6_rotated.DgjyKZq6_13cYoK.webp 1280w, /_astro/omd2_P1110001_6_rotated.DgjyKZq6_26Uz1h.webp 1668w, /_astro/omd2_P1110001_6_rotated.DgjyKZq6_Z29nsnE.webp 2048w, /_astro/omd2_P1110001_6_rotated.DgjyKZq6_1DtSNU.webp 2560w, /_astro/omd2_P1110001_6_rotated.DgjyKZq6_ZxQjwC.webp 3184w&quot; alt=&quot;Figure 10c: Pad/rectangle detection (ROI)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 3184px) 3184px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;3184&quot; height=&quot;544&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 10c: Pad/rectangle detection (ROI)&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 10c: Pad/rectangle detection (ROI).&lt;/figcaption&gt; &lt;/figure&gt;
&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/omd2_P1110001_7_rotated.BLaRx1xt_hoNpG.webp&quot; srcset=&quot;/_astro/omd2_P1110001_7_rotated.BLaRx1xt_iSPC0.webp 640w, /_astro/omd2_P1110001_7_rotated.BLaRx1xt_CFtSD.webp 750w, /_astro/omd2_P1110001_7_rotated.BLaRx1xt_YtxAt.webp 828w, /_astro/omd2_P1110001_7_rotated.BLaRx1xt_Z26Gkp6.webp 1080w, /_astro/omd2_P1110001_7_rotated.BLaRx1xt_2phi4v.webp 1280w, /_astro/omd2_P1110001_7_rotated.BLaRx1xt_Z189o3m.webp 1668w, /_astro/omd2_P1110001_7_rotated.BLaRx1xt_ZvtW9v.webp 2048w, /_astro/omd2_P1110001_7_rotated.BLaRx1xt_Z2cg3Ma.webp 2560w, /_astro/omd2_P1110001_7_rotated.BLaRx1xt_hoNpG.webp 3188w&quot; alt=&quot;Figure 10d: Filtered pads (ROI)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 3188px) 3188px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;3188&quot; height=&quot;532&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 10d: Filtered pads (ROI)&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 10d: Filtered pads (ROI).&lt;/figcaption&gt; &lt;/figure&gt;
&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/omd2_P1110001_8_rotated.jWON2_Ex_tNlmp.webp&quot; srcset=&quot;/_astro/omd2_P1110001_8_rotated.jWON2_Ex_Z1EorV4.webp 640w, /_astro/omd2_P1110001_8_rotated.jWON2_Ex_Z1kBNEq.webp 750w, /_astro/omd2_P1110001_8_rotated.jWON2_Ex_1BWiwV.webp 828w, /_astro/omd2_P1110001_8_rotated.jWON2_Ex_Z21nmnL.webp 1080w, /_astro/omd2_P1110001_8_rotated.jWON2_Ex_2uAg5P.webp 1280w, /_astro/omd2_P1110001_8_rotated.jWON2_Ex_Z1vSi6z.webp 1668w, /_astro/omd2_P1110001_8_rotated.jWON2_Ex_au0og.webp 2048w, /_astro/omd2_P1110001_8_rotated.jWON2_Ex_Z1YjXiV.webp 2560w, /_astro/omd2_P1110001_8_rotated.jWON2_Ex_tNlmp.webp 3180w&quot; alt=&quot;Figure 10e: Planned tool path (ROI)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 3180px) 3180px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;3180&quot; height=&quot;540&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 10e: Planned tool path (ROI)&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 10e: Planned tool path (ROI).&lt;/figcaption&gt; &lt;/figure&gt;
&lt;div&gt;&lt;h3 id=&quot;6-conclusion--outlook&quot;&gt;6 Conclusion &amp;#x26; Outlook&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;This work was focused on the development of a software tool for solder pad detection and printer control.
Apart from that, the developed software can act as an universal front-end for OpenCV.
This allows fast evaluation of new algorithms by interactively changing parameters by hand.
In the future, this tool shall be extended to handle more complex tasks of the PCB assembly process.
The software can work with a variety of different data sources as photographies, scans and Gerber files.
Even screenshots of the CAD tool or datasheets are usable.
This is an advantage to existing methods, where layout data is required.
The quality of results is also depending on the surface finish of the PCB.
Hot Air Solder Leveling (HASL) coats the solder pads with a thin film of tin.
Unfortunately, this results in an uneven surface finish which highly reflective.
To cope with bright spots and reflexions a diffuse illumination is essential.
Electroless Nickel Immersion Gold (ENIG) or Immersion Tin (ISn) coating in contrast, will result in a even and soft surface with a yellow / golden color.
Another influencing factor is the color of the silkscreen and solder resist.
The solder resist is a thin mask which is applied to the bare PCB to protect the traces from oxid.
Common colors for solder resists are green, black, white and blue.
Best results were achieved with black to gain a high contrast.
There is still a lot space for further usability improvements.
At the current state, pictures and G-Code instructions are transferred with memory cards between the camera, printer and PC.
This can be simplified by using the existing WiFi capabilities of those devices.
The import of Gerber files is currently only possible by using a conversion tool called gerbv.
However, it provides a software library called libgerbv to facilitate the import of Gerber files as part of the implementation.
Within the scope of this seminar, a detailed evaluation of the results and testing was not possible due to the limited amount of time.
It is eligible to compare the results the of camera based analysis with a Gerber based one of the same PCB.
In doing so the deviation between the original CAD data and their reconstruction can be evaluated.
For real application, a dispenser tool head for the printer is missing and has to be designed.
It’s desirable to use the existing 3D printing technology to do this.
The results in this paper are showing, that existing standard algorithms are sufficient for the detection of solder pads.
However there are situations in which they fail.
In these cases a segmentation based on the Watershed algorithm or using the Harris corner detection may be used to improve the results.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;7-literature-and-materials&quot;&gt;7 Literature and Materials&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[BreierLfB] Rotation Estimation for Printed Circuit Board Recycling by Matthias Breier et. al. (LfB, 2014)&lt;/li&gt;
&lt;li&gt;[MVGeom] Multiple View Geometry in Computer Vision by Richard Hartley, Andrew Zisserman (Cambridge University Press, March 2004)&lt;/li&gt;
&lt;li&gt;[LearnOCv] Learning OpenCV by Gary Bradski und Adrian Kaehler (O’Reilly &amp;#x26; Associates, October 2013)&lt;/li&gt;
&lt;li&gt;[OCvDoc] OpenCV Documentation and referenced papers: &lt;a href=&quot;https://www.opencv.org&quot;&gt;https://www.opencv.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[QtDoc] Qt Project Documentation: &lt;a href=&quot;https://www.qt-project.org&quot;&gt;https://www.qt-project.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[RRap] RepRap Project Wiki: &lt;a href=&quot;https://reprap.org/wiki&quot;&gt;https://reprap.org/wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h4 id=&quot;71-links-and-software&quot;&gt;7.1 Links and Software&lt;/h4&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;The Pastie implementation: &lt;a href=&quot;https://codeberg.org/stv0g/pastie&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/pastie&lt;/span&gt; &lt;/a&gt; .&lt;/li&gt;
&lt;li&gt;GerbV Gerber File Viewer and Library: &lt;a href=&quot;https://gerbv.github.io/&quot;&gt;https://gerbv.github.io/&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;libqt-omd Communication library for Olympus OM-D &amp;#x26; Pen cameras: &lt;a href=&quot;https://codeberg.org/stv0g/libqt-omd&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/libqt-omd&lt;/span&gt; &lt;/a&gt; .&lt;/li&gt;
&lt;/ul&gt;
&lt;section data-footnotes=&quot;&quot;&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;Logitech HD Pro C920: 2304x1536 pixel with autofocus. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;libgerbv is a free software library for rendering Gerber files. &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-3&quot;&gt;
&lt;p&gt;See OpenCV function &lt;a href=&quot;https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html#getperspectivetransform&quot;&gt;getPerspectiveTransform()&lt;/a&gt;. &lt;a href=&quot;#user-content-fnref-3&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-4&quot;&gt;
&lt;p&gt;The silkscreen contains printed markers and text on top of the PCB. &lt;a href=&quot;#user-content-fnref-4&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 4&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-5&quot;&gt;
&lt;p&gt;See OpenCV function &lt;a href=&quot;https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html#getaffinetransform&quot;&gt;getAffineTransform()&lt;/a&gt;. &lt;a href=&quot;#user-content-fnref-5&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 5&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-6&quot;&gt;
&lt;p&gt;The solder paste extruder itself is not part of this work. &lt;a href=&quot;#user-content-fnref-6&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 6&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-7&quot;&gt;
&lt;p&gt;libqt-omd is available as free software at: &lt;a href=&quot;https://codeberg.org/stv0g/libqt-omd&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/libqt-omd&lt;/span&gt; &lt;/a&gt; . &lt;a href=&quot;#user-content-fnref-7&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 7&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-8&quot;&gt;
&lt;p&gt;Pastie is available as free software at &lt;a href=&quot;https://codeberg.org/stv0g/pastie&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .5a12 12 0 0 0-12 12 12 12 0 0 0 1.8 6.4l10-13a.2.1 0 0 1 .4 0l10 13a12 12 0 0 0 1.8-6.4 12 12 0 0 0-12-12zm.3 6.5 4.4 16.5a12 12 0 0 0 5.2-4.2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/stv0g/pastie&lt;/span&gt; &lt;/a&gt; . &lt;a href=&quot;#user-content-fnref-8&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 8&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-9&quot;&gt;
&lt;p&gt;This functionality is provided by a software called Octoprint: &lt;a href=&quot;https://www.octoprint.org&quot;&gt;https://www.octoprint.org&lt;/a&gt;. &lt;a href=&quot;#user-content-fnref-9&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 9&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-10&quot;&gt;
&lt;p&gt;The dialect is documented on the RepRap website: &lt;a href=&quot;https://reprap.org/wiki/G-code&quot;&gt;https://reprap.org/wiki/G-code&lt;/a&gt;. &lt;a href=&quot;#user-content-fnref-10&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 10&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>Robotics</category><category>Electronics</category><category>Computer</category><category>OpenCV</category><category>Qt</category><category>Study</category><category>3D Printing</category><category>3D</category><category>English</category><category>Project</category></item><item><title>Bachelor Thesis: Extended Abstract</title><link>https://0l.de/blog/2015/01/bachelor-thesis-abstract/</link><guid isPermaLink="true">https://0l.de/blog/2015/01/bachelor-thesis-abstract/</guid><pubDate>Thu, 22 Jan 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Almost fourteen months ago, I started working on my bachelor thesis.
Although I finished it half a year ago, it’s still part of my work as a student research assistant.&lt;/p&gt;
&lt;p&gt;During my initial work, most of the code was written for an internal research kernel.
I’m now happy that we were able to port it to an open source kernel called &lt;em&gt;eduOS&lt;/em&gt;: &lt;a href=&quot;https://github.com/RWTH-OS/eduOS&quot;&gt; &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M12 .3a12 12 0 0 0-3.8 23.38c.6.12.83-.26.83-.57L9 21.07c-3.34.72-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.08-.74.09-.73.09-.73 1.2.09 1.83 1.24 1.83 1.24 1.08 1.83 2.81 1.3 3.5 1 .1-.78.42-1.31.76-1.61-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.14-.3-.54-1.52.1-3.18 0 0 1-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.29-1.23 3.29-1.23.64 1.66.24 2.88.12 3.18a4.65 4.65 0 0 1 1.23 3.22c0 4.61-2.8 5.63-5.48 5.92.42.36.81 1.1.81 2.22l-.01 3.29c0 .31.2.69.82.57A12 12 0 0 0 12 .3Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;span&gt;/RWTH-OS/eduOS&lt;/span&gt; &lt;/a&gt; ).
This minimal operating system is used for practical demo’s and assignments during the &lt;a href=&quot;https://www.os.rwth-aachen.de&quot;&gt;OS course&lt;/a&gt; at my university.
There’s much more I could write about.
So this will probably be another separate blog post.&lt;/p&gt;
&lt;p&gt;The motive for this article is an abstract I wrote for the student research competition of the &lt;a href=&quot;http://asplos15.bilkent.edu.tr&quot;&gt;ASPLOS conference&lt;/a&gt; which is held this year in Istanbul, Turkey.
Unfortunately my submission got rejected.
But as a nice side-effect, I’ve now the chance to present my work to an English audience as well:&lt;/p&gt;
&lt;center&gt; &lt;a download href=&quot;https://0l.de/blog/2015/01/bachelor-thesis-abstract/Self-referenced_Page_Tables-Vogel-ASPLOS_SrC.pdf&quot;&gt;   &lt;span&gt; &lt;svg aria-hidden=&quot;true&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot;&gt;&lt;path d=&quot;M8.29 13.29a1 1 0 0 0 0 1.42l3 3a1 1 0 0 0 1.42 0l3-3a1 1 0 0 0-1.42-1.42L13 14.59V3a1 1 0 0 0-2 0v11.59l-1.29-1.3a1 1 0 0 0-1.42 0ZM18 9h-2a1 1 0 0 0 0 2h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-7a1 1 0 0 1 1-1h2a1 1 0 0 0 0-2H6a3 3 0 0 0-3 3v7a3 3 0 0 0 3 3h12a3 3 0 0 0 3-3v-7a3 3 0 0 0-3-3Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;/span&gt;&lt;b&gt;Download:&lt;/b&gt;Extended Abstract
(PDF)  &lt;/a&gt;  &lt;/center&gt;

&lt;div&gt;&lt;h2 id=&quot;self-referencing-page-tables-for-the-x86-architecture&quot;&gt;Self-referencing Page Tables for the x86-Architecture&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;a-simple-paging-implementation-for-a-minimalistic-operating-system&quot;&gt;A simple Paging Implementation for a minimalistic Operating System&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;mailto:steffen.vogel@rwth-aachen.de&quot;&gt;Steffen Vogel&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Academic advisor: Dr. rer nat. Stefan Lankes Institute for Automation of Complex Power Systems E.ON Energy Research Center, RWTH Aachen University Mathieustr. 10, 52074 Aachen, Germany&lt;/p&gt;
&lt;p&gt;This was a submission for ASPLOS Student Research Competition ’15 Istanbul, Turkey&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;abstract&quot;&gt;Abstract&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The adoption of 64 bit architectures went along with an extension of the virtual address space (VAS).
To cope with this growth, the memory management unit (MMU) had to be extended as well.
For paging-based systems like Intel’s x86-architecture this was realized by adding more levels of indirection to the page table walk.&lt;/p&gt;
&lt;p&gt;This walk translates virtual pages to physical page frames (PF) by performing look-ups in a radix / prefix tree in which every node represents a page table (&lt;a href=&quot;#figure1a&quot;&gt;Figure 1a&lt;/a&gt;).
Since the tables are part of the translation process, they must be referenced by physical page frame numbers (PFN, blue line).
As the operating system is only eligible to access the VAS, it cannot follow the path of a walk.
In order to allow the manipulation of page tables, it must provide:&lt;/p&gt;

&lt;figure id=&quot;figure1a&quot;&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/pgt_walk.Bm-Rgxnq_Z1sQTwR.webp&quot; srcset=&quot;/_astro/pgt_walk.Bm-Rgxnq_Zky5B4.webp 640w, /_astro/pgt_walk.Bm-Rgxnq_ZIPB4N.webp 750w, /_astro/pgt_walk.Bm-Rgxnq_1JiaE9.webp 828w, /_astro/pgt_walk.Bm-Rgxnq_Z1sQTwR.webp 1037w&quot; alt=&quot;Figure 1a: Page table walk in the x86 64 longmode: Traditional, without self-reference&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1037px) 1037px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1037&quot; height=&quot;442&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 1a: Page table walk in the x86 64 longmode: Traditional, without self-reference&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 1a: Page table walk in the x86 64 longmode: Traditional, without self-reference.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;Access to the table entries, by mapping the tables themselves to the VAS.&lt;/li&gt;
&lt;li&gt;A mapping between physical references to corresponding locations in the VAS.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally, every level of the page table walk increases the complexity of managing these mappings.
They also increase the memory consumption by occupying physical page frames.
It is possible to avoid both drawbacks by the technique described in the following.&lt;/p&gt;
&lt;p&gt;In my bachelor thesis, I presented an approach, which is compatible with both the 32 bit and 64 bit version of Intel’s x86-architecture.
This allows for a replacement of two code bases, one for each architecture, by one supporting both.
Thus, results in a shorter, easier comprehensible, and maintainable code.
As foundation for this implementation our teaching OS called “eduOS” was used&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.
“eduOS” supports only the 32 bit protected mode whereas the 64 bit longmode is only implemented for an internal research kernel.&lt;/p&gt;
&lt;p&gt;Thanks to the sophisticated design of Intel’s x86 MMU, it is possible to avoid most of the complexity and space requirements by using a little trick.
Adding a self-reference in the root table (PML4 resp. PGD) automatically enables access to all page tables from the VAS without the need for manual mappings as described above (&lt;a href=&quot;#figure1b&quot;&gt;Figure 1b&lt;/a&gt;).
The operating system does not need to manually follow the path of a page table walk, as this task is executed by the MMU for accessing individual tables instead of page frames.&lt;/p&gt;

&lt;figure id=&quot;figure1b&quot;&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/pgt_walk_self.COAkTsRX_21BnqG.webp&quot; srcset=&quot;/_astro/pgt_walk_self.COAkTsRX_2o3eur.webp 640w, /_astro/pgt_walk_self.COAkTsRX_Z1dbznl.webp 750w, /_astro/pgt_walk_self.COAkTsRX_Zs7Veu.webp 828w, /_astro/pgt_walk_self.COAkTsRX_21BnqG.webp 1051w&quot; alt=&quot;Figure 1b: Page table walk in the x86 64 longmode: With self-reference&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 1051px) 1051px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;1051&quot; height=&quot;433&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 1b: Page table walk in the x86 64 longmode: With self-reference&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 1b: Page table walk in the x86 64 longmode: With self-reference.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;An access to the VAS region covered by a self-reference causes the MMU to look up the root table twice (red line).
Effectively, this shifts the whole page table walk by one level.
Therefore, it stops with the PFN of page tables instead of page frames that are usually translated by the MMU.
Here, both the PML4 and PDPT indexes are used to choose an entry out of the PML4 table.
Therefore, it must be guaranteed that PML4 entries can be interpreted as PDPT entries, too.
This demands for the following requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Homogenous coding of paging flags across all paging levels.&lt;/li&gt;
&lt;li&gt;Equal table sizes across all paging levels.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fortunately, the x86-architecture complies with this prerequisites as shown in &lt;a href=&quot;#figure2&quot;&gt;Figure 2&lt;/a&gt;.
Green colored flags are coded consistently across all paging levels.
Only PAT, size and global flags have a slightly different meaning for entries in the PGT.
My bachelor thesis shows that these deviations still allow maintaining full control caching and memory protection properties of self-mapped tables.
This includes for common system calls like fork() and kill().&lt;/p&gt;

&lt;figure id=&quot;figure2&quot;&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/page_flags.CU4EvCew_Zd6QIk.webp&quot; srcset=&quot;/_astro/page_flags.CU4EvCew_Zd6QIk.webp 598w&quot; alt=&quot;Figure 2: Similar flags across all paging levels&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 598px) 598px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;598&quot; height=&quot;502&quot;&gt; &lt;button aria-label=&quot;Zoom image: Figure 2: Similar flags across all paging levels&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Figure 2: Similar flags across all paging levels.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;By repeatedly addressing the self-reference, it is also possible to access tables of the upper levels (PGD to PML4).
&lt;a href=&quot;#table1&quot;&gt;Table 1&lt;/a&gt; shows the resulting virtual addresses of all page tables when using the last (512th) entry of the PML4 table for the self-reference&lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot; id=&quot;user-content-fnref-3&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.
This grants access to all possible page tables, including those which might not yet exist and may be allocated in the future.
Hence, the self-reference reserves a fixed fraction of the VAS for the page tables.
The size of this region is equal to 256 TiB / 512 = 512 GiB for 64 bit (resp. 4 GiB / 1024 = 4 MiB for 32 bit), which is negligible in comparison to the huge VAS of 248 byte.&lt;/p&gt;

&lt;figure id=&quot;table1&quot;&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/self_map_addrs.BlpFwUQl_27K2fx.webp&quot; srcset=&quot;/_astro/self_map_addrs.BlpFwUQl_27K2fx.webp 553w&quot; alt=&quot;Table 1: Virtual addresses of self-mapped tables&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 553px) 553px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;553&quot; height=&quot;212&quot;&gt; &lt;button aria-label=&quot;Zoom image: Table 1: Virtual addresses of self-mapped tables&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Table 1: Virtual addresses of self-mapped tables.&lt;/figcaption&gt; &lt;/figure&gt;
&lt;p&gt;For the manipulation of page table entries two approaches are feasible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Top-down&lt;/strong&gt; Use known tree traversals, starting at the root node, which corresponds to the PML4 respectively PGD.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bottom-up&lt;/strong&gt; Use the page fault handler to create new tables on-the-fly, when they are not yet present.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But there are also other architectures which satisfy the prerequisites described above.
One of these is the Alpha&lt;sup&gt;&lt;a href=&quot;#user-content-fn-4&quot; id=&quot;user-content-fnref-4&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; architecture, which suggests a similar approach in the reference manual.
Intel and AMD do not mention the technique in their x86 manuals.
In the field of operating systems, support is far more limited.
There is only a single reference&lt;sup&gt;&lt;a href=&quot;#user-content-fn-5&quot; id=&quot;user-content-fnref-5&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; dated to 2010 indicating that Microsoft might use a similar approach for its NT kernel.
Linux cannot profit because its paging implementation must support a broad selection of virtual memory architectures of which not all fulfill the requirements mentioned above.&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot;&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;A full version of the thesis and slides are available &lt;a href=&quot;https://0l.de/blog/2014/06/bachelor-thesis-defense&quot;&gt;in this post&lt;/a&gt;. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;Description and source code at: &lt;a href=&quot;https://www.os.rwth-aachen.de&quot;&gt;www.os.rwth-aachen.de&lt;/a&gt;. &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-3&quot;&gt;
&lt;p&gt;This is an arbitrary choice. All other entries are feasible, too. &lt;a href=&quot;#user-content-fnref-3&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-4&quot;&gt;
&lt;p&gt;Compaq Computer Corporation: Alpha Architecture Reference Manual. January 2002. &lt;a href=&quot;#user-content-fnref-4&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 4&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-5&quot;&gt;
&lt;p&gt;Dave Probert, Microsoft: &lt;a href=&quot;http://research.microsoft.com/en-us/um/redmond/events/wincore2010/Dave_Probert_1.pdf&quot;&gt;Windows Kernel Architecture Internals&lt;/a&gt;. April 2010. &lt;a href=&quot;#user-content-fnref-5&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 5&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>English</category><category>Abstract</category><category>Study</category><category>Thesis</category></item><item><title>noteblok.{de,net,org,dn42}</title><link>https://0l.de/blog/2014/06/noteblok-dn42/</link><guid isPermaLink="true">https://0l.de/blog/2014/06/noteblok-dn42/</guid><pubDate>Thu, 19 Jun 2014 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/noteblok.Bb83HLZo_N6BAD.svg&quot; srcset=&quot;/_astro/noteblok.Bb83HLZo_Ui7N0.svg 640w, /_astro/noteblok.Bb83HLZo_N6BAD.svg 700w&quot; alt=&quot;noteblok&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 700px) 700px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;700&quot; height=&quot;80&quot;&gt; &lt;button aria-label=&quot;Zoom image: noteblok&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt;
&lt;p&gt;Dies ist das neue Logo und Name meines Blogs.&lt;/p&gt;
&lt;p&gt;Bisher gab es hier nur wenige persönliche Beiträge.
Da ich das auch so beibehalten möchte, habe ich mich entschlossen meinen Namen aus dem Titel zu streichen.
Vielleicht findet so auch mal der ein oder andere Gastbeitrag seinen Weg hierher.&lt;/p&gt;

&lt;aside aria-label=&quot;Veralteter Blogeintrag&quot;&gt; &lt;p aria-hidden=&quot;true&quot;&gt; Veralteter Blogeintrag &lt;/p&gt; &lt;div&gt; &lt;p&gt;Dieser Blogeintrag ist schon etwas und beinhaltet veraltete Informationen.
Mittlerweile ist dieser Blog nur noch unter &lt;strong&gt;&lt;a href=&quot;https://0l.de&quot;&gt;0l.de&lt;/a&gt;&lt;/strong&gt; erreichbar und nicht mehr über die hier genannten Domains.&lt;/p&gt; &lt;/div&gt; &lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;domains&quot;&gt;Domains&lt;/h2&gt;&lt;/div&gt;

&lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/World_IPv6_launch_badge_256.8NsnDzaA_E2HhV.webp&quot; srcset=&quot;/_astro/World_IPv6_launch_badge_256.8NsnDzaA_E2HhV.webp 256w&quot; alt=&quot;World IPv6 Launch Badge&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 256px) 256px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;256&quot; height=&quot;256&quot;&gt; &lt;button aria-label=&quot;Zoom image: World IPv6 Launch Badge&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt;
&lt;p&gt;Mit dem neuen Namen hat sich auch die Domain geändert.
Der Blog ist nun erreichbar unter &lt;strong&gt;noteblok.{de,net,org,dn42}&lt;/strong&gt;.
Über meine &lt;a href=&quot;https://www.steffenvogel.de&quot;&gt;persönliche Domain&lt;/a&gt; gelangt man nun direkt zu ein paar Infos über mich.&lt;/p&gt;
&lt;p&gt;Neben den neuen Domains sind nun auch alle Webseiten/Blogs über &lt;a href=&quot;https://de.wikipedia.org/wiki/IPv6&quot;&gt;&lt;strong&gt;IPv6&lt;/strong&gt;&lt;/a&gt; erreichbar 😊.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;dn42&quot;&gt;dn42&lt;/h2&gt;&lt;/div&gt;

&lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/dn42.ptqmEgtA_ZHHxy0.webp&quot; srcset=&quot;/_astro/dn42.ptqmEgtA_ZHHxy0.webp 236w&quot; alt=&quot;dn42 Logo&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 236px) 236px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;236&quot; height=&quot;73&quot;&gt; &lt;button aria-label=&quot;Zoom image: dn42 Logo&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt;
&lt;p&gt;Zudem ist der Blog auf über des &lt;a href=&quot;https://dn42.net/Home&quot;&gt;dn42&lt;/a&gt; Darknet &lt;a href=&quot;http://www.noteblok.dn42&quot;&gt;erreichbar&lt;/a&gt;.
Das dn42 ist ein dezentrales und dynamisches VPN Netzwerk.
Es besteht aus einem Verbund von Freiwilligen Admins, die jeweils Peer-to-Peer Verbindungen über VPNs herstellen.
Es baut damit als Overlay Netzwerk auf dem bestehenden Internet auf.
Zudem nutzt das dn42 mit BGP, DNS, Whois die gleichen Protokolle wie das reguläre Internet.&lt;/p&gt;
&lt;p&gt;Als Teil von (&lt;a href=&quot;https://dev.0l.de&quot;&gt;/dev/nulll&lt;/a&gt;) betreibe ich das &lt;a href=&quot;https://de.wikipedia.org/wiki/Autonomes_System&quot;&gt;Autonome System&lt;/a&gt; &lt;a href=&quot;https://explorer.burble.com/?#/aut-num/AS4242422428&quot;&gt;AS4242422428&lt;/a&gt; und unterhalte Peerings mit anderen Knoten des dn42 Netzwerkes.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;screenshot&quot;&gt;Screenshot&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Hier ist noch ein Screenshot &lt;a href=&quot;https://web.archive.org/web/20141222105946/http://www.noteblok.net/&quot;&gt;meines Blog aus dem Jahr 2014&lt;/a&gt;:&lt;/p&gt;

&lt;figure&gt; &lt;div&gt;&lt;starlight-image-zoom-zoomable&gt; &lt;img src=&quot;https://0l.de/_astro/screenshot-2014-12-22-noteblok-net.DMjbKZTW_Zxrtf1.webp&quot; srcset=&quot;/_astro/screenshot-2014-12-22-noteblok-net.DMjbKZTW_ZuQdgc.webp 640w, /_astro/screenshot-2014-12-22-noteblok-net.DMjbKZTW_eK5ad.webp 750w, /_astro/screenshot-2014-12-22-noteblok-net.DMjbKZTW_Z1H5Ker.webp 828w, /_astro/screenshot-2014-12-22-noteblok-net.DMjbKZTW_LQYPs.webp 1080w, /_astro/screenshot-2014-12-22-noteblok-net.DMjbKZTW_Z22csqf.webp 1280w, /_astro/screenshot-2014-12-22-noteblok-net.DMjbKZTW_JHVPA.webp 1668w, /_astro/screenshot-2014-12-22-noteblok-net.DMjbKZTW_Z1H6j6C.webp 2048w, /_astro/screenshot-2014-12-22-noteblok-net.DMjbKZTW_Zxrtf1.webp 2330w&quot; alt=&quot;Screenshot noteblok.net vom 2014-12-22&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; sizes=&quot;(min-width: 2330px) 2330px, 100vw&quot; data-astro-image=&quot;constrained&quot; width=&quot;2330&quot; height=&quot;2024&quot;&gt; &lt;button aria-label=&quot;Zoom image: Screenshot noteblok.net vom 2014-12-22&quot;&gt; &lt;svg aria-hidden=&quot;true&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt; &lt;use href=&quot;#starlight-image-zoom-icon-zoom&quot;&gt;&lt;/use&gt; &lt;/svg&gt; &lt;/button&gt; &lt;/starlight-image-zoom-zoomable&gt;&lt;/div&gt; &lt;figcaption&gt;Screenshot noteblok.net vom 2014-12-22.&lt;/figcaption&gt; &lt;/figure&gt;</content:encoded><category>Blog</category><category>Meta</category><category>dn42</category><category>German</category></item></channel></rss>