Dietpi: General | Remove IPv6 disable feature

Created on 20 Aug 2018  ยท  17Comments  ยท  Source: MichaIng/DietPi

I've added some settings to /etc/sysctl.conf to disable IPv6. After adding them and running sysctl -p the settings are applied correctly but if I reboot these are not applied automatically.

Before:

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 4e:bf:e3:41:7e:06 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.62/24 brd 192.168.1.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::4cbf:e3ff:fe41:7e06/64 scope link
       valid_lft forever preferred_lft forever

cat << EOF | sudo tee -a  /etc/sysctl.conf
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
net.ipv6.conf.eth0.disable_ipv6 = 1
EOF

$ sudo sysctl -p

Manualy IPv6 is disabled:

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 4e:bf:e3:41:7e:06 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.62/24 brd 192.168.1.255 scope global eth0
       valid_lft forever preferred_lft forever

If I reboot, IPv6 is not disabled. I believe this is related to DietPi since I have some stock Debian Stretch installs that the same parameters are persisted after reboot.

Enhancement

All 17 comments

Also in my install (the Firefly RK3399 board), even if I toggle the IPv6 setting on dietpi-config Network Options, it keeps "On".

@carlosedp
Thanks for your report.

How to toggle IPv6 depends on the board/kernel.

The most effective way to completely disable IPv6 functionality is to blacklist the ipv6 module, instead of using the sysctl net.ipv6.conf settings: echo 'blacklist ipv6' > /etc/modprobe.d/blacklist-ipv6 Otherwise it is just not used for the configured interfaces, but still available, which can cause issues with other system/software parts trying to bind/access IPv6. But this is how we do it with the dietpi-config toggle, which you already tried. After toggle IPv6 there, note that you need to reboot for it to take effect. It says [On] as long as the related /proc/sys/net/ipv6 folder is still present. _We could add some flag to show Reboot needed, [Off] after reboot or something to make it clearer ๐Ÿค”._

However we found that on x86_64 machines, as well as RPi since kernel 4.14.y, IPv6 is not a module anymore, but baked into the kernel and enabled by default. Thus the blacklisting does not work there. If dietpi-config switch does not work in your case, then this seems to be true for Firefly RK3399 as well. In those cases we add ipv6.disable=1 to the boot cmd line. However this needs to be coded for every non grub machine separately, since the cmd line is found within different files/places on every SBC.

Maybe you can find our where to add boot commands (or @Fourdee if you find time), so I can add the correct switch for this board as well.

I am not 100% sure whether or not the net.ipv6.conf settings work in all cases (ipv6 module or not and all boards), but it should, since it is one layer above and should be respected by the interface tools etc. Also in your case it seemed to have worked. Now the question why it does not survive reboot:

  • Are the lines you added are still present within /etc/sysctl.conf? You can also check via sysctl -a | grep ipv6. If not, then the only idea I have is the asynchronous file system sync. Try sync after you added the settings, wait for some seconds, then reboot. If still file changes do not survive reboot, then there is a deeper issue to investigate.
  • Generally I advice to not edit /etc/sysctl.conf directly, but instead add a new file that contains the desired settings:
cat << _EOF_ > /etc/sysctl.d/disable-ipv6.conf
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
net.ipv6.conf.eth0.disable_ipv6 = 1
_EOF_

This is generally cleaner and you can easily revert changes by simply remove the file. As well system package updates can update the unchanged default config files, whereas they cannot (better should not), if you manually edited them.

Thanks @MichaIng, I've been using this settings on sysctl on many distributions with no problems so I believe is the "correct" way to do it.

Maybe you can find our where to add boot commands (or @Fourdee if you find time), so I can add the correct switch for this board as well.

Disabling on the boot parameters is a hassle on these boards since it's baked into the "img" that is flashed into the board via cable from another computer. You don't have access to the extlinux.conf file to change this since the boot partition is not mounted.

The sysctl.conf file is there correctly as I've configured but sysctl -a still shows ipv6 enabled after reboot. I need to sysctl -p to re-read them. I don't know where this get lost.

Ah yes, it's the best practice to have separate files, just did it as a test. Thanks for the tip.

@carlosedp
Hmm very strange, no idea how sysctl.conf settings are not applied automatically, if present on boot. Usually sysctl -p should only be needed to apply settings avoiding reboot. Needs some research, maybe as well a kernel / bootloader specific issue?


systemd-sysctl seems responsible for loading the sysctl configuration. Please check:
systemctl status systemd-sysctl
Try systemctl restart systemd-sysctl, if it has the same affect as sysctl -p and applies the IPv6 settings.

Maybe the settings get applied then something else overwrites and re-enables IPv6.

@carlosedp
Possible, as said without telling the kernel to disable IPv6 (cmd line), it is generally available. Possible that something else then enables it on demand. Not sure how well sysctl is respected then.

But again, did you try:

systemctl restart systemd-sysctl
systemctl status systemd-sysctl

and check for errors? Maybe it throws an error or a warning that/why IPv6 settings are not applied.

But so far we can sum up, that net.ipv6.conf.*.disable_ipv6=1 is needed on Firefly RK3399 since IPv6 is no module there and we have no easy way to access the boot cmd line so far. I will do some research about the latter. Actually it would be nice to unload IPv6 completely to avoid other interfaces and system parts trying to use it.

Found the problem. The ipv6 module is disabled by blacklist so when the sysctl.conf file is applied, the module is still not loaded and ipv6 doesn't get disabled by the settings below:

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
net.ipv6.conf.eth0.disable_ipv6 = 1

Then I don't know why the module gets loaded afterwards.

If I remove the modprobe.d/99-dietpi-blacklist-ipv6.conf and add the settings above to /etc/sysctl.d/60-ipv6-disable.conf, ipv6 is successfully disabled.

IMO, blacklisting the module is not necessary.

@carlosedp
Ah, okay in this case it IS indeed a module! I am confused.
Usually I would say it the other way round: Due to blacklisting, disabling the module (higher level, not completely unloaded, more needed config lines) is not needed. Furthermore disabling the module, if it is blacklisted throws warnings, that the module is not available, thus settings cannot be applied.

Then I don't know why the module gets loaded afterwards.

Yeah this is strange. Can you check cat /etc/modules, if ipv6 is explicitly listed there? Not sure if in such case the /etc/modules entry overrides the blacklisting. In case we need to check/remove the entry, when disabling IPv6. Also interesting would be, if the module is loaded by default on all devices or the /etc/modules entry is actually needed in some cases. At least on all machines I have, it is not needed.

No modules are added to /etc/modules. Look like some default behavior.

IMO, the correct way of disabling ipv6 is adding the lines to sysctl instead of blacklisting the ipv6 module (this also solves the problem where ipv6 is not a module in newer kernels).

@carlosedp

IMO, the correct way of disabling ipv6 is adding the lines to sysctl

"Correct" is properly not the right term here ๐Ÿ˜œ, as it depends on what you want. If you simply want your network interfaces to not use IPv6, then it "does the job" on all kind of IPv6 implementations.
But it is still loaded and generally available, check: ls -l /proc/sys/net
If you want to keep your system as slim as possible in terms of RAM usage, loaded modules/functions and/or completely want to disable IPv6 ability system-wide, then it "does not do the job".

I made some research:

  • If IPv6 is actually a module, blacklist ipv6 is indeed the cleanest way to skip module loading right in the first place. But it seems, that due to other module dependencies, the blacklist can be ignored.
  • In such cases, install ipv6 /bin/true or an alias redirect should work. It does not tell the system to not load the module, but pretends that it is either already installed respectively loads "nothing" instead of the actual module.
  • If it is no module and no access to cmd line, then indeed there seem to be no other way than sysctl.

Ref.: https://lists.debian.org/debian-security/2012/08/msg00016.html

If one finds time to test echo 'install ipv6 /bin/true' > /etc/modprobe.d/disable_ipv6.conf would be great. Otherwise we will add sysctl to toggle IPv6 on Firefly RK3399.

I can confirm that echo 'install ipv6 /bin/true' > /etc/modprobe.d/disable_ipv6.conf disables the ipv6 module successfully but the Docker bridge interface gave a couple errors on dmesg and does not get loaded/created:

[    3.862547] bridge: Unknown symbol ipv6_dev_get_saddr (err 0)
[    3.884099] bridge: Unknown symbol ipv6_dev_get_saddr (err 0)
[    4.198722] bridge: Unknown symbol ipv6_dev_get_saddr (err 0)
[    4.213138] bridge: Unknown symbol ipv6_dev_get_saddr (err 0)
[    4.299558] bridge: Unknown symbol ipv6_dev_get_saddr (err 0)
[    4.314741] bridge: Unknown symbol ipv6_dev_get_saddr (err 0)
[    4.972853] bridge: Unknown symbol ipv6_dev_get_saddr (err 0)
[    4.988431] bridge: Unknown symbol ipv6_dev_get_saddr (err 0)
[    5.242552] bridge: Unknown symbol ipv6_dev_get_saddr (err 0)
[    5.255784] bridge: Unknown symbol ipv6_dev_get_saddr (err 0)
[    5.365598] bridge: Unknown symbol ipv6_dev_get_saddr (err 0)
[    5.379761] bridge: Unknown symbol ipv6_dev_get_saddr (err 0)
[    6.078214] bridge: Unknown symbol ipv6_dev_get_saddr (err 0)

@carlosedp
Hmm, I guess Docker has some setting to enable/disable IPv6. Looks similar to default Lighttpd config that requires IPv6 available, otherwise throws errors.
So it is possible that Docker re-enables the blacklisted ipv6 then, which can't be done if install ipv6 /bin/true is used.

But indeed for most compatibility leaving IPv6 loaded (just don't use it for network interfaces via sysctl) works better. Maybe we can allow both, completely unload it via blacklist/install directive or, in case of errors, use the sysctl settings instead. I will think about a handy solution. Many thanks for your research and tests, that really made some points clearer ๐Ÿ‘.

I believe the most safe and workable way is using sysctl too. The module consumes 400kb of memory and I think it's acceptable to keep it loaded and avoid errors.

ipv6                  405504  31 bridge

@carlosedp @MichaIng

IMO, blacklisting the module is not necessary.

I actually believe we should remove the option to disable IPv6, for the following reasons:

  • IPv6 is now required by many applications to simply run.
  • Not all SBC images we use allow for kernel boot command line options to be edited.
  • If the IPv6 is built into the kernel (not module), i'am unsure if it can be disabled?
  • The memory saved by disabling it, is minimal on todays SBC devices.
  • IPv6 is becoming more and more common in end user home devices.

@Fourdee
Yeah, maybe you are right. I am perfectionist, thus will always prevent IPv6 from loading on my devices, where I know that it is really not needed. But I guess our current solution does anyway not work on some devices and cases (3rd party software depending on IPv6, thus re-enable the blacklisted module) and users like me can do that themselves.

If the IPv6 is built into the kernel (not module), i'am unsure if it can be disabled?

  • If it's a module, just blacklist ipv6 or install ipv6 /bin/true (or alias <name> off) inside /etc/modprobe[.d/] will work.

    • blacklist ipv6 tells the system to not load any module that has ipv6 alias. But 3rd party software (seems to be Docker in TO case) can still load (hotplug) it, if they depend on it.

    • install ipv6 /bin/true overwrites the install/insert command for the ipv6 module/alias with /bin/true, does doing nothing but returning 0/true. Thus also 3rd party software will fail to hotplug it, or let's say will think they did it but fail to access ipv6 functionality afterwards ๐Ÿ˜‰.

    • Ref: https://linux.die.net/man/5/modprobe.conf

  • If a module is baked into the kernel, thus no module, all modprobe/kmod related settings have no effect. lsmod/kmod list will not even show ipv6. Then only the boot cmd line addition ipv6.disable=1 can prevent it from being loaded, which is not that easy on all devices. At least so far this seems to be just the case for RPi with current kernel and x86_64, where we have easy cmd line access. But high likely other SBCs will also switch to non-module IPv6 with newer kernel versions (or did already and just no one recognized so far).
  • /etc/sysctl[.d/] settings work in all cases, as long as IPv6 (module or kernel-baked) is available. And as the related kernel config paths are available (/proc/sys/net/ipv6/), 3rd party software do not fail to read them.

Just on issue with RPi. By default (per Raspbian images) the ipv6 module is disabled (alias off) via:

cat /etc/modprobe.d/ipv6.conf
alias net-pf-10 off

This should not have any effect any more, since at least on my RPi Raspbian Buster it is no module and also I am not sure, if the net-pf-10 is actually still the correct alias on current kernel versions.

A bid funny, that we are talking about pros/cons of IPv6 toggle possibility, where all RPis, at least as Raspbian dev intention, have it disabled anyway, even in a way that does not work any more ๐Ÿคฃ.

AFAIK, the errors of missing net.ipv6.conf.* entries on boot were the reason that time for switching from sysctl to modprobe for IPv6 toggle ๐Ÿ˜‰.
So to avoid this, when using sysctl, we should as failure safety scan whole /etc/modprobe[.d/] for ipv6 files/entries and remove them. Should be done on PREP as well.
Also we should check for [[ -d /proc/sys/net/ipv6 ]] before adding the settings, otherwise inform user that ipv6 is not loaded at all.

@Fourdee
Next software title that needs IPv6 available for successful APT install:

  • G_AGI redis-server fails on Debian Buster due to bind 127.0.0.1 ::1 default setting in /etc/redis/redis.conf. On Stretch it is just bind 127.0.0.1, thus works fine here. Manual adjustment on second SSH session of that setting allows to continue install run.
  • Since we cannot adjust/pre-create all config files, and more and more software titles seem to configure IPv6 via ::1, I now fully agree that we should completely remove the option to unload IPv6 from kernel.
  • [x] Revert IPv6 disable option to use sysctl settings only.
  • [x] Remove ipv6.disable=1 from RPi and x86_64 systems (if found) on v6.15 patch.
  • [x] On IPv6 setting, check for [[ -d /proc/sys/net/ipv6 ]] and show a warning (in case of option to toggle), that current kernel settings do not load IPv6 which can cause issues on various software installs.
  • IPv6 is now enabled during patch (via the methods we previously used to disable)
  • IPv6 can no longer be disabled in DietPi scripts
  • preferipversion settings have been removed. Allowing the system to handle this automatically.

Testing:

  • ๐Ÿˆฏ๏ธ x86_64
  • ๐Ÿˆฏ๏ธ ARMv7

Completed.

Was this page helpful?
0 / 5 - 0 ratings