A peculiar phenomenon is on my mind. As you may know, dealing with a mail server directly exposed to the internet can be quite the 'joy' with various individuals attempting to break into it or use it as a relay. I don't have any issues with manually blocking addresses or ranges that annoy me through the firewall, even though it takes some effort. I'm not so keen on automating the whole process with fail2ban; I prefer to know what's 'going on'.
So, I've created various rules with iptables and ip6tables, and their number has nearly reached a plateau. Nevertheless, to maintain some semblance of organization, I'd like to relate the quantity of blocked V4 IPs and V4 ranges to the total number of V4 addresses. Concerning the latter, I'm setting aside the fact that there are some disallowed addresses like broadcast addresses or private address ranges that aren't routed. Instead, I'm simplistically assuming that there can be 2^32 addresses with four bytes.
From the rules for iptables, I extract the specified IP ranges using filters, primarily with awk, and obtain a list that looks like the following:
...
27.72.155.100/32
37.9.0.0/20
37.9.32.0/20
37.9.48.0/21
37.9.64.0/18
37.9.128.0/21
...
So, the usual combination of an address and valid bits in the mask. I process this list with a small Perl program that handles STDIN. To determine the quantity of affected addresses from such a string, I use the Perl library "Net::IP," which provides convenient processing. For example, after $str = "37.9.32.0/20"
, it's possible to do $ip = new Net::IP($str); $count = $ip -> size();
, and $count now contains 4096, which is the result of 2^(32-20). So far, everything is fine.
The problem arises when I try to perform calculations with $count. After summing all the quantities, I want to determine them as a percentage of the total possible IP quantity by dividing them by 2^32. Even with individual values, the problem is evident: Attempting to divide the determined quantity of 4096 by 3 doesn't yield the floating-point number "1365.33..." but simply the integer value 1365. I've tried casting before the division to obtain clear formats, but it didn't help. It likely has something to do with the object-oriented code used by Net::IP. I admit that as a former assembler programmer, I'm not well-versed in object-oriented programming and struggle with it. What is probably needed is a kind of \$count -> getInt()
because:
I resorted to a brute-force approach to actually obtain the desired result as a floating-point number by iterating through the IP quantity in a loop, decrementing the OOP result from Net::IP. But that's really too crude and completely bypasses the elegant concept of Net::IP. Moreover, I'm sure there are experts among you who can point me to something that produces the famous 'aha effect,' and I'm looking forward to that. Here's the source code I used, reduced to a single IP address/mask in Perl:
#!/usr/bin/perl
use strict;
use Net::IP;
my $count = 0;
my $str = "37.9.32.0/20";
my $ip = new Net::IP($str) or die (Net::IP::Error());
my $count = $ip -> size();
print "this is the result of 4096/3\t\t\t: ", 4096 / 3, "\n";
print "this is count\t\t\t\t\t: ", $count, "\n";
print "and this is the result of $count / 3\t\t: ", $count / 3, "\n";
print "and this is the result of int($count) / 3\t: ", int($count) / 3, "\n";
my $countW = 0;
while ($count > 0) {
$count--;
$countW++;
}
print "and now comes the result of $countW / 3\t\t: ", $countW / 3, "\n";
And here the outputs that are produced:
this is the result of 4096/3 : 1365.33333333333
this is count : 4096
and this is the result of $count / 3 : 1365
and this is the result of int($count) / 3 : 1365
and now comes the result of $countW / 3 : 1365.33333333333