#!/usr/bin/env bash ScriptVersion="1.0.0" ApiURL="https://zerotail.cc/api" SelfUpdateURL1="https://zerotail.cc/client/verify-zerotail.sh" SelfUpdateURL2="https://zerotail.org/client/verify-zerotail.sh" UpdateHarness="/tmp/verify-zerotail-update.sh" echo "zerotail certificate verification client v${ScriptVersion}" echo "" # check for required binaries if [ ! -f "$(which curl)" ]; then echo "error: curl not found in path" exit 2 fi if [ ! -f "$(which openssl)" ]; then echo "error: openssl not found in path" exit 2 fi if [ ! -f "$(which sha256sum)" ]; then echo "error: sha256sum not found in path" exit 2 fi # fetch certificate data from api echo "[1/4] fetching certificate data from ${ApiURL}/public/certs" ApiData=$(curl -s "${ApiURL}/public/certs" 2>/dev/null) if [ $? -ne 0 ] || [ -z "${ApiData}" ]; then echo "error: network error accessing ${ApiURL}/public/certs" echo "zerotail.cc may be offline or there is a problem with your network" exit 3 fi # parse json and verify each certificate echo "[2/4] parsing certificate data" echo "" # extract hostnames from json (simple grep/cut approach) Hostnames=$(echo "${ApiData}" | grep -o '"hostname":"[^"]*"' | cut -d'"' -f4 | sort -u) if [ -z "${Hostnames}" ]; then echo "error: no certificates found in api response" exit 4 fi TotalCerts=0 MatchingCerts=0 MismatchCerts=0 FailedCerts=0 echo "[3/4] verifying certificates against live connections" echo "" for hostname in ${Hostnames}; do TotalCerts=$((TotalCerts + 1)) # get api data for this host ApiFingerprint=$(echo "${ApiData}" | grep -A10 "\"hostname\":\"${hostname}\"" | grep '"remote_fingerprint"' | head -1 | cut -d'"' -f4) ApiMatches=$(echo "${ApiData}" | grep -A10 "\"hostname\":\"${hostname}\"" | grep '"matches"' | head -1 | grep -o 'true\|false') if [ -z "${ApiFingerprint}" ]; then echo " [SKIP] ${hostname} - no remote certificate data available" FailedCerts=$((FailedCerts + 1)) continue fi # fetch live certificate echo -n " [....] ${hostname} - fetching live certificate..." LiveCert=$(echo -n "Q" | openssl s_client -servername "${hostname}" -connect "${hostname}:443" 2>/dev/null) if [ $? -ne 0 ]; then echo -e "\r [FAIL] ${hostname} - connection failed " FailedCerts=$((FailedCerts + 1)) continue fi # extract fingerprint from live cert LiveFingerprint=$(echo "${LiveCert}" | openssl x509 -noout -fingerprint -sha256 2>/dev/null | cut -d'=' -f2) if [ -z "${LiveFingerprint}" ]; then echo -e "\r [FAIL] ${hostname} - could not extract fingerprint " FailedCerts=$((FailedCerts + 1)) continue fi # compare api fingerprint with live fingerprint if [ "${ApiFingerprint}" == "${LiveFingerprint}" ]; then echo -e "\r [ OK ] ${hostname} - certificate matches " MatchingCerts=$((MatchingCerts + 1)) else echo -e "\r [WARN] ${hostname} - CERTIFICATE MISMATCH DETECTED " echo " api fingerprint: ${ApiFingerprint}" echo " live fingerprint: ${LiveFingerprint}" MismatchCerts=$((MismatchCerts + 1)) fi # warn if api says local/remote don't match if [ "${ApiMatches}" == "false" ]; then echo " WARNING: zerotail.cc reports local/remote mismatch" fi done echo "" echo "[4/4] verification summary" echo " total certificates: ${TotalCerts}" echo " matching: ${MatchingCerts}" echo " mismatched: ${MismatchCerts}" echo " failed: ${FailedCerts}" echo "" if [ ${MismatchCerts} -gt 0 ]; then echo "WARNING: certificate mismatches detected" echo "this could indicate a man-in-the-middle attack or infrastructure issue" echo "verify at https://zerotail.cc for more details" exit 1 fi if [ ${FailedCerts} -eq ${TotalCerts} ]; then echo "ERROR: all certificate checks failed" echo "verify network connectivity and try again" exit 3 fi echo "all certificates verified successfully" echo "view detailed status at https://zerotail.cc" exit 0