Daniel López Azaña

Theme

Social Media

Blog

GNU/Linux, Open Source, Cloud Computing, DevOps and more...

How to use 2 network interfaces on the same AWS subnet in Linux

Diagrama de una instancia EC2 con múltiples interfaces de red compartiendo la misma subred dentro de la misma zona de disponibilidad en AWS

The following Linux procedure describes how to use at the same time 2 network interfaces connected to the same AWS subnet and, which is more important, how to make both communication works well internally (between hosts on the same subnet) and also externally (both interfaces visible from the Internet). This can be useful for example when you want the same EC2 instance to host a web server serving http or https requests and at the same time have a websockets server ws:// or wss:// listening on the same port 80 or 443 respectively. Although there are other ways to achieve this such as configuring Nginx to be able to discriminate web traffic (http) from websockets traffic (ws) and act as a proxy to redirect the corresponding requests to the websockets server, this other solution I propose seems simpler and to some extent more efficient because it is not necessary to redirect traffic, which will always introduce a small latency , and allows to keep both servers completely independent within the same host. The only drawback is that you will need to assign 2 Elastic IP addresses to the same EC2 instance instead of only 1, but at the same time this will give you more flexibility when establishing rules in the security groups or in the subnet NAT rules.

The following example shows how to use on an EC2 instance with Ubuntu 16.04.2 LTS operating system two different network interfaces within the same subnet 172.31.0.0.0/20 that corresponds by default to the Amazon Web Services eu-west-1a Availability Zone. Note, however, that the procedure is perfectly applicable to any other network address (CIDR) and can also be used on any other Linux server outside of AWS.

1.- Create a new network interface and attach it to your instance

Create a new network interface (EC2 -> Network Interfaces -> Create Network Interface) from the AWS management console. Then make sure that the new interface is in the same availability zone as the instance, otherwise you will not be able to attach it. In general it’s indifferent to use dynamic IP addressing (Private IP: auto assign) or static when configuring your own IP address.

Once created attach the new interface to your EC2 instance from the same screen where you created it. When the attachment process is finished and the interface becomes available (in-use status) access the instance and enable the second network interface:

root@ip-172-31-2-11:~# ifconfig eth1 up 
root@ip-172-31-2-11:~# ifconfig 
eth0      Link encap:Ethernet  HWaddr 06:c3:15:26:eb:ac   
          inet addr:172.31.2.11  Bcast:172.31.15.255  Mask:255.255.240.0 
          inet6 addr: fe80::4c3:15ff:fe26:ebac/64 Scope:Link 
          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1 
          RX packets:4983 errors:0 dropped:0 overruns:0 frame:0 
          TX packets:1344 errors:0 dropped:0 overruns:0 carrier:0 
          collisions:0 txqueuelen:1000  
          RX bytes:6716291 (6.7 MB)  TX bytes:128785 (128.7 KB) 
 
eth1      Link encap:Ethernet  HWaddr 06:b4:56:4c:9d:e2   
          inet6 addr: fe80::4b4:56ff:fe4c:9de2/64 Scope:Link 
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1 
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0 
          TX packets:7 errors:0 dropped:0 overruns:0 carrier:0 
          collisions:0 txqueuelen:1000  
          RX bytes:448 (448.0 B)  TX bytes:578 (578.0 B) 
 
lo        Link encap:Local Loopback   
          inet addr:127.0.0.1  Mask:255.0.0.0 
          inet6 addr: ::1/128 Scope:Host 
          UP LOOPBACK RUNNING  MTU:65536  Metric:1 
          RX packets:160 errors:0 dropped:0 overruns:0 frame:0 
          TX packets:160 errors:0 dropped:0 overruns:0 carrier:0 
          collisions:0 txqueuelen:1  
          RX bytes:11840 (11.8 KB)  TX bytes:11840 (11.8 KB)

2.- Configure the eth1 interface to modify the routing table when it is enabled

As you can see from the output of the above ifconfig command, the eth1 interface has no IP address assigned to it because there is no configuration available for it. Configuration of network interfaces in Ubuntu/Debian is located in /etc/network/interfaces.d/ directory. There you will find an eth0.cfg file corresponding to the first network interface, so there you will also create a second eth1.cfg file with the following configuration:

# The secondary network interface
auto eth1
iface eth1 inet dhcp

# The following rules allow the operation of this secondary network interface on the same subnet as eth0,
# something that is not possible by default since there is a default route in the routing table that always
# forces packets to go out using the same network interface even if their IP indicates that they come from
# the other one.

# In case these rules don't work, activate arp filter:
# sysctl -w net.ipv4.conf.all.arp_filter=1
# If the result is satisfactory, make the change permanent:
# echo "net.ipv4.conf.all.arp_filter = 1" >> /etc/sysctl.conf

# Create separate routing tables for each network interface
# These tables must be defined in the /etc/iproute2/rt_tables file:
# 10 eth0
# 20 eth1
post-up ip route add 172.31.0.0/20 dev eth0 src 172.31.2.11 table eth0
post-up ip route add 172.31.0.0/20 dev eth1 src 172.31.2.51 table eth1

# Force packets to go out using the appropriate network interface based on their source or destination IP
post-up ip rule add from 172.31.2.11 table eth0
post-up ip rule add from 172.31.2.51 table eth1

# Set the same default gateway for both network interfaces
post-up ip route add default via 172.31.0.1 dev eth1 table eth1
post-up ip route add default via 172.31.0.1 dev eth0 table eth0

# ip route changes have no effect on the classic routing table (netstat -rn).
# The following rules force packets that originate on the server to always go out using eth0 by default
post-up route del default
post-up route add default gw 172.31.0.1 eth0

3.- Create separate routing tables for each network interface

Edit /etc/iproute2/rt_tables file and add the following lines at the end:

10 eth0
20 eth1

4.- Restart the networking service

Once the above changes have been made, restart the networking service:

$ sudo service networking restart

If everything went well, ifconfig command should show now the eth1 interface with its assigned IP address and you should be able to access the instance via SSH through any of its internal IP addresses from other instances in the same subnet. However, by default AWS will not assign any public IP to the second network interface, so if you want to access it from the Internet you will have to associate a new elastic IP address to it. From that moment on you will be able to log in to your server from the Internet using any of its public IP addresses.

Daniel López Azaña

About the author

Daniel López Azaña

Tech entrepreneur and cloud architect with over 20 years of experience transforming infrastructures and automating processes.

Specialist in AI/LLM integration, Rust and Python development, and AWS & GCP architecture. Restless mind, idea generator, and passionate about technological innovation and AI.

Related articles

Logo AWS EBS

How to enlarge the size of an EBS volume in AWS and extend an ext4 partition

When we completely fill up an ext4 filesystem mounted on a partition hosted in an EBS volume of Amazon Web Services and we can not do anything to free space because we do not want to lose any of the stored data, the only solution is to grow up the volume and extend the associated partition up to 100% of its capacity to obtain free space again.We start in our example with a 50 GB volume full to 100%. We want to extend it to double the size, 100 GB:

May 23, 2017
terraform-and-route53-logos

How to quickly import all records from a Route53 DNS zone into Terraform

The terraform import command allows you to import into HashiCorp Terraform resources that already existed previously in the provider we are working with, in this case AWS. However, it only allows you to import those records one by one, with one run of terraform import at a time. This, apart from being extremely tedious, in some situations becomes impractical. This is the case for the records of a Route53 DNS zone. The task can become unmanageable if we have multiple DNS zones, each one with tens or hundreds of records. In this article I offer you a bash script that will allow you to import in Terraform all the records of a Route53 DNS zone in a matter of seconds or a few minutes.

February 8, 2022
Copy AMI using customer managed key for encryption

How to share an AMI between 2 AWS accounts

If you have an unencrypted AMI you can share it with another AWS account directly without doing anything special. But if the AMI is encrypted, things get complicated, as the destination account won't have the encryption key to decrypt its snapshots and you won't be able to share it. In this article I'll show you how to properly share an encrypted AMI between two AWS accounts using customer managed KMS keys, allowing you to securely share your EC2 instance images across different AWS accounts.

February 6, 2022

Comments

Be the first to comment

Submit comment