123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984 |
- #!/usr/bin/env bash
- #######################################################################
- # IPFire network object creator for IPv4 addresses based on ASN information
- # Creates 'customnetworks' objects in /var/ipfire/fwhosts/customnetworks
- # Creates 'customgroups' objects in /var/ipfire/fwhosts/customgroups
- #######################################################################
- #######################################################################
- revision="asn_ipfire.sh v0.7.13" # do not comment out
- # Last updated: May 13 2022 by maloe
- # Author: Mike Kuketz, maloe
- # Visit: www.kuketz-blog.de
- # Source: notabug.org/maloe/ASN_IPFire_Script
- # License: GNU GPL v3
- # Copyright 2017-2022 Mike Kuketz, maloe
- #######################################################################
- #######################################################################
- # Constants, Filenames, Enable/Disable Sources
- # Config file (if exists, it overwrites the default values specified in this header)
- configfile=asn_script.conf
- # Use download tool wget or curl
- downloadtool=wget # default
- #downloadtool=curl # alterantive (if existent)
- timeout=30 # timeout in seconds for availability check (-c|--check)
- # Path to IPFire customnetworks|customgroups
- customnetworks=/var/ipfire/fwhosts/customnetworks
- customgroups=/var/ipfire/fwhosts/customgroups
- # Remark for IPFire customnetworks|customgroups. This is used to identify entries made by asn_ipfire.sh.
- auto_remark="entry by asn_ipfire.sh"
- # Define iptables path for iptable/afwall output file
- iptables_path="/sbin/iptables"
- afwall_path="/system/bin/iptables"
- # Define custom output format
- outputline="%network%" # special variables: %network%, %company%
- # Output file
- output_file="asn_result.lst" # default output file
- # Deprecated output files, only used if output_file is empty
- file_network="network_list.txt" # deprecated output file for network consolidated
- file_asn="asn_list.txt" # deprecated output file for ASNs only
- file_iptable="iptable_rules.txt" # deprecated output file in iptable format
- file_afwall="afwall_rules.txt" # deprecated output file in afwall format
- temppath="." # path to store temporary source file (default is the script folder ".")
- temp1="asn_cidrreport.tmp" # Define temp file
- temp2="asn_bglooking.tmp" # Define temp file
- # Local files can be used as ASN and/or network sources. To be activated by enabling "gather_ASN0" and/or "gather_NET0" into following arrays.
- local_asn_file="local_asn.list" # Line format: 'ASN Company' or vice versa (e.g. 'AS1234 CompanyA' or 'CompanyA AS1234')
- local_net_file="local_net.list" # Line format: 'network ASN' or vice versa (e.g. '1.2.3.4/24 AS5678' or 'AS5678 1.2.3.4/24')
- # Enable/disable ASN sources: Remove leading hashes (#) to enable ASN_sources.
- getASNfromCOMPANY=( \
- ASN_local \ # local source (local_asn_file)
- ASN_cidrreport \ # cidr-report.org
- # ASN_bgplookingglass \ # bgplookingglass.com
- # ASN_bgpview \ # bgpview.io (white spaces in company names not supported)
- ##ASN_bgphenet \ # bgp.he.net (not supported due to js requirement)
- )
- # Enable/disable network sources: Remove leading hash (#) to enable NET_sources.
- getNETfromASN=( \
- NET_local \ # local source (local_net_file)
- NET_ripe \ # stat.ripe.net
- # NET_ipinfo \ # ipinfo.io
- # NET_bgpview \ # bgpview.io
- # NET_radb \ # whois.radb.net # use only if you know what you are doing. query results may be wrong!
- )
- #######################################################################
- # Include configuration file
- thisfolder=$(dirname $(readlink -f $0))
- if [[ -f ${thisfolder}/${configfile} ]]; then
- . ${thisfolder}/${configfile}
- fi
- #######################################################################
- # Gather-Functions: add further sources here and activate them in above arrays getASNfromCOMPANY() and getNETfromASN()
- # ASN sources: function must return a list of ASNs
- ASN_local() # Get ASN from local file
- {
- if [[ -f $local_asn_file ]]; then
- echo "---[Using local ASN Source file ($local_asn_file)]---"
- cname=`echo $1 | sed 's/~/ /g; s/*/.*/g'` # Replace ~ with space
- asn_array=`cat $local_asn_file | grep -i "$cname" | grep -Eo 'AS[0-9]+'`
- fi;
- }
- ASN_cidrreport() # Get ASN from cidr-report.org
- {
- if [[ $dl != "local" ]]; then # wget or curl available?
- if [[ ! -f $temp1 ]] && [[ ${#company_array[@]} -gt 1 || $keeptemp ]]; then # Temp file not exist and more than one company names or option keeptemp is enabled
- touch $temp1 2> /dev/null # Temp file writable?
- if [[ -w $temp1 ]]; then # Write temp file
- echo "---[Downloading ASN Source List from www.cidr-report.org]---"
- $dl "https://www.cidr-report.org/as2.0/autnums.html" | grep -Eo '>AS[0-9]+.*' | sed 's/^>//; s/[ ]*<\/a>[ ]*/ /' >> $temp1
- fi
- fi
- cname=`echo $1 | sed 's/~/ /g; s/*/.*/g'` # Replace ~ with space and * with expression .*
- if [[ -f $temp1 ]]; then # Read from temp file
- if [[ $verbose ]]; then echo "---[Using local (temporary) ASN Source List ($temp1)]---"; fi
- asn_array=`cat $temp1 | grep -i "$cname" | grep -Eo '^AS[0-9]+'`
- else # Read from source
- echo "---[Downloading ASN Source List from www.cidr-report.org]---"
- asn_array=`$dl "https://www.cidr-report.org/as2.0/autnums.html" | grep -i "$cname" | grep -Eo '>AS[0-9]+' | grep -Eo 'AS[0-9]+'`
- fi;
- fi
- }
- ASN_bgplookingglass() # Get ASN from bgplookingglass.com
- {
- if [[ $dl != "local" ]]; then # wget or curl available?
- if [[ ! -f $temp2 ]] && [[ ${#company_array[@]} -gt 1 || $keeptemp ]]; then # Temp file not exist and more than one company names or option keeptemp is enabled
- touch $temp2 2> /dev/null # Check if writable?
- if [[ -w $temp2 ]]; then
- echo "---[Downloading ASN Source List from www.bgplookingglass.com]---"
- $dl "http://www.bgplookingglass.com/list-of-autonomous-system-numbers" | sed -n '/AS[0-9]/ p' | sed 's/<br \/>/\'$'\n/g; s/^[[:space:]]*<pre>//; s/[ ]\+/ /g' >> $temp2
- $dl "http://www.bgplookingglass.com/list-of-autonomous-system-numbers-2" | sed -n '/AS[0-9]/ p' | sed 's/<br \/>/\'$'\n/g; s/^[[:space:]]*<pre>//; s/[ ]\+/ /g' >> $temp2
- $dl "http://www.bgplookingglass.com/4-byte-asn-names-list" | sed -n '/AS[0-9]/ p' | sed 's/<br \/>/\'$'\n/g; s/^[[:space:]]*<pre>//; s/[ ]\+/ /g' >> $temp2
- fi
- fi
- cname=`echo $1 | sed 's/~/ /g; s/*/.*/g'` # Replace ~ with space and * with expression .*
- if [[ -f $temp2 ]]; then # Read from temp file
- if [[ $verbose ]]; then echo "---[Using local (temporary) ASN Source List ($temp2)]---"; fi
- asn_array=`cat $temp2 | grep -i "$cname" | grep -Eo '^AS[0-9]+'`
- else # Temp file not writable
- echo "---[Downloading ASN Source List from www.bgplookingglass.com]---"
- asn_array=(`$dl "http://www.bgplookingglass.com/list-of-autonomous-system-numbers" | sed -n '/AS[0-9]/ p' | sed 's/<br \/>/\'$'\n/g' | grep -i "$cname" | sed 's/^[[:space:]]*<pre>//' | grep -Eo '^AS[0-9]+'`)
- asn_array=(${asn_array[@]} `$dl "http://www.bgplookingglass.com/list-of-autonomous-system-numbers-2" | sed -n '/AS[0-9]/ p' | sed 's/<br \/>/\'$'\n/g' | grep -i "$cname" | sed 's/^[[:space:]]*<pre>//' | grep -Eo '^AS[0-9]+'`)
- asn_array=(${asn_array[@]} `$dl "http://www.bgplookingglass.com/4-byte-asn-names-list" | sed -n '/AS[0-9]/ p' | sed 's/<br \/>/\'$'\n/g' | grep -i "$cname" | sed 's/^[[:space:]]*<pre>//' | grep -Eo '^AS[0-9]+'`)
- fi
- fi
- }
- ASN_bgpview() # Get ASN from bgpview.io
- {
- if [[ $dl != "local" ]]; then # wget or curl available?
- cname=`echo $1 | sed 's/~/ /g; s/+/%2B/g'` # Replace ~ with space and "+" with %2B
- asn_array=(`$dl "https://bgpview.io/search/$cname" | grep -Eo 'AS[0-9]+' | uniq`)
- fi
- }
- ASN_bgphenet() # Get ASN from bgp.he.net
- {
- if [[ $dl != "local" ]]; then # wget or curl available?
- cname=`echo $1 | sed 's/~/ /g; s/+/%2B/g'` # Replace ~ with space and "+" with %2B
- asn_array=(`$dl "https://bgp.he.net/search?search%5Bsearch%5D=$cname&commit=Search" | grep -Eo 'AS[0-9]+' | uniq`)
- fi
- }
- # Network sources: function must return a list of CIDR networks
- NET_local() # Get networks from local file, sorting
- {
- if [[ -f $local_net_file ]]; then
- cat $local_net_file | grep -i "$1" | grep -Eo '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/)(3[0-2]|[1-2][0-9]|0?[1-2]?[1-9])' | sed -E 's/^[0]{0,2}([0-9])/\1/g; s/\.[0]{0,2}([0-9])/.\1/g; s/\/[0]?/\//g' | sort -Vu
- fi
- }
- NET_ripe() # Get networks from stat.ripe.net, sorting
- {
- if [[ $dl != "local" ]]; then # wget or curl available?
- $dl "https://stat.ripe.net/data/announced-prefixes/data.json?resource=$1" | grep -Eo '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/)(3[0-2]|[1-2][0-9]|0?[1-2]?[1-9])' | sed -E 's/^[0]{0,2}([0-9])/\1/g; s/\.[0]{0,2}([0-9])/.\1/g; s/\/[0]?/\//g' | sort -Vu
- fi
- }
- NET_ipinfo() # Get networks from ipinfo.io, sorting
- {
- if [[ $dl != "local" ]]; then # wget or curl available?
- $dl "https://ipinfo.io/$1" | grep -Eo '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/)(3[0-2]|[1-2][0-9]|0?[1-2]?[1-9])' | sed -E 's/^[0]{0,2}([0-9])/\1/g; s/\.[0]{0,2}([0-9])/.\1/g; s/\/[0]?/\//g' | sort -Vu
- fi
- }
- NET_bgpview() # Get networks from bgpview.io, sorting
- {
- if [[ $dl != "local" ]]; then # wget or curl available?
- $dl "https://bgpview.io/asn/$1#prefixes-v4" | grep -Eo '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/)(3[0-2]|[1-2][0-9]|0?[1-2]?[1-9])' | sed -E 's/^[0]{0,2}([0-9])/\1/g; s/\.[0]{0,2}([0-9])/.\1/g; s/\/[0]?/\//g' | sort -Vu
- fi
- }
- NET_radb() # Get networks from whois, sorting
- {
- if [[ -x `which whois 2>/dev/null` ]]; then # whois available?
- whois -h whois.radb.net -i origin $1 | grep -w "route:" | grep -Eo '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/)(3[0-2]|[1-2][0-9]|0?[1-2]?[1-9])' | sed -E 's/^[0]{0,2}([0-9])/\1/g; s/\.[0]{0,2}([0-9])/.\1/g; s/\/[0]?/\//g' | sort -Vu
- fi
- }
- #######################################################################
- # NO NEED TO EDIT ANYTHING BELOW
- #######################################################################
- # Functions
- # Function: check for ipfire system and existence of wget or curl
- chkSystem()
- {
- if [[ -d /var/ipfire ]] && [[ -f /etc/init.d/firewall ]]; then # Running on ipfire system?
- is_ipfire=1
- else
- is_ipfire=""
- fi
-
- dl=local
- if [[ -x `which wget 2>/dev/null` ]]; then
- dl="wget --quiet --max-redirect 1 -O -" # Use wget if existent
- fi
- if [[ -x `which curl 2>/dev/null` ]]; then
- if [[ $dl == "local" ]] || [[ "$downloadtool" == "curl" ]]; then
- dl="curl --silent" # Use curl if existent and wget is missing
- dl="curl --silent --location" # Use curl if existent and wget is missing
- fi
- fi
- if [[ $dl == "local" ]]; then
- echo "Warning: did not found wget nor curl. Only local sources usable." # Neither wget nor curl was found
- fi
- }
- # Function: check source reachability
- chkSource() {
- if [[ $dl == "wget --quiet --max-redirect 0 -O -" ]]; then # Wget
- for s in ${getASNfromCOMPANY[@]}; do # Loop through ASN sources
- echo -n "---[Checking source $s]---"
- case $s in
- ASN_local) if [ -f "$local_asn_file" ]; then echo -n " (OK)"; else echo -n " (n/a)"; fi ;;
- ASN_cidrreport) wget --spider --quiet --connect-timeout=$timeout --tries=1 --max-redirect 0 "https://www.cidr-report.org/as2.0/autnums.html" ;;
- ASN_bgplookingglass) wget --spider --quiet --connect-timeout=$timeout --tries=1 --max-redirect 1 "http://www.bgplookingglass.com/list-of-autonomous-system-numbers" ;; # Check first site only
- ASN_bgpview) wget --spider --quiet --connect-timeout=$timeout --tries=1 --max-redirect 0 "https://bgpview.io/search/as1" ;;
- ASN_bgphenet) wget --spider --quiet --connect-timeout=$timeout --tries=1 --max-redirect 0 "https://bgp.he.net/as1" ;;
- esac
- if [ $? -ne 0 ]; then echo -e "\nAbort: couldn't reach (wget) selected source $s"; exit 4; fi
- echo
- done
- for s in ${getNETfromASN[@]}; do # Loop through ASN sources
- echo -n "---[Checking source $s]---"
- case $s in
- NET_local) if [ -f "$local_net_file" ]; then echo -n " (OK)"; else echo -n " (n/a)"; fi ;;
- NET_ripe) wget --spider --quiet --connect-timeout=$timeout --tries=1 --max-redirect 0 "https://stat.ripe.net/data/announced-prefixes/data.json?preferred_version=1.1&resource=0" ;;
- NET_ipinfo) wget --spider --quiet --connect-timeout=$timeout --tries=1 --max-redirect 0 "https://ipinfo.io/as1" ;;
- NET_bgpview) wget --spider --quiet --connect-timeout=$timeout --tries=1 --max-redirect 0 "https://bgpview.io/search/" ;;
- esac
- if [ $? -ne 0 ]; then echo -e "\nAbort: couldn't reach (curl) selected source $s"; exit 4; fi
- echo
- done
- elif [[ $dl == "curl --silent" ]]; then # Curl
- for s in ${getASNfromCOMPANY[@]}; do # Loop through ASN sources
- echo -n "---[Checking source $s]---"
- case $s in
- ASN_local) if [ -f "$local_asn_file" ]; then echo -n " (OK)"; else echo -n " (n/a)"; fi ;;
- ASN_cidrreport) curl --silent --head --connect-timeout $timeout "https://www.cidr-report.org/as2.0/autnums.html" | head -1 | grep '200' >/dev/null ;;
- ASN_bgplookingglass) curl --silent --head --connect-timeout $timeout --location "http://www.bgplookingglass.com/list-of-autonomous-system-numbers" | grep -E 'HTTP.*200' >/dev/null ;; # Check first site only
- ASN_bgpview) curl --silent --head --connect-timeout $timeout "https://bgpview.io/search/as1" | head -1 | grep '200' >/dev/null ;;
- ASN_bgphenet) curl --silent --head --connect-timeout $timeout "https://bgp.he.net/as1" | head -1 | grep '200' >/dev/null ;;
- esac
- if [ $? -ne 0 ]; then echo -e "\nAbort: couldn't reach selected source $s"; exit 4; fi
- echo
- done
- for s in ${getNETfromASN[@]}; do # Loop through ASN sources
- echo -n "---[Checking source $s]---"
- case $s in
- NET_local) if [ -f "$local_net_file" ]; then echo -n " (OK)"; else echo -n " (n/a)"; fi ;;
- NET_ripe) curl --silent --head --connect-timeout $timeout "https://stat.ripe.net/data/announced-prefixes/data.json?resource=0" | head -1 | grep '200' >/dev/null ;;
- NET_ipinfo) curl --silent --head --connect-timeout $timeout "https://ipinfo.io/as1" | head -1 | grep '200' >/dev/null ;;
- esac
- if [ $? -ne 0 ]; then echo -e "\nAbort: couldn't reach selected source $s"; exit 4; fi
- echo
- done
- fi
- }
- # Function: get network mask
- cdr2mask()
- {
- # Number of args to shift, 255..255, first non-255 byte, zeroes
- set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0
- [ $1 -gt 1 ] && shift $1 || shift
- echo ${1-0}.${2-0}.${3-0}.${4-0}
- }
- # Functions: get decimal IP values
- get_firstIP() { echo ${1/\//.} | awk -F"." '{ printf "%.0f", $1*2^24+$2*2^16+$3*2^8+$4 }'; } # First IP of network
- get_IPrange() { echo $1 | awk -F"/" '{ printf "%.0f", 2^(32-$2)}'; } # IP range of network
- get_lastIP() { echo ${1/\//.} | awk -F"." '{ printf "%.0f", $1*2^24+$2*2^16+$3*2^8+$4+2^(32-$5)}'; } # Last IP +1 of network
- # Function: transform decimal IP into dot noted IP
- dec2ip() { echo $1 | awk '{ printf "%i.%i.%i.%i", $1/(2^24), $1%(2^24)/(2^16), $1%(2^24)%(2^16)/(2^8), $1%(2^24)%(2^16)%(2^8)}'; }
- # Function: remove redundant networks
- rm_redundantIP() {
- declare -a array1=("${!1}") # Put $1 into new array
- declare -a array2=() # Create second array
- declare maxIP=0 # Initial IP for comparison
- declare n=0 # Counter for array
- for net in ${array1[@]}; do
- lastIP=`get_lastIP $net` # Get last IP(+1) of actual network
- if [[ `echo $lastIP $maxIP | awk '$1>$2 {printf 1}'` ]]; then # Comparing big integer. Only keep network if last IP is not covered by previous network
- array2[$n]=$net # Write actual network into second array
- maxIP=$lastIP # Update maximum IP(+1)
- ((n++))
- fi
- done
- for net in ${array2[@]}; do # Return result
- if [ $net ]; then echo ${net}; fi # Skip empty lines
- done
- }
- # Function: consolidate adjacent networks
- rm_adjacentIP() {
- declare -a array1=("${!1}") # Put $1 into new array1
- declare -a array2=() # Create working array2
- declare n=0 # Counter for array2
- declare d=0 # Initial counter for adjacents
- declare range=0 # IP range
- declare prefirstIP=0 # Get decimal first IP from actual network
- declare prenetmask=0 # Get decimal IP range from actual network
- declare prelastIP=-1 # Get decimal last IP(+1) from actual network
- for net in ${array1[@]}; do # Loop through network list
- firstIP=`get_firstIP $net` # Get decimal first IP from actual network
- netmask=`get_IPrange $net` # Get decimal IP range from actual network
- lastIP=`get_lastIP $net` # Get decimal last IP(+1) from actual network
- range=`echo $prenetmask $netmask | awk '{printf "%d", $1+$2;}'`
- # If all adjecent consolidation requirements are given
- if [[ `echo $firstIP $prelastIP $range $prefirstIP | awk '($1==$2) && (log($3)/log(2)==int(log($3)/log(2))) && ($4%$3==0) {printf 1}'` ]]; then
- suffix=`echo $range | awk '{printf "%i", 32-log($1)/log(2);}'`
- array2[(n-1)]=`dec2ip $prefirstIP`"/"$suffix
- prelastIP=$lastIP
- prenetmask=$range
- d=1
- else # No changes
- array2[$n]=$net
- prelastIP=$lastIP
- prefirstIP=$firstIP
- prenetmask=$netmask
- ((n++))
- fi
- done
- if [[ d -eq 1 ]]; then # If changes done, then...
- d=0
- rm_adjacentIP array2[@] # ... next Iteration
- else
- for net in ${array2[@]} ; do # Return result
- if [ $net ]; then echo ${net}; fi # Skip empty lines
- done
- fi
- }
- # Function: print statistics
- show_stats() { # Requires arguments: asn_array net_array, company
- declare -a asn_array=("${!1}") # Put $1 (asn_list) into new array
- declare -a net_array=("${!2}") # Put $2 (net_list) into new array
- declare countIP=0 # Counter for IP
- for net in ${net_array[@]}; do
- netmask=`get_IPrange $net` # Get decimal IP range from actual network
- countIP=`echo $countIP $netmask | awk '{printf "%.0f", $1+$2}'` # Count IP
- done
- countIP=`printf "%'i\n" $countIP` # Point separated format
- echo "${#net_array[@]} networks with $countIP IPs found in ${#asn_array[@]} ASNs for $3"
- }
- #######################################################################
- # Main procedures
- collectNetworks() {
- for company in ${company_array[@]}; do
- # Get all company ASNs
- declare asn_array=()
- declare asn_list=()
- prnt_company=`echo $company | sed 's/~/ /g; s/,//g'` # Printable company name with space (and no commas)
- echo "---[Get all '$prnt_company' ASNs]---"
- for asn_gather in ${getASNfromCOMPANY[@]}; do # Loop through ASN sources
- $asn_gather $company
- asn_list=(`echo ${asn_list[@]} ${asn_array[@]}`) # Append to list
- done
- output=`echo "### Company: ${prnt_company} ###" | sed 's/ /_/g'`" "
- if [ ! $asn_list ]; then
- echo "---[No ASN found for $prnt_company]---"
- elif [ "$1" == "--asn" ]; then
- for asn in ${asn_list[@]}; do
- output+="$asn " # Create output text
- done
- result_array=(`echo ${result_array[@]} ${output}`)
- else
- asn_list=(`echo ${asn_list[@]} | sed 's/ /\'$'\n/g' | sort -Vu`) # Linebreaking and Sorting # Adjusted for FreeBSD
- declare net_array=()
- declare net_list=()
- for asn in ${asn_list[@]}; do
- # Store networks from ASN in file
- echo "---[Get $prnt_company networks for $asn]---"
- for net_gather in ${getNETfromASN[@]}; do # Loop through NET webservices
- net_array=(`$net_gather $asn`)
- net_list=(`echo ${net_list[@]} ${net_array[@]} | sed 's/ /\'$'\n/g' | sort -Vu`) # Append to list, sorting # Adjusted for FreeBSD
- done
- done
- if [ ! $net_list ]; then
- echo "---[No networks found for $prnt_company]---"
- else
- # Consolidate adjacent and overlapping netblocks
- before=${#net_list[@]} # Number of network entries before consolidate
- tbefore="`date +%s`"
- if [[ $verbose ]]; then echo " $(show_stats asn_list[@] net_list[@] $company)"; fi
- if [ ! $raw ]; then
- echo "---[Remove adjacent and overlapping netblocks]---"
- net_list=(`rm_redundantIP net_list[@]`) # Remove redundant networks
- net_list=(`rm_adjacentIP net_list[@]`) # Consolidate adjacent networks
- fi
- after=${#net_list[@]} # Number of network entries after consolidate
- tafter="`date +%s`"
- if [[ $verbose ]]; then echo " $((before - after)) of $before networks removed in $((tafter - tbefore))s"; fi
- # Write objects to result array
- echo "---[Creating objects for $prnt_company networks]---"
- if [[ $verbose ]] && [[ "$1" == "--network" ]]; then
- output+=`echo "### $(show_stats asn_list[@] net_list[@] $company) ###" | sed 's/ /_/g'`" "
- fi
- for net in ${net_list[@]}; do
- output+="$net " # Create output text
- done
- result_array=(`echo ${result_array[@]} ${output}`)
- if [[ $verbose ]]; then echo " $(show_stats asn_list[@] net_list[@] $company)"; fi
- fi
- fi
- done
-
- # remove temp files
- if [[ ! $keeptemp ]]; then
- echo "---[Removing temporary source files]---"
- if [[ -f $temp1 ]]; then rm $temp1; fi
- if [[ -f $temp2 ]]; then rm $temp2; fi
- fi
- }
- addNetworks() { # Write result to ipfire files
- # Get highest number from existing objects in [customnetworks|customgroups]
- if [[ -w $customnetworks ]]; then
- network_object_number=$(cat $customnetworks | cut -f1 -d',' | awk '{for(i=1;i<=NF;i++) if($i>maxval) maxval=$i;}; END { print maxval;}')
- else
- echo -e "File $customnetworks not found or write protected.\nCheck your IPFire installation."
- exit 0
- fi
- if [[ -w $customgroups ]]; then
- group_object_number=$(cat $customgroups | cut -f1 -d',' | awk '{for(i=1;i<=NF;i++) if($i>maxval) maxval=$i;}; END { print maxval;}')
- else
- echo -e "File $customgroups not found or write protected.\nCheck your IPFire installation."
- exit 0
- fi
- # Increase counter
- ((network_object_number++))
- ((group_object_number++))
- for net in ${result_array[@]}; do
- if [[ ${net:0:1} == "#" ]]; then
- prnt_company=`echo $net | sed 's/###_Company:_\(.*\)_###/\1/' | sed 's/_/ /g'` # Get company name
- company=$prnt_company
- counter=1
- else
- # Separate IP and netmask
- ip=${net%/*}
- if [ "$ip" != "0.0.0.0" ]; then # Double check for invalid entry
- netmask=${net#*/}
- if [ "$netmask" == "32" ]; then echo "WARNING: Found single IP (${company}: ${ip}). This may cause an invalid entry in ipfire!"; fi # Double check for invalid entry
- # Write new objects to files [customnetworks|customgroups]
- ipf_company=`echo $prnt_company | sed 's/\(.*\)/\U\1/'` # Uppercase company name
- printf "$network_object_number,$company-Network Nr.$counter,$ip,$(cdr2mask $netmask),$auto_remark\n" >> $customnetworks
- printf "$group_object_number,$ipf_company,$auto_remark,$company-Network Nr.$counter,Custom Network\n" >> $customgroups
- # Increase counter
- ((network_object_number++))
- ((group_object_number++))
- ((counter++))
- fi
- fi
- done
- echo "---[Results written to $output_file]---" # Resultfile info
- }
- outResults() {
- case "$1" in # Output result to file
- --asn) {
- for asn in ${result_array[@]} ; do
- echo ${asn} | sed 's/_/ /g' >> "$output_file"
- done
- };;
- --network) {
- for net in ${result_array[@]}; do
- echo ${net} | sed 's/_/ /g' >> "$output_file"
- done
- };;
- --custom) {
- for net in ${result_array[@]}; do
- if [[ ${net:0:1} == "#" ]]; then
- echo "$net" | sed 's/_/ /g' >> "$output_file"
- prnt_company=`echo $net | sed 's/###_Company:_\(.*\)_###/\1/' | sed 's/_/ /g'` # Get company name
- number=1
- else
- echo -e "$outputline" | sed "s@%network%@$net@g" | sed "s@%company%@$prnt_company@g" | sed "s@%number%@$number@g" >> "$output_file"
- ((number++))
- fi
- done
- };;
- --iptable) {
- for net in ${result_array[@]}; do
- if [[ ${net:0:1} == "#" ]]; then
- echo "$net" | sed 's/_/ /g' >> "$output_file"
- else
- echo "$iptables_path -A OUTPUT -d $net -j REJECT" >> "$output_file"
- fi
- done
- };;
- --afwall) {
- for net in ${result_array[@]}; do
- if [[ ${net:0:1} == "#" ]]; then
- echo "$net" | sed 's/_/ /g' >> "$output_file"
- else
- echo "$afwall_path -A \"afwall\" -d $net -j REJECT" >> "$output_file"
- fi
- done
- };;
- *) { # Default ipfire mode
- echo "WARNING: unknown mode. Nothing done."
- };;
- esac
- }
- cleanupNetworks() { # Remove entries from ipfire files
- for ipfire_file in $customnetworks $customgroups; do
- if [[ -w $ipfire_file ]]; then
- if [[ $backup ]]; then
- if [[ $verbose ]]; then echo "---[Backing up $ipfire_file.bak ]---"; fi
- cp -f $ipfire_file $ipfire_file.bak # Create ipfire backup files
- fi
- if [[ ${company_array[0]} == "ALL" ]]; then # Remove all entries made by asn_ipfire.sh
- echo "---[Removing all objects from $ipfire_file ]---"
- sed -i "/,$auto_remark/Id" $ipfire_file;
- else
- for company in ${company_array[@]}; do
- prnt_company=`echo $company | sed 's/~/ /g; s/,//g; s/\(.*\)/\U\1/'` # Company name with space and "+"
- echo "---[Removing $prnt_company objects from $ipfire_file ]---"
- sed -i "/$prnt_company.*$auto_remark/Id" $ipfire_file; # Remove company entries made by asn_ipfire.sh
- done
- fi
- elif [[ -f $ipfire_file ]]; then
- echo -e "File $ipfire_file write protected.\nCheck your IPFire installation."
- fi
- done
- }
- removeBackup() { # Remove ipfire backup files
- for ipfire_file in $customnetworks $customgroups; do
- if [[ -w $ipfire_file.bak ]]; then
- if [[ $verbose ]]; then echo "---[Removing backup $ipfire_file.bak ]---"; fi
- rm -f $ipfire_file.bak
- fi
- done
- }
-
- renumberIpfireFiles() { # Renumber entries of ipfire files
- for ipfire_file in $customnetworks $customgroups; do
- if [[ -w $ipfire_file ]]; then
- if [[ $verbose ]]; then echo "---[Renumbering $ipfire_file ]---"; fi
- sed -i '/^$/d;=' $ipfire_file # Delete empty lines and add numbered lines
- sed -i 'N;s/\n[0-9]\+//' $ipfire_file # Renumber lines by consolidation
- else
- echo -e "File $ipfire_file not found or write protected.\nCheck your IPFire installation."
- fi
- done
- }
- sortIpfireFiles() { # Sort entries of ipfire files
- for ipfire_file in $customnetworks $customgroups; do
- if [[ -w $ipfire_file ]]; then
- if [[ $verbose ]]; then echo "---[Re-sorting $ipfire_file ]---"; fi
- cat $ipfire_file | sort -t, -k2,2V -o $ipfire_file # Sort lines by name
- sed -i '/^$/d;=' $ipfire_file # Delete empty lines and add numbered lines
- sed -i 'N;s/\n[0-9]\+//' $ipfire_file # Renumber lines by consolidation
- else
- echo -e "File $ipfire_file not found or write protected.\nCheck your IPFire installation."
- fi
- done
- }
- restoreIpfireFiles() { # Restore ipfire file
- for ipfire_file in $customnetworks $customgroups; do
- if [[ -w $ipfire_file ]]; then
- if [[ -f "$ipfire_file.bak" ]]; then
- cp -f $ipfire_file.bak $ipfire_file
- echo "File $ipfire_file restored."
- else
- echo "No backup file $ipfire_file.bak found."
- fi
- else
- echo -e "File $ipfire_file not found or write protected.\nCheck your IPFire installation."
- fi
- done
- }
- listIpfireFiles () { # Show companies from ipfire files
- for ipfire_file in $customnetworks $customgroups; do
- if [[ -f $ipfire_file ]]; then
- echo "Company names (number of networks) in "$ipfire_file":"
- grep "$auto_remark" $ipfire_file | cut -d, -f2,4 | cut -d- -f1 | cut -d, -f1 | uniq -c | awk -F" " '{ printf "%s (%i)\n", $2, $1 }'
- else
- echo -e "File $ipfire_file not found.\nCheck your IPFire installation."
- fi
- done
- }
- print_help() { # Help info
- echo "Usage: asn_ipfire.sh [OPTION] [COMPANYs | -f FILE] [PARAMETER]"
- echo "Add or remove networks to IPFire firewall Groups: Networks & Host Groups"
- echo
- echo "IPFire-Mode options:"
- echo " -a, --add Add new company networks"
- echo " -r, --remove Remove company networks from customnetworks & customgroups"
- echo
- echo "IPFire-Mode parameter:"
- echo " -l, --list List of companies already added by this script"
- echo " --renumber Renumber lines of customnetworks & customgroups"
- echo " --sort Re-sort lines of customnetworks & customgroups"
- echo " --backup Backup customnetworks & customgroups before change"
- echo " --rmbackup Remove backup files of customnetworks & customgroups"
- echo " --restore Restore customnetworks & customgroups from backup"
- echo
- echo "Non-IPFire-Mode options:"
- echo " --network Create FILE '$file_network' with networks"
- echo " --asn Create FILE '$file_asn' with ASNs only"
- echo " --custom Create FILE '$output_file' with custom rules"
- echo
- echo "Common parameter:"
- echo " -c, --check Check source for availability"
- echo " -f, --file FILE Get company list from FILE"
- echo " -i, --interactive Ask user before a file will be overwritten"
- echo " -k, --keep Keep temporary source files after finish"
- echo " -o, --outfile FILE Custom result file FILE (Non-IPFire-Mode)"
- echo " --raw Networks not consolidated"
- echo " -v, --verbose Verbose mode"
- echo " -V, --version Show this script version and exit"
- echo " -h, --help Show this help and exit"
- echo
- echo "COMPANY to be one or more company names, put into double quotes (\"...\")"
- echo " Multi company names must be comma separated"
- echo " Substitute spaces with tilde (~)"
- echo " Restrict to exact matches with tilde (~) before and after the name"
- echo " Company names are handled case insensitive."
- echo " example: asn_ipfire.sh --add \"CompanyA,Company~NameB,~CompanyC~\" "
- echo
- echo "FILE to be a name of a file, containing one or more company names."
- echo " Company names to be separated by comma or line feed."
- echo " examples: asn_ipfire.sh -a -f company.list "
- echo " asn_ipfire.sh --network -f company.list "
- echo
- echo "Option --remove only affects entries made by asn_ipfire.sh itself."
- echo " These entries are recognized by the 'Remark'-column in IPFire."
- echo " To remove all entries done by this script, use 'ALL' as COMPANY "
- echo " examples: asn_ipfire.sh -r \"CompanyA, CompanyB\" "
- echo " asn_ipfire.sh -r ALL "
- echo
- }
- #######################################################################
- # Main program
- company_array=() # Create empty company array
- result_array=() # Create empty result array
- mode="" # Initial mode
- verbose="" # Default verbose = OFF
- backup="" # Default backup of ipfire files = OFF
- keeptemp="" # Default interactive mode = OFF
- interact="" # Default Keep source temp file after finish = OFF
- temp1="$temppath/$temp1" # Source temp file
- temp2="$temppath/$temp2" # Source temp file
- helptext="Usage: asn_ipfire.sh [OPTION] [COMPANYs | -f FILE] \nTry 'asn_ipfire.sh --help' for more information."
- chkSystem # ipfire system? wget or curl available?
- # Check arguments and get company array
- if [[ $# -eq 0 ]]; then echo -e $helptext; exit 1; fi # No arguments --> exit
- if [[ $# -gt 10 ]]; then echo -e "Too many arguments.\n""$helptext"; exit 1; fi # Too many arguments --> exit
- while [[ $# -gt 0 ]] ; do
- case $1 in
- -a|--add | -r|--remove | --asn | --network | --iptable | --afwall | --custom) {
- if [[ $mode ]]; then # Mode already set
- echo -e "Too many arguments.\n""$helptext"
- exit 1
- else
- mode=$1
- if [[ ! $2 ]]; then
- echo -e "No COMPANY names given.\n""$helptext"
- exit 1
- elif [[ ${2:0:1} == "-" ]]; then # followed by argument instead of company names
- if [[ "$2" != "-f" && "$2" != "--file" ]]; then # followed by argument instead of company names
- echo -e "Wrong order of arguments.\n""$helptext" # Wrong order of arguments --> exit
- exit 1
- fi
- else
- company_array_from_arg=(`sed -E 's/[ ]*//g; s/[,]+/ /g; s/\[//g; s/\]//g; s/[.\]*//g' <<< $2`) # Trim empty entries
- shift
- fi
- fi
- };;
- -f | --file) {
- if [[ -f $2 ]]; then # File exist
- company_array_from_file=(`sed 's/[ ]*//g; s/,\+/ /g; s/\[//g; s/\]//g; s/[.\]*//g; s/#.*$//g; /^$/d' <<< cat $2`) # Substitute space,comma,slash,comments,lines
- shift
- else # File not exist --> exit
- echo "Company file not found."
- echo -e "$helptext"
- exit 2
- fi
- };;
- -o | --outfile) {
- if [[ ! $2 ]]; then
- echo -e "No output file given.\n""$helptext"
- exit 1
- else
- output_file="$2"
- shift
- fi
- };;
- -l|--list | --renumber | --sort | --restore | --rmbackup | -h|--help | -V|--version) {
- if [[ $mode ]] || [[ $3 ]] || ( [[ $interact ]] && [[ $2 ]] ); then # No more arguments allowed for this option, except of interact
- echo -e "Too many arguments.\n""$helptext" # Too many parameter --> exit
- exit 1
- else
- mode=$1
- fi
- };;
- --backup ) { # Don't write backup Ipfire files
- if [[ ! $mode ]] && [[ ! $2 ]]; then
- echo -e "Missing arguments.\n""$helptext"
- exit 1
- else
- backup=1
- fi
- };;
- --raw ) { # Keep temporary source files
- if [[ ! $mode ]] && [[ ! $2 ]]; then
- echo -e "Missing arguments.\n""$helptext"
- exit 1
- else
- raw=1
- fi
- };;
- -k|--keep ) { # Keep temporary source files
- if [[ ! $mode ]] && [[ ! $2 ]]; then
- echo -e "Missing arguments.\n""$helptext"
- exit 1
- else
- keeptemp=1
- fi
- };;
- -i|--interactive ) { # Verbose mode shows stats
- if [[ ! $mode ]] && [[ ! $2 ]]; then
- echo -e "Missing arguments.\n""$helptext"
- exit 1
- else
- interact=1
- fi
- };;
- -v|--verbose ) { # Verbose mode shows stats
- if [[ ! $mode ]] && [[ ! $2 ]]; then
- echo -e "Missing arguments.\n""$helptext"
- exit 1
- else
- verbose=1
- fi
- };;
- -c|--check ) { # Check source
- if [[ ! $mode ]] && [[ ! $2 ]]; then
- echo -e "Missing arguments.\n""$helptext"
- exit 1
- else
- checksource=1
- fi
- };;
- *) {
- echo -e "Unknown argument.\n""$helptext" # Unknown arguments --> exit
- exit 1
- };;
- esac
- shift
- done
- company_array=(`echo ${company_array_from_file[@]} ${company_array_from_arg[@]} | sort -uf`)
- case $mode in
- -a|--add) { # Add objects to ipfire files
- if [[ $is_ipfire ]]; then
- output_file="customnetworks & customgroups"
- if [ ! $company_array ]; then
- echo "No company names found. Nothing done!"
- echo "Try 'asn_ipfire.sh --help' for more information."
- exit 1
- fi
- if [[ $checksource ]]; then chkSource ; fi
- collectNetworks # Get networks and write to file
- if [[ $interact ]]; then
- echo -n "Update IPfire files now? OK[Enter]? "
- read -r p
- if [[ "$p" ]]; then
- echo "Nothing done to IPFire."
- exit 3
- fi
- fi
- cleanupNetworks # Remove existing entries
- renumberIpfireFiles # Renumbering
- addNetworks # Get networks and write to file
- echo "---[Restarting firewall]---"
- /etc/init.d/firewall restart 1> /dev/null # Restart firewall
- echo "---[All done!]---"
- else
- echo -e "IPFire not found.\nCheck your IPFire installation."
- fi
- };;
- -r|--remove) { # Add objects to ipfire files
- if [[ $is_ipfire ]]; then
- output_file="customnetworks & customgroups"
- if [ ! $company_array ]; then
- echo "No company names found. Nothing done!"
- echo "Try 'asn_ipfire.sh --help' for more information."
- exit 1
- fi
- if [[ $interact ]]; then
- echo -n "Update IPfire files now? OK[Enter]? "
- read -r p
- if [[ "$p" ]]; then
- echo "Nothing done to IPFire."
- exit 3
- fi
- fi
- cleanupNetworks # Remove existing entries
- renumberIpfireFiles # Renumbering
- echo "---[Restarting firewall]---"
- /etc/init.d/firewall restart 1> /dev/null # Restart firewall
- echo "---[All done!]---"
- else
- echo -e "IPFire not found.\nCheck your IPFire installation."
- fi
- };;
- -l|--list) { # Function: List all company names already there by asn_ipfire
- if [[ $is_ipfire ]]; then
- listIpfireFiles
- else
- echo -e "IPFire not found.\nCheck your IPFire installation."
- fi
- };;
- --renumber) {
- if [[ $is_ipfire ]]; then
- verbose=1
- if [[ $interact ]]; then
- echo -n "Update IPfire files now? OK[Enter]? "
- read -r p
- if [[ "$p" ]]; then
- echo "Nothing done."
- exit 3
- fi
- fi
- renumberIpfireFiles
- else
- echo -e "IPFire not found.\nCheck your IPFire installation."
- fi
- };;
- --sort) {
- if [[ $is_ipfire ]]; then
- if [[ $interact ]]; then
- echo -n "Update IPfire files now? OK[Enter]? "
- read -r p
- if [[ "$p" ]]; then
- echo "Nothing done."
- exit 3
- fi
- fi
- verbose=1
- sortIpfireFiles
- else
- echo -e "IPFire not found.\nCheck your IPFire installation."
- fi
- };;
- --rmbackup) {
- if [[ $is_ipfire ]]; then
- verbose=1
- if [[ $interact ]]; then
- echo -n "Remove backup files now? OK[Enter]? "
- read -r p
- if [[ "$p" ]]; then
- echo "Nothing done."
- exit 3
- fi
- fi
- removeBackup
- else
- echo -e "IPFire not found.\nCheck your IPFire installation."
- fi
- };;
- --restore) {
- if [[ $is_ipfire ]]; then
- if [[ $interact ]]; then
- echo -n "Restore previous IPfire files now? OK[Enter]? "
- read -r p
- if [[ "$p" ]]; then
- echo "Nothing done to IPFire."
- exit 3
- fi
- fi
- restoreIpfireFiles
- else
- echo -e "IPFire not found.\nCheck your IPFire installation."
- fi
- };;
- --asn | --network | --custom | --iptable | --afwall) { # Create output files
- if [[ $mode == "--iptable" || $mode == "--afwall" ]]; then
- echo
- echo "WARNING !"
- echo " You are using obsolete option '$mode', which will not work in future versions"
- echo " Use option '--custom' instead, together with a config file."
- echo " See the wiki for further information"
- echo
- fi
-
- if [[ ! "$output_file" ]]; then # Custom output file given?
- output_file="file_"${mode:2} # Generate output file
- output_file="${!output_file}"
- fi
-
- if [ $company_array ]; then
- if [[ -f "$output_file" ]]; then
- if [[ $interact ]]; then
- read -r -p "Output file ($output_file) already exists! [O]verwrite, [A]ppend or abort? " ans
- case "$ans" in
- [Oo]) >"$output_file" ;;
- [Aa]) ;;
- *) exit 3;;
- esac
- else
- echo "Warning: output file ($output_file) already exists and will be overwritten!"
- >"$output_file"
- fi
- else # File not exist --> exit
- touch "$output_file" 2> /dev/null # Check if writable?
- fi
- if [[ ! -w "$output_file" ]]; then
- echo "Output file ($output_file) is not writable!"
- exit 2
- fi
- if [[ $checksource ]]; then chkSource ; fi
- collectNetworks "$mode" # Get and add new networks
- outResults "$mode"
- echo "---[All done!]---"
- else
- echo "No company names found. Nothing done!"
- echo "Try 'asn_ipfire.sh --help' for more information."
- fi
- };;
- -V|--version ) { # Show version and quit
- echo "$revision";
- };;
- -h|--help) {
- print_help # Show help and quit
- };;
- *) echo -e "$helptext";; # Wrong or unknown parameter
- esac
- exit 0
|