Adding a whole IPv6 /64 block to an network interface on debian
Solution 1
I have needed something similar in the past. I found that there are three steps needed to get this working:
- You need to route a prefix to the host
- You need a local route on the host
- Applications need to set the
IP_FREEBIND
orIP_TRANSPARENT
option on sockets
The proper way to get a prefix routed to the host involves contacting your provider, if they do not already provide you one. They may have a DHCPv6 server, which can delegate a prefix to you, if you just send the right DHCPv6 request to it.
If a real routed prefix is for some reason impossible for you to get, but you have access to use as many addresses as you want from a link prefix available on one of your network interfaces, you can turn part of that into a routed prefix by having a daemon respond to neighbor discovery requests for every IPv6 address in that range.
Using such a daemon is not recommended other than as a last resort, since it will needlessly consume memory from all your neighbors. There are a few implementations of such a daemon, one that looks promissing is ndppd. (I have no specific experience with it, since I only learned about it after I had written my own with my link prefix hardcoded.)
It looks like you already got the local route working. As you noticed, it has to be assigned to the lo
interface in order to work.
Finally the applications using addresses from this range need an IP option in order to be able to bind to addresses, which are not explicitly assigned to a specific network interface on the host. Here is a code fragment, that can be used:
const int one = 1;
setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one));
Solution 2
It's 2019 year now. One word: ip_nonlocal_bind (since 4.3 kernel as i may know).
Use ndppd + sysctl net.ipv6.ip_nonlocal_bind = 1, last one allows you to bind to any IPv6 address(no IP_FREEBIND needed in this case).
Guess you did so:
ip add add local 2001::41d0:2:ad64::/64 dev lo
ip route add local 2001::41d0:2:ad64::/64 dev eth0
sysctl net.ipv6.ip_nonlocal_bind = 1
ndppd.conf will look like:
route-ttl 30000
proxy eth0 {
router no
timeout 500
ttl 30000
rule 2001::41d0:2:ad64::/64{
static
}
}
run ndppd and now you can bind to any address(of added block) and use it as it added itself.
Related videos on Youtube
Hikaru-Shindo
There's not really much to tell... I was a PHP developer for years and switched to Spring Boot / Kotlin a while ago. Heavy focus on backend development and DevOps. I like being stubborn sometimes ;)
Updated on September 18, 2022Comments
-
Hikaru-Shindo almost 2 years
I tried adding a whole IPv6 (/64) block to an interface using
ip route add local 2001:41d0:2:ad64::/64 dev lo
like described here on my Debian server, but I seem to be missing something.
If I ping for example
2001:41d0:2:ad64::fe
locally everything works just fine, but if I try from a remote machine it does not work. I then tried adding the route on eth0:ip route add local 2001::41d0:2:ad64::/64 dev eth0
Now I couldn't even ping any example address locally!
I'm a bit lost since I seem to be missing something but I can't find the answer here.
For short: I want
2001:41d0:2:ad64::/64
to be bound to eth0 so that every IP this block is containing will be reachable from the internet on my machine.I hope someone out there can point me the right way. Thanks in advance.
The guide provided by the ISP does require me to add each IPv6 to the interface explictly. I want it to be implict.
Working configuration with explict ip address binding
/etc/network/interfaces:
auto eth0 iface eth0 inet static address my.ip.v4 netmask 255.255.255.0 network my.network.address.ip broadcast my.broadcast.address.ip gateway my.gateway.ip iface eth0 inet6 static address 2001:41d0:2:ad64::fe netmask 64 gateway 2001:41d0:2:adff:ff:ff:ff:ff up ip addr add 2001:41d0:2:ad64::1/64 dev eth0 down ip addr del 2001:41d0:2:ad64::1/64 dev eth0 up ip addr add 2001:41d0:2:ad64::2/64 dev eth0 down ip addr del 2001:41d0:2:ad64::2/64 dev eth0 up ip addr add 2001:41d0:2:ad64::3/64 dev eth0 down ip addr del 2001:41d0:2:ad64::3/64 dev eth0 up ip addr add 2001:41d0:2:ad64::4/64 dev eth0 down ip addr del 2001:41d0:2:ad64::4/64 dev eth0 up ip addr add 2001:41d0:2:ad64::5/64 dev eth0 down ip addr del 2001:41d0:2:ad64::5/64 dev eth0 up ip addr add 2001:41d0:2:ad64::6/64 dev eth0 down ip addr del 2001:41d0:2:ad64::6/64 dev eth0 up ip addr add 2001:41d0:2:ad64::7/64 dev eth0 down ip addr del 2001:41d0:2:ad64::7/64 dev eth0 up ip addr add 2001:41d0:2:ad64::8/64 dev eth0 down ip addr del 2001:41d0:2:ad64::8/64 dev eth0 up ip addr add 2001:41d0:2:ad64::9/64 dev eth0 down ip addr del 2001:41d0:2:ad64::9/64 dev eth0 up ip addr add 2001:41d0:2:ad64::a/64 dev eth0 down ip addr del 2001:41d0:2:ad64::a/64 dev eth0
Solution try #1
I tried reenableing the local route as @kasperd suggested.
Content of my /etc/network/interfaces
auto lo iface lo inet loopback post-up ip route add local 2001:41d0:2:ad64::/64 dev lo pre-down ip route del local 2001:41d0:2:ad64::/64 dev lo auto eth0 iface eth0 inet static # <snip of ipv4 config> iface eth0 inet6 static address 2001:41d0:2:ad64::fe netmask 64 gateway 2001:41d0:2:adff:ff:ff:ff:ff
Local routing table:
# ip -6 route show table local local ::1 dev lo proto none metric 0 local 2001:41d0:2:ad64::fe dev lo proto none metric 0 local 2001:41d0:2:ad64::/64 dev lo metric 1024 local fe80::225:90ff:fe06:6bbe dev lo proto none metric 0 ff00::/8 dev eth0 metric 256
Output of
traceroute
(my local home PC):1 <1 ms <1 ms <1 ms fritz.box [xxx] 2 20 ms 21 ms 24 ms 2002:c058:6301::1 3 21 ms 22 ms 24 ms 10gigabitethernet6.switch2.fra1.he.net [2001:470 :0:150::1] 4 44 ms 31 ms 40 ms 100ge3-1.core1.ams1.he.net [2001:470:0:2d4::1] 5 * * * Zeitüberschreitung der Anforderung. 6 * * 35 ms ams-5-6k.nl.eu [2001:41d0::8d1] 7 37 ms 39 ms 36 ms rbx-g2-a9.fr.eu [2001:41d0::ab1] 8 37 ms 70 ms 36 ms chi-3-4m.il.us [2001:41d0::176] 9 Zielhost nicht erreichbar. Ablaufverfolgung beendet.
traceroute6
on server:traceroute to 2001:41d0:2:ad64::23 (2001:41d0:2:ad64::23), 30 hops max, 80 byte packets 1 2001:41d0:2:ad64::a (2001:41d0:2:ad64::a) 0.028 ms 0.009 ms 0.008 ms
ping6
on server:PING 2001:41d0:2:ad64::23(2001:41d0:2:ad64::23) 56 data bytes 64 bytes from 2001:41d0:2:ad64::23: icmp_seq=1 ttl=64 time=0.029 ms 64 bytes from 2001:41d0:2:ad64::23: icmp_seq=2 ttl=64 time=0.057 ms ^C --- 2001:41d0:2:ad64:23 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 999ms rtt min/avg/max/mdev = 0.029/0.043/0.057/0.014 ms
tcpdump
output (while pinging and tracerouting on remote server):tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
tracert
to the gateway:Routenverfolgung zu vss-3-6k.fr.eu [2001:41d0:2:adff:ff:ff:ff:ff] über maximal 3 0 Abschnitte: 1 <1 ms <1 ms <1 ms fritz.box [2002:5476:1b4c:0:c225:6ff:fe40:b2b0] 2 23 ms 22 ms 26 ms 2002:c058:6301::1 3 24 ms 40 ms 23 ms 10gigabitethernet6.switch2.fra1.he.net [2001:470 :0:150::1] 4 28 ms 37 ms 39 ms 100ge3-1.core1.ams1.he.net [2001:470:0:2d4::1] 5 * * * Zeitüberschreitung der Anforderung. 6 38 ms 33 ms * ams-5-6k.nl.eu [2001:41d0::8d1] 7 36 ms 39 ms 38 ms rbx-g2-a9.fr.eu [2001:41d0::ab1] 8 36 ms 35 ms 35 ms vss-3-6k.fr.eu [2001:41d0:2:adff:ff:ff:ff:ff] Ablaufverfolgung beendet.
ping
to the gateway:Ping wird ausgeführt für 2001:41d0:2:adff:ff:ff:ff:ff mit 32 Bytes Daten: Antwort von 2001:41d0:2:adff:ff:ff:ff:ff: Zeit=36ms Antwort von 2001:41d0:2:adff:ff:ff:ff:ff: Zeit=34ms Antwort von 2001:41d0:2:adff:ff:ff:ff:ff: Zeit=38ms Antwort von 2001:41d0:2:adff:ff:ff:ff:ff: Zeit=57ms Ping-Statistik für 2001:41d0:2:adff:ff:ff:ff:ff: Pakete: Gesendet = 4, Empfangen = 4, Verloren = 0 (0% Verlust), Ca. Zeitangaben in Millisek.: Minimum = 34ms, Maximum = 57ms, Mittelwert = 41ms
So it's still just working locally (server) but not from remote (my pc).
-
Zoredache about 10 yearsSo have you tried a traceroute from a remote machine? Where does the trace fail?
-
Spack about 10 yearsIf all the hosts are in the same network, you shouldn't had any route.
-
Michael Hampton about 10 yearsYour second
ip route
command has a typo in the IPv6 address. -
Hikaru-Shindo about 10 years@Spack I want eth0 to listen to a whole ipv6 /64 prefix (incoming traffic), @michael-hampton fixed, it was just while typing this question, @Zoredache It fails at the ISPs Gateway
2001:41d0:2:adff:ff:ff:ff:ff
after that it will just timeout. -
Nathan C about 10 yearsFrom research I've done in the past, this isn't possible. The reason it works locally is because your routing table knows where to route packets. If you added this prefix as a static route in your edge router then you'd see LAN clients able to connect.
-
TD_Nijboer almost 10 yearsi'm having the same question/problem. What is the working solution here? i noticed the mentioned ip address : 2001:41d0:2:ad64::/64 isn't that short 1 digit/hexgroup? shouldn't that be : 2001:41d0:2:ad64:xxxx::/64
-
Hikaru-Shindo almost 10 years@TD_Nijboer For short 2001:41d0:2:ad64:: is the same as 2001:41d0:0002:ad64:0000:0000:0000:0000
-
-
Hikaru-Shindo about 10 yearsI've got a static prefix routed to my server by the ISP (they do not provide DHCP. Neither fo IPv4 nor IPv6). I want all IPv6 in this /64 block to be reachable from the outside (most of my applications bind to :: which should be all available addresses if I'm not mistaken). Now I want all these IPs to be available on eth0 so if I try to connect to any IPv6 in that block any application listening to the specified port will be able to answer (for example each IP should respond to ping correctly).
-
kasperd about 10 yearsIf you bind to :: the IP_TRANSPARENT option is not needed. With a prefix routed to my server and the local route in place, I can bind to :: and receive connections made to arbitrary IPv6 addresses in that range. ping6 works as well. I am testing this on Ubuntu 12.04, but I would expect it to work on any recent kernel on other distributions as well. If it is not working for you, I suggest you take a look on the network traffic using
tcpdump -pni eth0 'host 2001:41d0:2:ad65::fe'
-
Hikaru-Shindo about 10 yearsIt's still not working. I provided a few more information on the configuration in my question, maybe this helps.
-
kasperd about 10 yearsYou say that you have a /64 routed to the server. But the examples in the hosting provider's guide only has a link prefix and no routed prefix. And the tcpdump and traceroute6 output looks like the addresses are not routed to the server. Have you managed to get a single IPv6 address working using the documentation from the provider?
-
Hikaru-Shindo about 10 yearsYes, this works perfectly fine.
-
kasperd about 10 yearsThen can you show us the configuration, which does work, as well as tell us what your routed IPv6 prefix is?
-
kasperd about 10 yearsIn your latest update, you mention two different /64 prefixes. Is 2001:41d0:2:ad64::/64 the link prefix and 2001:41d0:2:ad65::/64 the routed prefix? I cannot reach any of the IPv6 addresses you mentioned from those prefixes. Could you show the output of a traceroute from your server towards 2a01:4f8:d16:701:7a18:3d30:d395:28bb?
-
Hikaru-Shindo about 10 years
2001:41d0:2:ad64::/64
is the only prefix.2001:41d0:2:ad65::/64
was just writtern because I wanted to avoid attacks and for some privacy reasons and may or may not even exist. Where's the difference between a routed prefix and a link prefix anyway? (I'm not really good with network architecture ;) ) -
kasperd about 10 yearsThe question about the difference between a link prefix and a routed prefix would kind of deserve to be asked as a separate question and not just in a comment. What you are trying to do is best done with a routed prefix. But you should still keep the link prefix. A configuration with a routed prefix but no link prefix would be somewhat non-standard. I think you probably only have a link prefix and no routed prefix. You should ask your provider for a routed prefix. If they won't give you one you can use a daemon like previously mentioned to use part of the link prefix as if it was a routed pref
-
Chandra Nakka over 8 years@kasperd awesome solution. Millions of thanks to you. Because its very important for my project
-
kh h over 6 yearsI'm having a hard time getting this to work on Vultr.
-
kh h over 6 years@ChandraNakka which VPS provider are you using?
-
kasperd over 6 years@Arya I know nothing about that provider. I have used the setup described here on Hetzner, where it works just fine.
-
kh h over 6 years@kasperd How exactly would you route a prefix? That's the part I'm confused about.
-
kasperd over 6 years@Arya That's something the ISP is supposed to do for you. With many of the providers who don't do IPv6 properly you can work around the lack of routed prefix by setting up ndppd.
-
kh h over 6 years@kasperd how can I make the "ip route add local" command persistent that I don't have to execute it every time after a system reboot?
-
kasperd over 6 years@Arya When I needed such a thing I put the command in
/etc/rc.local
-
kh h over 6 yearsIs there any proxy server that uses IP_FREEBIND or IP_TRANSPARENT? I have tried Tinyproxy and Squid so far and they don't work with local route method. I'm trying to create a proxy server for all the IPs in the subnet.
-
kasperd over 6 years@Arya No idea. That question might be suitable for Software Recommendations.
-
kh h over 6 yearsunfortunately it looks like with this method of assigning IPs, the IPs can't be used for outgoing connections. They only work for incoming connections. For example, I can connect to the machine with any IP with the /64 block, but on the same machine if I do "wget --bind-address=2001:19f0:9002:073e:0000:0000:0000:3000 google.com" I get the message "failed: Cannot assign requested address." but I can connect to the same machine with "2001:19f0:9002:073e:0000:0000:0000:3000". If I add the same address in the interfaces file then wget will also work. Is there any workaround for this?
-
kasperd over 6 years@Arya It works for outgoing connections. All you need to do is to use
IP_FREEBIND
. If the application you want to use doesn't supportIP_FREEBIND
you will have to change a few lines of source code to make it work. -
kh h over 6 yearsI'm writing a simple C program to fetch a page with IP_FREEBIND, I will share my results
-
Chandra Nakka over 6 years@Arya sorry for long delay. I'm using Ubuntu 16.04 x64 server on DigitalOcean VPS services.
-
Pezhvak about 5 years@Hikaru-Shindo i'm facing the same issue, my app says 'failed: Cannot assign requested address.', did you found a way around?
-
robert about 4 yearswhen trying this ndppd responds with "(error) Unable to create socket." Anyone have any clue why?
-
Lamp about 3 yearswhat if application listens on [::]? i tried ndppd but it's not working...
-
Lamp about 3 yearsregardless of that i can't ping any random ipv6 either. But I see the echo request in tcpdump