diff --git a/libknet/internals.h b/libknet/internals.h
index 762c0d4..1da9e12 100644
--- a/libknet/internals.h
+++ b/libknet/internals.h
@@ -52,6 +52,8 @@ struct knet_link {
 	uint8_t  priority;			/* higher priority == preferred for A/P */
 	unsigned long long ping_interval;	/* interval */
 	unsigned long long pong_timeout;	/* timeout */
+	unsigned long long pong_timeout_adj;	/* timeout adjusted for latency */
+	uint8_t pong_timeout_backoff;		/* something undocumented for now */
 	unsigned int latency_fix;		/* precision */
 	uint8_t pong_count;			/* how many ping/pong to send/receive before link is up */
 	uint64_t flags;
diff --git a/libknet/links.c b/libknet/links.c
index 38c5b19..bdd36e8 100644
--- a/libknet/links.c
+++ b/libknet/links.c
@@ -215,6 +215,8 @@ int knet_link_set_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t l
 	link->has_valid_mtu = 0;
 	link->ping_interval = KNET_LINK_DEFAULT_PING_INTERVAL * 1000; /* microseconds */
 	link->pong_timeout = KNET_LINK_DEFAULT_PING_TIMEOUT * 1000; /* microseconds */
+	link->pong_timeout_backoff = 10;
+	link->pong_timeout_adj = link->pong_timeout * link->pong_timeout_backoff; /* microseconds */
 	link->latency_fix = KNET_LINK_DEFAULT_PING_PRECISION;
 	link->latency_exp = KNET_LINK_DEFAULT_PING_PRECISION - \
 			    ((link->ping_interval * KNET_LINK_DEFAULT_PING_PRECISION) / 8000000);
diff --git a/libknet/tests/api_knet_send_crypto.c b/libknet/tests/api_knet_send_crypto.c
index 77477b3..99ed96a 100644
--- a/libknet/tests/api_knet_send_crypto.c
+++ b/libknet/tests/api_knet_send_crypto.c
@@ -142,7 +142,7 @@ static void test(const char *model)
 		exit(FAIL);
 	}
 
-	if (wait_for_host(knet_h, 1, 10, logfds[0], stdout) < 0) {
+	if (wait_for_host(knet_h, 1, 60, logfds[0], stdout) < 0) {
 		printf("timeout waiting for host to be reachable");
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
@@ -250,11 +250,6 @@ int main(int argc, char *argv[])
 {
 	need_root();
 
-	test("none");
-
-#ifdef BUILDCRYPTONSS
-	test("nss");
-#endif
 #ifdef BUILDCRYPTOOPENSSL
 	test("openssl");
 #endif
diff --git a/libknet/threads_heartbeat.c b/libknet/threads_heartbeat.c
index bc68402..2971454 100644
--- a/libknet/threads_heartbeat.c
+++ b/libknet/threads_heartbeat.c
@@ -117,7 +117,7 @@ retry:
 
 	timespec_diff(pong_last, clock_now, &diff_ping);
 	if ((pong_last.tv_nsec) && 
-	    (diff_ping >= (dst_link->pong_timeout * 1000llu))) {
+	    (diff_ping >= (dst_link->pong_timeout_adj * 1000llu))) {
 		_link_down(knet_h, dst_host, dst_link);
 	}
 }
@@ -147,9 +147,48 @@ void _send_pings(knet_handle_t knet_h, int timed)
 	pthread_mutex_unlock(&knet_h->hb_mutex);
 }
 
+static void _adjust_pong_timeouts(knet_handle_t knet_h)
+{
+	struct knet_host *dst_host;
+	struct knet_link *dst_link;
+	int link_idx;
+
+	log_debug(knet_h, KNET_SUB_HEARTBEAT, "ADJUSTING PONG_TIMEOUTS");
+
+	if (pthread_rwlock_wrlock(&knet_h->global_rwlock) != 0) {
+		log_debug(knet_h, KNET_SUB_HEARTBEAT, "Unable to get write lock");
+		return;
+	}
+
+	for (dst_host = knet_h->host_head; dst_host != NULL; dst_host = dst_host->next) {
+		for (link_idx = 0; link_idx < KNET_MAX_LINK; link_idx++) {
+			if ((dst_host->link[link_idx].status.enabled != 1) ||
+			    (dst_host->link[link_idx].transport_type == KNET_TRANSPORT_LOOPBACK ) ||
+			    ((dst_host->link[link_idx].dynamic == KNET_LINK_DYNIP) &&
+			     (dst_host->link[link_idx].status.dynconnected != 1)))
+				continue;
+
+			log_debug(knet_h, KNET_SUB_HEARTBEAT, "Adjusting host %u link %i", dst_host->host_id, link_idx);
+			dst_link = &dst_host->link[link_idx];
+			log_debug(knet_h, KNET_SUB_HEARTBEAT, "current: %llu", dst_link->pong_timeout_adj);
+
+			if (dst_link->pong_timeout_backoff > 1) {
+				dst_link->pong_timeout_backoff--;
+			}
+
+			dst_link->pong_timeout_adj = (dst_link->pong_timeout * dst_link->pong_timeout_backoff) + (dst_link->status.stats.latency_max * 2);
+
+			log_debug(knet_h, KNET_SUB_HEARTBEAT, "new: %llu", dst_link->pong_timeout_adj);
+		}
+	}
+
+	pthread_rwlock_unlock(&knet_h->global_rwlock);
+}
+
 void *_handle_heartbt_thread(void *data)
 {
 	knet_handle_t knet_h = (knet_handle_t) data;
+	int i = 1;
 
 	/* preparing ping buffer */
 	knet_h->pingbuf->kh_version = KNET_HEADER_VERSION;
@@ -159,6 +198,16 @@ void *_handle_heartbt_thread(void *data)
 	while (!shutdown_in_progress(knet_h)) {
 		usleep(KNET_THREADS_TIMERES);
 
+		/*
+		 * this should execute approx once a second.
+		 */
+		if ((i % (1000000 / KNET_THREADS_TIMERES)) == 0) {
+			_adjust_pong_timeouts(knet_h);
+			i = 1;
+		} else {
+			i++;
+		}
+
 		if (pthread_rwlock_rdlock(&knet_h->global_rwlock) != 0) {
 			log_debug(knet_h, KNET_SUB_HEARTBEAT, "Unable to get read lock");
 			continue;
diff --git a/libknet/threads_pmtud.c b/libknet/threads_pmtud.c
index 3ef75dc..c209cfc 100644
--- a/libknet/threads_pmtud.c
+++ b/libknet/threads_pmtud.c
@@ -204,8 +204,8 @@ retry:
 		 * and add values to it that could overflow into seconds.
 		 */ 
 
-		ts.tv_sec += dst_link->pong_timeout / 1000000;
-		ts.tv_nsec += (((dst_link->pong_timeout) % 1000000) * 1000);
+		ts.tv_sec += dst_link->pong_timeout_adj / 1000000;
+		ts.tv_nsec += (((dst_link->pong_timeout_adj) % 1000000) * 1000);
 		while (ts.tv_nsec > 1000000000) {
 			ts.tv_sec += 1;
 			ts.tv_nsec -= 1000000000;
diff --git a/libknet/threads_rx.c b/libknet/threads_rx.c
index 95b23c3..fb2458a 100644
--- a/libknet/threads_rx.c
+++ b/libknet/threads_rx.c
@@ -607,7 +607,7 @@ retry_pong:
 				(src_link->latency_fix - src_link->latency_exp))) /
 					src_link->latency_fix;
 
-		if (src_link->status.latency < src_link->pong_timeout) {
+		if (src_link->status.latency < src_link->pong_timeout_adj) {
 			if (!src_link->status.connected) {
 				if (src_link->received_pong >= src_link->pong_count) {
 					log_info(knet_h, KNET_SUB_RX, "host: %u link: %u is up",
