From 6ada269f376786119cb4705461639ebe5caa30a5 Mon Sep 17 00:00:00 2001 From: Erich Eckner Date: Thu, 29 Nov 2018 15:48:22 +0100 Subject: ein Anfang --- .gitignore | 1 + network-topology-scanner | 197 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 .gitignore create mode 100755 network-topology-scanner diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d3127d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +network.png diff --git a/network-topology-scanner b/network-topology-scanner new file mode 100755 index 0000000..8db3315 --- /dev/null +++ b/network-topology-scanner @@ -0,0 +1,197 @@ +#!/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" \ + | sort -k2,5 -k1,1 \ + > "${tmp_dir}/routes.new" + +uniq -uf1 "${tmp_dir}/routes.new" | tee /dev/stderr \ + | grep '^f ' \ + > "${tmp_dir}/routes" + +# todo : remove duplicates + +uniq -df1 "${tmp_dir}/routes.new" \ + | sed 's/^[fr] /b /' \ + >> "${tmp_dir}/routes" +rm "${tmp_dir}/routes.new" + +sed ' + s/^f \(\S\+\) 4 \(\S\+\) \(\S\+\)$/"\1 \2" -> "\1 \3" [weight=0, color="#808080"];\n/ + t + s/^f \(\S\+\) 6 \(\S\+\) \(\S\+\)$/"\1 \2" -> "\1 \3" [weight=0, color="#000000"];\n/ + t + s/^b \(\S\+\) 4 \(\S\+\) \(\S\+\)$/"\1 \2" -> "\1 \3" [dir=both, weight=0, color="#808080"];\n/ + t + s/^b \(\S\+\) 6 \(\S\+\) \(\S\+\)$/"\1 \2" -> "\1 \3" [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 -- cgit v1.2.3-54-g00ecf