Thursday, August 4, 2016

FreeBSD on a tiny system; what's missing

Now that I'm trying to use more userland services, there are some obvious shortcomings which need addressing.

The first is a lack of real service management. FreeBSD doesn't have a service management daemon - the framework assumes that daemons implement their own background and monitoring. It would be much nicer if init or something similar to init could manage services and start/restart them where appropriate. Yes, this is one of those arguments for systemd. Eg, maybe I want to only start telnetd or dropbear/sshd whenever a connection comes in. But I'd also like to be able to add services for monitoring, such as dnsmasq and hostapd.

The next is a lack of suitable syslog daemon. Yes, I'd like to be able to log some messages locally - even if it's only a couple hundred kilobytes of messages. I'd also like to be able to push messages to a remote service. Unfortunately the FreeBSD syslog daemon doesn't do log rotation or maximum log file sizes itself - it's done by "newsyslog" which runs out of cron. This isn't any good for real embedded systems with limited storage.

Then yes, there's a lack of a cron service. It'd be nice to have that integrated into the service management framework so things could be easily added/removed. I may just use cron, but that means cron is also always running which adds memory footprint (~1.3 megabytes) for something that is almost never actually active. When you have 32MB of RAM, that's quite a bit of wasted memory.

Finally, there's a lack of some message bus and notification mechanism for device changes. For example, openvpn-client creates a tunnel device - ok, so what should then check to see if a NAT configuration needs updating? Or updated firewall rules? It can be done with shell scripts (which I'll write tomorrow) but ideally there'd be something like dbus (a dirty word, I know) where these systems could push updates to and events could be triggered from them. I'd like to be able to run ntpdate whenever an interface comes up, because yes, there is no RTC on this hardware.

With all of the above in mind, I'll start working on some of it tomorrow. Hopefully I can automate the openvpn NAT configuration a little bit more so I can optionally have wifi NAT or openvpn NAT, depending upon the current requirement. Fixing ntpdate to run out of dhclient as part of the 'up' script may be helpful. I'll see what else I can do to tidy things up before I start the process of merging all of this back into freebsd-wifi-build.

At least this year I can now use the defcon wireless with all of my devices.

Wednesday, August 3, 2016

Musings on bringing up services on freebsd-wifi MIPS devices, or "why cross compiling is important"

FreeBSD has run on these MIPS routers for quite some time, but it was limited to what ships in base. There's not been any cross-built packages as part of the image building, which means we can't easily have third-party functionality.

Now, some of this third-party functionality is pretty important these days. Relying on telnet sucks; I'd like to have dropbear as an SSH server so we at least have SSH. Not having a DNS relay or DHCP server also sucks; dnsmasq would solve this problem. I'd also like some VPN services, so openvpn would be nice.

So, I eventually snapped a few months ago and started integrating some external toolchain compiler use with the freebsd-wifi-build scripts. bapt@freebsd did a whole lot of work to build ports of cross-compilers to be used by the FreeBSD ports and base system so I'm leveraging that for doing MIPS cross compiling. A bit of hacking later, and I'm cross compiling dnsmasq, dropbear, openvpn and lua.

Then I needed to integrate things. I wrote up a bunch of simple startup script wrappers to generate suitable config files for these services. Everything except the openvpn server/client configuration is in the rc.conf file, which will eventually make it much easier to turn into a configuration database.

OpenVPN was the most amusing. It cross compiled fine, save needing liblzo for compression (so that's disabled for now.) However, FreeBSD's openvpn package is version 2.3 but the easyrsa component is actually from 3.0 - which means all the documentation is out of date.

I used this for the OpenVPN config:

https://airvpn.org/topic/15096-verify-error-depth1-errorcertificate-is-not-yet-valid-using-router-with-tomato-shibby-firmware/

And this for easyvpn:

https://community.openvpn.net/openvpn/wiki/EasyRSA3-OpenVPN-Howto

And digitalocean have a writeup for how to convert the config file into a combined config file and certification bundle:

https://www.digitalocean.com/community/tutorials/how-to-configure-and-connect-to-a-private-openvpn-server-on-freebsd-10-1

A few things tripped me up:
  • as mentioned before - the lack of freebsd openvpn documentation that works with easyvpn 3.0 made things frustrating;
  • openvpn really wants valid system time, so I am going to have to run ntpdate when the WAN comes up;
  • there's no RTC on many of these router boards, making time keeping very much reliant on NTP;
  • kernel NAT works pretty well, but it needs interfaces to be up before you can add them. I'll have to add some scripts to openvpn-client to setup the NAT state once the link comes up so this stops being a problem;
I'll go into a little more detail about the details in a future post. But, hi from being behind an openvpn-client LAN gateway!