Router and switch mode in tinc - the difference and how to use tinc on Android

06 Aug 2021 - tsp
Last update 06 Aug 2021
Reading time 10 mins

TL;DR: See table.

Mode OSI layer Virtual device type Connects
Switch 2 - Ethernet tap Arbitrary Ethernet segments
Router 3 - IP tun Different IP segments, list in local hosts file as Subnet

This is something that I’m asked often - what’s the difference between the switch and the router mode when using the tinc VPN client. The same goes about the question if these modes are interchangeable or compatible with each other (short answer: no).

The shortest answer would be that the difference is the same as between a router and a switch - at least when it comes to the idea of the two modes. In contrast to one being able to connect a router to a switch and vice versa - this is not possible when building the VPN mesh though.

In switch mode the VPN is built at layer 2 of the OSI model - at the Ethernet layer. One can pass arbitrary Ethernet packets and all nodes learn the MAC addresses used by the other nodes just like an ordinary network switch. In case they don’t know the route for a packet they just broadcast to all nodes - also like a typical switch - and slowly learn the MAC table that way. Switch mode is best when one really wants to bridge two Ethernet segments - they may even share the same IP address ranges - or wants to connect routers that learn their own IP address ranges for multiple attached networks in a dynamic fashion (for example using olsr or bgp). This is the mode that I personally usually use when interconnecting different complex sites that run themselves multiple network segments and get extended dynamically. Switch mode is realized via tap interfaces.

Router mode on the other hand is something like a layer 3 IP router embedded in the VPN client. All nodes announce the IP addresses that they’re responsible for and other nodes learn that way who is responsible for which net. The only drawback is that tinc nodes source the networks they announce from their hosts files Subnet declarations. This means it’s not easily possible to extend these routing tables dynamically via a protocol such as OLSR or BGP like it’s for the routing functionality when using full blown router implementations or hardware routers. At least one doesn’t have to change the host files on all nodes anyways but then there is the problem that one still has to configure routes on the host level for the virtual network interface anyways. Router mode is realized via tun interfaces.

Since switch mode is usually more flexible when building VPNs this is what I’m personally using most of the time (running a standard router configuration on the host machine and usually either olsrd or bgpd to announce routes)- unfortunately there are some clients like the Android implementation that use Androids VPN interface that only support tun interfaces so sometimes one has to use router mode.

How to use switch mode

I’ve already described this in another blog post including configuration of olsrd to learn new routes. This is the mode of operation that I personally prefer, especially when bridging whole network segments and not only backhauling single computers into some network.

How to use router mode

The basic ideas are similar to using switch mode - I’ll only outline the differences here. The main difference are some minor changes in tinc.conf - basically just specify the router mode and supply a tun interface instead of a tap one:

Name = anyexamplenodenamea
Mode = router
DecrementTTL = no
Device = /dev/tun1
DeviceType = tun
Forwarding = internal

# Followed by some ConnectTo =  statements if possible

The tinc-up and tinc-down scripts have to be modified too to create tun instead of tap devices. Since one configures the routes statically one can also add the static network configuration inside the tinc-up and tinc-down scripts:


# tinc-up
# First create the interface

ifconfig tun1 create
ifconfig tun1 inet

# Then add static routes

route add -net
route add -net
route add -net
route add -net

# tinc-down
# Remove static routes

route del -net
route del -net
route del -net
route del -net

# Then destroy interface

ifconfig tun1 destroy

After that the procedure is the same for host key creation:

tincd -n NETNAME -K

The next modification is that one has to add a Subnet declaration for each subnet that is reachable via this node to the hostfile (for example hosts/anyexamplenodenamea):

Address =
Subnet =
Subnet =
Subnet =
Compression = 9
Port = 656



In this case Address still is the publicly reachable external address that the host is reachable by. If a host uses a dynamic IP one cannot supply an Address. The Subnet declarations specify which subnets the node should announce - they are only read by the node itself, not by the nodes that the hosts file is distributed to.

The same has to be done for all other nodes. This basically is the main difference in configuration to layer 2 mode.

Configuration on Android

A word of caution: Many mobile network operators run carrier grade NAT for their devices and assign private IP ranges from the RFC1918 space to the devices, there might be collisions with own VPN meshes in case one uses these ranges too. So in case nothing appears to work check the IP address of your device on the mobile network side.

Unfortunately Android currently only supports tun devices in VPN mode. A nice app that wraps tinc and provides some simple way of configuration is tincapp. This application is available either as source, via F-Droid or Google Play. It provides no configuration GUI though - one has to enable the internal FTP server while being in a local network and upload configuration files that way after one has created a VPN network inside the app and generated the host keys. Unfortunately it currently does not support automatic launching on boot though.

Basically the configuration works the same way as for other machines - one uploads the required tinc.conf, the set of host keys (including the modified host key for the device one creates) and an additional network.conf.

The tinc.conf works the same as on any other system:

Name = anyexamplenodenameb
Mode = router
ConnectTo = anyexamplenodenamea

The network.conf is something specific for this platform though. It substitutes local interface configuration and route configuration since this has to be done through Androids VPN API. Basically it contains:

The Address is simply specified using Address:

Address =

The Route statements really only list all subnets that are supported by any of the remote nodes. This is also a shortfall of this solution since there seems to be no way to dynamically update this route information using OLSR or BGP.

Route =
Route =
Route =
Route =
Route =

In case one wants to route all traffic via the VPN one can set the usual default route with prefix length 0.

Route =

Whenever one wants to use an own internal DNS or DNS suffix the settings can also be set:

DNSServer =
DNSServer =

SearchDomain =

At the end bypass and reconnection settings finalize the configuration:

AllowBypass = true
ReconnectOnNetworkChange = true

After one has created the host keys via the UI one can download the generated host file using FTP - in this example the mobile device is reachable via on port 65521 after FTP access has been enabled in tincapp settings:

$ ftp tincapp@ 65521
Connected to
220 Service ready for new user.
331 User name okay, need password for tincapp.
230 User logged in, proceed.
Remote system type is UNIX.
ftp> cd files/networks/NETNAME
250 Directory changed to /files/networks/NETNAME

In case one has to change the local directory (tincd.conf and host files are not in the current working directory) one simply uses the lcd command:

ftp> lcd tinchosts
Local directory now: /usr/home/exampleuser/tinchosts

After that one can download the host file for the mobile node:

ftp> get hosts/anyexamplenodenameb
local: hosts/anyexamplenodenameb remote: hosts/anyexamplenodenameb
229 Entering Passive Mode (|||65530|)
150 File status okay; about to open data connection.
100% |***********************************|   554      333.13 KiB/s    --:-- ETA
226 Transfer complete.
554 bytes received in 00:00 (12.46 KiB/s)

Via the same mechanism one uploads tinc.conf, network.conf and any other hostfiles:

ftp> put hosts/anyexamplenodenamea
ftp> put tincd.conf
ftp> put network.conf

Then one should add the required subnet declaration (if any) to the hosts file. This might look like the following line:

Subnet =

At the end one just has to distribute the hosts file to all other hosts as usual. Now the mobile device should be able to join the VPN as usual.

This article is tagged:

Data protection policy

Dipl.-Ing. Thomas Spielauer, Wien (

This webpage is also available via TOR at http://rh6v563nt2dnxd5h2vhhqkudmyvjaevgiv77c62xflas52d5omtkxuid.onion/

Valid HTML 4.01 Strict Powered by FreeBSD IPv6 support