ripcalc 0.3.0

ripcalc, format and lookup IP addresses
Documentation

ripcalc

Calculate or lookup network addresses.

install

$ git clone 'https://gitlab.com/edneville/ripcalc.git'
$ cd ripcalc \
  && cargo build --release \
  && please install -m 0755 -s target/release/ripcalc /usr/local/bin

or

please snap install ripcalc

usage

Ripcalc allows networks to be provided by argument

$ ripcalc 127.0.0.1/8
IP is: 127.0.0.1/8
Broadcast is: 127.255.255.255
Network is: 127.0.0.0
Subnet is: 255.0.0.0
Wildcard is: 0.255.255.255
Network size: 16777216

The same output is visible with stdin:

echo '127.0.0.1/8' | ripcalc
...

The output format can be customised:

$ ripcalc 2001:ba8:1f1:f1cb::4/64 --format "select * from IP6 where (ip >= %ln and ip <= %lb) and active = 1;\nupdate IP6 set active = 0 where (ip >= %ln and ip <= %lb) and active = 1;"
select * from IP6 where (ip >= 42540724579414763292693624807812497408 and ip <= 42540724579414763311140368881522049023) and active = 1;
update IP6 set active = 0 where (ip >= 42540724579414763292693624807812497408 and ip <= 42540724579414763311140368881522049023) and active = 1;

pipes

Sometimes if you want to quickly see if an address is part of a group of networks you can set something like this in your .bash_aliases:

alias is_our_networks='ripcalc --inside 192.168.0.0/16 --format short'

With this alias it would then be possible to do something like this to quickly see if the domain uses your infrastructure:

dig +short domain.com | is_our_networks

formatting

% denotes a format control character, followed by one of the following:

placeholder effect
%a IP address string
%n Network address string
%s Subnet address string
%w Wildcard address string
%b Broadcast address string

Additional characters prefixing the above placeholder can control the representation:

placeholder effect
%B Binary address string
%S Split binary at network boundary string
%l Unsigned integer string
%L Signed integer string
%x Hex address string

Other format characters:

placeholder effect
%c CIDR mask
%C In encapsulated context, used address count
%t Network size
%r Network reservation information (if available)
%d Matching device interface by IP
%m Matching media link interface by network
%p PTR record
%k RBL/reverse DNS-style format
%D Network size (--networks)
%N Number of subnets (--networks)
%% %
\n Line break
\t Tab character

For example:

$ ripcalc --format '%k.all.s5h.net\n' 192.168.1.2
2.1.168.192.all.s5h.net

With a csv it can find networks that an IP address is within, use %{field} to print matches:

$ cat nets.csv
network,range,owner
rfc1918,192.168.0.0/16,bob
rfc1918,172.16.0.0/12,cliff
rfc1918,10.0.0.0/8,mr nobody
$ ripcalc --csv nets.csv -i range --format '%{owner}\n' 192.168.0.0
bob

Addresses can be read via file or from stdin (-):

$ cat list
127.0.0.1/28
10.0.0.1/28
192.168.1.1/30
172.18.1.1/30
10.0.0.0/30
$ ripcalc --csv nets.csv -i range --format '%{range} %{owner}\n' -s list
10.0.0.0/8 mr nobody
192.168.0.0/16 bob
172.16.0.0/12 cliff
10.0.0.0/8 mr nobody

When -a is used, addresses read from -s will not be shown when listing -l a network, showing only available addresses.

When -e is used with -s the smallest encapsulating network will be returned.

Given a list of IP addresses, print only those that match the network. When s and inside are used, only addresses from -s are printed if they are that are inside of the IP source network on the command line. This can be inverted with `--outside:

$ echo -e '192.168.0.0\n192.167.255.255\n' | ripcalc -s - --inside 192.168.0.0/16 --format short
192.168.0.0
$ echo -e '192.168.0.0\n192.167.255.255\n' | ripcalc -s - --outside 192.168.0.0/16 --format short
192.167.255.255

IP addresses can be treated as reversed, if /proc/net/route holds addresses in reversed format, --reverse inputs and --base 16 could be used together to convert to dotted-quad.

integer inputs

To process addresses in signed integer form, use --base -10 which will do the conversion.

To quickly format human-readable IP addresses to a database that stores addresses as integers, assuming addreses are in a table called IP4 and are signed integers:

printf '10.0.0.0/8\n192.168.0.0/16\n172.16.0.0/12\n127.0.0.0/8\n1.0.0.0/8\n' \
| ripcalc --format 'select ip from IP4 where active = 1 and (ip > %Ln and ip < %Lb);\n' \
| mysql -urip -pcalc ipdata \
| ripcalc -q --base 10 --format short

within networks

Is a domain wihtin a list of subnets? For example, in this part of the globe cloudflare.com was being served from their published list of networks:

echo http://cloudflare.com | ripcalc --inside 173.245.48.0/20 103.21.244.0/22 \
    103.22.200.0/22 103.31.4.0/22 141.101.64.0/18 108.162.192.0/18 \
    190.93.240.0/20 188.114.96.0/20 197.234.240.0/22 198.41.128.0/17 \
    162.158.0.0/15 104.16.0.0/13 104.24.0.0/14 172.64.0.0/13 \
    131.0.72.0/22 --format short
104.16.133.229

How many addresses is all that in total?

ripcalc 173.245.48.0/20 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 \
    141.101.64.0/18 108.162.192.0/18 190.93.240.0/20 188.114.96.0/20 \
    197.234.240.0/22 198.41.128.0/17 162.158.0.0/15 104.16.0.0/13 \
    104.24.0.0/14 172.64.0.0/13 131.0.72.0/22 --format '%t\n' \
    | paste -sd+ \
    | bc -l
1524736

If you need to manage a lot of IP addresses this could be helpful to you.

divide

Networks can be divided into subnets:

$ ripcalc 192.168.1.10/24 --divide 26 --format cidr
192.168.1.0/26
192.168.1.64/26
192.168.1.128/26
192.168.1.192/26

quickly block the encapsulating network

Suppose a large flood of requests are from a network pattern, to preserve service you may want to block the whole network that encapsulates a list:

please ip route add blackhole `ripcalc -e 192.168.56.10 192.168.57.1 192.168.44.47`

Networks can be grouped, in a scenario where you have a list of unwanted traffic, you can turn this into a list of small networks to block, supposing you don't want to block anything that covers more than a /19:

cat bad_traffic | ripcalc --encapsulating --group 19 --format cidr

This might be of help to you, assuming you can select a chunk of bad traffic via a grep:

grep -h scams log/* | awk '{print $1}' | ripcalc --encapsulating --group 24 --format '%C %a/%c\n'
15 192.168.1.0/25
12 172.16.80.0/24
1 172.16.209.9/32

Grouping with a limit helps show spread, without expanding beyond sensible limits. Setting a very large group mask would of course return very large results, using a smaller group can limit this so the probability of including legitimate traffic is reduced dramatically.

IP address counts can be shown with countseen and group:

cat log | ripcalc --countseen --quiet --format '%C %a/%c\n'

cdb

CDB databases are fast and if you have a large list of networks they offer a good way to lookup addresses without parsing CSV. CDB lookups can be performed using IP/cidr keys and the returned values should be stored as a NULL joined key=value string, e.g.:

192.168.1.0/24 name=lan\0owner=build\0service=web

The --makethymecdb argument will download ASN information from thyme.apnic.net and build that into a cdb file, or you can make your own. I find the data from thyme perfect for my needs, but this is the internet and geo-IP, please don't rely on geo-IP being accurate.

Obviously, if you have a fleet of computers using this data, it is best to download and build in one location then fan it out using rsync to your other computers to save resources and processing power.

Files can also be made using --makecdb, the stdin should be in the format of:

2600:3c0f:25::/48,ASNDESC=AKAMAI-LINODE-AP Akamai Connected Cloud,ASNCC=SG,ASN=2600:3c0f:25::/48,NET=63949

See cdb_maker.pl for a helper script which builds this. An example for making these can be seen in the Makefile in the ipdb target, it download ASN data and builds that using cdb_maker.pl, and this can be used like this:

ripcalc --cdb ipdb.cdb --format '%{ASNDESC} %{ASNCC} %a/%c\n' 1.1.1.1
CLOUDFLARENET US 1.1.1.1/24

filter

Input can be filtered using --filter which can be helpful as an accompaniment for grep-like workflows.

cat /var/log/apache/access.log | ripcalc --filter 1.2.3.0/24

Or inverted with --outside.

cat /var/log/apache/access.log | ripcalc --filter 1.1.1.0/24 --outside

--filter will use the first word in the inputline and try to parse that for an IP address, if the IP address is not the first word in the input, then --filternum can be used to indicate which word number holds the IP.

If you'd like to see the country code that the requests in your log are from:

cat /var/log/apache/access.log | ripcalc --filter --outside --cdb ipdb.cdb --format '%{ASNCC} %{line}\n'

abuseipdb

If --abuseipdb [key] is used then a successful lookup will populate %{abuseipdb_var} (where var is the lookup result data field) for use in a --format string.

Replace [key] with your abuseipdb API key.

If only the country code or ISP is needed, then using a locally generated cdb is more efficient, see the CDB section above as that can be much faster if you don't require an external abuse score.

maxmind geolite

MaxMind's geolite database files can be read using --mmasn, --mmcountry and --mmcity options. The text language can be defined with --mmlang.

In normal context the following are returned:

mmcity: %{mmcity_city}, %{mmcity_continent}, %{mmcity_country}, %{mmcity_code}, %{mmcity_latitude}, %{mmcity_longitude}

mmcountry: %{mmcountry_continent}, %{mmcountry_country}, %{mmcountry_registered_country}

mmasn: %{mmasn_autonomous_system_number}, %{mmasn_autonomous_system_organization }

Less information is returned in --top context:

ripcalc --top --allowemptyrow \
    --mmcity GeoLite2-City.mmdb \
    --mmcountry GeoLite2-Country.mmdb \
    --mmasn GeoLite2-ASN.mmdb 

Without needing to add a --format string, in --top context, this will display %{mmcity_code} and %{mmcity_country} for --mmcity, %{mmasn_autonomous_system_organization} for --mmasn, and %{mmcountry_registered_country} for --mmcountry.

top

Basic report of IP frequency, as read from stdin. Can be used with --group, --group[46], --filter, --filterany, --filternum or --inside to show which networks appear most frequently.

ripcalc --allowemptyrow --top --inside 10.0.0.0/8 --group 24 --delay 1

                                                   10.12.0.0/14 4800 ##
                                                   10.16.0.0/14 4075 ##
                                                    10.8.0.0/14 3740 #
                                                    10.4.0.0/14 3200 #
                                                    10.0.0.0/14 2400 #
                                                   10.20.0.0/14  800 

A cdb IP database can be used in conjunction, which defaults to %{ASNCC} %{ASNDESC}:

ripcalc --top --inside 10.0.0.0/8 --group 14 --delay 1 --allowemptyrow --cdb ipdb.cdb
XX PRIVATE                                          10.8.0.0/14 3200 ##
XX PRIVATE                                          10.4.0.0/14 3200 ##
XX PRIVATE                                         10.12.0.0/14 3200 ##
XX PRIVATE                                         10.16.0.0/14 3200 ##
XX PRIVATE                                          10.0.0.0/14 2400 #
XX PRIVATE                                         10.20.0.0/14  800 

If you want to show the abuse score from AbuseIPDB at the same time you can use a format string or allow the default to be used which shows the abuse score.

--iterations [num] can set the number of display iterations. If you wish to run a number of displays for an email report, use with --noclear:

( printf 'To: you\nFrom: me\nSubject: IP report\n\n';
tail -Fq /var/log/apache2/*log
| ripcalc --top --cdb ipdb.cdb --group4 24 --group6 64 --allowemptyrow --iterations 3 --noclear )
| /usr/sbin/sendmail -fme@example you@example

help

ripcalc version 0.2.7

Options:
    -4, --ipv4          treat inputs as ipv4 address
    -6, --ipv6          treat inputs as ipv6 address
    -a, --available     display unused addresses
        --abuseipdb KEY abuseipdb API
        --allowemptyrow 
                        when no matching cdb/csv network, use empty fields
    -b, --base INTEGER  ipv4 base format, default to oct
        --cdb PATH      cdb reference file
        --countseen     count times an ip is seen
    -c, --csv PATH      csv reference file
    -d, --divide CIDR   divide network into chunks
        --noexpand      do not expand networks in list
    -e, --encapsulating 
                        display encapsulating network from arguments or lookup
                        list
    -f, --format STRING format output
                        'cidr' expands to %a/%c\n
                        'short' expands to %a\n
                        See manual for more options
        --filter        print STDIN line if field parses as an IP and matches,
                        defaults to 1, use filternum to adjust
        --filterany     print STDIN line if any IP on STDIN matches
        --filternum NUMBER
                        change position NUMBER for IP filter, enables --filter
        --group CIDR    maximum network group size for encapsulation
        --group4 CIDR   v4 specific group, overrides group in top mode
        --group6 CIDR   v6 specific group, overrides group in top mode
    -h, --help          display help
    -i, --field FIELD   csv/db/json field
    -l, --list          list all addresses in network
        --outside       display when extremities are outside network
        --inside        display when extremities are inside network
        --makecdb PATH  build a cdb file from STDIN
        --makethymecdb PATH
                        download and build a cdb file, defaults to
                        thyme.apnic.net data
        --data-raw-table URL or PATH
                        URL/path of raw data
        --ipv6-raw-table URL or PATH
                        URL/path of ipv6 data
        --data-used-autnums URL or PATH
                        URL/path of ASN data
        --top           show IP frequency like top
        --delay SECONDS top update delay in seconds
        --iterations NUMBER
                        top iterations
        --noclear       don't print clear screen codes
        --mmlang LANG   the lang to use in results, defaults to en
        --mmasn PATH    path to maxmind geoip asn file
        --mmcity PATH   path to maxmind geoip city file
        --mmcountry PATH
                        path to maxmind geoip country file
    -m, --mask CIDR     cidr mask
    -n, --networks CIDR instead of hosts, display number of subnets of this
                        size
        --json PATH     json prefix file
    -q, --quiet         don't report errors
    -r, --reverse       (none, inputs, sources or both) v4 octets, v6 hex
    -s, --file PATH     lookup addresses from, - for stdin
    -v, --version       print version