# 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:
```
```
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:
```
# formatting
*%* denotes a format control character, followed by one of the following:
| %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:
| %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:
| %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:
```
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`:
```
# 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.
```
Or inverted with `--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:
```
# 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
```