Or are you describing something more like Nessus, where you've got sensors that are trying to connect to endpoints?
No. That's really cool, but not the thing I try to solve. Lemme explain.
I manage a somewhat suped-up home network, full of enthusiasm, but otherwise very not professional. It has multiple VLANs (say, one for untrustworthy IoT devices, one for management e.g. to prevent the kids hacking into firewall for circumventing their time limit, one for trusted family use). I like my privacy and deploy a bunch of (micro-)services that provide modern creature comforts without having to rely on cloud; e.g. pihole dns, file share, jellyfin, gitlab, etc. I want some services accessible from all vlans (dns, ntp, etc.), but make others only available to specific VLANs.
At this point I use the most basic way to test if a service accessible, netcat to a port (UDP/TCP depending on service). In case of a failure I want the script to collect some troubleshooting info. For example dns:
Bash:
test="$ssh_cmd nc -zw1 192.168.100.253 53 -s $local_ip"
if [ "$1" = "debug" ] ; then
$ssh_cmd ping -4c2 192.168.100.253
echo
echo $test
$($test -v)
else
$($test)
fi
I want to run this test once for each vlan, hence it is encapsulated in its own script. Also, as I said earlier, at this point I have a couple dozen of these tests.
The general idea is to use a test client connected to an interface on my ICX switch, submit all the tests and collect the results, then change the VLAN association on the ICX interface.
I use a raspberry pi with two network interfaces. The first (eth0) to connect and submit commands via SSH (
$ssh_cmd
), the second (eth1) as test interface. The script above uses the following command to figure out what IP the test interface currently has.
Bash:
local_ip=$($ssh_cmd ip a show dev eth1 | grep "inet \(.*\)/" -o | grep -o "[[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*")
To change the VLAN, I not only need to assign the ICX interface to the correct VLAN, but I also need to change the NIC address on the pi. The following script does all that
Bash:
# Figure out what VLAN the interface is currently assigned to.
current_vlan=$($ssh_cmd ip a show dev eth1 | grep "inet \(.*\)/" -o | sed 's/inet [[:digit:]]*\.[[:digit:]]*\.\([[:digit:]]*\)\.[[:digit:]]*\//\1/')
echo Current vlan is $current_vlan.
# Generate ICX script to switch interface to new VLAN
cat > vlan.script <<EOF
conf t vlan ${current_vlan}
no untagged ethernet $2
vlan $1
untagged ethernet $2
int e $2
exit
EOF
# Run above script on the ICX
./run_script.exp 192.168.10.14 vlan.script "SSH@icx6450"
# change ip on pi test interface
$ssh_cmd sudo nmcli c modify test_connection ipv4.addresses "192.168.$1.250/24"
$ssh_cmd sudo nmcli c modify test_connection ipv4.gateway "192.168.$1.1"
$ssh_cmd sudo nmcli c down test_connection
$ssh_cmd sudo nmcli c up test_connection
A parent script sets a switch port to the desired VLAN on my ICX (well,
associates the interface with the correct VLAN), then executes all the tests sequentially recording the results in industry-standard Junit format.
Bash:
# script is called with ${vlan} as a parameter
# load and cycle through all test scripts in tests folder
tests=0
failures=0
testsuitestart=$(date +%s%N)
for testfile in tests/*.test ; do
tests=$((tests+1))
testname=$(basename "$testfile")
echo -n "<testcase id=\"net.basic.$testfile\" name=\"VLAN${vlan} $testname\" " >> $tmpfile
teststart=$(date +%s%N)
if source "./$testfile" ; then
echo "time=\"$(timespent $teststart $(date +%s%N))\"> " >>$tmpfile
else
echo "time=\"$(timespent $teststart $(date +%s%N))\"> " >>$tmpfile
failures=$((failures+1))
echo "<failure message=\"$testfile: No connectivity.\" type=\"WARNING\"> $testfile: No connectivity." >> $tmpfile
source "./$testfile" debug >> $tmpfile 2>&1
echo "</failure>" >> $tmpfile
fi
echo "</testcase>" >> $tmpfile
done
# Printing results for testsuite into resultsfile
printf "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n <testsuites id=\"20240120_vlan\" name=\"VLAN Net Connectivity\" tests=\"$tests\" failures=\"$failures\" time=\"$(timespent $testsuitestart $(date +%s%N))\">\n" > $resultsfile
printf " <testsuite id=\"${vlan}\" name=\"VLAN${vlan}\" tests=\"$tests\" failures=\"$failures\" time=\"$(timespent $testsuitestart $(date +%s%N))\">" >> $resultsfile
cat $tmpfile >> $resultsfile
echo " </testsuite>" >> $resultsfile
echo " </testsuites>" >> $resultsfile
GitLab calls the parent script as part of project pipeline, finds the generated test results and makes them available:
Click on Job name to review details for all tests:
Debug details in case of failure:
