Of course it wasn't just me, I asked other people to blog to help me stay on
track. The idea here was that seeing other peoples blog posts would inspire and
force me to keep going. This worked reasonably well. The pressure to write the
blog posts was there, but publishing was harder. This ended up with me pushing
several posts in the final few days of June.
The pressure didn't really show up either, I know that the others wrote blog
posts, but they didn't tell me!
They were great sports to get involved and help me with this, you should look
up their blogs and drop them into your rss reader.
Because this wort of worked I think we should aim to keep doing this. Now 4
posts a month is a lot (maybe even too much) and so I thought that 8 more this
year would be good. That is about 1.3333333... a month and seems entirely
I am going to try and blow this number out the water, but even if I fail
completely and only manage one or two more post that will still be great.
Most of the time, I want to do some throw away networking temporally to play
with something or to try something out. I really don't like changing all the
config on a machine just to try something. The FreeBSD documentation leans the
other way first showing you what to edit in rc.conf before maybe mentioning
that actual commands to run.
The ipfw documentation has a different problem. The example in the handbook and
online are both very verbose and very complicated. Because ipfw is normally
configured with a shell script the authors go absolutely wild with all the
features they can.
I had a hard time figuring out ipfw in-kernel NAT from these guides. Instead
here I present the simplest set of commands I could find to set up a NAT and a
little explanation to help you debug when it doesn't work.
This is based on a great email from Allan Jude on the
freebsd-virtualization list from 2014 that laid out the basics of this setup.
Set up Overview
For testing I want to run virtual machines and vnet jails on my laptop and give
them have access to the internet. I want a throw away NAT setup that is ready
to go quickly.
My laptop connects to my home network (and eventually the internet) over wifi.
The wifi network offers me an address in the 192.168.1.0/24 subnet. On my
laptop I want to have multiple guests. To do this we are going to use ipfw NAT
and a bridge interface. It will look something like this:
+-------------| wlan0 |---------------+
| +-------+ |
| ^ |
| | |
| ipfw nat |
| | |
| V |
| +---------+ |
| 10.0.4.1 | bridge0 | |
| +----+----+ |
| ^ |
| | 10.0.4.0/24 |
| ___________+_______________ |
| | | | | |
| v v v v |
| +---+--+ +--+---+ +--+---+ +--+---+|
| | jail | | vm | | jail | | ... ||
| +------+ +------+ +------+ +------+|
+-------------- laptop ---------------+
The interfaces in the jails (the b half of the epair) and the virtual machines
(the vtnet in the V) won't be visible to ipfw, but will exist in their own
world. To work around this we will use a bridge with the epairs and tap
Setting up ipfw NAT
We need to load the kernel modules for ipfw and the ipfw in kernel NAT. ipfw
has the frustrating default (and annoyingly different to ipf and pf) of to
dening all traffic. This default has the great property of locking you out of a
machine you are setting up remotely.
This is control by a sysctl that cannot be changed at run time, but we can
change the default behaviour with kenv before we load the module:
# kenv net.inet.ip.fw.default_to_accept=1
Now we can safely load ipfw and the in-kernel NAT.
# kldload ipfw ipfw_nat
ipfw should load enabled, if you are having trouble later on double check that
the firewall is actually enabled.
Our jail will use an epair interface to speak to the outside world. They come
as an a and a b part, ifconfig only tells us about the a part when it clones
the interface. When we give a vnet jail an interface it is no longer visible to
the host system. An epair gives us two interfaces that act like a virtual
ethernet cable, we stick one end into the jail and the other is connected to
# ifconfig epair create
Our virtual machine will use a tap interface to access the world. The tap
interface needs to be brought up. There is a helpful sysctl that is off by
default which will trigger the interface to be brought up when it is first
opened. I like to set this to one, otherwise I find myself debugging networking
inside the VM alot with little success.
# ifconfig tap create
# sysctl net.link.tap.up_on_open=1
With all the interfaces set up we need to add them to our bridge.
# ifconfig bridge0 addm epair0a addm tap0
Never spoken about is the bsdinstall jail command. It takes a directory and
installs a jail into it. This command will ask you some questions, it would be
cool if it didn't, that would make automating jail creation in scripts much
easier for me.
# mkdir testjail
# bsdinstall jail testjail
We make our jail persist so it will stick around as we experiment. The
following command creates the jail on the host:
Now we can jexec into the jail and configure the epair. When you bring one end
of an epair up, the other end comes up, when it goes down the other end goes
down. We just need to configure an address and a default route in our jail.
For DNS in both the jail and the virtual machines I have to manually set up the
name server local from my network.
This won't be valid as I move to other networks, but I am sure I will remember
after only a little confusion and debugging.
That is all it takes. The NAT configuration is 3 firewall rules and enabling
forwarding. None of this is persistent and that isn't great practice for a
production environment, but it you just want to experiment with ipfw and NAT,
or spin up a VM for today knowing how to do this in a non-persistent way is
Ever want to scan a subnet in the nosiest, least reliable way and generate too
many processes while doing so? Yes? Well do I have a script for you:
if [ -z $1 ]
ping -t 1 -c 1 $1 > /dev/null
if [ $? -eq 0 ]
echo hit $1
for x in `jot 254`
pinghost $prefix.$x &
I wrote this while I was doing hack the box challenges and it was a fun
and quick way to look to actually find things on my test network. I do not
recommend using this. Some operating systems won't let you run it twice in
succession as it generates a lot of processes.
In April and May I did some streaming on twitch of hardware hacking
projects. I started this as a way to work through the material for my
cancelled BSDCan hardware hacking tutorial. With the tutorial
cancelled I have been left with quite a few NanoPi Neo LTS and
I was thinking about doing the tutorial as a series of videos with the idea of
selling intro kits with the boards.
So far I have done four streams aiming for about an hour for each. I will say
now that I haven't streamed again in June, I am not saying it is the end, but I
(and I bet you too) need to control my commitments or I just never get anything
I have also been asked to write up my streaming set up so other people can use
it. This vanity pic I tooted seems to include most of it.
I have a bunch of equipment because I want to stream stuff in the real world.
If you just wanted to share some windows and your webcam as Kristof
Provost does then you can get by just with your laptop.
This is quite a lot of stuff, but other than the Aputure light I had all of it
already from other projects. I would like to be able to capture the display of
my work oscilloscope, thankfully the scope has VGA out so it is just a matter
of figuring out a way to capture.
OBS supports a rich variety of input sources that can mixed to make a scene. I
have been using three scenes to make it easy to setup what is streamed in
Just the camera
Just the presentation
Everything is the mixed view of my terminal, the camera output and the slides
in a web browser. My tutorial slides are derived from my EuroBSDCan
Tutorial and render in a web browser natively. Having a browser
in the video mix quickly turned out to be really helpful.
OBS has been rock solid and I have had no problems with stability while
streaming. The interface is a bit of a maze, but I suspect that is a natural
result of the power it offers.
For most of the top down shots I used a canon 600D with a 18-55mm kit lens. The
battery in this thing is quite old and only manages about an hour and a half of
video output. I have since gotten a USB powered battery insert that should
allow me to run forever, but am yet to try streaming with it.
My canon camera does not support acting as a webcam, but gphoto2 does support
grabbing live video from it. This should have been easy to feed into OBS, but I
couldn't get it working and ended up instead using ffplay to render the video
and grabbed that with a video capture. To get video from gphoto2 into
ffplay I ran:
gphoto2 --stdout --capture-movie | ffplay -
This turned out to be very stable and easy to set up. There is quite high
latency between the capture output and the gphoto2 capture, but it worked
fine if I didn't have to move the camera much.
I also have a Nikon J1 and while the camera is awful to use I do have a 10mm
lens for it with a macro extender. This allows me to take very high detail
pictures of PCBs. I wanted to add this to the streaming set up too.
The Nikon firmware is garbage and while gphoto2 does support the camera I
found I could only get a single image from the camera before having to reset it
and was completely unable to get video from it. Never mind, my 2018 EuroBSDCon
Talk used a HDMI network extender as a capture device. In the stream
Crimes Against Computers3 I did something awful with a BeagleBone
Black and got video from the Nikon through the HDMI extender into OBS.
This was a lot of faff to setup (though I since did get a USB-C Ethernet for
the MacBook) and I am still kind of dubious of the stability of the LKV373 so I
have only used this in the stream where I figured it out. I might try this
Since doing that stream cheap USB2 and USB3 HDMI capture devices have appeared.
These are supposed to appear as UVC webcams to the system. I suspect these will
be a better method than the LKV373, but I want to try before recommending them.
For audio I am using a Zoom H3 dictaphone thing. I really like the audio from
the Zoom, but I seem to be in the minority. In the end it is the microphone I
It is stereo which should be mixed down or you will drift across the channels
when you move your head. OBS supports this so it wasn't a problem, but I did
have to be told about it.
The firmware for this thing isn't so great either, it cannot record to the
Micro SD card while acting as a USB interface and Annoyingly there is a bug
where it defaults to 44KHz for the audio. The USB driver doesn't seem to
advertise this to the properly and if you continue with the default you get
weird audio. I dealt with this before in FreeeBSD, but was
surprised to see it appear in macOS. You should always double check your audio
before starting a stream.
Why not stream from FreeBSD?
I wanted a pain free approach where I could set up and go for my first streams
so while OBS is ported to FreeBSD I expected it to be a lot more work than the
much more common macOS/OBS combination. I expect FreeBSD/OBS support to get
better if people continue streaming FreeBSD stuff.
The MacBook is similar specs to my Thinkpad, but the wireless card in the
Thinkpad doesn't have great support and only manages 80211g rates. That might
just be enough to stream out the video, but it seems very risky to me.
I will look at streaming with OBS from FreeBSD in the future.
The streams have done okay so far, there is a big social media boost network of
FreeBSD users and developers and that has helped people find the content. I am
sure the next stream will have fewer viewers as there has been a gap in my
You can support this
Finally, I set up a ko-fi page to support me writing and streaming. I plan to
write more this year and if there is interest I will do more streams too. The
streams so far have mostly been using equipment and parts I already had. Doing
more is going to require me spending money.
If you have enjoyed my streams, or if you just want me to do more a very solid
signal of your support would be tipping me a cup of coffee or something through
ko-fi. You can support my hardware habbit here.
FreeBSD uses bugzilla for tracking bugs, taking feature requests,
regressions and issues in the Operating System. The web interface for bugzilla
is okay, but if you want to do a lot of batch operations it is slow to deal
with. We are planning to run a bugsquash in July and that really
needs some tooling to help any hackers that show up process the giant bug list
bugz ships with a configuration for connecting to the FreeBSD bugzilla you
use it by selecting it as a connection. The supported connections are dumped
out if you try and do an operation with the -d 3 debug flag. This flag is
really helpful for figuring out how to use bugz because while it documents
itself, it holds on to the documentation like a powerful secret.
bugz really wants you to authenticate before you do anything, it won't show
you help for commands without auth. There is however a --skip-auth flag. With
this you can search for bugs, lets look for ipv6 issues with a patch in the
$ bugz --connection FreeBSD --skip-auth search --product "Base System" "patch ipv6"
* Info: Using [FreeBSD] (https://bugs.freebsd.org/bugzilla/xmlrpc.cgi)
* Info: Searching for bugs meeting the following criteria:
* Info: product = ['Base System']
* Info: status = ['New', 'Open', 'In Progress', 'UNCONFIRMED']
* Info: summary = ['patch ipv6']
88821 bugs [patch] IPv6 support for ggated(8)
186133 bugs [patch] tcpdump(1): zero checksums are invalid for UDP over IPv6
174225 bugs [network.subr] [patch] add support for ipv6_addrs_IF style aliases to rc.conf(5)
178881 bdrewery [patch] getifaddrs(3) does not report IPv6 addresses properly in 32-bit compatibility mode
180572 rc [network.subr] [patch] SLAAC is enabled for ipv6_cpe_wanif
133227 bugs [patch] whois(1): add support for SLD whois server lookups and IPv6 address lookups
104851 bugs [inet6] [patch] On link routes not configured when using both IPv6 autoconfiguration and manual configuration
147681 bugs [network.subr][patch] Add inet6 keyword if it wasn't specified in ifconfig_IF_ipv6
130657 bugs [ip6] [patch] ipv6 class option
165190 bugs [ipfw] [lo] [patch] loopback interface is not marking ipv6 packets
245103 bz [patch] [ipv6] IPv6: update v6 temporary address lifetime according to rfc4941bis
* Info: 11 bug(s) found.
bugz supports modifying and updating bugz from the command line, this is the
main focus of the README on github. To authenticate bugz takes a
username and password on the command line, I am not suggesting you fill your
history with your bugzilla password, I did something like:
$ bugz --connection FreeBSD -u email@example.com --password `pass show FreeBSD/bugz | head -n 1` search udp
There is a -k flag that takes a key file, but I didn't want to dig into the
source of bugz to figure out what this actually is.
Our bug squash is probably going to focus on clearing bugs with patches and the
readme has a workflow for finding bugs and grabbing any diffs. More tools can
and should be written around bugz this is just a start. Just playing with
this I have spotted bugs than can easily be closed from the tracker.
Finally, you are going to need the help while using bugz, it took me longer
than I liked to figure out that each sub command documents its own help and
they all take the -h after the command. You need auth (or to skip auth)
before you can use this flag.