@@ -7,7 +7,7 @@ type 'a env = <
7
7
..
8
8
> as 'a
9
9
10
- type io_addr = Ipaddr .t * int
10
+ type io_addr = [ `Plaintext of Ipaddr .t * int | `Tls of Tls.Config .client * Ipaddr .t * int ]
11
11
type stack = {
12
12
sw : Eio.Switch .t ;
13
13
mono_clock : Eio.Time.Mono .t ;
@@ -40,7 +40,7 @@ module Transport : Dns_client.S
40
40
and context =
41
41
{ t : t
42
42
; mutable requests : Cstruct .t Eio.Promise .u IM .t
43
- ; mutable ns_connection : < Eio.Net .stream_socket ; Eio. Flow.close >
43
+ ; mutable ns_connection : < Eio.Flow .two_way >
44
44
; mutable buf : Cstruct .t
45
45
}
46
46
@@ -64,16 +64,35 @@ module Transport : Dns_client.S
64
64
let ( let * ) = Result. bind
65
65
let ( let+ ) r f = Result. map f r
66
66
67
+ let authenticator =
68
+ let authenticator_ref = ref None in
69
+ fun () ->
70
+ match ! authenticator_ref with
71
+ | Some x -> x
72
+ | None -> match Ca_certs. authenticator () with
73
+ | Ok a -> authenticator_ref := Some a ; a
74
+ | Error `Msg m -> invalid_arg (" failed to load trust anchors: " ^ m)
75
+
67
76
let decode_resolv_conf data =
68
77
let * ips = Dns_resolvconf. parse data in
78
+ let authenticator = authenticator () in
69
79
match ips with
70
80
| [] -> Error (`Msg " empty nameservers from resolv.conf" )
71
- | ips -> Ok (List. map (function `Nameserver ip -> (ip, 53 )) ips)
81
+ | ips ->
82
+ List. map
83
+ (function `Nameserver ip ->
84
+ let tls_config = Tls.Config. client ~authenticator ~ip () in
85
+ [`Plaintext (ip, 53 ); `Tls (tls_config, ip, 853 )]
86
+ )
87
+ ips
88
+ |> List. flatten
89
+ |> Result. ok
72
90
73
- let default_resolvers =
74
- List. (map
75
- (fun ip -> (ip, 53 ))
76
- ((::) (Ipaddr. of_string_exn " 1.1.1.1" , Dns_client. default_resolvers)))
91
+ let default_resolvers () =
92
+ let authenticator = authenticator () in
93
+ let peer_name = Dns_client. default_resolver_hostname in
94
+ let tls_config = Tls.Config. client ~authenticator ~peer_name () in
95
+ List. map (fun ip -> `Tls (tls_config, ip, 853 )) Dns_client. default_resolvers
77
96
78
97
let rng = Mirage_crypto_rng. generate ?g:None
79
98
let clock = Mtime_clock. elapsed_ns
@@ -82,14 +101,14 @@ module Transport : Dns_client.S
82
101
{ nameservers =
83
102
(match nameservers with
84
103
| Some (`Udp,_ ) -> invalid_arg " UDP is not supported"
85
- | Some (`Tcp, [] ) -> Static default_resolvers
104
+ | Some (`Tcp, [] ) -> Static ( default_resolvers () )
86
105
| Some (`Tcp, ns ) -> Static ns
87
106
| None ->
88
107
(let * data = read_file stack.resolv_conf in
89
108
let + ips = decode_resolv_conf data in
90
109
(ips, Some (Digest. string data)))
91
110
|> function
92
- | Error _ -> Resolv_conf { ips = default_resolvers; digest = None }
111
+ | Error _ -> Resolv_conf { ips = default_resolvers () ; digest = None }
93
112
| Ok (ips , digest ) -> Resolv_conf {ips; digest})
94
113
; stack
95
114
; timeout = Eio.Time.Timeout. v stack.mono_clock @@ Mtime.Span. of_uint64_ns timeout
@@ -112,7 +131,7 @@ module Transport : Dns_client.S
112
131
resolv_conf.ips < - ips;
113
132
| Error _ ->
114
133
resolv_conf.digest < - None ;
115
- resolv_conf.ips < - default_resolvers
134
+ resolv_conf.ips < - default_resolvers ()
116
135
in
117
136
match t.nameservers with
118
137
| Static _ -> ()
@@ -125,9 +144,16 @@ module Transport : Dns_client.S
125
144
| Error _ , None -> ()
126
145
| Error _ , Some _ ->
127
146
resolv_conf.digest < - None ;
128
- resolv_conf.ips < - default_resolvers)
147
+ resolv_conf.ips < - default_resolvers () )
148
+
149
+ let find_ns t (ip , port ) =
150
+ List. find
151
+ (function `Plaintext (ip', p)
152
+ | `Tls (_ , ip' , p ) -> Ipaddr. compare ip ip' = 0 && p = port
153
+ )
154
+ (nameserver_ips t)
129
155
130
- let rec he_handle_actions t he actions =
156
+ let rec he_handle_actions t he actions : #Eio.Flow.two_way option =
131
157
let fiber_of_action = function
132
158
| Happy_eyeballs. Connect (host , id , (ip , port )) ->
133
159
fun () ->
@@ -144,6 +170,11 @@ module Transport : Dns_client.S
144
170
let flow = Eio.Net. connect ~sw: t.stack.sw t.stack.net stream in
145
171
Log. debug (fun m -> m " he_handle_actions: connected to nameserver (%a)"
146
172
Fmt. (pair ~sep: comma Ipaddr. pp int ) (ip, port));
173
+ let flow =
174
+ match find_ns t (ip, port) with
175
+ | `Plaintext _ -> (flow :> Eio.Flow.two_way )
176
+ | `Tls (config , _ ,_ ) -> (Tls_eio. client_of_flow config flow :> Eio.Flow.two_way )
177
+ in
147
178
Some flow)
148
179
with Eio.Time. Timeout ->
149
180
Log. debug (fun m -> m " he_handle_actions: connection to nameserver (%a) timed out"
@@ -163,6 +194,9 @@ module Transport : Dns_client.S
163
194
in
164
195
Eio.Fiber. any (List. map fiber_of_action actions)
165
196
197
+ let to_ip_port =
198
+ List. map (function `Plaintext (ip , port ) -> (ip, port) | `Tls (_ , ip , port ) -> (ip, port))
199
+
166
200
let rec connect t =
167
201
Log. debug (fun m -> m " connect : establishing connection to nameservers" );
168
202
match t.ctx, t.ns_connection_condition with
@@ -174,15 +208,15 @@ module Transport : Dns_client.S
174
208
let ns_connection_condition = Eio.Condition. create () in
175
209
t.ns_connection_condition < - Some ns_connection_condition;
176
210
maybe_update_nameservers t;
177
- let ns = nameserver_ips t in
211
+ let ns = to_ip_port @@ nameserver_ips t in
178
212
let he = Happy_eyeballs. create (clock () ) in
179
213
let he, actions = Happy_eyeballs. connect_ip he (clock () ) ~id: 1 ns in
180
214
begin match he_handle_actions t he actions with
181
- | Some ns_connection ->
215
+ | Some conn ->
182
216
let context =
183
217
{ t = t
184
218
; requests = IM. empty
185
- ; ns_connection
219
+ ; ns_connection = conn
186
220
; buf = Cstruct. empty
187
221
}
188
222
in
@@ -195,7 +229,7 @@ module Transport : Dns_client.S
195
229
let error_msg =
196
230
Fmt. str " unable to connect to nameservers %a"
197
231
Fmt. (list ~sep: (any " , " ) (pair ~sep: (any " :" ) Ipaddr. pp int ))
198
- (nameserver_ips t)
232
+ (to_ip_port @@ nameserver_ips t)
199
233
in
200
234
Logs. debug (fun m -> m " connect : %s" error_msg);
201
235
Error (`Msg error_msg)
@@ -249,7 +283,7 @@ module Transport : Dns_client.S
249
283
Error (`Msg " Invalid DNS query packet (data length <= 4)" )
250
284
251
285
let send_recv ctx packet =
252
- let * () = validate_query_packet packet in
286
+ let * () = validate_query_packet packet in
253
287
try
254
288
let request_id = Cstruct.BE. get_uint16 packet 2 in
255
289
Eio.Time.Timeout. run_exn ctx.t.timeout (fun () ->
0 commit comments