Tinc is another VPN daemon, secure, reliable, easy to use and easy to deploy. Lot of people tell me about this one to create distributed and decentralized VPN across different servers, and, honestly, I have not tried before. Easier to deploy and manage than IPsec, this is a really nice tool, and probably a must have on your server! So, a feature lists from official website (opens new window):
- Encryption, authentication and compression
- Automatic full mesh routing
- NAT traversal
- VPN Expansion
- **Bridge ethernet segment **
- IPv6 support and lot of environment
I will use tinc to create a meshed network on all my servers, OpenVPN can’t do that easily, and IPSec is really hard to deploy. Each of my servers will be in interconnection dedicated network one-by-one.
# Install Steps
tinc is ported on OpenBSD and FreeBSD system since a long time! You can install it with pre-build packages or install it from sources.
\# install tinc on OpenBSD
pkg_add tinc
\# install tinc on FreeBSD
pkg install tinc
If you want to build with your own feature and compiler flags, you can also use ports tree:
\# on OpenBSD
cd /usr/ports/net/tinc
make && make install
\# on FreeBSD
cd /usr/ports/security/tinc
make && make install
# Layer 2 Network Configuration
On OpenBSD, default configuration directory is located in
/etc/tinc . A tinc configuration is a directory containing all
required information to start tincd and let this one connect to
remote endpoint. In our example, I will create a new tinc
configuration named tunnel and create at the time the hosts
directory which will contain information about each hosts.
# creating main tunnel configuration
cd /etc/tinc
mkdir -p /etc/tinc/tunnel/hosts
We can now configure the main tinc daemon configuration file, named
tinc.conf . This one will contain the name of the tinc instance, all
remote hosts to connect to, the device used to map each configuration,
finally, for our example, the mode, in our case, in switch mode (L2).
# tinc.conf is the main configuration file
# for the daemon
touch /etc/tinc/tunnel/tinc.conf
cat >> /etc/tinc/tunnel/tinc.conf << EOF
Name = apoint
ConnectTo = bpoint
Device = /dev/tap0
Mode = switch
EOF
When tinc start, it execute tinc-up script. You can use it to
initialize your interface…
# tinc-up script, used when tunnel is started
touch /etc/tinc/tunnel/tinc-up
cat >> /etc/tinc/tunnel/tinc-up << EOF
#!/bin/sh
ifconfig \\${INTERFACE} inet 172.16.0.1/30 up
EOF
Tinc down script
# tinc-down script, used when we stop tunnel
touch /etc/tinc/tunnel/tinc-down << EOF
#!/bin/sh
ifconfig \\${INTERFACE} down
EOF
a point host configuration
# apoint host configuration
# public key is automatically generated
# in another step
touch /etc/tinc/tunnel/apoint
cat >> /etc/tinc/tunnel/apoint << EOF
Address = ${apoint_address}
Subnet = 172.16.0.0/30
\-----BEGIN RSA PUBLIC KEY-----
...
\-----END RSA PUBLIC KEY-----
EOF
bpoint host configuration
# bpoint host configuration
# public key must be imported from bpoint
touch /etc/tinc/tunnel/bpoint
cat >> /etc/tinc/tunnel/bpoint << EOF
Address = ${bpoint_address}
Subnet = 172.16.0.0/30
\-----BEGIN RSA PUBLIC KEY-----
...
\-----END RSA PUBLIC KEY-----
EOF
We have now all our configuration, we can generate our key pair for
our local server apoint .
# generate key
tincd -n tunnel -K
If everything is okay, we can now start tincd in standalone and
debug mode, see network traffic and other information.
# Start tinc standalone in debug mode
tincd -n tunnel -Dd5
If something goes wrong, we can take a look on all network flow with tcpdump:
# We can also check with tcpdump is everthing is okay
tcpdump -i ${interface} tcp port 655 or udp port 655
You can also look in route table
netstat -rnf inet
route show
Packet Filter configuration
# Configure packet-filter
mkdir -p /etc/pf.conf.d/tables
touch /etc/pf.conf.d/tables/tinc
echo "${apoint_address}" >> /etc/pf.conf.d/tables/tinc
echo "${bpoint_address}" >> /etc/pf.conf.d/tables/tinc
cat >> /etc/pf.conf << EOF
set skip on tap
table <tinc> counters persist file "/etc/pf.conf.d/tables/tinc"
pass quick proto {tcp, udp} from <tinc> to port 655
EOF
We can try to execute now pf.conf .
# check if our packet-filter configuration
# is well written and start it
pfctl -nf /etc/pf.conf
pfctl -f /etc/pf.conf
Now, we can set tinc at startup… A good way to protect our services is
to isolate everything. In our case, tinc can run with privilege
separation (fortunately, OpenBSD create _tinc user for this task)
with -Uargument. Tinc can also start in a chroot environment, locked
in their own configuration directory with -R argument.
# enable tincd at startup
rcctl enable tincd
rcctl set tincd flags "-n tunnel -U _tinc -d1 -R"
rcctl start tincd
# Layer 3 Network Configuration
# Monitoring Tunnel
I like simple tools but when we talk about monitoring and supervise services… It’s really hard to find a good solution. In my case, I like monit. A simple daemon, polling service and execute and action if something happen. Let see how to configure it.
# Resources
- https://www.freebsd.org/cgi/man.cgi?query=tincd (opens new window)
- https://www.freebsd.org/cgi/man.cgi?query=tinc.conf (opens new window)
- https://www.tinc-vpn.org/documentation/ (opens new window)
- https://www.tinc-vpn.org/examples/ (opens new window)
- https://www.digitalocean.com/community/tutorials/how-to-install-tinc-and-set-up-a-basic-vpn-on-ubuntu-14-04 (opens new window)