mirage/qubes-mirage-firewall

fragmented ip handling

Closed this issue · 4 comments

it seems there are still some basic problems with the mfw IP stack.
todays variant: fragmented packets.

the tests are against a 20190727 (today) build in templated mode.
the test commands are run in a (fedora-29) vm below the mirage-vm.
the log lines are from mfw-console-logs in dom0.
i am not pasting the hex dumps because afaict they dont matter and are easy to reproduce if anyone cares...

$ traceroute -U 8.8.8.8 2000

2019-07-27 18:33:40 -00:00: WRN [client_net] Ignored unknown IPv4 message: Failed to parse UDP packet: UDP header claimed a payload longer than the supplied buffer: 1972 vs 1480.
2019-07-27 18:33:40 -00:00: WRN [client_net] Ignored unknown IPv4 message: Failed to parse UDP packet: UDP header claimed a payload longer than the supplied buffer: 17469 vs 500.

the second line is almost more scary, because that means it tries to parse the payload/data of the second fragment as a header.

when using icmp instead (traceroute with -I instead of -U or "ping -s 2000 8.8.8.8") the failure pattern is mostly the same, except it doesnt complain about the first fragment with either a 20190727 nor 20190226 (pre #31) build.

and proactively pinging @yomimono on this.

note this is the other direction compared to #31, it already falls on its face while the pakets are coming from the inside.

also pinging @hannesm because of mirage/mirage-tcpip#375

hi @xaki23, thanks for your report. unfortunately I don't have a qubesos machine at my hands, so I can't reproduce or fix this issue. from reading the source code, here are my observations:

from my understanding, the flow for packets goes through:
Client_net.add_vif calling Netback.listen, parsing received ethernet frames, and then depending on the ethertype input_arp or input_ipv4 in the same module.

input_ipv4 then uses Nat_packet.of_ipv4_packet to parse the IPv4 payload, and could benefit from using a Fragments.t cache (https://github.com/mirage/mirage-tcpip/blob/master/src/ipv4/fragments.mli) before that (which offers a single function process, taking a cache, a timestamp, an IPv4 packet and its payload, and returning optionally an IPv4 packet and its payload). It looks to me that atm nothing takes a look at the offset and more fragments bits (which the Fragments module is for). the cache should be kept at a vif-local data structure (using some reasonable maximum capacity -- MirageOS' IPv4 host stack uses 256kB (in Static_ipv4.connect), and has a limit of 16 IPv4 fragments where the delta between first and last must not exceed 10 seconds).

hi @xaki23, thanks for your report. unfortunately I don't have a qubesos machine at my hands, so I can't reproduce or fix this issue. from reading the source code, here are my observations:

fortunately, that excuse is of limited validity when dealing with organized virtualization fanatics. :P

see mail/irc for how to access your dedicated personal qubes-mirage-firewall build-and-test env!

just fwiw, thanks to @xaki23 https://github.com/hannesm/mirage-nat/tree/fragment and https://github.com/hannesm/qubes-mirage-firewall/tree/fragmentation allow fragmentation (in a rather poor / hackish) way -- I suspect for proper support there should be some API changes in mirage-nat (to avoid reparsing packets) ; and things like mtu being exposed from "class type interface"