7 # include <sys/socket.h>
8 # include <arpa/inet.h>
9 # include <netinet/in.h>
19 #include <event2/event.h>
20 #include <event2/util.h>
22 #include "dnscrypt_client.h"
23 #include "dnscrypt_proxy.h"
28 #include "tcp_request.h"
29 #include "udp_request.h"
30 #include "udp_request_p.h"
33 # include "plugin_support.h"
37 udp_request_free(UDPRequest
* const udp_request
)
39 ProxyContext
*proxy_context
;
41 if (udp_request
->timeout_timer
!= NULL
) {
42 event_free(udp_request
->timeout_timer
);
43 udp_request
->timeout_timer
= NULL
;
45 DNSCRYPT_PROXY_REQUEST_UDP_DONE(udp_request
);
46 proxy_context
= udp_request
->proxy_context
;
47 if (udp_request
->status
.is_in_queue
!= 0) {
48 assert(! TAILQ_EMPTY(&proxy_context
->udp_request_queue
));
49 TAILQ_REMOVE(&proxy_context
->udp_request_queue
, udp_request
, queue
);
50 assert(proxy_context
->connections_count
> 0U);
51 proxy_context
->connections_count
--;
52 DNSCRYPT_PROXY_STATUS_REQUESTS_ACTIVE(proxy_context
->connections_count
,
53 proxy_context
->connections_count_max
);
55 udp_request
->proxy_context
= NULL
;
60 udp_request_kill(UDPRequest
* const udp_request
)
62 if (udp_request
== NULL
|| udp_request
->status
.is_dying
) {
65 udp_request
->status
.is_dying
= 1;
66 udp_request_free(udp_request
);
69 static int udp_send(SendtoWithRetryCtx
* const ctx
);
72 udp_send(SendtoWithRetryCtx
* const ctx
)
74 void (*cb
)(UDPRequest
*udp_request
);
75 UDPRequest
*udp_request
= ctx
->udp_request
;
77 (void) sendto(ctx
->handle
, ctx
->buffer
, ctx
->length
, ctx
->flags
,
78 ctx
->dest_addr
, ctx
->dest_len
);
87 resolver_to_proxy_cb(evutil_socket_t proxy_resolver_handle
, short ev_flags
,
88 void * const proxy_context_
)
90 uint8_t dns_reply
[DNS_MAX_PACKET_SIZE_UDP
];
91 ProxyContext
*proxy_context
= proxy_context_
;
92 UDPRequest
*scanned_udp_request
;
93 UDPRequest
*udp_request
= NULL
;
94 struct sockaddr_storage resolver_sockaddr
;
95 ev_socklen_t resolver_sockaddr_len
= sizeof resolver_sockaddr
;
97 size_t dns_reply_len
= (size_t) 0U;
101 nread
= recvfrom(proxy_resolver_handle
,
102 (void *) dns_reply
, sizeof dns_reply
, 0,
103 (struct sockaddr
*) &resolver_sockaddr
,
104 &resolver_sockaddr_len
);
105 if (nread
< (ssize_t
) 0) {
106 const int err
= evutil_socket_geterror(proxy_resolver_handle
);
107 if (!EVUTIL_ERR_RW_RETRIABLE(err
)) {
108 logger(proxy_context
, LOG_WARNING
,
109 "recvfrom(resolver): [%s]", evutil_socket_error_to_string(err
));
111 DNSCRYPT_PROXY_REQUEST_UDP_NETWORK_ERROR(NULL
);
114 if (evutil_sockaddr_cmp((const struct sockaddr
*) &resolver_sockaddr
,
115 (const struct sockaddr
*)
116 &proxy_context
->resolver_sockaddr
, 1) != 0) {
117 logger_noformat(proxy_context
, LOG_DEBUG
,
118 "Received a resolver reply from a different resolver");
121 TAILQ_FOREACH(scanned_udp_request
,
122 &proxy_context
->udp_request_queue
, queue
) {
123 if (dnscrypt_cmp_client_nonce(scanned_udp_request
->client_nonce
,
124 dns_reply
, (size_t) nread
) == 0) {
125 udp_request
= scanned_udp_request
;
129 if (udp_request
== NULL
) {
130 logger(proxy_context
, LOG_DEBUG
,
131 "Received a reply that doesn't match any active query");
134 if (nread
< (ssize_t
) (DNS_HEADER_SIZE
+ dnscrypt_response_header_size()) ||
135 nread
> (ssize_t
) sizeof dns_reply
) {
136 logger_noformat(proxy_context
, LOG_WARNING
, "Short reply received");
137 udp_request_kill(udp_request
);
140 DNSCRYPT_PROXY_REQUEST_UDP_PROXY_RESOLVER_REPLIED(udp_request
);
141 dns_reply_len
= (size_t) nread
;
142 assert(dns_reply_len
<= sizeof dns_reply
);
144 uncurved_len
= dns_reply_len
;
145 DNSCRYPT_PROXY_REQUEST_UNCURVE_START(udp_request
, uncurved_len
);
146 if (dnscrypt_client_uncurve
147 (&udp_request
->proxy_context
->dnscrypt_client
,
148 udp_request
->client_nonce
, dns_reply
, &uncurved_len
) != 0) {
149 DNSCRYPT_PROXY_REQUEST_UNCURVE_ERROR(udp_request
);
150 DNSCRYPT_PROXY_REQUEST_UDP_PROXY_RESOLVER_GOT_INVALID_REPLY(udp_request
);
151 logger_noformat(udp_request
->proxy_context
, LOG_WARNING
,
152 "Received a suspicious reply from the resolver");
153 udp_request_kill(udp_request
);
156 DNSCRYPT_PROXY_REQUEST_UNCURVE_DONE(udp_request
, uncurved_len
);
157 memset(udp_request
->client_nonce
, 0, sizeof udp_request
->client_nonce
);
158 assert(uncurved_len
<= dns_reply_len
);
159 dns_reply_len
= uncurved_len
;
161 assert(dns_reply_len
>= DNS_HEADER_SIZE
);
162 COMPILER_ASSERT(DNS_OFFSET_FLAGS
< DNS_HEADER_SIZE
);
163 if ((dns_reply
[DNS_OFFSET_FLAGS
] & DNS_FLAGS_TC
) != 0) {
164 if (proxy_context
->udp_current_max_size
<
165 proxy_context
->udp_max_size
) {
166 COMPILER_ASSERT(DNS_MAX_PACKET_SIZE_UDP_NO_EDNS_SEND
>=
167 DNSCRYPT_BLOCK_SIZE
);
168 if (proxy_context
->udp_max_size
-
169 proxy_context
->udp_current_max_size
> DNSCRYPT_BLOCK_SIZE
) {
170 proxy_context
->udp_current_max_size
+= DNSCRYPT_BLOCK_SIZE
;
172 proxy_context
->udp_current_max_size
=
173 proxy_context
->udp_max_size
;
179 const size_t max_reply_size_for_filter
= sizeof dns_reply
;
180 DCPluginDNSPacket dcp_packet
= {
181 .client_sockaddr
= &udp_request
->client_sockaddr
,
182 .dns_packet
= dns_reply
,
183 .dns_packet_len_p
= &dns_reply_len
,
184 .client_sockaddr_len_s
= (size_t) udp_request
->client_sockaddr_len
,
185 .dns_packet_max_len
= max_reply_size_for_filter
187 DNSCRYPT_PROXY_REQUEST_PLUGINS_POST_START(udp_request
, dns_reply_len
,
188 max_reply_size_for_filter
);
189 assert(proxy_context
->app_context
->dcps_context
!= NULL
);
190 const DCPluginSyncFilterResult res
=
191 plugin_support_context_apply_sync_post_filters
192 (proxy_context
->app_context
->dcps_context
, &dcp_packet
);
193 assert(dns_reply_len
> (size_t) 0U &&
194 dns_reply_len
<= sizeof dns_reply
&&
195 dns_reply_len
<= max_reply_size_for_filter
);
196 if (res
!= DCP_SYNC_FILTER_RESULT_OK
) {
197 DNSCRYPT_PROXY_REQUEST_PLUGINS_POST_ERROR(udp_request
, res
);
198 udp_request_kill(udp_request
);
201 DNSCRYPT_PROXY_REQUEST_PLUGINS_POST_DONE(udp_request
, dns_reply_len
,
202 max_reply_size_for_filter
);
204 udp_send(& (SendtoWithRetryCtx
) {
205 .udp_request
= udp_request
,
206 .handle
= udp_request
->client_proxy_handle
,
208 .length
= dns_reply_len
,
210 .dest_addr
= (struct sockaddr
*) &udp_request
->client_sockaddr
,
211 .dest_len
= udp_request
->client_sockaddr_len
,
212 .cb
= udp_request_kill
217 proxy_client_send_truncated(UDPRequest
* const udp_request
,
218 uint8_t dns_reply
[DNS_MAX_PACKET_SIZE_UDP
],
219 size_t dns_reply_len
)
221 DNSCRYPT_PROXY_REQUEST_UDP_TRUNCATED(udp_request
);
223 assert(dns_reply_len
> DNS_OFFSET_FLAGS2
);
224 dns_reply
[DNS_OFFSET_FLAGS
] |= DNS_FLAGS_TC
| DNS_FLAGS_QR
;
225 dns_reply
[DNS_OFFSET_FLAGS2
] |= DNS_FLAGS2_RA
;
226 udp_send(& (SendtoWithRetryCtx
) {
227 .udp_request
= udp_request
,
228 .handle
= udp_request
->client_proxy_handle
,
230 .length
= dns_reply_len
,
232 .dest_addr
= (struct sockaddr
*) &udp_request
->client_sockaddr
,
233 .dest_len
= udp_request
->client_sockaddr_len
,
234 .cb
= udp_request_kill
239 timeout_timer_cb(evutil_socket_t timeout_timer_handle
, short ev_flags
,
240 void * const udp_request_
)
242 UDPRequest
* const udp_request
= udp_request_
;
245 (void) timeout_timer_handle
;
246 DNSCRYPT_PROXY_REQUEST_UDP_TIMEOUT(udp_request
);
247 logger_noformat(udp_request
->proxy_context
, LOG_DEBUG
,
248 "resolver timeout (UDP)");
249 udp_request_kill(udp_request
);
252 #ifndef SO_RCVBUFFORCE
253 # define SO_RCVBUFFORCE SO_RCVBUF
255 #ifndef SO_SNDBUFFORCE
256 # define SO_SNDBUFFORCE SO_SNDBUF
260 udp_tune(evutil_socket_t
const handle
)
265 setsockopt(handle
, SOL_SOCKET
, SO_RCVBUFFORCE
,
266 (void *) (int []) { UDP_BUFFER_SIZE
}, sizeof (int));
267 setsockopt(handle
, SOL_SOCKET
, SO_SNDBUFFORCE
,
268 (void *) (int []) { UDP_BUFFER_SIZE
}, sizeof (int));
269 #if defined(IP_PMTUDISC_OMIT)
270 setsockopt(handle
, IPPROTO_IP
, IP_MTU_DISCOVER
,
271 (void *) (int []) { IP_PMTUDISC_OMIT
}, sizeof (int));
272 #elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
273 setsockopt(handle
, IPPROTO_IP
, IP_MTU_DISCOVER
,
274 (void *) (int []) { IP_PMTUDISC_DONT
}, sizeof (int));
275 #elif defined(IP_DONTFRAG)
276 setsockopt(handle
, IPPROTO_IP
, IP_DONTFRAG
,
277 (void *) (int []) { 0 }, sizeof (int));
282 client_to_proxy_cb_sendto_cb(UDPRequest
* const udp_request
)
285 DNSCRYPT_PROXY_REQUEST_UDP_PROXY_RESOLVER_START(udp_request
);
290 proxy_to_client_direct(UDPRequest
* const udp_request
,
291 const uint8_t * const dns_reply
,
292 const size_t dns_reply_len
)
294 udp_send(& (SendtoWithRetryCtx
) {
295 .udp_request
= udp_request
,
296 .handle
= udp_request
->client_proxy_handle
,
298 .length
= dns_reply_len
,
300 .dest_addr
= (struct sockaddr
*) &udp_request
->client_sockaddr
,
301 .dest_len
= udp_request
->client_sockaddr_len
,
302 .cb
= udp_request_kill
308 client_to_proxy_cb(evutil_socket_t client_proxy_handle
, short ev_flags
,
309 void * const proxy_context_
)
311 uint8_t dns_query
[DNS_MAX_PACKET_SIZE_UDP
];
312 ProxyContext
*proxy_context
= proxy_context_
;
313 UDPRequest
*udp_request
;
316 size_t dns_query_len
= (size_t) 0U;
317 size_t max_query_size
;
318 size_t request_edns_payload_size
;
321 assert(client_proxy_handle
== proxy_context
->udp_listener_handle
);
322 if ((udp_request
= calloc((size_t) 1U, sizeof *udp_request
)) == NULL
) {
325 udp_request
->proxy_context
= proxy_context
;
326 udp_request
->timeout_timer
= NULL
;
327 udp_request
->client_proxy_handle
= client_proxy_handle
;
328 udp_request
->client_sockaddr_len
= sizeof udp_request
->client_sockaddr
;
329 nread
= recvfrom(client_proxy_handle
,
330 (void *) dns_query
, sizeof dns_query
, 0,
331 (struct sockaddr
*) &udp_request
->client_sockaddr
,
332 &udp_request
->client_sockaddr_len
);
333 if (nread
< (ssize_t
) 0) {
334 const int err
= evutil_socket_geterror(client_proxy_handle
);
335 if (!EVUTIL_ERR_RW_RETRIABLE(err
)) {
336 logger(proxy_context
, LOG_WARNING
,
337 "recvfrom(client): [%s]", evutil_socket_error_to_string(err
));
339 DNSCRYPT_PROXY_REQUEST_UDP_NETWORK_ERROR(udp_request
);
340 udp_request_kill(udp_request
);
343 if (nread
< (ssize_t
) DNS_HEADER_SIZE
||
344 (size_t) nread
> sizeof dns_query
) {
345 logger_noformat(proxy_context
, LOG_WARNING
, "Short query received");
349 if (proxy_context
->connections_count
>=
350 proxy_context
->connections_count_max
) {
351 DNSCRYPT_PROXY_REQUEST_UDP_OVERLOADED();
352 if (udp_listener_kill_oldest_request(proxy_context
) != 0) {
353 tcp_listener_kill_oldest_request(proxy_context
);
356 proxy_context
->connections_count
++;
357 assert(proxy_context
->connections_count
358 <= proxy_context
->connections_count_max
);
359 DNSCRYPT_PROXY_STATUS_REQUESTS_ACTIVE(proxy_context
->connections_count
,
360 proxy_context
->connections_count_max
);
361 DNSCRYPT_PROXY_REQUEST_UDP_START(udp_request
);
362 TAILQ_INSERT_TAIL(&proxy_context
->udp_request_queue
,
364 memset(&udp_request
->status
, 0, sizeof udp_request
->status
);
365 udp_request
->status
.is_in_queue
= 1;
367 dns_query_len
= (size_t) nread
;
368 assert(dns_query_len
<= sizeof dns_query
);
370 edns_add_section(proxy_context
, dns_query
, &dns_query_len
,
371 sizeof dns_query
, &request_edns_payload_size
);
373 if (request_edns_payload_size
< DNS_MAX_PACKET_SIZE_UDP_NO_EDNS_SEND
) {
374 max_query_size
= DNS_MAX_PACKET_SIZE_UDP_NO_EDNS_SEND
;
376 max_query_size
= request_edns_payload_size
;
378 if (max_query_size
> sizeof dns_query
) {
379 max_query_size
= sizeof dns_query
;
381 assert(max_query_size
<= sizeof dns_query
);
382 if (udp_request
->proxy_context
->tcp_only
!= 0) {
383 proxy_client_send_truncated(udp_request
, dns_query
, dns_query_len
);
387 size_t max_query_size_for_filter
= dns_query_len
;
388 if (max_query_size
> DNSCRYPT_MAX_PADDING
+ dnscrypt_query_header_size()) {
389 max_query_size_for_filter
= max_query_size
-
390 (DNSCRYPT_MAX_PADDING
+ dnscrypt_query_header_size());
392 DCPluginDNSPacket dcp_packet
= {
393 .client_sockaddr
= &udp_request
->client_sockaddr
,
394 .dns_packet
= dns_query
,
395 .dns_packet_len_p
= &dns_query_len
,
396 .client_sockaddr_len_s
= (size_t) udp_request
->client_sockaddr_len
,
397 .dns_packet_max_len
= max_query_size_for_filter
399 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_START(udp_request
, dns_query_len
,
400 max_query_size_for_filter
);
401 assert(proxy_context
->app_context
->dcps_context
!= NULL
);
402 const DCPluginSyncFilterResult res
=
403 plugin_support_context_apply_sync_pre_filters
404 (proxy_context
->app_context
->dcps_context
, &dcp_packet
);
405 assert(dns_query_len
> (size_t) 0U && dns_query_len
<= max_query_size
&&
406 dns_query_len
<= max_query_size_for_filter
);
408 case DCP_SYNC_FILTER_RESULT_OK
:
410 case DCP_SYNC_FILTER_RESULT_DIRECT
:
411 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_DONE(udp_request
, dns_query_len
,
412 max_query_size_for_filter
);
413 proxy_to_client_direct(udp_request
, dns_query
, dns_query_len
);
416 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_ERROR(udp_request
, res
);
417 udp_request_kill(udp_request
);
420 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_DONE(udp_request
, dns_query_len
,
421 max_query_size_for_filter
);
423 assert(SIZE_MAX
- DNSCRYPT_MAX_PADDING
- dnscrypt_query_header_size()
427 max_len
= proxy_context
->udp_current_max_size
;
428 if (max_len
> max_query_size
) {
429 max_len
= max_query_size
;
431 if (dns_query_len
+ dnscrypt_query_header_size() > max_len
) {
432 proxy_client_send_truncated(udp_request
, dns_query
, dns_query_len
);
435 DNSCRYPT_PROXY_REQUEST_CURVE_START(udp_request
, dns_query_len
);
437 dnscrypt_client_curve(&udp_request
->proxy_context
->dnscrypt_client
,
438 udp_request
->client_nonce
, dns_query
,
439 dns_query_len
, max_len
);
440 if (curve_ret
<= (ssize_t
) 0) {
441 DNSCRYPT_PROXY_REQUEST_CURVE_ERROR(udp_request
);
444 dns_query_len
= (size_t) curve_ret
;
445 assert(dns_query_len
>= dnscrypt_query_header_size());
446 DNSCRYPT_PROXY_REQUEST_CURVE_DONE(udp_request
, dns_query_len
);
447 assert(dns_query_len
<= sizeof dns_query
);
449 udp_request
->timeout_timer
=
450 evtimer_new(udp_request
->proxy_context
->event_loop
,
451 timeout_timer_cb
, udp_request
);
452 if (udp_request
->timeout_timer
!= NULL
) {
453 const struct timeval tv
= {
454 .tv_sec
= (time_t) DNS_QUERY_TIMEOUT
, .tv_usec
= 0
456 evtimer_add(udp_request
->timeout_timer
, &tv
);
458 udp_send(& (SendtoWithRetryCtx
) {
459 .udp_request
= udp_request
,
460 .handle
= proxy_context
->udp_proxy_resolver_handle
,
462 .length
= dns_query_len
,
464 .dest_addr
= (struct sockaddr
*) &proxy_context
->resolver_sockaddr
,
465 .dest_len
= proxy_context
->resolver_sockaddr_len
,
466 .cb
= client_to_proxy_cb_sendto_cb
471 udp_listener_kill_oldest_request(ProxyContext
* const proxy_context
)
473 if (TAILQ_EMPTY(&proxy_context
->udp_request_queue
)) {
476 udp_request_kill(TAILQ_FIRST(&proxy_context
->udp_request_queue
));
482 udp_listener_bind(ProxyContext
* const proxy_context
)
484 if (proxy_context
->udp_listener_handle
== -1) {
485 if ((proxy_context
->udp_listener_handle
= socket
486 (proxy_context
->local_sockaddr
.ss_family
,
487 SOCK_DGRAM
, IPPROTO_UDP
)) == -1) {
488 logger_noformat(proxy_context
, LOG_ERR
,
489 "Unable to create a socket (UDP)");
492 if (bind(proxy_context
->udp_listener_handle
,
493 (struct sockaddr
*) &proxy_context
->local_sockaddr
,
494 proxy_context
->local_sockaddr_len
) != 0) {
495 logger(NULL
, LOG_ERR
, "Unable to bind (UDP) [%s]",
496 evutil_socket_error_to_string(evutil_socket_geterror(
497 proxy_context
->udp_listener_handle
)));
498 evutil_closesocket(proxy_context
->udp_listener_handle
);
499 proxy_context
->udp_listener_handle
= -1;
503 evutil_make_socket_closeonexec(proxy_context
->udp_listener_handle
);
504 evutil_make_socket_nonblocking(proxy_context
->udp_listener_handle
);
505 udp_tune(proxy_context
->udp_listener_handle
);
507 if ((proxy_context
->udp_proxy_resolver_handle
= socket
508 (proxy_context
->resolver_sockaddr
.ss_family
, SOCK_DGRAM
, IPPROTO_UDP
)) == -1) {
509 logger_noformat(proxy_context
, LOG_ERR
,
510 "Unable to create a socket to the resolver");
511 evutil_closesocket(proxy_context
->udp_listener_handle
);
512 proxy_context
->udp_listener_handle
= -1;
515 evutil_make_socket_closeonexec(proxy_context
->udp_proxy_resolver_handle
);
516 evutil_make_socket_nonblocking(proxy_context
->udp_proxy_resolver_handle
);
517 udp_tune(proxy_context
->udp_proxy_resolver_handle
);
519 TAILQ_INIT(&proxy_context
->udp_request_queue
);
525 udp_listener_start(ProxyContext
* const proxy_context
)
527 assert(proxy_context
->udp_listener_handle
!= -1);
528 if ((proxy_context
->udp_listener_event
=
529 event_new(proxy_context
->event_loop
,
530 proxy_context
->udp_listener_handle
, EV_READ
| EV_PERSIST
,
531 client_to_proxy_cb
, proxy_context
)) == NULL
) {
534 if (event_add(proxy_context
->udp_listener_event
, NULL
) != 0) {
535 udp_listener_stop(proxy_context
);
539 assert(proxy_context
->udp_proxy_resolver_handle
!= -1);
540 if ((proxy_context
->udp_proxy_resolver_event
=
541 event_new(proxy_context
->event_loop
,
542 proxy_context
->udp_proxy_resolver_handle
,
543 EV_READ
| EV_PERSIST
,
544 resolver_to_proxy_cb
, proxy_context
)) == NULL
) {
545 udp_listener_stop(proxy_context
);
548 if (event_add(proxy_context
->udp_proxy_resolver_event
, NULL
) != 0) {
549 udp_listener_stop(proxy_context
);
556 udp_listener_stop(ProxyContext
* const proxy_context
)
558 event_free(proxy_context
->udp_proxy_resolver_event
);
559 proxy_context
->udp_proxy_resolver_event
= NULL
;
560 while (udp_listener_kill_oldest_request(proxy_context
) != 0) { }
561 logger_noformat(proxy_context
, LOG_INFO
, "UDP listener shut down");