<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mehul</title>
    <description>The latest articles on DEV Community by Mehul (@infiniteregrets).</description>
    <link>https://dev.to/infiniteregrets</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F771759%2F36a3a091-e669-4f53-aed4-293b8e9b0a8e.jpeg</url>
      <title>DEV Community: Mehul</title>
      <link>https://dev.to/infiniteregrets</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/infiniteregrets"/>
    <language>en</language>
    <item>
      <title>mirrord internals - hooking libc functions in Rust and fixing bugs</title>
      <dc:creator>Mehul</dc:creator>
      <pubDate>Wed, 06 Jul 2022 04:25:53 +0000</pubDate>
      <link>https://dev.to/infiniteregrets/mirrord-internals-hooking-libc-functions-in-rust-and-fixing-bugs-2ilf</link>
      <guid>https://dev.to/infiniteregrets/mirrord-internals-hooking-libc-functions-in-rust-and-fixing-bugs-2ilf</guid>
      <description>&lt;p&gt;"Is mirrord some kind of &lt;a href="https://man7.org/linux/man-pages/man2/ptrace.2.html"&gt;ptrace&lt;/a&gt; magic?”, that’s what I exactly thought when I was introduced to this idea of “mirroring traffic”. To my surprise, the idea and design behind mirrord are based on simple concepts implemented in a novel way! This is what I want to discuss in this blog post along with my experience as a Junior Engineer learning how to tackle bugs working on this badass project.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is mirrord? 🪞
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/metalbear-co/mirrord"&gt;mirrord&lt;/a&gt; lets you run a local process in the context of a cloud service, which means we can test our code on staging, without actually deploying it there. This leads to shorter feedback loops (you don’t have to wait on long CI processes to test your code in staging conditions) and a more stable staging environment (since untested services aren’t being deployed there).  There is a detailed overview of mirrord and what we strive to achieve with it in &lt;a href="https://metalbear.co/blog/reintroducing-mirrord/"&gt;this&lt;/a&gt; blog post.&lt;/p&gt;

&lt;h2&gt;
  
  
  mirrord-layer + LD_PRELOAD = ❤️
&lt;/h2&gt;

&lt;p&gt;mirrord-layer, shipped as a dynamic library, is responsible for “overriding” or “hooking” libc functions through &lt;code&gt;LD_PRELOAD&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is &lt;code&gt;LD_PRELOAD&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;LD_PRELOAD&lt;/code&gt;&lt;sup id="fnref1"&gt;1&lt;/sup&gt;, available as an environment variable, is a feature provided by dynamic linkers like &lt;a href="https://man7.org/linux/man-pages/man8/ld.so.8.html"&gt;ld.so&lt;/a&gt; that lets us load a shared library into a process before the process loads anything else.&lt;br&gt;
In our case, we use &lt;code&gt;LD_PRELOAD&lt;/code&gt; to load mirrord-layer, which overrides libc functions with a custom implementation. By overriding file and socket functions, we can then transparently plug the process into the remote pod, having it read and write files and traffic remotely without changing a single line of code.&lt;br&gt;
Overriding these libc functions on different systems would have been a difficult task and this is where Frida-gum comes to save the day through its &lt;a href="https://github.com/frida/frida-gum/blob/main/gum/guminterceptor.h"&gt;inline hooking interceptor&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's go over a quick example of how we can hook the &lt;a href="https://man7.org/linux/man-pages/man2/open.2.html"&gt;open&lt;/a&gt; system call by finding and replacing libc symbols through Frida's Rust bindings.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get a reference to the &lt;code&gt;Frida Gum&lt;/code&gt; runtime.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;lazy_static!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="n"&gt;GUM&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Gum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;Gum&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;obtain&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Write a detour for &lt;code&gt;open&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;open_detour&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;c_int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"open_detour: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ffi&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;CStr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.to_str&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;libc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Inside the &lt;a href="https://docs.rs/ctor/latest/ctor/attr.ctor.html"&gt;constructor&lt;/a&gt; of our shared library:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create an interceptor.&lt;/p&gt;

&lt;p&gt;Find the exported symbol from other shared libraries for &lt;code&gt;open&lt;/code&gt; and replace it with our detour through the interceptor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[ctor]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;interceptor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Interceptor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;obtain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;GUM&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;open&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;find_export_by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"open"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;interceptor&lt;/span&gt;&lt;span class="nf"&gt;.replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;NativePointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;open_detour&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_void&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;NativePointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_void&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The complete crate for the example above is available &lt;a href="https://github.com/frida/frida-rust/tree/master/examples/gum/hook_open"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After &lt;code&gt;cargo +nightly build&lt;/code&gt;, let's &lt;code&gt;LD_PRELOAD&lt;/code&gt; our shared library and run the unix utility called &lt;code&gt;cat&lt;/code&gt; on our very cool sample file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mirrord-user@mirrord:~/mirrord&lt;span class="nv"&gt;$ LD_PRELOAD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;target/debug/libmirrord.so &lt;span class="nb"&gt;cat &lt;/span&gt;file.txt
open_detour: file.txt
boots and cats

mirrord-user@mirrord:~/mirrord&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"look at the statement before "&lt;/span&gt;boots and cats&lt;span class="s2"&gt;" is printed!"&lt;/span&gt;
look at the statement before &lt;span class="s2"&gt;"boots and cats"&lt;/span&gt; is printed!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Awesome! we are able to override the functionality of libc's system call wrappers and replace them with our custom code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mirroring network traffic &amp;amp; web servers 💻
&lt;/h2&gt;

&lt;p&gt;I want to do a quick walkthrough of how a simple webserver would work when run with mirrord and how this led me to finding my first bug! So, in general, web servers implement the flow of creating a socket and accepting connections on it by making the following system calls sequentially -  &lt;code&gt;socket&lt;/code&gt;, &lt;code&gt;bind&lt;/code&gt;, &lt;code&gt;listen&lt;/code&gt;, &lt;code&gt;accept&lt;/code&gt;&lt;sup id="fnref2"&gt;2&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Referring to the notes on the Linux manual for &lt;a href="https://man7.org/linux/man-pages/man2/listen.2.html#NOTES"&gt;listen&lt;/a&gt;, we discuss these system calls in detail and how mirrord handles them.&lt;/p&gt;

&lt;h3&gt;
  
  
  [1] socket
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://man7.org/linux/man-pages/man2/socket.2.html"&gt;socket&lt;/a&gt; returns a &lt;em&gt;socket descriptor&lt;/em&gt; referring to a communication endpoint. When mirrord hooks a process’ &lt;code&gt;socket&lt;/code&gt; call,  it maintains that original behavior, but also keeps a record of the new socket in an internal data structure. To describe this data structure and what's going on behind the scenes I will refer to these diagrams below -&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The local process calls &lt;code&gt;socket&lt;/code&gt;, which then tries to find the &lt;code&gt;socket&lt;/code&gt; symbol in libc from the shared library dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZPV9pd2C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/liyliachif9o850cse9h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZPV9pd2C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/liyliachif9o850cse9h.png" alt="mirrord-process-layer" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frida’s interceptor replaced (in-place) the libc’s socket wrapper with our detour, so the &lt;code&gt;socket&lt;/code&gt; call goes to our detour 😉.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SnE_xb_s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/taml7uain6b188n5m269.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SnE_xb_s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/taml7uain6b188n5m269.png" alt="mirrord-libc-intercept" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inside the detour, we call libc’s socket wrapper and store the returned descriptor in a hashmap called &lt;code&gt;SOCKETS&lt;/code&gt; that maps the socket to its related metadata and "initialized" state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z3Lt42zy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5rrs8yjuqwdhho8ijv0s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z3Lt42zy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5rrs8yjuqwdhho8ijv0s.png" alt="mirrord-layer-hashmap" width="880" height="495"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;SOCKETS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;LazyLock&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RawFd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Arc&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Socket&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nn"&gt;LazyLock&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="nn"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;HashMap&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;In the end, we just return the socket descriptor returned by the call to libc to the local process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dl95ulT4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ag0vpq83pa85oyq99crm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dl95ulT4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ag0vpq83pa85oyq99crm.png" alt="mirrord-layer-process" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The words “hook” and “detour” are used interchangeably as they refer to the same idea, but “detour” is more formal as it is used in the codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  [2] bind
&lt;/h3&gt;

&lt;p&gt;To bind an address to the socket descriptor returned by the &lt;code&gt;socket&lt;/code&gt; system call, &lt;a href="https://man7.org/linux/man-pages/man2/bind.2.html"&gt;bind&lt;/a&gt; is called. Our detour for bind doesn’t really do much because all the juicy stuff happens in &lt;code&gt;listen&lt;/code&gt;. However, it puts the socket in a &lt;code&gt;Bound&lt;/code&gt; state if it exists in our &lt;code&gt;SOCKETS&lt;/code&gt; hashmap along with the address supplied by the process through the &lt;code&gt;sockaddr&lt;/code&gt; struct.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_pzkcWZ6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ar4gi8rsn4l9yako7txi.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_pzkcWZ6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ar4gi8rsn4l9yako7txi.gif" alt="mirrord-bound" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Structs for Socket metadata and its states:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Socket&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;type_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SocketState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;SocketState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Initialized&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;Bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bound&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;Listening&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bound&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;Connected&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Connected&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  [3] listen
&lt;/h3&gt;

&lt;p&gt;To start accepting connections on our socket, we have to mark the socket as passive using the &lt;a href="https://man7.org/linux/man-pages/man2/listen.2.html"&gt;listen&lt;/a&gt; system call. There are quite a few things happening in our “little” detour here, so let's take it step by with the help of these diagrams below -&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change the socket state from &lt;code&gt;Bound&lt;/code&gt; to &lt;code&gt;Listening&lt;/code&gt; in our &lt;code&gt;SOCKETS&lt;/code&gt; hashmap.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nOgx0ApM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2unoa90moeslkscj2dww.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nOgx0ApM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2unoa90moeslkscj2dww.gif" alt="mirrord-listen-listening" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Call libc’s &lt;code&gt;bind&lt;/code&gt; with address port as 0, which looks something like &lt;code&gt;sockaddr_in.port = 0&lt;/code&gt; at a lower level in C. This makes the - OS assign a port to our address, without us having to check for any available ports.&lt;/li&gt;
&lt;li&gt;Call libc’s &lt;code&gt;getsockname&lt;/code&gt; to get the port that was assigned to our address. We call this our “fake port”.&lt;/li&gt;
&lt;li&gt;Call libc’s &lt;code&gt;listen&lt;/code&gt; to qualify as an endpoint open to accepting new connections.&lt;/li&gt;
&lt;li&gt;Send a message to mirrord-agent, with information including the "real" and "fake" port, that a new "peer" has connected to the agent to receive network traffic on the "real" port.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cD25mWu9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vs2jukqh967m0m9l8oki.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cD25mWu9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vs2jukqh967m0m9l8oki.png" alt="mirrord-listen-to-agent" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Long story short, mirrord-layer listens on the “fake" port bound to the address specified by the user. For example, if a user calls &lt;code&gt;bind&lt;/code&gt; on port 80, mirrord-layer will create a port like 3424 and call listen on it by binding the address to it. This also means that we don’t need &lt;code&gt;sudo&lt;/code&gt; to run our web server when listening on a special port like 80 since it is never actually bound. In parallel, mirrord-agent forwards traffic to this fake port giving us the illusion that our process is running on the remote pod. We will talk about how mirrord-agent works in another blog post!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iwYk2UJ9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b9lk92dzm3nc7x3q1tzo.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iwYk2UJ9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b9lk92dzm3nc7x3q1tzo.gif" alt="mirrord-listen-detour" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  [4] accept
&lt;/h3&gt;

&lt;p&gt;Now we just need to handle new connections! Every time &lt;a href="https://man7.org/linux/man-pages/man2/accept.2.html"&gt;accept&lt;/a&gt; is called in our local process, we call libc’s &lt;code&gt;accept&lt;/code&gt; and get a new socket descriptor referring to that connection/socket passed to &lt;code&gt;accept&lt;/code&gt;, but that’s just not it because under the hood we also maintain an internal connection queue for pending connections. This means that every time we receive a new connection request from the agent pod we enqueue that in our &lt;code&gt;CONNECTION_QUEUE&lt;/code&gt;. Each socket descriptor has its own unique queue.&lt;/p&gt;

&lt;p&gt;Furthermore in our detour for &lt;code&gt;accept&lt;/code&gt;, we do the following -&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is there a socket in &lt;code&gt;Listening&lt;/code&gt; state in our &lt;code&gt;SOCKETS&lt;/code&gt; hashmap, matching the socket passed to the parameters to &lt;code&gt;accept&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;If yes, we get the pending connection from our &lt;code&gt;CONNECTION_QUEUE&lt;/code&gt; for our original socket descriptor.&lt;/li&gt;
&lt;li&gt;Add the new socket descriptor to our &lt;code&gt;SOCKETS&lt;/code&gt; hashmap in the &lt;code&gt;Connected&lt;/code&gt; state.&lt;/li&gt;
&lt;li&gt;Modify the pointer to the &lt;code&gt;sockaddr&lt;/code&gt; struct to implicitly return the address of the new connection.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q94pb9kp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4h1s5q9l5f0dq80y3jvt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q94pb9kp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4h1s5q9l5f0dq80y3jvt.png" alt="mirrord-accept" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alright then, we have all our detours in place. Everything should work smoothly! Or so I thought. Let’s test it out by rolling back to the commit with only these detours in place.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git checkout&lt;/code&gt; &lt;a href="https://github.com/metalbear-co/mirrord/tree/d8b4de6f5c5907d4d682f018d42455cd41551eb2"&gt;d8b4de6&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s the commit before the &lt;a href="https://github.com/metalbear-co/mirrord/pull/32"&gt;patch&lt;/a&gt; I made for the bug I discovered. We don’t need to explicitly build and load the agent image in our cluster because the image is already hardcoded in the agent specification. So let’s get rolling?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;MIRRORD_IMPERSONATED_POD_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http-echo-deployment-77fddcdc49-6z22r &lt;span class="nv"&gt;LD_PRELOAD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/mehula/mirrord/target/debug/libmirrord.so node sample/app.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The YAML file for the http-echo deployment is available &lt;a href="https://github.com/metalbear-co/mirrord/blob/main/tests/app.yaml"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s look at some logs of our web server running with mirrord. I won’t dump all of them here, but I’ll just pick what’s important. All the logs are available &lt;a href="https://gist.github.com/infiniteregrets/4d471f576eb2ff66e44744352f24cb07"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="mi"&gt;2022&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="n"&gt;T20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;12.011931&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt; &lt;span class="n"&gt;DEBUG&lt;/span&gt; &lt;span class="n"&gt;mirrord&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="n"&gt;called&lt;/span&gt;
&lt;span class="mi"&gt;2022&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="n"&gt;T20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;12.012145&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt; &lt;span class="n"&gt;DEBUG&lt;/span&gt; &lt;span class="n"&gt;mirrord&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;bind&lt;/span&gt; &lt;span class="n"&gt;called&lt;/span&gt;
&lt;span class="mi"&gt;2022&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="n"&gt;T20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;12.012473&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt; &lt;span class="n"&gt;DEBUG&lt;/span&gt; &lt;span class="n"&gt;mirrord&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;listen&lt;/span&gt; &lt;span class="n"&gt;called&lt;/span&gt;
&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="n"&gt;listening&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="mi"&gt;2022&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="n"&gt;T20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;16.638872&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt; &lt;span class="n"&gt;DEBUG&lt;/span&gt; &lt;span class="n"&gt;mirrord&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alright, so our web server is up and running, waiting to accept new connections! And just like we talked about the system calls involved before, all of &lt;code&gt;socket&lt;/code&gt;, &lt;code&gt;bind&lt;/code&gt;, and &lt;code&gt;listen&lt;/code&gt; were called. But now let’s test out if sending a &lt;code&gt;GET&lt;/code&gt; request to our remote pod mirrors the traffic to our local process.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl http://192.168.49.2:32118&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="mi"&gt;2022&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="n"&gt;T20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;19.082404&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt; &lt;span class="n"&gt;DEBUG&lt;/span&gt; &lt;span class="n"&gt;mirrord&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
&lt;span class="mi"&gt;2022&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="n"&gt;T20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;21.901455&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt; &lt;span class="n"&gt;DEBUG&lt;/span&gt; &lt;span class="n"&gt;mirrord&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="mi"&gt;2022&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="n"&gt;T20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;21.901647&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt; &lt;span class="n"&gt;DEBUG&lt;/span&gt; &lt;span class="n"&gt;mirrord&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;No&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;connection_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="py"&gt;.js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;174&lt;/span&gt;
      &lt;span class="n"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;er&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Unhandled 'error' event&lt;/span&gt;
      &lt;span class="o"&gt;^&lt;/span&gt;

&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;accept&lt;/span&gt; &lt;span class="n"&gt;EINVAL&lt;/span&gt;
    &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;TCP&lt;/span&gt;&lt;span class="nf"&gt;.onconnection&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="py"&gt;.js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1497&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Emitted&lt;/span&gt; &lt;span class="nv"&gt;'error&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;TCP&lt;/span&gt;&lt;span class="nf"&gt;.onconnection&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="py"&gt;.js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1497&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks like even though a connection was enqueued in our &lt;code&gt;CONNECTION_QUEUE&lt;/code&gt;, it was never dequeued and no new socket descriptor was inserted in our &lt;code&gt;SOCKETS&lt;/code&gt; hashmap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: All references made are in the context of the present version of mirrord, not commit &lt;code&gt;d8b4de6&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That is weird, why was accept never called? Let’s debug our node process and see what’s going on!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pkP-Hvh_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m25djuubfb5wo7dlcj0p.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pkP-Hvh_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m25djuubfb5wo7dlcj0p.gif" alt="mirrord-debug-node" width="600" height="222"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Well, good luck debugging that and I won’t waste your time trying to figure out how to step into &lt;code&gt;listen()&lt;/code&gt; and other related functions to look at the underlying function calls. Instead, we will look at the underlying system calls with &lt;a href="https://strace.io/"&gt;strace&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s run the node server with &lt;code&gt;strace&lt;/code&gt; and send a &lt;code&gt;GET&lt;/code&gt; request to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mehula@mehul-machine:~/mirrord&lt;span class="nv"&gt;$ &lt;/span&gt;strace &lt;span class="nt"&gt;-c&lt;/span&gt; node sample/app.js
server listening to &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;:&lt;span class="s2"&gt;"::"&lt;/span&gt;,&lt;span class="s2"&gt;"family"&lt;/span&gt;:&lt;span class="s2"&gt;"IPv6"&lt;/span&gt;,&lt;span class="s2"&gt;"port"&lt;/span&gt;:8080&lt;span class="o"&gt;}&lt;/span&gt;
new client connection from ::ffff:127.0.0.1:48510
connection data from ::ffff:127.0.0.1:48510: &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;:&lt;span class="s2"&gt;"Buffer"&lt;/span&gt;,&lt;span class="s2"&gt;"data"&lt;/span&gt;:[71,69,84,32,47,32,72,84,84,80,47,49,46,49,13,10,72,111,115,116,58,32,108,111,99,97,108,104,111,115,116,58,56,48,56,48,13,10,85,115,101,114,45,65,103,101,110,116,58,32,99,117,114,108,47,55,46,54,56,46,48,13,10,65,99,99,101,112,116,58,32,42,47,42,13,10,13,10]&lt;span class="o"&gt;}&lt;/span&gt;
connection from ::ffff:127.0.0.1:48510 closed
^Cstrace: Process 285853 detached
% &lt;span class="nb"&gt;time     &lt;/span&gt;seconds  usecs/call     calls    errors syscall
&lt;span class="nt"&gt;------&lt;/span&gt; &lt;span class="nt"&gt;-----------&lt;/span&gt; &lt;span class="nt"&gt;-----------&lt;/span&gt; &lt;span class="nt"&gt;---------&lt;/span&gt; &lt;span class="nt"&gt;---------&lt;/span&gt; &lt;span class="nt"&gt;----------------&lt;/span&gt;
 80.95    0.018595           5      3361           mprotect
  4.74    0.001088           9       113           mmap
  3.56    0.000817           3       266           brk
  1.17    0.000268           5        51           futex
  0.94    0.000215           7        30         8 openat
  0.89    0.000204           9        22           fstat
  0.79    0.000182           5        31        10 ioctl
  0.71    0.000163           8        20           close
  0.68    0.000156           7        20           &lt;span class="nb"&gt;read
  &lt;/span&gt;0.56    0.000129          11        11           getgid
  0.54    0.000125          20         6           clone
  0.50    0.000114          10        11           geteuid
  0.45    0.000104           9        11           getegid
  0.45    0.000103           9        11           getuid
  0.44    0.000101          14         7           prlimit64
  0.42    0.000096          12         8           pread64
  0.41    0.000094           3        26           munmap
  0.34    0.000079           6        13           getpid
  0.33    0.000075          10         7           rt_sigaction
  0.24    0.000054          18         3           pipe2
  0.15    0.000034           4         7           rt_sigprocmask
  0.13    0.000031          15         2           eventfd2
  0.10    0.000024          12         2           epoll_create1
  0.09    0.000021           3         6           madvise
  0.07    0.000016           2         7           write
  0.07    0.000015           7         2         1 arch_prctl
  0.05    0.000012          12         1           set_robust_list
  0.04    0.000010           1         6           epoll_ctl
  0.04    0.000010          10         1           getrandom
  0.04    0.000009           9         1           set_tid_address
  0.02    0.000005           1         4         1 epoll_wait
  0.02    0.000004           0        11         8 &lt;span class="nb"&gt;stat
  &lt;/span&gt;0.02    0.000004           2         2           setsockopt
  0.01    0.000003           3         1           socket
  0.01    0.000003           3         1           listen
  0.01    0.000003           1         2         1 accept4
  0.01    0.000002           2         1           &lt;span class="nb"&gt;bind
  &lt;/span&gt;0.01    0.000002           2         1           getsockname
  0.00    0.000000           0         1         1 access
  0.00    0.000000           0         1           getpeername
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         2           fcntl
  0.00    0.000000           0         2           getcwd
  0.00    0.000000           0         4           &lt;span class="nb"&gt;readlink
  &lt;/span&gt;0.00    0.000000           0         2           dup3
  0.00    0.000000           0         7           statx
&lt;span class="nt"&gt;------&lt;/span&gt; &lt;span class="nt"&gt;-----------&lt;/span&gt; &lt;span class="nt"&gt;-----------&lt;/span&gt; &lt;span class="nt"&gt;---------&lt;/span&gt; &lt;span class="nt"&gt;---------&lt;/span&gt; &lt;span class="nt"&gt;----------------&lt;/span&gt;
100.00    0.022970                  4106        30 total
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks like &lt;code&gt;accept&lt;/code&gt; is never called and the only system call closest to accept we can see on this list is &lt;code&gt;accept4&lt;/code&gt;. According to the Linux manual page, &lt;code&gt;accept&lt;/code&gt; and &lt;code&gt;accept4&lt;/code&gt; are essentially the same except for the &lt;code&gt;flags&lt;/code&gt; parameter, which we probably don’t care about right now. So we will hook &lt;code&gt;accept4&lt;/code&gt; the same way as &lt;code&gt;accept&lt;/code&gt; and pray that things go well this time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;2022-06-24T16:22:59.983321Z DEBUG mirrord: accept4 hooked
2022-06-24T16:23:00.371721Z DEBUG mirrord: socket called
2022-06-24T16:23:00.371935Z DEBUG mirrord: &lt;span class="nb"&gt;bind &lt;/span&gt;called
2022-06-24T16:23:00.372050Z DEBUG mirrord: listen called
server listening to &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;:&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
2022-06-24T16:23:04.983632Z DEBUG mirrord: send message to client 80
2022-06-24T16:23:22.756866Z DEBUG mirrord: new connection &lt;span class="nb"&gt;id&lt;/span&gt;: 0
2022-06-24T16:23:22.758080Z DEBUG mirrord: No socket found &lt;span class="k"&gt;for &lt;/span&gt;connection_id: 0
events.js:174
      throw er&lt;span class="p"&gt;;&lt;/span&gt; // Unhandled &lt;span class="s1"&gt;'error'&lt;/span&gt; event
      ^

Error: accept EINVAL
    at TCP.onconnection &lt;span class="o"&gt;(&lt;/span&gt;net.js:1497:24&lt;span class="o"&gt;)&lt;/span&gt;
Emitted &lt;span class="s1"&gt;'error'&lt;/span&gt; event at:
    at TCP.onconnection &lt;span class="o"&gt;(&lt;/span&gt;net.js:1497:10&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hah, didn’t take long for things to south, the exact same error again 😔. We hooked the libc wrapper for &lt;code&gt;accept4&lt;/code&gt; but it was never called?&lt;/p&gt;

&lt;p&gt;Here are a few reasons that I can think of why this could not be working:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node is probably into some sorcery and has decided to screw with me this time.&lt;/li&gt;
&lt;li&gt;Maybe Node never even calls accept, but instead something else to accept new connections.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I don’t believe in sorcery, so I will dig into the second reasoning here.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;strace&lt;/code&gt; only shows us the underlying system calls made by a process. So let’s do some static analysis and look for some functions similar to &lt;code&gt;accept&lt;/code&gt; or &lt;code&gt;accept4&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I will be using &lt;a href="https://ghidra-sre.org/"&gt;Ghidra&lt;/a&gt; here, a reverse engineering toolkit that comes in super handy when decompiling a binary. So let’s load our node binary into Ghidra and analyze it!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PPlQDA2T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xuj2oadzl7kkbhl7erzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PPlQDA2T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xuj2oadzl7kkbhl7erzv.png" alt="mirrord-ghidra-search" width="880" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So looks like we won’t find anything useful unless we import some more relevant shared objects used by our node binary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pb3Z6h2M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ip667dtv4t41355kai4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pb3Z6h2M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ip667dtv4t41355kai4.png" alt="mirrord-ghidra-imports" width="316" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finding paths for shared library dependencies can be a bit painful with &lt;code&gt;find&lt;/code&gt;, so instead, I will use &lt;a href="https://man7.org/linux/man-pages/man1/ldd.1.html"&gt;ldd&lt;/a&gt; here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bigbear@metalbear:~/mirrord&lt;span class="nv"&gt;$ &lt;/span&gt;which node
/usr/bin/node
bigbear@metalbear:~/mirrord&lt;span class="nv"&gt;$ &lt;/span&gt;ldd /usr/bin/node
        linux-vdso.so.1 &lt;span class="o"&gt;(&lt;/span&gt;0x00007fffda938000&lt;span class="o"&gt;)&lt;/span&gt;
        libnode.so.64 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libnode.so.64 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f9934a00000&lt;span class="o"&gt;)&lt;/span&gt;
        libpthread.so.0 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libpthread.so.0 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f99349dd000&lt;span class="o"&gt;)&lt;/span&gt;
        libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f99347eb000&lt;span class="o"&gt;)&lt;/span&gt;
        libz.so.1 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libz.so.1 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f99347cf000&lt;span class="o"&gt;)&lt;/span&gt;
        libuv.so.1 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libuv.so.1 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f993479e000&lt;span class="o"&gt;)&lt;/span&gt;
        libcares.so.2 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libcares.so.2 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f993478a000&lt;span class="o"&gt;)&lt;/span&gt;
        libnghttp2.so.14 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libnghttp2.so.14 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f993475f000&lt;span class="o"&gt;)&lt;/span&gt;
        libcrypto.so.1.1 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libcrypto.so.1.1 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f9934489000&lt;span class="o"&gt;)&lt;/span&gt;
        libssl.so.1.1 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libssl.so.1.1 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f99343f6000&lt;span class="o"&gt;)&lt;/span&gt;
        libicui18n.so.66 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libicui18n.so.66 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f99340f7000&lt;span class="o"&gt;)&lt;/span&gt;
        libicuuc.so.66 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libicuuc.so.66 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f9933f11000&lt;span class="o"&gt;)&lt;/span&gt;
        libdl.so.2 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libdl.so.2 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f9933f0b000&lt;span class="o"&gt;)&lt;/span&gt;
        libstdc++.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libstdc++.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f9933d27000&lt;span class="o"&gt;)&lt;/span&gt;
        libm.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libm.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f9933bd8000&lt;span class="o"&gt;)&lt;/span&gt;
        libgcc_s.so.1 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libgcc_s.so.1 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f9933bbd000&lt;span class="o"&gt;)&lt;/span&gt;
        /lib64/ld-linux-x86-64.so.2 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f9935fcb000&lt;span class="o"&gt;)&lt;/span&gt;
        libicudata.so.66 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/x86_64-linux-gnu/libicudata.so.66 &lt;span class="o"&gt;(&lt;/span&gt;0x00007f99320fc000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s start with &lt;code&gt;libnode&lt;/code&gt; and look for the &lt;code&gt;accept&lt;/code&gt; like symbols/functions again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KJObRB-P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wzo95rj7ggf7z4m3jj2f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KJObRB-P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wzo95rj7ggf7z4m3jj2f.png" alt="mirrord-ghidra-accept" width="880" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That gives us some hope! And probably a good lead to follow -&lt;/p&gt;

&lt;p&gt;A quick Google search tells me that the &lt;code&gt;uv__accept&lt;/code&gt; function belongs to &lt;code&gt;libuv&lt;/code&gt; which is also listed as a node dependency &lt;a href="https://nodejs.org/en/docs/meta/topics/dependencies/#dependencies"&gt;here&lt;/a&gt;. Let's load &lt;code&gt;libuv&lt;/code&gt; and carry on our search!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4mCe1fFN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jivjovghe8vm8omdl7km.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4mCe1fFN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jivjovghe8vm8omdl7km.png" alt="mirrord-ghidra-uv__accept" width="880" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s a decompiled version of &lt;code&gt;uv__accept&lt;/code&gt; which clearly shows it makes calls to either &lt;code&gt;uv__accept4&lt;/code&gt; or &lt;code&gt;accept&lt;/code&gt;. We already have our hook for &lt;code&gt;accept&lt;/code&gt; in place, so we probably don’t need to worry about that, but let's look into &lt;code&gt;uv__accept4&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--puxdHTVa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ak7wenzjy4u0ptak5mz1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--puxdHTVa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ak7wenzjy4u0ptak5mz1.png" alt="mirrord-ghidra-uvdecompile" width="615" height="153"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AH! This is it. It all makes sense now. &lt;code&gt;uv__accept4&lt;/code&gt; is directly making the syscall instead of using the libc wrapper. So let’s hook &lt;code&gt;uv__accept4&lt;/code&gt; to behave the same as our hook for &lt;code&gt;accept/accept4&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[cfg(target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"linux"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;accept4_detour&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;sockfd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;sockaddr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;address_len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;socklen_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;accept_fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;libc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;accept4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sockfd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;accept_fd&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;accept_fd&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sockfd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accept_fd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yet another hopeful &lt;code&gt;GET&lt;/code&gt; request -&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl http://192.168.49.2:32118&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;2022-06-24T18:44:55.391978Z DEBUG mirrord: uv__accept4 hooked
2022-06-24T18:44:55.392238Z DEBUG mirrord: accept4 hooked
2022-06-24T18:44:55.392321Z DEBUG mirrord: accept hooked
2022-06-24T18:44:55.722728Z DEBUG mirrord: socket called
2022-06-24T18:44:55.722935Z DEBUG mirrord: &lt;span class="nb"&gt;bind &lt;/span&gt;called
2022-06-24T18:44:55.723112Z DEBUG mirrord: listen called
server listening to &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;:&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
2022-06-24T18:45:00.392698Z DEBUG mirrord: send message to client 80
2022-06-24T18:45:02.962967Z DEBUG mirrord: new connection &lt;span class="nb"&gt;id&lt;/span&gt;: 0
2022-06-24T18:45:02.963693Z DEBUG mirrord: No socket found &lt;span class="k"&gt;for &lt;/span&gt;connection_id: 0
2022-06-24T18:45:02.963787Z DEBUG mirrord: Accept called with sockfd 28, addr 0x0, addrlen 0x0
2022-06-24T18:45:02.963905Z DEBUG mirrord: Accepted connection from read_fd:30, write_sock:SocketpairStream &lt;span class="o"&gt;{&lt;/span&gt; raw_fd: 31 &lt;span class="o"&gt;}&lt;/span&gt;
2022-06-24T18:45:02.963949Z DEBUG mirrord: writing pending data &lt;span class="k"&gt;for &lt;/span&gt;connection_id: 0
new client connection from 127.0.0.1:8080
2022-06-24T18:45:02.965490Z DEBUG mirrord: Accept called with sockfd 28, addr 0x0, addrlen 0x0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion 🤠
&lt;/h2&gt;

&lt;p&gt;Time to celebrate? Yes! We were finally able to find the correct function to hook and make &lt;code&gt;accept&lt;/code&gt; work the way want it to work in the context of mirrord.&lt;br&gt;
Writing hooks is not easy - not only does it take an extensive amount of time, but also a ton of research. That's why we try to follow a &lt;a href="https://mirrord.dev/docs/developer/new_feature/"&gt;feature guide&lt;/a&gt; which lets us work on new features/hooks based on real use cases and needs so that we don't end up wasting time on something that no one would actually use.&lt;/p&gt;

&lt;p&gt;Hope you enjoyed reading the post! Please feel free to reach out to me with feedback at &lt;a href="//mehula@metalbear.co"&gt;mehula@metalbear.co&lt;/a&gt;/&lt;a href="https://discord.com/invite/J5YSrStDKD"&gt;Discord&lt;/a&gt;, or provide any suggestions/open issues/PRs on our &lt;a href="https://github.com/metalbear-co/metalbear.co"&gt;website&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits 🐻
&lt;/h2&gt;

&lt;p&gt;On a personal note, these past two months working at MetalBear on mirrord have not only been an amazing learning experience but have also given me a chance to work with some extremely talented engineers and Rust enthusiasts. Just want to take a moment and thank my team for their guidance and mentorship with this little &lt;a href="https://www.reddit.com/r/ProgrammerHumor/comments/vdumxo/you_can_do_it_jr_devs/"&gt;meme&lt;/a&gt; -&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hqVmIwyo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ho7n5chvmn4bw1ry21gt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hqVmIwyo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ho7n5chvmn4bw1ry21gt.png" alt="senior-junior-meme" width="880" height="880"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally posted @ MetalBear's &lt;a href="https://metalbear.co/blog/mirrord-internals-hooking-libc-functions-in-rust-and-fixing-bugs/"&gt;blog&lt;/a&gt;&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Available as &lt;code&gt;DYLD_INSERT_LIBRARIES&lt;/code&gt; on OSX. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Webservers also make use of &lt;a href="https://man7.org/linux/man-pages/man2/select.2.html"&gt;select&lt;/a&gt; between &lt;code&gt;listen&lt;/code&gt; and &lt;code&gt;accept&lt;/code&gt;. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>kubernetes</category>
      <category>rust</category>
      <category>node</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
