forked from robur/blog.robur.coop
68 lines
5.4 KiB
HTML
68 lines
5.4 KiB
HTML
|
<!doctype html>
|
||
|
<html lang="en">
|
||
|
<head>
|
||
|
<meta charset="utf-8">
|
||
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
|
<title>
|
||
|
Robur's blog - Testing MirageVPN against OpenVPN™
|
||
|
</title>
|
||
|
<meta name="description" content="Some notes about how we test MirageVPN against OpenVPN™">
|
||
|
<link type="text/css" rel="stylesheet" href="/css/hl.css">
|
||
|
<link type="text/css" rel="stylesheet" href="/css/style.css">
|
||
|
<script src="/js/hl.js"></script>
|
||
|
<link rel="alternate" type="application/rss+xml" href="/feed.xml" title="blog.robur.coop">
|
||
|
</head>
|
||
|
<body>
|
||
|
<header>
|
||
|
<h1>blog.robur.coop</h1>
|
||
|
<blockquote>
|
||
|
The <strong>Robur</strong> cooperative blog.
|
||
|
</blockquote>
|
||
|
</header>
|
||
|
<main><a href="/index.html">Back to index</a>
|
||
|
|
||
|
<article>
|
||
|
<h1>Testing MirageVPN against OpenVPN™</h1>
|
||
|
<ul class="tags-list"><li><a href="/tags.html#tag-OCaml">OCaml</a></li><li><a href="/tags.html#tag-MirageOS">MirageOS</a></li><li><a href="/tags.html#tag-cryptography">cryptography</a></li><li><a href="/tags.html#tag-security">security</a></li><li><a href="/tags.html#tag-testing">testing</a></li><li><a href="/tags.html#tag-vpn">vpn</a></li></ul><p>As our last milestone for the <a href="https://www.assure.ngi.eu/">EU NGI Assure</a> 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.</p>
|
||
|
<p>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.</p>
|
||
|
<p>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.</p>
|
||
|
<p>We added a flag to our client and our <a href="miragevpn-server">recently finished server</a> applications, <code>--test</code>, 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.</p>
|
||
|
<p>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 <a href="https://github.com/reynir/openvpn/tree/badmac-test">modifications to OpenVPN</a> and <a href="https://github.com/robur-coop/miragevpn/tree/badmac-test">modifications to MirageVPN</a>.</p>
|
||
|
<p>The end-to-end testing is in addition to our unit tests and fuzz testing; and to our <a href="miragevpn-performance.html">benchmarking</a> binary.</p>
|
||
|
<p>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.</p>
|
||
|
<p>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 <code>--gremlin</code> mode that injects faults, and would be interesting to investigate.</p>
|
||
|
|
||
|
</article>
|
||
|
|
||
|
</main>
|
||
|
<footer>
|
||
|
<a href="https://github.com/xhtmlboi/yocaml">Powered by <strong>YOCaml</strong></a>
|
||
|
<br />
|
||
|
</footer>
|
||
|
<script>hljs.highlightAll();</script>
|
||
|
</body>
|
||
|
</html>
|