Your ISP gave you a natively routed /64 prefix, and you want to use the 6bed4router as a tunnel. The clients of that tunnel might be a mobile device or a home network.
Following are instructions to setup for this. We use the Linux command line because it is the most general. Your distribution may have clever ways of automating the configuration, perhaps even graphically. If you desire such instructions, please use a forum for your distribution.
We assume that your hosting provider gave you a Linux virtual machine with
root privileges. We assume that its primary network interface is named
eth0
with MAC address a8:bb:cc:00:11:22
. The IPv6 prefix awarded to
you will be assumed to be 2001:db8:9:10::/64
.
When your eth0
interface goes up, it automatically configures a link-local
address, meant for communication on the link (to the router of your hosting
provider). It will start fall under fe80::/10
and in this case should be
fe80::aabb:ccff:fe00:1122
. You can see that it contains a mangled form
of the MAC address of the interface.
Without explicitly adding an IPv6 address with a global scope, you already have this link-scoped address configured:
shell# ip -6 addr show dev eth0
0: eth0: <...> ...
inet6 fe80::aabb:ccff:fe00:1122/64 scope link
The upstream router could use ping6
to reach you at this address, and so
could you from this virtual machine. However, this being a link-scoped
address, nobody else could reach the IPv6 address.
First, the IPv6 default route is set to the address of the upstream router of the hosting provider, something like
shell$ ip -6 route add default via fe80::aabb:ccff:fedd:eeff dev eth0
shell$ ip -6 route show
default via fe80::aabb:ccff:fedd:eeff dev eth0 metric 1024 mtu 1500 ...
Most people configure their hosted machine like they would do with a machine on their home network. So, we shall add a few IPv6 addresses:
shell# ip -6 addr add 2001:db8:9:10::11/64 dev eth0
shell# ip -6 addr add 2001:db8:9:10::30/64 dev eth0
shell# ip -6 addr show dev eth0
0: eth0: <...> ...
inet6 2001:db8:9:10::30/64 scope global
inet6 2001:db8:9:10::11/64 scope global
inet6 fe80::aabb:ccff:fe00:1122/64 scope link
Note how the new addresses are setup with global scope. Indeed, anyone on
the Internet should now be able to ping6
you on that address. You are
online!
You can now configure programs like a webserver to listen to one or both
of these addresses. Inasfar as they are already listening to all addresses
they will immediately pickup on the newly added addresses. This applies
to ping6
but also to most installations of sshd
:
shell# netstat -ptnl6
9378/sshd 0 0 :::22 ...
It would be confusing to parse due to the colon between the address and port,
but :::22
indicates address ::
and port 22. In other words, sshd
with
pid 9378 listens to all addresses and will respond to the newly added IPv6
addresses.
When you are using 6bed4router
, chances are it's the first time you start
to think of your virtual host as a router. This is indeed the added value of
the vast array of addresses that you get with IPv6.
The example setup sketched before is common, but from a router's viewpoint it is flawed. Just look at this:
shell# ip -6 route show
2001:db8:9:10::/64 dev eth0 ...
fe80::/64 dev eth0 ...
default via fe80::aabb:ccff:fedd:eeff dev eth0 ...
Note how silly this is — you are directing your assigned native /64
prefix back to the router of your hosting provider. This is the result of
your use of a /64
prefix when you setup your two addresses on eth0
.
When your eth0
is attached to a LAN, this setup makes sense; the LAN
has numerous hosts under this /64 prefix, and so your networking stack should
consider anything under the prefix local to the eth0
link. The prefix
is attached to the LAN by a router that connects the LAN to the rest of the
IPv6 internet.
In your hosting setup, this is usually not how things are done. Here, the
eth0
interface is a direct link to an upstream router whose sole purpose
it is to relay your prefix to your eth0
interface. There are no other
hosts residing under the same /64 prefix. Still, as long as you enumerate
all actual IPv6 addresses in use on the eth0
interface, this is going
to work.
But now you want to add 6bed4router
, which means you have entered the
realm of routing yourself. Now what do you do? If you let it, the
6bed4router
creates a 6bed4
network interface with the same /64 prefix,
and your system might get confused.
The solution is simple. You can use eth0
for inbound traffic for your
/64 prefix, even when it does not have local addresses assigned. All you
need to ensure is that it forwards frames that it cannot handle on the
interface itself.
shell# sysctl -w net.ipv6.conf.eth0.ip_forwarding=1
shell# sysctl net.ipv6.conf.eth0.ip_forwarding
net.ipv6.conf.eth0.ip_forwarding = 1
and, if you intend to support multicast as well, perhaps even
shell# sysctl -w net.ipv6.conf.eth0.ip_mc_forwarding=1
shell# sysctl net.ipv6.conf.eth0.ip_mc_forwarding
net.ipv6.conf.eth0.ip_mc_forwarding = 1
You could now remove the IPv6 addresses to pass all the traffic, for insance to the 6bed4 interface, which is not desirable if you intend to run servers under your /64 as well. But this is how it would be done:
shell# ip -6 addr del 2001:db8:9:10::11/64 dev eth0
shell# ip -6 addr del 2001:db8:9:10::30/64 dev eth0
shell# ip -6 addr show dev eth0
0: eth0: <...> ...
inet6 fe80::aabb:ccff:fe00:1122/64 scope link
shell# ip -6 route show
fe80::/64 dev eth0 ...
The trick is to redefine the addresses with a longer prefix than /64. With
the /64 assigned to the 6bed4
interface, the longer prefix is a better match
for some packets, which are then not forwarded over 6bed4
.
There is explicit support in the 6bed4 design for this approach, and that is
by being utterly uninterested in certain addresses. The one-but-last word
in the address structure of 6bed4 represents an UDP port, and since port 0
is never permitted, there is a whole range of IPv6 addresses that can be
bypassed for other uses — such as running a server locally. There just
have to take a format xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:0000:xxxx
to be clearly
distinguishable from 6bed4 addresses. In our case, we can use the addresses
ending in ::11
and ::30
without confusing with 6bed4. A decent prefix
to use would be either /128 for an exact match with the address or, if we
wish to offload the routing tables, a /112 prefix that is certain to hold
at least the port number.
The next question is where the addresses should go. For /128 prefixes, the
eth0
interface would be quite good, so it can match the addresses locally
and refrain from further routing. This is also pleasant if there is a
preference to route IPv4 and IPv6 over the same interfaces (though that is
a subject desire). Aside from the already-coded removal of the old
addresses, the procedure would be:
shell# ip -6 addr add 2001:db8:9:10::11/128 dev eth0
shell# ip -6 addr add 2001:db8:9:10::30/128 dev eth0
shell# ip -6 addr show dev eth0
0: eth0: <...> ...
inet6 2001:db8:9:10::30/128 scope global
inet6 2001:db8:9:10::11/128 scope global
inet6 fe80::aabb:ccff:fe00:1122/128 scope link
Where the option of one or more /112 prefixes is preferred, we might instead
do that on eth0
, or choose to not send packets for the smaller network
ranges back upstream by creating a virtual network interface. It may be
helpful to create a "dummy" network interface, which holds your
local IPv6 addresses and has them routed through the loopback interface,
shell# ip -6 link add dumbo0 type dummy
shell# ip -6 link set dumbo0 up
shell# ip -6 link show dev dumbo0
1: dumbo0: <...> ...
link/ether 11:22:33:44:55:66 brd ff:ff:ff:ff:ff:ff
Variations on this are many...
- You could create virtuel ethernet devices to link directly to others, possibly in another networking name space or container, and so on.
- You could setup a tunnel with a tool like socat to relay traffic to another network, where you unleash the address range via Router Advertisements and DHCPv6.
- You could setup a translation to logical addresses using the Host Identity Protocol.
- You could export an address range over a DNS tunnel.
- You could run L2TP to connect networks based on the /112 IPv6 prefix, possibly as a backend to PPPoE clients. Add IPsec and you have a nice, standards-compliant VPN.
And you could mix in any way you like, by assigning different /112 prefixes to each interface. Given the port-0 assumption, you have 4294967296 of those ranges for a total of 281474976710656 hosts, we hope that you will agree that 6bed4 leaves you some room to play.
Again, we should ensure forwarding:
shell# sysctl -w net.ipv6.conf.eth0.ip_forwarding=1
shell# sysctl net.ipv6.conf.eth0.ip_forwarding
net.ipv6.conf.eth0.ip_forwarding = 1
and possibly
shell# sysctl -w net.ipv6.conf.eth0.ip_mc_forwarding=1
shell# sysctl net.ipv6.conf.eth0.ip_mc_forwarding
net.ipv6.conf.eth0.ip_mc_forwarding = 1
Now we can proceed by adding the IPv6 addresses again, but this time with a
/112 prefix and to the dumbo0
device:
shell# ip -6 addr add 2001:db8:9:10::11/112 dev dumbo0
shell# ip -6 addr add 2001:db8:9:10::30/112 dev dumbo0
shell# ip -6 addr show dev dumbo0
0: dumbo0: <...> ...
inet6 fe80::aabb:ccff:fe00:1122/64 scope link
inet6 2001:db8:9:10::30/112 scope global
inet6 2001:db8:9:10::11/112 scope global
Do not forget to remove the /64 prefixes from eth0
, as coded above.
You can now run 6bed4router
without further problems.
Now that you are running a router, you may be assuming that your uplink does, too. This may not always be true. For instance:
- You may be running the
6bed4router
on an ethernet LAN - Your upstream may not be configured with your link-local address for your IPv6 range
In these cases, you may be subjected to Neighbor Solicitation requests for the various IPv6 addresses that make up 6bed4. This is a pitty, as the variety of addresses may be a bit much for the upstream. So if you can, tell your upstream to do something like
shell$ ip -6 route add 2001:db9:9:10::/64 via fe80::aa:bb:cc:ff:fe::dd:ee:ff/64 dev eth0
If this is not an option, for instance because the router is managed by another party that does not respond to such inquiries, you may have to Proxy Neighbor Discovery instead. Once it runs, your connections should magically come alive.