Initial commit.

This commit is contained in:
redxef 2023-06-15 01:05:12 +02:00
commit 804008933d
Signed by: redxef
GPG key ID: 7DAC3AA211CBD921
3 changed files with 176 additions and 0 deletions

10
Makefile Normal file
View file

@ -0,0 +1,10 @@
SCRIPT := gre-on-wg.sh
SCRIPT_NAME := $(SCRIPT:.sh=)
PREFIX ?= /usr/local
install: install-bin
install-bin: $(SCRIPT)
install -D -m 0755 -o root -g root -T $(SCRIPT) $(PREFIX)/bin/$(SCRIPT_NAME)
.PHONY: install install-bin

51
README.md Normal file
View file

@ -0,0 +1,51 @@
# gre-on-wg
Create a GRETAP mesh network on top of wireguard.
## Usage
`gre-on-wg WG_QUICK_CONFIG_FILE ADDRESS_TRANSLATIONS`
The first argument is the path to a wg-quick config file, while the
second argument provides address translations for wireguard internal ip
addresses to the new addresses.
The wireguard configuration must have the `Address` config in the
`[Interface]` section set to exactly **one** address, similarly every
`[Peer]` section may only contain **one** AllowedIPs entry with **one**
addresss.
The translation file should contain lines of the following format:
`<wireguard private ip> <space> <new bridge network ip>`
### Example
Consider the following wg0.conf file
```
[Interface]
Address = 192.168.3.100/24
[Peer]
AllowedIPs = 192.168.3.101/32
[Peer]
AllowedIPs = 192.168.3.102/32
[Peer]
AllowedIPs = 192.168.3.103/32
```
And the following translation file
```
192.168.3.100/24 192.168.4.100/24
192.168.3.101/24 192.168.4.101/24
192.168.3.102/24 192.168.4.102/24
192.168.3.103/24 192.168.4.103/24
```
This would result in the creation of the bridge network `wg0br1` on host
`192.168.3.100` where the different peers have the addresses
`192.168.4.10[0123]`. Additionally the point-to-point networks
`wg0gre[1234]` would be created.

115
gre-on-wg.sh Executable file
View file

@ -0,0 +1,115 @@
#!/bin/bash
set -euo pipefail
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 link add "$name" type gretap local "$local_ip" remote "$remote_ip"
$DEBUG ip link set up "$name"
}
add_gre_to_br() {
local br_name gre_name
br_name="$1"
gre_name="$2"
$DEBUG ip link set "$gre_name" master "$br_name"
}
finish_br() {
local name local_ip
name="$1"
local_ip="$2"
$DEBUG ip addr add "$local_ip" dev "$name"
$DEBUG ip 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"
}
main() {
local filepath translation_filepath
local r local_ip remote_ips local_ip_trans
filepath="$1"
if [[ "$filepath" =~ .*/.* ]]; then
# path, not a name, leave as is
:
else
filepath="/etc/wireguard/$filepath"
fi
translation_filepath="$(sort <<< "$2" | uniq)"
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"
}
main "$@"