feat(example): Added DNS over HTTPS (DoH) example
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
# Check for configuration options and set the EMBED_TXTFILES accordingly
|
||||
if(DEFINED CONFIG_HTTPS_DNS_CERT_GOOGLE_HIDDEN)
|
||||
set(cert_file "${CONFIG_HTTPS_DNS_CERT_GOOGLE_HIDDEN}")
|
||||
elseif(DEFINED CONFIG_HTTPS_DNS_CERT_CUSTOM_HIDDEN)
|
||||
set(cert_file "${CONFIG_HTTPS_DNS_CERT_CUSTOM_HIDDEN}")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "example_dns_over_https.c"
|
||||
INCLUDE_DIRS "."
|
||||
EMBED_TXTFILES ${cert_file})
|
||||
@@ -0,0 +1,102 @@
|
||||
menu "Example DNS-over-HTTPS Configuration"
|
||||
|
||||
choice HTTPS_DNS_SERVER
|
||||
prompt "Choose DNS-over-HTTPS Server"
|
||||
default HTTPS_DNS_SERVER_GOOGLE
|
||||
|
||||
config HTTPS_DNS_SERVER_GOOGLE
|
||||
bool "Google DNS (dns.google)"
|
||||
help
|
||||
Use Google's DNS-over-HTTPS server (dns.google) with its corresponding root certificate.
|
||||
|
||||
config HTTPS_DNS_SERVER_CLOUDFLARE
|
||||
bool "Cloudflare DNS (cloudflare-dns.com)"
|
||||
help
|
||||
Use Cloudflare's DNS-over-HTTPS server (cloudflare-dns.com) with its corresponding root certificate.
|
||||
|
||||
config HTTPS_DNS_SERVER_CUSTOM
|
||||
bool "Custom DNS-over-HTTPS Server"
|
||||
help
|
||||
Use a custom DNS-over-HTTPS server. You must specify both the server URL and certificate manually.
|
||||
endchoice
|
||||
|
||||
config HTTPS_DNS_SERVER_URL_GOOGLE
|
||||
string
|
||||
prompt "Google DNS-over-HTTPS Server URL"
|
||||
default "dns.google"
|
||||
depends on HTTPS_DNS_SERVER_GOOGLE
|
||||
help
|
||||
Google DNS-over-HTTPS server URL.
|
||||
|
||||
config HTTPS_DNS_SERVICE_PATH_GOOGLE
|
||||
string
|
||||
prompt "Path to Google DNS-over-HTTPS Service"
|
||||
default "dns-query"
|
||||
depends on HTTPS_DNS_SERVER_GOOGLE
|
||||
help
|
||||
Path to Google DNS-over-HTTPS Service.
|
||||
|
||||
config HTTPS_DNS_SERVER_URL_CLOUDFLARE
|
||||
string
|
||||
prompt "Cloudflare DNS-over-HTTPS Server URL"
|
||||
default "cloudflare-dns.com"
|
||||
depends on HTTPS_DNS_SERVER_CLOUDFLARE
|
||||
help
|
||||
Cloudflare DNS-over-HTTPS server URL.
|
||||
|
||||
config HTTPS_DNS_SERVICE_PATH_CLOUDFLARE
|
||||
string
|
||||
prompt "Path to Cloudflare DNS-over-HTTPS Service"
|
||||
default "dns-query"
|
||||
depends on HTTPS_DNS_SERVER_CLOUDFLARE
|
||||
help
|
||||
Path to Cloudflare DNS-over-HTTPS Service.
|
||||
|
||||
config HTTPS_DNS_SERVER_URL_CUSTOM
|
||||
string
|
||||
prompt "Custom DNS-over-HTTPS Server URL"
|
||||
depends on HTTPS_DNS_SERVER_CUSTOM
|
||||
help
|
||||
Specify your custom DNS-over-HTTPS server URL here.
|
||||
|
||||
config HTTPS_DNS_SERVICE_PATH_CUSTOM
|
||||
string
|
||||
prompt "Path to the Custom DNS-over-HTTPS Service"
|
||||
default "dns-query"
|
||||
depends on HTTPS_DNS_SERVER_CUSTOM
|
||||
help
|
||||
Path to the Custom DNS-over-HTTPS Service.
|
||||
|
||||
config HTTPS_DNS_ESP_CERT_BUNDLE
|
||||
bool "Use internal certificate bundle"
|
||||
default y
|
||||
help
|
||||
Enable this option to use the internal certificate bundle for DNS-over-HTTPS.
|
||||
|
||||
config HTTPS_DNS_CERT_GOOGLE_HIDDEN
|
||||
string
|
||||
default "cert_google_root.pem"
|
||||
depends on HTTPS_DNS_SERVER_GOOGLE && !HTTPS_DNS_ESP_CERT_BUNDLE
|
||||
|
||||
config HTTPS_DNS_CERT_GOOGLE
|
||||
string
|
||||
prompt "Google DNS Certificate (readonly)"
|
||||
default HTTPS_DNS_CERT_GOOGLE_HIDDEN
|
||||
depends on HTTPS_DNS_SERVER_GOOGLE && !HTTPS_DNS_ESP_CERT_BUNDLE
|
||||
help
|
||||
Google DNS root certificate in PEM format. This option is read-only.
|
||||
|
||||
config HTTPS_DNS_CERT_CUSTOM_HIDDEN
|
||||
string
|
||||
default "cert_custom_root.pem"
|
||||
depends on HTTPS_DNS_SERVER_CUSTOM && !HTTPS_DNS_ESP_CERT_BUNDLE
|
||||
|
||||
config HTTPS_DNS_CERT_CUSTOM
|
||||
string
|
||||
prompt "Custom DNS Certificate (readonly)"
|
||||
default HTTPS_DNS_CERT_CUSTOM_HIDDEN
|
||||
depends on HTTPS_DNS_SERVER_CUSTOM && !HTTPS_DNS_ESP_CERT_BUNDLE
|
||||
help
|
||||
Specify the certificate file for the custom DNS server in PEM format. This option is read-only.
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,31 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_timer.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "protocol_examples_common.h"
|
||||
#include "time_sync.h"
|
||||
#include "dns_over_https.h"
|
||||
#if defined(CONFIG_HTTPS_DNS_ESP_CERT_BUNDLE) && defined(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE)
|
||||
#include "esp_crt_bundle.h"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_HTTPS_DNS_ESP_CERT_BUNDLE) && !defined(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE)
|
||||
#error "CONFIG_HTTPS_DNS_ESP_CERT_BUNDLE is enabled, but CONFIG_MBEDTLS_CERTIFICATE_BUNDLE is not enabled. Please enable CONFIG_MBEDTLS_CERTIFICATE_BUNDLE."
|
||||
#endif
|
||||
|
||||
#ifndef INET6_ADDRSTRLEN
|
||||
#define INET6_ADDRSTRLEN INET_ADDRSTRLEN
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HTTPS_DNS_SERVER_GOOGLE
|
||||
#define HTTPS_DNS_SERVER CONFIG_HTTPS_DNS_SERVER_URL_GOOGLE
|
||||
#define HTTPS_DNS_SERVICE_PATH CONFIG_HTTPS_DNS_SERVICE_PATH_GOOGLE
|
||||
#if !defined(CONFIG_HTTPS_DNS_ESP_CERT_BUNDLE)
|
||||
extern const char server_root_cert_pem_start[] asm("_binary_cert_google_root_pem_start");
|
||||
extern const char server_root_cert_pem_end[] asm("_binary_cert_google_root_pem_end");
|
||||
#endif /* CONFIG_HTTPS_DNS_ESP_CERT_BUNDLE */
|
||||
|
||||
#elif CONFIG_HTTPS_DNS_SERVER_CLOUDFLARE
|
||||
#define HTTPS_DNS_SERVER CONFIG_HTTPS_DNS_SERVER_URL_CLOUDFLARE
|
||||
#define HTTPS_DNS_SERVICE_PATH CONFIG_HTTPS_DNS_SERVICE_PATH_CLOUDFLARE
|
||||
const char *server_root_cert_pem_start = NULL;
|
||||
const char *server_root_cert_pem_end = NULL;
|
||||
|
||||
#elif CONFIG_HTTPS_DNS_SERVER_CUSTOM
|
||||
#define HTTPS_DNS_SERVER CONFIG_HTTPS_DNS_SERVER_URL_CUSTOM
|
||||
#define HTTPS_DNS_SERVICE_PATH CONFIG_HTTPS_DNS_SERVICE_PATH_CUSTOM
|
||||
#if !defined(CONFIG_HTTPS_DNS_ESP_CERT_BUNDLE)
|
||||
extern const char server_root_cert_pem_start[] asm("_binary_cert_custom_root_pem_start");
|
||||
extern const char server_root_cert_pem_end[] asm("_binary_cert_custom_root_pem_end");
|
||||
#endif /* CONFIG_HTTPS_DNS_ESP_CERT_BUNDLE */
|
||||
#endif
|
||||
|
||||
static const char *TAG = "example_dns_over_https";
|
||||
|
||||
static void do_getaddrinfo(char *hostname, int family)
|
||||
{
|
||||
struct addrinfo hints, *res, *p;
|
||||
int status;
|
||||
char ipstr[INET6_ADDRSTRLEN];
|
||||
void *addr = NULL;
|
||||
char *ipver = NULL;
|
||||
|
||||
/* Initialize the hints structure */
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = family;
|
||||
hints.ai_socktype = SOCK_STREAM; /* TCP stream sockets */
|
||||
|
||||
/* Get address information */
|
||||
if ((status = getaddrinfo(hostname, NULL, &hints, &res)) != 0) {
|
||||
ESP_LOGE(TAG, "getaddrinfo error: %d", status);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Using DNS Over HTTPS server: %s", HTTPS_DNS_SERVER);
|
||||
ESP_LOGI(TAG, "Resolving IP addresses for %s:", hostname);
|
||||
|
||||
/* Loop through all the results */
|
||||
for (p = res; p != NULL; p = p->ai_next) {
|
||||
|
||||
/* Get pointer to the address itself */
|
||||
#if defined(CONFIG_LWIP_IPV4)
|
||||
if (p->ai_family == AF_INET) { /* IPv4 */
|
||||
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
|
||||
addr = &(ipv4->sin_addr);
|
||||
ipver = "IPv4";
|
||||
|
||||
/* Convert the IP to a string and print it */
|
||||
inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
|
||||
ESP_LOGI(TAG, "%s: %s", ipver, ipstr);
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_LWIP_IPV6)
|
||||
if (p->ai_family == AF_INET6) { /* IPv6 */
|
||||
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
|
||||
addr = &(ipv6->sin6_addr);
|
||||
ipver = "IPv6";
|
||||
|
||||
/* Convert the IP to a string and print it */
|
||||
inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
|
||||
ESP_LOGI(TAG, "%s: %s", ipver, ipstr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
cleanup:
|
||||
freeaddrinfo(res); /* Free the linked list */
|
||||
}
|
||||
|
||||
static void addr_info_task(void *pvParameters)
|
||||
{
|
||||
do_getaddrinfo("yahoo.com", AF_INET);
|
||||
do_getaddrinfo("yahoo.com", AF_UNSPEC);
|
||||
do_getaddrinfo("www.google.com", AF_INET6);
|
||||
do_getaddrinfo("www.google.com", AF_UNSPEC);
|
||||
do_getaddrinfo("0.0.0.0", AF_UNSPEC);
|
||||
do_getaddrinfo("fe80:0000:0000:0000:5abf:25ff:fee0:4100", AF_UNSPEC);
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
esp_err_t ret = nvs_flash_init(); /* Initialize NVS */
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
|
||||
* Read "Establishing Wi-Fi or Ethernet Connection" section in
|
||||
* examples/protocols/README.md for more information about this function.
|
||||
*/
|
||||
ESP_ERROR_CHECK(example_connect());
|
||||
|
||||
/* Enables periodic time synchronization required for certificate expiry validation */
|
||||
#ifdef CONFIG_MBEDTLS_HAVE_TIME_DATE
|
||||
setup_periodic_time_updates();
|
||||
#endif
|
||||
|
||||
/* Initialize the DOH config */
|
||||
dns_over_https_config_t config = {
|
||||
.dns_server = HTTPS_DNS_SERVER,
|
||||
.dns_service_path = HTTPS_DNS_SERVICE_PATH,
|
||||
#if defined(CONFIG_HTTPS_DNS_ESP_CERT_BUNDLE)
|
||||
.crt_bundle_attach = esp_crt_bundle_attach,
|
||||
#else
|
||||
.cert_pem = server_root_cert_pem_start,
|
||||
#endif
|
||||
};
|
||||
ESP_ERROR_CHECK(dns_over_https_init(&config));
|
||||
|
||||
xTaskCreate(addr_info_task, "AddressInfo", 4 * 1024, NULL, 5, NULL);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
idf:
|
||||
version: ">=5.1"
|
||||
protocol_examples_common:
|
||||
path: ${IDF_PATH}/examples/common_components/protocol_examples_common
|
||||
dns_over_https:
|
||||
path: ${IDF_PATH}/examples/protocols/dns_over_https/components/dns_over_https
|
||||
time_sync:
|
||||
path: ${IDF_PATH}/examples/protocols/dns_over_https/components/time_sync
|
||||
Reference in New Issue
Block a user