Compare commits

...

4 commits

7 changed files with 62 additions and 7 deletions

View file

@ -236,7 +236,7 @@ This work was funded by [the EU NGI Assure Fund through NLnet](https://nlnet.nl/
In my opinion, this shows that funding one open source project can have a positive impact on other open source projects, too.
[robur]: https://robur.coop/
[miragevpn-server]: https://blog.robur.coop/articles/miragevpn-server.html
[miragevpn-server]: miragevpn-server.html
[contact]: https://reyn.ir/contact.html
[^openvpn-tls]: This is not always the case. It is possible to use static shared secret keys, but it is mostly considered deprecated.

View file

@ -16,7 +16,7 @@ author:
## Updating MirageVPN
As announced [earlier this month](https://blog.robur.coop/articles/miragevpn.html), we've been working hard over the last months on MirageVPN (initially developed in 2019, targeting OpenVPN™ 2.4.7, now 2.6.6). We managed to receive funding from [NGI Assure](https://www.assure.ngi.eu/) call (via [NLnet](https://nlnet.nl)). We've made over 250 commits with more than 10k lines added, and 18k lines removed. We closed nearly all old issues, and opened 100 fresh ones, of which we already closed more than half of them. :D
As announced [earlier this month](miragevpn.html), we've been working hard over the last months on MirageVPN (initially developed in 2019, targeting OpenVPN™ 2.4.7, now 2.6.6). We managed to receive funding from [NGI Assure](https://www.assure.ngi.eu/) call (via [NLnet](https://nlnet.nl)). We've made over 250 commits with more than 10k lines added, and 18k lines removed. We closed nearly all old issues, and opened 100 fresh ones, of which we already closed more than half of them. :D
### Actual bugs fixed (that were leading to non-working MirageVPN applications)
@ -29,7 +29,7 @@ To avoid any future breakage while revising the code (cleaning it up, extending
### New features: AEAD ciphers, supporting more configuration primitives
We added various configuration primitives, amongst them configuratble tls ciphersuites, minimal and maximal tls version to use, [tls-crypt-v2](https://blog.robur.coop/articles/miragevpn.html), verify-x509-name, cipher, remote-random, ...
We added various configuration primitives, amongst them configuratble tls ciphersuites, minimal and maximal tls version to use, [tls-crypt-v2](miragevpn.html), verify-x509-name, cipher, remote-random, ...
From a cryptographic point of view, we are now supporting more [authentication hashes](https://github.com/robur-coop/miragevpn/pull/108) via the configuration directive `auth`, namely the SHA2 family - previously, only SHA1 was supported, [AEAD ciphers](https://github.com/robur-coop/miragevpn/pull/125) (AES-128-GCM, AES-256-GCM, CHACHA20-POLY1305) - previously only AES-256-CBC was supported.

View file

@ -21,7 +21,7 @@ coauthors:
link: https://reyn.ir/
---
As we were busy continuing to work on [MirageVPN](https://github.com/robur-coop/miragevpn), we got in touch with [eduVPN](https://eduvpn.org), who are interested about deploying MirageVPN. We got example configuration from their side, and [fixed](https://github.com/robur-coop/miragevpn/pull/201) [some](https://github.com/robur-coop/miragevpn/pull/168) [issues](https://github.com/robur-coop/miragevpn/pull/202), and also implemented [tls-crypt](https://github.com/robur-coop/miragevpn/pull/169) - which was straightforward since we earlier spend time to implement [tls-crypt-v2](https://blog.robur.coop/articles/miragevpn.html).
As we were busy continuing to work on [MirageVPN](https://github.com/robur-coop/miragevpn), we got in touch with [eduVPN](https://eduvpn.org), who are interested about deploying MirageVPN. We got example configuration from their side, and [fixed](https://github.com/robur-coop/miragevpn/pull/201) [some](https://github.com/robur-coop/miragevpn/pull/168) [issues](https://github.com/robur-coop/miragevpn/pull/202), and also implemented [tls-crypt](https://github.com/robur-coop/miragevpn/pull/169) - which was straightforward since we earlier spend time to implement [tls-crypt-v2](miragevpn.html).
In January, they gave MirageVPN another try, and [measured the performance](https://github.com/robur-coop/miragevpn/issues/206) -- which was very poor -- MirageVPN (run as a Unix binary) provided a bandwith of 9.3Mb/s, while OpenVPN provided a bandwidth of 360Mb/s (using a VPN tunnel over TCP).
@ -45,7 +45,7 @@ The learnings of our performance engineering are in three areas:
## Conclusion
To conclude: we already achieved a factor of 25 in performance by adapting the code in various ways. We have ideas to improve the performance even more in the future - we also work on using OCaml string and bytes, instead of off-the-OCaml-heap-allocated bigarrays (see [our previous article](https://blog.robur.coop/articles/speeding-ec-string.html), which provided some speedups).
To conclude: we already achieved a factor of 25 in performance by adapting the code in various ways. We have ideas to improve the performance even more in the future - we also work on using OCaml string and bytes, instead of off-the-OCaml-heap-allocated bigarrays (see [our previous article](speeding-ec-string.html), which provided some speedups).
Don't hesitate to reach out to us on [GitHub](https://github.com/robur-coop/miragevpn/issues), or [by mail](https://robur.coop/Contact) if you're stuck.

View file

@ -22,7 +22,7 @@ coauthors:
It is a great pleasure to finally announce that we have finished a server implementation for MirageVPN (OpenVPN™-compatible). This allows to setup a very robust VPN network on both the client and the server side.
As announced last year, [MirageVPN](https://blog.robur.coop/articles/miragevpn.html) is a reimplemtation of OpenVPN™ in OCaml, with [MirageOS](https://mirage.io) unikernels.
As announced last year, [MirageVPN](miragevpn.html) is a reimplemtation of OpenVPN™ in OCaml, with [MirageOS](https://mirage.io) unikernels.
## Why a MirageVPN server?

View file

@ -0,0 +1,54 @@
---
date: 2024-06-26
title: Testing MirageVPN against OpenVPN™
description: Some notes about how we test MirageVPN against OpenVPN™
tags:
- OCaml
- MirageOS
- cryptography
- security
- testing
- vpn
author:
name: Reynir Björnsson
email: reynir@reynir.dk
link: https://reyn.ir/
---
As our last milestone for the [EU NGI Assure](https://www.assure.ngi.eu/) funded MirageVPN project (for now) we have been working on testing MirageVPN, our OpenVPN™-compatible VPN implementation against the upstream OpenVPN™.
During the development we have conducted many manual tests.
However, this scales poorly and it is easy to forget testing certain cases.
Therefore, we designed and implemented interoperability testing, driving the C implementation on the one side, and our OCaml implementation on the other side. The input for such a test is a configuration file that both implementations can use.
Thus we test establishment of the tunnel as well as the tunnel itself.
While conducting the tests, our instrumented binaries expose code coverage information. We use that to guide ourselves which other configurations are worth testing. Our goal is to achieve a high code coverage rate while using a small amount of different configurations. These interoperability tests are running fast enough, so they are executed on each commit by CI.
A nice property of this test setup is that it runs with an unmodified OpenVPN binary.
This means we can use an off-the-shelf OpenVPN binary from the package repository and does not entail further maintenance of an OpenVPN fork.
Testing against a future version of OpenVPN becomes trivial.
We do not just test a single part of our implementation but achieve an end-to-end test.
The same configuration files are used for both our implementation and the C implementation, and each configuration is used twice, once our implementation acts as the client, once as the server.
We added a flag to our client and our [recently finished server](miragevpn-server) applications, `--test`, which make them to exit once a tunnel is established and an ICMP echo request from the client has been replied to by the server.
Our client and server can be run without a tun device which otherwise would require elevated privileges.
Unfortunately, OpenVPN requires privileges to at least configure a tun device.
Our MirageVPN implementation does IP packet parsing in userspace.
We test our protocol implementation, not the entire unikernel - but the unikernel code is a tiny layer on top of the purely functional protocol implementation.
We explored unit testing the packet decoding and decryption with our implementation and the C implementation.
Specifically, we encountered a packet whose message authentication code (MAC) was deemed invalid by the C implementation.
It helped us discover the MAC computation was correct but the packet encoding was truncated - both implementations agreed that the MAC was bad.
The test was very tedious to write and would not easily scale to cover a large portion of the code.
If of interest, take a look into our [modifications to OpenVPN](https://github.com/reynir/openvpn/tree/badmac-test) and [modifications to MirageVPN](https://github.com/robur-coop/miragevpn/tree/badmac-test).
The end-to-end testing is in addition to our unit tests and fuzz testing; and to our [benchmarking](miragevpn-performance.html) binary.
Our results are that with 4 configurations we achieve above 75% code coverage in MirageVPN.
While investigating the code coverage results, we found various pieces of code that were never executed, and we were able to remove them.
Code that does not exist is bug-free :D
With these tests in place future maintenance is less daunting as they will help us guard us from breaking the code.
At the moment we do not exercise the error paths very well in the code.
This is much less straightforward to test in this manner, and is important future work.
We plan to develop a client and server that injects faults at various stages of the protocol to test these error paths.
OpenVPN built with debugging enabled also comes with a `--gremlin` mode that injects faults, and would be interesting to investigate.

View file

@ -445,6 +445,7 @@ module Tags = struct
class tags ?title ?description articles =
object
inherit Articles.articles ?title ?description articles as super
method! title = Some "Tags"
method tags =
let tags =
let update article sm tag =

View file

@ -5,7 +5,7 @@
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>
Robur's blog{{ dash }}{{ title }}
Robur's blog - {{ title }}
</title>
<meta name="description" content="{{ description }}">
<link type="text/css" rel="stylesheet" href="/css/hl.css">