DKIM (DomainKeys Identified Mail) là một chuẩn bảo mật trong email, được thiết kế để bảo đảm rằng thông điệp không bị thay đổi trên đường chuyển dịch từ server người gởi đến server người nhận.
Khóa công khai trên DNS của mail server bên gởi, trong khi khóa riêng được giữ ở mail server bên gởi. DKIM chèn mã bảo mật vào email. Server bên nhận sẽ so khớp khóa công khai với khóa riêng để kiểm tra nguồn gốc email, dùng DKIM trong email để kiếm chứng với server bên gởi rằng nội dung email không thay đổi trong quá trình chuyển đi.
DKIM trên cloudflare.com, là một record txt chứa khóa công khai, được script tự động tạo/cập nhật từ một file chứa khóa công khai có dạng
dkim._domainkey IN TXT ( "v=DKIM1; k=rsa; " "p=MIIBIjANBabcdefghIJKlmnoAAOCAQ8AMIIBCgKCAQEAqpvm4gl4nZM39+Lssv3TeOIBPnt0PON322qFZJ4+FG/tRXGhI/quQ8LyOa3gQPfLKUDqm2KYHaB1pUKO+HibFhue1orz33TDedHWoBkNB/zJyXhPAEdQf6dbZOLhMGF1w1QC+55o9BxOVKbtsEOenyio3VAKMV5b5CAdzVj6td+CleHMFD2uKPzTf4txoou89ivNj9EOgiLO8jgHn" "zC+SX12345678901234JE1rt/wUF9FJbprcC+mPN/DzqxgJPmRt6ZfWZkiva4m8zr7GcXxZVK/gww9Xp8FmCx+Dk4DSQ4BGqLqVVeU+K4+Nn3LHo1KDSpYA49Thaid0tCFwIDAQAB" ) ;
Trong đó nhóm chữ đầu tiên trước dấu . là selector, nhóm chữ giữa cặp ngoặc () sau khi bỏ các dấu nháy ” là giá trị khóa công khai. Record txt tương ứng là
dkim._domainkey
v=DKIM1; k=rsa; p=MIIBIjANBabc...
Nội dung script
#!/bin/bash
# cfdkim.sh
# Create DKIM , DRMARC, SPF records for cloudflare
# © 2020 LNT <lnt@lyle.info>
# version 20211008
AUTH_EMAIL='your_email_account'
AUTH_KEY='your_cloudflare_authkey'
BASE_URL='https://api.cloudflare.com/client/v4/zones'
GETWAN='http://ifconfig.me/ip'
command -v jq &> /dev/null || apt install -y jq
if [ $# -eq 1 ]; then
DOMAIN=$1
else
echo 'Create DKIM, DRMARC, SPF records for cloudflare'
echo "Usage: $(basename $0) your.domain"
exit
fi
[ ! -e "$DOMAIN.pubkey" ] && { echo DKIM public key not found!; exit; }
hdr='-H X-Auth-Email:'${AUTH_EMAIL}' -H X-Auth-Key:'${AUTH_KEY}' -H Content-Type:application/json'
ZONE_ID=$(jq -r '.result[].id' <<< $(curl -s -H "X-Auth-Email: ${AUTH_EMAIL}" -H "X-Auth-Key: ${AUTH_KEY}" -H "Content-Type: application/json" -X GET ${BASE_URL}?name=${DOMAIN}&status=active))
[[ "${ZONE_ID}" =~ ^[0-9a-f]{32}$ ]] || { echo "Bad Zone ID"; exit 1; }
BASE_URL="${BASE_URL}"/"${ZONE_ID}"/dns_records
cfr=$(curl -s -S ${hdr} -G "${BASE_URL}?type=TXT" | jq -r '.result[] | {id,name,content,type}'| jq -s .)
cIP=$(curl -s $GETWAN)
### test https://www.appmaildev.com/en/dkim
declare -A nR
sel=$(cat "$DOMAIN.pubkey" | sed -z 's/^\(.*\)\._domainkey.*/\1/')
nR[dkim]=$(cat "$DOMAIN.pubkey" | sed -z 's/"[ \n\t]*"//g' | sed -z 's/^'$sel'\._domainkey.*"\(.*\)".*/\1/')
nR[spf]="v=spf1 a mx ip4:$cIP ~all"
nR[dmarc]="v=DMARC1;p=quarantine;sp=none;pct=100;rua=mailto:postmaster+dmarc@$DOMAIN;ruf=mailto:postmaster+dmarc@$DOMAIN;"
for n in "${!nR[@]}"; do
case $n in
'dmarc')
name="_dmarc.$DOMAIN"
j=".name == \"$name\""
;;
'dkim')
name="$sel._domainkey.$DOMAIN"
j=".name == \"$name\""
;;
*)
name="$DOMAIN"
j='(.name == "'$name'") and (.content | contains("v=spf1"))'
;;
esac
IFS=$'\t' read id co <<<$(echo $cfr | jq -r ".[] | select($j) | [.id, .content] | @tsv")
echo "⯀ $n: $name"
if [ "${nR[$n]}" == "$co" ]; then
echo " -► no change!"
else
[ -z "$id" ] && mt='POST' || mt='PATCH'
msg=$(curl -s -S ${hdr} -X $mt "${BASE_URL}/$id" -d "{\"type\":\"TXT\",\"name\":\"$name\",\"content\":\"${nR[$n]}\",\"ttl\":3600,\"proxied\":false}" | jq -r '.errors[].message')
[ -z "$msg" ] && echo " -► $mt: succeed!" || echo " -► $mt: $msg"
fi
done