diff --git a/cmd/net.c b/cmd/net.c
index 6d704fba86..2a68477aae 100644
--- a/cmd/net.c
+++ b/cmd/net.c
@@ -491,45 +491,10 @@ U_BOOT_CMD(
 #endif
 
 #if defined(CONFIG_CMD_DNS)
-int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
-{
-	if (argc == 1)
-		return CMD_RET_USAGE;
-
-	/*
-	 * We should check for a valid hostname:
-	 * - Each label must be between 1 and 63 characters long
-	 * - the entire hostname has a maximum of 255 characters
-	 * - only the ASCII letters 'a' through 'z' (case-insensitive),
-	 *   the digits '0' through '9', and the hyphen
-	 * - cannot begin or end with a hyphen
-	 * - no other symbols, punctuation characters, or blank spaces are
-	 *   permitted
-	 * but hey - this is a minimalist implmentation, so only check length
-	 * and let the name server deal with things.
-	 */
-	if (strlen(argv[1]) >= 255) {
-		printf("dns error: hostname too long\n");
-		return CMD_RET_FAILURE;
-	}
-
-	net_dns_resolve = argv[1];
-
-	if (argc == 3)
-		net_dns_env_var = argv[2];
-	else
-		net_dns_env_var = NULL;
-
-	if (net_loop(DNS) < 0) {
-		printf("dns lookup of %s failed, check setup\n", argv[1]);
-		return CMD_RET_FAILURE;
-	}
-
-	return CMD_RET_SUCCESS;
-}
-
+extern int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
+		       char *const argv[]);
 U_BOOT_CMD(
-	dns,	3,	1,	do_dns,
+	dns,	3,	1,	do_lwip_dns,
 	"lookup the IP of a hostname",
 	"hostname [envvar]"
 );
diff --git a/lib/lwip/Kconfig b/lib/lwip/Kconfig
index 3688ac3305..5e9062a6da 100644
--- a/lib/lwip/Kconfig
+++ b/lib/lwip/Kconfig
@@ -26,7 +26,7 @@ config LWIP_LIB_UDP
 
 config LWIP_LIB_DNS
         bool "dns"
-        default n
+        default y
 
 config LWIP_LIB_DHCP
         bool "dhcp"
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile
index e1a8a2a7b7..d6e511dff1 100644
--- a/lib/lwip/Makefile
+++ b/lib/lwip/Makefile
@@ -99,3 +99,5 @@ obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/tftp.o
 obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/lwip-tftp.o
 
 obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o
+
+obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o
diff --git a/lib/lwip/apps/dns/lwip-dns.c b/lib/lwip/apps/dns/lwip-dns.c
new file mode 100644
index 0000000000..04fd53bfcb
--- /dev/null
+++ b/lib/lwip/apps/dns/lwip-dns.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+
+#include <lwip/dns.h>
+#include <lwip/ip_addr.h>
+
+#include "../../../lwip/ulwip.h"
+
+static void dns_found_cb(const char *name, const ip_addr_t *ipaddr, void *callback_arg)
+{
+	char *varname = (char *)callback_arg;
+
+	if (varname)
+		env_set(varname, ip4addr_ntoa(ipaddr));
+
+	printf("resolved %s to %s\n",  name, ip4addr_ntoa(ipaddr));
+	ulwip_exit(0);
+}
+
+int ulwip_dns(char *name, char *varname)
+{
+	int err;
+	ip_addr_t ipaddr; /* not used */
+	ip_addr_t dns1;
+	ip_addr_t dns2;
+
+	ipaddr_aton(env_get("dnsip"), &dns1);
+	ipaddr_aton(env_get("dnsip2"), &dns2);
+
+	dns_init();
+	dns_setserver(0, &dns1);
+	dns_setserver(1, &dns2);
+
+	err = dns_gethostbyname(name, &ipaddr, dns_found_cb, varname);
+	if (err == ERR_OK)
+		dns_found_cb(name, &ipaddr, varname);
+
+	return err;
+}
diff --git a/lib/lwip/apps/dns/lwip-dns.h b/lib/lwip/apps/dns/lwip-dns.h
new file mode 100644
index 0000000000..c59f99e099
--- /dev/null
+++ b/lib/lwip/apps/dns/lwip-dns.h
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+int ulwip_dns(char *name, char *varname);
diff --git a/lib/lwip/cmd-lwip.c b/lib/lwip/cmd-lwip.c
index 625c8c53b8..86b35ccff8 100644
--- a/lib/lwip/cmd-lwip.c
+++ b/lib/lwip/cmd-lwip.c
@@ -12,6 +12,7 @@
 #include <net.h>
 #include <image.h>
 
+#include "apps/dns/lwip-dns.h"
 #include "apps/ping/lwip_ping.h"
 #include "ulwip.h"
 
@@ -208,6 +209,39 @@ static int _do_lwip_dhcp(struct cmd_tbl *cmdtp, int flag, int argc,
 }
 #endif /* CONFIG_CMD_DHCP */
 
+#if defined(CONFIG_CMD_DNS)
+int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
+		char *const argv[])
+{
+	int ret;
+	char *name;
+	char *varname;
+	int LWIP_ERR_INPROGRESS = -5;
+
+	if (argc == 1)
+		return CMD_RET_USAGE;
+
+	name = argv[1];
+
+	if (argc == 3)
+		varname = argv[2];
+	else
+		varname = NULL;
+
+	uboot_lwip_init();
+
+	ret = ulwip_dns(name, varname);
+	if (ret == 0)
+		return CMD_RET_SUCCESS;
+	if (ret != LWIP_ERR_INPROGRESS)
+		return CMD_RET_FAILURE;
+
+	net_set_timeout_handler(1000UL, ulwip_timeout_handler);
+
+	return ulwip_loop();
+}
+#endif /* CONFIG_CMD_DNS */
+
 static struct cmd_tbl cmds[] = {
 	U_BOOT_CMD_MKENT(info, 1, 0, do_lwip_info, "Info and stats", ""),
 	U_BOOT_CMD_MKENT(init, 1, 0, do_lwip_init,
@@ -230,6 +264,11 @@ static struct cmd_tbl cmds[] = {
 			"boot image via network using DHCP/TFTP protocol",
 			""),
 #endif
+#if defined(CONFIG_CMD_DNS)
+	U_BOOT_CMD_MKENT(dns, 3, 0, do_lwip_dns,
+			 "lookup dns name [and store address at variable]",
+			 ""),
+#endif
 };
 
 static int do_ops(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/lib/lwip/lwipopts.h b/lib/lwip/lwipopts.h
index b943d7b9be..7f99a536ee 100644
--- a/lib/lwip/lwipopts.h
+++ b/lib/lwip/lwipopts.h
@@ -43,7 +43,7 @@
 #define SLIP_DEBUG                      LWIP_DBG_OFF
 #define DHCP_DEBUG                      LWIP_DBG_ON
 #define AUTOIP_DEBUG                    LWIP_DBG_ON
-#define DNS_DEBUG                       LWIP_DBG_OFF
+#define DNS_DEBUG                       LWIP_DBG_ON
 #define IP6_DEBUG                       LWIP_DBG_OFF
 #define DHCP6_DEBUG                     LWIP_DBG_OFF
 #else
