tinc and VPN plugins
Andrew also talked about tinc and how he’d love if it had NetworkManager integration.
NetworkManager expects quite a bit out of VPN services; they cannot simply be dumb services that expect everything to be statically configured for every user on the system. Why? Because NetworkManager allows many different configurations of VPN setttings; you might have one VPN for your cover-story workplace and one for your Secret Three Letter Agency that you only use in secure locations. That configuration is stored in NM config files in /etc and includes not just VPN-specific configuration, but also IPv4 and IPv6 configuration, static routes, DNS and search domain information, and a human-readable name and connection UUID. This allows the user to override configuration the VPN might automatically return. In the future we’ll add proxy configuration and firewall rules to that list. Because all these things are highly specific to a single network connection (be that VPN, wifi, wired, 3G, whatever), they need to be kept together, changed together, and applied together. No existing VPN configuration file format supports all this. But NetworkManager does.
This means that we cannot simply use /etc/openvpn.conf or /etc/tinc/tinc.conf because
- standard config files often contain only one network: they are essentially “public” configuration files and the concept falls apart if you have ever configured more than one VPN; while some VPN daemons do have formats that allow defining more than one network, many do not.
- config files cannot encode related connection information: there is often no facility for expanded network-specific configuration like proxies, firewall rules, additional IP addresses, static routes, DNS search domains, etc that should be associated with VPN connection.
- secrets should be stored securely: if the user wants secure password storage in the GNOME Keyring or KWallet or whatever, they should be able to do so. The user should be able to keep the password in their session or even provide it on-demand and not require it to be stored in system configuration files.
- secrets can change periodically: at Red Hat we use RSA SecurID tokens that generate a new PIN code every 30 seconds which is entered every time we connect. Many VPN daemons will ask for passwords too, but that requires a terminal. Fail. We want to ask for secrets in a generic manner which is appropriate to each desktop environment (or lack thereof), and existing VPN secret request mechanisms (stdin, TCP management socket, static config files, etc) simply do not allow this.
To work around these limitations of configuration files, NetworkManager dynamically generates configuration for each VPN daemon and inserts your password when required, retrieved from secure GNOME Keyring/KWallet storage or from a PIN entry dialog or other mechanism. The VPN daemon is then executed and handed that configuration, either a path to a private, root-owned, transient configuration file or, even better cleanly written to stdin if the VPN daemon supports it.
Which leads me to tinc. Nothing appears to preclude creation of NetworkManager VPN plugin for tinc, but there are some complications that it would be great to get fixed upstream:
- quite a few configuration files required for each VPN network, and a plugin would have to create all these files dynamically before executing tincd; it appears that tinc 1.0.14 allows arbitrary config options on the command-line, which helps somewhat, but even better would be accepting configuration on stdin as a single unit instead of a bunch of separate files. This way no config files (possibly including secrets) might mistakenly get left lying around due to segfaults or programming errors.
- configuration appears to require an explicit device name (like “tun0”) which is a huge no-no; if the program can’t dynamically determine a suitable device name and return that to the caller, it gets a F- grade from me. If the user configures more than one VPN that they might use concurrently, they shouldn’t have to manually plan out interface names. At least it appears that tinc sends the interface name to the “up” script in the INTERFACE environment variable.
- like OpenVPN, it appears that many attributes of the VPN connection cannot be auto-detected, which requires the user to know a-priori what the VPN configuration will be. Stuff like “Cipher”, “Compression”, “Digest”, etc. This never helps users and apparently everybody writing VPN software thinks the user of their software is already a system administrator. I hope I’m wrong about this. If I’m not, hopefully tinc emits status information indicating that the parameters set in configuration are incompatible with the peers it’s trying to connect to such that we can notify the user about it.
- it’s unclear to me how tinc reports status and progress in a usable manner; it appears that one can send signals to tincd, but they dump information to syslog. Ideally tincd would include an option to dump this information to stdout as well, because screen-scraping syslog is just completely evil.
None of these issues are killers; but they simply result in a degraded experience for the user of tincd if that user is not a system administrator. At this point vpnc is the best-behaved VPN daemon because it (a) accepts configuration on stdin, (b) can request secrets dynamically via stdin, (c) automatically negotiates most options with the peer, and (d) doesn’t have 50,000 configuration options with complex interdependencies. I hope tinc can get there too.
If anyone wants to write a NetworkManager VPN plugin for tinc, definitely let me know or jump onto the mailing list and we’d be glad to help out with suggestions and advice.