Skip to content

Commit 1ac5951

Browse files
authored
Merge pull request #322 from djs55/internal-ip
Separate the localhost proxy from internal services
2 parents be714e6 + eb5c995 commit 1ac5951

11 files changed

+217
-114
lines changed

Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ vpnkit.exe:
4242
.PHONY: test
4343
test:
4444
jbuilder build --dev src/hostnet_test/main.exe
45-
./_build/default/src/hostnet_test/main.exe
45+
# One test requires 1026 file descriptors
46+
ulimit -n 1500 && ./_build/default/src/hostnet_test/main.exe
4647

4748
.PHONY: OSS-LICENSES
4849
OSS-LICENSES:

scripts/common.sh

-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ opam install $(ls -1 ${OPAM_REPO}/packages/upstream) -y
3737
OPAMVERBOSE=1 opam install --deps-only -t vpnkit -y
3838

3939
OPAMVERBOSE=1 make
40-
# One test requires 1026 file descriptors
41-
ulimit -n 1500
4240
OPAMVERBOSE=1 make test
4341
OPAMVERBOSE=1 make artefacts
4442
OPAMVERBOSE=1 make OSS-LICENSES

src/bin/main.ml

+26-5
Original file line numberDiff line numberDiff line change
@@ -339,9 +339,9 @@ let hvsock_addr_of_uri ~default_serviceid uri =
339339

340340
let main
341341
socket_url port_control_url introspection_url diagnostics_url
342-
max_connections vsock_path db_path db_branch dns http hosts host_names
342+
max_connections vsock_path db_path db_branch dns http hosts host_names gateway_names
343343
listen_backlog port_max_idle_time debug
344-
server_macaddr domain allowed_bind_addresses gateway_ip lowest_ip highest_ip
344+
server_macaddr domain allowed_bind_addresses gateway_ip host_ip lowest_ip highest_ip
345345
dhcp_json_path mtu log_destination
346346
=
347347
let level =
@@ -358,19 +358,23 @@ let hvsock_addr_of_uri ~default_serviceid uri =
358358
end;
359359

360360
let host_names = List.map Dns.Name.of_string @@ Astring.String.cuts ~sep:"," host_names in
361+
let gateway_names = List.map Dns.Name.of_string @@ Astring.String.cuts ~sep:"," gateway_names in
362+
361363
let dns_path, resolver = match dns with
362364
| None -> None, Configuration.default_resolver
363365
| Some file -> Some file, `Upstream in
364366
let server_macaddr = Macaddr.of_string_exn server_macaddr in
365367
let allowed_bind_addresses = Configuration.Parse.ipv4_list [] allowed_bind_addresses in
366368
let gateway_ip = Ipaddr.V4.of_string_exn gateway_ip in
369+
let host_ip = Ipaddr.V4.of_string_exn host_ip in
367370
let lowest_ip = Ipaddr.V4.of_string_exn lowest_ip in
368371
let highest_ip = Ipaddr.V4.of_string_exn highest_ip in
369372
let configuration = {
370373
Configuration.default with
371374
max_connections;
372375
port_max_idle_time;
373376
host_names;
377+
gateway_names;
374378
dns = Configuration.no_dns_servers;
375379
dns_path;
376380
http_intercept_path = http;
@@ -379,6 +383,7 @@ let hvsock_addr_of_uri ~default_serviceid uri =
379383
domain;
380384
allowed_bind_addresses;
381385
gateway_ip;
386+
host_ip;
382387
lowest_ip;
383388
highest_ip;
384389
dhcp_json_path;
@@ -526,7 +531,15 @@ let host_names =
526531
"Comma-separated list of DNS names to map to the Host's virtual IP"
527532
["host-names"]
528533
in
529-
Arg.(value & opt string "vpnkit.host" doc)
534+
Arg.(value & opt string "host.internal" doc)
535+
536+
let gateway_names =
537+
let doc =
538+
Arg.info ~doc:
539+
"Comma-separated list of DNS names to map to the gateway's virtual IP"
540+
["gateway-names"]
541+
in
542+
Arg.(value & opt string "gateway.internal" doc)
530543

531544
let listen_backlog =
532545
let doc = "Specify a maximum listen(2) backlog. If no override is specified \
@@ -567,6 +580,14 @@ let gateway_ip =
567580
in
568581
Arg.(value & opt string (Ipaddr.V4.to_string Configuration.default_gateway_ip) doc)
569582

583+
let host_ip =
584+
let doc =
585+
Arg.info ~doc:
586+
"IP address which represents the host. Connections to this IP will be forwarded to localhost on the host."
587+
[ "host-ip" ]
588+
in
589+
Arg.(value & opt string (Ipaddr.V4.to_string Configuration.default_host_ip) doc)
590+
570591
let lowest_ip =
571592
let doc =
572593
Arg.info ~doc:
@@ -609,8 +630,8 @@ let command =
609630
Term.(pure main
610631
$ socket $ port_control_path $ introspection_path $ diagnostics_path
611632
$ max_connections $ vsock_path $ db_path $ db_branch $ dns $ http $ hosts
612-
$ host_names $ listen_backlog $ port_max_idle_time $ debug
613-
$ server_macaddr $ domain $ allowed_bind_addresses $ gateway_ip
633+
$ host_names $ gateway_names $ listen_backlog $ port_max_idle_time $ debug
634+
$ server_macaddr $ domain $ allowed_bind_addresses $ gateway_ip $ host_ip
614635
$ lowest_ip $ highest_ip $ dhcp_json_path $ mtu $ Logging.log_destination),
615636
Term.info (Filename.basename Sys.argv.(0)) ~version:"%%VERSION%%" ~doc ~man
616637

src/hostnet/configuration.ml

+11-6
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,22 @@ type t = {
4141
domain: string option;
4242
allowed_bind_addresses: Ipaddr.V4.t list;
4343
gateway_ip: Ipaddr.V4.t;
44+
host_ip: Ipaddr.V4.t;
4445
(* TODO: remove this from the record since it is not constant across all clients *)
4546
lowest_ip: Ipaddr.V4.t;
4647
highest_ip: Ipaddr.V4.t;
47-
extra_dns: Ipaddr.V4.t list;
4848
dhcp_json_path: string option;
4949
dhcp_configuration: Dhcp_configuration.t option;
5050
mtu: int;
5151
http_intercept: Ezjsonm.value option;
5252
http_intercept_path: string option;
5353
port_max_idle_time: int;
5454
host_names: Dns.Name.t list;
55+
gateway_names: Dns.Name.t list;
5556
}
5657

5758
let to_string t =
58-
Printf.sprintf "server_macaddr = %s; max_connection = %s; dns_path = %s; dns = %s; resolver = %s; domain = %s; allowed_bind_addresses = %s; gateway_ip = %s; lowest_ip = %s; highest_ip = %s; extra_dns = %s; dhcp_json_path = %s; dhcp_configuration = %s; mtu = %d; http_intercept = %s; http_intercept_path = %s; port_max_idle_time = %s; host_names = %s"
59+
Printf.sprintf "server_macaddr = %s; max_connection = %s; dns_path = %s; dns = %s; resolver = %s; domain = %s; allowed_bind_addresses = %s; gateway_ip = %s; host_ip = %s; lowest_ip = %s; highest_ip = %s; dhcp_json_path = %s; dhcp_configuration = %s; mtu = %d; http_intercept = %s; http_intercept_path = %s; port_max_idle_time = %s; host_names = %s; gateway_name = %s"
5960
(Macaddr.to_string t.server_macaddr)
6061
(match t.max_connections with None -> "None" | Some x -> string_of_int x)
6162
(match t.dns_path with None -> "None" | Some x -> x)
@@ -64,24 +65,25 @@ let to_string t =
6465
(match t.domain with None -> "None" | Some x -> x)
6566
(String.concat ", " (List.map Ipaddr.V4.to_string t.allowed_bind_addresses))
6667
(Ipaddr.V4.to_string t.gateway_ip)
68+
(Ipaddr.V4.to_string t.host_ip)
6769
(Ipaddr.V4.to_string t.lowest_ip)
6870
(Ipaddr.V4.to_string t.highest_ip)
69-
(String.concat ", " (List.map Ipaddr.V4.to_string t.extra_dns))
7071
(match t.dhcp_json_path with None -> "None" | Some x -> x)
7172
(match t.dhcp_configuration with None -> "None" | Some x -> Dhcp_configuration.to_string x)
7273
t.mtu
7374
(match t.http_intercept with None -> "None" | Some x -> Ezjsonm.(to_string @@ wrap x))
7475
(match t.http_intercept_path with None -> "None" | Some x -> x)
7576
(string_of_int t.port_max_idle_time)
7677
(String.concat ", " (List.map Dns.Name.to_string t.host_names))
78+
(String.concat ", " (List.map Dns.Name.to_string t.gateway_names))
7779

7880
let no_dns_servers =
7981
Dns_forward.Config.({ servers = Server.Set.empty; search = []; assume_offline_after_drops = None })
8082

81-
let default_lowest_ip = Ipaddr.V4.of_string_exn "192.168.65.2"
83+
let default_lowest_ip = Ipaddr.V4.of_string_exn "192.168.65.3"
8284
let default_gateway_ip = Ipaddr.V4.of_string_exn "192.168.65.1"
85+
let default_host_ip = Ipaddr.V4.of_string_exn "192.168.65.2"
8386
let default_highest_ip = Ipaddr.V4.of_string_exn "192.168.65.254"
84-
let default_extra_dns = []
8587
(* The default MTU is limited by the maximum message size on a Hyper-V
8688
socket. On currently available windows versions, we need to stay
8789
below 8192 bytes *)
@@ -90,6 +92,8 @@ let default_port_max_idle_time = 300
9092
(* random MAC from https://www.hellion.org.uk/cgi-bin/randmac.pl *)
9193
let default_server_macaddr = Macaddr.of_string_exn "F6:16:36:BC:F9:C6"
9294
let default_host_names = [ Dns.Name.of_string "vpnkit.host" ]
95+
let default_gateway_names = [ Dns.Name.of_string "gateway.internal" ]
96+
9397
let default_resolver = `Host
9498

9599
let default = {
@@ -101,16 +105,17 @@ let default = {
101105
domain = None;
102106
allowed_bind_addresses = [];
103107
gateway_ip = default_gateway_ip;
108+
host_ip = default_host_ip;
104109
lowest_ip = default_lowest_ip;
105110
highest_ip = default_highest_ip;
106-
extra_dns = default_extra_dns;
107111
dhcp_json_path = None;
108112
dhcp_configuration = None;
109113
mtu = default_mtu;
110114
http_intercept = None;
111115
http_intercept_path = None;
112116
port_max_idle_time = default_port_max_idle_time;
113117
host_names = default_host_names;
118+
gateway_names = default_gateway_names;
114119
}
115120

116121
module Parse = struct

src/hostnet/hostnet_dhcp.ml

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ module Make (Clock: Mirage_clock_lwt.MCLOCK) (Netif: Mirage_net_lwt.S) = struct
4646
resolved in the future *)
4747
let low_ip, high_ip =
4848
let open Ipaddr.V4 in
49-
let all_static_ips = c.Configuration.gateway_ip :: c.Configuration.lowest_ip :: c.Configuration.extra_dns in
49+
let all_static_ips = [ c.Configuration.gateway_ip; c.Configuration.lowest_ip ] in
5050
let highest = maximum_ip all_static_ips in
5151
let i32 = to_int32 highest in
5252
of_int32 @@ Int32.succ i32, of_int32 @@ Int32.succ @@ Int32.succ i32 in
@@ -73,7 +73,7 @@ module Make (Clock: Mirage_clock_lwt.MCLOCK) (Netif: Mirage_net_lwt.S) = struct
7373
| _, _ -> Configuration.default_domain in
7474
let options = [
7575
Dhcp_wire.Routers [ c.Configuration.gateway_ip ];
76-
Dhcp_wire.Dns_servers (c.Configuration.gateway_ip :: c.Configuration.extra_dns);
76+
Dhcp_wire.Dns_servers [ c.Configuration.gateway_ip ];
7777
Dhcp_wire.Ntp_servers [ c.Configuration.gateway_ip ];
7878
Dhcp_wire.Broadcast_addr (Ipaddr.V4.Prefix.broadcast prefix);
7979
Dhcp_wire.Subnet_mask (Ipaddr.V4.Prefix.netmask prefix);

src/hostnet/hostnet_dns.ml

+33-18
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,31 @@ let try_etc_hosts =
135135
end
136136
| _ -> None
137137

138-
let try_builtins local_ip host_names question =
138+
let try_builtins builtin_names question =
139139
let open Dns.Packet in
140-
match local_ip, question with
141-
| Ipaddr.V4 local_ip, { q_class = Q_IN; q_type = (Q_A|Q_AAAA); q_name; _ }
142-
when List.mem q_name host_names ->
143-
Log.info (fun f ->
144-
f "DNS: %s is a builtin: %a" (Dns.Name.to_string q_name)
145-
Ipaddr.V4.pp_hum local_ip);
146-
Some [ { name = q_name; cls = RR_IN; flush = false; ttl = 0l;
147-
rdata = A local_ip } ]
140+
match question with
141+
| { q_class = Q_IN; q_type = (Q_A|Q_AAAA); q_name; _ } ->
142+
let bindings = List.filter (fun (name, _) -> name = q_name) builtin_names in
143+
let ipv4_rrs =
144+
List.fold_left (fun acc (_, ip) ->
145+
match ip with
146+
| Ipaddr.V4 ipv4 -> { name = q_name; cls = RR_IN; flush = false; ttl = 0l; rdata = A ipv4 } :: acc
147+
| _ -> acc
148+
) [] bindings in
149+
let ipv6_rrs =
150+
List.fold_left (fun acc (_, ip) ->
151+
match ip with
152+
| Ipaddr.V6 ipv6 -> { name = q_name; cls = RR_IN; flush = false; ttl = 0l; rdata = AAAA ipv6 } :: acc
153+
| _ -> acc
154+
) [] bindings in
155+
let rrs = if question.q_type = Q_A then ipv4_rrs else ipv6_rrs in
156+
if rrs = [] then None else begin
157+
Log.info (fun f ->
158+
f "DNS: %s is a builtin: %s" (Dns.Name.to_string q_name)
159+
(String.concat "; " (List.map (fun rr -> Dns.Packet.rr_to_string rr) rrs))
160+
);
161+
Some rrs
162+
end
148163
| _ -> None
149164

150165
module Make
@@ -191,7 +206,7 @@ struct
191206

192207
type t = {
193208
local_ip: Ipaddr.t;
194-
host_names: Dns.Name.t list;
209+
builtin_names: (Dns.Name.t * Ipaddr.t) list;
195210
resolver: resolver;
196211
}
197212

@@ -271,13 +286,13 @@ struct
271286
| None ->
272287
Random.int bound
273288

274-
let create ~local_address ~host_names =
289+
let create ~local_address ~builtin_names =
275290
let local_ip = local_address.Dns_forward.Config.Address.ip in
276291
Log.info (fun f ->
277-
let prefix = match host_names with
278-
| [] -> "No DNS names"
279-
| _ -> Printf.sprintf "DNS names [ %s ]" (String.concat ", " @@ List.map Dns.Name.to_string host_names) in
280-
f "%s will map to local IP %s" prefix (Ipaddr.to_string local_ip));
292+
let suffix = match builtin_names with
293+
| [] -> "no builtin DNS names; everything will be forwarded"
294+
| _ -> Printf.sprintf "builtin DNS names [ %s ]" (String.concat ", " @@ List.map (fun (name, ip) -> Dns.Name.to_string name ^ " -> " ^ (Ipaddr.to_string ip)) builtin_names) in
295+
f "DNS server configured with %s" suffix);
281296
fun clock -> function
282297
| `Upstream config ->
283298
let open Dns_forward.Config.Address in
@@ -300,11 +315,11 @@ struct
300315
>>= fun dns_udp_resolver ->
301316
Dns_tcp_resolver.create ~gen_transaction_id ~message_cb config clock
302317
>>= fun dns_tcp_resolver ->
303-
Lwt.return { local_ip; host_names;
318+
Lwt.return { local_ip; builtin_names;
304319
resolver = Upstream { dns_tcp_resolver; dns_udp_resolver } }
305320
| `Host ->
306321
Log.info (fun f -> f "Will use the host's DNS resolver");
307-
Lwt.return { local_ip; host_names; resolver = Host }
322+
Lwt.return { local_ip; builtin_names; resolver = Host }
308323

309324
let answer t is_tcp buf =
310325
let open Dns.Packet in
@@ -327,7 +342,7 @@ struct
327342
| Some answers ->
328343
Lwt.return (Ok (marshal @@ reply answers))
329344
| None ->
330-
match try_builtins t.local_ip t.host_names question with
345+
match try_builtins t.builtin_names question with
331346
| Some answers ->
332347
Lwt.return (Ok (marshal @@ reply answers))
333348
| None ->

src/hostnet/hostnet_dns.mli

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ sig
2626

2727
val create:
2828
local_address:Dns_forward.Config.Address.t ->
29-
host_names:Dns.Name.t list ->
29+
builtin_names:(Dns.Name.t * Ipaddr.t) list ->
3030
Clock.t -> Config.t -> t Lwt.t
3131
(** Create a DNS forwarding instance based on the given
3232
configuration, either [`Upstream config]: send DNS requests to

0 commit comments

Comments
 (0)