When setting up multiple tap interfaces bridged to a physical interface with IP addresses on the same subnet, we encounter two specific issues:
br0 (192.168.1.199)
___________|_____________________________________
| | | | | |
eth0 tap0 tap1 tap2 tap3 tap4
(192.168.1.150) (.151) (.152) (.153) (.154)
The current behavior shows asymmetric connectivity:
- External hosts can ping tap interfaces (192.168.1.150-154) successfully
- Ping from tap interfaces to external fails:
ping -I tap0 192.168.1.200
- ARP resolution shows bridge MAC instead of tap interface MAC
The primary issues stem from Linux bridge behavior:
# Check bridge MAC address
brctl showmacs br0
# Verify interface MAC addresses
ip link show tap0
ip link show br0
The bridge operates at layer 2 and handles all ARP requests, which explains why external hosts see the bridge's MAC address. For outgoing traffic from tap interfaces, we need proper routing and source address selection.
Implement these configurations to resolve both issues:
# Create bridge and add interfaces
ip link add name br0 type bridge
ip link set dev eth0 master br0
for i in {0..4}; do
ip tuntap add tap$i mode tap
ip link set dev tap$i master br0
ip link set tap$i up
done
ip link set br0 up
# Assign IP addresses with proper routing
ip addr add 192.168.1.199/24 dev br0
ip addr add 192.168.1.150/32 dev tap0
ip addr add 192.168.1.151/32 dev tap1
# ... repeat for other tap interfaces
# Enable proxy ARP for proper MAC resolution
echo 1 > /proc/sys/net/ipv4/conf/tap0/proxy_arp
# Repeat for all tap interfaces
# Add policy routing for source address selection
ip rule add from 192.168.1.150 lookup 150
ip route add default via 192.168.1.1 dev br0 table 150
# Repeat for each tap interface with unique table numbers
After implementing the solution:
# Verify ping from tap0 to external host
ping -I 192.168.1.150 192.168.1.200
# Check ARP resolution from external host
arp -a | grep 192.168.1.150
# Examine routing decisions
ip route get 192.168.1.200 from 192.168.1.150
For more complex scenarios, consider these options:
# Option 1: Network namespaces
ip netns add ns0
ip link set tap0 netns ns0
ip -n ns0 addr add 192.168.1.150/24 dev tap0
ip -n ns0 link set tap0 up
# Option 2: MACVLAN instead of bridge
ip link add link eth0 macvlan0 type macvlan mode bridge
ip addr add 192.168.1.150/24 dev macvlan0
Remember that bridge behavior differs from router behavior. If you need each tap interface to appear as fully independent hosts, network namespaces provide the most complete isolation while maintaining connectivity.
For production environments, consider adding firewall rules to properly handle traffic between interfaces:
iptables -A FORWARD -i br0 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o br0 -m state --state ESTABLISHED,RELATED -j ACCEPT
When working with bridge networks in Linux, a common setup involves creating multiple TAP interfaces attached to a bridge with IP addresses in the same subnet. The described configuration looks like this:
br0 (192.168.1.199)
___________|_____________________________________
| | | | | |
eth0 tap0 tap1 tap2 tap3 tap4
(192.168.1.150) (.151) (.152) (.153) (.154)
The current behavior shows two specific issues:
- Outbound ping from TAP interfaces fails (
ping -I tap0 192.168.1.200
) - Inbound ping responses show the bridge's MAC address instead of the TAP interface's MAC
The problem stems from Linux bridge behavior and routing configuration:
# Check current bridge configuration
brctl show
bridge name bridge id STP enabled interfaces
br0 8000.001122334455 no eth0
tap0
tap1
tap2
tap3
tap4
To resolve both issues, we need to make several adjustments:
# Enable promiscuous mode on the bridge
ip link set dev br0 promisc on
# Add individual IP addresses to TAP interfaces
ip addr add 192.168.1.150/24 dev tap0
ip addr add 192.168.1.151/24 dev tap1
# ... repeat for other TAP interfaces
# Disable bridge's IP address if not needed
ip addr del 192.168.1.199/24 dev br0
# Add route for external communication
ip route add 192.168.1.0/24 dev br0
ip route add default via 192.168.1.1 dev br0
# Enable proxy ARP for the bridge
echo 1 > /proc/sys/net/ipv4/conf/br0/proxy_arp
echo 1 > /proc/sys/net/ipv4/ip_forward
After implementing the changes:
# Verify outbound ping
ping -I tap0 192.168.1.200 -c 4
# Check MAC address responses
arp -a | grep 192.168.1.150
For better isolation, consider using network namespaces:
# Create namespace for each TAP interface
ip netns add ns_tap0
# Move TAP interface to namespace
ip link set tap0 netns ns_tap0
# Configure inside namespace
ip netns exec ns_tap0 ip addr add 192.168.1.150/24 dev tap0
ip netns exec ns_tap0 ip link set tap0 up
ip netns exec ns_tap0 ip route add default via 192.168.1.1
Ensure your firewall isn't blocking traffic:
# Allow bridge traffic
iptables -A FORWARD -i br0 -j ACCEPT
iptables -A FORWARD -o br0 -j ACCEPT
# Enable NAT if needed
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE