Open helbgd opened 3 years ago
I use IPv6 ULAs in the boot script already. They work fine but there are some caveats.
(1) and (2) are easy to solve. For (3), solving it is as simple as using a shell script with an infinite loop that checks the interface every second and re-adds it it's missing, then running the script with nohup in the background. Alternatively, you can code a go program that watches the netlink messages for when the interface is changed and act on that message. I've done both solutions and both work.
okay ...
what if you leave the ipv6 completely disabled via Unifi gui for the networks and assign a prefix assigned ipv6 gua and ula to each bridge interface manually via the init.d scripts ?
and write custom config files to /var/run/dnsmasq.conf.d/ to provide the slaac config by ourself ? i hope adding just a single file into that directory should not get deleted by the udapi server binary the dnsmasq thenn simply can get reloaded with kill -HUP and something like this as it reloads each config file in that directory ... as per
ps a |grep dnsmasq
1447 root grep dnsmasq
27465 nobody /usr/sbin/dnsmasq --conf-dir=/run/dnsmasq.conf.d/
the other question: not sure how this is normally beeing done:
Under a linux router how is a gua based on the prefix from the wan interface be built and kept refreshed once it changes ?
I hope the udapi server binary does not touch this ipv6 on the bridge interface at all once it is disabled in the gui for that network
# ps auxwww |grep dhcp6c
2166 root /usr/sbin/odhcp6c -e -v -s /usr/share/ubios-udapi-server/ubios-odhcp6c-script -P 58 eth4
4643 root grep dhcp6c
#
bad this is done by /usr/share/ubios-udapi-server/ubios-odhcp6c-script wich is getting triggered once the prefix changes this is a binary so once we want to do this we have to rewrite that ubios-odhcp6c-script ourself in a shell script or simmilar ...
not sure if this is worth the effort
I use IPv6 ULAs in the boot script already. They work fine but there are some caveats.
- You have to manually assign the ULA prefix (fd00::1/64 for example) to the bridge interface first.
- SLAAC is enabled and clients automatically configure addresses with the ULA prefix as long as Router Advertisement and Prefix Delegation is enabled in the Unifi Network LAN settings for that VLAN.
- The Unifi OS automatically deletes the ULA prefix from the bridge interfaces every few hours because it reconfigures them in response to prefix and lease changes. This means that you need a watcher daemon that watches the interfaces for when the ULA prefix is deleted and readds it if needed.
(1) and (2) are easy to solve. For (3), solving it is as simple as using a shell script with an infinite loop that checks the interface every second and re-adds it it's missing, then running the script with nohup in the background. Alternatively, you can code a go program that watches the netlink messages for when the interface is changed and act on that message. I've done both solutions and both work.
Do you have an example of the go and shell script ?
Thanks in advance
Do you have an example of the go and shell script ?
Sure, here is a simple shell script that checks every second and re-adds the ULAs if they're missing. Rename it to ula-watcher.sh (could only upload .txt), chmod +x ula-watcher.sh
, then run it in the background with
nohup ./ula-watcher.sh > ula-watcher.log &
@peacey @helbgd will you guys open a pull request and get this contributed to the repo?
@peacey I have tested your script. It works great. It's a shame that the UDM isn't capable to do this from the UI... Is it the right way, to use boostchicken/on-boot-script for this? I just copied my ula-watcher.sh to '/mnt/data/on_boot.d'. It works fine, but maybe you tell us, how you would deploy it in production?
@Menschomat, the script I wrote doesn't run in the background by default, so it will actually block other scripts from running if you use it as is in on_boot.d. You have to use the nohup ... &
command to run it in the background.
I would place the ula-watcher.sh script in /mnt/data or /mnt/data/scripts (not in on_boot.d). Then make a boot script in /mnt/data/on_boot.d/run-ula-watcher.sh
with these contents to run the script in the background:
#!/bin/sh
nohup /mnt/data/scripts/ula-watcher.sh > /mnt/data/scripts/ula-watcher.log &
Then run chmod +x on it. This way the script will run in the background. Confirm it is running in the background after you reboot by checking ps | grep ula-watcher
.
The nohup is necessary to run things in the background because the on-boot-script opens an SSH connection to the UDM base OS to run the boot scripts, and after the SSH connection is closed, all programs, even those running in the background will be terminated because SIGHUP will be sent to the programs. To get around that, we use nohup which runs the command in the background and makes the program ignore SIGHUP so it doesn't get terminated after the on-boot-script SSH session closes.
@peacey thank you very much for the fast response. This was very helpful 👍 It works like a charm.
Worth noting that we really should be careful in assigning prefixes -- note the MUST NOT in https://tools.ietf.org/html/rfc4193#section-3.2. Don't use the same hard-coded prefixes as everyone else :).
There's a tool to generate prefixes using the recommended algorithm here: https://cd34.com/rfc4193/
An alternative implementation:
In /mnt/data/ula/ensure_ula
, ensure you set ULA_PREFIX
using a value from https://cd34.com/rfc4193/ and you probably want to match the subnet numbers with any existing global subnets for each bridge interface rather than copying mine.
#!/bin/sh
ULA_PREFIX="fd60:e0ce:679d"
add_ula () {
if [ -z "`ip address show dev $1 to $ULA_PREFIX::/48`" ]
then
ip address add $ULA_PREFIX:$2::1/64 dev $1
fi
}
add_ula br0 0
add_ula br2 1
add_ula br3 2
add_ula br30 3
add_ula br40 4
In /mnt/data/on_boot.d/17-ula.sh
, sets things up to run ensure_ula
every minute:
#!/bin/sh
echo "* * * * * sh /mnt/data/ula/ensure_ula" > /etc/cron.d/ula
Ideally we'd have something that can run without needing to be edited -- a script that generates a ULA prefix if none exists, save it in a file that'll be kept, and examines existing IPv6 addresses if there's any assigned to see which subnet to use.
Thanks for the script, but I need to bump this. Same issue here with German Telecom. They mostly offer PD with changing addresses unless you have a business account with fixed addresses. But still I would rather use NATv6 and do not assign a public addresses. ULA support is needed on all Ubiquiti Products.
Are you planning on implementing this into the udm-tools? Is there a way to help besides submitting a pull request and developing it?
simple and dirty workaround if you want RA for a ULA prefix from dnsmasq enter following into on-state-change.sh after adding the ipv6 ula address to br0 device for example:
#!/bin/sh
ULA_PREFIX="fd60:e0ce:679d"
# on-state-change.sh
add_ula () {
if [ -z "`ip address show dev $1 to $ULA_PREFIX::/48`" ]
then
ip address add $ULA_PREFIX:$2::1/64 dev $1
fi
}
add_ula br0 0
#add_ula br2 1
#add_ula br3 2
#add_ula br30 3
#add_ula br40 4
# only add entry to dnsmasq config if it does not exist
add_dnsmasq () {
range=dhcp-range=set:ula6_$1,$ULA_PREFIX:$2::2,$ULA_PREFIX:$2::7d1,constructor:$1,64,86400
conf=$(find /run/dnsmasq.conf.d/ -type f -name "*$1*IPV6.conf")
if [ -z "`grep ula6_$1 $conf`" ]
then
echo $range >> $conf
# reload dnsmasq config
pkill -u 0 --signal HUP dnsmasq
fi
}
add_dnsmasq br0 0
# the same can be done for ip6tables firewall rules:
ip6tables -S | grep custom-80-443-tcp || ip6tables -I UBIOS_WAN_IN_USER -d ::xx:xxxx:xxxx:x/::ffff:ffff:ffff:ffff -p tcp -m comment --comment custom-80-443-tcp -m multiport --dports 80,443 -j RETURN
ip6tables -S | grep custom-80-443-udp || ip6tables -I UBIOS_WAN_IN_USER -d ::xx:xxxx:xxxx:x/::ffff:ffff:ffff:ffff -p udp -m comment --comment custom-80-443-udp -m multiport --dports 80,443 -j RETURN
# the above for example expose port 443 and 80 tcp for example in your ipv6 subnet to internet even with changing prefixes from provider because the firewall entry matches only the host part of the ipv6 GUA (the part after /64) and the provider prefix part of the address can change at any time ::ffff:ffff:ffff:ffff hostmask for masking the IPv6 Address ensures exactly that
# notice the GUA of the host should be always the same as it is calculated via the MAC address of the host
# with the above in place you can fully utilize customize everything you want
# ip6tables -S gives the iptables output in a way you can feed it back via commands to ip6tables for example
An alternative implementation:
In
/mnt/data/ula/ensure_ula
, ensure you setULA_PREFIX
using a value from https://cd34.com/rfc4193/ and you probably want to match the subnet numbers with any existing global subnets for each bridge interface rather than copying mine.#!/bin/sh ULA_PREFIX="fd60:e0ce:679d" add_ula () { if [ -z "`ip address show dev $1 to $ULA_PREFIX::/48`" ] then ip address add $ULA_PREFIX:$2::1/64 dev $1 fi } add_ula br0 0 add_ula br2 1 add_ula br3 2 add_ula br30 3 add_ula br40 4
In
/mnt/data/on_boot.d/17-ula.sh
, sets things up to runensure_ula
every minute:#!/bin/sh echo "* * * * * sh /mnt/data/ula/ensure_ula" > /etc/cron.d/ula
Ideally we'd have something that can run without needing to be edited -- a script that generates a ULA prefix if none exists, save it in a file that'll be kept, and examines existing IPv6 addresses if there's any assigned to see which subnet to use.
Works for me, Thanks!
I was able to use what @helbgd built on my UDM SE, with a couple of modifications.
$ULA_PREFIX:$2::/64
/data/
not /mnt/data
dnsmasq
if it was requiredHere's the new script that works on my Ubiquiti Dream Machine SE
#!/bin/bash
ULA_PREFIX="fded"
add_ula () {
if [ -z "`ip address show dev $1 to $ULA_PREFIX:$2::/64`" ]
then
ip address add $ULA_PREFIX:$2::1/64 dev $1
fi
}
add_ula br0 0
add_ula br2 2
add_ula br20 20
add_ula br100 100
add_ula br101 101
add_ula br102 102
ADDEDDNSMASQ=0
# only add entry to dnsmasq config if it does not exist
add_dnsmasq () {
range=dhcp-range=set:ula6_$1,$ULA_PREFIX:$2::2,$ULA_PREFIX:$2::7d1,constructor:$1,64,86400
conf=$(find /run/dnsmasq.conf.d/ -type f -name "*$1*IPV6.conf")
if [ -z "`grep ula6_$1 $conf`" ]
then
echo $range >> $conf
echo "Added $range"
ADDEDDNSMASQ=1
# reload dnsmasq config
# pkill -u 0 --signal HUP dnsmasq
fi
}
[ "$ADDDNSMASQ" == "1" ] && pkill -u 0 --signal HUP dnsmasq
Don't forget to chmod +x
that script so it will work.
The scripts here works great for setting up ULA, however, did anyone get reverse name lookups on the ULA ipv6 addresses working? I'm trying to overcome a "problem" where adguard won't properly assign client names when queries where sent from ipv6 addr
Hm, so while my devices do infact get the ULA addresses, I cannot use them to send/receive packets across the ULA networks (or more accurately across VLANs). The UDM SE can ping into both ULA v6 networks, but the devices cannot ping each other...
Ok, THANK YOU for this solution! It worked, but needed a few tweaks & requisites.
1) /mnt/data/onboot.d/ does not exist. Actually, /mnt is empty. So we need to install onboot.d and it'll now be in /data/ instead.
2) the script, at least in my UDM SE v4.0.6 did not like the sigle [ ] brackets in the last line. I had to do it the long way of if [ ... ] fi
3) running cron with 'sh' did not work either. I had to run bash -c 'sh ...'
via root.
To summarise,
curl -fsL "https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/HEAD/on-boot-script-2.x/remote_install.sh" | /bin/bash
Reference from here.
cd /data/onboot.d/
chmod -x 05-install-cni-plugins.sh 06-cni-bridge.sh
Enter your UDM SE interface's MAC address and get the prefix to use.
for this example, we'll use fdaa:abcd:1234
.
You can put it anywhere in /data/. I made a directory called ipv6-ula for consistency.
mkdir /data/ipv6-ula
vim /data/ipv6-ula/ensure_ula.sh
Add the following. Uncomment the interfaces you need.
#!/bin/bash
ULA_PREFIX="fdaa:abcd:1234"
add_ula () {
if [ -z "`ip address show dev $1 to $ULA_PREFIX:$2::/64`" ]
then
ip address add $ULA_PREFIX:$2::1/64 dev $1
fi
}
add_ula br0 0
#add_ula br2 2
#add_ula br20 20
#add_ula br100 100
#add_ula br101 101
#add_ula br102 102
ADDEDDNSMASQ=0
# only add entry to dnsmasq config if it does not exist
add_dnsmasq () {
range=dhcp-range=set:ula6_$1,$ULA_PREFIX:$2::2,$ULA_PREFIX:$2::7d1,constructor:$1,64,86400
conf=$(find /run/dnsmasq.conf.d/ -type f -name "*$1*IPV6.conf")
if [ -z "`grep ula6_$1 $conf`" ]
then
echo $range >> $conf
echo "Added $range"
ADDEDDNSMASQ=1
fi
}
# Use single brackets for compatibility
if [ "$ADDEDDNSMASQ" = "1" ]; then
pkill -u 0 --signal HUP dnsmasq
fi
Then,
chmod a+x /data/ipv6-ula/ensure_ula.sh
Then, in /data/on_boot.d/17-ula.sh, sets things up to run ensure_ula every minute:
vim /data/on_boot.d/17-ula.sh
add:
#!/bin/sh
echo "* * * * * root /bin/bash -c 'sh /data/ipv6-ula/ensure_ula.sh'" > /etc/cron.d/ula
and then chmod a+x /data/on_boot.d/17-ula.sh
That did the trick! And I got this working with my pihole too.
The add_dnsmasq
function currently requires IPv6 be enabled with Prefix Delegation or Static in Unifi Network App. It also seems to currently break DNSMASQ in Unifi with the following error.
2024 Aug 20 05:05:03 UDM-SE prefix must be zero with "constructor:" argument at line 13 of /run/dnsmasq.conf.d//dhcp.dhcpServers-net_Internet_of_Things_br2_192-168-2-0-24_IPV6.conf
2024 Aug 20 05:05:03 UDM-SE FAILED to start up
This error apparently prevents the DNS server from starting.
The
add_dnsmasq
function currently requires IPv6 be enabled with Prefix Delegation or Static in Unifi Network App. It also seems to currently break DNSMASQ in Unifi with the following error.2024 Aug 20 05:05:03 UDM-SE prefix must be zero with "constructor:" argument at line 13 of /run/dnsmasq.conf.d//dhcp.dhcpServers-net_Internet_of_Things_br2_192-168-2-0-24_IPV6.conf 2024 Aug 20 05:05:03 UDM-SE FAILED to start up
This error apparently prevents the DNS server from starting.
I’m facing the same issue. Is it mandatory to add the mode
between the interface
and the prefix-length
?
range=dhcp-range=set:ula6_$1,$ULA_PREFIX:$2::2,$ULA_PREFIX:$2::7d1,constructor:$1,ra-only,64,86400
I’m not sure, though, what the appropriate mode is. From Man page of DNSMASQ:
For IPv6, the mode may be some combination of ra-only, slaac, ra-names, ra-stateless, ra-advrouter, off-link.
ra-only tells dnsmasq to offer Router Advertisement only on this subnet, and not DHCP.
slaac tells dnsmasq to offer Router Advertisement on this subnet and to set the A bit in the router advertisement, so that the client will use SLAAC addresses. When used with a DHCP range or static DHCP address this results in the client having both a DHCP-assigned and a SLAAC address.
ra-stateless sends router advertisements with the O and A bits set, and provides a stateless DHCP service. The client will use a SLAAC address, and use DHCP for other configuration information.
ra-names enables a mode which gives DNS names to dual-stack hosts which do SLAAC for IPv6. Dnsmasq uses the host's IPv4 lease to derive the name, network segment and MAC address and assumes that the host will also have an IPv6 address calculated using the SLAAC algorithm, on the same network segment. The address is pinged, and if a reply is received, an AAAA record is added to the DNS for this IPv6 address. Note that this is only happens for directly-connected networks, (not one doing DHCP via a relay) and it will not work if a host is using privacy extensions. ra-names can be combined with ra-stateless and slaac.
ra-advrouter enables a mode where router address(es) rather than prefix(es) are included in the advertisements. This is described in RFC-3775 section 7.2 and is used in mobile IPv6. In this mode the interval option is also included, as described in RFC-3775 section 7.3.
off-link tells dnsmasq to advertise the prefix without the on-link (aka L) bit set.
Hello, would it anyhow possible to add ipv6 ULA support to the UDM ?
The Problem is I like to provide a pihole container trough podman in a mgmt Network that is reachable via all VLAN separated networks.
My ISP changes my ipv6 prefix from time to time and therefore a fix configured ULA would help me in assigning this ipv6 IP of the pihole to my end client's via SLAAC from the UDM ...
I think the script should manually assign all bridged vlan interfaces on the UDM a own specified ipv6 ULA address then enable SLAAC Service to provide additional ULA adsresses to end clients in the VLAN's
Does anyone have a comment on this ?
the counterpart on the USG can be found under following topic: https://community.ui.com/questions/IPv6-Have-USG-assign-Unique-Local-Address-through-Router-Advertisement/e516521b-9f40-4a00-a0b6-60311790276d#comment/5cb60cbc-7bb4-46cd-a284-1d52db8b1173