What should be the appropriate security group rules to allow all EC2 instances attached to a single SecurityGroup to talk to each other using their ElasticIPs instead of their PrivateIPs
ILLUSTRATING THE DIAGRAM ABOVE I have a single Public Subnet in a AmazonVPC. The subnet has 3 to many more EC2 instances: DevOps instance, PHP instance, Python instance, and several others. The DevOps instances is attached to 2 security groups SG1 & SG2. The PHP/Python instances are attached to only 1 security group SG2. Given the SG1 & SG2 rules shown in the table: the DevOps instance can be accessed from the world via SSH port:22 only; the PHP/Python instances can be accessed from the world via HTTP port:80 only; all ports in all the DevOps/PHP/Python instances can be accessed from all EC2 instances that are attached to the same security group only.
USE CASE: I would like to SSH into the DevOps instance from the internet using its ElasticIP 9.8.7.1. Then from the DevOps instance i would like to SSH into PHP/Python instance using their ElasticIPs 9.8.7.2 / 9.8.7.3 (not using their PrivateIPs). Also, my PHP app should be able to talk to the Python app via ElasticIP and vice versa - because the ElasticIPs are what we have in our source codes of the apps.
PROBLEM1: Given the security group rules shown in the table, currently i am able to SSH from DevOps instance to PHP/Python instances by using their PrivateIPs only and not by using their ElasticIPs.
PROBLEM2: My PHP/Python instances are also not able to communicate with each other via their ElasticIPs.
CONSTRAINT: We regularly launch new instances for our PHP/Python apps from new/updated AMIs. Every time we launch a new instance, the PrivateIP changes. But I need to perform regular communication via something which does not change (i.e. the ElasticIP). We keep a ~/.ssh/config file in the DevOps instance so that doing SSH into the app instances are easy. In the ssh config file we have kept ElasticIPs as the IP address for our PHP/Python/Other instances. It's not possible to change the IP address in the ssh config file to a new PrivateIP address every time an app instance is replaced by a new one.
The simplest solution is to use the IP addresses' hostnames, instead of IP addresses directly, because VPC does some magical mapping for you.
Take this elastic IP for example:
$ nslookup 203.0.113.50
50.113.0.203.in-addr.arpa name = ec2-203-0-113-50.compute-1.amazonaws.com.
From inside the same VPC, this hostname does not resolve back to the elastic IP. Instead, it resolves to the private IP.
$ nslookup ec2-203-0-113-50.compute-1.amazonaws.com.
Name: ec2-203-0-113-50.compute-1.amazonaws.com.
Address: 172.31.10.25 # returns the private IP of the attached instance
Yet from outside the VPC, it resolves more like you would expect:
$ nslookup ec2-203-0-113-50.compute-1.amazonaws.com.
Name: ec2-203-0-113-50.compute-1.amazonaws.com.
Address: 203.0.113.50 # returns the elastic IP
By extension, then, if you were to configure a DNS CNAME
devops.example.com pointing to the hostname of the elastic address of the devops machine, you'd get the external IP if you accessed it externally, but the internal IP if you accessed it internally.
Since internal requests would use the private IPs, no unusual security group configuration is needed.
Additional motivation: you pay for the traffic to leave your VPC and come back if you configure your instances to communicate using Elastic IPs within the same availability zone, $0.01/GB each direction, but not when using private IPs. See data transfer pricing. Presumably the difference is because you're using more of the AWS network hardware to translate and retranslate the traffic, which traverses the Internet Gateway twice when you use elastic IPs.
The example above is a real example from my network, with my EIP replaced with a placeholder from RFC-5737.