diff --git a/doc/man/kdig.1in b/doc/man/kdig.1in
index 7670f9f1b3f4affe3b2a59bbf14f09e98ae60cbf..f4472bde42ccfb4901ed981596c8e75cbca43c9f 100644
--- a/doc/man/kdig.1in
+++ b/doc/man/kdig.1in
@@ -207,6 +207,13 @@ Request the nameserver identifier (NSID).
 \fB+\fP[\fBno\fP]\fBbufsize\fP=\fIB\fP
 Set the EDNS buffer size in bytes (default is 512 bytes).
 .TP
+\fB+\fP[\fBno\fP]\fBpadding\fP=\fIB\fP
+Set EDNS(0) padding option data length (default is no).
+.TP
+\fB+\fP[\fBno\fP]\fBalignment\fP[=\fIB\fP]
+Align the query to B\-byte\-block message using the EDNS(0) padding option
+(default is no or 128 if no argument is specified).
+.TP
 \fB+\fP[\fBno\fP]\fBclient\fP=\fISUBN\fP
 Set the EDNS client subnet SUBN=IP/prefix.
 .TP
diff --git a/doc/man_kdig.rst b/doc/man_kdig.rst
index 52e33fb292b0f56b3a49b35155f8f658f39085ee..0ada1822ccb61baf38b8ad34b7f7835bc90710fe 100644
--- a/doc/man_kdig.rst
+++ b/doc/man_kdig.rst
@@ -184,6 +184,13 @@ Options
 **+**\ [\ **no**\ ]\ **bufsize**\ =\ *B*
   Set the EDNS buffer size in bytes (default is 512 bytes).
 
+**+**\ [\ **no**\ ]\ **padding**\ =\ *B*
+  Set EDNS(0) padding option data length (default is no).
+
+**+**\ [\ **no**\ ]\ **alignment**\[\ =\ *B*\]
+  Align the query to B\-byte-block message using the EDNS(0) padding option
+  (default is no or 128 if no argument is specified).
+
 **+**\ [\ **no**\ ]\ **client**\ =\ *SUBN*
   Set the EDNS client subnet SUBN=IP/prefix.
 
diff --git a/src/libknot/rrtype/opt.h b/src/libknot/rrtype/opt.h
index b16eb5384ca6bdfb1d762a7eda1bb7cfd1749962..76a1305b6ea7ee2030b7369789ec1e756f0d4615 100644
--- a/src/libknot/rrtype/opt.h
+++ b/src/libknot/rrtype/opt.h
@@ -24,6 +24,8 @@
 
 #pragma once
 
+#include <assert.h>
+
 #include "libknot/consts.h"
 #include "libknot/rrset.h"
 
@@ -53,7 +55,9 @@ enum knot_edns_const {
 	/*! \brief EDNS client subnet option code. */
 	KNOT_EDNS_OPTION_CLIENT_SUBNET = 8,
 	/*! \brief EDNS DNS Cookie option code. */
-	KNOT_EDNS_OPTION_COOKIE        = 10
+	KNOT_EDNS_OPTION_COOKIE        = 10,
+	/*! \brief EDNS Padding option code. */
+	KNOT_EDNS_OPTION_PADDING       = 12
 };
 
 /* Helpers for splitting extended RCODE. */
@@ -385,4 +389,31 @@ int knot_edns_client_subnet_parse(const uint8_t *data,
                                   uint16_t *addr_len,
                                   uint8_t *src_mask,
                                   uint8_t *dst_mask);
+
+/*!
+ * \brief Computes additional Padding data length for required packet alignment.
+ *
+ * \param current_pkt_size  Current packet size.
+ * \param current_opt_size  Current OPT rrset size (OPT must be used).
+ * \param block_size        Required packet block length (must be non-zero).
+ *
+ * \return Required padding length or -1 if padding not required.
+ */
+static inline int knot_edns_alignment_size(size_t current_pkt_size,
+                                           size_t current_opt_size,
+                                           size_t block_size)
+{
+	assert(current_opt_size > 0);
+	assert(block_size > 0);
+
+	size_t current_size = current_pkt_size + current_opt_size;
+	if (current_size % block_size == 0) {
+		return -1;
+	}
+
+	size_t modulo = (current_size + KNOT_EDNS_OPTION_HDRLEN) % block_size;
+
+	return (modulo == 0) ? 0 : block_size - modulo;
+}
+
 /*! @} */
diff --git a/src/utils/common/exec.c b/src/utils/common/exec.c
index eb00fc1e803463e5fa39d285fee8ae3efacac96d..1362c4155f011d3c598f7e7fe1982c322b4d3f41 100644
--- a/src/utils/common/exec.c
+++ b/src/utils/common/exec.c
@@ -262,6 +262,9 @@ static void print_section_opt(const knot_rrset_t *rr, const uint8_t rcode)
 			printf(";; CLIENT-SUBNET: ");
 			print_edns_client_subnet(opt_data, opt_len);
 			break;
+		case KNOT_EDNS_OPTION_PADDING:
+			printf(";; PADDING: %u B\n", opt_len);
+			break;
 		default:
 			printf(";; Option (%u): ", opt_code);
 			short_hex_print(opt_data, opt_len);
@@ -462,7 +465,7 @@ static void print_error_host(const uint16_t   code,
 	free(owner);
 }
 
-knot_pkt_t *create_empty_packet(const size_t max_size)
+knot_pkt_t *create_empty_packet(const uint16_t max_size)
 {
 	// Create packet skeleton.
 	knot_pkt_t *packet = knot_pkt_new(NULL, max_size, NULL);
diff --git a/src/utils/common/exec.h b/src/utils/common/exec.h
index 90e5aea54baa37a710fa1580d208fd4ae3b6a986..0c5ad5dfb9d8ffdad6ea5ee3ac140c6b24f92e60 100644
--- a/src/utils/common/exec.h
+++ b/src/utils/common/exec.h
@@ -38,7 +38,7 @@
  * \retval packet	if success.
  * \retval NULL		if error.
  */
-knot_pkt_t *create_empty_packet(const size_t max_size);
+knot_pkt_t *create_empty_packet(const uint16_t max_size);
 
 /*!
  * \brief Prints information header for transfer.
diff --git a/src/utils/kdig/kdig_exec.c b/src/utils/kdig/kdig_exec.c
index d2821c9d3f48f84e50ded48b51b97511a656da79..5b9ecc3ceef7abee25bcd41b2c56b9b5f8ec4b81 100644
--- a/src/utils/kdig/kdig_exec.c
+++ b/src/utils/kdig/kdig_exec.c
@@ -270,6 +270,25 @@ static int add_query_edns(knot_pkt_t *packet, const query_t *query, uint16_t max
 		}
 	}
 
+	/* Append EDNS Padding. */
+	int padding = query->padding;
+	if (query->alignment > 0) {
+		padding = knot_edns_alignment_size(packet->size,
+		                                   knot_rrset_size(&opt_rr),
+		                                   query->alignment);
+	}
+	if (padding > -1) {
+		uint8_t zeros[padding];
+		memset(zeros, 0, sizeof(zeros));
+
+		ret = knot_edns_add_option(&opt_rr, KNOT_EDNS_OPTION_PADDING,
+		                           padding, zeros, &packet->mm);
+		if (ret != KNOT_EOK) {
+			knot_rrset_clear(&opt_rr, &packet->mm);
+			return ret;
+		}
+	}
+
 	/* Add prepared OPT to packet. */
 	ret = knot_pkt_put(packet, KNOT_COMPR_HINT_NONE, &opt_rr, KNOT_PF_FREE);
 	if (ret != KNOT_EOK) {
@@ -282,7 +301,8 @@ static int add_query_edns(knot_pkt_t *packet, const query_t *query, uint16_t max
 static bool use_edns(const query_t *query)
 {
 	return query->edns > -1 || query->udp_size > -1 || query->nsid ||
-	       query->flags.do_flag || query->subnet != NULL;
+	       query->flags.do_flag || query->subnet != NULL ||
+	       query->padding > -1 || query->alignment > 0;
 }
 
 static knot_pkt_t *create_query_packet(const query_t *query)
diff --git a/src/utils/kdig/kdig_params.c b/src/utils/kdig/kdig_params.c
index 6a298f7de8609f56dbd15b2ec91654adfdea0862..ebeb0eacf90f0d90ba950a27e79ba3e8d496ecf4 100644
--- a/src/utils/kdig/kdig_params.c
+++ b/src/utils/kdig/kdig_params.c
@@ -35,6 +35,7 @@
 
 #define DEFAULT_RETRIES_DIG	2
 #define DEFAULT_TIMEOUT_DIG	5
+#define DEFAULT_ALIGNMENT_SIZE	128
 
 static const flags_t DEFAULT_FLAGS_DIG = {
 	.aa_flag = false,
@@ -596,6 +597,58 @@ static int opt_nobufsize(const char *arg, void *query)
 	return KNOT_EOK;
 }
 
+static int opt_padding(const char *arg, void *query)
+{
+	query_t *q = query;
+
+	uint16_t num;
+	if (str_to_u16(arg, &num) != KNOT_EOK) {
+		ERR("invalid +padding=%s\n", arg);
+		return KNOT_EINVAL;
+	}
+
+	q->padding = num;
+
+	return KNOT_EOK;
+}
+
+static int opt_nopadding(const char *arg, void *query)
+{
+	query_t *q = query;
+
+	q->padding = -1;
+
+	return KNOT_EOK;
+}
+
+static int opt_alignment(const char *arg, void *query)
+{
+	query_t *q = query;
+
+	if (arg == NULL) {
+		q->alignment = DEFAULT_ALIGNMENT_SIZE;
+		return KNOT_EOK;
+	} else {
+		uint16_t num;
+		if (str_to_u16(arg, &num) != KNOT_EOK || num < 2) {
+			ERR("invalid +alignment=%s\n", arg);
+			return KNOT_EINVAL;
+		}
+
+		q->alignment = num;
+		return KNOT_EOK;
+	}
+}
+
+static int opt_noalignment(const char *arg, void *query)
+{
+	query_t *q = query;
+
+	q->alignment = 0;
+
+	return KNOT_EOK;
+}
+
 static int opt_client(const char *arg, void *query)
 {
 	query_t *q = query;
@@ -693,6 +746,8 @@ static int opt_noedns(const char *arg, void *query)
 	opt_nodoflag(arg, query);
 	opt_nonsid(arg, query);
 	opt_nobufsize(arg, query);
+	opt_nopadding(arg, query);
+	opt_noalignment(arg, query);
 	opt_noclient(arg, query);
 
 	return KNOT_EOK;
@@ -835,6 +890,12 @@ static const param_t kdig_opts2[] = {
 	{ "bufsize",      ARG_REQUIRED, opt_bufsize },
 	{ "nobufsize",    ARG_NONE,     opt_nobufsize },
 
+	{ "padding",      ARG_REQUIRED, opt_padding },
+	{ "nopadding",    ARG_NONE,     opt_nopadding },
+
+	{ "alignment",    ARG_OPTIONAL, opt_alignment },
+	{ "noalignment",  ARG_NONE,     opt_noalignment },
+
 	{ "client",       ARG_REQUIRED, opt_client },
 	{ "noclient",     ARG_NONE,     opt_noclient },
 
@@ -895,6 +956,8 @@ query_t *query_create(const char *owner, const query_t *conf)
 		query->idn = true;
 		query->nsid = false;
 		query->edns = -1;
+		query->padding = -1;
+		query->alignment = 0;
 		//query->tsig_key
 		query->subnet = NULL;
 #if USE_DNSTAP
@@ -930,6 +993,8 @@ query_t *query_create(const char *owner, const query_t *conf)
 		query->idn = conf->idn;
 		query->nsid = conf->nsid;
 		query->edns = conf->edns;
+		query->padding = conf->padding;
+		query->alignment = conf->alignment;
 		if (conf->tsig_key.name != NULL) {
 			int ret = knot_tsig_key_copy(&query->tsig_key,
 			                             &conf->tsig_key);
@@ -1410,6 +1475,8 @@ static void print_help(void)
 	       "       +[no]ignore        Don't use TCP automatically if truncated.\n"
 	       "       +[no]nsid          Request NSID.\n"
 	       "       +[no]bufsize=B     Set EDNS buffer size.\n"
+	       "       +[no]padding=N     Padding block size EDNS(0) padding.\n"
+	       "       +[no]alignment(=N) Set packet alignment with EDNS(0) padding.\n"
 	       "       +[no]client=SUBN   Set EDNS(0) client subnet IP/prefix.\n"
 	       "       +[no]edns(=N)      Use EDNS (=version).\n"
 	       "       +[no]time=T        Set wait for reply interval in seconds.\n"
diff --git a/src/utils/kdig/kdig_params.h b/src/utils/kdig/kdig_params.h
index f08c69d33ae5bd20df23ba55d7962493cb0bddcc..5b5d5e7165db325206594220b7f09520dc480043 100644
--- a/src/utils/kdig/kdig_params.h
+++ b/src/utils/kdig/kdig_params.h
@@ -132,6 +132,10 @@ struct query {
 	knot_tsig_key_t tsig_key;
 	/*!< EDNS client subnet. */
 	subnet_t	*subnet;
+	/*!< EDNS0 padding (16unsigned + -1 uninitialized). */
+	int32_t		padding;
+	/*!< Query alignment with EDNS0 padding (0 ~ uninitialized). */
+	uint16_t	alignment;
 #if USE_DNSTAP
 	/*!< Context for dnstap reader input. */
 	dt_reader_t	*dt_reader;
diff --git a/tests/libknot/test_edns.c b/tests/libknot/test_edns.c
index bb67ccad08799375b3c5dbd2272e55221a762983..e52360d2830f36199a183d736734b3ac319d69b7 100644
--- a/tests/libknot/test_edns.c
+++ b/tests/libknot/test_edns.c
@@ -826,6 +826,26 @@ static void test_client_subnet()
            "EDNS-client-subnet: parse (cmp addr)");
 }
 
+static void test_alignment()
+{
+	int ret;
+
+	ret = knot_edns_alignment_size(1, 1, 1);
+	ok(ret == -1, "no alignment");
+
+	ret = knot_edns_alignment_size(1, 1, 2);
+	ok(ret == -1, "no alignment");
+
+	ret = knot_edns_alignment_size(1, 1, 3);
+	ok(ret == (6 - (1 + 1 + KNOT_EDNS_OPTION_HDRLEN)), "%i-Byte alignment", ret);
+
+	ret = knot_edns_alignment_size(1, 1, 4);
+	ok(ret == (8 - (1 + 1 + KNOT_EDNS_OPTION_HDRLEN)), "%i-Byte alignment", ret);
+
+	ret = knot_edns_alignment_size(1, 1, 512);
+	ok(ret == (512 - (1 + 1 + KNOT_EDNS_OPTION_HDRLEN)), "%i-Byte alignment", ret);
+}
+
 int main(int argc, char *argv[])
 {
 	plan_lazy();
@@ -842,6 +862,7 @@ int main(int argc, char *argv[])
 	test_remove();
 	test_unique();
 	test_client_subnet();
+	test_alignment();
 
 	knot_rrset_clear(&opt_rr, NULL);