IPv6, dynamic prefixes: NPTv6 an option?

Maybe he said that because Cisco doesn't have the tools.

I'm using IPv6 multihoming without any big problems. The solution is to use a dynamic routing protocol which supports source-specific routing such as babel. With dynamic prefixes you also need a way to dynamically assign addresses which is also included in the homenet protocols. (Unfortunately Path MTU discovery seems to be broken in recent versions of the Linux kernel when using source-specific default routes. It's working in Openwrt 18.06 but not in Ubuntu 18.04 which uses linux kernel 4.15)

1 Like

Doesn't using something like Babel require cooperation from the ISP? Could a person with a typical consumer service or two succeed in using that? Can you give a brief outline of what's required other than installing babeld?

Maybe, but it was Dan Wing, former co chair of the IETF BEHAVE working group. Here's the RFCs he's written/contributed to:
https://datatracker.ietf.org/person/Dan%20Wing

The talk was from a couple years back though. So maybe things have evolved in the meantime. Glad for you.

1 Like

Another thing that can at least partially mitigate prefix renumbering is to use an HTTP proxy. These days a lot of the "user experience" is around being able to surf the web. If you run squid on your router and have all the LAN clients use the ULA of the router as the proxy (or a dns entry that points to the ULA) then no matter what happens in terms of renumbering, they can always contact the proxy and the proxy can always talk to the outside world.

It won't keep your email connections or skype etc from breaking, but it does mitigate a lot of hassle, and also adds filtering, prioritization, and bandwidth management features that can be useful.

1 Like

It doesn't require cooperation from the ISP, Hurricane Electric in my case, since the source-specific default routes causes the traffic to exit at the router which has received the prefix delegation in question from the ISP.

If you have access to static IPv6 prefixes then assigning them to routers isn't hard. You can assign a subnet of each prefix in one or more ip6prefix options. (It's also possible to assign the whole prefix to several routers but you have to make sure that there is no conflicts in the IPv6 assignment hints.)

Source-Specific Routing in Babel is a work in progress. There exist a draft, but it's expired. But it seems to work well in the reference implementation.

1 Like

Ok, for the sake of completeness, this is the hotplug script I hacked together

#!/bin/sh

[ "$ACTION" = ifup ] && [ "$INTERFACE" = wan6 ] || exit 0

log() {
    [ -t ] && echo "$1"
    logger -t nat "$1"
}

wan_iface=`ifstatus wan6 | jsonfilter -e '$.device'`
wmask=`ifstatus wan6 | jsonfilter -e '@["ipv6-prefix"][0].mask'`
lmask=`ifstatus lan | jsonfilter -e '@["ipv6-prefix-assignment"][0].mask'`
hops="`ifstatus wan6 | jsonfilter -e '$.route[*].nexthop' | grep -v '^::$' | sort -u`"
numhops=`echo "$hops" | wc -l`

[ -n "$hops" ] && [ "$numhops" -eq 1 ] || {
    log "None/too many choices for route's next hop - $hops"
    exit 1
}

    
[ -n "$wmask" ] && [ -n "$lmask" ] && [ $wmask -le $lmask ] || {
    log "No suitable mask - wmask: $wmask lmask: $lmask"
    exit 1
}

waddr=`ifstatus wan6 | jsonfilter -e '@["ipv6-prefix"][0].address'`
laddr=`ifstatus lan | jsonfilter -e '@["ipv6-prefix-assignment"][0].address'`

[ -n "$waddr" ] && [ -n "laddr" ] || {
    log "No suitable prefix - waddr: $waddr laddr: $laddr"
    exit 1
}

log "mapping $laddr/$lmask -> $waddr/$wmask on device $wan_iface"

ip6tables-restore -n <<-EOF;
*nat
-F PREROUTING
-F POSTROUTING
-A PREROUTING  -i $wan_iface -d $waddr/$lmask -j NETMAP --to $laddr/$lmask
-A POSTROUTING -o $wan_iface -s $laddr/$lmask -j NETMAP --to $waddr/$lmask
COMMIT
EOF

nexthop=$hops
route="default from $laddr/$lmask via $nexthop dev $wan_iface"
log "Installing route - $route"

ip -6 route del default from $laddr/$lmask
ip -6 route add $route

Error checking is minimal, and there are some sort of random choices. Like which prefixes to map on each interface (first one in ifstatus output on each side) and what route to open for ULA/LAN addresses.

It also assumes that there are no other rules in the nat pre/postroute chains, because those are simply flushed before installing the new mapping.

Tested so far only in a virtual machine setup, but it seems to do what it's supposed to.

Suggestions for improvements welcome, of course.

1 Like

I suggest to use $.l3_device instead. In many cases it is identical to .device but some protocols do not have .device at all and for other .device deviates from .l3_device. The former refers to the physical netdev while the latter refers to the ifname carrying the IP configuration. With PPPoE they'll differ for example; .device will be something like eth0 while .l3_device will be pppoe-wan or similar.

You can shorten that to ... | jsonfilter -e '$.route[@.nexthop!="::"].nexthop' | sort -u

1 Like

Very nice. Thanks indeed for both. I have no clue about that JSON path filter syntax, but understood that jsonfilter implements only a subset after it threw some errors at me. So any advice helping me to improve robustness, like the one about the device most certainly does, is highly welcome.

UPDATE:

Wrote a more sanitized version of my hotplug script

Edit: another update: to be more technically correct, and enhance potential reusability of code portions, we need IPv6 address expansion. Added that to the awk part of the script. With that we're pretty much done now, I suppose.

Edit: yet another update, suspicious bitstring conversion code fixed. Will be the last one, sorry for the noise. Moved code permanently to here:

2 Likes