diff --git a/src/core/dns.c b/src/core/dns.c
index 121ea12..f5744e5 100644
--- a/src/core/dns.c
+++ b/src/core/dns.c
@@ -299,6 +299,7 @@ static u8_t                   dns_seqno;
 static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
 static struct dns_req_entry   dns_requests[DNS_MAX_REQUESTS];
 static ip_addr_t              dns_servers[DNS_MAX_SERVERS];
+static u8_t                   dns_curr_server_idx;
 
 #if LWIP_IPV4
 const ip_addr_t dns_mquery_v4group = DNS_MQUERY_IPV4_GROUP_INIT;
@@ -350,6 +351,22 @@ dns_init(void)
 #endif
 }
 
+/* reset the current server index to the first valid one if servers were changed */
+static void
+dns_reset_curr_server_idx(void)
+{
+  u8_t j;
+
+  for (j = 0; j < DNS_MAX_SERVERS; j++) {
+    if (!ip_addr_isany_val(dns_servers[j])) {
+      dns_curr_server_idx = j;
+      return;
+    }
+  }
+  /* if no valid dns server */
+  dns_curr_server_idx = 0;
+}
+
 /**
  * @ingroup dns
  * Initialize one of the DNS servers.
@@ -366,6 +383,8 @@ dns_setserver(u8_t numdns, const ip_addr_t *dnsserver)
     } else {
       dns_servers[numdns] = *IP_ADDR_ANY;
     }
+
+    dns_reset_curr_server_idx();
   }
 }
 
@@ -1043,10 +1062,23 @@ static u8_t
 dns_backupserver_available(struct dns_table_entry *pentry)
 {
   u8_t ret = 0;
+  u8_t idx;
+  u8_t j;
 
-  if (pentry) {
-    if ((pentry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[pentry->server_idx + 1])) {
-      ret = 1;
+  if (pentry != NULL && pentry->retries < DNS_MAX_RETRIES) {
+    idx = pentry->server_idx;
+
+    for (j = 0; j < DNS_MAX_SERVERS; j++) {
+      idx = (idx + 1) % DNS_MAX_SERVERS;
+
+      if (idx == dns_curr_server_idx) {
+        break;
+      }
+
+      if (!ip_addr_isany_val(dns_servers[idx])) {
+        ret = 1;
+        break;
+      }
     }
   }
 
@@ -1075,8 +1107,8 @@ dns_check_entry(u8_t i)
       /* initialize new entry */
       entry->txid = dns_create_txid();
       entry->state = DNS_STATE_ASKING;
-      entry->server_idx = 0;
-      entry->tmr = 1;
+      entry->server_idx = dns_curr_server_idx;
+      entry->tmr = 2;
       entry->retries = 0;
 
       /* send DNS packet for this entry */
@@ -1088,34 +1120,51 @@ dns_check_entry(u8_t i)
       break;
     case DNS_STATE_ASKING:
       if (--entry->tmr == 0) {
-        if (++entry->retries == DNS_MAX_RETRIES) {
-          if (dns_backupserver_available(entry)
 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
-              && !entry->is_mdns
-#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
-             ) {
-            /* change of server */
-            entry->server_idx++;
-            entry->tmr = 1;
-            entry->retries = 0;
-          } else {
-            LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", entry->name));
+        if (entry->is_mdns) {
+            LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": mDNS timeout\n", entry->name));
             /* call specified callback function if provided */
             dns_call_found(i, NULL);
             /* flush this entry */
             entry->state = DNS_STATE_UNUSED;
+            return;
+        }
+#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
+        /* try the next dns server */
+        u8_t j;
+        u8_t found_new = 0;
+        for (j = 0; j < DNS_MAX_SERVERS; j++) {
+          entry->server_idx = (entry->server_idx + 1) % DNS_MAX_SERVERS;
+          if (entry->server_idx == dns_curr_server_idx) {
             break;
           }
-        } else {
-          /* wait longer for the next retry */
-          entry->tmr = entry->retries;
+          if (!ip_addr_isany_val(dns_servers[entry->server_idx])) {
+            found_new = 1;
+            break;
+          }
+        }
+
+        if (found_new == 0) {
+          /* start a new round */
+          entry->retries++;
+          entry->server_idx = dns_curr_server_idx;
         }
 
-        /* send DNS packet for this entry */
-        err = dns_send(i);
-        if (err != ERR_OK) {
-          LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
-                      ("dns_send returned error: %s\n", lwip_strerr(err)));
+        entry->tmr = entry->retries + 1;
+
+        if (entry->retries < DNS_MAX_RETRIES) {
+          /* send DNS packet for this entry */
+          err = dns_send(i);
+          if (err != ERR_OK) {
+            LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
+                        ("dns_send returned error: %s\n", lwip_strerr(err)));
+          }
+        } else {
+          LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", entry->name));
+          /* call specified callback function if provided */
+          dns_call_found(i, NULL);
+          /* flush this entry */
+          entry->state = DNS_STATE_UNUSED;
         }
       }
       break;
@@ -1168,6 +1217,12 @@ dns_correct_response(u8_t idx, u32_t ttl)
   if (entry->ttl > DNS_MAX_TTL) {
     entry->ttl = DNS_MAX_TTL;
   }
+
+  if (dns_curr_server_idx != entry->server_idx) {
+    /* for the successful dns query, update the current server index */
+    dns_curr_server_idx = entry->server_idx;
+  }
+
   dns_call_found(idx, &entry->ipaddr);
 
   if (entry->ttl == 0) {
@@ -1274,9 +1329,8 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
            * then don't stop the DNS request
            */
           if (dns_backupserver_available(entry)) {
-            /* avoid retrying the same server */
-            entry->retries = DNS_MAX_RETRIES-1;
-            entry->tmr     = 1;
+            /* if recv a bad DNS reply, retry the next available server immediately */
+            entry->tmr = 1;
 
             /* contact next available server for this entry */
             dns_check_entry(i);
