Network Security Through Subnet Separation
Note
This article discusses the thought process behind a design philosophy I’ve adopted to achieve server network isolation. There are certainly drawbacks and alternatives to the method I outline here, though many alternatives are only available with enterprise hardware or software. Consider what I have to say but use your own judgement if you decide to implement.
So you’re running several servers, each of which needs network access (probably just for internet access). The simplest way to connect them all is a flat network; one VLAN, one subnet. This is certainly the natural way that a homelab network would start out. But as we learn more and better security practices, and about the threats that these practices help guard against, a flat network seems less and less the proper solution.
Zero Trust
The concept of a “flat” or “trusted network” should be abandoned in favor of “zero trust” designs that isolate individual services or related collections of services away from all other network traffic.
The typical hosted service will likely need access to the internet, as well as other facilitation services you run (identity, DNS, DHCP…), but access to the other application services you host is not something that it needs. Since that’s the case, why allow it? Placing all services in a flat network allows direct communication between servers, without filtering by a firewall or other security system. This can lead to disaster.
Tabletop Exercise: What if your network was compromised?
Our security efforts aim to deal with the eventuality of getting hacked. Securing an individual server takes different measures than securing the rest of your network from a compromised server. If we were to describe a general outline of how a hack takes over a network the first step would be gaining a foothold by compromising a single server, then the hacker looks for other servers in the network “neighborhood” that they can also compromise. Once they have their foothold they are “inside” the trusted network, making it easier to discover vulnerable services to exploit on neighboring servers. This is because direct communication is possible on a trusted network, completely bypassing the secrutiy of a firewall. Modern servers provide a large list of default or standard services - the security reality is that some number of unpatched vulnerabilities are likely to exist on each server through one of the services it provides. Our best strategy is to force all network traffic to be inspected by the firewall, and prevent servers from communicating directly by isolating them.
Subnet Separation
Though VLANs are the usual go-to solution for isolation, there is an alternative that can be considered: subnets. Two hosts on the same VLAN that have distinct subnet definitions will not directly communicate. A host that needs to communicate with an IP address outside of its defined subnet will send the traffic to its configured default gateway, which is the firewall in our case.
BAM! Done! Isolation! But wait - what if one of these servers is compromised? We must assume that an attacker would have complete control over the server they have compromised, which would include network configuration / subnet configuration. This means they could easily set a subnet definition that let’s them communicate directly to other servers without sending the traffic to the default gateway (firewall). Thus a major weakness of relying on just subnet definitions for isolation is how the server is “voluntarily” isolating. However it is true that not all security is lost if this happens; a compromised server with expanded subnet definition that communicates to a non-compromised server won’t see any communication return from the non-compromised server. The non-compromised server would receive traffic from an IP outside its subnet, so if it wanted to reply it would send the traffic to its default gateway, because the IP of the compromised server is still outside its subnet as far as it is concerned. But we should still be concerned that the compromised server can send traffic directly to any other server, just in case this might still allow vulnerable services to be compromised. As we can see, additional separation controls are needed.
Another major drawback to creating a whole separate subnet for each server you host is IP wastage. Subnets can be designed to be as small as two IP addresses (two non-useable IP addresses, as in a /31 subnet, but realistically a subnet of /30 with two useable IP addresses and two non-useable IP addresses). Because of how IPv4 subnets are required to be defined there is additional wastage because of network and broadcast IP addresses. These appear as the first and last IPs in the subnet respectively. This means that a subnet defined to connect a single server eats up a total of 4 IPv4 addresses (two unuseable, one for the server, one for the default gateway/firewall)! However, even limiting ourselves to Class C private IP address space we’re still not likely to run out of subnets of this size in a homelab environment. If we ever do feel the walls closing in on us, there’s always IPv6 to save the day.
VLANs
The topic of network isolation typically starts with a look into VLANs, so why don’t we consider them now. VLANs force traffic separation within the network and without clients or servers needing to apply a configuration. This seems to be an effective way to accomplish server isolation and addresses the shortcommings of subnet isolation. Perhaps separating servers each into their own VLAN is all that is needed?
As we work to implement individual VLANs per server we must add these VLANs to our firewall as well. This is when we discover that the firewall wants a unique subnet definition per VLAN. So we’re back to using subnet isolation too. However this makes a two-pronged approach: isolating servers using host-based network configuration (subnets) as well as network-based configuration (VLANs).
The Risk of Subnet Communication - Mixed Docker and Virtual Machine Networking
Let’s also consider a real-world scenario, where a host is running the Docker engine with several containers in a flat subnet that contains other full virtual machines and services running on traditional physical servers. The Docker containers are all configured to use standard Docker bridge networking with ports published on the Docker host for service connectivity back to the network.
One large advantage of container architechure is data processing isolation and network isolation. Even though each container runs directly on the host running the Docker engine, the processes are isolated so that they can only access the resources explicitly configured for them. A service running in one container should not be aware of services in other containers, including through network connections (even Docker network connections). But services wouldn’t be very useful without network connectivity, which is allowed by publishing the service’s ports through the Docker engine.
Even with the protections each container enjoys, are they truly isolated from each other server on the network? Unfortunately, no. There are other virtual and physical servers on the same subnet as the Docker host. Just as before all it takes is a malicious actor gaining a foothold on any virtual, physical, or containerized service and then he would be able to pivot to any other server in the subnet (not container to container, but container to virtual/physical or virtual/physical to container).
To mitigate the issue it is a best practice to isolate the Docker host in its own VLAN and subnet. But then why stop there? Why not isolate each server, each container? It’s easy to facilitate this using MACvlan Docker networks (see more about it in my article discussing Docker network types). In short, Docker containers using MACvlan type connections appear as traditional servers to the network, allowing our network security measures (subnets and VLANs) to apply.
Alternatives - Private VLANs
A homelab is far from a commercial datacenter, even though both operate on similar concepts that differ mostly in scale. But let us consider the datacenter for a moment. How might a datacenter solve the problem of server isolation, especially with disparate tenants hosting servers side-by-side; mixing physical, virtual, and containerized deployments? The datacenter would likely feel the constraints of IPv4 waste from separate subnets much faster than a homelab, so that may not be a good solution any longer (though IPv6 would still probably resolve this issue). What else can be done?
Available in enterprise grade switch hardware, Private VLANs offer a way to keep traffic from disparate servers isolated, at least until it reaches the edge of the subnet. Private VLANs operate cheifly on two VLAN IDs: the promiscuous VLAN and the private VLAN. A relationship between the VLANs is recorded in the switch, so that the switch can pass traffic between the VLANs using the following rule: traffic received on a private VLAN port may only exit through a related promiscuous VLAN port, traffic from a promiscuous port may exit any related private port. This arrangement specifically prohibits traffic from a private port to exit through another private port. Servers are connected using private ports while firewalls/gateways are on promiscuous ports, thus forcing servers to only communicate with the firewall while the firewall can still communicate with any server.
The downside here is the cost of enterprise grade equipment. Considering that, I’ve never been able to try out private VLANs in a homelab, but if I had the opportunity I’d like to confirm a suspicion… what happens if two servers are connected to a switch using private VLAN configuration, but then that switch is connected upstream to a switch that is not configured with private VLAN? My suspicion is that the upstream switch would receive packets from devices on the downstream switch that were destined for hosts in the same subnet that are also connected on the downstream switch. Doing its job as a switch, the upstream switch would forward the packets right back to the downstream switch without the packet ever being evaluated by the firewall. Thus a simple misconfiguration of private VLANs in the network as a whole would compromise the entire security design.