Created
March 5, 2021 22:24
-
-
Save Xumeiquer/941c74234987edb7d1e1b2a819e42053 to your computer and use it in GitHub Desktop.
Tinc VPN installation wizard
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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