vShield App Unexpected Firewall Rule Application
We recently experienced some confusion when creating vShield App firewall rules, so I figured that it would make for a good post. For those who are unaware, vShield App (which is now a component of the vCloud Networking and Security solution) is a virtual firewall. Rather than being a traditional firewall though, which allows for rules based on either layer 2 or layer 3 constructs, this firewall integrates with vCenter and so can have rules based on vCenter constructs. At first glance, this is a little confusing, but once you become familiar with the concept it becomes very empowering.
We have a motley collection of Port Groups in this VDI environment. Each Port Group needs different firewall rules to be applied to it. We have a “production” Port Group where the bulk of the customer’s employees sit, we have an “internet only” Port Group for external users and we have a whole bunch of Port Groups that are in between those two extremes for consultants, which allow that consultant access to the infrastructure that they need while blocking general access. Oh, and I forgot to mention, this is all being done on the same Layer 2 VLAN, within the same DHCP scope. When we want a new security context, vShield allows us to simply create another Port Group with our needed rules, rather than requiring that we go through the much more laborious process of carving out a new Layer 2 space.
So, we’ve got this awesome design and are implementing it in a POC. We have our 2 most basic Port Groups created, each with appropriate rules. The “Production” port group is simple: Any Source to Any Destination on Any Port = Allowed.
The Internet Only Port Group is more difficult. You see, we say “internet only” but the fact of the matter is that these are still Windows desktops in the domain, to which we will connect users via PCoIP. After much time spent looking at WindowsServices Network Port Requirements, we had created a set of rules to allow the basic windows functions to work (that included domain user authentication, DNS, KMS, NTP and PCoIP). At the end of the list, we put a rule that said “Inside this Port Group Source to Inside Our Server Subnets Destination = Blocked” With all of those rules in place, we were expecting that the desktop would be able to contact the internal infrastructure for authentication/licensing/PCoIP purposes, but could not access it for anything else. External networks, such as the internet, should still be available.
That behavior, however, was not manifesting on a test desktop. We placed a desktop on the “Production” Port Group and, as expected, it could talk to anything. When moved onto the “Internet Only” Port Group however… it still talked to anything. We poked around at all sorts of things, trying to figure out what was happening, but eventually we called VMware support and got our answer.
Even though the GUI shows a hierarchy, the system doesn’t actually process the rules in that fashion. Unless you start creating additional Namespaces on the various Port Groups, you have a single firewall with a single set of rules. What was happening in our environment was that “Any/Any:Allowed” rule on the “Production” Port Group was allowing Any Source to talk to Any Destination, even when the VMs were on our “Internet Only” Port Group. This was happening because the two Port Groups were in the same Namespace and so the firewall was simply receiving a rule that said that Any Source could talk to Any Destination. The fix, from a procedural perspective, is very easy – don’t create an “Any/Any” rule. In our case, what we were really trying to do was “Inside Production Source to Any Destination = Allowed”. Once we set the rule up that way, the “Internet Only” Port Group actually started applying its firewall rules correctly and so everything started working as intended.
If anyone is interested, we understood this behavior with the help of the following process. We logged into the console of a vShield appliance and used the “show vmwall rules 1002” command, which displays the list of all rules in that Namespace (1002 is the default Namespace). It quickly became apparent that our Source/Destination specifications did not respect the object on which they were defined, and so we simply redefined them to specify that object and were good to go.