Feuerfest

Just the private blog of a Linux sysadmin

Fix keepalived error: bind unicast_src - 99 cannot assign requested address

TL;DR: The configured unicast_src IP isn't present on any network interface. In my case DHCPv6 was to blame.

I accidentally unplugged the power cable from my RaspberryPi 4 today. Due to this I learned a few things today.

  1. First that my home DSL router (a FritzBox) doesn't always honor the preferred IPv4/v6 addresses send in DHCP-Request
    • /etc/dhcpcd.conf did contain static ip_address=... and static ip6_address=...
  2. The FritzBox can't set DHCP reservations for IPv6 addresses - only IPv4 - WHY!?
  3. I have to read the keepalived error message with my head turned on
    • I stumbled across the cannot assign requested address and thought of DHCP and was confused why the hell keepalived does DHCP things (the word requested mislead me)
    • In the following line the reason is written in plain text...  entering FAULT state (src address not configured)
  4. Static IP-configuration for servers was, is and will always be the best
  5. A mixed static & dynamic IPv6  configuration isn't hard at all once you read a bit about SLAAC

Long story short, this was the keepalived error I got. The VRRP-Instance immediately went into FAULT state and stayed there.

root@raspi:~# systemctl status keepalived.service
[...]
Feb 05 13:14:22 raspi Keepalived_vrrp[1279]: Delaying startup for 5 seconds
Feb 05 13:14:22 raspi Keepalived[1278]: Startup complete
Feb 05 13:14:22 raspi systemd[1]: Started keepalived.service - Keepalive Daemon (LVS and VRRP).
Feb 05 13:14:22 raspi Keepalived_vrrp[1279]: bind unicast_src fd87:f53:25b4:0:231d:4cbb:bca7:10 failed 99 - Cannot assign requested address
Feb 05 13:14:22 raspi Keepalived_vrrp[1279]: (VI_2): entering FAULT state (src address not configured)
Feb 05 13:14:22 raspi Keepalived_vrrp[1279]: (VI_2) Entering FAULT STATE
Feb 05 13:14:22 raspi Keepalived_vrrp[1279]: VRRP_Group(ALL) Syncing instances to FAULT state

At first I skipped the following line:

Feb 05 13:14:22 raspi Keepalived_vrrp[1279]: (VI_2): entering FAULT state (src address not configured)

Hence I searched a bit and found an older GitHub issue where this problem was explained with VRRP trying to do stuff to fast, while the interface wasn't ready. The solution mentioned in keepalived issue #2237: Keepalived entering fault state on reboot was to set vrrp_startup_delay inside the global_defs section of /etc/keepalived/keepalived.conf. However this was already the present in my case.

Yeah, turns out the configured unicast_src IP wasn't present on any interface. As the FritzBox deemed it fit to assign a random one from the configured DHCP-Range. We can verify this quickly by grep'ing for the IPv6 address.

root@raspi:~ # ip -6 a | grep fd87:f53:25b4:0:231d:4cbb:bca7:10
root@raspi:~ #

The solution

In my case I finally switched to a mixed static and dynamic IPv6 setup. Configuring the local ULA address as a static one, but still receive and apply the router advertisement (RA) to get a global IPv6 so my RaspberryPi can still connect to the Internet.

Then it showed up on the interface.

root@raspi:~ # ip -6 a | grep fd87:f53:25b4:0:231d:4cbb:bca7:10
    inet6 fd87:f53:25b4:0:231d:4cbb:bca7:10/64 scope global
root@raspi:~ #

Another viable solution would of course be to just reboot the RaspberryPi and hope your DHCP-Server now assigns the correct IP. However my FritzBox only allows to set an IPv4 reservation in the DHCP settings. IPv6 addresses can't be used for DHCP reservations at all. So this was no solution for me.

If you want to know how to configured a mixed static and dynamic IPv6 read here: Configuring an mixed IPv6 setup - static ULA, dynamic GLA

Comments

Configuring an mixed IPv6 setup - static ULA, dynamic GLA

In Fix keepalived error: bind unicast_src - 99 cannot assign requested address I mentioned that I fixed my problem with a mixed static & dynamic IPv6 setup. Here is how I did it.

Status quo

For a few years I followed the Raspbian recommendation to use DHCP to assign the static IP. And it worked - until it didn't. This was my config. Note that I didn't use a fallback profile. I like to notice when DHCP doesn't work.

root@raspi:~# cat /etc/dhcpcd.conf
[...]
interface eth0
        static ip_address=192.168.1.10/24
        static ip6_address=fd87:f53:25b4:0:231d:4cbb:bca7:10/64
        static routers=192.168.1.1
        static domain_name_servers=127.0.0.1 ::1

# It is possible to fall back to a static IP if DHCP fails:
# define static profile
#profile static_eth0
#static ip_address=192.168.1.23/24
#static routers=192.168.1.1
#static domain_name_servers=192.168.1.1

# fallback to static profile on eth0
#interface eth0
#fallback static_eth0

Due to an accidental power loss my RaspberryPi rebooted and got a new IPv4 and IPv6, totally different from the configured ones.

The changed IPv4 was easily identified. I forgot to set a DHCP reservation for the MAC address in my DSL router. I suspected then that I also forgot this for the IPv6. Only to notice: My FritzBox 7530 doesn't allow to add IP/MAC reservations for IPv6. Only IPv4 addresses are supported.

And that was the moment where I had enough and decided to ditch DHCP all together.

For IPv4 this was easy enough.

root@raspi:~# cat /etc/network/interfaces.d/ipv4
auto eth0
iface eth0 inet static
        address 192.168.1.10
        netmask 255.255.255.0
        gateway 192.168.1.1

However for IPv6 it took me a few minutes. Specify address and netmask, done. Right?

Well, no. Internet access wasn't working. A quick check revealed that the GLA address was missing.

root@raspi:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether aa:aa:aa:aa:aa:aa brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.10/24 brd 192.168.1.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fd87:f53:25b4:0:231d:4cbb:bca7:10/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::aaaa:bbbb:cccc:dddd/64 scope link
       valid_lft forever preferred_lft forever

Hosts in my LAN were perfectly reachable. A ping to an public IPv6 didn't succeed.

root@raspi:~# ping6 google.de
PING google.de(lcmuca-ah-in-x03.1e100.net (2a00:1450:4016:803::2003)) 56 data bytes
^C
--- 2a00:1450:4016:803::2003 ping statistics ---
13 packets transmitted, 0 received, 100% packet loss, time 12441ms

Turns out, when you configure a static Unique Local Address (ULA), which is the IPv6 equivalent to our beloved RFC1918 IPv4 (192.168.0.0/16, etc.), Linux doesn't listen to Router Advertisements (RAs) anymore. Hence no Global Link Address (GLA).

The small details is to set autoconf 1 and accept_ra 2 for the interface. This is also documented in the Debian Wiki. This is my working config. My internal network config is now static which is a must as I run some services on keepalived VIPs.

root@raspi:~# cat /etc/network/interfaces.d/ipv6
# IPv6
auto eth0
iface eth0 inet6 static
        address fd87:f53:25b4:0:231d:4cbb:bca7:10
        netmask 64
        # Mixing static and dynamic IPv6
        # from: https://wiki.debian.org/NetworkConfiguration
        # use SLAAC to get global IPv6 address from the router
        # we may not enable ipv6 forwarding, otherwise SLAAC gets disabled
        #
        # Automatically create IPv6 addresses based on Router Advertisements (RA)
        autoconf 1
        # Always accept RAs, even if a static IPv6 address is configured
        # as normally Linux doesn't listen to RAs anymore when a static IPv6 is assigned
        accept_ra 2

Disable DHCP

And don't forget to disable the DHCP service.

root@raspi:~# systemctl stop dhcpcd.service
root@raspi:~# systemctl disable dhcpcd.service
Synchronizing state of dhcpcd.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install disable dhcpcd
Removed "/etc/systemd/system/dhcpcd5.service".
Removed "/etc/systemd/system/multi-user.target.wants/dhcpcd.service".

After all these years?

Once again I am left wondering why I had this problem for the first time in 2026. After all IPv6 is 25 years old..

Comments

Datenschutzverständnis

Wann immer ich Leuten erklären muss, wieso Datenschutz in der Realität so merkwürdig gehandhabt wird und häufig irgendwie am Ziel vorbeigeht, erkläre ich das mit dem Diskretionsverständnis in einer Arztpraxis.

Dort gilt ja auch "Aus Diskretionsgründen bitte Abstand halten". Bringt halt nur gar nichts, wenn die Anmeldung mitten im Raum ist oder die Mitarbeitenden an der Rezeption so laut sprechen, das man doch alles versteht.

Comments

Calculating filehashes with PowerShell (Get-FileHash)

As I forgot again that PowerShell has the Get-FileHash cmdlet I am now writing a small article about it.

It's plain easy to use and supports MD5, SHA1, SHA256, SHA384, SHA512, MACTripleDES, RIPEMD160.

This way I can check if the .zip-file containing the Android ROM update for my mobile was downloaded correctly.

PS D:\> Get-FileHash -algorithm MD5 .\0e4b047c9f2d49df8d92f45ebff4704f.zip

Algorithm       Hash                                                                   Path
---------       ----                                                                   ----
MD5             1C53E270FE049B1CDBD361F6A29900D0                                       D:\0e4b047c9f2d49df8d92...

PS D:\>

Back in the day I used the HashTab to add a "Hashes" tab to the file detail dialog. Displaying the hash for several algorithms for the file. Even allowing to compare them against a given string.

Sadly that utility is not developed anymore. German IT magazine Heise still has a download and it should still work under Windows 10, but I'm good with the PowerShell cmdlet.

Comments

Enrollment into Windows 10 Extended Security Updates (ESU) not working? Try this script

For a few weeks I tried to enroll my Windows 10 gaming PC into the Extended Security Update (ESU) program. Nothing worked. I could click on the register link in Windows Update, provide my username and password for the Microsoft account and then: Nothing.

A blank window appears for the fraction of a second, my mouse cursor turns into a loading wheel for ~5 seconds and that's it.

Windows Update kept showing me that I won't receive security updates along with the link to register.

I tried various things.. Logging into the Microsoft Store app. Enabling "Find my device". Turn on Geolocation. Set various registry keys. Restarting services. Deinstalling Microsoft patches of which some people claimed interfered with the enrollment. The one thing I just didn't want, was to convert the logon method to log on with my Microsoft account. I wanted to keep my local account.

And this evening I finally managed to get my PC enrolled.

The following discussion under this question in the Microsoft Q&A forums contained the link to a GitHub repository and the user claimed this script fixed it for him.

Onwards to GitHub it is! Visiting https://github.com/abbodi1406/ConsumerESU I was amazed that it's a simple PowerShell or CMD-Script. This means I could take a quick glance over the code. Naturally I'm a bit paranoid running some script somebody on the Internet wrote. But the script is harmless. Yes it does many things with various services, set some config values and send a few HTTPS-Requests. All of these are fine though, targeting Microsoft servers and are there to acquire needed information (Enrollment Tokens, etc.) for the Enrollment to succeed.

And what should I say? Executing the PowerShell script with the -Local option finally did the trick.

PS C:\Users\USERNAME\Downloads\ConsumerESU> .\Consumer_ESU_Enrollment.ps1 -Local

Enable Consumer ESU feature ...

Disable EEA_REGION_POLICY_CHECK features ...

Evaluate ESU Eligibility state ...
Eligibility Status:  2 Eligible
Eligibility Result:  1 SUCCESS

Obtain Authorization Local Token ...
Obtained token for Local user account

Request Consumer ESU License ...
Operation result: Success

Evaluate ESU Eligibility state ...
Eligibility Status:  3 DeviceEnrolled
Eligibility Result:  1 SUCCESS
PS C:\Users\USERNAME\Downloads\ConsumerESU>

Now the register link in Windows update is gone along with the warning that I am not receiving security updates anymore. The download for the current cumulative updates started shortly after a search for new updates.

Thank you abbodi1406!

Comments

Sauce cooking book organized

Things you do to calm down in the evening. 😄

Now my sauce cooking book is a bit more organised. Making it easier to find what I search.

Comments