gre-on-wg/gre-on-wg.sh
redxef f9cbba8607
Add pssibility of delay between ip commands.
Also fix wg interface name detection to use the name, and not wg0.
2023-06-15 13:35:30 +02:00

152 lines
3.5 KiB
Bash
Executable file

#!/bin/bash
set -euo pipefail
_="${DEBUG:=}"
_="${GOW_IP_DELAY:=0}"
ip_hook() {
ip "$@"
sleep "$GOW_IP_DELAY"
}
strstrip() {
sed -E -e 's/^\s*//' -e 's/\s*$//'
}
create_br() {
local name
name="$1"
$DEBUG ip link add "$name" type bridge
}
create_gre() {
local name local_ip remote_ip
name="$1"
local_ip="$(sed 's_/.*$__' <<< "$2")"
remote_ip="$(sed 's_/.*$__' <<< "$3")"
$DEBUG ip_hook link add "$name" type gretap local "$local_ip" remote "$remote_ip"
$DEBUG ip_hook link set up "$name"
}
add_gre_to_br() {
local br_name gre_name
br_name="$1"
gre_name="$2"
$DEBUG ip_hook link set "$gre_name" master "$br_name"
}
finish_br() {
local name local_ip
name="$1"
local_ip="$2"
$DEBUG ip_hook addr add "$local_ip" dev "$name"
$DEBUG ip_hook link set up "$name"
}
read_wg_conf() {
local filepath
local local_ip remote_ips mode line
filepath="$1"
local_ip=
remote_ips=
mode=
while read -r line; do
line="$(strstrip <<< "$line")"
if [[ "$line" = '[Interface]' ]]; then
mode=interface
continue
elif [[ "$line" = '[Peer]' ]]; then
mode=peer
continue
fi
if [[ "$mode" = 'interface' ]] && [[ "$line" =~ ^Address\ *=\ * ]]; then
local_ip="$(awk -F= '{print $2}' <<< "$line" | strstrip)"
elif [[ "$mode" = 'peer' ]] && [[ "$line" =~ ^AllowedIPs\ *=\ * ]]; then
remote_ips="$remote_ips $(awk -F= '{print $2}' <<< "$line" | strstrip)"
fi
done < "$filepath"
remote_ips="$(strstrip <<< "$remote_ips")"
echo "$local_ip"
echo "$remote_ips"
}
create_networks() {
local wg_name local_ip local_ip_trans remote_ips
local br_name n
wg_name="$1"
local_ip="$2"
local_ip_trans="$3"
remote_ips="$4"
br_name="${wg_name}br1"
n=1
create_br "$br_name"
for remote_ip in $remote_ips ; do
create_gre "${wg_name}gre$n" "$local_ip" "$remote_ip"
add_gre_to_br "$br_name" "${wg_name}gre$n"
n=$((n+1))
done
finish_br "$br_name" "$local_ip_trans"
}
up() {
local filepath translation_filepath
local r local_ip remote_ips local_ip_trans
filepath="$1"
translation_filepath=
if [[ "$filepath" =~ .*/.* ]]; then
# path, not a name, leave as is
:
else
if [[ $# -eq 1 ]]; then
translation_filepath="$filepath"
fi
filepath="/etc/wireguard/$filepath.conf"
fi
if [[ -z "$translation_filepath" ]]; then
translation_filepath="$2"
fi
if [[ "$translation_filepath" =~ .*/.* ]]; then
# path, not a name, leave as is
:
else
translation_filepath="/etc/gre-on-wg/$translation_filepath.conf"
fi
r="$(read_wg_conf "$filepath")"
local_ip="$(head -n1 <<< "$r")"
remote_ips="$(tail -n1 <<< "$r")"
unset r
local_ip_trans="$(grep -E "$(sed 's_\._\\._g' <<< "$local_ip")" "$translation_filepath" | awk '{print $2}')"
create_networks "$(basename --suffix='.conf' "$filepath")" "$local_ip" "$local_ip_trans" "$remote_ips"
}
down() {
local filepath
local wg_name link
filepath="$1"
if [[ "$filepath" =~ .*/.* ]]; then
# path, not a name, leave as is
:
else
filepath="/etc/wireguard/$filepath.conf"
fi
wg_name="$(basename --suffix=.conf "$filepath")"
for link in $(ip_hook link list | grep -Eo '^[0-9]+:\s+'"$wg_name"'[^:@]+' | sed -E 's/[0-9]+:\s+//' | tac); do
$DEBUG ip_hook link del "$link"
done
}
"$@"