DEV Community

Cover image for A Slow Wi-Fi Connection Led Me to Maintain an Abandoned Network Tool
Davidson Rafael
Davidson Rafael

Posted on AI-assisted

A Slow Wi-Fi Connection Led Me to Maintain an Abandoned Network Tool

How it started

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.

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.

Around the same time, I was really into experimenting with Kali Linux. While looking through networking tools and GitHub repositories, I came across evillimiter by bitbrute. 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.

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.

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.

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.

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.

It combines ARP spoofing with traffic shaping. Traffic from the target device is routed through your machine, where tc and iptables can throttle it. All you need is a machine on the same LAN.

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.

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.

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.

But when I tried evillimiter again, quite a few things no longer worked as expected. The two commands I needed most, limit and block, 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 tc and iptables 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.

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.

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.

What I added

Starting from upstream's last release, v1.5.0, I added the following to my fork:

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

The README has the complete list and the changelog going back to the upstream project.

Quick look

git clone https://github.com/DavidsonRafaelK/evillimiter.git
cd evillimiter
python3 -m venv .venv
source .venv/bin/activate
pip install .
sudo .venv/bin/evillimiter
Enter fullscreen mode Exit fullscreen mode

Once inside:

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
Enter fullscreen mode Exit fullscreen mode

Current limitations

There are still a few important limitations:

  • Rate limiting works on IPv4, while IPv6 traffic can only be blocked. The underlying tc and iptables setup does not shape IPv6 traffic.
  • A phone that's blocked on WiFi can just switch to LTE/5G. That traffic never touches your network.
  • Devices using MAC randomization may appear as a new host when they reconnect, so previous restrictions will not follow them.
  • An existing download or stream may continue briefly using a stale ARP or NDP cache entry. New connections are caught immediately.
  • Devices on another subnet or VLAN cannot be discovered. This can also affect mesh networks that place different bands on separate subnets.
  • A device with another network path, such as a laptop connected through Ethernet as well as Wi-Fi, can route around the restriction.
  • 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.

A note on responsible use

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

Try it out

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:

👉 github.com/DavidsonRafaelK/evillimiter

Issues, feature requests, and pull requests are welcome. See CONTRIBUTING.md for details. If the project is useful to you, a star also helps other people find it.

Top comments (0)