Table of Contents
- Similar projects
- Current issues and potential fixes
- OpenVPN 3.0: Development issues
- OpenVPN 3.0: Design and implementation
OpenVPN's current codebase has a number of limitations. Some of the limitations can't be fixed without changes to the underlying architecture. Roadmap issues and relationship of OpenVPN 2.x series and 3.0 have been discussed earlier in a few IRC meetings:
- 1st Apr 2010
- 21:36 - 21:47: James' plans for 3.0
- 21:59 - 22:09: Multithreading and the event system
- 15th Apr 2010
- 14:28 - 14:31: Roadmap and Trac
- 29th Apr 2010
- 22:23 - 22:53: Planning of the roadmap meeting
- 6th May 2010
- The roadmap meeting. James' views about OpenVPN 3.0 are available here
- 13th May 2010
The are a few similar projects which we could use for reference purposes, code etc:
- Magic Tunnel Daemon: This is pretty close to what we want, but lacks authentication and encryption. Uses BSD-license, so the code could be reused without any problems
- User Mode Linux: Userspace network drivers
- n2n: a Layer Two Peer-to-Peer VPN
Current issues and potential fixes
The fact that OpenVPN is currently implemented as a monolithic C application makes it difficult to control OpenVPN's internal operation from higher level languages. Having the core functionality of OpenVPN implemented as a C library would allow it to be wrappable by higher-level language objects more easily. For example, suppose you wanted to build a full-mesh OpenVPN cloud, where OpenVPN runs on hundreds of machines, and where each machine has multiple processors. It would be much more straightforward to implement the cloud in a high-level language such as python, and wrap the OpenVPN library as a python extension.
Another related problem is that OpenVPN's components are not easily exchangable. This means adding certain types of functionality (e.g. IPv6) or replacing current SSL and compression functionality is much more difficult than it needs to be. As OpenVPN is essentially a special-case of a user-space network stack, it could be modularized so that the central core is implemented as a user-space network stack, and the other components such as VPN and routing would be modules in this stack. The above changes make it more straightforward to implement other protocols in the stack, such as IPv6. The network stack changes would also make it much more straightforward to implement alternative topologies for OpenVPN, such as full-mesh. The SSL and compression functionality should be modularized so that OpenVPN can be used with different SSL libraries or different compression algorithms.
Currently, OpenVPN is scaled on SMP machines by adding processes rather than threads. While it might be interesting to look into scaling OpenVPN across threads, there may be kernel-level bottlenecks that impede this, e.g. note the problems facebook had when trying to scale memcached, specifically the problems of having multiple threads contend for a single UDP socket:
Lack of multithreading is closely tied to the current event system implementation.
The current non-asynchrous-clean status of the event system makes maintenance of certain OpenVPN components quite tenuous, such as mtcp.c. While the current event model is partially asynchronous, it is not sufficiently clean to allow certain features to be implemented such as concurrent multithreading or the ability to listen on multiple interfaces simultaneously. The limitations of current event system are also closely tied to OpenVPN's lack of multithreading. To get these features the current i/o event system needs to be revamped into a true asynchronous model. It might be worthwhile to look into using one of the following i/o event systems for OpenVPN:
OpenVPN 3.0: Development issues
Organic vs. planned development
Community-driven development model excels in developing software incrementally in small steps. Most community developers are driven by healthy self-interest and concentrate on features that are of interest to them. Fixing parts of the architecture may or may not have value for them. An example of an architectural change that developers would probably be interested in is making OpenVPN multithreaded. That said, there are certainly some community developers who may be interested in less concrete work such as rewriting parts of the codebase to allow easier development in the future. Also, if the architecture is made more modular, people will be able to contribute to the project more easily in the future.
Start from scratch vs. incremental approach
Starting from scratch has the benefit that we can focus on fixing the current architectural problems. Also, we would not really need to start from scratch, as many parts of the old codebase can be utilized in the new codebase with minor modifications. However, as the codebase as whole would be new, it would almost certainly have unknown problems.
There is also the problem that the new codebase will be competing for users and developers against the old codebase. Non-developers are unlikely to use the new codebase until it provides something the old codebase does not. Attracting developers to work on the new codebase may also be difficult unless somebody (e.g. at the company) bootstraps and leads the development effort. This means the new codebase will be relatively untested for a long time even after it's somewhat functional. To minimize this time period we'd need solid data on how people use OpenVPN (e.g. what features) and focus on developing those. Asking the users directly (e.g. on mailing lists) would help, but the dataset would be relatively small. An automated opt-in system similar to Debian's popularity contest would give a larger dataset, but would have to be coupled with a new software release to get widest possible audience.
Incremental approach solves the problem with competing codebases. However, as software architecture is difficult to change afterwards, incremental approach works only on a limited subset of the code. Some of the problematic code may be too tightly integrated to be fixable without invasive changes. However, there are a few good candidates for incremental modularization:
Generic network stack vs. focus on VPN functionality
In the roadmap meeting (6th May 2010) James presented his views of OpenVPN 3.0. In a nutshell, OpenVPN 3.0 would become a generic user-space network stack. This would solve many of the architectural problems with the current codebase. This approach would also potentially allow a much wider user- and developer base as people could build non-VPN functionality on top of the core.
The big question is whether going 100% generic is beneficial or not. If there's no interest in a generic userspace network stack then focusing on VPN functionality and just modularizing and cleaning up the code would be the best option.
OpenVPN 3.0: Design and implementation
OpenVPN 3.0 architecture might look something like this.
Openvpn configuration file would define which modules to use.
Thoughts about modules:
- Socket module
- Switch from the current SSL over UDP implementation to DTLS? DTLS: Datagram Transport Layer Security (RFC4347)
- Consider support for the SCTP protocol? http://www.ibm.com/developerworks/linux/library/l-sctp/
- Be able to create more local oriented VPNs, using layer 2 with MAC addresses for listen/remote, similar to MACSec and TrustSec? (suggested by stony on irc Jan 8, 2011)
- For the creative minds, in theory, it could be possible to write a socket module which would send data as HTTP requests, to trick itself through strict proxies. Or as DNS requests.
- Rate Limiting
- Limit client bandwidth in both directions
- allow changing the limits in realtime
- SSL modules needs some kind of possibility to communicate to the authentication module, for client certificate authentication. This is to avoid any authentication at all in the SSL module
- The same could go for the socket module, to "authenticate" (allow/disallow) clients based on their IP address
- This module is responsible for the packets inside the tunnel only. It needs to make sure the different supported protocol types are routed and/or filtered correctly.
- Other generic modules
- A logging module will log to file, syslog, a network socket, database connection - depending on the module. If not enabled, no logging whatsoever happens.
- Communication between the modules:
- Could zero-mq (0MQ) be useful, configured for INCPROC communication (In-Process) using a "Publish Subscribe" or a "pipeline" model? (ZeroMQ introduction)
Provided we choose to design OpenVPN as above, we'd need to do the following:
- Will OpenVPN 3.0 support the OpenVPN 2.0 wire protocol? Pro: portability - Cons: adds complexity to the implementation.
- A solution can be to not support both a new 3.x and the current 2.x wire protocol simultaneously, where there is a specific Socket module for the OpenVPN 2.x wire protocol and another Socket module for a more feature rich wire protocol for more advanced users.
- Define which types of modules OpenVPN core should support. The function they have would be the category. The drawing mentions modules as Socket, SSL, Authentication, Configuration, Compression, Protocol and Consumer/Producer?.
- Define/draft the API for the core functions of each module category. It must be defined which modules are chain-able and which are not, as well as a chain order priority.
- Define/draft the core's internal packet bus for passing data between each of the modules.
- Implement the core from scratch
- Rewrite the current OpenVPN 2.x parts which are interesting to pull into OpenVPN 3.x, to use the new module API. Then make OpenVPN 2.x make use of this API internally - without loading the code as external modules.