e42.uk Circle Device

 

Quick Reference

multihomed hosts and arp

Multi-Homed Hosts and ARP

Why does Linux answer to ARP on incorrect interfaces?

Consider the following host configuration:

       Joshua                      Fredrick
+---------------------+     +--------------------+
| eth0: NOT ASSIGNED  |     |                    |
| br0: 192.168.0.31   +-----+ eth0: 192.168.0.21 |
| tap25: 192.168.80.2 +---+ | eth0: 192.168.1.21 |
| tap29: 192.168.81.2 |   | +--------------------+
+---------------------+   |
                          |
                          |
                          |
      Riker               |
+---------------------+   |
| eth0: 192.168.80.25 +---+
+---------------------+

All these hosts are normal Linux hosts and have the following settings:

/proc/sys/net/ipv4/conf/eth0/rp_filter - 1
/proc/sys/net/ipv4/ip_forward          - 0

Who can talk to who?

It is not surprising that Riker cannot communicate with Fredrick on any IP address, for that to work Joshua would have to forward packets to Fredrick.

What may be surprising is that Fredrick can connect to Joshua on any of the configured interface addresses (assuming routing would allow it) the same is true for Riker: Riker may connect to Joshua using any of the addresses assigned to interfaces on Joshua.

The reason for this is that the Linux IP stack uses what is referred to as the Weak Host model. Explained by "The Cable Guy" on Microsoft TechNet (see References).

With the weak host model it does not matter on which interface a packet is received as long as the packet is destined for an address that is assigned on the receiving host it will be accepted and processed by the stack in the normal way.

Implications for Security

There is a certain class of attack that can be instigated by sending a packet to a local address when connected physically to an external interface.

In the example above a service intended only for Riker (or on Riker's subnet 192.168.80.0/24) could be bound to an address within that subnet on the assumption that since Fredrick is not on that subnet Fredrick will not be able to access the service bound on 192.168.80.2. This assumption is incorrect for the weak host model as it is indeed possible to connect to a service running on 192.168.80.2 from 192.168.0.21 without forwarding pakets.

ARP

Since the above outlined behaviour is a feature and not a bug then ARP also provides the support required. When Riker requests that someone reply with the MAC address for 192.168.0.31 Joshua will respond with the MAC address of the tap25 interface allowing IP communication to begin. Of course this would not be a required step for SLIP or PPP.

ARP Tweaking

As the SO post (see References) details there are some settings that can be customised to stop this first step. It is important to note that it will not prevent the IP stack from processing incoming data but it will force the client to know the MAC address of the server (easy) and also the IP address on which the service is bound (which is also probably easy).

The filenames in /proc/sys/net/ipv4/conf/?/ are:

  • arp_announce
  • arp_ignore

Further details in sysctl variables and the SO post.

Final Note on rp_filter

Read the detail of what rp_filter does carefully. Sending a packet with a source address on an interface that is not the optimal route will fail the filter check if the flag is set in all OR interface:

The max value from conf/{all,interface}/rp_filter is used
when doing source validation on the {interface}.

See sysctl variables in References.

See also a problem for Multi-Homed hosts in References and RFC 3704.

Configure Stronger Host Model using systemd

Configuring the strong host model (or something like it) with systemd involves creating different routing tables for each interface. This is not specific to systemd and so can be configured with a shell script...

systemd Configuration

For these hosts the example will include a DHCP configured interface and two statically configured interfaces:

eth0   - DHCP
eth1   - VLAN Interface
vlan8  - 10.8.0.1/16
vlan16 - 10.16.0.1/16

# /usr/lib/systemd/network/21-eth0.network
[Match]
Name=eth0
[Network]
DHCP=yes
[DHCPv4]
RouteTable=200
[DHCP]
UseMTU=yes
RouteMetric=10
ClientIdentifier=mac

# /usr/lib/systemd/network/22-eth1.network
[Match]
Name=eth1

[Network]
DHCP=no
VLAN=vlan8
VLAN=vlan16

# /usr/lib/systemd/network/23-vlan8.network
[Match]
Name=vlan8
[Network]
DHCP=no
[Address]
Address=10.8.0.1/16
AddPrefixRoute=false
[Route]
Destination=10.8.0.1/16
Scope=link
Table=8
[RoutingPolicyRule]
From=10.8.0.0/16
To=10.8.0.0/16
IncomingInterface=vlan8
Table=8
[RoutingPolicyRule]
From=10.8.0.0/16
To=10.8.0.0/16
Table=8

# /usr/lib/systemd/network/24-vlan16.network
[]

Shell Script Configuration

Creating a VLAN device on eth1:

ip link add link eth1 name vlan8 type vlan id 8

Adding an address to an interface without creating an entry in the main routing table:

ip addr add 10.8.0.0/16 dev vlan8 noprefixroute

To be continued...

References

Quick Links: Techie Stuff | General | Personal | Quick Reference