upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/main/dns_server.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/dns_server.c')
-rw-r--r--main/dns_server.c61
1 files changed, 54 insertions, 7 deletions
diff --git a/main/dns_server.c b/main/dns_server.c
index 733e771..15a729f 100644
--- a/main/dns_server.c
+++ b/main/dns_server.c
@@ -11,10 +11,14 @@
11#define MAX_PENDING 50 11#define MAX_PENDING 50
12#define DNS_BUF_SIZE 512 12#define DNS_BUF_SIZE 512
13#define DNS_PORT 53 13#define DNS_PORT 53
14#define DOT_PORT 853
14#define DNS_TASK_STACK 4096 15#define DNS_TASK_STACK 4096
16#define DOT_TASK_STACK 3072
15#define DNS_TASK_PRIO 5 17#define DNS_TASK_PRIO 5
18#define DOT_TASK_PRIO 5
16#define DNS_FORWARD_TIMEOUT_MS 2000 19#define DNS_FORWARD_TIMEOUT_MS 2000
17#define NXDOMAIN_TTL 30 20#define NXDOMAIN_TTL 30
21#define HIJACK_TTL 10
18 22
19static const char *TAG = "dns_server"; 23static const char *TAG = "dns_server";
20 24
@@ -47,6 +51,7 @@ typedef struct {
47static auth_entry_t s_auth_list[MAX_AUTH_IPS]; 51static auth_entry_t s_auth_list[MAX_AUTH_IPS];
48static int s_auth_count = 0; 52static int s_auth_count = 0;
49static TaskHandle_t s_dns_task = NULL; 53static TaskHandle_t s_dns_task = NULL;
54static TaskHandle_t s_dot_task = NULL;
50static volatile bool s_dns_running = false; 55static volatile bool s_dns_running = false;
51static esp_ip4_addr_t s_ap_ip; 56static esp_ip4_addr_t s_ap_ip;
52static esp_ip4_addr_t s_upstream_dns; 57static esp_ip4_addr_t s_upstream_dns;
@@ -106,7 +111,7 @@ static int build_redirect_response(uint8_t *response, int req_len)
106 ans.name = htons(0xC00C); 111 ans.name = htons(0xC00C);
107 ans.type = htons(1); 112 ans.type = htons(1);
108 ans.class = htons(1); 113 ans.class = htons(1);
109 ans.ttl = htonl(NXDOMAIN_TTL); 114 ans.ttl = htonl(HIJACK_TTL);
110 ans.len = htons(4); 115 ans.len = htons(4);
111 ans.addr = s_ap_ip.addr; 116 ans.addr = s_ap_ip.addr;
112 memcpy(response + resp_len, &ans, sizeof(ans)); 117 memcpy(response + resp_len, &ans, sizeof(ans));
@@ -201,23 +206,21 @@ static void dns_server_task(void *arg)
201 sendto(sock, tx_buf, resp_len, 0, (struct sockaddr *)&client_addr, client_len); 206 sendto(sock, tx_buf, resp_len, 0, (struct sockaddr *)&client_addr, client_len);
202 } 207 }
203 } else { 208 } else {
209 char qname[256] = {0};
210 parse_dns_name(rx_buf, n, sizeof(dns_header_t), qname, sizeof(qname));
211 ESP_LOGI(TAG, "Hijack DNS from " IPSTR ": %s (type=%d)", IP2STR(&(esp_ip4_addr_t){.addr=client_ip}), qname, qtype);
204 if (qtype == 1) { 212 if (qtype == 1) {
205 int resp_len = build_redirect_response(rx_buf, req_len); 213 int resp_len = build_redirect_response(rx_buf, req_len);
206 memcpy(tx_buf, rx_buf, resp_len); 214 memcpy(tx_buf, rx_buf, resp_len);
207 dns_header_t *resp_hdr = (dns_header_t *)tx_buf; 215 dns_header_t *resp_hdr = (dns_header_t *)tx_buf;
208 resp_hdr->id = htons(txn_id); 216 resp_hdr->id = htons(txn_id);
209 sendto(sock, tx_buf, resp_len, 0, (struct sockaddr *)&client_addr, client_len); 217 sendto(sock, tx_buf, resp_len, 0, (struct sockaddr *)&client_addr, client_len);
210 } else if (qtype == 28) { 218 } else {
211 int resp_len = build_nxdomain(rx_buf, req_len); 219 int resp_len = build_nxdomain(rx_buf, req_len);
212 memcpy(tx_buf, rx_buf, resp_len); 220 memcpy(tx_buf, rx_buf, resp_len);
213 dns_header_t *resp_hdr = (dns_header_t *)tx_buf; 221 dns_header_t *resp_hdr = (dns_header_t *)tx_buf;
214 resp_hdr->id = htons(txn_id); 222 resp_hdr->id = htons(txn_id);
215 sendto(sock, tx_buf, resp_len, 0, (struct sockaddr *)&client_addr, client_len); 223 sendto(sock, tx_buf, resp_len, 0, (struct sockaddr *)&client_addr, client_len);
216 } else {
217 int resp_len = forward_dns(rx_buf, req_len, tx_buf, sizeof(tx_buf), &client_addr, txn_id);
218 if (resp_len > 0) {
219 sendto(sock, tx_buf, resp_len, 0, (struct sockaddr *)&client_addr, client_len);
220 }
221 } 224 }
222 } 225 }
223 } 226 }
@@ -227,6 +230,49 @@ static void dns_server_task(void *arg)
227 vTaskDelete(NULL); 230 vTaskDelete(NULL);
228} 231}
229 232
233static void dot_reject_task(void *arg)
234{
235 int sock = socket(AF_INET, SOCK_STREAM, 0);
236 if (sock < 0) {
237 ESP_LOGE(TAG, "Failed to create DoT reject socket");
238 vTaskDelete(NULL);
239 return;
240 }
241
242 int opt = 1;
243 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
244
245 struct sockaddr_in bind_addr = {
246 .sin_family = AF_INET,
247 .sin_port = htons(DOT_PORT),
248 .sin_addr.s_addr = INADDR_ANY,
249 };
250 if (bind(sock, (struct sockaddr *)&bind_addr, sizeof(bind_addr)) < 0) {
251 ESP_LOGE(TAG, "Failed to bind DoT reject socket on port %d", DOT_PORT);
252 close(sock);
253 vTaskDelete(NULL);
254 return;
255 }
256
257 listen(sock, 1);
258 ESP_LOGI(TAG, "DoT reject server on port %d (forces DNS fallback to port 53)", DOT_PORT);
259
260 while (s_dns_running) {
261 struct sockaddr_in client_addr;
262 socklen_t client_len = sizeof(client_addr);
263 int client_sock = accept(sock, (struct sockaddr *)&client_addr, &client_len);
264 if (client_sock >= 0) {
265 struct linger ling = { .l_onoff = 1, .l_linger = 0 };
266 setsockopt(client_sock, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
267 close(client_sock);
268 }
269 }
270
271 close(sock);
272 ESP_LOGI(TAG, "DoT reject server stopped");
273 vTaskDelete(NULL);
274}
275
230esp_err_t dns_server_start(esp_ip4_addr_t ap_ip, esp_ip4_addr_t upstream_dns) 276esp_err_t dns_server_start(esp_ip4_addr_t ap_ip, esp_ip4_addr_t upstream_dns)
231{ 277{
232 if (s_dns_running) return ESP_OK; 278 if (s_dns_running) return ESP_OK;
@@ -234,6 +280,7 @@ esp_err_t dns_server_start(esp_ip4_addr_t ap_ip, esp_ip4_addr_t upstream_dns)
234 s_upstream_dns = upstream_dns; 280 s_upstream_dns = upstream_dns;
235 s_dns_running = true; 281 s_dns_running = true;
236 xTaskCreate(dns_server_task, "dns_server", DNS_TASK_STACK, NULL, DNS_TASK_PRIO, &s_dns_task); 282 xTaskCreate(dns_server_task, "dns_server", DNS_TASK_STACK, NULL, DNS_TASK_PRIO, &s_dns_task);
283 xTaskCreate(dot_reject_task, "dot_reject", DOT_TASK_STACK, NULL, DOT_TASK_PRIO, &s_dot_task);
237 return ESP_OK; 284 return ESP_OK;
238} 285}
239 286