This is useful for proxies/middleware/interception of requests, a running
example is let's encrypt and the HTTP challenge.
The methodology is as follows:
- the unikernel requests (via https from let's encrypt) a challenge and solves it
(using a private key, some cryptographic computations)
- the let's encrypt server (wants to proof the ownership of the hostname in the
certificate signing request) requests via HTTP (port 80) a specific resource
(http://example.com/.well-known/acme-challenge/...)
- the unikernel needs to properly reply to that challenge
Now, one path (that we took until now) is to treat this .well-knwon/acme-challenge
very special in any unikernel that we wrote.
Another path is to create a let's encrypt http challenge library that takes a
stack, and whenever it needs it registers itself for port 80, proxying
everything it is not interested in, to the old handler (thus, is_listening),
and serving the .well-known/acme-challenge.
Concurrent updates to the "listen" hashtable are dangerous of course, great
care has to be taken (if some other parts of the application as well re-register
listeners). But I'm confident since listen, unlisten, and is_listening are pure
(not in Lwt monad), it's fine and can be dealt with. Another option would be to
implement a real protocol/locking around the shared global resource of listening
ports (but I'd first see whether we run into such troubles).
Another example is the let's encrypt ALPN challenge, where the process is as follows:
- the unikernel requests (via https from let's encrypt) a challenge and solves it
(using a private key, some cryptographic computations)
- the let's encrypt server (wants to proof the ownership of the hostname in the
signing request) connects via TLS on port 443 with a specific ALPN string
- the unikernel needs to reply with a specially craftes self-signed certificate
This can, as above, be implemented by a temporary proxy while the challenge is
in process -- without service interruptions for other parties (web browser, ...)