ISPmail (13): DNS

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

Comments Off on ISPmail (13): DNS

Filed under Software

Comments are closed.