Some time ago I described how to use 6to4 to provide a stable IPv6 connection for a host having a fixed, public IPv4 address, a really simple procedure (at least in its basic configuration) which allows us to access a new Internet with abundance of addresses where everyone can offer their own services.
However, the procedure is something of an entelechy since a host which has a fixed, public IPv4 address is already capable of offering services to the Internet. However, what about our home computers sitting behind a NAT device (thus with private addresses), or those we carry with ourselves (thus with dynamic addresses)?
In this article I describe how to use tinc to extend IPv6 connectivity from a host with its own (native or 6to4) IPv6 network into home and mobile devices, so that they have publicly accessible addresses in this network regardless of their location.
Network topology
Tinc is free/libre software used for building virtual private networks (VPN) which stands out from other VPN products in that it greatly eases setting up networks of a distributed topology with no need for central nodes doing routing or authentication. Each tinc node defines its own subnet and the system takes care of propagating the needed routes and keys for communication to take place in a direct (if possible) and secure way between nodes which don't explicitly know each other.
We'll assume that we have a so-called gateway node with a fixed, public IPv4
address and its own IPv6 network. To continue the example in the previous article, these will be 1.2.3.4
and its associated 6to4 network
2002:0102:0304::/48
(but it may be any other public IPv6 network). We'll also
assume that the rest of nodes have no connection to the IPv6 Internet nor
fixed, public IPv4 addresses.
We'll set tinc up so that each node in the network gives access to its own
subnet 2002:0102:0304:N::/64
(with N = 0 for the gateway). Nodes shall
connect to the gateway, which shall thus connect all subnets together and
provide access to the IPv6 Internet to those nodes which choose the tinc
network as their default route.
IPv4 and IPv6 networks.
Please note how each node shall have the same address both in the tinc and local networks, something we achieve by using two different network masks. In this sense, the manual is a mix of this example and this article.
Gateway configuration
For setting the gateway with Debian or similar, in the first place we'll
install package tinc
. Next we'll create the directory /etc/tinc/inet6
which
will hold the configuration files for our network, which we shall call inet6
here (tinc can manage several ones).
Now we'll create tinc's server configuration file for this node,
/etc/tinc/inet6/tinc.conf
:
AddressFamily = ipv4 BindToAddress = gateway.example.net 655 Name = gateway
The only option actually necessary is Name
, here setting this node's unique
name in the tinc network to gateway
. The AddressFamily
option restricts tinc
to always using IPv4 connections, something reasonable for providing IPv6 on
top of it. The options BindToAddress
fixes the address and port (TCP and
UDP, default 655) where tinc will listen, and it can be useful if the
gateway has multiple IPv4 addresses or if we're going to manage more than one
network with tinc, since each one needs a different port.
For any two tinc nodes to connect in a secure way both must know beforehand their respective names and public keys, as well as the subnets they provide access to. If a node wants to connect to another, it will need to know the address and port where the other tinc server listens. Each node defines all these parameters in a host configuration file which must be copied to the nodes it wants to connect to.
Next we'll create the gateway's host configuration file,
/etc/tinc/inet6/hosts/gateway
. We'll need to create the hosts
subdirectory
first taking care that we use for the file the same name given above in Name
.
Address = gateway.example.net 655 Subnet = 2002:0102:0304:0000:0:0:0:0/64 Subnet = 0:0:0:0:0:0:0:0/0
Of course the values in Address
are those given far above. The
announced subnet is 2002:0102:0304:0000::/64
(tinc doesn't support compact
notation) as shown in the diagram, as well as ::/0
, i.e. the whole IPv6
Internet.
We'll complete this file with the node's public key, which we'll generate by
running tincd -n inet6 -K
and accepting the default answers. This will add a
BEGIN/END RSA PUBLIC KEY
block to the end of file.
Tinc doesn't automatically add any address or route to the host, instead it
leaves the task to some network configuration scripts. In our case, assuming
that the gateway already has set its IPv6 interfaces and routes up, we'll
create the following scripts /etc/tinc/inet6/tinc-up
#!/bin/sh ip -6 link set "$INTERFACE" up mtu 1400 ip -6 addr add 2002:0102:0304:0000::1/48 dev "$INTERFACE"
and /etc/tinc/inet6/tinc-down
#!/bin/sh ip -6 addr del 2002:0102:0304:0000::1/48 dev "$INTERFACE" ip -6 link set "$INTERFACE" down
that shall run when starting and stopping tinc's inet6
network (don't forget
to make them executable with chmod a+rx SCRIPT
). Please note how the maximum
IPv6 datagram size (MTU) is limited to 1400 bytes: we take into account the
overhead added by 6to4 (in our case) or tinc to reduce the chance of coming
across problems during the discovery process of the MTU between two IPv6
hosts. The safest (and slightly less efficient) value is 1280. Please read
this article for further information.
Finally we'll add inet6
to file /etc/tinc/nets.boot
, which lists networks automatically started by tinc's init script, and we'll start it by running
invoke-rc.d tinc restart
. This completes the configuration of tinc itself.
If the gateway runs a firewall we'll still need some final touches. Since it will receive connections from other tinc nodes it's important that we open the TCP and UDP ports given above with rules that equal the following commands:
# iptables -A INPUT -p udp -m udp --dport 655 -j ACCEPT # iptables -A INPUT -p tcp -m tcp --dport 655 -j ACCEPT
The gateway shall also route IPv6 traffic, so we'll need to allow IPv6 forwarding in the firewall with the rule equivalent to:
# ip6tables -P FORWARD ACCEPT
We'll also need to enable IPv6 forwarding in the kernel via sysctl
, for
instance:
# cat > /etc/sysctl.d/local-forwarding.conf << EOF net.ipv6.conf.all.forwarding=1 EOF # sysctl -p /etc/sysctl.d/local-forwarding.conf
Other nodes' setup
As we saw before tinc is a distributed system, thus there are no servers and clients, only nodes which connect between themselves. In our case nodes without fixed, public IPv4 addresses will initiate connections towards the gateway node. But as we'll see configurations are nearly the same.
We'll install tinc
and create directory /etc/tinc/inet6
. We'll write the
following server configuration file /etc/tinc/inet6/tinc.conf
:
AddressFamily = ipv4 BindToAddress = * 655 Name = my_pc ConnectTo = gateway
Since this node shall initiate connections to others (and not the other way
round) the address where tinc shall listen doesn't matter (thus the *
). Nonetheless, since
each tinc network needs a different port it's still OK to make it explicit,
and in our case we'll be using it later. Once again the name (my_pc
) of this
node is most important here, as well as appearances of ConnectTo
options which
indicate to which nodes (by their name) connections shall be initiated.
We'll create the host configuration file /etc/tinc/inet6/hosts/my_pc
with the
subnets that this node shall provide access to
Subnet = 2002:0102:0304:0004:0:0:0:0/64
and we'll invoke tincd -n inet6 -K
to create node keys. By the way, if we
only want to give access to this host we can use a /128
mask, e.g.
2002:0102:0304:0004:0:0:0:1/128
.
Since we'll connect to the gateway node, we'll need to copy into its hosts
directory this node's host file, as well as copy into this node's hosts
directory the gateway's host file. Sharing host files can be the most
obnoxious step in setting up a tinc network, and if we have lots of nodes with
a complex connection topology the simplest way may be to provide all host
files in the network together (e.g. by using some distributed version control
system), which may also help in deciding unique new names and subnets.
Network configuration scripts will only differ from the gateway's (besides the
assigned address, of course) in that they'll add a default route to the IPv6
Internet via the tinc network. Thus /etc/tinc/inet6/tinc-up
:
#!/bin/sh ip -6 link set "$INTERFACE" up mtu 1400 ip -6 addr add 2002:0102:0304:0004::1/48 dev "$INTERFACE" ip -6 route add default dev "$INTERFACE"
and /etc/tinc/inet6/tinc-down
:
#!/bin/sh ip -6 route del default dev "$INTERFACE" ip -6 addr del 2002:0102:0304:0004::1/48 dev "$INTERFACE" ip -6 link set "$INTERFACE" down
Please note that there's no default gateway address given, only the interface
where the packets shall be sent to. On packet reception, tinc takes care of
locating the node that provides access to the proper destination subnet (and
remember that the gateway node announces ::/0
).
After enabling script execution with chmod
, we'll add inet6
to
/etc/tinc/nets.boot
and restart tinc with invoke-rc.d tinc restart
. Past a
few seconds we shall be able to ping the gateway:
$ ping6 2002:0102:0304:0000::1 PING 2002:0102:0304:0000::1(2002:102:304::1) 56 data bytes 64 bytes from 2002:102:304::1: icmp_seq=1 ttl=64 time=141 ms 64 bytes from 2002:102:304::1: icmp_seq=2 ttl=64 time=141 ms 64 bytes from 2002:102:304::1: icmp_seq=3 ttl=64 time=142 ms 64 bytes from 2002:102:304::1: icmp_seq=4 ttl=64 time=142 ms --- 2002:102:304::1 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3004ms rtt min/avg/max/mdev = 141.617/142.174/142.737/0.505 ms
If there is any problem have a look at /var/log/daemon.log
. If it works you
can test your connectivity with the rest of the IPv6 Internet visiting
ipv6-test.com or test-ipv6.com (:D
), or SubnetOnline.com where you can provide
your address and get it pinged. Remember that your computer will be publicly accessible through IPv6, so you'd better prepare a good firewall
configuration. And regarding firewalls, if you're going to provide access to
more computers on your local IPv6 network, remember to enable IPv6 forwarding
in your firewall and kernel as described before.
Direct connection on the local network
If you have a look at the network diagram you'll see that my_laptop
is in the
same local network as my_pc
. However, since they aren't accessible from the
Internet whenever they want to communicate on the IPv6 network, traffic must
go through gateway
, which isn't too efficient. Tinc 1.0.17 or above allows
looking for known nodes in the local network, avoiding unneeded hops while
keeping traffic security. This can be interesting in local WiFi networks with
no encryption.
To enable this lookup we'll include the option LocalDiscovery = yes
into the
node's tinc.conf
. This will make tinc broadcast on the local network UDP
packets addressed to the port specified in that file (that's why fixing the
value of the port in there is convenient), which means that this mechanism will
only work if all nodes in the local network use the same port.
Of course we'll need that contacted nodes keep this port open in the firewall and that nodes to connect to have the others' host files. Once again, the simplest way is for all nodes to have the host files of all nodes in the network.
Pingback