How to create your own private network


#1

Hi everybody! We often see many posts how to deal with private IPs on Scaleway (that are dynamics), and isolation in the network. Today, I suggest you to create your own private between all your servers. That way, your servers without IP address can be NATed and have access to internet through a router server. Data between your server will be disclosed through encrypted tunnels.
In this tutorial, I’ll show you how to use Tinc to create a meshed network, and how to deal with the dynamic private IPs from Scaleway.

Ready to fight the IPv4 shortage? :smiley:

Requirements

In order to follow the following tutorial, you must have:

  • At least 2 servers
  • A public IP
  • A temporary public IP

Note

I used Debian servers to do this tutorial, and the scripts provided are bash scripts.
We’ll name the meshed network local.
We’ll use the 172.16.0.0/16 network for the meshed network.
Use the temporary public IP on the server you want to include in the network. It is used to have internet connection while installing dependencies.

Router configuration

We will use the server with your attached public IP as the router a server that’ll act as master of the meshed network.

Installations

apt update
apt upgrade
apt install iptables iptables-persistent dnsutils tinc

Configure Tinc

mkdir -p /etc/tinc/local/hosts
tincd -n local -K 4096 # Creates a RSA key representing the router in /etc/tinc/local

Create the file /etc/tinc/local/tinc.conf and paste the following content:

Name=master
Device=/dev/net/tun
Mode=switch

Create the file /etc/tinc/local/hosts/master and paste the following content:

Address=xxxxxxxxxxxxxx.priv.cloud.scaleway.com
Port=655
Compression=0
Subnet=172.16.0.1/32

Change the Address by the private DNS address given in the Scaleway Panel for your router. In subnet, put whatever IP you want for your router (beware to keep the /32 at the end).
Now we’ll append the public key to this configuration file:

cat /etc/tinc/local/rsa_key.pub >> /etc/tinc/local/hosts/master

Next, create the file /etc/tinc/local/tinc-up and paste the following content:

#!/bin/bash
ip link set $INTERFACE up
ip addr add 172.16.0.1/16 dev $INTERFACE

Don’t forget to replace 172.16.0.1/16 by the IP you want.
We’re almost done, one more time, create the file /etc/tinc/local/tinc-down and paste the following content:

#!/bin/bash
ip link set dev $INTERFACE down

Then, we’ll tell Tinc to start the local network at boot:

echo local >> /etc/tinc/nets.boot

Endly, we’ll make tinc-up and tinc-down executable:

chmod a+x /etc/tinc/local/tinc-*

##NAT
Here are the following minimum commands to configure NAT on the router:

iptables -A FORWARD -i eth0 -o local -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i local -o eth0 -j ACCEPT
iptables -A POSTROUTING -o eth0 -j MASQUERADE
iptables-save > /etc/iptables/rules.v4

Endly…

reboot

We made it! The router is now ready to accept Tinc connections and is natting from the private network to the Internet.
Next step: configure and automatize server inclusion into the network!

#Clients inclusion
I’ll provide you a ready-to-use script that can include any servers you manage into the Tinc meshed network.

##Prepare the files
Go back to your home as working directory, and copy all the Tinc local folder:

cp -r /etc/tinc ./files
rm ./files/local/rsa_key.*

Let’s edit ./files/local/tinc.conf and replace all the content by:

Name=%HOSTNAME%
Device=/dev/net/tun
Mode=switch
ConnectTo=master

Now, same thing with ./files/local/tinc-up:

#!/bin/bash
ip link set $INTERFACE up
ip addr add 172.16.%ENDIP%/16 dev $INTERFACE

# Setup the default gateway
GATEWAY=`ip route show default | awk '/default via/{print $3}'`
NAMESERVERS=`cat /etc/resolv.conf | awk '/nameserver/{print $2}'`
SERVERNAME=`cat /etc/tinc/local/hosts/master | grep Address | sed 's/Address=//g'`
SERVERIP=`dig $SERVERNAME | grep -v '^;' | grep 'IN A' | awk '{print $NF}'`

for ns in $NAMESERVERS; do
    ip route add $ns via $GATEWAY dev eth0
done
ip route delete default
ip route add $SERVERIP via $GATEWAY dev eth0
ip route add default via 172.16.0.1 dev $INTERFACE

Endly, ./files/local/tinc-down:

#!/bin/bash
GATEWAY=`ip route show | awk '/dev eth0 .* scope link/{print $1}' | sed 's/\/[0-9]*//g'`
ROUTES=`ip route show | awk '/via .* dev eth0/{print $1}'`
for ip in $ROUTES; do
    ip route delete $ip
done
ip link set dev $INTERFACE down
ip route delete default
ip route add default via $GATEWAY dev eth0

##The script
The last step to be ready… Here’s the script! Put it in the same directory where is the folder files; I named it include.

#!/bin/bash
echo "Going to include $1 ($2) with IP 172.16.$3 in the local network"
read -p "Is it okay?"

echo "Creating files..."
cp -r ~/files /tmp/tinc
sed -i -e "s/%HOSTNAME%/$1/g" /tmp/tinc/local/tinc.conf
sed -i -e "s/%ENDIP%/$3/g" /tmp/tinc/local/tinc-up

echo "Preparing client"
ssh root@$2 << EOF
  apt-get update
  apt-get upgrade -y
  apt-get install -y dnsutils tinc
EOF

echo "Transferring files"
scp -r /tmp/tinc/* root@$2:/etc/tinc/

echo "Configuring client"
ssh root@$2 << EOF
  tincd -n local -K4096
EOF

echo "Getting pubkey"
scp -r root@$2:/etc/tinc/local/hosts/$1 /etc/tinc/local/hosts/

echo "Should be okay, rebooting!"
ssh root@$2 reboot &

rm -r /tmp/tinc

And let’s make it executable:

chmod a+x ./include

Include a new server in the network

In order to add a server to the meshed network, you just have to execute the following command:

./include HOSTNAME 10.xx.xx.xx yy.zz

Replace HOSTNAME with the hostname of your server, 10.xx.xx.xx with the current internal IP, and yy.zz with the end of the private network IP. The script will ask for confirmation, verify the information is correct and press enter.

###Note
When connecting to the router from the web, don’t forget to use the Agent Forwarding (ssh -A), it’ll allow the script to connect using the SSH key you referenced in the Scaleway Web Panel.

#To go further
Now we have all our servers in the same meshed network, we can easily port forward from the router to the wanted servers or use a loadbalancer, like HAProxy on the router.


I really hope it helped because it was an issue for me and dealing with Scaleway’s dynamic IPs to Port Forward was more than hard. Here we took the advantage of Tinc to disclose our network as if it was a real local network.
Of course, there’s still a lot of improvements to do, like multiple Tinc servers to keep the network up even if the router goes down, or use multiple routers with multiple IPs…

Let me know if you’ve got any questions, I may not have been clear while writting this tutorial…


#2

very nice, I was wondering if you had a look at wireGuard, it sayed that it is as easy as tinc but more powefull.


#3

I didn’t know the existence of WireGuard. Tinc was easy to use and documented enough to do this exact type of network :slight_smile:


#4

Just if someone struggled, the NAT wont work unless forwarding is enabled in the master with echo 1 > /proc/sys/net/ipv4/ip_forward. This configuration should also be persisted in the system by adding net.ipv4.ip_forward = 1 to /etc/sysctl.conf.
@Mavyre Is there any way to tell tinc to pick a free ip address from a pool and assign it to the client interface. I don’t want to track all my clients ip address, I don’t even care about them, so instead of ip addr add 172.16.%ENDIP%/16 dev $INTERFACE and provide endip, I want tinc to assign a free one. Is that possible? Thanks by the way good tutorial