#!/usr/bin/env bash set -euo pipefail SCRIPT_NAME=$(basename "$0") function usage() { cat <: Integer PRNG seed EOF } EXIT_STATUS=0 SEED=1 while getopts "hs:" opt ; do case "$opt" in h) usage exit 0 ;; s) SEED="$OPTARG" ;; *) echo "Unknown option. (Run $0 -h for usage)" exit 1 ;; esac done echo "SEED=$SEED" # Remove output of previous run rm -rf shadow.data export RUST_BACKTRACE=1 # Fix permissions on hidden service dir to prevent tor from bailing. # TODO: isn't there a way to set the permissions in the git repo? Tried `git # update-index --chmod`, but it refuses to set permissions on a directory. chmod 700 shadow.data.template/hosts/fileserver-onion/hs chmod 700 shadow.data.template/hosts/fileserver-onion-auth/hs chmod 700 shadow.data.template/hosts/fileserver-onion-arti-auth/authorized_clients chmod 700 shadow.data.template/hosts/fileserver-onion-arti-auth-ctor/ctor-store chmod 700 shadow.data.template/hosts/articlient-onion-artiserver-auth-ctor/ctor-store # Run the simulation shadow \ --log-level=info \ --template-directory=./shadow.data.template \ --progress=true \ --use-memory-manager=false \ --use-cpu-pinning=false \ --use-worker-spinning=false \ --seed="$SEED" \ shadow.yaml \ > shadow.log # Look for any non-empty stderr files. In particular rust panics sometimes end # up showing up here (even though we try to log them properly). nonempty_stderr=$(find shadow.data/hosts/ -name '*.stderr' -size +0 -print -quit) if [ -n "$nonempty_stderr" ]; then echo "FAIL: Found non-empty stderr file $nonempty_stderr:" cat "$nonempty_stderr" EXIT_STATUS=1 fi # Look for errors in arti logs. # TODO: Maybe fail on warnings, too? There currently are a few, though. arti_errs=$(find shadow.data/hosts/ -name 'arti.log.txt' -exec grep --with-filename '\bERROR\b' \{\} \;) if [ -n "$arti_errs" ]; then echo "Found arti errors:" echo "$arti_errs" EXIT_STATUS=1 fi check_host_xfers() { hostname="$1" min="$2" total="$3" successes="$(grep -c stream-success shadow.data/hosts/"$hostname"/tgen.*.stdout || true)" result="$hostname had $successes/$total successful streams (required at least $min)" if [ "$successes" -ge "$min" ] then echo "PASS: $result" else echo "FAIL: $result" EXIT_STATUS=1 fi } # Check whether file transfers via arti inside the simulation succeeded check_host_xfers articlient 10 10 check_host_xfers articlient-extra 10 10 check_host_xfers articlient-bridge 10 10 check_host_xfers articlient-bridge-obfs4 10 10 check_host_xfers torclient-onion-artiserver 10 10 check_host_xfers torclient-onion-artiserver-full-vanguards 10 10 # arti-client onion-service transfers have tended to be a bit less reliable. # For a while we only required 1/10 to succeed. It looks like it's gotten # better, but still seeing some occasional failures so requiring 5/10 for now. # https://gitlab.torproject.org/tpo/core/arti/-/issues/2109 check_host_xfers articlient-onion 5 10 check_host_xfers articlient-onion-artiserver 5 10 check_host_xfers articlient-onion-artiserver-full-vanguards 5 10 check_host_xfers articlient-onion-artiserver-auth 5 10 check_host_xfers articlient-onion-artiserver-auth-2 5 10 check_host_xfers articlient-onion-artiserver-auth-ctor 5 10 # https://gitlab.torproject.org/tpo/core/arti/-/issues/1986 check_host_xfers articlient-onion-auth 1 10 HOSTS=( articlient-onion articlient-onion-auth articlient-onion-artiserver articlient-onion-artiserver-full-vanguards articlient-onion-artiserver-auth articlient-onion-artiserver-auth-ctor fileserver-onion-arti fileserver-onion-arti-full-vanguards fileserver-onion-arti-auth fileserver-onion-arti-auth-ctor ) for HOST in "${HOSTS[@]}"; do # There should be only one such file per host. file=(shadow.data/hosts/"$HOST"/arti.log.txt) # TODO: this is a temporary measure until we implement other ways of testing # that the circuits we've built have the desired properties. bugs="$(grep -c Bug "${file[*]}" || true)" if [ "$bugs" -eq 0 ] then echo "$HOST simulation successful" else echo "FAIL: Found $bugs internal errors in ${file[*]}." EXIT_STATUS=1 fi done pushd shadow.data/hosts/articlient-bridge/ for PCAP in *.pcap; do # verify all connection are either from/to the bridge, or local. LEAK=$(tshark -r "$PCAP" 'ip.src != 100.0.0.2 && ip.dst != 100.0.0.2 && ip.dst != 127.0.0.0/8') if [ "$LEAK" ]; then echo "FAIL: Found tcp leaks in PCAP: $PCAP" echo "$LEAK" EXIT_STATUS=1 fi done DNS_LEAK=$(grep -l shadow_hostname_to_addr_ipv4 arti.*.strace || true) if [ "$DNS_LEAK" ]; then echo "FAIL: Found DNS leaks in $DNS_LEAK" EXIT_STATUS=1 fi popd exit "$EXIT_STATUS"