├── .editorconfig ├── .github └── workflows │ └── docker.yaml ├── Dockerfile ├── LICENSE ├── README.md ├── asn ├── asn.1 └── cloudshell_bootstrap.sh /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true -------------------------------------------------------------------------------- /.github/workflows/docker.yaml: -------------------------------------------------------------------------------- 1 | name: docker-build-and-push 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - 'v*' 8 | 9 | jobs: 10 | docker: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - 14 | name: Checkout 15 | uses: actions/checkout@v4 16 | - 17 | name: Docker meta 18 | id: meta 19 | uses: docker/metadata-action@v5 20 | with: 21 | images: nitefood/asn 22 | - 23 | name: Login to DockerHub 24 | if: github.event_name != 'pull_request' 25 | uses: docker/login-action@v3 26 | with: 27 | username: ${{ secrets.DOCKERHUB_USERNAME }} 28 | password: ${{ secrets.DOCKERHUB_TOKEN }} 29 | - 30 | name: Build and push 31 | uses: docker/build-push-action@v5 32 | with: 33 | context: . 34 | push: ${{ github.event_name != 'pull_request' }} 35 | tags: ${{ steps.meta.outputs.tags }} 36 | labels: ${{ steps.meta.outputs.labels }} 37 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.20.2 2 | 3 | ENV IQS_TOKEN="" 4 | ENV IPINFO_TOKEN="" 5 | ENV CLOUDFLARE_TOKEN="" 6 | 7 | # - Prepare the config directory 8 | # - Create the entrypoint script that writes the API tokens to the config files 9 | # - Install prerequisite packages 10 | RUN mkdir -p /etc/asn && \ 11 | chown nobody:nobody /etc/asn/ && \ 12 | printf '%s\n' '#!/usr/bin/env bash' \ 13 | '[[ -n "$IQS_TOKEN" ]] && echo "$IQS_TOKEN" > /etc/asn/iqs_token' \ 14 | '[[ -n "$IPINFO_TOKEN" ]] && echo "$IPINFO_TOKEN" > /etc/asn/ipinfo_token' \ 15 | '[[ -n "$CLOUDFLARE_TOKEN" ]] && echo "$CLOUDFLARE_TOKEN" > /etc/asn/cloudflare_token' \ 16 | 'exec "$@"' > /entrypoint.sh && \ 17 | chmod +x /entrypoint.sh && \ 18 | apk update && \ 19 | apk add --no-cache aha bash bind-tools coreutils curl grepcidr3 ipcalc jq mtr ncurses nmap nmap-ncat whois 20 | 21 | COPY asn /bin/asn 22 | RUN chmod 0755 /bin/asn 23 | 24 | # Start the service by default 25 | USER nobody 26 | EXPOSE 49200/tcp 27 | ENTRYPOINT ["/entrypoint.sh", "/bin/asn"] 28 | CMD ["-l", "::"] 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Adriano Provvisiero 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ASN Lookup Tool and Traceroute Server 2 | 3 | [![Packaging status](https://repology.org/badge/vertical-allrepos/asn.svg)](https://repology.org/project/asn/versions) 4 | 5 | #### Container support: 6 | 7 | [![Docker](https://img.shields.io/badge/docker-%230db7ed.svg?style=for-the-badge&logo=docker&logoColor=white)](#running-the-script-from-a-container) 8 | [![Google Cloud](https://img.shields.io/badge/GoogleCloud-%234285F4.svg?style=for-the-badge&logo=google-cloud&logoColor=white)](#running-the-script-from-a-container) 9 | 10 | #### OS support: 11 | 12 | [![Debian](https://img.shields.io/badge/Debian-D70A53?style=for-the-badge&logo=debian&logoColor=white)](#installation) 13 | [![Ubuntu](https://img.shields.io/badge/Ubuntu-E95420?style=for-the-badge&logo=ubuntu&logoColor=white)](#installation) 14 | [![Kali](https://img.shields.io/badge/Kali-268BEE?style=for-the-badge&logo=kalilinux&logoColor=white)](#installation) 15 | [![Cent OS](https://img.shields.io/badge/cent%20os-002260?style=for-the-badge&logo=centos&logoColor=F0F0F0)](#installation) 16 | [![Red Hat](https://img.shields.io/badge/Red%20Hat-EE0000?style=for-the-badge&logo=redhat&logoColor=white)](#installation) 17 | [![Rocky Linux](https://img.shields.io/badge/-Rocky%20Linux-%2310B981?style=for-the-badge&logo=rockylinux&logoColor=white)](#installation) 18 | [![Fedora](https://img.shields.io/badge/Fedora-294172?style=for-the-badge&logo=fedora&logoColor=white)](#installation) 19 | [![Arch](https://img.shields.io/badge/Arch%20Linux-1793D1?logo=arch-linux&logoColor=fff&style=for-the-badge)](#installation) 20 | [![Manjaro](https://img.shields.io/badge/Manjaro-35BF5C?style=for-the-badge&logo=Manjaro&logoColor=white)](#installation) 21 | [![Alpine Linux](https://img.shields.io/badge/Alpine_Linux-%230D597F.svg?style=for-the-badge&logo=alpine-linux&logoColor=white)](#installation) 22 | [![openSUSE](https://img.shields.io/badge/openSUSE-73BA25?logo=opensuse&logoColor=fff&style=for-the-badge)](#installation) 23 | [![FreeBSD](https://img.shields.io/badge/-FreeBSD-%23870000?style=for-the-badge&logo=freebsd&logoColor=white)](#installation) 24 | [![Nix](https://img.shields.io/badge/NIX-5277C3.svg?style=for-the-badge&logo=NixOS&logoColor=white)](#installation) 25 | [![macOS](https://img.shields.io/badge/mac%20os-000000?style=for-the-badge&logo=macos&logoColor=F0F0F0)](#installation) 26 | [![Windows](https://img.shields.io/badge/Windows-0078D6?style=for-the-badge&logo=windows&logoColor=white)](#installation) 27 | [![Raspberry Pi](https://img.shields.io/badge/-RaspberryPi-C51A4A?style=for-the-badge&logo=Raspberry-Pi)](#installation) 28 | 29 | ### Table of contents: 30 | 31 | * [Description](#description) 32 | * [Screenshots](#screenshots) 33 | * [Running the script from a container](#running-the-script-from-a-container) 34 | * [Installation](#installation) 35 | * _Optional: adding your [API tokens](#api-tokens) to improve functionalities_ 36 | * [Usage (as a command line tool)](#usage) 37 | * [Usage (as a lookup & traceroute server)](#running-lookups-from-the-browser) 38 | * [Usage (as a lookup API with JSON output)](#json-output-and-api-mode) 39 | 40 | --- 41 | 42 | ## Description 43 | 44 | ASN / RPKI validity / BGP stats / IPv4v6 / Prefix / ASPath / Organization / IP reputation / IP geolocation / IP fingerprinting / Network recon / lookup tool / Web traceroute server. 45 | 46 | This script serves the purpose of having a quick OSINT **command line tool** at disposal when investigating network data, which can come in handy in incident response scenarios as well (with features such as [bulk geolocation](#bulk-geolocation-mode) and threat scoring). 47 | 48 | It can be used as a **recon tool** by querying Shodan for data about any type of target (CIDR blocks/URLs/single IPs/hostnames). This will quickly give the user a complete breakdown about open ports, known vulnerabilities, known software and hardware running on the target, and more - without ever sending a single packet to the target. 49 | JSON output of the results, multiple simultaneous targets and IP list file inputs and are also supported. Click [here](#shodan-scanning-recon-mode) for more information about Shodan scanning mode. 50 | 51 | It can also be used as a **web-based traceroute server**, by running it in listening mode and launching lookups and traces from a local or remote browser (via a bookmarklet or custom search engine) or terminal (via `curl`, `elinks` or similar tools). Click [here](#running-lookups-from-the-browser) for more information about server mode functionality. 52 | 53 | Furthermore, it can serve as a self-hosted lookup **API endpoint** and output JSON-formatted data while running in both interactive and server mode. Click [here](#json-output-and-api-mode) for more information about API mode functionality. 54 | 55 | #### Features: 56 | 57 | * It will lookup relevant Autonomous System information for any given AS number, including: 58 | 59 | * **Organization name and RIR region** 60 | * **IXP Presence** (*Internet Exchange facilities where the AS is present*) 61 | * **Global AS rank** (*derived from the size of its customer cone, number of peering relationships and more*) 62 | * **BGP statistics** (*neighbours count, originated v4/v6 prefix count*) 63 | * **BGP incident history** (number of *BGP hijacks* and *route leaks* involving the target AS in the past 12 months, as a **victim** or a **hijacker**) 64 | * **Peering relationships** separated by type (*upstream/downstream/uncertain*), and sorted by observed *path count*, to give more reliable results (so for instance, the first few upstream peers are most likely to be transits). Furthermore, a recap of *transits/peers/customers* amount (per latest CAIDA data) is displayed. 65 | * **Announced prefixes** aggregated to the most relevant less-specific `INET(6)NUM` object (actual [LIR allocation](https://www.ripe.net/manage-ips-and-asns/db/support/documentation/ripe-database-documentation/rpsl-object-types/4-2-descriptions-of-primary-objects/4-2-4-description-of-the-inetnum-object)). 66 | 67 | * It will perform an **AS path trace** (using [mtr](https://github.com/traviscross/mtr) and retrieving AS data from the results) for single IPs or DNS results, optionally reporting detailed data for each hop, such as RPKI ROA validity, organization/network name, geographic location, etc. 68 | 69 | * It will detect **IXPs** (Internet Exchange Points) traversed during the trace, and highlight them for clarity. 70 | 71 | * It will attempt to lookup all relevant **abuse contacts** for any given IP or prefix. 72 | 73 | * It will perform **RPKI validity** lookups for every possible IP. Data is validated using the [RIPEStat RPKI validation API](https://stat.ripe.net/docs/data_api#rpki-validation). For path traces, the tool will match each hop's ASN/Prefix pair (retrieved from the Prefix Whois public server) with relevant published RPKI ROAs. In case of origin AS mismatch or unallowed more-specific prefixes, it will warn the user of a potential **route leak / BGP hijack** along with the offending AS in the path (requires `-d` option, see below for usage info). 74 | 75 | * *Read more about BGP hijacking [here](https://en.wikipedia.org/wiki/BGP_hijacking).* 76 | * *Read more about RPKI [here](https://en.wikipedia.org/wiki/Resource_Public_Key_Infrastructure), [here](https://blog.cloudflare.com/rpki/), or [here](https://www.ripe.net/manage-ips-and-asns/resource-management/certification).* 77 | 78 | * It will perform **IP geolocation** lookups according to the logic described [below](#geolocation). 79 | 80 | * geolocation can be performed in **bulk mode**. See [here](#bulk-geolocation-mode) for more info. 81 | * the script can also **map all IPv4/IPv6 CIDR blocks** allocated to any given country, by querying data from Marcel Bischoff's [country-ip-blocks](https://github.com/herrbischoff/country-ip-blocks) repo. See [below](#mapping-the-ipv4v6-address-space-of-specific-countries) for more info. 82 | 83 | * It will perform **IP reputation, noise classification** and in-depth **threat analysis** reporting (especially useful when investigating foreign IPs from log files). 84 | 85 | * It will perform **IP fingerprinting** using Shodan's [InternetDB API](%5Bhttps://internetdb.shodan.io/%5D(https://internetdb.shodan.io/)) and report any known **vulnerabilities**, **open ports** and **services/operating system/hardware** pertaining to target IPs and individual trace hops (detailed traces only). 86 | 87 | * Directly querying Shodan for any type of targets (including CIDR blocks) is also possible. More information [here](#shodan-scanning-recon-mode) about how to use the script as a recon tool. 88 | 89 | * It will perform **IP type identification** (*Anycast IP/Mobile network/Proxy host/Datacenter or hosting provider/IXP prefix*) for target IPs and individual trace hops. Broad type classification comes from [ip-api](https://ip-api.com), while detailed DC+region identification comes from [incolumitas.com](https://incolumitas.com/pages/Datacenter-IP-API/) 90 | 91 | * It will also identify **bogon** addresses being traversed and classify them according to the relevant RFC (Private address space/CGN space/Test address/link-local/reserved/etc.) 92 | 93 | * It is possible to search by **organization name** in order to retrieve a list of IPv4/6 network ranges related to a given company. A multiple choice menu will be presented if more than one organization matches the search query. 94 | 95 | * It is possible to search for **ASNs matching a given name**, in order to map the ASNs for a given organization. The list will be enriched by each result's AS rank and useful tags highlighting the highest-ranking ASNs found. 96 | 97 | * It is possible to quickly identify the **transit/upstream AS network(s)** for a given prefix, through analysis of observed BGP updates and ASPATHs. 98 | 99 | * the tool will also inform the user when a prefix is likely coming from a large tier-1 or multihomed network. 100 | 101 | * Lookup data can be integrated by third party tools by choosing **JSON output** and parsing the results externally, turning the script into a lookup API endpoint. 102 | 103 | Screenshots for every lookup option are below. 104 | 105 | The script uses the following services for data retrieval: 106 | 107 | * [Team Cymru](https://team-cymru.com/community-services/ip-asn-mapping/) 108 | * [The Prefix WhoIs Project](https://pwhois.org/) 109 | * [PeeringDB](https://www.peeringdb.com/) 110 | * [CAIDA ASRank](https://asrank.caida.org/) 111 | * [ifconfig.co](https://ifconfig.co/) 112 | * [ipify](https://www.ipify.org/) 113 | * [ipinfo.io](https://ipinfo.io) 114 | * [RIPEStat](https://stat.ripe.net/) 115 | * [RIPE IPmap](https://ipmap.ripe.net/) 116 | * [ip-api](https://ip-api.com/) 117 | * [StopForumSpam](https://www.stopforumspam.com/) 118 | * [IP Quality Score](https://www.ipqualityscore.com) 119 | * [Cloudflare Radar](https://radar.cloudflare.com/) 120 | * [ISC DSHIELD](https://isc.sans.edu/) 121 | * [GreyNoise](https://greynoise.io) 122 | * [Shodan](https://www.shodan.io/) 123 | * [NIST National Vulnerability Database](https://nvd.nist.gov/) 124 | * [Incolumitas.com](https://incolumitas.com/pages/Datacenter-IP-API/) 125 | * [RestCountries](https://restcountries.com/) 126 | * Marcel Bischoff's [country-ip-blocks](https://github.com/herrbischoff/country-ip-blocks) repo 127 | 128 | It also provides hyperlinks (in [server](#running-lookups-from-the-browser) mode) to the following external services when appropriate: 129 | 130 | * [HE.net](https://bgp.he.net) 131 | * [BGPView](https://bgpview.io) 132 | * [BGPTools](https://bgp.tools) 133 | * [ipinfo.io](https://ipinfo.io) 134 | * [Host.io](https://host.io) 135 | * [Cloudflare Radar](https://radar.cloudflare.com/) 136 | 137 | Requires Bash v4.2+. Tested on: 138 | 139 | * Linux 140 | * FreeBSD 141 | * Windows (WSL2, Cygwin) 142 | * MacOS *(thanks [Antonio Prado](https://github.com/Antonio-Prado) and Alessandro Barisone)* 143 | 144 | - - - 145 | 146 | ## Screenshots 147 | 148 | ### Generic usage 149 | 150 | * *IPv4 lookup with IP type detection (Anycast, Hosting/DC) and classification as good* 151 | 152 | ![ipv4lookup](https://github.com/nitefood/asn/assets/24555810/81def31a-e080-4b01-9aa2-25b979062963) 153 | 154 | * *IPv4 lookup (bad reputation IP) with threat analysis/scoring, CPE/CVE identification and open ports reporting* 155 | 156 | ![ipv4badlookup](https://github.com/nitefood/asn/assets/24555810/302dc69f-7026-4f41-afe6-e24c4d0a514a) 157 | 158 | * *IP fingerprinting with advanced datacenter+region identification, known vulnerabilities affecting the target and honeypot identification according to Shodan data* 159 | 160 | ![](https://user-images.githubusercontent.com/24555810/159185618-fa20f45c-91b4-45b4-ad82-02becc648fa5.png) 161 | 162 | * *IPv6 lookup* 163 | 164 | ![ipv6lookup](https://user-images.githubusercontent.com/24555810/159185780-44a1af6e-7aa9-4f52-b04c-55a314b2a5e3.png) 165 | 166 | * *Autonomous system number lookup with AS ranking, operational region, BGP stats and incident history, peering and prefix information* 167 | 168 | ![asnlookup](https://github.com/user-attachments/assets/9ae33fe8-6069-48e6-a4a3-ea74d2f351e1) 169 | 170 | * *Hostname/URL lookup* 171 | 172 | ![hostnamelookup](https://github.com/nitefood/asn/assets/24555810/f6c71594-d38a-4c7c-9142-5aa1e203f3fa) 173 | 174 | ### AS Path tracing 175 | 176 | * *ASPath trace to www.github.com* 177 | 178 | ![pathtrace](https://github.com/nitefood/asn/assets/24555810/8dfa68ba-de39-47f4-96d3-618210197e70) 179 | 180 | * *ASPath trace traversing both an unannounced PNI prefix (FASTWEB->SWISSCOM at hop 11) and an IXP (SWISSCOM -> RCN through Equinix Ashburn at hop 16)* 181 | 182 | ![pathtrace_pni_ixp](https://user-images.githubusercontent.com/24555810/100301579-b4d00c00-2f98-11eb-82c5-047c190ffcd6.png) 183 | 184 | * *Detailed ASPath trace to 8.8.8.8 traversing the Milan Internet Exchange (MIX) IXP peering LAN at hop 6* 185 | 186 | ![detailed_pathtrace](https://user-images.githubusercontent.com/24555810/117335188-28a50780-ae9b-11eb-98d9-cfd3bc2f1295.png) 187 | 188 | ### Network search by organization 189 | 190 | * *Organization search for "github"* 191 | 192 | ![search_by_org](https://user-images.githubusercontent.com/24555810/99845076-5b20a980-2b74-11eb-9312-986867034cc9.png) 193 | 194 | ### Shodan scanning 195 | 196 | * *Scanning for Shodan information for a list of IPs* 197 | 198 | ![shodanscan](https://github.com/nitefood/asn/assets/24555810/550d3004-9cbc-404e-b74c-9248a2d0bb0f) 199 | 200 | ### Country IPv4/IPv6 CIDR mapping 201 | 202 | * *Displaying a list of CIDR blocks allocated to Jamaica* 203 | 204 | ![country_cidr](https://user-images.githubusercontent.com/24555810/163061676-bae440c6-ff0d-478e-8799-98a927600964.png) 205 | 206 | ### Bulk Geolocation / country stats 207 | 208 | * *Performing bulk extraction, geolocation and stats for IPs from a logfile* 209 | 210 | ![bulk_geolocation](https://user-images.githubusercontent.com/24555810/162656545-11db3759-6741-44e0-bcfb-f3542482415f.png) 211 | 212 | ### Suggested ASNs search 213 | 214 | * *Suggested ASNs (and respective AS rankings) for "google"* 215 | 216 | ![asnsuggest](https://github.com/nitefood/asn/assets/24555810/c8bd8cab-9894-4886-94b5-bfd6bb0b9d8e) 217 | 218 | ### Transit/Upstream lookup 219 | 220 | * *A large tier-1 network (**COMCAST**, AS7922) prefix is reachable through multiple other tier-1 networks like **COGENT** (AS174), **LEVEL3** (AS3356) etc. - likely through settlement-free peering rather than BGP transit:* 221 | 222 | ![upstreamfinder_tier1_network](https://github.com/nitefood/asn/assets/24555810/4a6a00d9-7a8c-4765-a4d6-ea99aa516200) 223 | 224 | * *Transit identification for a multihomed AS (**AS30036** announces this prefix to **Hurricane** and **GTT** in a balanced way):* 225 | 226 | ![upstreamfinder_multihoming](https://github.com/nitefood/asn/assets/24555810/6c036a97-83f8-4c37-9ebd-2717c2d53507) 227 | 228 | * *Preferred transit identification - **Chinese UNICOM AS** is a large network, but likely prefers Russian **TRANSTELECOM** (AS20485) transit over **TELIA** (AS1299), **HURRICANE** (AS6939), **GTT** (AS3257) and others:* 229 | 230 | ![upstreamfinder_preferred_transit](https://github.com/nitefood/asn/assets/24555810/dbb64ecc-394a-4fbd-8607-5b7f6955b340) 231 | 232 | 233 | - - - 234 | 235 | ## Running the script from a container 236 | 237 | To run the script without installing it locally, you have the following options: 238 | 239 | * **Docker** _(thanks [Gianni Stubbe](https://github.com/33Fraise33), [anarcat](https://github.com/anarcat), [Francesco Colista](https://github.com/fcolista), [arbal](https://github.com/arbal))_ 240 | 241 | _Note: the Docker image runs by default in server mode, if no parameters are given. This is equivalent to running the tool as `asn -l ::` (run server, bind to all interfaces - this is necessary to expose the server port to the host machine). You can run the server with different [options](#syntax) by explicitly passing `-l [options]`. It's also possible to pass an [IpQualityScore](#ip-reputation-api-token-ipqualityscore), [ipinfo.io](#geolocation-api-token-ipinfoio) and/or [Cloudflare](#bgp-hijack-and-route-leak-incidents-cloudflare-radar) API token (both client and server runs) by setting, respectively, the `IQS_TOKEN`, `IPINFO_TOKEN` and `CLOUDFLARE_TOKEN` environment variables (examples below) in the container._ 242 | 243 | Usage examples: 244 | - Start server: `docker run -it -p 49200:49200 nitefood/asn` 245 | - Client mode: `docker run -it nitefood/asn 1.1.1.1` 246 | - Supply an IQS token: `docker run -it -e IQS_TOKEN="xxx" nitefood/asn [...]` 247 | - Supply multiple tokens: `docker run -it -e IQS_TOKEN="xxx" -e IPINFO_TOKEN="yyy" -e CLOUDFLARE_TOKEN="zzz" nitefood/asn [...]` 248 | 249 | * **Google Cloud Shell** 250 | 251 | _Note: server mode **is supported** out of the box in Cloud Shell, just follow the **bookmarklet** link that will be shown at server launch to access the VM for remote lookups._ 252 | 253 | **1.** Clone the repository in Cloud Shell by clicking the following button: 254 | 255 | [![Open in Cloud Shell](https://gstatic.com/cloudssh/images/open-btn.svg)](https://shell.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https://github.com/nitefood/asn&ephemeral=true&show=terminal) 256 | 257 | **2.** Prepare the GCP environment by launching `./cloudshell_bootstrap.sh` 258 | 259 | **3.** _(OPTIONAL)_ Input your [API tokens](#api-tokens) when requested to enable full script features 260 | 261 | - - - 262 | 263 | ## Installation 264 | 265 | This script requires **BASH v4.2** or later. You can check your version by running from your shell: 266 | 267 | ``` 268 | bash -c 'echo $BASH_VERSION' 269 | ``` 270 | 271 | After installation, you can use the script by running the `asn` command. 272 | 273 | ### Method 1: Install prerequisites + manual download 274 | 275 | > *Note: this method is **recommended** as it will always get you the **latest version** of the script.* 276 | 277 |
STEP 1. Install prerequisite packages

278 | 279 | Some packages are required for full functionality: 280 | 281 | * **Debian 10 / Ubuntu 20.04 (or newer):** 282 | 283 | ``` 284 | apt -y install curl whois bind9-host mtr-tiny jq ipcalc grepcidr nmap ncat aha 285 | ``` 286 | 287 | * **Debian 9 / Ubuntu 18.04 (or older):** 288 | 289 | ``` 290 | apt -y install curl whois bind9-host mtr-tiny jq ipcalc grepcidr nmap git gcc make && \ 291 | git clone https://github.com/theZiz/aha.git && \ 292 | make install -C aha/ 293 | ``` 294 | 295 | * **CentOS / RHEL / Rocky Linux 9:** 296 | 297 | ``` 298 | dnf -y install epel-release && \ 299 | dnf -y install curl whois bind-utils mtr jq nmap nmap-ncat ipcalc aha grepcidr 300 | ``` 301 | 302 | * **CentOS / RHEL / Rocky Linux 8:** *(thanks [Robert Scheck](https://github.com/robert-scheck))* 303 | 304 | ``` 305 | dnf -y install epel-release 'dnf-command(copr)' && \ 306 | dnf -y copr enable robert/ipcalc && \ 307 | dnf -y install curl whois bind-utils mtr jq nmap nmap-ncat ipcalc aha grepcidr 308 | ``` 309 | 310 | * **CentOS / RHEL 7:** *(thanks [Robert Scheck](https://github.com/robert-scheck))* 311 | 312 | ``` 313 | yum -y install epel-release yum-plugin-copr && \ 314 | yum -y copr enable robert/ipcalc && \ 315 | yum -y install curl whois bind-utils mtr jq nmap nmap-ncat ipcalc aha grepcidr && \ 316 | hash -d ipcalc 317 | ``` 318 | 319 | * **Fedora:** 320 | 321 | ``` 322 | dnf -y install curl whois bind-utils mtr jq nmap nmap-ncat ipcalc aha grepcidr 323 | ``` 324 | 325 | * **openSUSE Leap 15.5 (or newer), openSUSE Tumbleweed** 326 | 327 | ``` 328 | zypper in -y curl whois bind-utils mtr jq nmap ncat ipcalc aha grepcidr 329 | ``` 330 | 331 | * **FreeBSD**: 332 | 333 | ``` 334 | env ASSUME_ALWAYS_YES=YES pkg install bash coreutils curl whois mtr jq ipcalc grepcidr nmap aha 335 | ``` 336 | 337 | * **Windows**: 338 | 339 | * **using [WSL2](https://docs.microsoft.com/en-us/windows/wsl/about) (recommended):** 340 | Install Windows Subsystem for Linux (v2) by following Microsoft's [guide](https://docs.microsoft.com/en-us/windows/wsl/install-win10#manual-installation-steps). On step 6, choose one of the Linux distributions listed above (Ubuntu 20.04 LTS is recommended). 341 | Once your WSL2 system is up and running, open a Linux terminal and follow the prerequisite installation instructions above for your distribution of choice. 342 | 343 | > *Note for WSL2 users: Check [this](https://devblogs.microsoft.com/commandline/systemd-support-is-now-available-in-wsl/) page for details on how to activate **systemd** if you plan to install the [asn service](#optional-installing-the-asn-server-as-a-system-service).* 344 | 345 | * **using [Cygwin](https://cygwin.com/index.html):** 346 | Most of the prerequisite packages listed above for *Debian 10 / Ubuntu 20.04 (or newer)* are obtainable directly with Cygwin's own Setup wizard (or through scripts like *apt-cyg*). You will still have to manually compile (or find a suitable third-party precompiled binary) the *mtr*, *grepcidr* and *aha* tools. Instructions on how to do so can be found directly on the respective projects homepages. 347 |

348 | 349 |
STEP 2. Script download and installation

350 | 351 | Afterwards, to install the **asn** script from your shell to **/usr/bin**: 352 | 353 | `curl "https://raw.githubusercontent.com/nitefood/asn/master/asn" > /usr/bin/asn && chmod 0755 /usr/bin/asn` 354 | 355 |

356 | 357 | ### Method 2: Installing a packaged version of the script 358 | 359 | > *Note: packages may not reflect the latest version, check [Repology](https://repology.org/project/asn/versions) first.* 360 | 361 | Packaged versions of the tool are available for the following distributions: 362 | 363 |
Distribution list

364 | 365 | * **Debian-based:** *(thanks [Marcos Rodrigues de Carvalho](https://github.com/odaydebian))* 366 | > *Debian 13 / Sid*\ 367 | > *Ubuntu 24.04 (or newer)*\ 368 | > *Kali (rolling)*\ 369 | > *Raspbian (testing)* 370 | 371 | ``` 372 | sudo apt update && sudo apt install asn 373 | ``` 374 | * **Manjaro / Arch Linux:** *(thanks [Worty](https://github.com/worty))* 375 | 376 | ``` 377 | yay -S asn-git 378 | ``` 379 | 380 | * **Alpine Linux 3.18 (or newer)** *(thanks [Francesco Colista](https://github.com/fcolista))* 381 | 382 | ``` 383 | apk add -X https://dl-cdn.alpinelinux.org/alpine/v3.19/community asn 384 | ``` 385 | 386 | * **NixOS** *(thanks [devhell](https://github.com/devhell))* 387 | 388 | * Package [here](https://github.com/NixOS/nixpkgs/tree/master/pkgs/by-name/as/asn) 389 | 390 | * **MacOS** *(using [Homebrew](https://formulae.brew.sh/formula/asn), thanks [filippovitale](https://github.com/filippovitale))* 391 | 392 | ``` 393 | brew install asn 394 | ``` 395 | 396 | >*Note for MacOS users:* 397 | > 398 | > *Homebrew has a [policy](https://github.com/Homebrew/homebrew-core/issues/35085#issuecomment-447184214) not to install any binary with the **setuid** bit, and mtr (or actually, the mtr-packet helper binary that comes with it) requires to elevate to root to perform traces (good explanations for this can be found [here](https://github.com/traviscross/mtr/issues/204#issuecomment-723961118) and [here](https://github.com/traviscross/mtr/blob/master/SECURITY)). If mtr (and therefore `asn`) traces are not working on your system, you should either run `asn` as root using **sudo**, or set the proper SUID permission bit on the mtr (or better, on the mtr-packet) binary.* 399 | 400 |

401 | 402 | ### *(Optional)* Installing the *asn server* as a system service 403 | 404 | >*Note: this step is optional, and these instructions are only for **systemd**-based Linux systems (most current major distributions).* 405 | 406 | To control the **asn server** with utilities like *systemctl* and *service*, and to enable it to automatically start at boot, follow these steps: 407 | 408 | 1. create a new file called `/etc/systemd/system/asn.service` with the following content (make sure you edit the *ExecStart* line to match your installation path and desired startup options): 409 | 410 | ``` 411 | [Unit] 412 | Description=ASN lookup and traceroute server 413 | After=network.target 414 | StartLimitIntervalSec=0 415 | 416 | [Service] 417 | Type=simple 418 | Restart=always 419 | RestartSec=1 420 | User=nobody 421 | ExecStart=/usr/bin/asn -l :: 422 | 423 | [Install] 424 | WantedBy=multi-user.target 425 | ``` 426 | 427 | 2. Enable the *CAP\_NET\_RAW* capability for the mtr-packet binary: 428 | `setcap cap_net_raw+ep $(which mtr-packet)` 429 | *Explanation: this will allow mtr-packet to create raw sockets (and thus perform traces) when launched as an unprivileged user (we're setting up the service to run as user nobody for added security), without the requirement of the setuid-root bit and without having to invoke mtr as root. A thorough explanation for this can be found [here](https://github.com/traviscross/mtr/blob/master/SECURITY).* 430 | 3. Now you can refer to standard systemd utilities to perform service operations: 431 | * To start the service: `systemctl start asn` 432 | * To stop the service: `systemctl stop asn` 433 | * To check its status and latest logs: `systemctl status asn` 434 | * To follow its logging in real time: `journalctl -f -u asn` 435 | * To start the service automatically on boot: `systemctl enable asn` 436 | * To disable automatic start on boot: `systemctl disable asn` 437 | 438 | ## API tokens 439 | 440 | The script can be configured to make use of your API tokens to enhance its functionalities. 441 | 442 | The currently supported API tokens are: 443 | 444 | ### Geolocation API token (ipinfo.io) 445 | 446 |
Geolocation API token details

447 | 448 | The geolocation provider of choice for single lookups (i.e. when not running bulk geolocation queries with the `-g` option) is **ipinfo.io**. 449 | 450 | By default, the script uses the free (no API key) tier that supports up to **1,000** geolocation requests per day. In order to boost this limit (for free) to **50,000** requests per month, an API key token is required. 451 | 452 | In order to obtain an API token, after [signing up](https://ipinfo.io/signup), the API token can be found in the [token section](https://ipinfo.io/account/token) of your reserved area. Once copied, the token should be written to one of the following files (parsed in that order): 453 | 454 | `$HOME/.asn/ipinfo_token` or 455 | `/etc/asn/ipinfo_token` 456 | 457 | The `/etc`-based file should be used when running asn in **server mode**. The `$HOME`-based file takes precedence if both files exist, and is ideal for **user mode** (that is, running `asn` interactively from the command line). 458 | 459 | In order to do so, you can use the following command: 460 | 461 | ***User mode:*** 462 | 463 | `TOKEN=""; mkdir "$HOME/.asn/" && echo "$TOKEN" > "$HOME/.asn/ipinfo_token" && chmod -R 600 "$HOME/.asn/"` 464 | 465 | ***Server mode:*** 466 | 467 | `TOKEN=""; mkdir "/etc/asn/" && echo "$TOKEN" > "/etc/asn/ipinfo_token" && chmod -R 700 "/etc/asn/" && chown -R nobody /etc/asn/` 468 | 469 | Either way, `asn` will pick up your token on the next run (no need to restart the service if running in server mode), and use it to query the ipinfo.io API. 470 | 471 |

472 | 473 | ### IP reputation API token (IPQualityScore) 474 | 475 |
IP reputation API token details

476 | 477 | The script will perform first-level IPv4/v6 reputation lookups using [StopForumSpam](https://www.stopforumspam.com/), and in case of a match it will perform a second-level, in-depth threat analysis for targets and trace hops using the [IPQualityScore](https://www.ipqualityscore.com/) API. The StopForumSpam API is free and requires no sign-up, and the service aggregates a [huge](https://www.stopforumspam.com/contributors) amount of blacklist feeds. 478 | 479 | Still, in order to use the IPQualityScore API for in-depth threat reporting, it's necessary to [sign up](https://www.ipqualityscore.com/create-account) for their service (it's free) and get an API token (it will be emailed to you on sign-up), which will entitle you to 5000 free lookups per month. 480 | 481 | Once obtained, the api token should be written to one of the following files (parsed in that order): 482 | 483 | `$HOME/.asn/iqs_token` or 484 | `/etc/asn/iqs_token` 485 | 486 | The `/etc`-based file should be used when running asn in **server mode**. The `$HOME`-based file takes precedence if both files exist, and is ideal for **user mode** (that is, running `asn` interactively from the command line). 487 | 488 | In order to do so, you can use the following command: 489 | 490 | ***User mode:*** 491 | 492 | `TOKEN=""; mkdir "$HOME/.asn/" && echo "$TOKEN" > "$HOME/.asn/iqs_token" && chmod -R 600 "$HOME/.asn/"` 493 | 494 | ***Server mode:*** 495 | 496 | `TOKEN=""; mkdir "/etc/asn/" && echo "$TOKEN" > "/etc/asn/iqs_token" && chmod -R 700 "/etc/asn/" && chown -R nobody /etc/asn/` 497 | 498 | Either way, `asn` will pick up your token on the next run (no need to restart the service if running in server mode), and use it to query the IPQualityScore API. 499 | 500 | > ***Note:*** 501 | > *IPQualityScore is not queried by default for every target, but only for targets that get flagged as BAD by StopForumSpam. It's possible to override this behavior (and force IQS lookup for every target) by setting the `IQS_ALWAYS_QUERY` parameter to `true` in the [preferences file](#preferences-file-homeasnrc). It is also possible to specify [custom query settings](https://www.ipqualityscore.com/documentation/proxy-detection/overview) through the `IQS_CUSTOM_SETTINGS` parameter.* 502 | 503 |

504 | 505 | ### BGP hijack and route leak incidents (Cloudflare Radar) 506 | 507 |
Cloudflare token details

508 | 509 | When this token is available, an additional lookup will be enabled for **autonomous system** targets, in order to enumerate the BGP incidents (both **BGP hijacks** and **BGP route leaks**) involving the target ASN. 510 | 511 | The script will use the [Cloudfare Radar](https://radar.cloudflare.com/) API to retrieve the amount of incidents involving the target ASN in the past 12 months. Additionally, it will report how many incidents saw the target ASN as a **hijacker** or as a **victim**. 512 | 513 | The Cloudflare Radar API is **free** to use, but requires a registration. The steps are: 514 | 515 | 1. [Sign up](https://dash.cloudflare.com/sign-up) for a free Cloudflare account and **validate your email** 516 | 2. From the [Cloudflare dashboard](https://dash.cloudflare.com/profile/api-tokens/), go to **My Profile > API Tokens**. 517 | 3. Select **Create Token** 518 | 4. Choose the "*Read Cloudflare Radar data*" template 519 | 5. Click **Continue to summary** (the default values are fine) 520 | 6. Click **Create token** 521 | 522 | Once obtained, the api token should be written to one of the following files (parsed in that order): 523 | 524 | `$HOME/.asn/cloudflare_token` or 525 | `/etc/asn/cloudflare_token` 526 | 527 | The `/etc`-based file should be used when running asn in **server mode**. The `$HOME`-based file takes precedence if both files exist, and is ideal for **user mode** (that is, running `asn` interactively from the command line). 528 | 529 | In order to do so, you can use the following command: 530 | 531 | ***User mode:*** 532 | 533 | `TOKEN=""; mkdir "$HOME/.asn/" && echo "$TOKEN" > "$HOME/.asn/cloudflare_token" && chmod -R 600 "$HOME/.asn/"` 534 | 535 | ***Server mode:*** 536 | 537 | `TOKEN=""; mkdir "/etc/asn/" && echo "$TOKEN" > "/etc/asn/cloudflare_token" && chmod -R 700 "/etc/asn/" && chown -R nobody /etc/asn/` 538 | 539 | Either way, `asn` will pick up your token on the next run (no need to restart the service if running in server mode), and use it to query the Cloudflare Radar API. 540 | 541 |

542 | 543 | - - - 544 | 545 | ## Usage 546 | 547 | ##### *Syntax* 548 | 549 | `asn [OPTIONS] [TARGET]` 550 | 551 | `asn [-v] -l [SERVER OPTIONS]` 552 | 553 | where `TARGET` can be one of the following: 554 | 555 | * **AS number** \-\- lookup matching ASN and BGP announcements/neighbours data\. Supports "as123" and "123" formats \(case insensitive\) 556 | * **IPv4/IPv6/Prefix** \-\- lookup matching route\(4/6), IP reputation and ASN data 557 | * **Hostname** \-\- resolve the host and lookup data \(same as IPv4/IPv6 lookup\. Supports multiple IPs \- e\.g\. DNS RR\) 558 | * **URL** \-\- extract hostname/IP from the URL and lookup relative data\. Supports any protocol prefix\, non\-standard ports and [prepended credentials](https://en.wikipedia.org/wiki/Basic_access_authentication#URL_encoding) 559 | * **Organization name** \-\- search by company name and lookup network ranges exported by \(or related to\) the company 560 | 561 | Options: 562 | 563 | * `-t` 564 | 565 | * enables lookup and path tracing for targets **(this is the default behavior)** 566 | 567 | >*.asnrc option equivalent: `MTR_TRACING=true` (default: `true`)* 568 | 569 | * `-d` 570 | 571 | * enables detailed trace mode (more info below) 572 | 573 | >*.asnrc option equivalent: `DETAILED_TRACE=true` (default: `false`)* 574 | 575 | * `-n` 576 | 577 | * disables path tracing and only outputs lookup info _(for IP targets)_ 578 | * disables additional INETNUM/origin lookups _(for AS targets)_ 579 | 580 | >*.asnrc option equivalent: `MTR_TRACING=false` (default: `true`), `ADDITIONAL_INETNUM_LOOKUP=false` (default: `true`)* 581 | 582 | * `-s` 583 | 584 | * Launch a Shodan InternetDB scan for the target(s). Supports multiple targets, 585 | mixed target types (IP/hostname/CIDR/URL) and piping from stdin. 586 | 587 | * `-o` 588 | 589 | * forces a Search-By-Organization lookup and skip all target identification checks 590 | 591 | * `-a` 592 | 593 | * enable *ASN suggestion mode*. This will search for all ASNs matching a given name. 594 | 595 | * `-u` 596 | 597 | * enable *Transit/Upstream lookup mode*. This will inspect BGP updates and ASPATHs for the TARGET address/prefix and identify possible transit/upstream autonomous systems. 598 | 599 | * `-c` 600 | 601 | * enable *Country CIDR mode*. This will output all IPv4/v6 CIDR blocks allocated to the specified country. 602 | 603 | * `-g` 604 | 605 | * enable *Bulk Geolocation mode*. This will extract all IPv4/v6 addresses from the input, geolocate them and draw some stats. 606 | 607 | * `-l` 608 | 609 | * Launch the script in *server mode*. See **Server Options** below 610 | 611 | * `-j` 612 | 613 | * enables compact JSON output. Useful for feeding the output into other tools (like `jq` or other parsers), or storing the lookup results. 614 | 615 | >*.asnrc option equivalent: `JSON_OUTPUT=true` (default: `false`)* 616 | 617 | * `-J` 618 | 619 | * enables pretty-printed JSON output. 620 | 621 | >*.asnrc option equivalent: `JSON_PRETTY=true` (default: `false`)* 622 | 623 | * `-m` 624 | 625 | * enables monochrome mode (disables all colors). 626 | 627 | >*.asnrc option equivalent: `MONOCHROME_MODE=true` (default: `false`)* 628 | 629 | * `-v` 630 | 631 | * Enable debug messages (will display all URLs being queried to help identify external API slowdowns). In client mode, `asn` will log all output (external calls and their response data) to the location defined by `$ASN_LOGFILE` _(by default the logfile can be found at `$HOME/asndebug.log`)_. 632 | 633 | >*.asnrc option equivalent: `ASN_DEBUG=true` (default: `false`)* 634 | 635 | * `-h` 636 | 637 | * Show usage information. 638 | 639 | Server Options: 640 | 641 | * `BIND_ADDRESS` 642 | 643 | * IP address (v4/v6) to bind the listening server to (e.g. `asn -l 0.0.0.0`) 644 | 645 | >*.asnrc option equivalent: `DEFAULT_SERVER_BINDADDR_v4=""` (default: `"127.0.0.1"`) and `DEFAULT_SERVER_BINDADDR_v6=""` (default: `"::1"`)* 646 | 647 | * `BIND_PORT` 648 | 649 | * TCP Port to bind the listening server to (e.g. `asn -l 12345`) 650 | 651 | >*.asnrc option equivalent: `DEFAULT_SERVER_BINDPORT=""` (default: `"49200"`)* 652 | 653 | * `BIND_ADDRESS BIND_PORT` 654 | 655 | * IP address and port to bind the listening server to (e.g. `asn -l ::1 12345`) 656 | 657 | * `-v` 658 | 659 | * Enable verbose output and debug messages in server mode 660 | 661 | >*.asnrc option equivalent: `ASN_DEBUG=true` (default: `false`)* 662 | 663 | * `--allow host[,host,...]` 664 | 665 | * Allow only given hosts to connect to the server 666 | 667 | * `--allowfile file` 668 | 669 | * A file of hosts allowed to connect to the server 670 | 671 | * `--deny host[,host,...]` 672 | 673 | * Deny given hosts from connecting to the server 674 | 675 | * `--denyfile file` 676 | 677 | * A file of hosts denied from connecting to the server 678 | 679 | * `--max-conns ` 680 | 681 | * The maximum number of simultaneous connections accepted by the server. 100 is the default. 682 | 683 | >*Note: Every option in server mode (after* `-l`*) is passed directly to the ncat listener.* *Refer to* `man ncat` *for more details on the available commands.* 684 | *Unless specified, the default IP:PORT values of **127.0.0.1:49200** (for IPv4) or **[::1]:49200** (for IPv6) will be used (e.g.* `asn -l`*)* 685 | 686 | ##### *Default behavior:* 687 | 688 | * The script will attempt to automatically identify the `TARGET` type, if invoked with `-t`, `-n`, `-d` or without options, 689 | * AS path tracing is **enabled by default** for all lookups involving an IP or hostname. In case of multiple IP results, the script will trace the first IP, with a preference for IPv6 if possible on the user's host. 690 | 691 | ##### *Preferences file (`$HOME/.asnrc`)* 692 | 693 | Options defaults can be overridden by creating a file called `.asnrc` in the user's **home directory**. 694 | The following values are the defaults. Any (or all) of them can be specified in the settings file and adjusted to the user's preference: 695 | 696 | ```shell 697 | ASN_LOGFILE="$HOME/asndebug.log" 698 | MTR_TRACING=true 699 | ADDITIONAL_INETNUM_LOOKUP=true 700 | DETAILED_TRACE=false 701 | MTR_ROUNDS=5 702 | MAX_CONCURRENT_SHODAN_REQUESTS=10 703 | SHODAN_SHOW_TOP_N=5 704 | MONOCHROME_MODE=false 705 | ASN_DEBUG=false 706 | JSON_OUTPUT=false 707 | JSON_PRETTY=false 708 | DEFAULT_SERVER_BINDADDR_v4="127.0.0.1" 709 | DEFAULT_SERVER_BINDADDR_v6="::1" 710 | DEFAULT_SERVER_BINDPORT="49200" 711 | IQS_ALWAYS_QUERY=false 712 | IQS_CUSTOM_SETTINGS="" 713 | ``` 714 | 715 | ##### *Detailed mode (`-d` | `DETAILED_TRACE=true`)* 716 | 717 | * Detailed hop info reporting and RPKI validation can be turned on by passing the `[-d|--detailed]` command line switch. This will enable querying the public [pWhois server](https://pwhois.org/server.who) and the [RIPEStat RPKI validation API](https://stat.ripe.net/docs/data_api#rpki-validation) for every hop in the mtr trace. Relevant info will be displayed as a "tree" below the hop data, in addition to Team Cymru's server output (which only reports the AS name that the organization originating the prefix gave to its autonomous system number). This can be useful to figure out more details regarding the organization's name, the prefix' intended designation, and even (to a certain extent) its geographical scope. 718 | Furthermore, this will enable a warning whenever RPKI validation fails for one of the hops in the trace, indicating which AS in the path is wrongly announcing (as per current pWhois data) the hop prefix, indicating a potential route leak or BGP hijacking incident. 719 | 720 | ##### *Organization search (`-o`)* 721 | 722 | * The script will try to figure out if the input is an Organization name (i.e. if it doesn't look like an IP address, an AS number or a hostname). 723 | In order to force an organization search (for example for Orgs containing `.` in their name), pass the `[-o|--organization]` command line switch. 724 | 725 | ##### *ASN suggest (`-a`)* 726 | 727 | * The script will try to find ASNs matching the given search string, using the RIPEStat API. This mode can be used to map all the autonomous systems related to a given company. 728 | 729 | ##### *Upstream/transit identification (`-u`)* 730 | 731 | * The script will inspect BGP updates for the given IP (v4/v6) and identify the likelihood of the upstream autonomous system(s) being transit(s) for the origin AS. A probability of the upstreams being transits will be inferred by the amount of times the upstream AS appears in the observed ASPATHs towards the target IP, in comparison to other BGP peers. The script will also inform the user if the prefix is being simultaneously announced to multiple upstreams (e.g. in case of BGP multihoming, tier-1 prefixes, anycast addresses, etc.). JSON mode is supported. 732 | 733 | ##### *Server mode (`-l`)* 734 | 735 | * The script will start up a webserver allowing the user to run remote lookups and traceroutes directly from the browser. 736 | The web server is actually an [ncat](https://nmap.org/ncat/) listener waiting for requests, responding to browsers querying through the HTTP protocol. This interface makes for a straightforward integration into user workflow and no need to download any client-side tools. 737 | By simply using a Javascript [bookmarklet](https://en.wikipedia.org/wiki/Bookmarklet) or custom [search engine](https://www.howtogeek.com/114176/how-to-easily-create-search-plugins-add-any-search-engine-to-your-browser/), it will be possible to launch remote traces and lookups without ever leaving the browser. 738 | Refer to the [this section](#running-lookups-from-the-browser) for more information. 739 | 740 | ## Notes 741 | 742 | ##### *Organization data, IP Reputation, noise classification and IP fingerprinting* 743 | 744 | * Organization data is taken from pWhois 745 | * IP reputation data is taken from StopForumSpam and IpQualityScore 746 | > Reputation is also enriched with IP *noise* classification (addresses that have been observed scanning the Internet, and very likely to appear in your logs), taken from [GreyNoise](https://greynoise.io). This will also help identify known-good IPs (e.g. Google networks, CDNs, etc.) from aggressive, known-malicious scanners. 747 | * IP fingerprinting data is retrieved from Shodan's [InternetDB API](https://internetdb.shodan.io/). Data includes open ports, [software/hardware information](https://en.wikipedia.org/wiki/Common_Platform_Enumeration) and [known vulnerabilities](https://en.wikipedia.org/wiki/Common_Vulnerabilities_and_Exposures) pertaining to the IP address. 748 | 749 | ##### *Geolocation* 750 | 751 | The script will perform IP and trace hop geolocation with this logic: 752 | 753 | 1. Using the [ipinfo.io](https://ipinfo.io/) service as a primary source of geolocation data. It offers extremely precise geolocation data based on a proprietary network of geographically distributed probes, and is extremely reliable 754 | 2. Using the [ip-api](https://ip-api.com/) service as a fallback source of geolocation data 755 | 3. Using the [Prefix Whois](https://pwhois.org/) service as a last-resort source of geolocation data 756 | 757 | ##### *IP Classification* 758 | 759 | The script will use the ip-api, incolumitas.com, ipinfo.io and PeeringDB services to classify target IPs and trace hops into these categories: 760 | 761 | * [Anycast](https://en.wikipedia.org/wiki/Anycast) IP 762 | * Mobile network 763 | * Proxy host (TOR exit node/VPN/etc) 764 | * Hosting network (datacenter/hosting provider/etc) along with detailed DC and region identification where available 765 | * IXP network 766 | 767 | ##### *IXP detection and unannounced prefixes* 768 | 769 | * The script will detect [IXPs](https://en.wikipedia.org/wiki/Internet_exchange_point) traversed during path traces by matching them with [PeeringDB](https://www.peeringdb.com/)'s comprehensive dataset of IXP prefixes. 770 | * The script will also attempt a best-effort, fallback generic `whois` lookup when Team Cymru, pWhois and PeeringDB have no info about the IP address or prefix. This is usually the case with some [PNI](https://en.wikipedia.org/wiki/Peering#Private_peering) prefixes, and will give better insight into the path taken by packets. 771 | 772 | ## Running lookups from the browser 773 | 774 | ##### *Prerequisite tools for server mode* 775 | 776 | Server mode requires two tools for its functionality: `ncat` and `aha`. Specifically, [aha](https://github.com/theZiz/aha) (the ANSI->HTML converter) v0.5+ is required. The ncat tool is contained inside the *nmap* package on older distributions (e.g. Ubuntu 18.04, Debian 9), while it is packaged as a standalone tool on newer ones. 777 | 778 | Please refer to the [installation](#installation) section and run the appropriate commands to install the required packages for your operating system, and optionally to install the asn server as a systemd service. 779 | 780 | ##### *Advantages of server mode* 781 | 782 | The main advantage of running lookups from the browser, is that every IP address and AS number gets converted into a hyperlink, allowing to perform subsequent lookups by simply clicking on them. 783 | 784 | When looking up an URL/hostname/domain, quick WHOIS info and links to relevant external resources will be available in the results. 785 | 786 | When looking up an AS number, all peering ASNs will be clickable. Also, if an AS peers at a public facility, PeeringDB info for that facility will be linked directly. Furthermore, additional external BGP information sources will be linked, directly for the target ASN. 787 | 788 | Here are some examples: 789 | 790 | ![srvmode_hostname_lookup](https://user-images.githubusercontent.com/24555810/117340152-e1217a00-aea0-11eb-9d8f-abaea0d3389e.png) 791 | 792 | ![srvmode_whois](https://user-images.githubusercontent.com/24555810/117340278-01e9cf80-aea1-11eb-8cad-457f60e80a86.png) 793 | 794 | ![srvmode_asn_lookup](https://user-images.githubusercontent.com/24555810/117340969-d7e4dd00-aea1-11eb-8e94-88d166f67360.png) 795 | 796 | #### Server side 797 | 798 | Once started in **server mode**, `asn` will spin up a custom webserver waiting for browser requests. This is what the server-side console looks like: 799 | 800 | ![server_console](https://user-images.githubusercontent.com/24555810/102154363-80ee5500-3e79-11eb-840f-53e3619be2e4.png) 801 | 802 | The server is now ready to accept browser requests (only from the local machine, in this case - since I've launched it with no command line switches, which defaults to listening on **127.0.0.1:49200**. Refer to the [usage](#usage) section for more information about the available server options). 803 | 804 | #### Client side 805 | 806 | Visit [this page](http://127.0.0.1:49200/asn_bookmarklet) in your browser and follow the instructions to copy the bookmarklet to your bookmarks toolbar: 807 | 808 | ![bookmarklet_install](https://user-images.githubusercontent.com/24555810/102159720-640b4f00-3e84-11eb-8360-afa79b6f0f5f.png) 809 | 810 | ##### *How it works* 811 | 812 | The bookmarklet is actually a small piece of Javascript code which will grab the hostname of the website you're currently visiting in the browser, and pass it to the server through a simple *HTTP GET* request. The server then proceeds to perform the lookup and traceroute (from its own viewpoint, just like it does when ran interactively from the command line), and feed the results to your browser through an HTML page, mimicking the effect of a scrolling terminal. 813 | 814 | >*Note: The link you drag to the bookmarks bar is actually a *minified* (i.e.: compacted) version of the source javascript code, but for reference, here's the full source:* 815 | > 816 | >```javascript 817 | >javascript:(function () { 818 | > var asnserver = "localhost:49200"; 819 | > var target = window.location.hostname; 820 | > var width = screen.width - screen.width / 7; 821 | > var height= screen.height - screen.height / 4; 822 | > var left = window.innerWidth / 2 - width / 2; 823 | > var top = window.innerHeight / 2 - height / 2; 824 | > window.open("http://" + asnserver + "/asn_lookup&" + target, "newWindow", "width=" + width + ",height=" + height + ",top=" + top + ",left=" + left); 825 | >})(); 826 | >``` 827 | > 828 | >*If you want to "un-minify" the actual bookmarklet code, you can refer to [this site](https://unminify.com/)* 829 | 830 | Once the trace is finished, an option to share the output on [termbin](https://termbin.com/) is given to the user. This makes for quick sharing of the traceroute or lookup output with other people: 831 | 832 | ![termbin](https://user-images.githubusercontent.com/24555810/102160506-dc264480-3e85-11eb-9e14-8c851f261172.png) 833 | 834 | ![termbin_2](https://user-images.githubusercontent.com/24555810/102168101-f49b5c80-3e8f-11eb-8bc6-9f0592fa9624.png) 835 | 836 | #### Search engine setup 837 | 838 | In order to take full advantage of having `asn` inside the browser, it is possible to configure it as a custom search engine for the browser search bar. This allows to leverage the server to search for **ASNs**, **URLs**, **IPs**, **Hostnames**, and so on, depending on the search string. 839 | 840 | Generally speaking, this implies instructing the browser that when a certain **keyword** is prepended to a search, the following characters (the actual **search string**, identified by `%s`) have to be passed to a certain URL. The URL is then composed according to this logic, and opened just like a normal webpage. 841 | 842 | I've used `@asn` for my keyword, but anything would do. In order to speed up things, one could very well use a shorter tag (e.g. `#`) that, when used in the address bar, automatically switches your search engine to the ASN Lookup server. 843 | Note that the leading `@` sign is not mandatory, just handy since it doesn't get in the way of normal searches, but there's much freedom with that. 844 | 845 | For quick reference, the location URL string to enter (for both Firefox and Chrome) is: `http://127.0.0.1:49200/asn_lookup&%s`. Of course that sends lookup requests to the *locally* running ASN server. 846 | 847 | Here's how to add a search engine in Firefox and Chrome: 848 | 849 | ***Firefox:*** 850 | 851 | * Simply create a new bookmark and fill its details like this: 852 | 853 | ![searchsetup_firefox](https://user-images.githubusercontent.com/24555810/102160982-c6fde580-3e86-11eb-9885-c23eb60d622b.png) 854 | 855 | Afterwards, you will be able to run queries and traceroutes by simply entering, for example, `@asn 8.8.8.8` in the browser's location bar. 856 | 857 | ***Chrome:*** 858 | 859 | 1. Right click the location bar and select **Manage search engines...** 860 | 861 | ![searchsetup_chrome_1](https://user-images.githubusercontent.com/24555810/102161929-87d09400-3e88-11eb-9e42-70087e3fab87.png) 862 | 863 | 2. Click **Add**: 864 | 865 | ![searchsetup_chrome_2](https://user-images.githubusercontent.com/24555810/102162100-dc740f00-3e88-11eb-8037-528fbcc636e9.png) 866 | 867 | 3. Fill in the details as shown below: 868 | 869 | ![searchsetup_chrome_3](https://user-images.githubusercontent.com/24555810/102162218-16451580-3e89-11eb-85d1-a4d24c980d7d.png) 870 | 871 | As usual, the keyword is entirely customizable to your preference. 872 | 873 | ***Other browsers:*** 874 | 875 | * You may want to follow [this post](https://www.howtogeek.com/114176/how-to-easily-create-search-plugins-add-any-search-engine-to-your-browser/) to search for instructions on how to add a custom search engine for your browser of choice. 876 | 877 | #### Running the server on an external host 878 | 879 | ##### *Port forwarding* 880 | 881 | In order to access the server remotely, beside binding to `0.0.0.0` (or any other relevant IP address for your scenario), if the host is behind a NAT router, you'll need to forward the listening port (`BIND_PORT`) from the host/router outside IP to the actual machine where the ASN server is running on. 882 | It is a single TCP port (by default `TCP/49200`), and you can change it via the command line parameters (see [Usage](#usage)). 883 | 884 | ##### *Textual browser client* 885 | 886 | It is possible to launch remote traces from another command line, and view the results directly in the terminal. All it takes is a compatible text browser, for example `elinks` (but you can download results for later reviewing even using `curl` or really anything else). 887 | 888 | The script makes use of 8-bit ANSI colors for its output, so the command to launch a remote trace using elinks would be something like this: 889 | 890 | `elinks -dump -dump-color-mode 3 http://:49200/asn_lookup&8.8.8.8` 891 | 892 | ##### *Security considerations* 893 | 894 | The server logic in itself is very simple: the script implements a basic web server entirely in BASH, leveraging the fact that it can talk to a browser using the HTTP protocol and the HTML language, in a reasonably simple way. 895 | 896 | The core behind it revolves around [ncat](https://nmap.org/ncat/), a very robust and stable netcat-like network tool. This is the actual "server" listening for incoming connection, and spawning connection handlers (that is, 'single-purpose' instances of the `asn` script itself) as clients connect. 897 | 898 | If you decide to open it to the outside (i.e.: binding it to something that is not localhost, and launching traces from outside your local machine), please bear in mind that there is no authentication mechanism (yet) integrated into the code, so theoretically anybody with the right URL could *spawn traceroutes from your server* and view the results (bear in mind however that the server sanitizes user input by stripping any dangerous characters). 899 | 900 | To contrast that, fortunately `ncat` implements a robust allow/deny logic (based both on command line parameters and files, a la `/etc/hosts.allow` and `hosts.deny`). The script supports passing parameters directly to `ncat`, therefore it's possible to make full use of its filtering capabilities and lock the server to a restricted range of trusted IPs. 901 | 902 | The available options, and some usage examples, can be viewed by running `asn -h`. 903 | 904 | >*Note: if you plan to run the server somewhere else than your local machine, remember to change the bookmarklet code and the custom search engine URL values to reflect the actual IP of the asn server. It is naturally possible to have multiple bookmarklets and search engine keywords to map to different ASN server instances.* 905 | > 906 | >*For the bookmarklet, you'll need to change this value at the very beginning:* `var asnserver="localhost:49200"` *and make it point to the new address:port pair. No further change is required in the remaining JS code.* 907 | 908 | ## Shodan scanning (Recon Mode) 909 | 910 | The tool can query Shodan's InternetDB API to look up information regarding any type of targets when launched with the `-s` command line switch. 911 | 912 | If the scan identifies any vulnerabilities, the NIST NVD API is queried in order to provide descriptions, any well known names and a link to learn more about the top ones. 913 | 914 | Currently supported targets are: 915 | 916 | - **IP addresses** 917 | - **CIDR blocks** *(will scan all of the IPs in the range)* 918 | - **URLs** 919 | - **Hostnames** *(will resolve to an IP (or list of IPs) and query all of them)* 920 | 921 | Target types can be mixed and queried in a single run. Targets can be piped to the tool via standard input as well. 922 | 923 | *Usage Examples:* 924 | 925 | `asn -s 1.1.1.1 8.8.8.8 9.9.9.9` 926 | 927 | `asn -s https://www.google.com 8.8.8.0/24` 928 | 929 | `asn -s < iplist` 930 | 931 | `curl -s https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/blocklist_de_bots.ipset | asn -s` 932 | 933 | Shodan scan results can be output in JSON mode by passing the `-j` or `-J` options. 934 | 935 | >*Note: the Nmap tool is needed to use this feature, but note that **no packets whatsoever** are sent to the targets. Nmap is only required to break down CIDR blocks into single IPs (as a calculator tool).* 936 | 937 | ## Mapping the IP(v4/v6) address space of specific countries 938 | 939 | The tool will search and display all IPv4 and IPv6 CIDR blocks allocated to a specific country when launched with the `-c` command line switch, plus some statistics. 940 | 941 | * Searching for a specific country code with a leading dot (e.g. `.fr`) will yield direct results for France, while full text search will display country codes matching the search string, or proceed to display the results if only one match is found. 942 | * Statistics such as v4 prefix length distribution, total IPv4 addresses available to the country, IPv4 addresses per capita, etc. are included. 943 | * JSON output is supported. 944 | 945 | *Usage Examples:* 946 | 947 | `asn -c germany` 948 | 949 | `asn -c .de` 950 | 951 | ```shell 952 | # scan a random norwegian subnet for CVE/CPE/open ports/hostnames: 953 | asn -jc .no | jq -r ".results[] | .ipv4[$RANDOM % .ipv4_blocks]" | asn -s 954 | ``` 955 | 956 | ## Bulk geolocation mode 957 | 958 | In this mode the tool will extract all IPv4 and IPv6 addresses from the input data and geolocate them. Anycast detection and general stats (top IPv4/IPv6 addresses with number of occurrences, number of IPs per country etc.) are included in the output. Bulk geolocation is quicker than normal `asn` lookups (300 IP addresses can be parsed in ~5s), and its main use case is to extract, geolocate and calculate country/occurrence stats for any number of IPs from arbitrarily formatted data streams (e.g. server logs). JSON output and stdin input are supported. 959 | 960 | *Usage Examples:* 961 | 962 | `asn -g 1.1.1.1 8.8.8.8` 963 | 964 | ```shell 965 | # geolocate webserver clients 966 | asn -g < /var/log/apache2/access.log 967 | ``` 968 | 969 | ```shell 970 | # geolocate IPs that have logged in to the system 971 | last | asn -g 972 | ``` 973 | 974 | ## JSON output and API mode 975 | 976 | #### Locally (shell mode) 977 | 978 | The tool can be instructed to output lookup results in JSON mode by using the `-j` (compact JSON) or `-J` (pretty-printed JSON) command line options: 979 | 980 |
Example 1 - IPv4 lookup

981 | 982 | ##### Command: 983 | 984 | `asn -J 8.8.8.8` 985 | 986 | ##### Output: 987 | 988 | ```json 989 | { 990 | "target": "8.8.8.8", 991 | "target_type": "ipv4", 992 | "result": "ok", 993 | "reason": "success", 994 | "version": "0.78.0", 995 | "request_time": "2024-08-20T02:50:28", 996 | "request_duration": 5, 997 | "api_tokens": { 998 | "ipqualityscore": true, 999 | "ipinfo": true, 1000 | "cloudflare": true 1001 | }, 1002 | "result_count": 1, 1003 | "results": [ 1004 | { 1005 | "ip": "8.8.8.8", 1006 | "ip_version": "4", 1007 | "reverse": "dns.google", 1008 | "org_name": "Google LLC", 1009 | "net_range": "8.8.8.0/24", 1010 | "net_name": "GOGL", 1011 | "abuse_contacts": [ 1012 | "network-abuse@google.com" 1013 | ], 1014 | "routing": { 1015 | "is_announced": true, 1016 | "as_number": "15169", 1017 | "as_name": "GOOGLE, US", 1018 | "as_rank": "1788", 1019 | "route": "8.8.8.0/24", 1020 | "route_name": "", 1021 | "roa_count": "1", 1022 | "roa_validity": "valid" 1023 | }, 1024 | "type": { 1025 | "is_bogon": false, 1026 | "is_anycast": true, 1027 | "is_mobile": false, 1028 | "is_proxy": false, 1029 | "is_dc": true, 1030 | "dc_details": { 1031 | "dc_name": "Google LLC" 1032 | }, 1033 | "is_ixp": false 1034 | }, 1035 | "geolocation": { 1036 | "city": "Mountain View", 1037 | "region": "California", 1038 | "country": "United States", 1039 | "cc": "US" 1040 | }, 1041 | "reputation": { 1042 | "status": "good", 1043 | "is_known_good": true, 1044 | "known_as": "Google Public DNS" 1045 | }, 1046 | "fingerprinting": { 1047 | "ports": [ 1048 | 53, 1049 | 443 1050 | ] 1051 | } 1052 | } 1053 | ] 1054 | } 1055 | ``` 1056 |

1057 |
Example 2 - ASN lookup

1058 | 1059 | ##### Command: 1060 | 1061 | `asn -J 5505` 1062 | 1063 | ##### Output: 1064 | 1065 | ```json 1066 | { 1067 | "target": "5505", 1068 | "target_type": "asn", 1069 | "result": "ok", 1070 | "reason": "success", 1071 | "version": "0.78.0", 1072 | "request_time": "2024-08-20T02:50:46", 1073 | "request_duration": 17, 1074 | "api_tokens": { 1075 | "ipqualityscore": true, 1076 | "ipinfo": true, 1077 | "cloudflare": true 1078 | }, 1079 | "result_count": 1, 1080 | "results": [ 1081 | { 1082 | "asn": "5505", 1083 | "asname": "VADAVO, ES", 1084 | "asrank": 4448, 1085 | "org": "VDV-VLC-RED06 VDV-VLC-RED06 - CLIENTES TELECOM", 1086 | "holder": "VADAVO SOLUCIONES SL", 1087 | "abuse_contacts": [ 1088 | "abuse@vadavo.com" 1089 | ], 1090 | "registration_date": "2016-12-13T08:28:07", 1091 | "ixp_presence": [ 1092 | "DE-CIX Madrid: DE-CIX Madrid Peering LAN", 1093 | "ESpanix Madrid Lower LAN" 1094 | ], 1095 | "prefix_count_v4": 8, 1096 | "prefix_count_v6": 1, 1097 | "bgp_peer_count": 36, 1098 | "bgp_hijack_incidents": { 1099 | "total": 0, 1100 | "as_hijacker": 0, 1101 | "as_victim": 0 1102 | }, 1103 | "bgp_leak_incidents": { 1104 | "total": 0 1105 | }, 1106 | "bgp_peers": { 1107 | "upstream": [ 1108 | "1299", 1109 | "6939", 1110 | "59432", 1111 | "174", 1112 | "34549", 1113 | "25091", 1114 | "35625", 1115 | "33891", 1116 | "48348", 1117 | "13030", 1118 | "8218", 1119 | "41327", 1120 | "3303", 1121 | "4455", 1122 | "6424", 1123 | "6057", 1124 | "34927", 1125 | "9498", 1126 | "35280", 1127 | "1239" 1128 | ], 1129 | "downstream": [ 1130 | "48952", 1131 | "208248", 1132 | "205086", 1133 | "202054" 1134 | ], 1135 | "uncertain": [ 1136 | "24482", 1137 | "51185", 1138 | "41047", 1139 | "29680", 1140 | "212483", 1141 | "198150", 1142 | "14840", 1143 | "49544", 1144 | "39384", 1145 | "37721", 1146 | "36236", 1147 | "25160" 1148 | ] 1149 | }, 1150 | "announced_prefixes": { 1151 | "v4": [ 1152 | "185.210.225.0/24", 1153 | "188.130.247.0/24", 1154 | "185.210.227.0/24", 1155 | "185.123.205.0/24", 1156 | "185.123.207.0/24", 1157 | "185.210.226.0/24", 1158 | "185.123.206.0/24", 1159 | "185.123.204.0/24" 1160 | ], 1161 | "v6": [ 1162 | "2a03:9320::/32" 1163 | ] 1164 | }, 1165 | "inetnums": { 1166 | "v4": [ 1167 | "185.123.204.0/22", 1168 | "185.210.225.0/24", 1169 | "185.210.226.0/24", 1170 | "185.210.227.0/24", 1171 | "188.130.247.0/24" 1172 | ], 1173 | "v6": [ 1174 | "2a03:9320::/32" 1175 | ] 1176 | }, 1177 | "inetnums_announced_by_other_as": { 1178 | "v4": [ 1179 | { 1180 | "prefix": "188.130.254.0/24", 1181 | "origin_asn": "", 1182 | "origin_org": "", 1183 | "is_announced": false 1184 | } 1185 | ], 1186 | "v6": [] 1187 | } 1188 | } 1189 | ] 1190 | } 1191 | ``` 1192 | 1193 |

1194 |
Example 3 - enumerating abuse contacts for every IP to which a hostname resolves

1195 | 1196 | ##### Command: 1197 | 1198 | `asn -j www.google.com | jq '[.results[].abuse_contacts[]] | unique[]'` 1199 | 1200 | ##### Output: 1201 | 1202 | ``` 1203 | "network-abuse@google.com" 1204 | "ripe-contact@google.com" 1205 | ``` 1206 | 1207 |

1208 |
Example 4 - enumerating known vulnerabilities for a target

1209 | 1210 | ##### Command: 1211 | 1212 | `asn -j 45.67.34.100 | jq '.results[].fingerprinting.vulns[]'` 1213 | 1214 | ##### Output: 1215 | ``` 1216 | "CVE-2017-15906" 1217 | "CVE-2018-15919" 1218 | ``` 1219 | 1220 |

1221 |
Example 5 - upstream/transit AS lookup for a given IP

1222 | 1223 | ##### Command: 1224 | 1225 | `asn -Ju 72.17.119.201` 1226 | 1227 | ##### Output: 1228 | 1229 | ```json 1230 | { 1231 | "target": "72.17.119.201", 1232 | "target_type": "ipv4", 1233 | "result": "ok", 1234 | "reason": "success", 1235 | "version": "0.78.0", 1236 | "request_time": "2024-08-20T02:54:03", 1237 | "request_duration": 4, 1238 | "api_tokens": { 1239 | "ipqualityscore": true, 1240 | "ipinfo": true, 1241 | "cloudflare": true 1242 | }, 1243 | "result_count": 1, 1244 | "results": [ 1245 | { 1246 | "prefix": "72.17.0.0/17", 1247 | "origin_as": "33363", 1248 | "origin_as_name": "BHN-33363, US", 1249 | "origin_as_rank": 441, 1250 | "upstreams_count": 1, 1251 | "upstreams": [ 1252 | { 1253 | "asn": "7843", 1254 | "asname": "TWC-7843-BB, US", 1255 | "probability": 100, 1256 | "is_tier1": false 1257 | } 1258 | ], 1259 | "multiple_upstreams": false 1260 | } 1261 | ] 1262 | } 1263 | ``` 1264 | 1265 |

1266 |
Example 6 - enumerating unannounced address blocks for a given AS

1267 | 1268 | ##### Command: 1269 | 1270 | `asn -j AS5505 | jq -r '.results[].inetnums_announced_by_other_as.v4[] | select(.is_announced==false) | .prefix'` 1271 | 1272 | ##### Output: 1273 | 1274 | ``` 1275 | 188.130.254.0/24 1276 | ``` 1277 | 1278 |

1279 |
Example 7 - enumerating the amount of BGP hijacking incidents involving a given AS

1280 | 1281 | ##### Command: 1282 | 1283 | `asn -j AS8860 | jq '.results[].bgp_hijack_incidents'` 1284 | 1285 | ##### Output: 1286 | 1287 | ``` 1288 | { 1289 | "total": 18, 1290 | "as_hijacker": 11, 1291 | "as_victim": 7 1292 | } 1293 | ``` 1294 | 1295 |

1296 | 1297 | #### Remotely (API endpoint) 1298 | 1299 | By running the script in [server mode](#running-lookups-from-the-browser), it is possible to use it as a self-hosted lookup API service by running HTTP queries against it and retrieving the results in compact or pretty-printed JSON format. The server exposes the `asn_lookup_json` and `asn_lookup_jsonp` endpoints for this purpose. The syntax is the same as with normal browser-based remote queries. 1300 | 1301 | *Example 1: querying the server remotely using `curl` (compact output):* 1302 | 1303 | ```shell 1304 | root@KRUSTY:~# curl -s "http://localhost:49200/asn_lookup_json&1.1.1.1" 1305 | {"target":"1.1.1.1","target_type":"ipv4","result":"ok","reason":"success","version":"0.72.1","request_time":"2022-03-29T00:13:11","request_duration":5,"result_count":1,"results":[{"ip":"1.1.1.1","ip_version":"4","reverse":"one.one.one.one","org_name":"APNIC and Cloudflare DNS Resolver project","abuse_contacts":["helpdesk@apnic.net"],"routing":{"is_announced":true,"as_number":"13335","as_name":"CLOUDFLARENET, US","net_range":"1.1.1.0/24","net_name":"APNIC-LABS","roa_count":"1","roa_validity":"valid"},"type":{"is_bogon":false,"is_anycast":true,"is_mobile":false,"is_proxy":false,"is_dc":true,"dc_details":{"dc_name":"Cloudflare"},"is_ixp":false},"geolocation":{"city":"Magomeni","region":"Dar es Salaam","country":"Tanzania","cc":"TZ"},"reputation":{"status":"good","is_known_good":true,"known_as":"Cloudflare Public DNS"},"fingerprinting":{"ports":[53,80,443]}}]} 1306 | ``` 1307 | 1308 | *Example 2: querying the server remotely using `curl` (pretty printed output):* 1309 | 1310 | ```shell 1311 | root@KRUSTY:~# curl -s "http://localhost:49200/asn_lookup_jsonp&10.0.0.1" 1312 | { 1313 | "target": "10.0.0.1", 1314 | "target_type": "ipv4", 1315 | "result": "ok", 1316 | "reason": "success", 1317 | "version": "0.72.1", 1318 | "request_time": "2022-03-29T00:14:57", 1319 | "request_duration": 0, 1320 | "result_count": 1, 1321 | "results": [ 1322 | { 1323 | "ip": "10.0.0.1", 1324 | "ip_version": "4", 1325 | "org_name": "IANA", 1326 | "routing": { 1327 | "is_announced": false, 1328 | "net_name": "PRIVATE-ADDRESS-ABLK-RFC1918-IANA-RESERVED" 1329 | }, 1330 | "type": { 1331 | "is_bogon": true, 1332 | "bogon_type": "rfc1918 (Private Space)" 1333 | }, 1334 | "reputation": {}, 1335 | "fingerprinting": {} 1336 | } 1337 | ] 1338 | } 1339 | ``` 1340 | 1341 | - - - 1342 | 1343 | ## Thanks 1344 | 1345 | An initial version of this script was featured in the **Security Trails** blog post "[*ASN Lookup Tools, Strategies and Techniques*](https://securitytrails.com/blog/asn-lookup#autonomous-system-lookup-script)". Thank you [Esteban](https://www.estebanborges.com/)! 1346 | 1347 | Thanks [Massimo Candela](https://github.com/massimocandela/) for your support and excellent work on [IPmap](https://ipmap.ripe.net/), [BGPlay](https://github.com/massimocandela/BGPlay) and [TraceMON](https://github.com/RIPE-NCC/tracemon)! 1348 | 1349 | Thanks to all the awesome contributors for their code, ideas, suggestions, packages and bug reports! 1350 | 1351 | ## Feedback and contributing 1352 | 1353 | Any feedback or pull request to improve the code is welcome. Feel free to contribute! 1354 | -------------------------------------------------------------------------------- /asn.1: -------------------------------------------------------------------------------- 1 | .TH ASN 1 "March 2025" "0.78.5" "User Commands" 2 | .SH NAME 3 | asn \- ASN / RPKI validity / BGP stats / IPv4v6 / Prefix / ASPath / Organization / IP reputation lookup tool 4 | .SH SYNOPSIS 5 | .B asn 6 | [\fIOPTIONS\fR] [\fITARGET\fR] 7 | .br 8 | .B asn 9 | [\fB-v\fR] \fB-l\fR [\fISERVER OPTIONS\fR] 10 | .SH DESCRIPTION 11 | ASN is a tool for performing various lookup operations related to ASN (Autonomous System Number), RPKI validity, BGP statistics, IPv4/v6 addresses, prefixes, ASPaths, organizations, and IP reputations. 12 | .SH OPTIONS 13 | .TP 14 | \fB-t\fR 15 | .B (enable trace) 16 | .br 17 | Enable AS path trace to the 18 | .B TARGET 19 | (this is the default behavior) 20 | .TP 21 | \fB-n\fR 22 | .B (no trace|no additional INETNUM lookups) 23 | .br 24 | Disable tracing the AS path to the 25 | .B TARGET 26 | (for IP targets) or 27 | .br 28 | Disable additional (unannounced / announced by other AS) INETNUM lookups for the 29 | .B TARGET 30 | (for AS targets) 31 | .TP 32 | \fB-d\fR 33 | .B (detailed) 34 | Output detailed hop info during the AS path trace to the 35 | .B TARGET 36 | .br 37 | This option also enables RPKI validation/BGP hijacking detection for every hop 38 | .TP 39 | \fB-a\fR 40 | .B (ASN Suggest) 41 | .br 42 | Lookup AS names and numbers matching 43 | .B TARGET 44 | .TP 45 | \fB-u\fR 46 | .B (Transit/Upstream lookup) 47 | .br 48 | Inspect BGP updates and ASPATHs for the 49 | .B TARGET 50 | address/prefix and identify possible transit/upstream autonomous systems 51 | .TP 52 | \fB-c\fR 53 | .B (Country CIDR) 54 | .br 55 | Lookup all IPv4/v6 CIDR blocks allocated to the 56 | .B TARGET 57 | country 58 | .TP 59 | \fB-g\fR 60 | .B (Bulk Geolocate) 61 | .br 62 | Geolocate all IPv4/v6 addresses passed as 63 | .B TARGET 64 | .br 65 | This mode supports multiple targets, stdin input and IP extraction from input, e.g. 66 | .br 67 | .B asn -g < /var/log/apache2/error.log 68 | or 69 | .B echo 1.1.1.1 2.2.2.2 | asn -g 70 | .TP 71 | \fB-s\fR 72 | .B (Shodan scan) 73 | .br 74 | Query Shodan's InternetDB for CVE/CPE/Tags/Ports/Hostnames data about TARGET 75 | .br 76 | This mode supports multiple targets and stdin input, e.g. 77 | .br 78 | .B asn -s < iplist 79 | or 80 | .B echo 1.1.1.0/24 google.com | asn -s 81 | .TP 82 | \fB-o\fR 83 | .B (organization search) 84 | .br 85 | Force 86 | .B TARGET 87 | to be treated as an Organization Name 88 | .TP 89 | \fB-m\fR 90 | .B (monochrome output) 91 | .br 92 | Disable colored output 93 | .TP 94 | \fB-v\fR 95 | .B (verbose) 96 | .br 97 | Enable (and log to $HOME/asndebug.log) debug messages (URLs being queried and variable names being assigned) 98 | .br 99 | API call response data (i.e. the JSON output) is logged to the logfile. 100 | .TP 101 | \fB-j\fR 102 | .B (compact JSON output) 103 | .br 104 | Set output to compact JSON mode (ideal for machine parsing) 105 | .TP 106 | \fB-J\fR 107 | .B (pretty-printed JSON output) 108 | .br 109 | Set output to pretty-printed JSON mode 110 | .TP 111 | \fB-h\fR 112 | .B (help) 113 | .br 114 | Show this help screen 115 | .TP 116 | \fB-l\fR 117 | .B (lookup server) 118 | .br 119 | Launch the script in server mode. See 120 | .B SERVER OPTIONS 121 | below 122 | .SH TARGET 123 | .TP 124 | \fB\fR 125 | Lookup matching ASN and BGP announcements/neighbours data. 126 | .TP 127 | \fB\fR 128 | Lookup matching route(4/6), IP reputation, and ASN data. 129 | .TP 130 | \fB\fR 131 | Lookup matching ASN data. 132 | .TP 133 | \fB\fR 134 | Lookup matching IP, route, and ASN data. Supports multiple IPs - e.g. DNS RR. 135 | .TP 136 | \fB\fR 137 | Extract hostname/IP from the URL and lookup relative data. Supports any protocol prefix, non-standard ports, and prepended credentials. 138 | .TP 139 | \fB\fR 140 | Search by company name and lookup network ranges exported by (or related to) the company. 141 | .SH SERVER OPTIONS 142 | .TP 143 | \fB\&BIND_ADDRESS\fR 144 | IP address (v4/v6) to bind the listening server to (e.g., 'asn -l 0.0.0.0'). 145 | .br 146 | Default value: 147 | .B 127.0.0.1 (IPv4) or ::1 (IPv6). 148 | .TP 149 | \fB\&BIND_PORT\fR 150 | TCP Port to bind the listening server to (e.g., 'asn -l 12345'). 151 | .br 152 | Default value: 153 | .B 49200. 154 | .TP 155 | \fB\&BIND_ADDRESS BIND_PORT\fR 156 | IP address and port to bind the listening server to (e.g., 'asn -l ::1 12345'). 157 | .TP 158 | .B \fB-v\fR 159 | .B (verbose) 160 | .br 161 | Enable verbose output and debug messages in server mode. 162 | .TP 163 | .B \fB--allow\fR host[,host,...] 164 | Allow only given hosts to connect to the server. 165 | .TP 166 | .B \fB--allowfile\fR file 167 | A file of hosts allowed to connect to the server. 168 | .TP 169 | .B \fB--deny\fR host[,host,...] 170 | Deny given hosts from connecting to the server. 171 | .TP 172 | .B \fB--denyfile\fR file 173 | A file of hosts denied from connecting to the server. 174 | .TP 175 | .B \fB-m\fR, \fB--max-conns\fR 176 | The maximum number of simultaneous connections accepted by the server. 100 is the default. 177 | .SH NOTES 178 | Every option in server mode (after -l) is passed directly to the ncat listener. Refer to 179 | .B man ncat 180 | for more details on the available commands. Unless specified, the default IP:PORT values of 127.0.0.1:49200 (for IPv4) or [::1]:49200 (for IPv6) will be used (e.g., 'asn -l'). 181 | .SH EXAMPLES 182 | Example server usage: 183 | .PP 184 | .B asn -l 185 | (starts server on default IP(v4/v6):PORT) 186 | .PP 187 | .B asn -l 0.0.0.0 --allow 192.168.0.0/24,192.168.1.0/24,192.168.2.245 188 | (binds to all available IPv4 interfaces on the default port, allowing only connections from the three specified subnets) 189 | .PP 190 | .B asn -l :: 2222 --allow 2001:DB8::/32 191 | (binds to all available IPv6 interfaces on port 2222, allowing only connections from the specified prefix) 192 | .PP 193 | .B asn -v -l 0.0.0.0 --allowfile "~/goodips.txt" -m 5 194 | (verbose mode, bind to all IPv4 interfaces, use an allowfile with allowed addresses, accept a maximum of 5 concurrent connections) 195 | .SH "SEE ALSO" 196 | To file a bug report or feature request, please open an issue on the project homepage: 197 | .B https://github.com/nitefood/asn 198 | .SH "AUTHOR" 199 | Project author: nitefood 200 | .B 201 | .PP 202 | This manpage was created by Marcos Rodrigues de Carvalho (aka oday) 203 | .B 204 | -------------------------------------------------------------------------------- /cloudshell_bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | read -r -d '' banner <<- END_OF_BANNER 4 | #########################################################################################################" 5 | # Helper script to prepare the GCP environment (install prerequisite packages / install the ASN script) # 6 | # Project homepage: https://github.com/nitefood/asn # 7 | ######################################################################################################### 8 | END_OF_BANNER 9 | 10 | green=$'\e[38;5;035m' 11 | blue=$'\e[38;5;038m' 12 | red=$'\e[38;5;203m' 13 | black=$'\e[38;5;016m' 14 | greenbg=$'\e[48;5;035m'${black} 15 | dim=$'\e[2m' 16 | default=$'\e[0m' 17 | 18 | clear 19 | sudo mkdir -p /etc/asn 20 | echo -e "${dim}$banner${default}\n" 21 | echo -en "Enter your IPQualityScore API token (or press Enter to skip): " 22 | read -sr IQS_TOKEN 23 | echo -en "\nEnter your ipinfo.io API token (or press Enter to skip): " 24 | read -sr IPINFO_TOKEN 25 | echo -en "\nEnter your Cloudflare API token (or press Enter to skip): " 26 | read -sr CLOUDFLARE_TOKEN 27 | 28 | if [ -n "$IQS_TOKEN" ]; then 29 | echo -en "\n\n- Enabling IPQualityScore API..." 30 | echo "$IQS_TOKEN" | sudo tee /etc/asn/iqs_token &>/dev/null 31 | echo "${green}OK${default}" 32 | else 33 | echo -e "\n\n- IPQualityScore API ${red}DISABLED${default}" 34 | fi 35 | if [ -n "$IPINFO_TOKEN" ]; then 36 | echo -en "- Enabling ipinfo.io API..." 37 | echo "$IPINFO_TOKEN" | sudo tee /etc/asn/ipinfo_token &>/dev/null 38 | echo "${green}OK${default}" 39 | else 40 | echo -e "- ipinfo.io API ${red}DISABLED${default}" 41 | fi 42 | if [ -n "$CLOUDFLARE_TOKEN" ]; then 43 | echo -en "- Enabling Cloudflare API..." 44 | echo "$CLOUDFLARE_TOKEN" | sudo tee /etc/asn/cloudflare_token &>/dev/null 45 | echo "${green}OK${default}" 46 | else 47 | echo -e "- Cloudflare API ${red}DISABLED${default}" 48 | fi 49 | 50 | echo -en "- Installing prerequisite packages..." 51 | sudo apt update &>/dev/null 52 | sudo apt -y install curl whois bind9-host mtr-tiny jq ipcalc grepcidr nmap ncat aha &>/dev/null 53 | echo -e "${green}OK${default}" 54 | echo -en "- Installing the asn script..." 55 | sudo install -m 755 asn /usr/bin 56 | echo -e "${green}OK${default}" 57 | echo -e "\n${greenbg} All done ${default}\n" 58 | echo -e "Example usage:\n\tServer mode : ${blue}asn -l${default}\n\tASPath trace: ${blue}asn 1.1.1.1${default}\n\nFor a full feature list visit ${blue}https://github.com/nitefood/asn${default}\n\n" 59 | --------------------------------------------------------------------------------