diff --git a/daemon/worker.c b/daemon/worker.c
index a5dd9bc02..b4e50b345 100644
--- a/daemon/worker.c
+++ b/daemon/worker.c
@@ -1550,6 +1550,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
 				return 0;
 			}
 			query_error(c->buffer, LDNS_RCODE_FORMERR, 0);
+			sldns_buffer_copy(c->dnscrypt_buffer, c->buffer);
 			return 1;
 		}
 		dname_str(qinfo.qname, buf);
@@ -1568,6 +1569,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
 			query_error(c->buffer, LDNS_RCODE_SERVFAIL,
 				qinfo.qname_len);
 			worker->stats.num_query_dnscrypt_cleartext++;
+			sldns_buffer_copy(c->dnscrypt_buffer, c->buffer);
 			return 1;
 		}
 		worker->stats.num_query_dnscrypt_cert++;
@@ -1828,7 +1830,13 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
 		server_stats_insquery(&worker->stats, c, qinfo.qtype,
 			qinfo.qclass, &edns, repinfo);
 	if(c->type != comm_udp)
+#ifdef USE_DNSCRYPT
+		edns.udp_size = (c->dnscrypt && repinfo->is_dnscrypted)
+			? sldns_buffer_capacity(c->buffer) - DNSCRYPT_REPLY_HEADER_SIZE
+			: 65535;
+#else
 		edns.udp_size = 65535; /* max size for TCP replies */
+#endif
 	if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo,
 		&edns, repinfo, c->buffer)) {
 		regional_free_all(worker->scratchpad);
@@ -2112,7 +2120,7 @@ send_reply_rc:
 		}
 	}
 #ifdef USE_DNSCRYPT
-	if(!dnsc_handle_uncurved_request(repinfo)) {
+	if(!dnsc_handle_uncurved_request(repinfo, c->buffer)) {
 		return 0;
 	}
 #endif
diff --git a/dnscrypt/dnscrypt.c b/dnscrypt/dnscrypt.c
index 173484cdf..08f9dcb8c 100644
--- a/dnscrypt/dnscrypt.c
+++ b/dnscrypt/dnscrypt.c
@@ -474,10 +474,18 @@ dnscrypt_server_curve(const dnsccert *cert,
     uint8_t *const buf = sldns_buffer_begin(buffer);
     size_t len = sldns_buffer_limit(buffer);
 
+    if(len + DNSCRYPT_REPLY_HEADER_SIZE > sldns_buffer_capacity(buffer))
+	return -1;
+    sldns_buffer_clear(buffer);
+
     if(udp){
         if (max_len > max_reply_size)
             max_len = max_reply_size;
     }
+    if(max_len > sldns_buffer_capacity(buffer))
+	max_len = sldns_buffer_capacity(buffer);
+    if(max_len > 65535)
+	    max_len = 65535;
 
 
     memcpy(nonce, client_nonce, crypto_box_HALF_NONCEBYTES);
@@ -520,6 +528,7 @@ dnscrypt_server_curve(const dnsccert *cert,
                           DNSCRYPT_MAGIC_HEADER_LEN,
                           nonce,
                           crypto_box_NONCEBYTES);
+    sldns_buffer_flip(buffer);
     sldns_buffer_set_limit(buffer, len + DNSCRYPT_REPLY_HEADER_SIZE);
     return 0;
 }
@@ -912,12 +921,13 @@ dnsc_handle_curved_request(struct dnsc_env* dnscenv,
 }
 
 int
-dnsc_handle_uncurved_request(struct comm_reply *repinfo)
+dnsc_handle_uncurved_request(struct comm_reply *repinfo,
+	struct sldns_buffer* buffer)
 {
     if(!repinfo->c->dnscrypt) {
         return 1;
     }
-    sldns_buffer_copy(repinfo->c->dnscrypt_buffer, repinfo->c->buffer);
+    sldns_buffer_copy(repinfo->c->dnscrypt_buffer, buffer);
     if(!repinfo->is_dnscrypted) {
         return 1;
     }
diff --git a/dnscrypt/dnscrypt.h b/dnscrypt/dnscrypt.h
index b0da9b732..998237d48 100644
--- a/dnscrypt/dnscrypt.h
+++ b/dnscrypt/dnscrypt.h
@@ -128,7 +128,8 @@ int dnsc_handle_curved_request(struct dnsc_env* dnscenv,
  * \return 0 in case of failure.
  */
 
-int dnsc_handle_uncurved_request(struct comm_reply *repinfo);
+int dnsc_handle_uncurved_request(struct comm_reply *repinfo,
+	struct sldns_buffer* buffer);
 
 /**
  * Computes the size of the shared secret cache entry.
diff --git a/testdata/dnscrypt_cert.tdir/dnscrypt_cert.test b/testdata/dnscrypt_cert.tdir/dnscrypt_cert.test
index fdb88e8f9..4631d02e1 100644
--- a/testdata/dnscrypt_cert.tdir/dnscrypt_cert.test
+++ b/testdata/dnscrypt_cert.tdir/dnscrypt_cert.test
@@ -9,20 +9,21 @@ PRE="../.."
 
 # do the test
 
-# Query plain request over DNSCrypt channel get closed
-# We use TCP to avoid hanging on waiting for UDP.
-# We expect `outfile` to contain no DNS payload
-echo "> dig TCP www.example.com. DNSCrypt port"
-dig +tcp @127.0.0.1 -p $DNSCRYPT_PORT www.example.com. A | tee outfile
+# Query plain request over DNSCrypt.
+# This used to close the channel; now it returns SERVFAIL.
+# Old: We use TCP to avoid hanging on waiting for UDP.
+#      We expect `outfile` to contain no DNS payload
+echo "> dig www.example.com. DNSCrypt port"
+dig @127.0.0.1 -p $DNSCRYPT_PORT www.example.com. A | tee outfile
 echo "> cat logfiles"
 cat fwd.log
 cat unbound.log
 echo "> check answer"
-if grep "QUESTION SECTION" outfile; then
+if grep "SERVFAIL" outfile; then
+	echo "OK"
+else
 	echo "NOK"
 	exit 1
-else
-	echo "OK"
 fi
 
 
diff --git a/testdata/dnscrypt_cert_chacha.tdir/dnscrypt_cert_chacha.test b/testdata/dnscrypt_cert_chacha.tdir/dnscrypt_cert_chacha.test
index 2db073ad6..a92f196f5 100644
--- a/testdata/dnscrypt_cert_chacha.tdir/dnscrypt_cert_chacha.test
+++ b/testdata/dnscrypt_cert_chacha.tdir/dnscrypt_cert_chacha.test
@@ -9,20 +9,21 @@ PRE="../.."
 
 # do the test
 
-# Query plain request over DNSCrypt channel get closed
-# We use TCP to avoid hanging on waiting for UDP.
-# We expect `outfile` to contain no DNS payload
-echo "> dig TCP www.example.com. DNSCrypt port"
-dig +tcp @127.0.0.1 -p $DNSCRYPT_PORT www.example.com. A | tee outfile
+# Query plain request over DNSCrypt.
+# This used to close the channel; now it returns SERVFAIL.
+# Old: We use TCP to avoid hanging on waiting for UDP.
+#      We expect `outfile` to contain no DNS payload
+echo "> dig www.example.com. DNSCrypt port"
+dig @127.0.0.1 -p $DNSCRYPT_PORT www.example.com. A | tee outfile
 echo "> cat logfiles"
 cat fwd.log
 cat unbound.log
 echo "> check answer"
-if grep "QUESTION SECTION" outfile; then
+if grep "SERVFAIL" outfile; then
+	echo "OK"
+else
 	echo "NOK"
 	exit 1
-else
-	echo "OK"
 fi
 
 
diff --git a/util/netevent.c b/util/netevent.c
index a86e22518..c5287e6c9 100644
--- a/util/netevent.c
+++ b/util/netevent.c
@@ -6685,7 +6685,9 @@ comm_point_send_reply(struct comm_reply *repinfo)
 	log_assert(repinfo && repinfo->c);
 #ifdef USE_DNSCRYPT
 	buffer = repinfo->c->dnscrypt_buffer;
-	if(!dnsc_handle_uncurved_request(repinfo)) {
+	if(!dnsc_handle_uncurved_request(repinfo,
+		repinfo->c->tcp_req_info?
+		repinfo->c->tcp_req_info->spool_buffer:repinfo->c->buffer)) {
 		return;
 	}
 #else
