<?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: Davidson Rafael</title>
    <description>The latest articles on DEV Community by Davidson Rafael (@davidson_rafael).</description>
    <link>https://dev.to/davidson_rafael</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4111691%2F205879de-81d0-40da-9ca5-f1769fd02517.png</url>
      <title>DEV Community: Davidson Rafael</title>
      <link>https://dev.to/davidson_rafael</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidson_rafael"/>
    <language>en</language>
    <item>
      <title>A Slow Wi-Fi Connection Led Me to Maintain an Abandoned Network Tool</title>
      <dc:creator>Davidson Rafael</dc:creator>
      <pubDate>Sat, 05 Sep 2026 23:29:14 +0000</pubDate>
      <link>https://dev.to/davidson_rafael/a-slow-wi-fi-connection-led-me-to-maintain-an-abandoned-network-tool-3jmg</link>
      <guid>https://dev.to/davidson_rafael/a-slow-wi-fi-connection-led-me-to-maintain-an-abandoned-network-tool-3jmg</guid>
      <description>&lt;h2&gt;
  
  
  How it started
&lt;/h2&gt;

&lt;p&gt;I first found evillimiter when I was still in vocational high school. At the time, my family had a 20 Mbps connection at home. We shared it with a neighbor who paid us for access, and for a while that arrangement seemed fine.&lt;/p&gt;

&lt;p&gt;Then the connection became painfully slow. Even downloading a 100 MB file could take ages. At first, I assumed it was just the usual ISP trouble, but it kept happening every day.&lt;/p&gt;

&lt;p&gt;Around the same time, I was really into experimenting with Kali Linux. While looking through networking tools and GitHub repositories, I came across &lt;a href="https://github.com/bitbrute/evillimiter" rel="noopener noreferrer"&gt;evillimiter&lt;/a&gt; by &lt;a href="https://github.com/bitbrute" rel="noopener noreferrer"&gt;bitbrute&lt;/a&gt;. It was a Python tool that could scan, monitor, and limit devices on a local network without requiring access to the router's admin panel.&lt;/p&gt;

&lt;p&gt;Naturally, the first thing I did was scan my own network. I expected to see a few familiar devices. Instead, evillimiter found somewhere between eight and twelve active hosts.&lt;/p&gt;

&lt;p&gt;That was far more than my family and our neighbor should have been using. My immediate suspicion was that the neighbor had started reselling access to our Wi-Fi. I never confirmed it, but seeing that many devices on a 20 Mbps connection certainly explained why downloading anything had become such a struggle.&lt;/p&gt;

&lt;p&gt;So I tried using evillimiter on the devices I did not recognize and limited their bandwidth. Honestly, I found it pretty funny at the time. After that, I changed the Wi-Fi password and started paying more attention to who was connected to the network.&lt;/p&gt;

&lt;p&gt;That was my introduction to evillimiter. What began as a practical solution to a very specific problem also became one of the projects that made networking feel real to me. I was no longer just reading about packets, hosts, and ARP tables. I could see how they affected a network I used every day.&lt;/p&gt;

&lt;p&gt;It combines &lt;a href="https://en.wikipedia.org/wiki/ARP_spoofing" rel="noopener noreferrer"&gt;ARP spoofing&lt;/a&gt; with &lt;a href="https://en.wikipedia.org/wiki/Traffic_shaping" rel="noopener noreferrer"&gt;traffic shaping&lt;/a&gt;. Traffic from the target device is routed through your machine, where &lt;code&gt;tc&lt;/code&gt; and &lt;code&gt;iptables&lt;/code&gt; can throttle it. All you need is a machine on the same LAN.&lt;/p&gt;

&lt;p&gt;Years later, another bandwidth problem brought me back to the project. A friend of mine regularly used the campus Wi-Fi and LAN so heavily that their usage could reach hundreds of gigabytes in a single day. Sometimes an entire classroom would be left with a connection that was barely usable because one person was consuming almost all of the available bandwidth.&lt;/p&gt;

&lt;p&gt;It reminded me of that 20 Mbps connection at home. The scale was different, but the problem was the same: one user could make the network miserable for everyone else. I reached for evillimiter again to cap the bandwidth going to and from that device, leaving enough capacity for the rest of the room to stay online.&lt;/p&gt;

&lt;p&gt;Looking back, changes to a campus network should be handled by its administrators or done with their explicit permission. Still, the experience showed me that evillimiter solved a real problem I had now encountered twice. Fair bandwidth allocation is not always about getting the fastest connection. Sometimes it is simply about making sure everyone gets a usable share.&lt;/p&gt;

&lt;p&gt;But when I tried evillimiter again, quite a few things no longer worked as expected. The two commands I needed most, &lt;code&gt;limit&lt;/code&gt; and &lt;code&gt;block&lt;/code&gt;, appeared to succeed but did not actually apply the restriction on my setup. Digging into the code revealed part of the problem: failures from the underlying &lt;code&gt;tc&lt;/code&gt; and &lt;code&gt;iptables&lt;/code&gt; commands could be swallowed while evillimiter still printed a success message. When I checked the upstream repository, I found open issues describing similar problems, but the project had gone quiet and they were no longer being addressed. Pull requests were also sitting without responses.&lt;/p&gt;

&lt;p&gt;IPv6 support was missing as well. On a dual-stack network, a device could continue using IPv6 even after its IPv4 traffic had been limited. Fixing one problem kept revealing another, and it became clear that a small local patch would not be enough.&lt;/p&gt;

&lt;p&gt;At that point, I thought: why not continue maintaining the project myself? It gave me a useful tool again, but it was also a chance to learn from a real codebase, dig deeper into networking, and pick up insights I would not get from tutorials alone. What began as a fix for my own situation gradually became an actively maintained fork.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I added
&lt;/h2&gt;

&lt;p&gt;Starting from upstream's last release, v1.5.0, I added the following to &lt;a href="https://github.com/DavidsonRafaelK/evillimiter" rel="noopener noreferrer"&gt;my fork&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IPv6 (NDP) spoofing.&lt;/strong&gt; &lt;code&gt;limit&lt;/code&gt; and &lt;code&gt;block&lt;/code&gt; now cover a host's IPv6 traffic instead of leaving it untouched.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Config file support.&lt;/strong&gt; Defaults such as the interface, watch range, and log file can go in &lt;code&gt;~/.config/evillimiter/config.ini&lt;/code&gt;, so they do not need to be entered every session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;--log-file&lt;/code&gt;&lt;/strong&gt; to persist every ok/error message to disk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A &lt;code&gt;--version&lt;/code&gt; flag&lt;/strong&gt;, so checking the installed version does not require reading the source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;mDNS/NetBIOS/DHCP hostname fallback&lt;/strong&gt; when reverse DNS comes up empty.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Broader &lt;code&gt;block&lt;/code&gt; coverage.&lt;/strong&gt; It now applies to &lt;code&gt;INPUT&lt;/code&gt; and &lt;code&gt;OUTPUT&lt;/code&gt; as well as &lt;code&gt;FORWARD&lt;/code&gt;, including traffic to and from the machine running evillimiter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;watch&lt;/code&gt; shows live Online/Offline status&lt;/strong&gt; per host and auto-adds hosts on &lt;code&gt;limit&lt;/code&gt;/&lt;code&gt;block&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Host tracking by MAC address instead of IP.&lt;/strong&gt; This fixes reconnect detection and a hash/equality bug caused by IP-based tracking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Randomized MAC detection.&lt;/strong&gt; Locally administered addresses are marked as &lt;code&gt;(random)&lt;/code&gt; in the host table, making devices that may return under a new identity easier to spot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accurate failure reporting.&lt;/strong&gt; &lt;code&gt;limit&lt;/code&gt; and &lt;code&gt;block&lt;/code&gt; previously reported success even when the underlying &lt;code&gt;tc&lt;/code&gt; or &lt;code&gt;iptables&lt;/code&gt; command failed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More reliable cleanup.&lt;/strong&gt; Restriction teardown no longer runs duplicate or irrelevant commands for combined upload and download rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;scan --intensity [1,2,3]&lt;/code&gt;&lt;/strong&gt;, which lets you trade scan speed for more thorough discovery on lossy networks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An &lt;code&gt;auto_scan&lt;/code&gt; config option&lt;/strong&gt; to run &lt;code&gt;scan&lt;/code&gt; and &lt;code&gt;hosts&lt;/code&gt; automatically at startup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;limit&lt;/code&gt; accepts independent up/down rates&lt;/strong&gt; in one call, e.g. &lt;code&gt;limit 4 200kbit/1mbit&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;netem [ID] --delay [ms] --loss [%]&lt;/code&gt;&lt;/strong&gt; to add delay or packet loss to an already limited host. This is useful when testing an application on a poor connection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More useful host and monitoring output.&lt;/strong&gt; The host table shows the assigned rate and direction, while &lt;code&gt;monitor&lt;/code&gt; tracks every discovered host rather than only restricted ones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correct totals at terabyte scale.&lt;/strong&gt; The byte formatter no longer produces incorrect output for very large usage totals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command history&lt;/strong&gt; persisted across sessions, navigable with ↑/↓.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI&lt;/strong&gt; that runs the test suite on every push and pull request.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://github.com/DavidsonRafaelK/evillimiter#fork-specific-changes" rel="noopener noreferrer"&gt;README&lt;/a&gt; has the complete list and the changelog going back to the upstream project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick look
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/DavidsonRafaelK/evillimiter.git
&lt;span class="nb"&gt;cd &lt;/span&gt;evillimiter
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt; .venv/bin/evillimiter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once inside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scan                        # find hosts on your network
hosts                       # list them with IDs
limit 4 200kbit/1mbit       # throttle host 4: 200kbit up, 1mbit down
watch                       # see who's online/offline
monitor                     # live bandwidth usage of everyone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Current limitations
&lt;/h2&gt;

&lt;p&gt;There are still a few important limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rate limiting works on IPv4, while IPv6 traffic can only be blocked. The underlying &lt;code&gt;tc&lt;/code&gt; and &lt;code&gt;iptables&lt;/code&gt; setup does not shape IPv6 traffic.&lt;/li&gt;
&lt;li&gt;A phone that's blocked on WiFi can just switch to LTE/5G. That traffic never touches your network.&lt;/li&gt;
&lt;li&gt;Devices using MAC randomization may appear as a new host when they reconnect, so previous restrictions will not follow them.&lt;/li&gt;
&lt;li&gt;An existing download or stream may continue briefly using a stale ARP or NDP cache entry. New connections are caught immediately.&lt;/li&gt;
&lt;li&gt;Devices on another subnet or VLAN cannot be discovered. This can also affect mesh networks that place different bands on separate subnets.&lt;/li&gt;
&lt;li&gt;A device with another network path, such as a laptop connected through Ethernet as well as Wi-Fi, can route around the restriction.&lt;/li&gt;
&lt;li&gt;Enterprise switches with Dynamic ARP Inspection may block the spoofing entirely. This project is aimed at home and small networks, not locked-down corporate environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A note on responsible use
&lt;/h2&gt;

&lt;p&gt;ARP and NDP spoofing interfere with other devices' traffic by design. &lt;strong&gt;Only use this tool on a network you own or have explicit written permission to test.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it out
&lt;/h2&gt;

&lt;p&gt;If you need bandwidth controls on your own network without access to the router, or want to study how ARP/NDP spoofing and traffic shaping work in practice, you can find the project here:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/DavidsonRafaelK/evillimiter" rel="noopener noreferrer"&gt;github.com/DavidsonRafaelK/evillimiter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Issues, feature requests, and pull requests are welcome. See &lt;a href="https://github.com/DavidsonRafaelK/evillimiter/blob/master/CONTRIBUTING.md" rel="noopener noreferrer"&gt;CONTRIBUTING.md&lt;/a&gt; for details. If the project is useful to you, a star also helps other people find it.&lt;/p&gt;

</description>
      <category>python</category>
      <category>networking</category>
      <category>security</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
