Instead of relying on traditional VLAN based isolation, every Exoscale instance gets assigned a Public IP and leverages Security Groups to provide full-fledged isolation and security.
In this post we’re going to demonstrate how we can totally isolate and secure an instance or a group of instances from being accessed by any traffic not explicitly allowed, even though a public IP subnet is being used on the machine.
A typical use case may be a frontend / backend setup where frontend is publicly accessible and backend can only be accessed by frontend on specific ports. Another use case may be a VPC (virtual private cloud) where a group of machines needs to be isolated from any other machines and be accessed remotely through a VPN.
Before digging into the setup, let’s first see what the security groups can do for us:
Layer 2 filtering
Security groups provides Layer 2 filtering to keep your instance safe from different types of spoofing and Man In The Middle attacks. This filtering is being managed automatically so you don’t need to worry about it. For example the following traffic will be dropped:
ARP is allowed only when the source MAC matches the instance’s assigned MAC address, it is therefore not possible to spoof an instance mac address.
An instance cannot send ARP responses for the IP address it does not own.
An instance cannot spoof a DHCP server response.
If you run Wireshark/tcpdump within your instance you won’t see your neighbors traffic even though your NIC is set to promiscuous mode.
With security groups on Exoscale, layer 2 Ethernet isolation is enforced. This is commonly achieved using VLANs on a standard architecture.
Layer 3 (and 4) filtering
Security groups provides also Layer 3 filtering, which can be managed through our console or API:
Ingress and egress IP traffic can filtered by Protocol / destination / destination port.
By default all ingress is denied and egress is fully allowed until you create a first rule. As soon as you create an egress rule, only the matching traffic will be allowed
Egress filtering is preventing any broadcast / multicast traffic to leave your instance.
Layer 3 and 4 filtering typically take for source parameters:
- An IP address in the form of a single IP or network. For example: 18.104.22.168/32 or 0.0.0.0/0 are valid entries
- Or a Security Group; this can be a self declaration for allowing traffic from machines belonging to the same group or another Security Group
Security groups in action
We’re going to illustrate a secure Frontend / Backend scenario. Web servers in the Frontend group will communicate with MySQL servers in the backend group. We don’t want any backend servers to be accessible directly from outside.
Please take into account that BUM traffic is not supported with network isolation setup. BUM is being dropped by egress rule (see below). This is an expected behavior as we don’t want anyone to receive this traffic, which may also leak sensitive information. Therefore any application relying on Broadcast, Unknown unicast and Multicast traffic type will not work.
First we’re going to create 3 security groups through the console. Let’s call them “Backend”, “Frontend” and “Management”
Now we add the following 3 required egress rules to allow our Backend instances to get their user data (port 80), their password (port 8080) and DNS resolution:
- Egress: TCP, Destination subnet 22.214.171.124/22, start port: 80, end port: 80.
- Egress: TCP, Destination subnet 126.96.36.199/22, start port: 8080, end port: 8080.
- Egress: TCP, Destination subnet 0.0.0.0/0, start port: 53, end port; 53.
We now allow each instances part of the “Backend group” to communicate with each others within the group:
- Egress: TCP, Source SG Backend, start port: 1, end port: 65535.
- Egress: UDP, Source SG Backend, start port: 1, end port: 65535.
- Ingress: TCP, Source SG Backend, start port: 1, end port: 65535.
- Ingress: UDP, Source SG Backend, start port: 1, end port: 65535.
For this demo we chose to allow all TCP and UDP traffic between instances. Depending on the use case this rule may not be required. It’s also possible if your application traffic flows are well known to only select specific Protocols / ports here, which is more secure but also more complicated to maintain / operate.
At this stage backend group is an isolated island, it cannot be accessed from outside the backend group and cannot go outside as well.
Let’s allow some ingress HTTP traffic from internet (any) to our Frontend group:
- Ingress: TCP, Source subnet 0.0.0.0/0, start port: 80, end port: 80.
Now we’re going to allow Frontend to access Mysql port on the backend:
- Ingress: TCP, Source SG Frontend, start port: 3306, end port: 3306.
In our demo we want to allow Backend instances to perform OS updates from the internet. We need then to allow HTTP and HTTPS:
- Egress: TCP, Destination subnet 0.0.0.0/0, start port: 80, end port; 80.
- Egress: TCP, Destination subnet 0.0.0.0/0, start port: 443, end port; 443.
As we wanted maximum security, we did not allowed remote management (SSH) from the internet. To be able to manage our machines, we’re going to allow SSH only from the “Management” group to “Frontend” and Backend”:
- Ingress: TCP, Source SG Management, start port: 22, end port: 22.
And we allow SSH to “Management” from the internet:
- Ingress: TCP, Source subnet 0.0.0.0/0, start port: 22, end port: 22.
It is even better if your SSH access is restricted from a known source IP;
- Ingress: TCP, Source subnet 188.8.131.52/32, start port: 22, end port: 22. (Replace 184.108.40.206 by your IP)
Let’s see what we’ve achieved with this setup:
In an upcoming blog post we will cover Virtual Private Cloud (VPC) setup in details.