Browse Source

support "--local-address" to specify a listening ip address in standalone mode if the server have multiple ips. By default, the standalone server listens to 0.0.0.0

neil 8 years ago
parent
commit
0463b5d6cd
1 changed files with 138 additions and 70 deletions
  1. 138 70
      acme.sh

+ 138 - 70
acme.sh

@@ -1,6 +1,6 @@
 #!/usr/bin/env sh
 #!/usr/bin/env sh
 
 
-VER=2.5.5
+VER=2.5.6
 
 
 PROJECT_NAME="acme.sh"
 PROJECT_NAME="acme.sh"
 
 
@@ -25,6 +25,8 @@ VTYPE_DNS="dns-01"
 VTYPE_TLS="tls-sni-01"
 VTYPE_TLS="tls-sni-01"
 VTYPE_TLS2="tls-sni-02"
 VTYPE_TLS2="tls-sni-02"
 
 
+LOCAL_ANY_ADDRESS="0.0.0.0"
+
 MAX_RENEW=80
 MAX_RENEW=80
 
 
 DEFAULT_DNS_SLEEP=120
 DEFAULT_DNS_SLEEP=120
@@ -178,6 +180,35 @@ _hasfield() {
   return 1 #not contains 
   return 1 #not contains 
 }
 }
 
 
+_getfield(){
+  _str="$1"
+  _findex="$2"
+  _sep="$3"
+  
+  if [ -z "$_findex" ] ; then
+    _usage "Usage: str field  [sep]"
+    return 1
+  fi
+  
+  if [ -z "$_sep" ] ; then
+    _sep=","
+  fi
+
+  _ffi=$_findex
+  while [ "$_ffi" -gt "0" ]
+  do
+    _fv="$(echo "$_str" |  cut -d $_sep -f $_ffi)"
+    if [ "$_fv" ] ; then
+      printf -- "%s" "$_fv"
+      return 0
+    fi
+    _ffi="$(_math $_ffi - 1)"
+  done
+  
+  printf -- "%s" "$_str"
+
+}
+
 _exists(){
 _exists(){
   cmd="$1"
   cmd="$1"
   if [ -z "$cmd" ] ; then
   if [ -z "$cmd" ] ; then
@@ -559,7 +590,7 @@ _ss() {
     _debug "Using: netstat"
     _debug "Using: netstat"
     if netstat -h 2>&1 | grep "\-p proto" >/dev/null ; then
     if netstat -h 2>&1 | grep "\-p proto" >/dev/null ; then
       #for windows version netstat tool
       #for windows version netstat tool
-      netstat -anb -p tcp | grep "LISTENING" | grep ":$_port "
+      netstat -an -p tcp | grep "LISTENING" | grep ":$_port "
     else
     else
       if netstat -help 2>&1 | grep "\-p protocol" >/dev/null ; then
       if netstat -help 2>&1 | grep "\-p protocol" >/dev/null ; then
         netstat -an -p tcp | grep LISTEN | grep ":$_port "
         netstat -an -p tcp | grep LISTEN | grep ":$_port "
@@ -1134,20 +1165,24 @@ _clearaccountconf() {
   fi
   fi
 }
 }
 
 
+# content localaddress
 _startserver() {
 _startserver() {
   content="$1"
   content="$1"
+  ncaddr="$2"
+  _debug "ncaddr" "$ncaddr"
+
   _debug "startserver: $$"
   _debug "startserver: $$"
   nchelp="$(nc -h 2>&1)"
   nchelp="$(nc -h 2>&1)"
   
   
   if echo "$nchelp" | grep "\-q[ ,]" >/dev/null ; then
   if echo "$nchelp" | grep "\-q[ ,]" >/dev/null ; then
-    _NC="nc -q 1 -l"
+    _NC="nc -q 1 -l $ncaddr"
   else
   else
     if echo "$nchelp" | grep "GNU netcat" >/dev/null && echo "$nchelp" | grep "\-c, \-\-close" >/dev/null ; then
     if echo "$nchelp" | grep "GNU netcat" >/dev/null && echo "$nchelp" | grep "\-c, \-\-close" >/dev/null ; then
-      _NC="nc -c -l"
+      _NC="nc -c -l $ncaddr"
     elif echo "$nchelp" | grep "\-N" |grep "Shutdown the network socket after EOF on stdin"  >/dev/null ; then
     elif echo "$nchelp" | grep "\-N" |grep "Shutdown the network socket after EOF on stdin"  >/dev/null ; then
-      _NC="nc -N -l"
+      _NC="nc -N -l $ncaddr"
     else
     else
-      _NC="nc -l"
+      _NC="nc -l $ncaddr"
     fi
     fi
   fi
   fi
 
 
@@ -1234,7 +1269,7 @@ _starttlsserver() {
   fi
   fi
   
   
   #start openssl
   #start openssl
-  _debug "openssl s_server -cert \"$TLS_CERT\"  -key \"$TLS_KEY\" -accept $port -naccept 1 -tlsextdebug"
+  _debug "openssl s_server -cert \"$TLS_CERT\"  -key \"$TLS_KEY\" -accept $port  -tlsextdebug"
   if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ] ; then
   if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ] ; then
     (printf "HTTP/1.1 200 OK\r\n\r\n$content" | openssl s_server -cert "$TLS_CERT"  -key "$TLS_KEY" -accept $port -tlsextdebug ) &
     (printf "HTTP/1.1 200 OK\r\n\r\n$content" | openssl s_server -cert "$TLS_CERT"  -key "$TLS_KEY" -accept $port -tlsextdebug ) &
   else
   else
@@ -1609,6 +1644,78 @@ _clearupwebbroot() {
 }
 }
 
 
 _on_before_issue() {
 _on_before_issue() {
+
+  if _hasfield "$Le_Webroot" "$NO_VALUE" ; then
+    if ! _exists "nc" ; then
+      _err "Please install netcat(nc) tools first."
+      return 1
+    fi
+  elif ! _hasfield "$Le_Webroot" "$W_TLS" ; then
+    #no need to check anymore
+    return 0
+  fi
+
+  _debug Le_LocalAddress "$Le_LocalAddress"
+  
+  alldomains=$(echo "$Le_Domain,$Le_Alt" |  tr ',' ' ' )
+  _index=1
+  _currentRoot=""
+  _addrIndex=1
+  for d in $alldomains   
+  do
+    _debug "Check for domain" $d
+    _currentRoot="$(_getfield "$Le_Webroot" $_index)"
+    _debug "_currentRoot" "$_currentRoot"
+    _index=$(_math $_index + 1)
+    _checkport=""
+    if [ "$_currentRoot" = "$NO_VALUE" ] ; then
+      _info "Standalone mode."
+      if [ -z "$Le_HTTPPort" ] ; then
+        Le_HTTPPort=80
+      else
+        _savedomainconf "Le_HTTPPort"  "$Le_HTTPPort"
+      fi
+      _checkport="$Le_HTTPPort"
+    elif [ "$_currentRoot" = "$W_TLS" ] ; then
+      _info "Standalone tls mode."
+      if [ -z "$Le_TLSPort" ] ; then
+        Le_TLSPort=443
+      else
+        _savedomainconf "Le_TLSPort"  "$Le_TLSPort"
+      fi
+      _checkport="$Le_TLSPort"
+    fi
+    
+    if [ "$_checkport" ] ; then
+      _debug _checkport "$_checkport"
+      _checkaddr="$(_getfield "$Le_LocalAddress" $_addrIndex)"
+      _debug _checkaddr "$_checkaddr"
+      
+      _addrIndex="$(_math $_addrIndex + 1)"
+      
+      _netprc="$(_ss "$_checkport" | grep "$_checkport")"
+      netprc="$(echo "$_netprc" | grep "$_checkaddr")"
+      if [ -z "$netprc" ] ; then
+        netprc="$(echo "$_netprc" | grep "$LOCAL_ANY_ADDRESS")"
+      fi
+      if [ "$netprc" ] ; then
+        _err "$netprc"
+        _err "tcp port $_checkport is already used by $(echo "$netprc" | cut -d :  -f 4)"
+        _err "Please stop it first"
+        return 1
+      fi
+    fi
+  done
+
+  if _hasfield "$Le_Webroot" "apache" ; then
+    if ! _setApache ; then
+      _err "set up apache error. Report error to me."
+      return 1
+    fi
+  else
+    usingApache=""
+  fi
+
   #run pre hook
   #run pre hook
   if [ "$Le_PreHook" ] ; then
   if [ "$Le_PreHook" ] ; then
     _info "Run pre hook:'$Le_PreHook'"
     _info "Run pre hook:'$Le_PreHook'"
@@ -1678,6 +1785,7 @@ issue() {
   Le_PreHook="${10}"
   Le_PreHook="${10}"
   Le_PostHook="${11}"
   Le_PostHook="${11}"
   Le_RenewHook="${12}"
   Le_RenewHook="${12}"
+  Le_LocalAddress="${13}"
   
   
   #remove these later.
   #remove these later.
   if [ "$Le_Webroot" = "dns-cf" ] ; then
   if [ "$Le_Webroot" = "dns-cf" ] ; then
@@ -1712,69 +1820,17 @@ issue() {
   _savedomainconf "Le_PreHook"      "$Le_PreHook"
   _savedomainconf "Le_PreHook"      "$Le_PreHook"
   _savedomainconf "Le_PostHook"     "$Le_PostHook"
   _savedomainconf "Le_PostHook"     "$Le_PostHook"
   _savedomainconf "Le_RenewHook"     "$Le_RenewHook"
   _savedomainconf "Le_RenewHook"     "$Le_RenewHook"
-
-  if ! _on_before_issue ; then
-    _err "_on_before_issue."
-    return 1
-  fi
-
+  _savedomainconf "Le_LocalAddress"     "$Le_LocalAddress"
+  
   if [ "$Le_Alt" = "$NO_VALUE" ] ; then
   if [ "$Le_Alt" = "$NO_VALUE" ] ; then
     Le_Alt=""
     Le_Alt=""
   fi
   fi
-
-  if _hasfield "$Le_Webroot" "$NO_VALUE" ; then
-    _info "Standalone mode."
-    if ! _exists "nc" ; then
-      _err "Please install netcat(nc) tools first."
-      _on_issue_err
-      return 1
-    fi
-    
-    if [ -z "$Le_HTTPPort" ] ; then
-      Le_HTTPPort=80
-    else
-      _savedomainconf "Le_HTTPPort"  "$Le_HTTPPort"
-    fi    
-    
-    netprc="$(_ss "$Le_HTTPPort" | grep "$Le_HTTPPort")"
-    if [ "$netprc" ] ; then
-      _err "$netprc"
-      _err "tcp port $Le_HTTPPort is already used by $(echo "$netprc" | cut -d :  -f 4)"
-      _err "Please stop it first"
-      _on_issue_err
-      return 1
-    fi
-  fi
   
   
-  if _hasfield "$Le_Webroot" "$W_TLS" ; then
-    _info "Standalone tls mode."
-    
-    if [ -z "$Le_TLSPort" ] ; then
-      Le_TLSPort=443
-    else
-      _savedomainconf "Le_TLSPort"  "$Le_TLSPort"
-    fi    
-    
-    netprc="$(_ss "$Le_TLSPort" | grep "$Le_TLSPort")"
-    if [ "$netprc" ] ; then
-      _err "$netprc"
-      _err "tcp port $Le_TLSPort is already used by $(echo "$netprc" | cut -d :  -f 4)"
-      _err "Please stop it first"
-      _on_issue_err
-      return 1
-    fi
-  fi
-  
-  if _hasfield "$Le_Webroot" "apache" ; then
-    if ! _setApache ; then
-      _err "set up apache error. Report error to me."
-      _on_issue_err
-      return 1
-    fi
-  else
-    usingApache=""
+  if ! _on_before_issue ; then
+    _err "_on_before_issue."
+    return 1
   fi
   fi
-  
+
   if [ ! -f "$ACCOUNT_KEY_PATH" ] ; then
   if [ ! -f "$ACCOUNT_KEY_PATH" ] ; then
     _acck="$NO_VALUE"
     _acck="$NO_VALUE"
     if [ "$Le_Keylength" ] ; then
     if [ "$Le_Keylength" ] ; then
@@ -1869,7 +1925,7 @@ issue() {
     do
     do
       _info "Getting webroot for domain" $d
       _info "Getting webroot for domain" $d
       _w="$(echo $Le_Webroot | cut -d , -f $_index)"
       _w="$(echo $Le_Webroot | cut -d , -f $_index)"
-      _debug _w "$_w"
+      _info _w "$_w"
       if [ "$_w" ] ; then
       if [ "$_w" ] ; then
         _currentRoot="$_w"
         _currentRoot="$_w"
       fi
       fi
@@ -2037,6 +2093,7 @@ issue() {
   
   
   _debug "ok, let's start to verify"
   _debug "ok, let's start to verify"
 
 
+  _ncIndex=1
   ventries=$(echo "$vlist" |  tr ',' ' ' )
   ventries=$(echo "$vlist" |  tr ',' ' ' )
   for ventry in $ventries
   for ventry in $ventries
   do
   do
@@ -2064,7 +2121,9 @@ issue() {
     if [ "$vtype" = "$VTYPE_HTTP" ] ; then
     if [ "$vtype" = "$VTYPE_HTTP" ] ; then
       if [ "$_currentRoot" = "$NO_VALUE" ] ; then
       if [ "$_currentRoot" = "$NO_VALUE" ] ; then
         _info "Standalone mode server"
         _info "Standalone mode server"
-        _startserver "$keyauthorization" &
+        _ncaddr="$(_getfield "$Le_LocalAddress" "$_ncIndex" )"
+        _ncIndex="$(_math $_ncIndex + 1)"
+        _startserver "$keyauthorization" "$_ncaddr" &
         if [ "$?" != "0" ] ; then
         if [ "$?" != "0" ] ; then
           _clearup
           _clearup
           _on_issue_err
           _on_issue_err
@@ -2129,7 +2188,9 @@ issue() {
       _SAN_B="$_x.$_y.acme.invalid"
       _SAN_B="$_x.$_y.acme.invalid"
       _debug2 _SAN_B "$_SAN_B"
       _debug2 _SAN_B "$_SAN_B"
       
       
-      if ! _starttlsserver "$_SAN_B" "$_SAN_A" "$Le_TLSPort" "$keyauthorization" ; then
+      _ncaddr="$(_getfield "$Le_LocalAddress" "$_ncIndex" )"
+      _ncIndex="$(_math $_ncIndex + 1)"
+      if ! _starttlsserver "$_SAN_B" "$_SAN_A" "$Le_TLSPort" "$keyauthorization" "$_ncaddr"; then
         _err "Start tls server error."
         _err "Start tls server error."
         _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
         _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
         _clearup
         _clearup
@@ -2362,7 +2423,7 @@ renew() {
   fi
   fi
   
   
   IS_RENEW="1"
   IS_RENEW="1"
-  issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" "$Le_PreHook" "$Le_PostHook" "$Le_RenewHook"
+  issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" "$Le_PreHook" "$Le_PostHook" "$Le_RenewHook" "$Le_LocalAddress"
   res=$?
   res=$?
   IS_RENEW=""
   IS_RENEW=""
 
 
@@ -3215,6 +3276,7 @@ Parameters:
   --days                            Specifies the days to renew the cert when using '--issue' command. The max value is $MAX_RENEW days.
   --days                            Specifies the days to renew the cert when using '--issue' command. The max value is $MAX_RENEW days.
   --httpport                        Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer.
   --httpport                        Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer.
   --tlsport                         Specifies the standalone tls listening port. Only valid if the server is behind a reverse proxy or load balancer.
   --tlsport                         Specifies the standalone tls listening port. Only valid if the server is behind a reverse proxy or load balancer.
+  --local-address                   Specifies the standalone server listening address, in case you have multiple ip addresses.
   --listraw                         Only used for '--list' command, list the certs in raw format.
   --listraw                         Only used for '--list' command, list the certs in raw format.
   --stopRenewOnError, -se           Only valid for '--renewall' command. Stop if one cert has error in renewal.
   --stopRenewOnError, -se           Only valid for '--renewall' command. Stop if one cert has error in renewal.
   --insecure                        Do not check the server certificate, in some devices, the api server's certificate may not be trusted.
   --insecure                        Do not check the server certificate, in some devices, the api server's certificate may not be trusted.
@@ -3324,6 +3386,7 @@ _process() {
   _renew_hook=""
   _renew_hook=""
   _logfile=""
   _logfile=""
   _log=""
   _log=""
+  _local_address=""
   while [ ${#} -gt 0 ] ; do
   while [ ${#} -gt 0 ] ; do
     case "${1}" in
     case "${1}" in
     
     
@@ -3447,6 +3510,11 @@ _process() {
           _webroot="$_webroot,$wvalue"
           _webroot="$_webroot,$wvalue"
         fi
         fi
         ;;
         ;;
+    --local-address)
+        lvalue="$2"
+        _local_address="$_local_address$lvalue,"
+        shift
+        ;;
     --apache)
     --apache)
         wvalue="apache"
         wvalue="apache"
         if [ -z "$_webroot" ] ; then
         if [ -z "$_webroot" ] ; then
@@ -3643,7 +3711,7 @@ _process() {
     uninstall) uninstall "$_nocron" ;;
     uninstall) uninstall "$_nocron" ;;
     upgrade) upgrade ;;
     upgrade) upgrade ;;
     issue)
     issue)
-      issue  "$_webroot"  "$_domain" "$_altdomains" "$_keylength" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath" "$_pre_hook" "$_post_hook" "$_renew_hook"
+      issue  "$_webroot"  "$_domain" "$_altdomains" "$_keylength" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address"
       ;;
       ;;
     signcsr)
     signcsr)
       signcsr "$_csr" "$_webroot"
       signcsr "$_csr" "$_webroot"