Allow naming hosts and add examples to rules.ml

Previously we passed in the interface, from which it was possible (but
a little difficult) to extract the IP address and compare with some
predefined ones. Now, we allow the user to list IP addresses and named
tags for them, which can be matched on easily.

Added example rules showing how to block access to an external service
or allow SSH between AppVMs.

Requested at
https://groups.google.com/d/msg/qubes-users/BnL0nZGpJOE/61HOBg1rCgAJ.
This commit is contained in:
Thomas Leonard 2019-04-11 12:25:19 +01:00
parent 433f3e8f01
commit acf46b4231
3 changed files with 47 additions and 5 deletions

View File

@ -125,9 +125,21 @@ let nat_to t ~host ~port packet =
(* Handle incoming packets *)
let parse_ips ips = List.map (fun (ip_str, id) -> (Ipaddr.of_string_exn ip_str, id)) ips
let clients = parse_ips Rules.clients
let externals = parse_ips Rules.externals
let resolve_host = function
| `Client c -> `Client (try List.assoc (Ipaddr.V4 c#other_ip) clients with Not_found -> `Unknown)
| `External ip -> `External (try List.assoc ip externals with Not_found -> `Unknown)
| (`Client_gateway | `Firewall_uplink | `NetVM) as x -> x
let apply_rules t rules info =
let packet = info.packet in
match rules info, info.dst with
let resolved_info = { info with src = resolve_host info.src;
dst = resolve_host info.dst } in
match rules resolved_info, info.dst with
| `Accept, `Client client_link -> transmit_ipv4 packet client_link
| `Accept, (`External _ | `NetVM) -> transmit_ipv4 packet t.Router.uplink
| `Accept, (`Firewall_uplink | `Client_gateway) ->

View File

@ -13,9 +13,15 @@ type ports = {
type host =
[ `Client of client_link | `Client_gateway | `Firewall_uplink | `NetVM | `External of Ipaddr.t ]
type info = {
(* Note: 'a is either [host], or the result of applying [Rules.clients] and [Rules.externals] to a host. *)
type 'a info = {
packet : Nat_packet.t;
src : host;
dst : host;
src : 'a;
dst : 'a;
proto : [ `UDP of ports | `TCP of ports | `ICMP | `Unknown ];
}
(* The first message in a TCP connection has SYN set and ACK clear. *)
let is_tcp_start = function
| `IPv4 (_ip, `TCP (hdr, _body)) -> Tcp.Tcp_packet.(hdr.syn && not hdr.ack)
| _ -> false

View File

@ -25,13 +25,37 @@ open Packet
- [`Drop reason] drop the packet and log the reason.
*)
(* List your AppVM IP addresses here if you want to match on them in the rules below.
Any client not listed here will appear as [`Client `Unknown]. *)
let clients = [
(*
"10.137.0.12", `Dev;
"10.137.0.14", `Untrusted;
*)
]
(* List your external (non-AppVM) IP addresses here if you want to match on them in the rules below.
Any external machine not listed here will appear as [`External `Unknown]. *)
let externals = [
(*
"8.8.8.8", `GoogleDNS;
*)
]
(** Decide what to do with a packet from a client VM.
Note: If the packet matched an existing NAT rule then this isn't called. *)
let from_client = function
(* Examples (add your own rules here): *)
(*
| { src = `Client `Dev; dst = `Client `Untrusted; proto = `TCP { dport = 22 } } -> `Accept
| { src = `Client _; dst = `Client _; proto = `TCP _; packet }
when not (is_tcp_start packet) -> `Accept
| { dst = `External `GoogleDNS } -> `Drop "block Google DNS"
*)
| { dst = (`External _ | `NetVM) } -> `NAT
| { dst = `Client_gateway; proto = `UDP { dport = 53 } } -> `NAT_to (`NetVM, 53)
| { dst = (`Client_gateway | `Firewall_uplink) } -> `Drop "packet addressed to firewall itself"
| { dst = `Client _ } -> `Drop "prevent communication between client VMs"
| { dst = `Client _ } -> `Drop "prevent communication between client VMs by default"
(** Decide what to do with a packet received from the outside world.
Note: If the packet matched an existing NAT rule then this isn't called. *)