13 #include <event2/event.h>
14 #include <event2/util.h>
17 #include "dnscrypt_client.h"
18 #include "dnscrypt_proxy.h"
19 #include "salsa20_random.h"
22 #include "sandboxes.h"
23 #include "stack_trace.h"
24 #include "tcp_request.h"
25 #include "udp_request.h"
27 #ifndef INET6_ADDRSTRLEN
28 # define INET6_ADDRSTRLEN 46U
31 static AppContext app_context
;
34 sockaddr_from_ip_and_port(struct sockaddr_storage
* const sockaddr
,
35 ev_socklen_t
* const sockaddr_len_p
,
36 const char * const ip
, const char * const port
,
37 const char * const error_msg
)
39 char sockaddr_port
[INET6_ADDRSTRLEN
+ sizeof "[]:65535"];
43 _Bool has_columns
= 0;
44 _Bool has_brackets
= *ip
== '[';
46 if ((pnt
= strchr(ip
, ':')) != NULL
) {
48 if (strchr(pnt
+ 1, ':') != NULL
) {
52 sockaddr_len_int
= (int) sizeof *sockaddr
;
53 if ((has_brackets
!= 0 || has_column
!= has_columns
) &&
54 evutil_parse_sockaddr_port(ip
, (struct sockaddr
*) sockaddr
,
55 &sockaddr_len_int
) == 0) {
56 *sockaddr_len_p
= (ev_socklen_t
) sockaddr_len_int
;
59 if (has_columns
!= 0 && has_brackets
== 0) {
60 evutil_snprintf(sockaddr_port
, sizeof sockaddr_port
, "[%s]:%s",
63 evutil_snprintf(sockaddr_port
, sizeof sockaddr_port
, "%s:%s",
66 sockaddr_len_int
= (int) sizeof *sockaddr
;
67 if (evutil_parse_sockaddr_port(sockaddr_port
, (struct sockaddr
*) sockaddr
,
68 &sockaddr_len_int
) != 0) {
69 logger(NULL
, LOG_ERR
, "%s: %s", error_msg
, sockaddr_port
);
70 *sockaddr_len_p
= (ev_socklen_t
) 0U;
74 *sockaddr_len_p
= (ev_socklen_t
) sockaddr_len_int
;
80 proxy_context_init(ProxyContext
* const proxy_context
, int argc
, char *argv
[])
82 memset(proxy_context
, 0, sizeof *proxy_context
);
83 proxy_context
->event_loop
= NULL
;
84 proxy_context
->tcp_accept_timer
= NULL
;
85 proxy_context
->tcp_conn_listener
= NULL
;
86 proxy_context
->udp_listener_event
= NULL
;
87 proxy_context
->udp_proxy_resolver_event
= NULL
;
88 proxy_context
->udp_proxy_resolver_handle
= -1;
89 proxy_context
->udp_listener_handle
= -1;
90 if (options_parse(&app_context
, proxy_context
, argc
, argv
) != 0) {
95 WSAStartup(MAKEWORD(2, 2), &wsa_data
);
97 if ((proxy_context
->event_loop
= event_base_new()) == NULL
) {
98 logger(NULL
, LOG_ERR
, "Unable to initialize the event loop");
101 if (sockaddr_from_ip_and_port(&proxy_context
->resolver_sockaddr
,
102 &proxy_context
->resolver_sockaddr_len
,
103 proxy_context
->resolver_ip
,
104 proxy_context
->resolver_port
,
105 "Unsupported resolver address") != 0) {
108 if (sockaddr_from_ip_and_port(&proxy_context
->local_sockaddr
,
109 &proxy_context
->local_sockaddr_len
,
110 proxy_context
->local_ip
,
111 proxy_context
->local_port
,
112 "Unsupported local address") != 0) {
119 proxy_context_free(ProxyContext
* const proxy_context
)
121 if (proxy_context
== NULL
) {
124 options_free(proxy_context
);
125 logger_close(proxy_context
);
131 static char default_tz_for_putenv
[] = "TZ=UTC+00:00";
138 if ((tm
= localtime(&now
)) != NULL
&&
139 strftime(stbuf
, sizeof stbuf
, "%z", tm
) == (size_t) 5U) {
140 evutil_snprintf(default_tz_for_putenv
, sizeof default_tz_for_putenv
,
141 "TZ=UTC%c%c%c:%c%c", (*stbuf
== '-' ? '+' : '-'),
142 stbuf
[1], stbuf
[2], stbuf
[3], stbuf
[4]);
144 putenv(default_tz_for_putenv
);
145 (void) localtime(&now
);
152 revoke_privileges(ProxyContext
* const proxy_context
)
154 (void) proxy_context
;
156 salsa20_random_stir();
158 (void) strerror(ENOENT
);
160 if (proxy_context
->user_dir
!= NULL
) {
161 if (chdir(proxy_context
->user_dir
) != 0 ||
162 chroot(proxy_context
->user_dir
) != 0 || chdir("/") != 0) {
163 logger(proxy_context
, LOG_ERR
, "Unable to chroot to [%s]",
164 proxy_context
->user_dir
);
168 if (sandboxes_app() != 0) {
169 logger_noformat(proxy_context
, LOG_ERR
,
170 "Unable to sandbox the main process");
173 if (proxy_context
->user_id
!= (uid_t
) 0) {
174 if (setgid(proxy_context
->user_group
) != 0 ||
175 setegid(proxy_context
->user_group
) != 0 ||
176 setuid(proxy_context
->user_id
) != 0 ||
177 seteuid(proxy_context
->user_id
) != 0) {
178 logger(proxy_context
, LOG_ERR
, "Unable to switch to user id [%lu]",
179 (unsigned long) proxy_context
->user_id
);
188 dnscrypt_proxy_start_listeners(ProxyContext
* const proxy_context
)
190 char local_addr_s
[INET6_ADDRSTRLEN
+ sizeof "[]:65535"];
191 char resolver_addr_s
[INET6_ADDRSTRLEN
+ sizeof "[]:65535"];
193 if (proxy_context
->listeners_started
!= 0) {
196 if (udp_listener_start(proxy_context
) != 0 ||
197 tcp_listener_start(proxy_context
) != 0) {
200 evutil_format_sockaddr_port((const struct sockaddr
*)
201 &proxy_context
->local_sockaddr
,
202 local_addr_s
, sizeof local_addr_s
);
203 evutil_format_sockaddr_port((const struct sockaddr
*)
204 &proxy_context
->resolver_sockaddr
,
205 resolver_addr_s
, sizeof resolver_addr_s
);
206 logger(proxy_context
, LOG_INFO
, "Proxying from %s to %s",
207 local_addr_s
, resolver_addr_s
);
209 proxy_context
->listeners_started
= 1;
215 main(int argc
, char *argv
[])
217 ProxyContext proxy_context
;
219 setvbuf(stdout
, NULL
, _IOLBF
, BUFSIZ
);
220 stack_trace_on_crash();
221 if (proxy_context_init(&proxy_context
, argc
, argv
) != 0) {
222 logger_noformat(NULL
, LOG_ERR
, "Unable to start the proxy");
225 app_context
.proxy_context
= &proxy_context
;
226 logger_noformat(&proxy_context
, LOG_INFO
, "Generating a new key pair");
227 dnscrypt_client_init_with_new_key_pair(&proxy_context
.dnscrypt_client
);
228 logger_noformat(&proxy_context
, LOG_INFO
, "Done");
230 if (cert_updater_init(&proxy_context
) != 0 ||
231 udp_listener_bind(&proxy_context
) != 0 ||
232 tcp_listener_bind(&proxy_context
) != 0) {
236 signal(SIGPIPE
, SIG_IGN
);
239 revoke_privileges(&proxy_context
);
240 if (cert_updater_start(&proxy_context
) != 0) {
243 event_base_dispatch(proxy_context
.event_loop
);
245 logger_noformat(&proxy_context
, LOG_INFO
, "Stopping proxy");
246 cert_updater_free(&proxy_context
);
247 udp_listener_stop(&proxy_context
);
248 tcp_listener_stop(&proxy_context
);
249 event_base_free(proxy_context
.event_loop
);
250 proxy_context_free(&proxy_context
);
251 app_context
.proxy_context
= NULL
;
252 salsa20_random_close();