#!/bin/bash hosts=( 'router 192.168.0.13' 'rpi3 192.168.1.3' ) tmp_dir=$(mktemp -d) trap 'rm -rf --one-file-system "${tmp_dir:?}"' EXIT for host in "${hosts[@]}"; do name="${host% *}" addr="${host##* }" printf '"%s" [fontcolor="#800000"];\n' "${name}" >> "${tmp_dir}/print-content" ssh "${addr}" ip -o addr | \ sed -n ' s/\s*\\.*$// s/\s\+/ /g / scope link/d s/^[0-9]\+: // /^lo /d h s/^\(\S\+\) .*$/'"${name}"' \1/ w '"${tmp_dir}"'/interfaces s/^\(.\+\) \(\S\+\)$/"\0" [label = "\2", fontcolor="#00ff00"];/ w '"${tmp_dir}/print-content"' g s/^\(\S\+\) .*$/"'"${name}"'" -> "'"${name}"' \1";/ w '"${tmp_dir}/print-content"' g s/^\(\S\+\) \S\+ \(\S\+\) .*$/"'"${name}"' \1" -> "\2";/ w '"${tmp_dir}/print-content"' g s/^\S\+ \(\S\+\) \(\S\+\) .*$/\1 \2/ w '"${tmp_dir}"'/ips ' for file in ips interfaces print-content; do cat "${tmp_dir}/${file}" >> "${tmp_dir}/all-${file}" done ssh "${addr}" 'sudo iptables-save | sed "s/^/4 /"; sudo ip6tables-save | sed "s/^/6 /"' 2>/dev/null | \ sed ' s/^/'"${name}"' / ' >> \ "${tmp_dir}/iptables" done while read -r version address; do case ${version} in inet) printf '"%s" [fontcolor="#000080"];\n' "${address}" >> "${tmp_dir}/adress-types" ;; inet6) printf '"%s" [fontcolor="#0000ff"];\n' "${address}" >> "${tmp_dir}/adress-types" ;; esac subnet_mask=${address##*/} if [ -z "${subnet_mask}" ] || [ "${subnet_mask}" = "${address}" ]; then continue; fi case ${version} in inet) printf '"%s" [fontcolor="#000080"];\n' "${address}" >> "${tmp_dir}/adress-types" if [ "${subnet_mask}" = 32 ]; then continue fi base_address=$( sipcalc "${address}" | \ sed ' s/^Network\s\+address\s\+-\s\+\(\S\+\)\s*$/\1/ t d ' ) ;; inet6) if [ "${subnet_mask}" = 128 ]; then continue fi base_address=$( sipcalc "${address}" | \ sed -n ' s/^Subnet\s\+prefix\s\+(masked)\s\+-\s\+\(\S\+\)\s*$/\1/ T s,0\(:0\)*/,:/, p ' ) ;; *) continue ;; esac printf '%s %s\n' \ "${address}" \ "${base_address}" done \ < "${tmp_dir}/all-ips" \ | sort -u \ | sort -k2,2 -k1,1 \ | uniq -Df1 \ | sed ' s/^\(\S\+\) \(\S\+\)$/"\1" -> "\2";\n/ ' \ | tee -a "${tmp_dir}/all-print-content" \ | sed -n ' s/^".*" -> "\(\S\+\)";$/\1/ T /:/ { s/.*/"\0" [fontcolor="#a0a000"];/ p } /\./ { s/.*/"\0" [fontcolor="#808000"];/ p } ' \ >> "${tmp_dir}/adress-types" cat "${tmp_dir}/adress-types" >> "${tmp_dir}/all-print-content" grep '\S\+ [46] :FORWARD ACCEPT ' "${tmp_dir}/iptables" | \ while read -r host ipver _; do grep "^${host} " "${tmp_dir}/all-interfaces" done | \ sort -u > \ "${tmp_dir}/ifs-routed" join -j1 "${tmp_dir}/ifs-routed" "${tmp_dir}/ifs-routed" \ | grep -v ' \(\S\+\) \1$' \ | sed ' s/^\(\S\+\)\( .*\)$/\1 4\2\n\1 6\2/ ' \ > "${tmp_dir}/routes" grep -vwF "$( grep -vwF -- '-m conntrack' "${tmp_dir}/iptables" | \ grep -v '^\S\+ 4 .*/32 ' | \ grep -v '^\S\+ 6 .*/128 ' | \ sed -n ' s/^\(\S\+\) \([46]\) \(.* \)\?-A FORWARD \(.* \)\?-i \(\S\+\) \(.* \)\?-j DROP/\1 \2 \5/ T p ' )" "${tmp_dir}/routes" \ > "${tmp_dir}/routes.new" mv "${tmp_dir}/routes.new" "${tmp_dir}/routes" grep -vwF -- '-m conntrack' "${tmp_dir}/iptables" | \ grep -v '^\S\+ 4 .*/32 ' | \ grep -v '^\S\+ 6 .*/128 ' | \ sed ' s/^\(\S\+\) \([46]\) \(.* \)\?-A FORWARD \(.* \)\?-i \(\S\+\) \(.* \)\?-o \(\S\+\) \(.* \)\?-j ACCEPT/\1 \2 \5 \7/ t s/^\(\S\+\) \([46]\) \(.* \)\?-A FORWARD \(.* \)\?-o \(\S\+\) \(.* \)\?-i \(\S\+\) \(.* \)\?-j ACCEPT/\1 \2 \7 \5/ t d ' \ >> "${tmp_dir}/routes" sed ' s/^\(\S\+ \S\+\) \(\S\+\) \(\S\+\)$/f \1 \2 \3\nr \1 \3 \2/ ' "${tmp_dir}/routes" \ | while read -r dir host ip from to; do printf '%s %s %s %s %s %s\n' \ "${dir}" \ "${from}" \ "${to}" \ "${host}" \ "${ip}" \ "$( printf '%s\n' "${from}" "${to}" | \ sort | \ sha512sum | \ awk '{print $1}' )" done \ | sort -k2,6 -k1,1 \ > "${tmp_dir}/routes.new" uniq -uf1 "${tmp_dir}/routes.new" | tee /dev/stderr \ | grep '^f ' \ > "${tmp_dir}/routes" uniq -df1 "${tmp_dir}/routes.new" \ | sed 's/^[fr] /b /' \ | sort -k4,6 -k1,3 \ | uniq -f3 \ >> "${tmp_dir}/routes" rm "${tmp_dir}/routes.new" sed ' s/^f \(\S\+\) \(\S\+\) \(\S\+\) 4 \S\+$/"\3 \1" -> "\3 \2" [weight=0, color="#808080"];\n/ t s/^f \(\S\+\) \(\S\+\) \(\S\+\) 6 \S\+$/"\3 \1" -> "\3 \2" [weight=0, color="#000000"];\n/ t s/^b \(\S\+\) \(\S\+\) \(\S\+\) 4 \S\+$/"\3 \1" -> "\3 \2" [dir=both, weight=0, color="#808080"];\n/ t s/^b \(\S\+\) \(\S\+\) \(\S\+\) 6 \S\+$/"\3 \1" -> "\3 \2" [dir=both, weight=0, color="#000000"];\n/ t d ' "${tmp_dir}/routes" \ >> "${tmp_dir}/all-print-content" sort -u "${tmp_dir}/all-print-content" | cat -n { echo 'digraph network {' echo 'rankdir=LR;' sort -u "${tmp_dir}/all-print-content" echo '}' } | \ dot -Tpng -onetwork.png