Linux Network Configuration: Using Same IP Address Across Multiple Physical Interfaces


3 views

In enterprise device management systems where each client device requires isolated physical networks, administrators often face IP address management complexities. Our case involves a Linux server (kernel 3.14) serving multiple set-top boxes (STBs) through separate physical interfaces, each requiring the server to appear as a different IP address within identical subnet ranges.

Server Interfaces:
- eth0: External network
- eth1: 172.16.50.1/24 → STB1 LAN
- eth2: 172.16.51.1/24 → STB2 LAN 
- eth3: 172.16.52.1/24 → STB3 LAN

We can implement network namespace isolation combined with policy-based routing to achieve identical IP addressing across physical interfaces while maintaining network separation.

# Create network namespaces
sudo ip netns add stb1
sudo ip netns add stb2
sudo ip netns add stb3

# Move interfaces to namespaces
sudo ip link set eth1 netns stb1
sudo ip link set eth2 netns stb2 
sudo ip link set eth3 netns stb3

# Configure identical IPs in each namespace
sudo ip netns exec stb1 ip addr add 172.16.50.1/24 dev eth1
sudo ip netns exec stb2 ip addr add 172.16.50.1/24 dev eth2
sudo ip netns exec stb3 ip addr add 172.16.50.1/24 dev eth3

# Bring up interfaces
sudo ip netns exec stb1 ip link set eth1 up
sudo ip netns exec stb2 ip link set eth2 up
sudo ip netns exec stb3 ip link set eth3 up

For services running in each namespace (TFTP/NFS/HTTP), use systemd units with namespace specification:

[Unit]
Description=TFTP Server for STB1
After=network.target

[Service]
ExecStart=/usr/sbin/in.tftpd --listen --user tftp --address 172.16.50.1:69 /srv/tftp/stb1
Restart=always
NetworkNamespacePath=/run/netns/stb1

[Install]
WantedBy=multi-user.target

Add specific route tables for each namespace to prevent routing conflicts:

# Create custom routing tables
echo "100 stb1" >> /etc/iproute2/rt_tables
echo "101 stb2" >> /etc/iproute2/rt_tables
echo "102 stb3" >> /etc/iproute2/rt_tables

# Configure routing in each namespace
sudo ip netns exec stb1 ip route add default via 172.16.50.1 table stb1
sudo ip netns exec stb1 ip rule add from 172.16.50.1 lookup stb1

Test connectivity from within each namespace:

sudo ip netns exec stb1 ping 172.16.50.100  # STB1 device
sudo ip netns exec stb2 arping -I eth2 172.16.50.101

For high-throughput scenarios, consider XDP (eXpress Data Path) programs to handle namespace-specific packet processing at the driver level.

// Sample XDP program to filter by physical interface
SEC("xdp")
int xdp_prog(struct xdp_md *ctx) {
    void *data_end = (void *)(long)ctx->data_end;
    void *data = (void *)(long)ctx->data;
    
    // Process packets based on ingress interface
    switch (ctx->ingress_ifindex) {
        case ETH1_IFINDEX:
            return process_stb1(data, data_end);
        case ETH2_IFINDEX:
            return process_stb2(data, data_end);
        default:
            return XDP_PASS;
    }
}

In embedded systems development, particularly when working with multiple consumer devices like set-top boxes, we often encounter unique networking requirements. The scenario involves a Linux server (kernel 3.14) serving as a central TFTP, NFS, and HTTP server for multiple devices, each requiring complete network isolation.

The existing configuration uses separate subnets for each device:

# Current interface configuration
auto eth1
iface eth1 inet static
    address 172.16.50.1
    netmask 255.255.255.0

auto eth2
iface eth2 inet static
    address 172.16.51.1
    netmask 255.255.255.0

auto eth3
iface eth3 inet static
    address 172.16.52.1
    netmask 255.255.255.0

This approach creates maintenance overhead as each device must reference the server using different IP addresses in their configuration files.

Using the same IP address (172.16.50.1) on multiple interfaces connected to physically separate networks is technically feasible with proper configuration:

# Modified interface configuration
auto eth1
iface eth1 inet static
    address 172.16.50.1
    netmask 255.255.255.0
    up ip route add 172.16.50.0/24 dev eth1 table 100
    up ip rule add from 172.16.50.1 table 100

auto eth2
iface eth2 inet static
    address 172.16.50.1
    netmask 255.255.255.0
    up ip route add 172.16.50.0/24 dev eth2 table 101
    up ip rule add from 172.16.50.1 table 101

auto eth3
iface eth3 inet static
    address 172.16.50.1
    netmask 255.255.255.0
    up ip route add 172.16.50.0/24 dev eth3 table 102
    up ip rule add from 172.16.50.1 table 102

The key components making this work:

  1. Policy-based routing using multiple routing tables
  2. Strict ARP filtering to prevent cross-network conflicts
  3. Interface-specific ARP announcements

Enable ARP filtering and configure interface-specific responses:

# Add to /etc/sysctl.conf
net.ipv4.conf.all.arp_filter = 1
net.ipv4.conf.default.arp_filter = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_announce = 2

After implementation, verify the setup:

# Check routing tables
ip route show table 100
ip route show table 101
ip route show table 102

# Test connectivity from each network
arping -I eth1 172.16.50.1
arping -I eth2 172.16.50.1
arping -I eth3 172.16.50.1

While this solution works well for our specific use case, consider:

  • Broadcast traffic will be limited to each physical network
  • Some network monitoring tools might show warnings
  • Requires careful firewall configuration

For firewall rules, ensure you specify the outgoing interface:

# Example iptables rules
iptables -A INPUT -i eth1 -s 172.16.50.0/24 -d 172.16.50.1 -j ACCEPT
iptables -A INPUT -i eth2 -s 172.16.50.0/24 -d 172.16.50.1 -j ACCEPT
iptables -A INPUT -i eth3 -s 172.16.50.0/24 -d 172.16.50.1 -j ACCEPT