From: Ian Jackson Date: Tue, 10 Oct 2017 13:35:34 +0000 (+0100) Subject: modrelays-probe: wip X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~webstump/git?a=commitdiff_plain;ds=sidebyside;h=eb3305d6e47dc86dbeba5bb6c9c499c9dee433c9;p=modbot-ulm.git modrelays-probe: wip --- diff --git a/probes/modrelays-probe b/probes/modrelays-probe new file mode 100755 index 0000000..1c4ead4 --- /dev/null +++ b/probes/modrelays-probe @@ -0,0 +1,201 @@ +#!/bin/bash + +set -e + +id=$(date +%s)_$$ + +fail () { + printf >&2 "%s\n" "modrelays-probe: error: $1" + exit 16 +} + +record-probing () { + # implicitly uses newsgroup, id, domain + # prints working dir filename + local probeid=$1 + + probeid=${probeid//[^=-.,_0-9A-Za-z]/%/} + case $probeid in + .*|*/*) fail "yikes, sanitisation bug!" ;; + esac + + local newtd="monitoring/modrelays.probes/$probeid" + mkdir -p $newtd + printf "%s" $newtd +} + +record-outcome () { + local probeid=$1 + local outcome=$2 + local message=$3 + local td=`record-probing "$probeid"` + printf "%s\n" >"$td"/"$outcome" +} + +record-success () { record-outcome "$1" ok '' } +record-tempfail () { record-outcome "$1" tempfail "$2" } +record-permfail () { record-outcome "$1" permfail "$2" } + +probe-addr () { + local mx=$1 + local addr=$2 + + local td=`record-probing "mx=$mx,addr=$addr"` + + set +e + swaks --to "${GROUP//./-/}@$domain" \ + --server $addr \ + --tls-optional-strict \ + --header 'Subject: test modrelays probe test' \ + --header \ + "X-WebSTUMP-Relay-Probe: $GROUP $id $domain $mx $addr" \ + -n >$td/swaks.log 2>$td/swaks.err + rc=$? + set -e + + case $rc in + 0) return ;; # record-success done by receiver + esac + local permfail='' + + local rhs + local prefix + local expect_no_5xx='initial connection' + while read <$td/swaks.log prefix rhs; do + case "$prefix" in + '<'*) + case "$rhs" in + 5*) + if [ "x$expect_no_5xx" != x ] && \ + [ "x$permfail" = x ]; then + permfail="$rhs ($expect_no_5xx)" ;; + fi + ;; + esac + ;; + *'>') + case "$rhs" in + EHLO*|STARTTLS*) expect_no_5xx='' ;; + *) expect_no_5xx="after $rhs" ;; + esac + ;; + *) + done + + if [ "x$permfail" = x ]; then + record-tempfail "mx=$mx,addr=$addr" "see swaks.log / swaks.err" + else + record-permfail "mx=$mx,addr=$addr" "$permfail" + fi +} + +probe-domain () { + local domain=$1 + local td=`record-probing dns` + + set +e + adnshost -Fi -Tn +Do +Dt -t mx $domain >$td/dns + rc=$? + set -e + + case $rc in + 0) + # have a list of MX's + exec <$td/dns + local pref + local mx + local statustype + local rhs + while read pref mx statustype rhs; do + case $statustype in + 0) + # have a list of relays + case $rhs in + *" ( "*")") ;; + *) + record-permfail "mx=$mx" \ + "dns format $rhs" + continue + ;; + rhs=${rhs%%* (} + rhs=${rhs# )} + local addr + for addr in $rhs; do + case $addr in + INET|INET6) continue ;; + esac + probe-addr $mx $addr + done + ;; + [123]) + # temporary errors + record-tempfail "mx=$mx" "dns $rc $rhs" + ;; + *) + # yikes + record-permfail "mx=$mx" "dns $rc $rhs" + ;; + esac + done + record-success dns + return + ;; + 6) + permfail, try A + set +e + adnshost -Fi -Tn +Do +Dt -t a $domain >$td + rc=$? + set -e + ;; + esac + + case $rc in + 0) + # have a list of A's (dealt with MXs above) + exec <$td/dns + local addr + while read addr; do + probe-addr '' $addr + done + record-success dns + return + ;; + [123]) + local emsg + read <$td/dns emsg + record-tempfail dns "dns $emsg" + ;; + *) + local emsg + read <$td/dns emsg + record-permfail dns "dns $emsg" + ;; + esac +} + +no_args () { + case $1 in + 0) return ;; + *) fail + +mode_all () { + no_args $# + for domain in $MODRELAYS; do + probe $domain + done +} + +mode_auto () { + no_args $# + xxx do something to cause sleeping + mode_all +} + +mode_relay () { + relay="$1" + probe "$relay" +} + +mode=$1; shift||: + +"mode_$mode" "$@"