IPv4 and IPv6 (dual stack) via ddclient instead of IPv4 via router

Hi, everyone,

I need your swarm knowledge.

I run a web server behind a Fritzbox on a dual stack connection (dynamic IPv4 address and dynamic IPv6 prefix).

As I could see from the documentation, you cannot, as usual, update IPv4 from the Fritzbox and IPv6 from the web server, which is set up as a client on the Fritzbox. An IPv6 query deletes IPv4 from the DDNS or vice versa.

Now my first solution is to delete the IPv4 update from the Fritbox and to do this for IPv4 and IPv6 via the ddclient 3.9.1.

The documentation said: If I send my IPv4 to the DDNS via the web at update6.dedyn.io, my IPv6 is also stored as a DNS entry.

Now I have working /etc/ddclint.conf for me:

## Configuration file for ddclient generated by debconf
##
## deSEC IPv4 & IPv6 (https://desec.io)
##
syslog=yes
##
protocol=dyndns2
use=web
web=https://checkipv4.dedyn.io/
ssl=yes
server=update6.dedyn.io
login=[domain]
password='[token]'
[domain]

Question for connoisseurs and experts:
Can you leave it like that or is there a more elegant solution?
If so, what might this look like?

Best regards

Hi fraenkiman,

welcome do deSEC! :slight_smile:

A feature to not delete a v4 or v6 IP address when no address was transmitted has been requested before and could be useful in your case. Sadly, no work has been done on the implementation yet.

An alternative could be do just register two domain names?

Best,
Nils

Hi fraenkiman,

Yes, the issue is probably that the provider will supply an IPv6 address for the FRITZ!Box and a separate IPv6 prefix, a part of which gets passed to the clients on the LAN. So the DDNS client on the FRITZ!Box can only update using the public IPv6 address of the FB but not that of the LAN client.

For example for a Telekom VDSL connection the FRITZ!Box gets:

  • a dynamic public /64 prefix, which combined with the EUI64 interface id of the WAN interface on the FB forms a public /128 IPv6 address.

  • in addition a dynamic public /56 prefix is communicated to the FRITZ!Box. A /64 subnet of that is then communicated to the hosts on the LAN. Packets from the Internet addressed to this prefix are routed to the public IPv6 address of the FRITZ!Box.

Other providers probably do something similar.

Issues:
When the dynamic /56 prefix changes the clients usually use SLAAC to generate new IPv6 addresses.

a) You already noticed that you need to keep DNS records updated in this situation. :slight_smile:

b) You may also need to adjust local firewall and service configurations on the host.

c) And most importantly for FRITZ!OS to pass incoming packets to your host, it needs to have port forwarding configured. However that configuration hinges on the interface id of the host. Depending on how SLAAC is configured for the host, SOII interface ids might be generated which change with every change of the prefix! That would require manual reconfiguration on the FRITZ!Box! The solution is to use EUI64 interface ids.

Note: EUI64 interface ids are based on the MAC address of the interface in a 1:1 mapping. Thus some information about the vendor of the interface is leaked to the outside world. If that is a concern for you then you can probably configure a self generated random MAC-Address for the interface. But this may depend on the capabilities of the OS you are using on the host.

Conclusion:
You need a way to detect changes of the prefix on the host. Such a change would then trigger a number of actions such as updating DNS, updating local firewall and service configurations, etc.

This can be done. I have an experimental, work-in-progress ksh script running on an OpenBSD 7.0 VM that seems to be doing what I want. I run it via cron(8) every minute. It detects the changes, keeps track of the old and new prefix and can trigger actions to be done when a change occurs. It also logs relevant data and keeps the last known prefix in a state file. Let me know if that would be of interest. I’d need to clean it up and anonymize it some before I’d consider sharing. It would probably need to be modified for other OSes.

HTH
fiwswe

Hallo @fiwswe,

You guessed well. My ISP is Deutsche Telekom. The parts from a, b and c described by you apply and have already been implemented by me. The host is a Raspberry Pi 4b with a 32-bit Debian distribution (Raspberry OS / Bullseye).

Except that I had to stall eht0’s privacy extension. So far I have not been able to find the possibility of setting a self-generated random MAC address for eht0 for the Raspberry OS. Derivatives from Ubuntu are not applicable as far as I know. If a solution were revealed to me, this construction site would also be eliminated. However, that shouldn’t be the topic of this thread.

Your experimental solution is interesting and how practical it is.
Is it possible to port ksh to classic Debian-sh? I’m not familiar with ksh. Or does it make more sense to reload the shell extension?

An adjustment of the firewall via the script is not necessary for the time being. I use the firewall of the Fritzbox. In Debian Stretch I used to rely on itpables. Unfortunately, I haven’t managed to switch to nftables to this day.

@nils
The solution with two domains for one host is not practical for me.
Here I already fail to issue the SSL certificate (letsencrypt/cerbot) for two domains. There may be a way to merge both domains back into one. Unfortunately I do not know this.
Unfortunately, this is also cumbersome for outsiders who access the host.

The outsider must then know which IP protocol is currently being used to communicate. Especially with public hotspots or mobile communications, this is not always clear to everyone.
Therefore, it would be important for me to be able to update IPv4 and IPv6 for a domain via DDNS.

I apologize for my bad english
I am pleased to read from you.
Best regards

Not sure what you mean by „reload the shell extension“ but…

The issues are probably not so much with ksh vs. a bash sh. The networking parts of the code might need to be different. I have not touched a Debian Linux in a long time so I don’t know the details. For example the script parses the output of the route(8) command. If that is different on Debian then changes need to be made. Here is one of the central routines:

#	Get the current IPv6 address prefix for a given interface.
#	Parameters:
#		interface	The interface for which to get the public IPv6 address prefix
function getIPv6Prefix
{
	local interface="$1"
	
	#	route -n show -inet6 | grep $interface = List all IPv6 networks.
	#	grep '::/' = List only network addresses.
	#	grep -vE '^(fd|fe80)' = Remove ULA and link-local networks.
	#	awk -F '::/' '{print substr($1,1,19)}' = Shorten to the prefix.
	#	sort -u = Remove duplicates.
	#	tail -n 1 = Newer networks are listed at the bottom.
	#				Last entry therefore is the current IPv6 prefix.
	local publicIPv6Net=`route -n show -inet6 | grep -E '.+::/[1-9].+ '"$interface" \
		| grep -vE '^(fd|fe80)' \
		| awk -F '::/' '{print substr($1,1,19)}' \
		| sort -u | tail -n 1`

	echo "$publicIPv6Net"
}

(Attribution: This code was inspired by prior work by Thomas Bohl, see: https://aloof.de/f/IPv6Aliases-en.sh, https://aloof.de/f/IPv6Aliases-de.sh)

I’ll see if I can clean up the code in the next few days…

You fail to issue certificates? Why? I’ve got that working just fine currently for one certificate. But I see no reason it shouldn’t work for more than one. (Again OpenBSD 7.0 and the included acme-client.) If port 80 is reachable using the hostname (via IPv4 or IPv6) and your web server is set up for the HTTP-01 challenge there should be no issues.

You could always disable the DDNS client on the FRITZ!Box and update both IPv4 and IPv6 address from your RPi. You’ll see slightly higher delays for IPv4 when the IPs change because you need to poll instead of getting the FB to trigger on the change. OTOH Telekom tends to change IPs very seldom (weeks to months) nowadays unless your FB forces a disconnect every night. (I’ve been keeping an eye on this for several months now on my line and another I can monitor.) So a small delay (≤60s) every few months might be ok?

HTH
fiwswe

BTW: If you want to hide your IPs you need to obscure the hostnames as well. They contain the IPs in hex :wink:

See pXXXXXXXX.dip0-t-interconnect.de and pXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.dip0-t-interconnect.de.

fiwswe

FWIW: openbsd-networking/ipv6PrefixCheck at main · fiwswe/openbsd-networking · GitHub

Not pretty bit it works for me…

HTH
fiwswe

1 Like

This also works and leaves the IPv4 (A records) unchanged:

newIPv6addr='2001:db8::dead:beef'
deDynSubdomain='example'
deDynHostname="${deDynSubdomain}.dedyn.io"
deDynToken='dedyn-api-auth-token'

curl -X PATCH \
	--url "https://desec.io/api/v1/domains/${deDynHostname}/rrsets/@/AAAA/" \
	--silent \
	--header "Authorization: Token ${deDynToken}" \
	--header 'Content-Type: application/json' \
	--data '{"records": ["'"${newIPv6addr}"'"]}'
# Note: The changed `AAAA` records are sent to stdout as a JSON string. Ignore using >/dev/null or send to a log if you want.

So you could use this on your LAN host while FRITZ!OS takes care of updating the public IPv4 address. This would avoid the need for separate domain names.

HTH
fiwswe