<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Peakhour.IO - Technical</title><link href="https://www.peakhour.io/" rel="alternate"></link><link href="https://www.peakhour.io/feeds/technical.atom.xml" rel="self"></link><id>https://www.peakhour.io/</id><updated>2026-07-29T00:00:00+10:00</updated><entry><title>ZDNS - scan the entire internet</title><link href="https://www.peakhour.io/blog/zdns/" rel="alternate"></link><published>2023-06-20T13:00:00+10:00</published><updated>2026-07-29T00:00:00+10:00</updated><author><name>AC</name></author><id>tag:www.peakhour.io,2023-06-20:/blog/zdns/</id><summary type="html">&lt;p&gt;Details the use of ZDNS, a high-performance DNS toolkit, to create a comprehensive Reverse DNS (rDNS) lookup database by scanning the entire internet, and how randomizing the IP space overcomes UDP timeout issues.&lt;/p&gt;</summary><content type="html">&lt;p&gt;The lack of a free &lt;a href="/learning/reverse-dns-lookup/"&gt;Reverse DNS&lt;/a&gt; (rDNS) lookup database has made large-scale DNS research harder. To address this,
we used ZDNS, an open-source, high-performance DNS toolkit developed by Stanford University, to create our own
rDNS database. To reduce UDP timeout issues during rDNS operations, we devised a scan-ordering approach that randomised
the IP space and improved the efficiency of the scanning process.&lt;/p&gt;
&lt;h2&gt;Leveraging ZDNS for rDNS Lookups Across the Internet&lt;/h2&gt;
&lt;p&gt;Understanding rDNS is useful for internet operations and research. Active DNS measurement helps us inspect how providers
advertise the use of their IP address space. One of the components of this ecosystem is Reverse DNS (rDNS), which serves
an important role in IP database categorisation and ASN (Autonomous System Number) classification. However, running rDNS
across the entire internet is not a trivial task.&lt;/p&gt;
&lt;p&gt;Previously, Rapid7 provided a free database for rDNS lookups, but it has discontinued the offering. This situation has
prompted the need to create our own database, calling for a robust, efficient, and scalable tool to accomplish
the task. ZDNS was the right fit.&lt;/p&gt;
&lt;h2&gt;Introducing ZDNS&lt;/h2&gt;
&lt;p&gt;ZDNS, a part of the ZMap.io project, is a capable tool developed by Stanford University to support scalable and
reproducible DNS research. ZDNS is an open-source DNS measurement framework specifically optimised for large-scale
DNS research on the public internet. It can resolve 50 million domains in 10 minutes and query the PTR records of the
complete public IPv4 address space in approximately 12 hours.&lt;/p&gt;
&lt;p&gt;This high-performance toolkit offers a modular interface, enabling researchers to safely implement new functionalities.
Its architecture is designed to expose &lt;a href="/learning/web-concepts/what-is-reverse-dns-lookup/"&gt;DNS lookup&lt;/a&gt; chains by performing recursive resolution. ZDNS supports a
command-line interface and outputs results in JSON, a machine-parsable format.&lt;/p&gt;
&lt;h2&gt;Enhancements by ZDNS&lt;/h2&gt;
&lt;p&gt;ZDNS's architecture and feature set are tailored to the challenges of extensive DNS research. Its guiding
principles are that the DNS lookup chain is exposed, and that the tool is safe, easy to use, and extensible.&lt;/p&gt;
&lt;p&gt;ZDNS's performance optimisations make it a suitable tool for DNS experiments that require querying a large number of
names. Parallelism, UDP socket reuse, and selective caching are some of the critical performance optimisations that
enable ZDNS to efficiently handle large volumes of DNS queries.&lt;/p&gt;
&lt;p&gt;ZDNS's scalability, execution time, and success rate have been evaluated against several existing tools, showcasing its
performance. For instance, when it comes to exposing the DNS lookup chain, ZDNS is 85 times faster than Dig.
ZDNS also outperforms other higher-performance tools, achieving 2.6 to 3.6 times more successful queries per second and
experiencing about 30% less packet drop than MassDNS.&lt;/p&gt;
&lt;h2&gt;Our rDNS Journey&lt;/h2&gt;
&lt;p&gt;When we started scanning the whole internet with rDNS, we hit a practical roadblock: UDP timeouts made the scans
slow. The system spent too much time waiting for responses from parts of the internet that were either empty or broken.&lt;/p&gt;
&lt;p&gt;We used two changes. Firstly, instead of scanning the internet's addresses in order, we mixed them
up and scanned randomly. This spread out our requests and stopped the system from getting stuck on troublesome ranges.
Secondly, we checked smaller sections of the internet first, so we did not waste time waiting for big chunks of the
internet that weren't responding.&lt;/p&gt;
&lt;p&gt;With these changes, we scanned the whole internet in &lt;em&gt;13 days&lt;/em&gt;, finding over a &lt;em&gt;billion addresses&lt;/em&gt;. The main lesson was
straightforward: scan order matters when timeout behaviour dominates runtime.&lt;/p&gt;
&lt;h2&gt;The result depended on scan order&lt;/h2&gt;
&lt;p&gt;ZDNS gave us the throughput and structured output we needed, but the tool alone did not make the scan finish. The
decisive change was to stop walking adjacent address ranges in sequence. Randomising the work kept slow or empty ranges
from dominating a worker's runtime and brought the full scan down to 13 days.&lt;/p&gt;
&lt;p&gt;ZDNS is available on GitHub, and the IMC 2022 paper covers its architecture and benchmark results. If you repeat this
kind of measurement, treat target ordering, timeout policy, responsible scan rates, and restartability as part of the
design rather than as command-line details.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1^"&gt;
&lt;p&gt;Izhikevich, L., Akiwate, G., Berger, B., Drakontaidis, S., Ascheman, A., Pearce, P., Adrian, D., &amp;amp; Durumeric, Z. (2022). ZDNS: a fast DNS toolkit for internet measurement. In Proceedings of the 22nd ACM Internet Measurement Conference (pp. 33-43). https://doi.org/10.1145/3517745.3561434&amp;#160;&lt;a class="footnote-backref" href="#fnref:1^" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2^"&gt;
&lt;p&gt;ZMap Project. (n.d.). ZDNS. GitHub. Retrieved 2023-05-15 13:00, from https://github.com/zmap/zdns.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2^" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="Technical"></category><category term="DNS"></category><category term="CDN"></category><category term="Rate Limiting"></category><category term="Residential Proxies"></category><category term="DDoS"></category></entry><entry><title>Double MAD?</title><link href="https://www.peakhour.io/blog/double-mad/" rel="alternate"></link><published>2023-05-15T13:00:00+10:00</published><updated>2023-05-15T13:00:00+10:00</updated><author><name>AC</name></author><id>tag:www.peakhour.io,2023-05-15:/blog/double-mad/</id><summary type="html">&lt;p&gt;This article explores the use of Double Median Absolute Deviation (Double MAD) for anomaly detection in time series data, particularly in skewed or non-symmetric distributions.&lt;/p&gt;</summary><content type="html">&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;This&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;explores&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Median&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Absolute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Deviation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MAD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;anomaly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;detection&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;learning&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;threat&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;detection&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;anomaly&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;detection&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;series&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;particularly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;skewed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;symmetric&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;distributions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MAD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;which&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;calculates&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;two&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;median&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;absolute&lt;/span&gt;
&lt;span class="n"&gt;deviations&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;—&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;below&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;median&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;above&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;—&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;provides&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;more&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nuanced&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;approach&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;than&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;traditional&lt;/span&gt;
&lt;span class="n"&gt;MAD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;allowing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;accurate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;detection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;anomalies&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;even&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;skewed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;distributions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;We&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;also&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;delve&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;into&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;its&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;identifying&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;slow&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;abuse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;like&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bots&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;catching&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;anomalies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;However&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;important&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MAD&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;
&lt;span class="n"&gt;limitations&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;such&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;capturing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seasonal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;over&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;comparison&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;also&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;drawn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;
&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;highlighting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;between&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;two&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;depends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nature&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;provides&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;insights&lt;/span&gt;
&lt;span class="n"&gt;into&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;practical&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;implementation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MAD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;its&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;potential&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;improve&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;analysis&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;toolkit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Operational systems increasingly rely on time-series data for decisions. Anomaly detection is one practical use: by
identifying patterns that deviate from the norm, businesses can investigate potential issues early or understand
unexpected opportunities.&lt;/p&gt;
&lt;p&gt;One useful technique for anomaly detection is the Median Absolute Deviation (MAD) and, more specifically, its extension,
the Double MAD. This article explains where Double MAD fits in time-series anomaly detection and how it can help identify
anomalous clients.&lt;/p&gt;
&lt;h2&gt;Understanding MAD and Double MAD&lt;/h2&gt;
&lt;p&gt;MAD, a robust measure of variability, is less susceptible to outliers than standard deviation. It calculates the median
of absolute deviations from the data's median, often providing a better representation of 'normal' behaviour in
datasets with skewed distributions or outliers.&lt;/p&gt;
&lt;p&gt;Double MAD is an extension of MAD, where two MADs are calculated — one for the data below the median and another for the
data above. This split gives the detection process a better fit for asymmetric data, which is common in real-world time
series data.&lt;/p&gt;
&lt;h2&gt;Why Double MAD?&lt;/h2&gt;
&lt;p&gt;While MAD provides a robust way to understand the 'normal' range of a dataset, it assumes a symmetric distribution of
data around the median, which may not always hold true. Double MAD is useful where that assumption breaks down, offering
an improved anomaly detection process for skewed or asymmetric datasets.&lt;/p&gt;
&lt;p&gt;In time-series analysis, especially with 24-hour cycles like web traffic or server usage, patterns can exhibit
seasonality and trend components. These patterns can often be asymmetric, making Double MAD a valuable tool for
capturing the variability in different parts of the data.&lt;/p&gt;
&lt;h2&gt;Using Double MAD in Anomaly Detection&lt;/h2&gt;
&lt;p&gt;The Double MAD implementation provided uses Rust, a system programming language known for speed and memory safety. The
code calculates the lower and upper MAD values, along with their respective thresholds. Anomalies can then be detected by
comparing each data point to these thresholds.&lt;/p&gt;
&lt;p&gt;An anomaly is defined as a data point that deviates significantly from the expected range. If a data point falls below
the lower MAD threshold or above the upper one, it can be flagged as an anomaly. This approach is especially effective
when handling datasets with high variability or extreme values.&lt;/p&gt;
&lt;h2&gt;Double MAD for Anomalous Client Detection&lt;/h2&gt;
&lt;p&gt;Beyond time-series data, Double MAD can also be instrumental in identifying anomalous behaviour among clients. By
comparing each client's behaviour against the Double MAD of the time-series data, teams can pinpoint clients that deviate
from the norm.&lt;/p&gt;
&lt;p&gt;For instance, in the context of web service usage, an anomalous client might be one that is sending an unusually high or
low number of requests. By using Double MAD, you can flag such outliers and take appropriate action, such as
investigating potential misuse or reaching out to understand and address any issues they may be facing.&lt;/p&gt;
&lt;h2&gt;Detecting Lower-Range Anomalies: A Case of Slow Abuse&lt;/h2&gt;
&lt;p&gt;An interesting application of Double MAD is in detecting lower-range anomalies, a pattern often associated with slow
abuse such as bots or Distributed Denial of Service (DDoS) attacks. These abuses are characterised by an unusually low
frequency of activity that is consistent over a prolonged period. This consistent, low-level activity can fly under the
radar of typical anomaly detection systems.&lt;/p&gt;
&lt;p&gt;By setting a lower MAD threshold, Double MAD can effectively detect these lower-range anomalies, providing early warning
of slow abuse. Its ability to detect both high and low anomalies makes Double MAD a flexible tool for anomaly detection.&lt;/p&gt;
&lt;h2&gt;The Math Behind Double MAD&lt;/h2&gt;
&lt;p&gt;To illustrate the power of Double MAD, let's consider a dataset from a right-skewed distribution. Applying the
conventional MAD approach might lead to false positives where normal data points are marked as outliers. This is because
MAD uses a symmetric interval around the median, which doesn't account for the skewed nature of our data.&lt;/p&gt;
&lt;p&gt;With Double MAD, we instead calculate two MADs — one for the data below the median (MAD-lower) and another for the data
above (MAD-upper). Outlier thresholds are then defined using these two MADs. The lower threshold is calculated as the
median minus a multiplier (k) times MAD-lower. The upper threshold is the median plus k times MAD-upper.&lt;/p&gt;
&lt;p&gt;This approach takes into account the asymmetric nature of our data, providing more accurate anomaly detection.
For example, in a right-skewed distribution, Double MAD would correctly identify only the extreme right tail values as
outliers without incorrectly flagging data points on the left tail.&lt;/p&gt;
&lt;h2&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;Accurate anomaly detection matters when teams rely on time-series data to operate and investigate systems. The Double
MAD approach provides a robust method for this, allowing businesses to better understand their data, spot potential
issues early, and make more informed decisions.&lt;/p&gt;
&lt;p&gt;Whether you're monitoring web traffic, server usage, or client behaviour, leveraging Double MAD can offer valuable
insights and help ensure your operations continue to run smoothly. The ability to detect both high and low anomalies
makes it especially powerful, providing protection against potential threats like slow abuse.&lt;/p&gt;
&lt;p&gt;Understanding and implementing Double MAD gives your data analysis toolkit a more complete view of asymmetric data and
helps you detect potential anomalies earlier.&lt;/p&gt;</content><category term="Technical"></category><category term="Anomaly Detection"></category><category term="Threat Detection"></category><category term="Bot Management"></category><category term="Residential Proxies"></category><category term="DDoS"></category></entry><entry><title>Double MAD vs the Rest</title><link href="https://www.peakhour.io/blog/double-mad-vs-zscore/" rel="alternate"></link><published>2023-05-15T13:00:00+10:00</published><updated>2023-05-15T13:00:00+10:00</updated><author><name>AC</name></author><id>tag:www.peakhour.io,2023-05-15:/blog/double-mad-vs-zscore/</id><summary type="html">&lt;p&gt;A look at the limitations of Double MAD for anomaly detection, and a comparison with the Z-score method, to help you choose the right approach for your data.&lt;/p&gt;</summary><content type="html">&lt;h2&gt;Limitations of Double MAD and Comparison with Z-Score&lt;/h2&gt;
&lt;p&gt;Double MAD is useful for anomaly detection, but it has clear limits. One is that it does not account for the shape of
seasonal data. Time series data often show cyclical patterns by time of day, week, or year. For instance, web traffic to
an e-commerce site might spike during holidays and dip on off-peak days.&lt;/p&gt;
&lt;p&gt;Double MAD can capture shifts in the median of these data, but it does not consider the shape or pattern within these
cycles. It might therefore miss anomalies that occur within a specific season, or flag normal seasonal variations as
anomalies.&lt;/p&gt;
&lt;p&gt;Another limitation is that Double MAD does not account for trends over time. If your time series data shows a consistent
increase or decrease, &lt;a href="/blog/double-mad/"&gt;Double MAD&lt;/a&gt; might misinterpret this trend as a series of anomalies.&lt;/p&gt;
&lt;h3&gt;Double MAD vs. Z-Score&lt;/h3&gt;
&lt;p&gt;In anomaly detection, Double MAD is often compared with the more traditional Z-score method. A Z-score measures how many
standard deviations a data point is from the mean. It assumes that the data follows a Gaussian (or normal) distribution,
which often does not hold true for real-world data.&lt;/p&gt;
&lt;p&gt;Double MAD, on the other hand, is a non-parametric method that does not make assumptions about the distribution of data.
This makes it more robust to outliers and skewed distributions.&lt;/p&gt;
&lt;p&gt;However, Z-score has an advantage when data follows a Gaussian distribution, or when the data size is large enough for
the Central Limit Theorem to take effect. It also accounts for the mean and standard deviation, giving it an edge in
datasets where these measures are informative.&lt;/p&gt;
&lt;p&gt;In contrast, Double MAD is more robust for datasets with outliers or skewed distributions, as it uses the median and
absolute deviations from the median, which are less sensitive to extreme values.&lt;/p&gt;
&lt;p&gt;Both Double MAD and Z-score have strengths, and the choice between them should be guided by the nature of your data.
Understanding these nuances helps you choose the method that fits your specific use case.&lt;/p&gt;</content><category term="Technical"></category><category term="Anomaly Detection"></category></entry><entry><title>Efficiently Generating and Printing All IPv4 Addresses in a Random Order</title><link href="https://www.peakhour.io/blog/linear-congruential-generator/" rel="alternate"></link><published>2023-05-15T13:00:00+10:00</published><updated>2023-05-15T13:00:00+10:00</updated><author><name>AC</name></author><id>tag:www.peakhour.io,2023-05-15:/blog/linear-congruential-generator/</id><summary type="html">&lt;p&gt;Explains how to efficiently generate all IPv4 addresses in a random order using a Linear Congruential Generator (LCG), a memory-efficient method for tasks like security testing and network simulation.&lt;/p&gt;</summary><content type="html">&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;In&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;we&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;explored&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;an&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;efficient&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;way&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;possible&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IPv4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;addresses&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Linear&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Congruential&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Generator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LCG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LCG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pseudorandom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;helps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;full&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IP&lt;/span&gt;
&lt;span class="n"&gt;addresses&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;without&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;consuming&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vast&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;amounts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;making&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;approach&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;suitable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;systems&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;constraints&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;We&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;also&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;provided&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demonstrating&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;concept&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;along&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;verify&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;its&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correctness&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;We&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;delved&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;into&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;importance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;randomising&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;addresses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;highlighting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;its&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;critical&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;areas&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;like&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;security&lt;/span&gt;
&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;load&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;balancing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;enhancing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;privacy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;web&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;scraping&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;However&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;technique&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s essential to&lt;/span&gt;
&lt;span class="n"&gt;respect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;privacy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;legality&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;misuse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;can&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lead&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;legal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;repercussions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ability&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IPv4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;addresses&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;powerful&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;especially&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;
&lt;span class="n"&gt;realm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;networking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cybersecurity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;can&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;achieved&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;efficiently&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LCG&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;approach&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In networking, some tasks require generating and printing every possible IPv4 address. Doing that in random order
without a large memory footprint is less straightforward. The IPv4 address space contains 2^32, or 4,294,967,296,
values. Storing all of them in memory at once is not feasible for most systems.&lt;/p&gt;
&lt;p&gt;This article uses a Linear Congruential Generator (LCG) to generate the full range without holding it in memory.&lt;/p&gt;
&lt;h2&gt;Linear Congruential Generator&lt;/h2&gt;
&lt;p&gt;A Linear Congruential Generator is a type of pseudorandom number generator that can run without storing the whole
sequence. It generates each next value from a linear equation based on the previous value. The basic form of the LCG is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;X_(n+1) = (a*X_n + c) mod m
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;c&lt;/code&gt;, and &lt;code&gt;m&lt;/code&gt; are constants, and &lt;code&gt;X_n&lt;/code&gt; is the nth number in the sequence. The initial seed or starting point
of the sequence is X_0.&lt;/p&gt;
&lt;p&gt;If we choose parameters such that the period of the LCG is maximum (equal to the modulus), and the modulus equals the
range of numbers we're generating (the number of possible IPv4 addresses in this case), then the LCG should generate
each number in the range exactly once before repeating.&lt;/p&gt;
&lt;p&gt;Here is that idea in Python:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;ipaddress&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lcg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modulus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Linear congruential generator.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;modulus&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;seed&lt;/span&gt;

&lt;span class="n"&gt;start_ip_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;0.0.0.0&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;end_ip_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;255.255.255.255&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;start_ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ipaddress&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IPv4Address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start_ip_str&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;end_ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ipaddress&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IPv4Address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;end_ip_str&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;modulus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;end_ip&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start_ip&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1664525&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1013904223&lt;/span&gt;
&lt;span class="n"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;  &lt;span class="c1"&gt;# Arbitrary seed&lt;/span&gt;

&lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lcg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modulus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modulus&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;ip_int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;start_ip&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ipaddress&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IPv4Address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip_int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The script first defines the parameters of the LCG. &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;c&lt;/code&gt;, and &lt;code&gt;seed&lt;/code&gt; are set to values used in Numerical Recipes'
LCG, a well-known and widely used LCG. The modulus is set to the total number of possible IPv4 addresses.&lt;/p&gt;
&lt;p&gt;The function &lt;code&gt;lcg()&lt;/code&gt; is implemented as a Python generator, yielding the next number in the sequence each time it is
called.&lt;/p&gt;
&lt;p&gt;The loop then generates and prints each IP address. It adds the output of the LCG to the start IP address, converts it
back to an IP address string, and prints it.&lt;/p&gt;
&lt;p&gt;This script generates and prints each IP address in random (more precisely, pseudorandom) order using very little
memory. Each IP address is printed exactly once, assuming the period of the LCG is maximum.&lt;/p&gt;
&lt;p&gt;The point is that a small pseudorandom number generator can walk a large range without materialising the whole list. The
code can still be tweaked and optimised for specific requirements and constraints.&lt;/p&gt;
&lt;h2&gt;The Importance of Randomising IP Addresses&lt;/h2&gt;
&lt;p&gt;Randomising IP addresses has practical uses in several networking workflows:&lt;/p&gt;
&lt;h3&gt;1. Security Testing and Penetration Testing&lt;/h3&gt;
&lt;p&gt;In cybersecurity, randomising IP addresses can help simulate attacks on a network from various sources. By using a range
of IP addresses in no particular order, penetration testers can mimic the unpredictable nature of real-world cyber
threats and build more robust test scenarios.&lt;/p&gt;
&lt;h3&gt;2. Load Balancing and Network Traffic Simulation&lt;/h3&gt;
&lt;p&gt;Randomising IP addresses is also useful in network traffic simulations. Network engineers and administrators can use
this approach to test network resilience and capacity. By sending requests to servers from randomised IP addresses, they
can evaluate how well their load balancing strategies are functioning and whether the network can handle high traffic
loads from various sources.&lt;/p&gt;
&lt;h3&gt;3. Anonymity and Privacy&lt;/h3&gt;
&lt;p&gt;In some cases, randomising IP addresses can help with privacy and anonymity. While it is not a foolproof method, using a
different IP address for each request can make it more challenging for online trackers to monitor user activity. It is a
common practice among privacy-focused internet users and is also used in some VPN (Virtual Private Network) services.&lt;/p&gt;
&lt;h3&gt;4. Web Scraping&lt;/h3&gt;
&lt;p&gt;Web scraping is another area where randomising IP addresses is useful. To prevent being blocked by anti-bot measures,
web scrapers often need to rotate their IP addresses. By using a different IP address for each request, they can avoid
being detected and blocked by the sites they are scraping.&lt;/p&gt;
&lt;p&gt;Randomising IP addresses can be useful in these cases, but privacy and legality still matter. Unauthorised network
scanning, privacy breaches, and cyberattacks are illegal and punishable under law.&lt;/p&gt;
&lt;p&gt;Generating and printing every possible IPv4 address in a random order is a valuable technique with various applications,
from network testing to privacy enhancement. With the Linear Congruential Generator approach, we can do it efficiently.&lt;/p&gt;</content><category term="Technical"></category><category term="Residential Proxies"></category><category term="Networking"></category><category term="DDoS"></category><category term="TLS Fingerprinting"></category></entry><entry><title>Scaling anomaly detection with RRCF</title><link href="https://www.peakhour.io/blog/rrcf-scaling/" rel="alternate"></link><published>2023-05-15T13:00:00+10:00</published><updated>2023-05-15T13:00:00+10:00</updated><author><name>AC</name></author><id>tag:www.peakhour.io,2023-05-15:/blog/rrcf-scaling/</id><summary type="html">&lt;p&gt;Discusses strategies for scaling the Robust Random Cut Forest (RRCF) algorithm for large-scale anomaly detection, including using summary statistics, buffering input, and parallelisation.&lt;/p&gt;</summary><content type="html">&lt;p&gt;As data volumes grow, the &lt;a href="/learning/threat-detection/what-is-anomaly-detection/"&gt;anomaly detection&lt;/a&gt; process has to scale with them. RRCF is
efficient, but large, high-dimensional datasets can still create performance challenges. The following strategies focus
on reducing dimensionality, smoothing bursts of input, and distributing independent work.&lt;/p&gt;
&lt;h2&gt;Compute Summary Statistics Instead of Shingling&lt;/h2&gt;
&lt;p&gt;Shingling transforms a single time series into a multivariate one by stacking lagged versions of the data. This can help
capture temporal dependencies, but it also increases the dimensionality of the points inserted into each tree, which can
slow the algorithm down.&lt;/p&gt;
&lt;p&gt;An alternative is to compute summary statistics that capture the types of anomalies you are looking for. For instance,
if you are detecting spikes, the data points could consist of second central differences. If you are looking for
long-term trends, the data points could consist of rolling means at different window sizes. This reduces the dimension
of the points inserted into each tree, improving performance.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Placeholder for Summary Statistics graph" src="#"&gt;&lt;/p&gt;
&lt;h2&gt;Buffer Input and Compute Rolling Summary Statistics&lt;/h2&gt;
&lt;p&gt;When data arrives too quickly to be inserted into the trees directly, buffer the input and compute rolling summary
statistics (mean, median, max, etc.). This reduces the number of points that need to be inserted into the trees and
helps the algorithm keep up with the streaming data.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Placeholder for Rolling Summary Statistics graph" src="#"&gt;&lt;/p&gt;
&lt;h2&gt;Parallelisation&lt;/h2&gt;
&lt;p&gt;RRCF can be parallelised, which is particularly useful when dealing with multiple independent time series. Different
RRCF instances can be run for each time series, using separate processes or server instances. This distributes the
computational load and can improve performance.&lt;/p&gt;
&lt;p&gt;For instance, if you have 10 independent time series, you can run 10 instances of RRCF in parallel, each focusing on one
time series. This scales the anomaly detection process to handle larger volumes of data.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Placeholder for Parallelization graph" src="#"&gt;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Scaling RRCF for large datasets usually means reducing the work each tree has to do, controlling input volume, and
parallelising where the data allows it. Summary statistics, input buffering, and independent RRCF instances can help
manage high-dimensional data and high data velocities without changing the underlying anomaly detection goal.&lt;/p&gt;</content><category term="Technical"></category><category term="Anomaly Detection"></category><category term="Threat Detection"></category></entry><entry><title>Applied RRCF - thresholding techniques.</title><link href="https://www.peakhour.io/blog/rrcf-thresholding/" rel="alternate"></link><published>2023-05-15T13:00:00+10:00</published><updated>2023-05-15T13:00:00+10:00</updated><author><name>AC</name></author><id>tag:www.peakhour.io,2023-05-15:/blog/rrcf-thresholding/</id><summary type="html">&lt;p&gt;Explores various thresholding techniques like Median Absolute Deviation (MAD), Min/Max, and Z-Score for interpreting Robust Random Cut Forest (RRCF) anomaly scores, crucial for classifying data points as normal or anomalous.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Once we've applied the RRCF algorithm to our streaming data, the resulting scores measure how anomalous each data point
is. To classify data points as "normal" or "anomalous", we still need to set a threshold. This defines the level of
deviation considered anomalous and controls how often anomalies are over-identified or missed.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Placeholder for RRCF score graph" src="#"&gt;&lt;/p&gt;
&lt;h2&gt;Why is Thresholding Needed?&lt;/h2&gt;
&lt;p&gt;Thresholding matters in anomaly detection because it separates normal and anomalous behaviour. Without a threshold, the
scores still indicate relative degrees of anomalousness, but they do not provide a clear dividing line between normal
points and anomalies.&lt;/p&gt;
&lt;p&gt;Set the threshold too low and normal data points may be misclassified as anomalies, increasing false positives. Set it
too high and actual anomalies may be missed, increasing false negatives.&lt;/p&gt;
&lt;h2&gt;How to Set the Threshold?&lt;/h2&gt;
&lt;p&gt;There are several ways to set a threshold for RRCF scores, including the Median Absolute Deviation (MAD), Min/Max, and
others. The right method depends on the characteristics of the data and the specific use case.&lt;/p&gt;
&lt;h3&gt;Median Absolute Deviation (MAD)&lt;/h3&gt;
&lt;p&gt;The Median Absolute Deviation is a robust measure of variability in a data set. For RRCF scores, MAD can be used to set
a threshold. A typical approach is to set the threshold as some multiple of the MAD above the median. This approach is
robust to outliers and can be useful when the data has heavy-tailed distributions.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Placeholder for MAD graph" src="#"&gt;&lt;/p&gt;
&lt;h3&gt;Min/Max&lt;/h3&gt;
&lt;p&gt;Another approach is to use the minimum and maximum RRCF scores to set the threshold. This could mean setting the
threshold as a percentage of the range between the minimum and maximum scores. The method is straightforward, but it can
be sensitive to extreme score values.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Placeholder for Min/Max graph" src="#"&gt;&lt;/p&gt;
&lt;h3&gt;Z-Score&lt;/h3&gt;
&lt;p&gt;Several other methods can be used to set the threshold, depending on the data. These include statistical techniques such
as setting the threshold based on standard deviations from the mean, using quartiles of the data, or using machine
learning techniques to dynamically adjust the threshold based on observed data.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Placeholder for Other Methods graph" src="#"&gt;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Thresholding gives anomaly detection a clear boundary between normal and anomalous scores, which helps identify
potential issues such as cyber threats or system errors. The choice of thresholding method depends on the use case and
the characteristics of the data. Whatever method is used, the threshold needs to balance anomaly detection against the
risk of false positives and false negatives.&lt;/p&gt;</content><category term="Technical"></category><category term="Anomaly Detection"></category><category term="Threat Detection"></category></entry></feed>