Created
April 10, 2026 07:53
-
-
Save dkrusky/2133fd9019da79dfc84efe19affadd22 to your computer and use it in GitHub Desktop.
Quickly generate and verify DANE/TLSA/etc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Usage: | |
| # ./generate-tlsa.sh /path/to/cert.pem | |
| # | |
| # Output: | |
| # TLSA values for: | |
| # selector 0 / matchtype 0,1,2 | |
| # selector 1 / matchtype 0,1,2 | |
| CERT="$1" | |
| if [ -z "$CERT" ]; then | |
| echo "Usage: $0 /path/to/cert.pem" | |
| exit 1 | |
| fi | |
| if [ ! -f "$CERT" ]; then | |
| echo "File not found: $CERT" | |
| exit 1 | |
| fi | |
| # Convert PEM → DER | |
| openssl x509 -in "$CERT" -outform DER > cert.der | |
| # Extract SPKI (SubjectPublicKeyInfo) | |
| openssl x509 -in "$CERT" -pubkey -noout \ | |
| | openssl pkey -pubin -outform DER > spki.der | |
| echo "====================================================" | |
| echo " TLSA Generator for: $CERT" | |
| echo "====================================================" | |
| echo | |
| # Helper function | |
| hex() { | |
| xxd -p -c 9999 "$1" | tr -d '\n' | |
| } | |
| sha256() { | |
| openssl sha256 -binary "$1" | xxd -p -c 9999 | tr -d '\n' | |
| } | |
| sha512() { | |
| openssl sha512 -binary "$1" | xxd -p -c 9999 | tr -d '\n' | |
| } | |
| echo "Selector 0 (Full Certificate)" | |
| echo "-----------------------------" | |
| echo "Matchtype 0 (Exact):" | |
| echo " $(hex cert.der)" | |
| echo | |
| echo "Matchtype 1 (SHA-256):" | |
| echo " $(sha256 cert.der)" | |
| echo | |
| echo "Matchtype 2 (SHA-512):" | |
| echo " $(sha512 cert.der)" | |
| echo | |
| echo "Selector 1 (SPKI)" | |
| echo "-----------------------------" | |
| echo "Matchtype 0 (Exact):" | |
| echo " $(hex spki.der)" | |
| echo | |
| echo "Matchtype 1 (SHA-256):" | |
| echo " $(sha256 spki.der)" | |
| echo | |
| echo "Matchtype 2 (SHA-512):" | |
| echo " $(sha512 spki.der)" | |
| echo | |
| echo "====================================================" | |
| echo " Done — copy the value you need into your TLSA record" | |
| echo "====================================================" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Usage: ./verify-mail-security.sh domain.com | |
| DOMAIN="$1" | |
| if [ -z "$DOMAIN" ]; then | |
| echo "Usage: $0 domain.com" | |
| exit 1 | |
| fi | |
| POLICY_URL="https://mta-sts.${DOMAIN}/.well-known/mta-sts.txt" | |
| MTA_STS_TXT="_mta-sts.${DOMAIN}" | |
| TLS_RPT_TXT="_smtp._tls.${DOMAIN}" | |
| echo "====================================================" | |
| echo " Checking Mail Security for: $DOMAIN" | |
| echo "====================================================" | |
| echo | |
| echo "1) Checking MTA-STS DNS TXT record (${MTA_STS_TXT})" | |
| echo "----------------------------------------------------" | |
| dig +short TXT ${MTA_STS_TXT} | |
| echo | |
| echo "2) Checking TLS-RPT DNS TXT record (${TLS_RPT_TXT})" | |
| echo "----------------------------------------------------" | |
| dig +short TXT ${TLS_RPT_TXT} | |
| echo | |
| echo "3) Checking MX records" | |
| echo "----------------------------------------------------" | |
| MX_HOSTS=$(dig +short MX ${DOMAIN} | awk '{print $2}' | sed 's/\.$//') | |
| echo "$MX_HOSTS" | |
| echo | |
| echo "4) Fetching MTA-STS HTTPS policy" | |
| echo "----------------------------------------------------" | |
| curl -s -D headers_mta_sts.txt "${POLICY_URL}" -o mta_sts_policy.txt | |
| echo | |
| echo "5) Checking TLS certificate for mta-sts.${DOMAIN}" | |
| echo "----------------------------------------------------" | |
| echo | openssl s_client -connect mta-sts.${DOMAIN}:443 -servername mta-sts.${DOMAIN} 2>/dev/null \ | |
| | openssl x509 -noout -dates -issuer -subject | |
| echo | |
| echo "6) Checking DANE TLSA records and validating against MX certificates" | |
| echo "----------------------------------------------------" | |
| for MX in $MX_HOSTS; do | |
| echo "MX Host: $MX" | |
| dig +short TLSA _25._tcp.${MX} > tlsa_raw.txt | |
| if [ ! -s tlsa_raw.txt ]; then | |
| echo " No TLSA records found (DANE not enabled)" | |
| echo | |
| continue | |
| fi | |
| echo " TLSA Records:" | |
| sed 's/^/ /' tlsa_raw.txt | |
| echo " Fetching certificate via STARTTLS..." | |
| CERT_DER="cert_${MX}.der" | |
| echo | openssl s_client -starttls smtp -connect ${MX}:25 -servername ${MX} 2>/dev/null \ | |
| | openssl x509 -outform DER > "$CERT_DER" | |
| if [ ! -s "$CERT_DER" ]; then | |
| echo " ERROR: Could not retrieve certificate" | |
| echo | |
| continue | |
| fi | |
| while read -r line; do | |
| # Parse usage, selector, matchtype | |
| usage=$(echo "$line" | awk '{print $1}') | |
| selector=$(echo "$line" | awk '{print $2}') | |
| matchtype=$(echo "$line" | awk '{print $3}') | |
| # Join all remaining fields into one hex string | |
| data=$(echo "$line" | cut -d' ' -f4- | tr -d ' ') | |
| echo " TLSA: usage=$usage selector=$selector matchtype=$matchtype" | |
| echo " Data: $data" | |
| # Determine data to hash | |
| if [ "$selector" = "0" ]; then | |
| tohash="$CERT_DER" | |
| elif [ "$selector" = "1" ]; then | |
| SPKI_DER="spki_${MX}.der" | |
| openssl x509 -in "$CERT_DER" -inform DER -pubkey -noout \ | |
| | openssl pkey -pubin -outform DER > "$SPKI_DER" | |
| tohash="$SPKI_DER" | |
| else | |
| echo " ✘ Invalid selector" | |
| continue | |
| fi | |
| # Compute hash | |
| if [ "$matchtype" = "0" ]; then | |
| hash=$(xxd -p -c 9999 "$tohash") | |
| elif [ "$matchtype" = "1" ]; then | |
| hash=$(openssl sha256 -binary "$tohash" | xxd -p -c 9999) | |
| elif [ "$matchtype" = "2" ]; then | |
| hash=$(openssl sha512 -binary "$tohash" | xxd -p -c 9999) | |
| else | |
| echo " ✘ Invalid matchtype" | |
| continue | |
| fi | |
| # Compare lowercase | |
| if [ "${hash,,}" = "${data,,}" ]; then | |
| echo " ✔ MATCH" | |
| else | |
| echo " ✘ MISMATCH" | |
| echo " Expected: ${data,,}" | |
| echo " Got: ${hash,,}" | |
| fi | |
| done < tlsa_raw.txt | |
| echo | |
| done | |
| echo | |
| echo "7) Displaying MTA-STS policy file" | |
| echo "----------------------------------------------------" | |
| cat mta_sts_policy.txt | |
| echo | |
| echo "8) Displaying MTA-STS HTTPS response headers" | |
| echo "----------------------------------------------------" | |
| cat headers_mta_sts.txt | |
| echo | |
| echo "====================================================" | |
| echo " Mail Security Verification Complete" | |
| echo "====================================================" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment