Home Network Segmentation, NAT Loopback to VLAN on Ubiquiti Unifi Gear

2016-11-05

I’ve been putting off segmenting my network for a while now, but the recent IoT botnet powered DDoS has bumped the task up my list of priorities, and I finally got around to doing it. Generally, if your network is anything other than non-critical clients accessing the internet, that is to say if you have any sort of IoT devices or it you host any internet-facing services at home, it’s probably a smart thing to split up your network into segments. Doing so allows finer-grained control over which machines can talk to each other, thus enhancing security. A segmented network is usually also easier to survey and audit, because irregularities like “why the hell is there an Acer laptop in my server segment?” stand out more, and with the appropriate monitoring solutions you can more easily generate usage stats by just running queries for an entire segment.

Let’s use the IoT botnet situation as a practical example. If your chinese-made, off-brand IP camera system was rooted, we now know that it has the potential to take part in taking down a third of the internet. But being that a third party has complete control over the device, there’s no telling what what it could do, including spread to other machines on your network, steal some files off an improperly secured network share, etc. Not being able to shitpost to Facebook is one thing, but messing around with my self-hosted stuff and data is where I draw the line.

There exists several models for how to segment networks, but this is one of those things that is really an exercise in common sense. A military buddy once evoked a three tier system that’s the standard for military IP networks; that’s probably great for their use case, but your home isn’t a forward operating base in the horn of Africa, and the military probably doesn’t have the likes of Nests and Augusts in their networks. Thanks to the magic of VLANs, you aren’t bound to a specific number of segments, and you’re probably better off doing more than not enough, within reason. Here’s what my setup looks like. 

homenet

It’s a pretty simple setup, but since the pictures are not really representative, here’s some more explanation.

General access: This is the untagged network that anybody who connects via wifi or wired connection gets assigned to without further configuration. This is the least trusted segment, in that it has limited access to the others, but it’s also protected from the other segments.

Web-facing services: Self-explanatory. This is completely isolated from all the other segments, both in and out, because clients who normally just connect through WAN. There is an exception for local clients trying to connect from General access and Network managment segments, which get NAT’d back in, but those exceptions are made for application specific ports only and everything else can be firewalled out. For Unifi gear, everything needs to talk back to the controller for your network to work, and if that controller is local, you’ll need to punch a few holes in your firewall. More on this later.

Network management: This is for the administration interfaces of switches, routers and access points, in addition to IPMI and other remote KVM options. In a Unifi environment, nobody should be talking to the APs or the switch, so can normally be isolation. A per-host exceptions can be made if you want to access those devices, most likely an IPMI console, with your main machine. Seeing that IPMI practically gives the next best thing to physical access to your systems and has been proven to be a wide-open opportunity for attack, it stands to reason to reason that this segment should be as strongly sealed up through your firewall policy. Note that for now, Unifi APs do not support being managed on a tagged VLAN, although the feature is supposed to be in the works. My own Unifi switch did not have this problem with the latest firmware.

Home Automation: Since home automation products usually only talk to the internet anyways, this is another locked-down segment that can’t speak to anybody. Where necessary, an appliance that needs access to more “commercial-grade” products that actually allow interaction from the LAN can be assigned an address within the VLAN. While it’s not deployed right now, a virtualized machine running Home Assistant would be interesting.


Building a segmented network with a Unifi gateway as your router is a bit different from what could be done on other platforms, since the incomplete GUI controls don’t offer all the options necessary to fine-tuning your setup. The major annoyance is that NAT loopback (aka hairpin or reflection) doesn’t seem to be properly implemented. Port-forwarding via the USG configuration menu works when accessing from the internet, but loopback config seems to assume that you will only be forwarding ports to a single subnet, and hence only need loopback to and from this subnet. We’ll need to fix this.

Unifi USG port forward dialog. Simple enough.

I found the fix for this while reading a date how-to for EdgeMAX products. Once you’ve configured your port forwards, you’ll have to manually setup NAT masquerading to the hosts that will be receiving the forwards for loopback to function correctly. There are no means of settings these things up in the GUI, so you’ll have to use the old config.gateway.json trick to manually input some NAT rules.

I strongly recommend learning how to program Edgemax / Unifi gear, because it’s great help in understanding how to modify the config file, but in case you’re in a hurry, here’s a sample of the JSON you’ll need to add.

 
{
     "service": {
          "nat": {
               "rule": {
                    "7001": {
                         "description": "Hairpin NAT Transmission",
                         "destination": {
                               "address": "10.1.2.3",
                               "port": "9091"
                         },
                         "log": "disable",
                         "outbound-interface": "eth1.121",
                         "protocol": "tcp",
                         "source": {
                               "address": "10.1.0.0/24"
                         },
                        "type": "masquerade"
                    }
               }
          }
     }
}

Replace the description, destination address and port, source address range, outbound interface (mind the VLAN!) and you are good to go. You will need one rule for every host. This JSON was built assuming you have nothing in your on-controller config file, do respect the hierarchy if you have other things going on in there, and ALWAYS validate your code.

You’ll need a rule for every port forward you want accessible from your LAN. It might be possible to define those in one shot by defining several destination addresses and ports, but I have’t tested this.

In the event that the destination port on your forward is not identical to the incoming port, you’ll want to configure the inside port in this masquerade for it to work. Be careful, loopback traffic is not exempt from passing through your LAN-IN firewall rules, so you’ll need to configure exemptions to let that through.

This is what my LAN-IN firewall config looks like. Note the exemptions: 1) for NAT loopbacks, 2) for the switch on the management segment, which still needs to talk to the controller which has not yet been migrated from my general access segment. Rule 2003 is disabled for the same reason.

This is what my LAN-IN firewall config looks like. Note the exemptions: 1) for NAT loopbacks, 2) for packets coming back on active connections to services available through loopback connections and 3) for the switch on the management segment, which still needs to talk to the controller which has not yet been migrated from my general access segment. Rule 2004 is disabled for the same reason.

The content of Web-Service-Loopbacks group. Note that I used hosts, not the entire segment, which would negate my isolation rules.

The content of Web-Service-Loopbacks group. Note that I used hosts, not the entire segment, which would negate my isolation rules.

That’s it! While you’re doing the legwork of editing the JSON file, you might want to do things like disable SSH password authentication…

 
{
     "service": {
          "ssh": {
               "disable-password-authentication": "''"
          }
     }
}

…and configure RSA login.

 
{
     "system": {
          "login": {
               "user": {
                    "admin": {
                         "authentication": {
                               "public-keys": {
                                    "user@hostname": {
                                         "key": "aaaaabbbbbcccccddddd",
                                         "type": "ssh-rsa"
                                    }
                               }
                         }
                    }
               }
          }
     }
}

That’s a pretty good start to a robust and secure home network. Let me know if I missed anything.