# rules handling in /etc/conf.d/net - nultihomed, static ips

## ervin.peters

Hi,

I had to set up a multihomed gentoo box with to internet uplinks. That was not easy because of my lack of advanced routing knowledge (I working on it) and  it is not covered by the ordinary net setup from gentoo baslayout.

Though the net-rc-scripts provides the iproute2 module they do not provide rules handling yet.

After some forum searches ('rule route') I found severall attempts, but no sufficent solution.

I recognized bug 107268 which covers the must useful informations (beneath http://lartc.org/). After some discussions roy reopened it, and includes the proposed rules-handler in an patch for /lib/rcscripts/net.modules.d/iproute2 of baslayout-1.12.0.pre15.

The main intention was to look for a /etc/conf.d/net entry:

```
rules_$iface=( ... )
```

similar to the routes_$iface entries. This rules could be evaluatet in iproute2_poststart() and iproute_predown funktions in iproute2 net module.

As this is the right way shown in some threads here, it has a difficulty: the approch using the iface to bind the rule on, e.g:

```
rules_eth0=(

 "to 192.168.255.0/24 lookup wlan"

 "to 192.168.25.0/24 lookup local"

 "from all lookup dsl"

)
```

would result in:

```
ip rule add to 192.168.255.0/24 lookup wlan dev eth0

ip rule add to 192.168.25.0/24 lookup local dev eth0

ip rule from all lookup dsl dev eth0
```

Thats not sufficent, as all rules would only look for packets which knows there interface.

But the fist thing I stumbled over was the order of rules. If rules were set up for multiple interfaces they the rule order depends on the order of starting interfaces.

By reading the iproute2 command reference (->doc) I recognized the priority option and the recommendation from Alexey to use it to specify the rules order.

That works well:

```
rules_eth0=(

 "to 192.168.255.0/24 lookup wlan priority 1000"

 "to 192.168.25.0/24 lookup local priority 1010"

 "from all lookup dsl priority 10000"

)
```

Then, the second thing I stumbled over was to discover the handling of local generated pakets. Usualy local packets recognize their outgoing interface the first time _after_ the routing decision is made.

That means all answers with destinations others than the local networks will be send via the default route, and that would be followed by dropping that packet at destination - obviously if there is any masquerading/NATing on the way. (It would take some more words to discribe the routing in kernel and effects which appear - very interesting, but look for yourself)

In consequence rules are related to an interface, but must not be limited to traffic going through that interface.

Right now I got an emal from developers to not include rules support in /lib/rcscripts/iproute, see 107268. So the rules - evaluation has to take place in post{up|down} funktions in /etc/conf.d/net. They decided to explain that in net.example.

But that is not really important - it works with post{up|down} function anyway.

At least I'll hint to  take care of the right order of rules! It might be useful to look at 'ip rule show' after each interface is started...

And here is my complete test case for a multihomed router:

```
# /etc/conf.d/net:

# $Header: /home/cvsroot/gentoo-src/rc-scripts/etc/conf.d/net,v 1.7 2002/11/18 19:39:22 azarah Exp $

# Global config file for net.* rc-scripts

modules=("iproute2")

# eth0, localnet

config_eth0=("192.168.200.253/24 brd 192.168.200.255")

routes_eth0=(

  "default via 192.168.200.254"

  "default via 192.168.200.254 table rt0"

)

rules_eth0=(

  "from 192.168.200.253/24 lookup rt0 priority 20000"

  "to 192.168.200.1/24  lookup main priority 10000"

)

# eth1, dmz1

config_eth1=("192.168.2.100/24 brd 192.168.2.255")

routes_eth1=(

  "default via 192.168.2.3 table rt1"

)

rules_eth1=(

  "from 192.168.2.100/24 lookup rt1 priority 20010"

  "to 192.168.2.1/24 lookup main priority 10010"

)

# eth2, dmz2

config_eth2=("192.168.254.254/24 brd 192.168.254.255")

routes_eth2=(

  "default via 192.168.254.3 table rt2"

)

rules_eth2=(

  "from 192.168.254.3/24 lookup rt2 priority 20020"

  "to 192.168.254.1/24 lookup main priority 10020"

)

postup()

{

  local iface="$1" ifvar=$( bash_variable "$1" )

  # Apply any rules we may want

  x="rules_${ifvar}[@]"

  local -a rules=( "${!x}" )

  if [[ -n ${rules} ]] ; then

    einfo "Adding IP policy routing rules"

    eindent

    # Ensure that the kernel supports policy routing

    if ! ip rule list | grep -q "^" ; then

      eerror "You need to enable IP Policy Routing (CONFIG_IP_MULTIPLE_TABLES)"

      eerror "in your kernel to use ip rules"

    else

      for x in "${rules[@]}" ; do

        ebegin "${x}"

        ip rule add ${x}

        eend $?

      done

    fi

    eoutdent

  fi

  # Flush the route cache

  ip route flush cache

}

predown()

{

  local iface="$1" ifvar=$( bash_variable "$1" )

  # Remove all rules defined and related to $iface

  x="rules_${ifvar}[@]"

  local -a rules=( "${!x}" )

  if [[ -n ${rules} ]] ; then

    einfo "Removing IP policy routing rules"

    eindent

    for x in "${rules[@]}" ; do

      ebegin "${x}"

      ip rule del ${x}

      eend $?

    done

  fi

  eoutdent

}
```

And now some statup logs, it starts after eth0 is up (I use ssh ;)):

```
postbote ~ # ip rule show

0:      from all lookup local

10000:  from all to 192.168.200.1/24 lookup main

20000:  from 192.168.200.253/24 lookup rt0

32766:  from all lookup main

32767:  from all lookup default

postbote ~ # /etc/init.d/net.eth1 start

 * Starting eth1

 *   Bringing up eth1

 *     192.168.2.100/24                                                   [ ok ]

 *   Adding routes

 *     default via 192.168.2.3 table rt1 ...                              [ ok ]

 *   Running postup function

 *     Adding IP policy routing rules

 *       from 192.168.2.100/24 lookup rt1 priority 20010 ...              [ ok ]

 *       to 192.168.2.1/24 lookup main priority 10010 ...                 [ ok ]

postbote ~ # ip rule show

0:      from all lookup local

10000:  from all to 192.168.200.1/24 lookup main

10010:  from all to 192.168.2.1/24 lookup main

20000:  from 192.168.200.253/24 lookup rt0

20010:  from 192.168.2.100/24 lookup rt1

32766:  from all lookup main

32767:  from all lookup default

postbote ~ # /etc/init.d/net.eth2 start

 * Starting eth2

 *   Bringing up eth2

 *     192.168.254.254/24                                                 [ ok ]

 *   Adding routes

 *     default via 192.168.254.3 table rt2 ...                            [ ok ]

 *   Running postup function

 *     Adding IP policy routing rules

 *       from 192.168.254.3/24 lookup rt2 priority 20020 ...              [ ok ]

 *       to 192.168.254.1/24 lookup main priority 10020 ...               [ ok ]

postbote ~ # ip rule show

0:      from all lookup local

10000:  from all to 192.168.200.1/24 lookup main

10010:  from all to 192.168.2.1/24 lookup main

10020:  from all to 192.168.254.1/24 lookup main

20000:  from 192.168.200.253/24 lookup rt0

20010:  from 192.168.2.100/24 lookup rt1

20020:  from 192.168.254.3/24 lookup rt2

32766:  from all lookup main

32767:  from all lookup default
```

You the a rule chain with holes where later started interfaces can place their rules in a useful order.

BTW: As described in the corespondig bug there is a bug in bash-3.0 handling 'local' variables. you might want to remove the 'local' statements or update to bash-3.1...

ervin

----------

