This commit is contained in:
Freya Murphy 2023-12-30 15:23:30 -05:00
parent ab75f7f7e3
commit 9ea034f420
No known key found for this signature in database
GPG key ID: 988032A5638EE799
12 changed files with 292 additions and 284 deletions

View file

@ -1,12 +1,17 @@
FROM alpine FROM alpine
RUN apk add --no-cache wireguard-tools bind-tools bird openrc udev-init-scripts-openrc RUN apk add --no-cache openrc udev-init-scripts-openrc wireguard-tools bind-tools bird
COPY ./wait.initd /etc/init.d/wait RUN mkdir -p /var/lib/inet2
COPY ./inet2.initd /etc/init.d/inet2 COPY ./bin /usr/local/bin
COPY ./lib /var/lib/inet2
COPY ./deployments/openrc/inet2.initd /etc/init.d/inet2
COPY ./deployments/docker/wait.initd /etc/init.d/wait
RUN sed -i 's/#rc_sys=""/rc_sys="docker"/' /etc/rc.conf && \ RUN sed -i 's/#rc_sys=""/rc_sys="docker"/' /etc/rc.conf && \
rc-update add wait && \ rc-update add wait && \
rc-update add inet2 rc-update add inet2
COPY ./setup.sh /setup.sh
COPY ./bin /usr/local/bin
ENTRYPOINT ["/setup.sh"] RUN rm -rf /run/openrc 2>/dev/null
RUN mkdir /run/openrc
RUN touch /run/openrc/softlevel
COPY ./deployments/docker/entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]

11
Makefile Normal file
View file

@ -0,0 +1,11 @@
.PHONY: install
install:
mkdir -p /var/lib/inet2
cp ./bin/* /usr/local/bin
cp ./lib/* /var/lib/inet2
alpine:
apk add --no-cache wireguard-tools bind-tools bird
cp ./deployments/openrc/inet2.initd /etc/init.d/inet2
rc-update add inet2

View file

@ -1,12 +1,10 @@
# freyanet # freyanet
this container allows perring multiple servers togeather with ospf creating an internetwork on any subnet peer multiple ospf nodes over wireguard to make an internal network
## running ## running
`docker run --privileged --network host -v $PWD/config:/config g.freya.cat/freya/freyanet` ### docker
or with docker-compose:
```yml ```yml
version: "3" version: "3"
@ -16,26 +14,54 @@ services:
network_mode: host # needed otherwise internal network wont be accessable network_mode: host # needed otherwise internal network wont be accessable
privileged: true privileged: true
volumes: volumes:
- ./config:/config - ./inet2.conf:/etc/inet2.conf
``` ```
### host
run the following commands with the provided makefile
```bash
$ make
$ make <os>
```
the current supported os's are: `alpine`
start the `inet2` service to start freyanet
## config ## config
create a file at /config/inet2.conf - if running in docker mount a file called `inet2.conf` at `/etc/inet2.conf`
- if running on host make a file called `/etc/inet2.conf`
``` ```
# specify router id # specify router id for ospf
RouterID 10.1.1.1 RouterID 10.1.1.1
# optionally assign static addresses to the loopback interface
Loopback 1.2.3.4
# specify routed subnets # specify routed subnets
# ips that are not in these subnets will be ignored
# put the ip blocks for your entire internal network
Subnet 10.0.0.0/8 Subnet 10.0.0.0/8
Subnet fd:cafe::/48 Subnet fd:cafe::/32
# specify node stubnets
# ip blocks that this node is gurenteed to route
Stubnet 10.1.0.0/8
Stubnet fd:cafe:dead::/48
# optional global private key gets used for all interfaces # optional global private key gets used for all interfaces
PrivateKey = {host private key} PrivateKey = {host private key}
# create a peered wireguard interface
# specify addresses, routes, ports, pre/post commands, and peers
# keys can be generated with wg genkey and wg pubkey
interface interfacename interface interfacename
# indentation is a single tab per level # indentation is a single tab per level
# otherwise file will fail to parse
# set the address(es) to assign to the interface # set the address(es) to assign to the interface
# route lines are usually the same as Address but with host bits zeroed # route lines are usually the same as Address but with host bits zeroed
@ -51,10 +77,6 @@ interface interfacename
# more syntax options # more syntax options
Route 1.1.2.0/24 via 1.1.1.2 Route 1.1.2.0/24 via 1.1.1.2
Route default via 1.1.1.3 Route default via 1.1.1.3
# optional: set Gateway and Gateway6 to configure a default gateway
# through this interface
Gateway 1.1.1.2
Gateway6 fe80::1111:1111:1111:1111
# port to listen on in the host's network namespace, over udp # port to listen on in the host's network namespace, over udp
# you probably have to allow this through your firewall # you probably have to allow this through your firewall
ListenPort {host port} ListenPort {host port}
@ -86,17 +108,9 @@ interface interfacename
# optional # optional
PersistentKeepalive = 25 PersistentKeepalive = 25
# optionally assign static addresses to the loopback interface
# this has its uses for making things ibgp not dependent on a specific interface being up
Loopback 1.2.3.4
``` ```
and other optional files: ## licenses
- `/config/setup.sh` gets run on the first run of the container with the host's networking
- `/config/start.sh` gets run every time the container starts up with the host's networking
### Licenses
| License | Author | Project | | License | Author | Project |
|---------|--------|---------| |---------|--------|---------|

View file

@ -1,20 +1,6 @@
#!/sbin/openrc-run #!/usr/bin/env sh
name="inet2"
description="Sets up wireguard interfaces connected via the host's internet connection"
extra_started_commands="reloadwg" . /var/lib/inet2/inet2.sh
run() {
printf '$ \x1b[32;1m%s\x1b[0m\n' "$*"
"$@"
}
step() {
printf '\x1b[34;1m>> %s\x1b[0m\n' "$*"
}
getval() {
/usr/local/bin/config.awk /run/inet2/inet2.conf "$@"
}
runscripts() { runscripts() {
if [ -n "$(getval "interface $2" "$1")" ]; then if [ -n "$(getval "interface $2" "$1")" ]; then
@ -25,23 +11,24 @@ runscripts() {
fi fi
} }
start() { start() {
step "Starting inet2"
step "Removing old Wireguard interfaces"
for file in /sys/class/net/*; do # Clear all wireguard interfaces for file in /sys/class/net/*; do # Clear all wireguard interfaces
type=$(cat "$file/type") type=$(cat "$file/type")
if [ "$type" = "65534" ]; then if [ "$type" = "65534" ]; then
ifname="$(basename $file)" ifname="$(basename $file)"
ip link del "$ifname" run ip link del "$ifname"
fi fi
done done
rm -rf /run/inet2/config 2>/dev/null rm -fr /run/inet2/wg 2> /dev/null
rm -rf /run/inet2/wg 2>/dev/null mkdir -p /run/inet2/wg
cp /config/inet2.conf /run/inet2/inet2.conf
mkdir /run/inet2/wg
mkbirdconfig.sh
step "Setting loopback addresses"
getval Loopback | while read -r addr; do getval Loopback | while read -r addr; do
run ip addr add "$addr" dev lo run ip addr add "$addr" dev lo
done done
@ -84,7 +71,8 @@ start() {
} }
stop() { stop() {
if [ -f /run/inet2/inet2.conf ]; then step "Stopping inet2"
step "Removing loopback"
getval Loopback | while read -r addr; do getval Loopback | while read -r addr; do
run ip addr del "$addr" dev lo run ip addr del "$addr" dev lo
done done
@ -97,16 +85,9 @@ stop() {
runscripts PostDown "$inter" runscripts PostDown "$inter"
done done
rm -rf /run/inet2/inet2.conf
fi
} }
# just reloads the wireguard configs for existing interfaces reload() {
# for if a peer's domain name resolves to a different ip address now
# and it needs to be re-resolved without taking down the connection
reloadwg() {
if [ -f /run/inet2/inet2.conf ]; then
getval interface | while read -r inter; do getval interface | while read -r inter; do
step "Generating config for $inter" step "Generating config for $inter"
run mkwgconfig.sh "$inter" /run/inet2/wg/"$inter" /config/inet2.conf run mkwgconfig.sh "$inter" /run/inet2/wg/"$inter" /config/inet2.conf
@ -114,6 +95,11 @@ reloadwg() {
step "Setting Wireguard config for $inter" step "Setting Wireguard config for $inter"
run wg setconf "$inter" /run/inet2/wg/"$inter" run wg setconf "$inter" /run/inet2/wg/"$inter"
done done
fi
} }
restart() {
stop
start
}
$1

84
bin/mkbirdconfig.sh Executable file
View file

@ -0,0 +1,84 @@
#!/bin/sh
. /var/lib/inet2/inet2.sh
escapebird() {
sed -e 's/\\/\\\\/g;s/"/\\"/g'
}
step "Creating Bird configuration"
touch /var/log/bird.log
chown bird:bird /var/log/bird.log
interfacelist=$(
echo " interface \"lo\" { stub; };"
getval interface | while read -r inter; do
val="$(getval "interface $inter" OSPF)"
if [ "$?" = "0" ]; then
echo " interface \"$(printf "%s" "$inter" | escapebird)\" {"
echo " type ptp;"
if [ -n "$val" ]; then
echo " $val;";
fi
echo " };"
fi
done
)
filter4=$(getval "Subnet" | grep -v ':' | while read -r line; do printf "%s+," "$line"; done | sed 's/,$//')
filter6=$(getval "Subnet" | grep ':' | while read -r line; do printf "%s+," "$line"; done | sed 's/,$//')
(cat <<EOF
log "/var/log/bird.log" all;
$(getval RouterID | while read -r line; do echo "router id $line;"; done)
protocol kernel {
ipv4 { export filter { if net ~ [$filter4] then accept; else reject; }; };
}
protocol kernel {
ipv6 { export filter { if net ~ [$filter6] then accept; else reject; }; };
}
protocol device {
}
protocol direct {
ipv4;
ipv6;
}
protocol static {
ipv4;
}
EOF
cat <<EOF
protocol ospf v3 ospf4 {
ipv4 {
import all;
export filter { if source ~ [RTS_DEVICE, RTS_INHERIT] && net ~ [$filter4] then accept; else reject; };
};
area 0 {
$(getval "Stubnet" | grep -v ':' | while read -r net; do echo " stubnet $net {};"; done)
$interfacelist
};
}
protocol ospf v3 ospf6 {
ipv6 {
import all;
export filter { if source ~ [RTS_DEVICE, RTS_INHERIT] && net ~ [$filter6] then accept; else reject; };
};
area 0 {
$(getval "Stubnet" | grep ':' | while read -r net; do echo " stubnet $net {};"; done)
$interfacelist
};
}
EOF
) > /etc/bird.conf
chown root:bird /etc/bird.conf
chmod 640 /etc/bird.conf

View file

@ -1,14 +1,11 @@
#!/bin/sh #!/usr/bin/env sh
# args: /path/to/interface-config /path/to/output.conf # args: /path/to/interface-config /path/to/output.conf
inter="$1" inter="$1"
configfile="$3" configfile=/etc/inet2.conf
if [ -z "$configfile" ]; then
configfile=/run/inet2/inet2.conf
fi
getval() { getval() {
/usr/local/bin/config.awk "$configfile" "$@" /var/lib/inet2/config.awk "$configfile" "$@"
} }
k() { k() {

View file

@ -0,0 +1,12 @@
#!/bin/sh
if [ "$#" = "0" ]; then
step "Starting OpenRC"
rm -rf /run/openrc 2>/dev/null
mkdir /run/openrc
touch /run/openrc/softlevel
exec /sbin/openrc
else
"$@"
fi

26
deployments/openrc/inet2.initd Executable file
View file

@ -0,0 +1,26 @@
#!/sbin/openrc-run
name="inet2"
description="Sets up wireguard interfaces connected via the host's internet connection"
extra_started_commands="reloadwg"
start() {
/usr/local/bin/inet2.sh start
rc-service bird start 2> /dev/null
}
stop() {
/usr/local/bin/inet2.sh stop
rc-service bird stop 2> /dev/null
}
restart() {
stop
start
}
reload() {
/usr/local/bin/inet2.sh reload
rc-service bird restart 2> /dev/null
}

22
lib/inet2.sh Executable file
View file

@ -0,0 +1,22 @@
#!/usr/bin/env sh
run() {
printf '$ \x1b[32;1m%s\x1b[0m\n' "$*"
"$@"
}
step() {
printf '\x1b[34;1m>> %s\x1b[0m\n' "$*"
}
getval() {
/var/lib/inet2/config.awk /etc/inet2.conf "$@"
}
haskey() {
getval interface | while read -r inter; do
if getval "interface $inter" "$1"; then
echo "true"
return
fi
done
}

149
setup.sh
View file

@ -1,149 +0,0 @@
#!/bin/sh
run() {
printf '$ \x1b[32;1m%s\x1b[0m\n' "$*"
"$@"
}
step() {
printf '\x1b[34;1m>> %s\x1b[0m\n' "$*"
}
getval() {
/usr/local/bin/config.awk /config/inet2.conf "$@"
}
haskey() {
getval interface | while read -r inter; do
if getval "interface $inter" "$1"; then
echo "true"
return
fi
done
}
# ensure the /run/inet2 directory is empty (docker doesn't mount tmpfs to /run)
# /run/inet2 is used for storage during runtime - restarting the container should clear it
rm -rf /run/inet2 2>/dev/null
mkdir /run/inet2
# ensure the /var/lib/inet2 directory exists
# /var/lib/inet2 is used for storage for the entire lifetime of the container - restarting the container shouldn't clear it
if [ ! -d /var/lib/inet2 ]; then
mkdir -p /var/lib/inet2
fi
# these are disabled in the docker netns
step "Enabling IPv6"
run sysctl net.ipv6.conf.all.disable_ipv6=0 net.ipv6.conf.default.disable_ipv6=0 net.ipv6.conf.all.forwarding=1
ospf="$(haskey OSPF)"
escapebird() {
sed -e 's/\\/\\\\/g;s/"/\\"/g'
}
if [ -n "$ospf" ]; then
step "Creating Bird configuration"
touch /var/log/bird.log
chown bird:bird /var/log/bird.log
selfas=$(getval AS)
(
cat <<EOF
log "/var/log/bird.log" all;
$(getval RouterID | while read -r line; do echo "router id $line;"; done)
protocol kernel {
ipv4 { export all; };
}
protocol kernel {
ipv6 { export all; };
}
protocol device {
}
protocol direct {
ipv4;
ipv6;
}
protocol static {
ipv4;
}
EOF
if [ -n "$ospf" ]; then
interfacelist=$(
echo " interface \"lo\" { stub; };"
getval interface | while read -r inter; do
val="$(getval "interface $inter" OSPF)"
if [ "$?" = "0" ]; then
echo " interface \"$(printf "%s" "$inter" | escapebird)\" {"
echo " type ptp;"
if [ -n "$val" ]; then
echo " $val;";
fi
echo " };"
fi
done
)
cat <<EOF
protocol ospf v3 ospf4 {
ipv4 {
import all;
export filter { if source ~ [RTS_DEVICE, RTS_INHERIT] && net ~ [$(getval "Subnet" | grep -v ':' | while read -r line; do printf "%s+," "$line"; done | sed 's/,$//')] then accept; else reject; };
};
area 0 {
$(getval "Stubnet" | grep -v ':' | while read -r net; do echo " stubnet $net {};"; done)
$interfacelist
};
}
protocol ospf v3 ospf6 {
ipv6 {
import all;
export filter { if source ~ [RTS_DEVICE, RTS_INHERIT] && net ~ [$(getval "Subnet" | grep ':' | while read -r line; do printf "%s+," "$line"; done | sed 's/,$//')] then accept; else reject; };
};
area 0 {
$(getval "Stubnet" | grep ':' | while read -r net; do echo " stubnet $net {};"; done)
$interfacelist
};
}
EOF
fi
) > /etc/bird.conf
chown root:bird /etc/bird.conf
chmod 640 /etc/bird.conf
step "Enabling BIRD"
run rc-update add bird
fi
if [ ! -f /var/lib/inet2/setupDone ]; then
if [ -f /config/setup.sh ]; then
step "Running /config/setup.sh"
/config/setup.sh
fi
touch /var/lib/inet2/setupDone
fi
if [ -f /config/start.sh ]; then
step "Running /config/start.sh"
/config/start.sh
fi
if [ "$#" = "0" ]; then
step "Starting OpenRC"
rm -rf /run/openrc 2>/dev/null
mkdir /run/openrc
touch /run/openrc/softlevel
exec /sbin/openrc
else
"$@"
fi