Chúng ta đã có mailserver rồi. Nhưng làm thế nào để các máy chủ mail khác tìm được mailserver của chúng ta? Câu trả lời nằm ở dịch vụ quan trọng nhất trên internet: DNS. Giả sử rằng một mailserver ở đâu đó của internet muốn gửi email đến john@example.org. Máy chủ phải tìm ra tên (và địa chỉ IP) của máy chủ thư chịu trách nhiệm về tên miền example.org. Đây là cách nó hoạt động:
Máy chủ từ xa truy vấn máy chủ DNS của nó để tìm bản ghi MX (Mail eXchanger) của tên miền Ví dụ.example.org. (Nếu không tìm thấy bản ghi MX nào, nó sẽ thử lại và yêu cầu bản ghi A (địa chỉ). Đó là một giải pháp dự phòng.)
Chúng ta có một số chỉ thứ tự ưu tiên của tên mailserver. (ưu tiên số nhỏ hơn). MX record phải gồm tên server thay vì IP..
Script
#!/bin/bash
# Tên script: 14.ddns.sh
# Cài đặt DDNS cho mailserver
# © 2020 LNT <lnt@ly-le.info>
# version 20200801
#
echo 'Cài đặt DDNS cho mailserver...'
HOSTNAME=$(hostname)
DOMAIN=${HOSTNAME#*.}
cp ./T1.cloudflareIP.sh /usr/share
#Update cloudflare 3 phút một lần
cat > /etc/cron.d/cloudflare <<EOF
*/3 * * * * root /usr/share/T1.cloudflareIP.sh ${DOMAIN} @,\* &> /dev/null
EOF
#!/bin/bash
# Tên script: T1.cloudflareIP.sh
# Cập nhật dynamic IP cho cloudflare
# © 2020 LNT <lnt@ly-le.info>
# version 20200801
#
echo 'Cập nhật dynamic IP cho cloudflare...'
( command -v jq &> /dev/null ) || apt install -y jq
AUTH_EMAIL='lyntuan@hotmail.com'
AUTH_KEY='2c3ff1eff6e39543358d96973fd60a8803541'
BASE_URL='https://api.cloudflare.com/client/v4/zones'
GETWAN='http://icanhazip.com'
# Shared Memory
SHM=/dev/shm/cfIP
[ -d $SHM ] || mkdir $SHM
[ '-f' = "$1" ] && { rm -rf $SHM/*; ff=1; shift; } || ff=0
[[ "$1" =~ ([0-9]{1,3}\.)+[0-9]{1,3} ]] && { uIP="$1"; shift; } || uIP=''
set -f
if [ $# -ne 2 ]; then
echo
echo 'Update the IP for domain/subdomains in cloudflare.com'
echo
echo "usage: $(basename $0) [-f] [ip] yr.domain sub[,sub2 ...]"
echo ' -f : clear cache'
echo ' ip : WAN IP if not specified'
echo ' sub: instead of sub.yr.domain'
echo ' @ : instead of yr.domain'
echo ' \* : all subdomains except @'
echo ' -sub: except sub'
exit 1
fi
DOMAIN="$1"
PARAMS="$2"
hbk=$(md5sum <<< "$PARAMS" | awk '{print $1}')
[ "$uIP" ] && wIP="$uIP" || wIP=$(curl -s "$GETWAN")
[ -f "$SHM/ip" ] && oIP=$(<$SHM/ip) || oIP=''
printf $wIP > $SHM/ip
[[ $ff -eq 0 && "$wIP" = "$oIP" ]] && { echo "IP has not changed"; exit 0; }
if [[ -f $SHM/"$hbk" ]]; then
hosts=$(<$SHM/"$hbk")
ZONE_ID=$(<$SHM/$DOMAIN)
BASE_URL="${BASE_URL}"/"${ZONE_ID}"/dns_records
else
# ID của domain
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; }
echo "${ZONE_ID}" > $SHM/$DOMAIN
BASE_URL="${BASE_URL}"/"${ZONE_ID}"/dns_records
# json string of subdomain
tmp=$(curl -s -H "X-Auth-Email: ${AUTH_EMAIL}" -H "X-Auth-Key: ${AUTH_KEY}" -H "Content-Type: application/json" -X GET "${BASE_URL}?type=A" | jq -r '.result[] | {id,name,content}' | jq -s .)
if [[ $PARAMS = *\** ]]; then
ra=($(echo $PARAMS | grep -Po '(?<=-)[^,]+' | jq -Rr ". + \".$DOMAIN\""))
[[ ! $PARAMS = *@* ]] && ra+=($DOMAIN)
c=''; for a in "${ra[@]}"; do [ ! "$c" ] && c=".name == \"$a\"" || c="$c or .name == \"$a\""; done
[[ ! -z "$c" ]] && hosts=$(echo "$tmp" | jq ".[] | del(select($c))" | jq -s .) || hosts=$(echo "$tmp" | jq -s ".[]")
else
aa=($(echo $PARAMS | grep -Po '(?<!-)[^,]+' | jq -Rr ". + \".$DOMAIN\""))
aa=("${aa[@]/@./}")
c=''; for a in "${aa[@]}"; do [ ! "$c" ] && c=".name == \"$a\"" || c="$c or .name == \"$a\""; done
hosts=$(echo "$tmp" | jq ".[] | select($c)" | jq -s .)
fi
echo $hosts > $SHM/$hbk
fi
# json array
echo "$hosts" | jq -r '.[] | [.id, .name, .content] | @tsv' |
while IPS=$'\t' read id name cIP; do
if [[ $ff -eq 0 && "$wIP" == "$cIP" ]]; then
ret='IP has not changed'
else
ret=$(curl -s -X PUT -H "X-Auth-Email: ${AUTH_EMAIL}" -H "X-Auth-Key: ${AUTH_KEY}" -H "Content-Type: application/json" "${BASE_URL}/$id" --data "{\"type\":\"A\",\"name\":\"$name\",\"content\":\"${wIP}\",\"ttl\":3600,\"proxied\":false}" | jq -r '.success')
fi
echo "Updated IP for $name: $ret"
done
#update /etc/hosts
HOSTNAME=$(hostname)
sed "/\[.0-9\]*\s*${HOSTNAME}/d
s/\(127\.0\.0\.1\).*/\1\tlocalhost\t${HOSTNAME}/
" -i /etc/hosts
grep -q "^$wIP\s*${HOSTNAME}" /etc/hosts || echo -e "$wIP\t${HOSTNAME}" >> /etc/hosts