Raspberry Pi + Manjaro: Adding IPv6 Static IP in Network Manager

Hello!

I’m trying to add a static IPv4 and IPv6 address to interface eth0, using Network Manager.
Instructions:

Networking - Manjaro
How to setup a static IP address on Manjaro Linux - LinuxConfig.org

I had no issues setting up the IPv4 address. I restricted my router’s v4 DHCP to a certain range of addresses, and am happily assigning static IPs across the network from the pool DHCP can’t touch.

However, I cannot set up a routable static IPv6. I think this is coming down to my unfamiliarity with how IPv6 works. I’m trying, but a lot of the documentation assumes I know more than I already do.

My router is handing out v6 IPs in stateless mode, which seems to work best for my ISP and LAN.

Manjaro wants an:

  1. IPv6 address;
  2. IPv6 prefix; and
  3. Gateway

I think I can just make the v6 address up, and it will work without conflict, since my router is smart enough to use RA to see if an address is taken before it tries to assign it via DHCP. (No more v4 DHCP reservation tables!)

The “Prefix” appears to be the size of the block. I’m not sure what to give it for this one. I want to reserve a single address, so perhaps /64 isn’t the way to go? Even if it works, that’s a lot of wasted space.

I gave it a shot and added an address in the form: WWWW:XXXX:YYYY:ZZZZ:7d01::1/64, where the first 4 bytes are the network wide prefix set at the router level, prefix 64, gateway set to my router’s IP.

It shows up via ip address show eth0, and I can ping the machine from itself, so it’s working as a localhost address, but I can’t get to it from anywhere else. Network Manager highlights my router’s IPv6 address in yellow, so I guess it’s trying to warn me about something?

Any suggestions would be appreciated. Thanks!

This will also work best for your Manjaro system. One of the nice things with IPv6 is that you can have a lot of address added to a interface.

Choose in NM the automatic method. Use the EUI64 address generation mode. You can choose to add a extra IPv6 with the IPv6 privacy extension. You might want to use that and choose Enabled (prefer temporary address). Which means all outgoing connections are done with the temporary IPv6. But you can connect to your device via the static IPv6. Network services (like sshd or httpd) should listen on all IPv6 addresses.

If you choose the IPv6 privacy extension you will get 3 IPv6 addresses attached to your interface. The f80:: is the link local address. Many router use a link local address as the gateway. You will also get a temporary IPv6 and a static IPv6. The static IPv6 uses the prefix and adds the mac address via the EUI-64 schema.

The modified EUI-64 schema uses the MAC address of the interface, spltis it in half, added ff:fe in the middle and inverts the 7th bit of the MAC address (which usually means add 2 to the 2. hex-symbol).

If you want to go completely static, you need to find out the address of the gateway. It is often a fe80:: link local address. You can try to ping FF02:0:0:0:0:0:0:2 via your Network device, all router in your network should answer over their IPv6 gateway address.

ping -I eth0 FF02:0:0:0:0:0:0:2 

You need to specify the interface. A link local IPv6 should be available even without any IPv6 set up.

Hello!

Thanks for your help. That … is a lot of information, and I’m still digesting it between having to interface with the real world for work things.

I’m trying to add a second, static IP for use with server apps running on the device. In other words, I need an unchanging, permanent IPv6 address for the device.

For the moment, I’ve removed the static IP I tried to set up, so I can start over. I’m back to:

  1. IPv6 Link Local Address
  2. Router-assigned, rarely-changing IPv6 address. (I’m actually pretty sure this hasn’t changed in months, but it’s still listed as “dynamic.”

ip address show eth0 :

inet6 +router-assigned address+/64 scope global dynamic noprefixroute
valid_lft 604454sec preferred_lft 604454sec

inet6 fe80::/64 scope link noprefixroute
valid_lft forever preferred_lft forever

The localhost address is, of course, not reachable from other machines on the network.

Unrelated, I notice that the v6 connection is REQUIRED for this interface, but the v4 connection is not. Is that normal?

EDIT: I found this instruction/example settings file, but it clearly does not apply to a system running Network Manager.

In the question you reference, the second answer shows the equivalent solution for IPv4. In the case of IPv6, the /etc/network/interfaces file should contain something like this:

iface eth0 inet6 static
address 2001:db8:1:2::2
netmask 64

Add additional IPv6 addresses when $IFACE goes up

up ip -6 addr add 2001:db8:1:2::3/64 dev $IFACE
up ip -6 addr add 2001:db8:1:2::4/64 dev $IFACE

Remove them when $IFACE goes down

down ip -6 addr del 2001:db8:1:2::3/64 dev $IFACE
down ip -6 addr del 2001:db8:1:2::4/64 dev $IFACE

You always will get the same address with SLAAC and EUI-64. The Host part of the IPv6 is static. This is the reason the hole IPv6 privacy extension stuff was introduced. However if your router starts to give out a new IPv6 Network Prefix, the address changes. The host part is still static, but the Network part will change to the new Network Part.

But if your Network Part is not static you will never have a static IPv6 address that is reachable. In this case it doesn’t matter how you configure it.

An example. The MAC address is b8:27:eb:ac:1a:2e , the IPv6 Network Part is 2001:db8:a:b::/64
The IPv6 with SLAAC and EUI-64 will always be

2001:db8:a:b:ba27:ebff:feac:1a2e
\___________/\_________________/
  Network         Hostpart
  Prefix

But if your ISP assigns to you a new Network Prefix, the address changes. Let’s say you now need to use 2001:db8:c:e::/64
The IPv6 with SLAAC and EUI-64 will always be

2001:db8:c:e:ba27:ebff:feac:1a2e
\___________/\_________________/
  Network         Hostpart
  Prefix

However if you assign 2001:db8:a:b::2 static to the network interface, this address can’t be reached after your ISP give out a new IPv6 Network Prefix to your router.

If you can’t be certain to have always the same IPv6 network prefix, you need to create your own IPv6 Prefix network in your LAN. For example in the fd00::/8 address space. This is not pretty, but it works. So you would have your normal link local, the IPv6 address with your ISP prefix and your own IPv6 prefix network.

I would not worry about the word “dynamic”. Every address that is created via SLAAC is dynamic but also static.

The localhost address is ::1 . A link local address always starts with fe80:: . These addresses are reachable and they need to be reachable form every devices on the same link. Without you can’t use IPv6. But since they are link local address, you need to specify the network interface to use them.
With ping you can use the -I option or you can use fe80::ba27:ebff:feac:1a2e%eth0 . (Sometimes it is %25 , depends on the application and/or OS)

No, you can choose if you want to have it required or not. For example if IPv6 is required but NM can’t set up IPv6, the connection will fail even if IPv4 setup was successful.

You would have to swtich to a Debian based OS to follow this.


But since we are talking about providing server services, why not ditch the GUI (and NM) and use a more admin friendly network setup program, like systemd-networkd.

I’m on a pi and would prefer not to change network management tools at this juncture if avoidable.

Thanks for the additional info about IPv6. That is useful information I did not have.

My prefix is unchanging. To my knowledge it has even survived cable modem reboots, which maybe happen once every 6 months or so.

So what I need, based on what you said, is to get a second SLAAC/EUI-64 address for eth0 on the Pi? How do I do this with network manager?

Or should I just use the link-local address?
EDIT 2: I can’t use the link-local v6 address, because I’m doing this for use with docker, and docker can’t understand IPv6 addresses containing a % sign, even though the &eth0 thing works perfectly when you, say, ping -6 -c 4 link_local_address%eth0.

EDIT: I should clarify that my end goal is to make sure the Pi has two (2) IPv6 addresses reachable inside my LAN.

EDIT 3: At this point, yes, I’m attempting to modify my network to get around a docker failing with IPv6. Go, docker. Good job.

Docker and IPv6 is totally different to set up than Docker with IPv4. For example there is by default no NAT and I would not try to create one. Which means you need to configure the Docker bridge which a IPv6 subnet prefix. Or even better create a own bridge network in Docker for your containers. Docker then will use a IPv6 address form this subnet (you can make the chosen addresses static). It will not use any IPv6 configured on the Host network interface. You might need a tool like NDPPD running on the host. Since there is no NAT, every Docker container is completly exposed with IPv6. You should think about a firewall for the Docker bridge IPv6 subnet.

Yes indeed. Docker can’t use link local. I would use a /80 for the Docker IPv6 subnet. ( If this
is your IPv6 network part 2001:db8:a:b::/64 this is one available subnet 2001:db8:a:b:123a::/80

Enable IPv6 support | Docker Documentation

Use bridge networks | Docker Documentation

There is only one static IPv6 address available with SLAAC/EUI-64. There is only one MAC address attached to a network interface. You can get a second global temporary IPv6 with the privacy extension, but this one is dynamic.

Not with NM. The only way to get two global static IPv6 address with NM is to set up everything statically.

No, link local addresses work nicely in the terminal, but it would not work in a browser for example.

I’ve got docker configured to use IPv6 alongside IPv4 after a … great deal of struggle over a period of a couple weeks. My setup includes a number of bridge networks. Docker’s IPv6 support is so incomplete, following the official docs does not even lead to a working solution. I had to dig deep into the google, and ended up using a solution that probably counts as cheating.

All I ever wanted to do when I made my original post in this thread was resolve a port conflict: I have two docker containers that want to listen on port 443, so I wanted to bind each of them to separate interfaces.

  1. I could very easily solve this with a reverse proxy and a single IPv6 address, but I did not want to put the docker container for pi-hole on the public internet, even if I’ve restricted access to myself/my local network.
  2. First alternative: activate the wifi interface and use those addresses for one of the containers. I had been trying to avoid this because I didn’t want to bind a service service critical to my internal network to wifi, especially in a building where there are dozens of different networks.
  3. The other alternative, which I have used successfully, is just to plug a second NIC into the pi and let he router hand me another pair of v4 and v6 internet-routable addresses. I was actually doing this for a while with great success, but I found it slowed the Pi’s overall network performance somewhat. Not to mention I’d be losing one of two of the Pi’s USB 3.0 ports.

Since the Pi apparently can’t do what I need, I’m going to leave the pi-hole as the only container running on it, and shift all my other containers running behind nginx-proxy-manager to my new NAS that’s getting set up this week.

It is unfortunate the IPv6 addressing on eth0 cannot be made to do what I need at the OS level, considering I got it working on the IPv4 side in less than 10 minutes.

A Pi can do it. And even Manjaro can do that, but of course I would argue that using Manjaro for this was a wrong decision.

The problem is that you try to use the wrong software for the job. NM is still a good fit for a desktop, you get some options primarily for the need of Desktop users, specially with the GUI.

If you want more, you need to choose different software. Like systemd-networkd or netctl for Arch Linux based distros.

Well, it is not. Everything is there, you just need to set it up correctly.

I would argue that setting up IPv6 is even faster, because you just need to set the IPv6 network prefix. You don’t need to add any IPs or think about configure port forwarding.

@xabbu, thanks for all your help and the useful information you shared. :slight_smile:

I’m not really interested at all in debating whether I’m using the right tools–I’m using the tools I have on hand. I’m using the Pi with Manjaro on it because that is the one linux machine I have, and I’ve already wasted more time than I really had to spend trying to get this to work. I certainly don’t have time to redo it with another distro or re-learn how to manage Manjaro’s network stack with a new tool, unfortunately.

I agree that the tools I’m trying to use are not up to the task. I just don’t have time to do anything about that. And it is incredibly frustrating because if I could just stick to IPv4 this entire problem would have been solved in 5 minutes–that’s about how long it took me to assign a static IPv4 using Network Manager–but I can’t run a DNS Server without IPv6 support and consider it good.

I will have another linux box by the end of the week when my Q-NAP arrives, and I will be circumventing this entire problem by moving my microservices over to the NAS’ docker subsystem, and leaving the Pi to do nothing but run pi-hole, which will be free to monopolize incoming connections on port 443.

This is veering off topic, and I’d rather not get into a whole thing about this unless it was in a separate thread, but I consider Docker’s IPv6 support incomplete for a number of reasons related to the difficulty of using it compared to IPv4 support–it requires you learn a lot more about networking than IPv4 support does–and the utter lack of complete documentation. As you noted, the user must set up IPv6 support, and there is NO official complete documentation to do that, unless you’re content just to run everything through the default bridge, which you should not be doing.

I respectfully disagree that setting up IPv6 is faster for my use case. I spent minutes making IPv4 do what I wanted. I’ve spent days to discover my current software/hardware configuration cannot do what I want, at least without replacing portions of the network stack, because the documentation available was not sufficient to make that clear. It wasn’t until I talked to you that I realized the built in network stack literally cannot do what I want without modification.

Not to mention that all I ever wanted to do was add a static local IP with internet access alongside a server-assigned IP. That should not be something I need to replace my network stack/OS/hardware to do, and with IPv4 it is stupidly simple.

And if I want to solve this problem the quickest, dirtiest way, I can just turn WiFi on for the Pi and use that interface’s separate assigned IPv6 address to do what I want. I’m probably going to end up going with that because the Pi doesn’t seem to like having a second ethernet adapter plugged into the USB port, and I need the last ethernet jack on my router for my NAS.

When the fastest solution is an inelegant kludge, that is what most end-users will use, and the core problems of usability of the proper solution remain unresolved.

Thanks again. I end this journey better educated and supremely frustrated with IPv6, which … is about how it always goes for me with IPv6.