Weekly Learning Logs

When IPv6 Only Gives You fe80:: (and Other Things My Coursework Is Teaching Me)

Notes from this semester's networking and security courses: subnetting, NAT, building out dual-stack IPv6, and why the problem was never the client.

Most of my writing here so far has been about CTFs and malware analysis. Those are the fun parts, but this semester a lot of my actual hours have gone into coursework, mostly a networking course built around labs and a security course on the business side of things. This post is a look at what I’ve been doing in them, kept at the concept level. The labs are individual and get checked through verbal interviews, so I’m not posting my actual configs or addresses. Every address below is a generic example.

The networking lab setup

The networking course runs in GNS3. We build topologies out of VyOS routers, Ubuntu machines (configured through both the GUI and the CLI with nmcli), Windows hosts, and VPCS for quick test clients. Every topology also gets drawn in draw.io, which I was annoyed by at first and now kind of appreciate. Having to draw the network forces you to know what you actually built.

Working on VyOS comes down to three commands:

set ...
commit
save

set stages a change, commit applies it, and save makes it survive a reboot. I learned the difference between commit and save the way everyone does. I rebooted and watched my work disappear.

Subnetting and DHCP for real

Subnetting finally clicked for me when I had to do it on an actual network and not just a worksheet. One lab had us take a /20 and split it into two /21s. With an example block of 192.168.0.0/20, that’s:

  • 192.168.0.0/21, covering 192.168.0.0 to 192.168.7.255
  • 192.168.8.0/21, covering 192.168.8.0 to 192.168.15.255

For DHCP we followed a set of conventions. The gateway goes at the last usable address, static assignments go at the start of the range, and the dynamic pool sits in between. So in the first /21 the gateway is 192.168.7.254, a few statics live right after 192.168.0.1, and the pool takes the middle. None of that is required by the protocol. The point is that anyone who walks up to the network can guess where things are, and that turns out to matter a lot once there’s more than one subnet to keep track of.

On top of that we set up source NAT covering the whole block, DNS, and then the part that took me the longest: dual-stack IPv4 and IPv6.

The IPv6 chain

IPv4 on a LAN is pretty simple. A DHCP server hands out addresses and you’re done. IPv6 the way we built it is a chain of separate steps, and if one breaks, everything after it breaks too:

  1. The router’s WAN interface gets a lease over DHCPv6 from upstream.
  2. The router requests a delegated prefix (DHCPv6 prefix delegation). In our case that was a /62, which holds four /64s. Using sla-id 0 and sla-id 1 assigns the first two /64s to two different LANs.
  3. The router sends router advertisements on each LAN, announcing the /64 that LAN got.
  4. Clients use SLAAC to build their own global address from that advertised prefix.

In VyOS, the delegation part looks roughly like this (generic interface names):

set interfaces ethernet eth0 address dhcpv6
set interfaces ethernet eth0 dhcpv6-options pd 0 length 62
set interfaces ethernet eth0 dhcpv6-options pd 0 interface eth1 sla-id 0
set interfaces ethernet eth0 dhcpv6-options pd 0 interface eth2 sla-id 1

Then router advertisements get turned on for eth1 and eth2 so clients actually hear about their prefix.

Why the problem was never the client

The biggest lesson from all this is one I’ll remember for a long time. When an IPv6 client only has an fe80:: address, stop poking at the client.

Every IPv6 interface gives itself a link-local fe80:: address no matter what, so having one only tells you the interface is up. If that’s the only IPv6 address the client has, it means the client never heard a router advertisement with a usable prefix. That means either the router didn’t send one, or it had nothing to advertise because the delegation upstream didn’t work.

I spent a while restarting network services on an Ubuntu box and re-checking nmcli settings before that clicked. Once it did, troubleshooting turned into walking the chain backwards: does the LAN interface have a delegated prefix, did the WAN interface get its lease, are RAs enabled on that interface. The fix was on the router every time.

That feels like a lesson that goes beyond IPv6. The machine showing the symptom usually isn’t where the problem is.

How AI fits into the course

The course allows AI for concepts and debugging, as long as you disclose it. Then the verbal interviews check that you can explain your own configuration. I like that setup a lot. It’s basically the same rule I try to follow in CTFs. Using a tool to understand something is fine, but if you can’t explain what you built, you didn’t really learn it. Knowing someone is going to ask “why is the gateway there?” or “what does sla-id do?” makes me actually understand each line instead of pasting it in.

Next up in the networking course are VLANs, site-to-site OpenVPN, and static and dynamic routing.

The security side

The other course is about cybersecurity for business and information systems. It covers security concepts, risk, access control, incident response, threat types, OWASP, and vulnerability management, with labs that also run on GNS3. It’s less hands-on-keyboard than the networking course, but it fills in a gap that CTFs leave wide open. CTFs teach you how a single thing breaks. This course is about how an organization decides which of its many broken things to fix first, and what to do when one of them actually gets used against it.

Put those next to each other with my IT support job, where I’m in Active Directory and Jamf every week, and the semester has been a lot of seeing the same ideas from three different angles. That’s probably been the most valuable part of it.