Skip to content

Instantly share code, notes, and snippets.

@Xumeiquer
Created March 5, 2021 22:24
Show Gist options
  • Save Xumeiquer/941c74234987edb7d1e1b2a819e42053 to your computer and use it in GitHub Desktop.
Save Xumeiquer/941c74234987edb7d1e1b2a819e42053 to your computer and use it in GitHub Desktop.
Tinc VPN installation wizard
#!/bin/bash
#
# Tinc install script
#
# Original: https://gist.github.com/jpillora/9069c7421fd70a4dae92
#
# Adapted by Xumeiquer
#
# Version: 1.0
# Version: 1.1
# Changelog:
# - Check whether keypairs already exist to avoid overwrite
# Version: 1.2
# Changelog:
# - Configure everything within the $NETWORK scope (usually /etc/tinc/$NETWORK)
# - Check whether Tinc is already installed
# Version: 1.3
# Changelog:
# - Added option to clone Mesh nodes from a Git repository
# - Added option to push your node to the Git repository
# Version: 1.4
# Changelog:
# - Added Git Hook to reload Tinc if needed
# - Added contrab entry for pulling new Mesh nodes
# Version: 1.5
# Changelog:
# - Detect previous configuration and avoid overwrite
# Version: 1.6
# Changelog:
# - Added limits in /etc/default/tinc
# - Fix typo in systemd service file name
################################################################################
################################################################################
# Default values
TINC_VERSION="1.1pre17"
NODE_NAME=$(hostname)
NETWORK="tinc-net-name"
IP="10.10.0.X"
NET="10.10.0.0"
IPMASK="32"
MASK="16"
PORT="655"
IFACE="tun0"
DEVICE="/dev/net/tun"
MODE="router"
TINC_DIR="/etc/tinc"
DNS=("10.10.0.1" "10.10.0.2")
PEERS=(peer1 peer2 peer3)
KEY_SIZE="4096"
LOG_PATH="/var/log/tinc"
################################################################################
function getValue() {
# Read value from user input
# Arguments:
# $1: Used to store result
# $2: Default value
# $3: Message
local tmp
local msg
declare -n ret=$1
msg="$3 [$2]: "
read -p "$msg" tmp
if [ -z ${tmp} ]; then
ret="$2"
else
ret="$tmp"
fi
}
# install tinc
getValue TINC_VERSION $TINC_VERSION "Tinc version to install"
TINC_URL="https://www.tinc-vpn.org/packages/tinc-$TINC_VERSION.tar.gz"
REINSTALL="n"
PREV_TINC=$(tinc --version | head -n1 | cut -d ' ' -f 3)
if [ -z x"$PREV_TINC" ] || [ x"$PREV_TINC" == x"$TINC_VERSION" ]; then
echo -e
read -p "[*] Tinc version $TINC_VERSION is already installed. Do you want compile an intall it again (y/n) [n]: " REINSTALL
else
REINSTALL="y"
fi
if [ x"$REINSTALL" == x"y" ]; then
echo "Updating and installing dependencies"
apt-get update && echo "===> update deps" &&
apt-get install -y gcc make libssl1.0.2 zlib1g-dev liblzo2-dev libreadline-dev libncurses5-dev && echo "===> got deps" &&
curl $TINC_URL | tar xzvf - && echo "===> got tinc src" &&
cd tinc-$TINC_VERSION &&
./configure && echo "===> configured tinc" &&
make &&
make install && echo "===> installed tinc" &&
tinc --version # tinc version $TINC_VERSION (built Nov 12 2015 16:25:28, protocol 17.4)
if [ $? == 0 ]; then
echo "Tinc version $TINC_VERSION was intalled successfully"
else
echo "Something went wrong during Tinc installtion. Exiting..."
exit 1
fi
fi
echo -e
# setup my-network, keys, hosts...
echo "[*] Gathering information to configure Tinc"
getValue TINC_DIR $TINC_DIR "Tinc config directory"
getValue NETWORK $NETWORK "Tinc network name"
CONFIG_DIR="$TINC_DIR/$NETWORK"
CONTINUE="n"
if [ -d "$CONFIG_DIR" ]; then
echo -e
echo "Configuration found in $CONFIG_DIR"
read -p "[*] By continuing some configuration will be overwritten. Do you want to continue? (y/n) [$CONTINUE]: " CONTINUE
if [ -z "$CONTINUE" ] || [ x"$CONTINUE" == x"n" ]; then
systemctl restart tinc
exit 0
fi
fi
if [ ! -d "$CONFIG_DIR" ] || [ x"$CONTINUE" != x"n" ]; then
NODE_NAME=$(echo $NODE_NAME | tr -cs 'a-zA-Z0-9' '_' | rev | cut -c 2- | rev)
getValue NODE_NAME $NODE_NAME "Tinc node name"
NODE_NAME=$(echo $NODE_NAME | tr -cs 'a-zA-Z0-9' '_' | rev | cut -c 2- | rev)
getValue IP $IP "Tinc node IP"
getValue NET $NET "Tinc node network"
getValue MASK $MASK "Tinc network mask"
getValue PORT $PORT "Tinc port"
getValue IFACE $IFACE "Tinc network interface"
getValue DEVICE $DEVICE "Tinc network device"
getValue MODE $MODE "Tinc node mode"
HOSTS_DIR="$CONFIG_DIR/hosts"
read -p "Tinc Mesh DNS Servers [${DNS[*]}]: " -a DNS_AUX
if [ x$DNS_AUX != x"" ]; then
unset DNS
DNS=${DNS_AUX[@]}
fi
read -p "Tinc Mesh Peers [${PEERS[*]}]: " -a PEERS_AUX
if [ x$PEERS_AUX != x"" ]; then
unset PEERS
PEERS=${PEERS_AUX[@]}
fi
mkdir -p $CONFIG_DIR $HOSTS_DIR $LOG_PATH
mkdir -p /usr/local/var/run/
echo "Name = $NODE_NAME
AddressFamily = ipv4
Interface = $IFACE
Device = $DEVICE
Mode = $MODE
Hostnames = no
Port = $PORT
PingTimeout = 60
debug = 5
logfile = $LOG_PATH/$NODE_NAME.log
StrictSubnets = no" > $CONFIG_DIR/tinc.conf
for host in ${PEERS[@]}; do
echo "ConnectTo = $host" >> $CONFIG_DIR/tinc.conf
done
#set static up (or do some advanced stuff)
echo "#!/bin/sh" > $CONFIG_DIR/tinc-up
echo "ip link set \$INTERFACE up" >> $CONFIG_DIR/tinc-up
echo "ip addr add $IP/$IPMASK dev \$INTERFACE" >> $CONFIG_DIR/tinc-up
echo "ip route add $NET/$MASK dev \$INTERFACE" >> $CONFIG_DIR/tinc-up
for dns in ${DNS[@]}; do
echo "echo 'nameserver $dns' >> /etc/resolv.conf" >> $CONFIG_DIR/tinc-up
done
echo "#!/bin/sh" > $CONFIG_DIR/tinc-down
echo "ip route del $NET/$MASK dev \$INTERFACE" >> $CONFIG_DIR/tinc-down
echo "ip addr del $IP/$IPMASK dev \$INTERFACE" >> $CONFIG_DIR/tinc-down
echo "ip link set \$INTERFACE down" >> $CONFIG_DIR/tinc-down
for dns in ${DNS[@]}; do
echo "sed -i '/nameserver $dns/d' /etc/resolv.conf" >> $CONFIG_DIR/tinc-down
done
#make these scripts executable
chmod +x $CONFIG_DIR/{tinc-up,tinc-down}
echo "$NETWORK" >> $TINC_DIR/nets.boot
chmod 755 $TINC_DIR/nets.boot
# clone mesh nodes
CLONE="y"
echo -e
read -p "[*] Do you want to clone mesh nodes from a Git repository? (y/n) [$CLONE]: " CLONE
if [ -z "$CLONE" ] || [ x"$CLONE" == x"y" ]; then
GIT_URL="https://<username>:<token>@<hostname>/<org>/<repo>"
getValue GIT_URL $GIT_URL "Git URL"
git clone $GIT_URL $HOSTS_DIR
echo "#!/usr/bin/env bash
changed_files=\"\$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)\"
[[ \${#changed_files} -gt 0 ]] && systemctl restart tinc" > "$HOSTS_DIR/.git/hooks/post-merge"
chmod +x "$HOSTS_DIR/.git/hooks/post-merge"
CRON="y"
echo -e
read -p "[*] Do you want to add a crontab entry to check periodically new Mesh nodes? (y/n) [y]: " CRON
if [ -z "$CRON" ] || [ x"$CRON" == x"y" ]; then
FREQ="0 */8 * * *"
read -p "Update frequency [${FREQ[*]}]: " -a FREQ_AUX
if [ x$FREQ_AUX != x"" ]; then
unset FREQ
FREQ=${FREQ_AUX[@]}
fi
crontab -l | { cat; echo "${FREQ[@]} cd $HOSTS_DIR && /usr/bin/git pull origin master"; } | crontab -
fi
fi
# setup node configuration
echo "Cipher=blowfish
Compression=0
Digest=sha1
IndirectData=no
Subnet=$IP/$IPMASK
TCPonly=no" > "$HOSTS_DIR/$NODE_NAME"
# generate keypairs
REGENERATE_KEYS="n"
if [ -f "$CONFIG_DIR/rsa_key.priv" ] || [ -f "$CONFIG_DIR/rsa_key.priv" ] || [ -f "$CONFIG_DIR/rsa_key.priv" ] || [ -f "$CONFIG_DIR/rsa_key.priv" ]; then
echo -e
read -p "[*] Found some keypairs, do you want to overwrite them? (y/n) [n]: " REGENERATE_KEYS
else
REGENERATE_KEYS="y"
fi
if [ x$REGENERATE_KEYS == x"y" ]; then
getValue KEY_SIZE $KEY_SIZE "Tinc RSA Key size"
echo "[*] PLEASE ACCEPT DEFAULTS."
tinc -c $CONFIG_DIR generate-keys $KEY_SIZE
fi
# updating Mesh nodes repositories
CLONE="y"
echo -e
read -p "[*] Do you want to push your mesh node to the Git repository? (y/n) [$CLONE]: " CLONE
if [ -z "$CLONE" ] || [ x"$CLONE" == x"y" ]; then
cd $HOSTS_DIR
git add $NODE_NAME
git commit -m "New node $NODE_NAME added to the mesh"
git push origin master
cd - >/dev/null
fi
#setup startup scripts
echo "[Unit]
Description=tinc
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/usr/local/sbin/tincd -D --config=$CONFIG_DIR -n $NETWORK --debug=3 --logfile=$LOG_PATH/$NODE_NAME.log
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
" > /etc/systemd/system/tinc-$NETWORK.service
systemctl daemon-reload
systemctl enable tinc-$NETWORK
#setup logrotate
echo "$LOG_PATH/* {
rotate 7
size 100M
weekly
missingok
notifempty
compress
}" > /etc/logrotate.d/tinc
touch $LOG_PATH/$NODE_NAME.log
#updating limit
echo 'LIMITS="-l 32768 -n 512"' >> /etc/default/tinc
#test with this until it works
echo "Testing connectivity for 10 sec."
timeout 10 tincd -D -c $CONFIG_DIR -n $NETWORK -d3 --logfile=/dev/stdout
#and then start
systemctl start tinc-$NETWORK.service
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment