Hello everyone,
I’m very pleased to announce that firewall-tree library has reached a presentable stage and a demo which uses firewall-tree in MirageOS is available.
Demo
The demo code is available here.
The code itself is quite thoroughly commented, the README in the folder contains build and run instructions and also illustrations of the tree in graphical form, so I won’t dive into the details of the demo here.
In short, the demo shows how to separate of ICMP trafffic and TCP traffic. For TCP, filter some TCP traffic, then load balance the remaining TCP connections across multiple destination IPv4 addresses. For ICMP ping requests, only reply to every other one.
The tree itself is only a couple of lines, but there is quite a bit setup code for wrapping MirageOS stuff into a module and types usable by firewall-tree. However, it should be possible to package the setup code into a library supporting MirageOS as a firewall-tree backend, so in future the usage of the library should be much smoother and less cluttered than the demo.
I’d like to note that the library right now is still very rough at more complex constructs, and the connection tracker, which is used inside the translators, works fine for a very typical TCP connection, but fails to handle TCP retransmissions, or TCP PDUs with RST and PSH flags.
Library overview
The library requires a “base”, which you can think of as an environment implementation (see here for module type signature), which it then extends into a full firewall module. The resulting module provides the following functions/constructs
- Hierarchical PDU definition
- PDU decapsulation
- PDU mapping (can also map inner components)
- PDU replacement (can also replace inner components)
- PDU pretty printing (see the demo for sample output)
- Memory bounded lookup table with evict timed out entries function
- Routing logic unit only partial implementaiton is in place currently
-
Connection tracker (bidirectional, so you can use it without much thinking)
- Largely functional, still a long way to go before becoming robust enough
- Predicates for building filters/selectors
-
Translators for building load balancers or proxy
- These were essentially a more general form of NAT translators when I wrote them, so hopefully they (or variant of them) can be used to build a full blown NAT at some point
The package provides another set of functors which take the resulted tree module as parameter and derive commonly used constructs. See demo for example use.
Moving onward
Still a lot of things to be done, following lists a few of the items
- TCP connection tracking needs to be fixed
- Implement more translators, make them more modular (e.g. swappable algorithms)
- Couple translators to form NAT modules
- Benchmark
- I am hoping this library doesn’t slow down MirageOS too much for equivalent functionalities, but I don’t have concrete benchmarks
Final thoughts
The progress so far has been quite time consuming to implement, with a lot of redesigns and rewrites in-between. I am hoping the current design is sane, but I feel I’ve invested too much time in last couple of weeks to get a clear view of things. So I would absolutely appreciate any feedback, whether it’s on API design, the architecture of the code or any other aspects.
I had some experiences with networking and firewall, but as far as implementing a network stack goes, I have zero experience, so I’d also appreciate help on components which demand such expertise as well.
Thanks for reading!
Darren