How to set the preferred_lft variable in a LXC config file

Hi all.

I have a question (I’ll give you the details of the problem - I found the solution on the command line, but how to do it in the config file of a container).

I have a network interface configured with an IPv6 ULA address.

I have enabled MASQUERADE for the IPv6 ULA address (to be able to access the Internet via the v6 network); I exit with the router’s IPv6 address.

If I now add another IPv6, a GUA, without adding a “proxifying neighbor” I can no longer access Internet v6.

I don’t find that normal. What do you think!?


On the command line it might speak to you better! :wink:

The machine (an LXC container) :

root@dc0:~ # ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.126.42.2  netmask 255.255.255.0  broadcast 0.0.0.255
        inet6 fe80::216:3eff:fef3:56b  prefixlen 64  scopeid 0x20<link>
        inet6 fc01::10:126:42:dc0  prefixlen 112  scopeid 0x0<global>
        inet6 2a01:cb1d:12:1c00:1ab3:126:42:dc0  prefixlen 112  scopeid 0x0<global>
        ether 00:16:3e:f3:05:6b  txqueuelen 1000  (Ethernet)
        RX packets 17  bytes 1266 (1.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 24  bytes 2360 (2.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

The MASQUERADE on the host.

root@host:~ # ip6tables -t nat -A POSTROUTING -o netbr0 -s fc01::10:126:42:0/112 ! -d fc00::/7 -j MASQUERADE

So; without the GUA address (2a01:cb1d:12:1c00:1ab3:126:42:dc0) - I can access Internet v6 - I exit with the GUA address (2a01:cb1d:12:1c00:beef::cafe) of the router.
So; as soon as I add the GUA address (2a01:cb1d:12:1c00:1ab3:126:42: dc0) on my container’s network interface, I can no longer access Internet v6.

Info: To declare that the Container’s GUA address can “output” and especially that we can “input” it, the command line is as follows:

On the host “add the GUA address as a neighbor” to the connected network interface:

root@host:~ # ip -6 neighbor add proxy 2a01:cb1d:12:1c00:1ab3:126:42:dc0 dev netbr0

By the way, I even modified the “/etc/gai.conf” file; Linux IP preferences.

# ----------------------------------------
# MyPrefer
# lo (localhost)
precedence  ::1/128       50
# Default Unicast
precedence  ::/0          48
# ULA Unique Local Address (LAN IPv6)
precedence  fc00::/7      45
# SLAN Site-Local Address Network (Secure)
precedence  fec0::/10     44
# 6to4
precedence  2002::/16     30
# Teredo tunneling
precedence  2001::/32     25
# 6bone (returned)
precedence  3ffe::/16     24
# IPv4-compatible addresses (deprecated)
precedence ::/96          20
# IPv4-mapped IPv6 address
precedence ::ffff:0:0/96  10
# ----------------------------------------

I add this link to RFC 6724: Default Address Selection for Internet Protocol version 6 (IPv6) (french page) by Stéphane Bortzmeyer.

Good evening, good day.


If I try to ping google.fr2607:f8b0:4006:80c::2003”, my IPv6 GUA address “2a01:cb1d:12:1c00:1ab3:126:42:dc0” is the closest, but what is the selection rule ? Is it rule 2, is that right ?

I add the text of this page:

IPv6 source address selection under Linux (11/05/2009)”:

Sometimes it is desirable to have the outgoing IPv6 address on an interface selected deterministically. All else being equal, Linux will default to using the latest address added to the interface as the source address. This is generally not what you would expect or want. This article describes how to influence the source address selection under Linux.

Selection algorithm

Linux implements RFC 3484, "Default Address Selection for Internet Protocol version 6 (IPv6). Briefly, the algorithm involves building a candidate list of potential source addresses, then following these rules in order:

  1. Prefer same address. (i.e. destination is local machine)
  2. Prefer appropriate scope. (i.e. smallest scope shared with the destination)
  3. Avoid deprecated addresses.
  4. Prefer home addresses.
  5. Prefer outgoing interface. (i.e. prefer an address on the interface we’re sending out of)
  6. Prefer matching label.
  7. Prefer public addresses.
  8. Use longest matching prefix.

“If the eight rules fail to choose a single address, some unspecified tie-breaker should be used.” Linux chooses to use the latest address added.

Influencing the algorithm

It is necessary therefore to break any tie by influencing one of these rules. The solution is to mark unwanted source addresses as “deprecated”, causing them to fail rule 3.

The method to implement this under Linux is to set preferred_lft to 0, thus causing the address to be marked as deprecated. Note that deprecation doesn’t make the address invalid, so you can still receive packets destined for that address, but it just won’t be used as source adddres.

Note from Myself at 02:50 GMT+2:

I’m trying to put a “preferred_lft 0” on my GUA to know; I didn’t know the “ip a change” command; and moreover the “ifconfig” command doesn’t display the “preferred life time”.

root@dc0:~ # ip -6 address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
inet6 fc01::10:126:42:dc0/112 scope global
valid_lft forever preferred_lft forever
inet6 2a01:cb1d:12:1c00:1ab3:126:42:dc0/112 scope global
valid_lft forever preferred_lft forever
inet6 fe80::216:3eff:fef3:56b/64 scope link
valid_lft forever preferred_lft forever

root@dc0:~ # ip -6 addr change 2a01:cb1d:12:1c00:1ab3:126:42:dc0/1128 dev eth0 preferred_lft 0

root@dc0:~ # ip -6 address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
inet6 fc01::10:126:42:dc0/112 scope global
valid_lft forever preferred_lft forever
inet6 2a01:cb1d:12:1c00:1ab3:126:42:dc0/112 scope global deprecated
valid_lft forever preferred_lft 0sec
inet6 fe80::216:3eff:fef3:56b/64 scope link
valid_lft forever preferred_lft forever

And perfect it works :smiley: oh yeahh !!

root@dc0:~ # ping6 -n lab3w.fr -c4
PING zw3b.fr(2607:5300:60:9389::1) 56 data bytes
64 bytes from 2607:5300:60:9389::1: icmp_seq=1 ttl=47 time=102 ms
64 bytes from 2607:5300:60:9389::1: icmp_seq=2 ttl=47 time=102 ms
64 bytes from 2607:5300:60:9389::1: icmp_seq=3 ttl=47 time=102 ms
64 bytes from 2607:5300:60:9389::1: icmp_seq=4 ttl=47 time=102 ms

--- lab3w.fr ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 101.677/101.834/101.923/0.097 ms
root@lab3w:~ # tcpd_icmpv6 vmbr0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on vmbr0, link-type EN10MB (Ethernet), capture size 262144 bytes
02:40:34.468020 IP6 2a01:cb1d:12:1c00:beef::cafe > 2607:5300:60:9389::1: ICMP6, echo request, seq 20, length 64
02:40:34.468054 IP6 2607:5300:60:9389::1 > 2a01:cb1d:12:1c00:beef::cafe: ICMP6, echo reply, seq 20, length 64
02:40:35.468775 IP6 2a01:cb1d:12:1c00:beef::cafe > 2607:5300:60:9389::1: ICMP6, echo request, seq 21, length 64
02:40:35.468815 IP6 2607:5300:60:9389::1 > 2a01:cb1d:12:1c00:beef::cafe: ICMP6, echo reply, seq 21, length 64
02:40:36.470010 IP6 2a01:cb1d:12:1c00:beef::cafe > 2607:5300:60:9389::1: ICMP6, echo request, seq 22, length 64
02:40:36.470045 IP6 2607:5300:60:9389::1 > 2a01:cb1d:12:1c00:beef::cafe: ICMP6, echo reply, seq 22, length 64
02:40:37.471138 IP6 2a01:cb1d:12:1c00:beef::cafe > 2607:5300:60:9389::1: ICMP6, echo request, seq 23, length 64
02:40:37.471172 IP6 2607:5300:60:9389::1 > 2a01:cb1d:12:1c00:beef::cafe: ICMP6, echo reply, seq 23, length 64

I’ll add 4 IPv4/6 aliases that are useful to me :wink:

alias tcpd_icmpv6="tcpdump -s0 -n 'icmp6 and (ip6[40+0]&0xFE == 128)' and port ! 22 -i ${1}"
alias tcpd_icmpv4="tcpdump -s0 -n 'icmp' and port ! 22 -i ${1}"
alias tcpd_ipv6="tcpdump -s0 -t -n ip6 or proto ipv6 and port ! 22 -i ${1}"
alias tcpd_ipv4="tcpdump -s0 -t port ! 22 -i ${1}"

Now I come to the reason for creating this topic: “How to configure a network interface” the preferred life time.

I declared the variable “preferred_lft” on the GUA network interface but it doesn’t work.

root@host:~ # cat /var/lib/lxc/dc0/config
# Template used to create this container: /usr/share/lxc/templates/lxc-debian
# Parameters passed to the template: -r bookworm -a amd64
# For additional config options, please look at lxc.container.conf(5)

# Uncomment the following line to support nesting containers:
# lxc.include = /usr/share/lxc/config/nesting.conf
# (Be aware this has security implications)

lxc.net.0.type = veth
lxc.net.0.hwaddr = 00:16:3e:f3:05:6b
lxc.net.0.link = vmbr1
lxc.net.0.flags = up
lxc.apparmor.profile = generated
lxc.apparmor.allow_nesting = 1
lxc.rootfs.path = dir:/var/lib/lxc/dc0/rootfs

# Common configuration
lxc.include = /usr/share/lxc/config/debian.common.conf

# Container specific configuration
lxc.tty.max = 4
lxc.uts.name = dc0
lxc.arch = amd64
lxc.pty.max = 1024

#-----------------

lxc.net.0.veth.pair = veth102i0
lxc.net.0.name = eth0
lxc.net.0.flags = up

lxc.net.0.ipv4.address = 10.126.42.2/24
lxc.net.0.ipv4.gateway = 10.126.42.254

lxc.net.0.ipv6.address = fc01::10:126:0042:0dc0/112
lxc.net.0.ipv6.gateway = fc01::10:126:0042:ffff

lxc.net.0.ipv6.address = 2a01:cb1d:12:1c00:1ab3:126:0042:0dc0/112
# lxc.net.0.ipv6.gateway = 2a01:cb1d:12:1c00:1ab3:126:0042:ffff
lxc.net.0.ipv6.address.preferred_lft = 0

So:

lxc.net.0.ipv6.preferred_lft = 0
lxc.net.0.ipv6.address.preferred_lft = 0
lxc.net.0.ipv6.1.address.preferred_lft = 0 # ;)

Example :

lxc.net.0.ipv6.0.address = fc01::10:126:0042:0dc0/112
lxc.net.0.ipv6.0.gateway = fc01::10:126:0042:ffff

lxc.net.0.ipv6.1.address = 2a01:cb1d:12:1c00:1ab3:126:0042:0dc0/112
lxc.net.0.ipv6.1.gateway = 2a01:cb1d:12:1c00:1ab3:126:0042:ffff
lxc.net.0.ipv6.1.address.preferred_lft = 0

Doesn’t work.

Do you have any idea?

Thanks.


Add my configuration of “host” :

root@host:~ # cat /etc/sysctl.conf

net.ipv4.ip_forward = 1

net.ipv6.conf.netbr0.forwarding = 1
net.ipv6.conf.netbr0.accept_redirects = 1
net.ipv6.conf.netbr0.accept_ra = 2
net.ipv6.conf.netbr0.autoconf = 0
net.ipv6.conf.netbr0.proxy_ndp = 1
net.ipv6.conf.netbr0.use_tempaddr = 0

net.ipv6.conf.lxbr0.forwarding = 1
net.ipv6.conf.lxbr0.accept_redirects = 1
net.ipv6.conf.lxbr0.accept_ra = 2
net.ipv6.conf.lxbr0.autoconf = 0
net.ipv6.conf.lxbr0.proxy_ndp = 1
net.ipv6.conf.lxbr0.use_tempaddr = 0

Romain.

There is no option to set preferred_lft currently, adding one to liblxc shouldn’t be too difficult though.

The alternative is to rely on hooks to put things in place from a script.