diff --git a/Knot.files b/Knot.files
index 423b38c38fab3153b20ba59f492bdab708559527..1025dd5c25869e814b0216e7dcfd30a5f89f511d 100644
--- a/Knot.files
+++ b/Knot.files
@@ -266,6 +266,8 @@ src/knot/modules/rosedb.h
 src/knot/modules/rosedb_tool.c
 src/knot/modules/synth_record.c
 src/knot/modules/synth_record.h
+src/knot/modules/whoami.c
+src/knot/modules/whoami.h
 src/knot/nameserver/axfr.c
 src/knot/nameserver/axfr.h
 src/knot/nameserver/chaos.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 2ddd23146e5b7411fe9bc2983c91b26e90991102..ad1c2a55b3a12058ffc6446c8b518314c730d899 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -282,6 +282,8 @@ libknotd_la_SOURCES =				\
 	knot/modules/online_sign/nsec_next.h	\
 	knot/modules/synth_record.c		\
 	knot/modules/synth_record.h		\
+	knot/modules/whoami.c			\
+	knot/modules/whoami.h			\
 	knot/nameserver/axfr.c			\
 	knot/nameserver/axfr.h			\
 	knot/nameserver/chaos.c			\
diff --git a/src/knot/conf/scheme.c b/src/knot/conf/scheme.c
index 5226f47651842527c55f886a09c0c010f3aade41..8046cd5bb9a5f94695ef93041abcae57db5830f2 100644
--- a/src/knot/conf/scheme.c
+++ b/src/knot/conf/scheme.c
@@ -37,6 +37,7 @@
 #if USE_DNSTAP
 #include "knot/modules/dnstap.h"
 #endif
+#include "knot/modules/whoami.h"
 
 #define HOURS(x)	((x) * 3600)
 #define DAYS(x)		((x) * HOURS(24))
@@ -260,6 +261,7 @@ const yp_item_t conf_scheme[] = {
 	                                         { check_mod_dnstap } },
 #endif
 	{ C_MOD_ONLINE_SIGN,  YP_TGRP, YP_VGRP = { scheme_mod_online_sign }, YP_FMULTI },
+	{ C_MOD_WHOAMI,       YP_TGRP, YP_VGRP = { scheme_mod_whoami }, YP_FMULTI },
 /***********/
 	{ C_TPL,      YP_TGRP, YP_VGRP = { desc_template }, YP_FMULTI, { check_template } },
 	{ C_ZONE,     YP_TGRP, YP_VGRP = { desc_zone }, YP_FMULTI, { check_zone } },
diff --git a/src/knot/modules/whoami.c b/src/knot/modules/whoami.c
new file mode 100644
index 0000000000000000000000000000000000000000..c7c5dda5fea21f3c646d0a1f3292ea72b0775c65
--- /dev/null
+++ b/src/knot/modules/whoami.c
@@ -0,0 +1,154 @@
+/*  Copyright (C) 2016 Fastly, Inc.
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "knot/modules/whoami.h"
+#include "knot/nameserver/process_query.h"
+#include "knot/nameserver/internet.h"
+#include "libknot/libknot.h"
+
+const yp_item_t scheme_mod_whoami[] = {
+	{ C_ID,         YP_TSTR, YP_VNONE },
+	{ C_COMMENT,    YP_TSTR, YP_VNONE },
+	{ NULL }
+};
+
+static int whoami_query(int state, knot_pkt_t *pkt, struct query_data *qdata, void *ctx)
+{
+	knot_rrset_t *rrset = NULL;
+
+	/* Sanity checks. */
+	if (pkt == NULL ||
+	    qdata == NULL ||
+	    qdata->query == NULL ||
+	    qdata->param == NULL || qdata->param->remote == NULL ||
+	    qdata->zone == NULL || qdata->zone->name == NULL ||
+	    qdata->zone->contents == NULL || qdata->zone->contents->apex == NULL)
+	{
+		return ERROR;
+	}
+
+	/* Retrieve the query tuple. */
+	const knot_dname_t *qname = knot_pkt_qname(qdata->query);
+	const uint16_t qtype = knot_pkt_qtype(qdata->query);
+	const uint16_t qclass = knot_pkt_qclass(qdata->query);
+
+	/* We only generate A and AAAA records, which are Internet class. */
+	if (qclass != KNOT_CLASS_IN) {
+		return state;
+	}
+
+	/* Only handle queries with qname set to the zone name. */
+	if (!knot_dname_is_equal(qname, qdata->zone->name)) {
+		return state;
+	}
+
+	/* Only handle A and AAAA queries. */
+	if (qtype != KNOT_RRTYPE_A && qtype != KNOT_RRTYPE_AAAA) {
+		return state;
+	}
+
+	/* Retrieve the IP address that sent the query. */
+	const struct sockaddr_storage *query_source = qdata->param->remote;
+	if (query_source == NULL) {
+		return ERROR;
+	}
+
+	/* If the socket address family corresponds to the query type (i.e.,
+	 * AF_INET <-> A and AF_INET6 <-> AAAA), put the socket address and
+	 * length into 'rdata' and 'len_rdata'.
+	 */
+	const void *rdata = NULL;
+	size_t len_rdata = 0;
+	if (query_source->ss_family == AF_INET && qtype == KNOT_RRTYPE_A) {
+		const struct sockaddr_in *sai = (struct sockaddr_in *)query_source;
+		rdata = &sai->sin_addr.s_addr;
+		len_rdata = sizeof(sai->sin_addr.s_addr);
+	} else if (query_source->ss_family == AF_INET6 && qtype == KNOT_RRTYPE_AAAA) {
+		const struct sockaddr_in6 *sai6 = (struct sockaddr_in6 *)query_source;
+		rdata = &sai6->sin6_addr;
+		len_rdata = sizeof(sai6->sin6_addr);
+	} else {
+		/* Query type didn't match address family. */
+		return state;
+	}
+
+	/* Sanity check, since knot_rrset_add_rdata() takes a uint16_t length
+	 * parameter.
+	 */
+	if (len_rdata > UINT16_MAX) {
+		return state;
+	}
+
+	/* Synthesize the response RRset. */
+
+	/* Owner name, type, and class are taken from the question. */
+	rrset = knot_rrset_new(qname, qtype, qclass, &pkt->mm);
+	if (rrset == NULL) {
+		return ERROR;
+	}
+
+	/* TTL is taken from the TTL of the SOA record. */
+	uint32_t ttl = 0;
+	const zone_node_t *apex = qdata->zone->contents->apex;
+	for (uint16_t i = 0; apex != NULL && i < apex->rrset_count; i++) {
+		const struct rr_data *rr_data = &apex->rrs[i];
+		if (rr_data->type == KNOT_RRTYPE_SOA) {
+			ttl = knot_rdataset_ttl(&rr_data->rrs);
+			break;
+		}
+	}
+
+	/* Record data is the query source address. */
+	int ret = knot_rrset_add_rdata(rrset, rdata, len_rdata, ttl, &pkt->mm);
+	if (ret != KNOT_EOK) {
+		knot_rrset_free(&rrset, &pkt->mm);
+		return ERROR;
+	}
+
+	/* Add the new RRset to the response packet. */
+	ret = knot_pkt_put(pkt, KNOT_COMPR_HINT_QNAME, rrset, KNOT_PF_FREE);
+	if (ret != KNOT_EOK) {
+		knot_rrset_free(&rrset, &pkt->mm);
+		return ERROR;
+	}
+
+	/* Success. */
+	return HIT;
+}
+
+int whoami_load(struct query_plan *plan, struct query_module *self,
+                const knot_dname_t *zone)
+{
+	/* Sanity checks. */
+	if (plan == NULL || self == NULL) {
+		return KNOT_EINVAL;
+	}
+
+	/* Hook to the query plan. */
+	query_plan_step(plan, QPLAN_ANSWER, whoami_query, NULL);
+
+	return KNOT_EOK;
+}
+
+int whoami_unload(struct query_module *self)
+{
+	/* Sanity check. */
+	if (self == NULL) {
+		return KNOT_EINVAL;
+	}
+
+	return KNOT_EOK;
+}
diff --git a/src/knot/modules/whoami.h b/src/knot/modules/whoami.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b922e76af9f84864fdaa822c771e49e17d08cb4
--- /dev/null
+++ b/src/knot/modules/whoami.h
@@ -0,0 +1,39 @@
+/*  Copyright (C) 2016 Fastly, Inc.
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*!
+ * \file
+ *
+ * \brief whoami module
+ *
+ * \addtogroup query_processing
+ * @{
+ */
+
+#pragma once
+
+#include "knot/nameserver/query_module.h"
+
+/*! \brief Module scheme. */
+#define C_MOD_WHOAMI "\x0A""mod-whoami"
+extern const yp_item_t scheme_mod_whoami[];
+
+/*! \brief Module interface. */
+int whoami_load(struct query_plan *plan, struct query_module *self,
+                const knot_dname_t *zone);
+int whoami_unload(struct query_module *self);
+
+/*! @} */
diff --git a/src/knot/nameserver/query_module.c b/src/knot/nameserver/query_module.c
index 04caa2e15f6330e2a33a4ec8e0d5bd9164983106..5011c3111f7dfb435d1a4cc43145c76fedcba8b9 100644
--- a/src/knot/nameserver/query_module.c
+++ b/src/knot/nameserver/query_module.c
@@ -29,6 +29,7 @@
 #if USE_DNSTAP
 #include "knot/modules/dnstap.h"
 #endif
+#include "knot/modules/whoami.h"
 
 typedef struct static_module {
 	const yp_name_t *name;
@@ -48,6 +49,7 @@ static_module_t MODULES[] = {
 #if USE_DNSTAP
         { C_MOD_DNSTAP,       &dnstap_load,       &dnstap_unload,       MOD_SCOPE_ANY },
 #endif
+        { C_MOD_WHOAMI,       &whoami_load,       &whoami_unload,       MOD_SCOPE_ANY },
         { NULL }
 };