commit
						4f59a821d3
					
				|  | @ -326,6 +326,7 @@ You don't have to do anything manually! | |||
| 1. ConoHa (https://www.conoha.jp) | ||||
| 1. netcup DNS API (https://www.netcup.de) | ||||
| 1. GratisDNS.dk (https://gratisdns.dk) | ||||
| 1. Namecheap API (https://www.namecheap.com/) | ||||
| 
 | ||||
| And:  | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										4
									
								
								acme.sh
								
								
								
								
							
							
						
						
									
										4
									
								
								acme.sh
								
								
								
								
							|  | @ -1810,14 +1810,14 @@ _send_signed_request() { | |||
|     if [ -z "$_CACHED_NONCE" ]; then | ||||
|       _headers="" | ||||
|       if [ "$ACME_NEW_NONCE" ]; then | ||||
|         _debug2 "Get nonce. ACME_NEW_NONCE" "$ACME_NEW_NONCE" | ||||
|         _debug2 "Get nonce with HEAD. ACME_NEW_NONCE" "$ACME_NEW_NONCE" | ||||
|         nonceurl="$ACME_NEW_NONCE" | ||||
|         if _post "" "$nonceurl" "" "HEAD" "$__request_conent_type"; then | ||||
|           _headers="$(cat "$HTTP_HEADER")" | ||||
|         fi | ||||
|       fi | ||||
|       if [ -z "$_headers" ]; then | ||||
|         _debug2 "Get nonce. ACME_DIRECTORY" "$ACME_DIRECTORY" | ||||
|         _debug2 "Get nonce with GET. ACME_DIRECTORY" "$ACME_DIRECTORY" | ||||
|         nonceurl="$ACME_DIRECTORY" | ||||
|         _headers="$(_get "$nonceurl" "onlyheader")" | ||||
|       fi | ||||
|  |  | |||
|  | @ -28,8 +28,10 @@ fritzbox_deploy() { | |||
|   _debug _cfullchain "$_cfullchain" | ||||
| 
 | ||||
|   if ! _exists iconv; then | ||||
|     _err "iconv not found" | ||||
|     return 1 | ||||
|     if ! _exists perl; then | ||||
|       _err "iconv or perl not found" | ||||
|       return 1 | ||||
|     fi | ||||
|   fi | ||||
| 
 | ||||
|   _fritzbox_username="${DEPLOY_FRITZBOX_USERNAME}" | ||||
|  | @ -61,7 +63,11 @@ fritzbox_deploy() { | |||
| 
 | ||||
|   _info "Log in to the FRITZ!Box" | ||||
|   _fritzbox_challenge="$(_get "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*<Challenge>//' -e 's/<\/Challenge>.*$//')" | ||||
|   _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" | ||||
|   if _exists iconv; then | ||||
|     _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" | ||||
|   else | ||||
|     _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | perl -p -e 'use Encode qw/encode/; print encode("UTF-16LE","$_"); $_="";' | md5sum | awk '{print $1}')" | ||||
|   fi | ||||
|   _fritzbox_sid="$(_get "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_fritzbox_username}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*<SID>//' -e 's/<\/SID>.*$//')" | ||||
| 
 | ||||
|   if [ -z "${_fritzbox_sid}" ] || [ "${_fritzbox_sid}" = "0000000000000000" ]; then | ||||
|  |  | |||
|  | @ -972,7 +972,7 @@ The `NC_Apikey`,`NC_Apipw` and `NC_CID` will be saved in `~/.acme.sh/account.con | |||
| 
 | ||||
| ## 52. Use GratisDNS.dk | ||||
| 
 | ||||
| GratisDNS.dk (https://gratisdns.dj/) does not provide an API to update DNS records (other than IPv4 and IPv6 | ||||
| GratisDNS.dk (https://gratisdns.dk/) does not provide an API to update DNS records (other than IPv4 and IPv6 | ||||
| dynamic DNS addresses).  The acme.sh plugin therefore retrieves and updates domain TXT records by logging | ||||
| into the GratisDNS website to read the HTML and posting updates as HTTP.  The plugin needs to know your | ||||
| userid and password for the GratisDNS website. | ||||
|  | @ -986,8 +986,32 @@ The username and password will be saved in `~/.acme.sh/account.conf` and will be | |||
| 
 | ||||
| Now you can issue a certificate. | ||||
| 
 | ||||
| Note: It usually takes a few minutes (usually 3-4 minutes) before the changes propagates to gratisdns.dk nameservers (ns3.gratisdns.dk often are slow), | ||||
| and in rare cases I have seen over 5 minutes before google DNS catches it. Therefor a DNS sleep of at least 300 seconds are recommended- | ||||
| 
 | ||||
| ```sh | ||||
| acme.sh --issue --dns dns_gdnsdk -d example.com -d *.example.com | ||||
| acme.sh --issue --dns dns_gdnsdk --dnssleep 300 -d example.com -d *.example.com | ||||
| ``` | ||||
| 
 | ||||
| ## 53. Use Namecheap | ||||
| 
 | ||||
| You will need your namecheap username, API KEY (https://www.namecheap.com/support/api/intro.aspx) and your external IP address (or an URL to get it), this IP will need to be whitelisted at Namecheap. | ||||
| Due to Namecheap's API limitation all the records of your domain will be read and re applied, make sure to have a backup of your records you could apply if any issue would arise. | ||||
| 
 | ||||
| ```sh | ||||
| export NAMECHEAP_USERNAME="..." | ||||
| export NAMECHEAP_API_KEY="..." | ||||
| export NAMECHEAP_SOURCEIP="..." | ||||
| ``` | ||||
| 
 | ||||
| NAMECHEAP_SOURCEIP can either be an IP address or an URL to provide it (e.g. https://ifconfig.co/ip). | ||||
| 
 | ||||
| The username and password will be saved in `~/.acme.sh/account.conf` and will be reused when needed. | ||||
| 
 | ||||
| Now you can issue a certificate. | ||||
| 
 | ||||
| ```sh | ||||
| acme.sh --issue --dns dns_namecheap -d example.com -d *.example.com | ||||
| ``` | ||||
| 
 | ||||
| # Use custom API | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| #!/usr/bin/env sh | ||||
| 
 | ||||
| # Cloudxns.com Domain api | ||||
| # CloudXNS Domain api | ||||
| # | ||||
| #CX_Key="1234" | ||||
| # | ||||
|  | @ -19,7 +19,7 @@ dns_cx_add() { | |||
|   if [ -z "$CX_Key" ] || [ -z "$CX_Secret" ]; then | ||||
|     CX_Key="" | ||||
|     CX_Secret="" | ||||
|     _err "You don't specify cloudxns.com  api key or secret yet." | ||||
|     _err "You don't specify cloudxns.net  api key or secret yet." | ||||
|     _err "Please create you key and try again." | ||||
|     return 1 | ||||
|   fi | ||||
|  |  | |||
|  | @ -0,0 +1,308 @@ | |||
| #!/usr/bin/env sh | ||||
| 
 | ||||
| # Namecheap API | ||||
| # https://www.namecheap.com/support/api/intro.aspx | ||||
| # | ||||
| # Requires Namecheap API key set in NAMECHEAP_API_KEY, NAMECHEAP_SOURCEIP and NAMECHEAP_USERNAME set as environment variable | ||||
| # Due to Namecheap's API limitation all the records of your domain will be read and re applied, make sure to have a backup of your records you could apply if any issue would arise. | ||||
| 
 | ||||
| ########  Public functions ##################### | ||||
| 
 | ||||
| if [ "$STAGE" -eq 1 ]; then | ||||
|   NAMECHEAP_API="https://api.sandbox.namecheap.com/xml.response" | ||||
| else | ||||
|   NAMECHEAP_API="https://api.namecheap.com/xml.response" | ||||
| fi | ||||
| 
 | ||||
| #Usage: dns_namecheap_add   _acme-challenge.www.domain.com   "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" | ||||
| dns_namecheap_add() { | ||||
|   fulldomain=$1 | ||||
|   txtvalue=$2 | ||||
| 
 | ||||
|   if ! _namecheap_check_config; then | ||||
|     _err "$error" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   if ! _namecheap_set_publicip; then | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _debug "First detect the root zone" | ||||
|   if ! _get_root "$fulldomain"; then | ||||
|     _err "invalid domain" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _debug fulldomain "$fulldomain" | ||||
|   _debug txtvalue "$txtvalue" | ||||
|   _debug domain "$_domain" | ||||
|   _debug sub_domain "$_sub_domain" | ||||
| 
 | ||||
|   _set_namecheap_TXT "$_domain" "$_sub_domain" "$txtvalue" | ||||
| } | ||||
| 
 | ||||
| #Usage: fulldomain txtvalue | ||||
| #Remove the txt record after validation. | ||||
| dns_namecheap_rm() { | ||||
|   fulldomain=$1 | ||||
|   txtvalue=$2 | ||||
| 
 | ||||
|   if ! _namecheap_set_publicip; then | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   if ! _namecheap_check_config; then | ||||
|     _err "$error" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _debug "First detect the root zone" | ||||
|   if ! _get_root "$fulldomain"; then | ||||
|     _err "invalid domain" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _debug fulldomain "$fulldomain" | ||||
|   _debug txtvalue "$txtvalue" | ||||
|   _debug domain "$_domain" | ||||
|   _debug sub_domain "$_sub_domain" | ||||
| 
 | ||||
|   _del_namecheap_TXT "$_domain" "$_sub_domain" "$txtvalue" | ||||
| } | ||||
| 
 | ||||
| ####################  Private functions below ################################## | ||||
| #_acme-challenge.www.domain.com | ||||
| #returns | ||||
| # _sub_domain=_acme-challenge.www | ||||
| # _domain=domain.com | ||||
| _get_root() { | ||||
|   domain=$1 | ||||
| 
 | ||||
|   if ! _namecheap_post "namecheap.domains.getList"; then | ||||
|     _err "$error" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   i=2 | ||||
|   p=1 | ||||
| 
 | ||||
|   while true; do | ||||
| 
 | ||||
|     h=$(printf "%s" "$domain" | cut -d . -f $i-100) | ||||
|     _debug h "$h" | ||||
|     if [ -z "$h" ]; then | ||||
|       #not valid | ||||
|       return 1 | ||||
|     fi | ||||
| 
 | ||||
|     if ! _contains "$response" "$h"; then | ||||
|       _debug "$h not found" | ||||
|     else | ||||
|       _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) | ||||
|       _domain="$h" | ||||
|       return 0 | ||||
|     fi | ||||
|     p="$i" | ||||
|     i=$(_math "$i" + 1) | ||||
|   done | ||||
|   return 1 | ||||
| } | ||||
| 
 | ||||
| _namecheap_set_publicip() { | ||||
| 
 | ||||
|   if [ -z "$NAMECHEAP_SOURCEIP" ]; then | ||||
|     _err "No Source IP specified for Namecheap API." | ||||
|     _err "Use your public ip address or an url to retrieve it (e.g. https://ipconfig.co/ip) and export it as NAMECHEAP_SOURCEIP" | ||||
|     return 1 | ||||
|   else | ||||
|     _saveaccountconf NAMECHEAP_SOURCEIP "$NAMECHEAP_SOURCEIP" | ||||
|     _debug sourceip "$NAMECHEAP_SOURCEIP" | ||||
| 
 | ||||
|     ip=$(echo "$NAMECHEAP_SOURCEIP" | _egrep_o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') | ||||
|     addr=$(echo "$NAMECHEAP_SOURCEIP" | _egrep_o '(http|https)://.*') | ||||
| 
 | ||||
|     _debug2 ip "$ip" | ||||
|     _debug2 addr "$addr" | ||||
| 
 | ||||
|     if [ -n "$ip" ]; then | ||||
|       _publicip="$ip" | ||||
|     elif [ -n "$addr" ]; then | ||||
|       _publicip=$(_get "$addr") | ||||
|     else | ||||
|       _err "No Source IP specified for Namecheap API." | ||||
|       _err "Use your public ip address or an url to retrieve it (e.g. https://ipconfig.co/ip) and export it as NAMECHEAP_SOURCEIP" | ||||
|       return 1 | ||||
|     fi | ||||
|   fi | ||||
| 
 | ||||
|   _debug publicip "$_publicip" | ||||
| 
 | ||||
|   return 0 | ||||
| } | ||||
| 
 | ||||
| _namecheap_post() { | ||||
|   command=$1 | ||||
|   data="ApiUser=${NAMECHEAP_USERNAME}&ApiKey=${NAMECHEAP_API_KEY}&ClientIp=${_publicip}&UserName=${NAMECHEAP_USERNAME}&Command=${command}" | ||||
| 
 | ||||
|   response="$(_post "$data" "$NAMECHEAP_API" "" "POST")" | ||||
|   _debug2 response "$response" | ||||
| 
 | ||||
|   if _contains "$response" "Status=\"ERROR\"" >/dev/null; then | ||||
|     error=$(echo "$response" | _egrep_o ">.*<\\/Error>" | cut -d '<' -f 1 | tr -d '>') | ||||
|     _err "error $error" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   return 0 | ||||
| } | ||||
| 
 | ||||
| _namecheap_parse_host() { | ||||
|   _host=$1 | ||||
|   _debug _host "$_host" | ||||
| 
 | ||||
|   _hostid=$(echo "$_host" | _egrep_o '\sHostId="[^"]*' | cut -d '"' -f 2) | ||||
|   _hostname=$(echo "$_host" | _egrep_o '\sName="[^"]*' | cut -d '"' -f 2) | ||||
|   _hosttype=$(echo "$_host" | _egrep_o '\sType="[^"]*' | cut -d '"' -f 2) | ||||
|   _hostaddress=$(echo "$_host" | _egrep_o '\sAddress="[^"]*' | cut -d '"' -f 2) | ||||
|   _hostmxpref=$(echo "$_host" | _egrep_o '\sMXPref="[^"]*' | cut -d '"' -f 2) | ||||
|   _hostttl=$(echo "$_host" | _egrep_o '\sTTL="[^"]*' | cut -d '"' -f 2) | ||||
| 
 | ||||
|   _debug hostid "$_hostid" | ||||
|   _debug hostname "$_hostname" | ||||
|   _debug hosttype "$_hosttype" | ||||
|   _debug hostaddress "$_hostaddress" | ||||
|   _debug hostmxpref "$_hostmxpref" | ||||
|   _debug hostttl "$_hostttl" | ||||
| } | ||||
| 
 | ||||
| _namecheap_check_config() { | ||||
| 
 | ||||
|   if [ -z "$NAMECHEAP_API_KEY" ]; then | ||||
|     _err "No API key specified for Namecheap API." | ||||
|     _err "Create your key and export it as NAMECHEAP_API_KEY" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   if [ -z "$NAMECHEAP_USERNAME" ]; then | ||||
|     _err "No username key specified for Namecheap API." | ||||
|     _err "Create your key and export it as NAMECHEAP_USERNAME" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _saveaccountconf NAMECHEAP_API_KEY "$NAMECHEAP_API_KEY" | ||||
|   _saveaccountconf NAMECHEAP_USERNAME "$NAMECHEAP_USERNAME" | ||||
| 
 | ||||
|   return 0 | ||||
| } | ||||
| 
 | ||||
| _set_namecheap_TXT() { | ||||
|   subdomain=$2 | ||||
|   txt=$3 | ||||
|   tld=$(echo "$1" | cut -d '.' -f 2) | ||||
|   sld=$(echo "$1" | cut -d '.' -f 1) | ||||
|   request="namecheap.domains.dns.getHosts&SLD=$sld&TLD=$tld" | ||||
| 
 | ||||
|   if ! _namecheap_post "$request"; then | ||||
|     _err "$error" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   hosts=$(echo "$response" | _egrep_o '<host[^>]*') | ||||
|   _debug hosts "$hosts" | ||||
| 
 | ||||
|   if [ -z "$hosts" ]; then | ||||
|     _error "Hosts not found" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _namecheap_reset_hostList | ||||
| 
 | ||||
|   while read -r host; do | ||||
|     if _contains "$host" "<host"; then | ||||
|       _namecheap_parse_host "$host" | ||||
|       _namecheap_add_host "$_hostname" "$_hosttype" "$_hostaddress" "$_hostmxpref" "$_hostttl" | ||||
|     fi | ||||
|   done <<EOT | ||||
| echo "$hosts" | ||||
| EOT | ||||
| 
 | ||||
|   _namecheap_add_host "$subdomain" "TXT" "$txt" 10 120 | ||||
| 
 | ||||
|   _debug hostrequestfinal "$_hostrequest" | ||||
| 
 | ||||
|   request="namecheap.domains.dns.setHosts&SLD=${sld}&TLD=${tld}${_hostrequest}" | ||||
| 
 | ||||
|   if ! _namecheap_post "$request"; then | ||||
|     _err "$error" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   return 0 | ||||
| } | ||||
| 
 | ||||
| _del_namecheap_TXT() { | ||||
|   subdomain=$2 | ||||
|   txt=$3 | ||||
|   tld=$(echo "$1" | cut -d '.' -f 2) | ||||
|   sld=$(echo "$1" | cut -d '.' -f 1) | ||||
|   request="namecheap.domains.dns.getHosts&SLD=$sld&TLD=$tld" | ||||
| 
 | ||||
|   if ! _namecheap_post "$request"; then | ||||
|     _err "$error" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   hosts=$(echo "$response" | _egrep_o '<host[^>]*') | ||||
|   _debug hosts "$hosts" | ||||
| 
 | ||||
|   if [ -z "$hosts" ]; then | ||||
|     _error "Hosts not found" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _namecheap_reset_hostList | ||||
| 
 | ||||
|   found=0 | ||||
| 
 | ||||
|   while read -r host; do | ||||
|     if _contains "$host" "<host"; then | ||||
|       _namecheap_parse_host "$host" | ||||
|       if [ "$_hosttype" = "TXT" ] && [ "$_hostname" = "$subdomain" ] && [ "$_hostaddress" = "$txt" ]; then | ||||
|         _debug "TXT entry found" | ||||
|         found=1 | ||||
|       else | ||||
|         _namecheap_add_host "$_hostname" "$_hosttype" "$_hostaddress" "$_hostmxpref" "$_hostttl" | ||||
|       fi | ||||
|     fi | ||||
|   done <<EOT | ||||
| echo "$hosts" | ||||
| EOT | ||||
| 
 | ||||
|   if [ $found -eq 0 ]; then | ||||
|     _debug "TXT entry not found" | ||||
|     return 0 | ||||
|   fi | ||||
| 
 | ||||
|   _debug hostrequestfinal "$_hostrequest" | ||||
| 
 | ||||
|   request="namecheap.domains.dns.setHosts&SLD=${sld}&TLD=${tld}${_hostrequest}" | ||||
| 
 | ||||
|   if ! _namecheap_post "$request"; then | ||||
|     _err "$error" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   return 0 | ||||
| } | ||||
| 
 | ||||
| _namecheap_reset_hostList() { | ||||
|   _hostindex=0 | ||||
|   _hostrequest="" | ||||
| } | ||||
| 
 | ||||
| #Usage: _namecheap_add_host HostName RecordType Address MxPref TTL | ||||
| _namecheap_add_host() { | ||||
|   _hostindex=$(_math "$_hostindex" + 1) | ||||
|   _hostrequest=$(printf '%s&HostName%d=%s&RecordType%d=%s&Address%d=%s&MXPref%d=%d&TTL%d=%d' "$_hostrequest" "$_hostindex" "$1" "$_hostindex" "$2" "$_hostindex" "$3" "$_hostindex" "$4" "$_hostindex" "$5") | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	 neil
						neil