Limen.Signal.Asn (limen v0.2.1)

Copy Markdown View Source

Maps the client address to its autonomous system (ASN).

An autonomous system is a network run by one operator, such as a cloud provider, a hosting company or an ISP, and identified on the internet by its number.

Traffic from hosting providers and clouds is far more likely to be automated than traffic from residential and mobile networks. This signal looks the client address up in an IP-to-ASN table and classifies the ASN.

Data

The data comes in the format of the iptoasn.com ip2asn-combined.tsv dataset, gzipped or not:

range_start<TAB>range_end<TAB>asn<TAB>country<TAB>description

It is packed into a single :persistent_term entry (see Limen.Signal.Asn.Table): the full dataset, about 580,000 routed ranges, takes about 10 MB, and a lookup is a few hundred nanoseconds of binary matching, without copying the table or taking a lock.

Limen.Signal.Asn.Loader loads it off the request path, from the :file of the :asn configuration, and with a :url also keeps it current:

config :my_app, Limen,
  asn: [
    file: "/var/lib/my_app/ip2asn-combined.tsv.gz",
    url: "https://iptoasn.com/data/ip2asn-combined.tsv.gz",
    refresh: [
      every: :timer.hours(24),
      window: {~T[01:00:00], ~T[05:00:00]},
      max_utilization: 0.8
    ]
  ]

The file is where downloads are kept, so a node that starts loads the last data it had without waiting for the network, and checks for new data on schedule: once a day here, at a random time between 01:00 and 05:00 UTC, unless its schedulers are busier than 80%. See the :asn options of Limen.Config and Limen.Signal.Asn.Schedule.

iptoasn.com publishes its data in the public domain. Any source in the same format works, such as a file your own pipeline writes.

Other sources

To look addresses up in data your application already has, such as MaxMind's GeoLite2, implement Limen.Signal.Asn.Source and set it as the :source; Limen then loads no data of its own:

config :my_app, Limen, asn: [source: MyApp.GeoAsn]

Classification

:asn_kind is :hosting for a built-in list of large cloud and hosting providers plus any ASN in the :hosting option, :other for any other known ASN and :unknown when the address is not in the table (or no table is loaded). A custom source may classify its entries itself. Google and Microsoft run crawlers from their main ASNs; allow verified crawlers before scoring hosting providers.

Provides :asn, :asn_kind, :asn_country and :asn_name. With a custom source, the evidence for :asn names it.

Summary

Functions

Classifies an ASN as :hosting or :other.

Returns the ASN entry covering ip in the data instance loaded, if any.

Types

entry()

@type entry() :: Limen.Signal.Asn.Table.entry()

Functions

kind(asn, config)

@spec kind(pos_integer(), Limen.Config.t()) :: :hosting | :other

Classifies an ASN as :hosting or :other.

lookup(instance, ip)

@spec lookup(atom(), :inet.ip_address() | nil) :: entry() | nil

Returns the ASN entry covering ip in the data instance loaded, if any.

This is the default Limen.Signal.Asn.Source, whatever the instance's :source.