Multiple IPs with one EC2 instance
How to have multiple public IPs with one AWS EC2 Instance
Edited: 2020-07-05 18:04
If you login to the console in amazon web services you will find that it is possible to assign more than one external IP to one instance, to do this, you will need to right-click on a running instance, and then click on Networking->Manage Private IP Addresses, and note the VPC subnet size (in this case /20):
eth0: eni-97987gb99 - 172.31.0.0/20
You need to know the subnet size when adding the private IP in Ubuntu/linux.
You can now go to Elastic IPs and add allocate a new IP address, once you are done, right-click on the address and click on Associate Address, then choose one of your running instances.
Once done, you will also need to add the IP to your network inside the operating system of the instance. On Ubuntu, this is pretty simple. Simply connect to your instance via SSH, then enter the following command:
sudo ip addr add xxx.xxx.xxx.xxx/20 dev eth0
Note. the /20 part at the end of the IP is the subnet size, you will need to replace this with the one of your instance – which you should have noted earlier. Finally, replace xxx.xxx.xxx.xxx with the private IP address pointing to the Elastic IP you just assigned (you can find the private IP in the Elastic IP section of your AWS console).
Making the changes permanent
The problem with this solution is that it is not permanent. After your system reboots, the changes will be lost, and you will have to add the IP again.
To avoid this problem, we can add a startup job which will add the IP automatically whenever the system is rebooted. This is done in like 5mins, and highly recommended.
1. Create a file (add-ips.sh) somewhere in your /home/ubuntu/ directory with the command from before:
ip addr add xxx.xxx.xxx.xxx/20 dev eth0
2. Make the file executable by running the following command:
sudo chmod -x /home/ubuntu/add-ips.sh
3. Run crontab as root:
sudo crontab -e
4. Add the following line last in the file:
@reboot /home/ubuntu/add-ips.sh
Done. You can now run sudo reboot to test if things are working.
Configuring Apache to listen to multiple IPs
Before the web server will accept incoming requests on its newly added public IP, it may also need to have its VHOSTs configured to handle multiple IPs.
Note. If you have already setup your VHOST using name based virtual hosting, then you may be able to skip this part.
With the Apache HTTP server, virtual hosts are added in the VHOST configuration file, which is located at:
/etc/apache2/sites-available/ooo.default.conf
So if you want to accept requests for a given domain name, you can simply use the (*) wildcard in the VirtualHost block, and then enter the domain name as the ServerName. I.e.:
# ***********
# example.com
# ***********
<VirtualHost *:80>
DocumentRoot "/var/www/example.com/"
ServerName example.com
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log common
<Directory "/var/www/example.com/">
Options FollowSymLinks
AllowOverride All
Order allow,deny
Deny from all
</Directory>
</VirtualHost>
Using the (*) wildcard name based method is much simpler than using the IP based method, and it avoids the problem of having to update your .conf file whenever you make changes to your IP configuration.
IP and Name based virtual hosting
When the server receives a request it will first look for a VirtualHost block that matches the IP of the request, if there is more than one matching block, it will move on and compare the ServerName and ServerAlias directives of the blocks with the host header of the request. Assuming the host header in the request matches either the ServerName or ServerAlias, and the match was unique, the server can finally process the matched VirtualHost block, and send it's response.
It is possible to mix IP based VHOST blocks with name based.
VHOST blocks that are purely IP based do not need a ServerName or ServerAlias directive in their blocks. So if you wanted to deliver a certain site based on the IP the request was received on, you would create a block matching the private IP that corresponds with the public IP. I.e.:
<VirtualHost 172.8.0.50:80>
# The rest of the configuration...
# blah blah..
Blocks that are either partly IP based or name based should contain at least a ServerName each, which corresponds to the host you wish to match.
Name based virtual hosting is simpler than IP based, since you usually only need to setup the DNS of your domain names, making it to point to the public IP of your web server.
Final notes
1. Remember that IPV6 adresses should be specified in square brackets:
<VirtualHost [2001:db8::a00:20ff:fea7:ccea]:80>
# The rest of the configuration...
# blah blah..
2. You may have seen the Apache listen directive mentioned in other examples on the internet, but it should generally not be necessary to mess with that when adding extra IPs to your server.
Tell us what you think: