#!/bin/bash # # Author: Georg Voell - georg.voell@standby.cloud # Version: @(#)get-ip 3.2.0 05.09.2024 (c)2024 Standby.cloud # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ # # This script can be used free of charge. Use it as is or customize as needed. It is not guaranteed to be # error free and you will not be reimbursed for any damage it may cause. # #@ Get the external ip of the instance and some more infos. It calls an external site via 'curl' to #@ get besides the external ip e.g. the ASN number back. If the instance uses an NAT geateway instead #@ of an Internet gateway, toe tool returns the public IP of the NAT gateway. #@ If there is no internet connection, the result would be empty. #@ #@Usage: get-ip [options] [key] #@ Options: #@ -h, --help : Displays helptext. #@ -v, --version : Displays the version of the script. #@ -o, --output : Output format: can be "plain" (default), "keys", "json", "tsv", "line" or "table". #@ Key: This script can be called with an optional parameter "key" (otherwise it prints out all keys) e.g: #@ ip : Displays the IP e.g. "87.162.84.113". #@ country: Displays the Country e.g. "Germany". #@ city : Displays the City e.g. "Berlin". #@ asn : Displays the ASN ID e.g. "AS3320" for "Deutsche Telekom AG" or "AS31898" for "ORACLE-BMC / OCI" #@ #@Examples: #@ get-ip ip #@ Displays the External IP of the instance (returns empty string if there is no internet connection). #@ get-ip --output json #@ Displays all results in json format. #@ get-ip --output keys #@ Displays all results in key-pair-value format. # # Exit codes: # 01: Unknown or wrong parameter. # 02: **curl** not found. This script needs **curl** to perform. # 03: Key not found # 04: No internet access. This script calls an external tool to get ip infos. # 99: User interrupt. # # See also: # **check-port**(1), **get-platform**(1), **install-scripts**(1) # # ToDo: # # Known bugs: # # Update history: # # V 3.0.0 24.04.2020 New version # V 3.0.1 11.06.2020 Using library # V 3.0.2 21.05.2023 Using HTTPS instead of HTTP # V 3.1.0 05.06.2023 New copyright # V 3.1.1 31.08.2023 Also get ipv4, ipv6 and local ip # V 3.1.2 09.09.2023 Additional asn # V 3.2.0 05.09.2024 New minor version # # Find executable bash library and source it lib=`which lib.bash 2>/dev/null | sed 's|^no 'lib.bash' in .*||'` if [ "$lib" != "" ]; then source "$lib" else progdir=`dirname "$0"` if [ -r "${progdir}/lib.bash" ]; then source "${progdir}/lib.bash" else echo "Unexpected error: Unable to locate bash library 'lib.bash'." exit 1 fi fi # Do extra cleanup function ExtraCleanup() { filecheck -rm ${scratchfile}.pre } # Set the Base URLs readonly url="https://ifconfig.co" readonly baseurl="https://standby.cloud" readonly asnurl="${baseurl}/cgi-bin/get-asn.pl?param" readonly ipurl="${baseurl}/cgi-bin/ip.pl" # ASN lookup info: https://securitytrails.com/blog/asn-lookup # Get ASN: https://stat.ripe.net/data/as-overview/data.json?resource=AS3320 # Preset param="" formatstr="" # Check parameters: Loop until all parameters are used up while [ $# -gt 0 ]; do pname=${1} case "$pname" in -o | --output) shift if [ "$1" != "" ]; then if [ "$formatstr" = "" ]; then formatstr=`echo "$1" | tolower` if [ "$formatstr" != "plain" -a "$formatstr" != "keys" -a "$formatstr" != "json" -a "$formatstr" != "tsv" -a "$formatstr" != "line" \ -a "$formatstr" != "table" ]; then errstr="Unknown format '$formatstr' after parameter '$pname'. Please choose from 'plain', 'keys', 'json', 'tsv', 'line' or 'table'." fi else errstr="Option '$pname' used more then once." fi shift else errstr="Please specify a format ('plain', 'keys', 'json', 'tsv', 'line' or 'table') after parameter '$pname'." fi ;; -v | --version) shift showversion=true ;; -h | --help) shift showhelp=true ;; *) shift paramck=`echo "$pname" | grep '^-'` # Types don't begin with '-' if [ "$paramck" != "" ]; then errstr="Unknown option '$pname'." else if [ "$param" = "" ]; then param=`echo "$pname" | tolower` # We don't use uppercase letters here # param=`ConvertKeys "$param"` else errstr="Keys were already specified '$param'. Unknown additional parameter: '$pname'." fi fi esac done # Check if we can reformat the output pt=`filecheck -x print-table` #if [ "$pt" = "" ]; then # errstr="Script 'print-table' not found." #fi # Display help or error message DisplayHelp # Set output to table if not specified if [ "$formatstr" = "" ]; then formatstr="plain" fi # Check if he have curl and jq in path curl=`filecheck -x curl` # jq=`check-version jq --min 1.5 | cut -d' ' -f3` # We don't need jq if [ "$curl" = "" ]; then exitcode=2 errormsg $exitcode "($progstr) No 'curl' in '$PATH'. Please install first e.g. 'sudo yum -y install curl'." exit $exitcode else # Application Error = 3: Redo until we do not get an Application Error stat=3 while [ $stat -eq 3 ]; do if [ "$param" = "ip" -o "$param" = "ip_v4" -o "$param" = "country" -o "$param" = "city" ]; then echo "$param" > $scratchfile # Don't use JSON if we have the above parameter if [ "$param" = "ip_v4" ]; then myurl="$ipurl" else myurl="${url}/$param" fi else myurl="${url}/json" fi # Get result from server via curl transfer --quiet --seconds 15 "$myurl" >> $scratchfile stat=$? if [ $stat -eq 0 ]; then if [ "$myurl" = "${url}/json" ]; then # Get ip from scratch and check if it is an ipv6 myip=`cat $scratchfile | grep '"ip": ' | cut -d'"' -f4` result=`echo "$myip" | grep ':'` # Get additional ipv4 if ip was ipv6 if [ "$result" = "" ]; then ipv4="$myip" ipv6="//" # Don't display ipv6 else ipv6="$myip" ipv4=`curl -4skL --connect-timeout 15 $url` stat=$? if [ $stat -ne 0 ]; then ipv4="" fi fi # Get first parameters ipdec=`grep ' "ip_decimal": ' $scratchfile | cut -d':' -f2 | sed 's|^ ||g' | sed 's|,$||g'` country=`grep ' "country": ' $scratchfile | cut -d'"' -f4` countryiso=`grep ' "country_iso": ' $scratchfile | cut -d'"' -f4` countryeu=`grep ' "country_eu": ' $scratchfile | cut -d':' -f2 | sed 's|^ ||g' | sed 's|,$||g'` regionname=`grep ' "region_name": ' $scratchfile | cut -d'"' -f4` regioncode=`grep ' "region_code": ' $scratchfile | cut -d'"' -f4` zipcode=`grep ' "zip_code": ' $scratchfile | cut -d'"' -f4` city=`grep ' "city": ' $scratchfile | cut -d'"' -f4` latitude=`grep ' "latitude": ' $scratchfile | cut -d':' -f2 | sed 's|^ ||g' | sed 's|,$||g'` longitude=`grep ' "longitude": ' $scratchfile | cut -d':' -f2 | sed 's|^ ||g' | sed 's|,$||g'` timezone=`grep ' "time_zone": ' $scratchfile | cut -d'"' -f4` # Determine asn and asn_org asn=`grep ' "asn": ' $scratchfile | cut -d'"' -f4` asnorg=`grep ' "asn_org": ' $scratchfile | cut -d'"' -f4` if [ "$asn" = "" -o "$asnorg" = "" ]; then # No asn in response from ipfonfig.co - try to get it elsewhere if [ "$ipv4" != "" ]; then check="$ipv4" else check="$myip" fi if [ "$check" != "" ]; then transfer --quiet --seconds 15 "${asnurl}=$check" > ${scratchfile}.pre stat=$? if [ $stat -eq 0 ]; then result=`cat ${scratchfile}.pre | grep '\[AS' | taillastline | cut -d'[' -f2` asnorg=`echo "$result" | cut -d']' -f2 | cut -d',' -f1` asnorg="${asnorg/ /}" # Check if asn was already defined if [ "$asn" = "" ]; then asn=`echo "$result" | cut -d']' -f1` fi fi fi fi # Get lst parameters product=`grep ' "product": ' $scratchfile | cut -d'"' -f4` pvers=`grep ' "version": ' $scratchfile | cut -d'"' -f4` rawvalue=`grep ' "raw_value": ' $scratchfile | cut -d'"' -f4` hname=`grep ' "hostname": ' $scratchfile | cut -d'"' -f4` if [ "$hname" = "" ]; then hname="//" # Don't display hostname fi # Create tsv file printf "ip\tip_v4\tip_v6\tip_decimal\tcountry\tcountry_iso\tcountry_eu\tregion_name\tregion_code\tzip_code\tcity\tlatitude\tlongitude\ttime_zone\tasn\tasn_org\thostname\tuser_agent/product\tuser_agent/version\tuser_agent/raw_value\n" > $scratchfile printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" \ "$myip" "$ipv4" "$ipv6" "/${ipdec}/" "$country" "$countryiso" "/${countryeu}/" "$regionname" "$regioncode" "$zipcode" "$city" "/${latitude}/" \ "/${longitude}/" "$timezone" "$asn" "$asnorg" "$hname" "$product" "$pvers" "$rawvalue" >> $scratchfile fi # Display the result if [ "$param" = "" ]; then if [ "$pt" = "" ]; then # No print-table found - just display the tsv file cat $scratchfile else cat $scratchfile | $pt --quiet --output "$formatstr" > ${scratchfile}.pre fi else if [ "$myurl" = "${url}/json" ]; then cat $scratchfile | $pt --quiet --output "$formatstr" "$param" > ${scratchfile}.pre stat=$? if [ $stat -ne 0 ]; then # Parameter not found exitcode=3 errormsg $exitcode "($progstr) None of the specified keys were found. Exiting." Cleanup exit $exitcode fi else # Display the value (only one was specified) if [ "$formatstr" = "plain" ]; then tail -n 1 $scratchfile Cleanup exit else cat $scratchfile | $pt --quiet --output "$formatstr" > ${scratchfile}.pre fi fi fi if [ "$ENVELOPE_TABLE" = false -o "$formatstr" != "json" ]; then cat ${scratchfile}.pre else cat ${scratchfile}.pre | sed 's|\("contentItems":.*\)|\1,\n "creator": "'$progstr'"|' fi else if [ $stat -ne 3 ]; then # No internet access? exitcode=4 Cleanup exit $exitcode fi fi done fi # Cleanup and exit Cleanup exit $exitcode