From 85096bf757bb5ebd4796cafe506e018303778eed Mon Sep 17 00:00:00 2001 From: Jinhill Date: Wed, 6 Oct 2021 11:40:55 +0800 Subject: [PATCH] Add dnsapi for GeoScaling DNS2 --- dnsapi/dns_geos.sh | 157 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 dnsapi/dns_geos.sh diff --git a/dnsapi/dns_geos.sh b/dnsapi/dns_geos.sh new file mode 100644 index 00000000..a0025de2 --- /dev/null +++ b/dnsapi/dns_geos.sh @@ -0,0 +1,157 @@ +#! /usr/bin/env sh +####################################################### +# GeoScaling DNS2 hook script for acme.sh +# +# Environment variables: +# +# - $GEOS_Username (your geoscaling.com username) +# - $GEOS_Password (your geoscaling.com password) +# +# Author: Jinhill +# GEOS DNS: https://www.geoscaling.com +# Git repo: https://github.com/jinhill/acme.sh +####################################################### +COOKIE_FILE="/tmp/.geos.cookie" +_CURL="curl -c ${COOKIE_FILE} -b ${COOKIE_FILE} -A 'Mozilla/5.0;Chrome/92.0.4515.107;Safari/537.36'" +SESSION_TIMEOUT=300 +log(){ + echo "$@" 1>&2 +} + +#$1:url +url_encode() { + echo "$1" | awk -v ORS="" '{ gsub(/./,"&\n") ; print }' | while read -r l; + do + case "$l" in + [-_.~a-zA-Z0-9] ) printf '%s' "$l" ;; + "" ) printf '%%20' ;; + * ) printf '%%%02X' "'$l" + esac + done +} + +#$1:string,$2:char, if $2 not set return array len,$ret:count +count() { + if [ -n "$2" ];then + echo "$1" | awk -F"$2" '{print NF-1}' + else + echo "$1" | wc -w + fi +} + +contains() { + echo "$1" | grep -- "$2" >/dev/null 2>&1 +} + +#$1:seesion mode,$2:username,$3:password +login() { + if [ -n "$1" ] && [ "$1" = "1" ] && [ -f "${COOKIE_FILE}" ];then + c_t=$(date -r "${COOKIE_FILE}" "+%s") + now=$(date "+%s") + s_t=$(( now - c_t )) + if [ ${s_t} -lt ${SESSION_TIMEOUT} ];then + return 0 + fi + fi + + GEOS_Username="${GEOS_Username:-$(_readaccountconf_mutable GEOS_Username)}" + GEOS_Password="${GEOS_Password:-$(_readaccountconf_mutable GEOS_Password)}" + if [ -z "${GEOS_Username}" ] || [ -z "${GEOS_Password}" ]; then + GEOS_Username= + GEOS_Password= + _err "No auth details provided. Please set user credentials using the \$GEOS_Username and \$GEOS_Password environment variables." + return 1 + fi + enc_username=$(url_encode "${GEOS_Username}") + enc_password=$(url_encode "${GEOS_Password}") + body="username=${enc_username}&password=${enc_password}" + http_code=$($_CURL -X POST -d "$body" -o /dev/null -w "%{http_code}" "https://www.geoscaling.com/dns2/index.php?module=auth") + log "$body,$http_code" + if [ "${http_code}" = "302" ]; then + return 0 + fi + _err "geoscaling login failed for user ${GEOS_Username} bad RC from post" + return 1 +} + +#$1:full domain name,_acme-challenge.www.domain.com +#ret: +# sub_domain=_acme-challenge.www +# zone_id=xxxxxx +get_zone() { + resp=$($_CURL "https://www.geoscaling.com/dns2/index.php?module=domains") + table=$(echo "${resp}" | grep -oE "]+ class=\"threecolumns\">.*") + items=$(echo "${table}" | grep -oE ']+>[^>]+>') + i=1 + c=$(count "$1" ".") + while [ $i -le $c ]; do + d=$(echo "$1" | cut -d . -f $i-) + if [ -z "$d" ]; then + return 1 + fi + zone_id=$(echo "${items}" | grep -oE "id=[0-9]*.*$d" | cut -d "=" -f 2 | cut -d "'" -f 1) + if [ -n "${zone_id}" ]; then + sub_domain=$(echo "$1" | sed "s/.$d//") + return 0 + fi + i=$(( i + 1 )) + done + return 1 +} + +#$1:domain id,$2:dns fullname +get_record_id() { + resp=$($_CURL "https://www.geoscaling.com/dns2/index.php?module=domain&id=$1") + ids=$(echo "${resp}" | tr -d "\n" | grep -oE "
" | grep -oE "id=\"[0-9]*.name\">$2" | cut -d '"' -f 2 | cut -d '.' -f 1) + if [ -z "${ids}" ]; then + _err "DNS record $2 not found." + return 1 + fi + echo "${ids}" + return 0 +} + +########################## PUBLIC FUNCTIONS ########################### + +# Usage: dns_geos_add _acme-challenge.subdomain.domain.com "XyZ123..." +dns_geos_add() { + full_domain=$1 + value=$2 + type=$3 + [ -n "${type}" ] || type="TXT" + _info "Using GeoScaling DNS2 hook" + login || return 1 + get_zone "${full_domain}" || return 1 + + body="id=${zone_id}&name=${sub_domain}&type=${type}&content=${value}&ttl=300&prio=0" + resp=$($_CURL -X POST -d "$body" "https://www.geoscaling.com/dns2/ajax/add_record.php") + if contains "${resp}" '"code":"OK"'; then + _info "${type} record added successfully." + else + _err "Couldn't add the ${type} record." + return 1 + fi + return 0 +} + +# Usage: dns_geos_rm _acme-challenge.subdomain.domain.com "XyZ123..." +dns_geos_rm() { + full_domain=$1 + value=$2 + _info "Cleaning up after GeoScaling DNS2 hook" + login || return 1 + get_zone "${full_domain}" || return 1 + log "zone id \"${zone_id}\" will be used." + + # Find the record id to clean + subdomain_id=$(get_record_id "${zone_id}" "${full_domain}") || return 1 + body="id=${zone_id}&record_id=${subdomain_id}" + resp=$($_CURL -X POST -d "$body" "https://www.geoscaling.com/dns2/ajax/delete_record.php") + if contains "${resp}" '"code":"OK"'; then + _info "Record removed successfully." + else + _err "Could not clean (remove) up the record. Please go to https://www.geoscaling.com and clean it by hand." + return 1 + fi + return 0 +}