Hi,
i am trying to add multiple networks/nics to VMs which one has a public address, and the other should be an internal leg. Now i know about the possibilities by either setting more specific routes e.g. RFC1918 on the internal leg, or using a seperate routing table.
Can this be put into ONE context so people adding another interface will not blow up their networking?
Currently i am instantiating the VMs, purge one-context (Ubuntu) so that it will not touch the network/interfaces after i put the multi-homeing stuff into that file. But it feels very kludgy.
Okay - After some trying i came to this hackish script. Partially stolen from the one-context network creation. It should run in user-scripts so put it in the context.
Then set an ETH1_ROUTINGTABLE=“internet” for example.
It will move the /etc/network/interfaces entry for eth1 to its own file and add some post-ups for adding routes in a new table and adding rules.
Currently it’ll fail if you have multiple entrys as it does not increment the routing table number etc.
#!/bin/bash
get_iface_var() {
var_name="${UPCASE_DEV}_$1"
var=$(eval "echo \"\${$var_name}\"")
echo $var
}
mask2cdr () {
# Assumes there's no "255." after a non-255 byte in the mask
local x=${1##*255.}
set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) ${x%%.*}
x=${1%%$3*}
echo $(( $2 + (${#x}/4) ))
}
get_context_interfaces()
{
env | grep -E "^ETH[0-9]+_MAC=" | sed 's/_.*$//' | sort
}
# Gets the network part of an IP
get_network() {
network=$(get_iface_var "NETWORK")
if [ -z "$network" ]; then
IFS=. read -r i1 i2 i3 i4 <<< "$IP"
IFS=. read -r m1 m2 m3 m4 <<< "$(get_mask)"
network=$(printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))")
fi
echo $network
}
# Gets the network mask
get_mask() {
mask=$(get_iface_var "MASK")
if [ -z "$mask" ]; then
mask="255.255.255.0"
fi
echo $mask
}
CONTEXT_INTERFACES=$(get_context_interfaces)
mkdir -p /etc/network/interfaces.d
for interface in $CONTEXT_INTERFACES; do
UPCASE_DEV=$interface
ROUTINGTABLE=$(get_iface_var "ROUTINGTABLE")
DEV=$(ip -br link show | grep $(get_iface_var "MAC") | awk '{ print $1 }')
if [ -z "${ROUTINGTABLE}" ]; then
continue
fi
cat /etc/network/interfaces \
| sed -n -e "/auto ${DEV}/,/^$/p" \
| sed -e '/gateway/d' \
>/etc/network/interfaces.d/${DEV}.cfg
sed -i -e "/auto ${DEV}/,/^$/d" \
/etc/network/interfaces
cat <<EOF >>/etc/network/interfaces.d/${DEV}.cfg
post-up ip route add $(get_network)/$(mask2cdr $(get_iface_var "MASK")) dev ${DEV} src $(get_iface_var "IP") table ${ROUTINGTABLE}
post-up ip route add 0.0.0.0/0 dev ${DEV} via $(get_iface_var "GATEWAY") table ${ROUTINGTABLE}
post-up ip rule add from $(get_iface_var "IP") table ${ROUTINGTABLE}
post-up ip rule add to $(get_iface_var "IP") table ${ROUTINGTABLE}
EOF
egrep -q "^[[:digit:]]+ *${ROUTINGTABLE}\$" /etc/iproute2/rt_tables \
|| echo 1 ${ROUTINGTABLE} >>/etc/iproute2/rt_tables
ifdown ${DEV}
ip r flush dev ${DEV}
ip a flush dev ${DEV}
ifup ${DEV}
done