fix(gateway): Fix systemd gateways on SELinux-enabled distros and improve systemd gateway UX (#3127)

- Fix permissions and caps on each start
- Fixes incompatibility with some systemd versions that barf at the
inline `ExecStartPre`
- Fixes erroneous error printed by iptables
- Fixes masquerading not working for wireless interfaces
- Single-step systemd copy-paste command
- Fixes #2944 
- Fixes #3124 
- Fixes #3112 


Tested on CentOS 7 and Ubuntu 22.04
This commit is contained in:
Jamil
2024-01-08 09:56:54 -08:00
committed by GitHub
parent c02e7ed332
commit bc93762c16

View File

@@ -70,70 +70,14 @@ defmodule Web.Sites.NewToken do
selected={@selected_tab == "systemd-instructions"}
>
<p class="p-4">
1. Create an unprivileged user and group to run the gateway:
Copy-paste this command to your server:
</p>
<.code_block
id="code-sample-systemd0"
class="w-full text-xs whitespace-pre-line"
phx-no-format
>sudo groupadd -f firezone \
&& id -u firezone &>/dev/null || sudo useradd -r -g firezone -s /sbin/nologin firezone</.code_block>
<p class="p-4">
2. Create a new systemd unit file:
</p>
<.code_block
id="code-sample-systemd1"
class="w-full text-xs whitespace-pre-line"
phx-no-format
>sudo nano /etc/systemd/system/firezone-gateway.service</.code_block>
<p class="p-4">
3. Copy-paste the following contents into the file:
</p>
<.code_block
id="code-sample-systemd2"
class="w-full text-xs whitespace-pre-line"
phx-no-format
phx-update="ignore"
><%= systemd_command(@env) %></.code_block>
<p class="p-4">
4. Save by pressing <kbd>Ctrl</kbd>+<kbd>X</kbd>, then <kbd>Y</kbd>, then <kbd>Enter</kbd>.
</p>
<p class="p-4">
5. Reload systemd configuration:
</p>
<.code_block
id="code-sample-systemd4"
class="w-full text-xs whitespace-pre-line"
phx-no-format
>sudo systemctl daemon-reload</.code_block>
<p class="p-4">
6. Start the service:
</p>
<.code_block
id="code-sample-systemd5"
class="w-full text-xs whitespace-pre-line"
phx-no-format
>sudo systemctl start firezone-gateway</.code_block>
<p class="p-4">
7. Enable the service to start on boot:
</p>
<.code_block
id="code-sample-systemd6"
class="w-full text-xs whitespace-pre-line"
phx-no-format
>sudo systemctl enable firezone-gateway</.code_block>
</:tab>
<:tab
id="docker-instructions"
@@ -151,6 +95,15 @@ defmodule Web.Sites.NewToken do
phx-no-format
phx-update="ignore"
><%= docker_command(@env) %></.code_block>
<p class="p-4">
<strong>Important:</strong>
If you need IPv6 support, you must <.link
href="https://docs.docker.com/config/daemon/ipv6"
class={link_style()}
target="_blank"
>enable IPv6 in the Docker daemon</.link>.
</p>
</:tab>
</.tabs>
@@ -238,6 +191,14 @@ defmodule Web.Sites.NewToken do
defp systemd_command(env) do
"""
( function install-firezone {
# Create firezone user and group
sudo groupadd -f firezone
id -u firezone &>/dev/null || sudo useradd -r -g firezone -s /sbin/nologin firezone
# Create systemd unit file
cat << EOF > /etc/systemd/system/firezone-gateway.service
[Unit]
Description=Firezone Gateway
After=network.target
@@ -246,47 +207,11 @@ defmodule Web.Sites.NewToken do
[Service]
Type=simple
#{Enum.map_join(env, "\n", fn {key, value} -> "Environment=\"#{key}=#{value}\"" end)}
ExecStartPre=/bin/sh -c 'set -ue; \\
if [ ! -e /usr/local/bin/firezone-gateway ]; then \\
FIREZONE_VERSION=$(curl -Ls \\
-H "Accept: application/vnd.github+json" \\
-H "X-GitHub-Api-Version: 2022-11-28" \\
"https://api.github.com/repos/firezone/firezone/releases/latest" | \\
grep "\\\\"tag_name\\\\":" | sed "s/.*\\\\"tag_name\\\\": \\\\"\\([^\\\\"\\\\]*\\).*/\\1/" \\
); \\
[ "$FIREZONE_VERSION" = "" ] && echo "[Error] Can not fetch latest version, rate limited by GitHub?" && exit 1; \\
echo "Downloading Firezone Gateway version $FIREZONE_VERSION"; \\
arch=$(uname -m); \\
case $arch in \\
aarch64) \\
bin_url="https://github.com/firezone/firezone/releases/download/$FIREZONE_VERSION/gateway-arm64" ;; \\
armv7l) \\
bin_url="https://github.com/firezone/firezone/releases/download/$FIREZONE_VERSION/gateway-arm" ;; \\
x86_64) \\
bin_url="https://github.com/firezone/firezone/releases/download/$FIREZONE_VERSION/gateway-x64" ;; \\
*) \\
echo "Unsupported architecture"; \\
exit 1 ;; \\
esac; \\
curl -Ls $bin_url -o /usr/local/bin/firezone-gateway; \\
chgrp firezone /usr/local/bin/firezone-gateway; \\
chmod 0750 /usr/local/bin/firezone-gateway; \\
setcap 'cap_net_admin+eip' /usr/local/bin/firezone-gateway; \\
fi; \\
mkdir -p /var/lib/firezone; \\
chown firezone:firezone /var/lib/firezone; \\
chmod 0775 /var/lib/firezone; \\
iptables-nft -C FORWARD -i tun-firezone -j ACCEPT || iptables-nft -A FORWARD -i tun-firezone -j ACCEPT; \\
iptables-nft -C FORWARD -o tun-firezone -j ACCEPT || iptables-nft -A FORWARD -o tun-firezone -j ACCEPT; \\
iptables-nft -t nat -C POSTROUTING -o e+ -j MASQUERADE || iptables-nft -t nat -A POSTROUTING -o e+ -j MASQUERADE; \\
ip6tables-nft -C FORWARD -i tun-firezone -j ACCEPT || ip6tables-nft -A FORWARD -i tun-firezone -j ACCEPT; \\
ip6tables-nft -C FORWARD -o tun-firezone -j ACCEPT || ip6tables-nft -A FORWARD -o tun-firezone -j ACCEPT; \\
ip6tables-nft -t nat -C POSTROUTING -o e+ -j MASQUERADE || ip6tables-nft -t nat -A POSTROUTING -o e+ -j MASQUERADE; \\
'
ExecStart=/usr/bin/sudo \\
--preserve-env=FIREZONE_NAME,FIREZONE_ID,FIREZONE_TOKEN,FIREZONE_API_URL,RUST_LOG \\
-u firezone \\
-g firezone \\
ExecStartPre=/usr/local/bin/firezone-gateway-init
ExecStart=/usr/bin/sudo \\\\
--preserve-env=FIREZONE_NAME,FIREZONE_ID,FIREZONE_TOKEN,FIREZONE_API_URL,RUST_LOG \\\\
-u firezone \\\\
-g firezone \\\\
/usr/local/bin/firezone-gateway
TimeoutStartSec=3s
TimeoutStopSec=15s
@@ -295,6 +220,84 @@ defmodule Web.Sites.NewToken do
[Install]
WantedBy=multi-user.target
EOF
# Create ExecStartPre script
cat << EOF > /usr/local/bin/firezone-gateway-init
#!/bin/sh
set -ue
# Download latest version of the gateway if it doesn't already exist
if [ ! -e /usr/local/bin/firezone-gateway ]; then
echo "/usr/local/bin/firezone-gateway not found. Downloading latest version..."
FIREZONE_VERSION=\\$(curl -Ls \\\\
-H "Accept: application/vnd.github+json" \\\\
-H "X-GitHub-Api-Version: 2022-11-28" \\\\
"https://api.github.com/repos/firezone/firezone/releases/latest" | grep '"tag_name":' | sed 's/.*"tag_name": "\([^"]*\).*/\1/'
)
[ "\\$FIREZONE_VERSION" = "" ] && echo "[Error] Cannot fetch latest version. Rate-limited by GitHub?" && exit 1
echo "Downloading Firezone Gateway version \\$FIREZONE_VERSION"
arch=\\$(uname -m)
case \\$arch in
aarch64)
bin_url="https://github.com/firezone/firezone/releases/download/\\$FIREZONE_VERSION/gateway-arm64"
;;
armv7l)
bin_url="https://github.com/firezone/firezone/releases/download/\\$FIREZONE_VERSION/gateway-arm"
;;
x86_64)
bin_url="https://github.com/firezone/firezone/releases/download/\\$FIREZONE_VERSION/gateway-x64"
;;
*)
echo "Unsupported architecture"
exit 1
esac
curl -Ls \\$bin_url -o /usr/local/bin/firezone-gateway
else
echo "/usr/local/bin/firezone-gateway found. Skipping download."
fi
# Set proper capabilities and permissions on each start
chgrp firezone /usr/local/bin/firezone-gateway
chmod 0750 /usr/local/bin/firezone-gateway
setcap 'cap_net_admin+eip' /usr/local/bin/firezone-gateway
mkdir -p /var/lib/firezone
chown firezone:firezone /var/lib/firezone
chmod 0775 /var/lib/firezone
# Enable masquerading for ethernet and wireless interfaces
iptables -C FORWARD -i tun-firezone -j ACCEPT 2&>1 > /dev/null || iptables -A FORWARD -i tun-firezone -j ACCEPT
iptables -C FORWARD -o tun-firezone -j ACCEPT 2&>1 > /dev/null || iptables -A FORWARD -o tun-firezone -j ACCEPT
iptables -t nat -C POSTROUTING -o e+ -j MASQUERADE 2&>1 > /dev/null || iptables -t nat -A POSTROUTING -o e+ -j MASQUERADE
iptables -t nat -C POSTROUTING -o w+ -j MASQUERADE 2&>1 > /dev/null || iptables -t nat -A POSTROUTING -o w+ -j MASQUERADE
ip6tables -C FORWARD -i tun-firezone -j ACCEPT 2&>1 > /dev/null || ip6tables -A FORWARD -i tun-firezone -j ACCEPT
ip6tables -C FORWARD -o tun-firezone -j ACCEPT 2&>1 > /dev/null || ip6tables -A FORWARD -o tun-firezone -j ACCEPT
ip6tables -t nat -C POSTROUTING -o e+ -j MASQUERADE 2&>1 > /dev/null || ip6tables -t nat -A POSTROUTING -o e+ -j MASQUERADE
ip6tables -t nat -C POSTROUTING -o w+ -j MASQUERADE 2&>1 > /dev/null || ip6tables -t nat -A POSTROUTING -o w+ -j MASQUERADE
# Enable packet forwarding
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv4.conf.all.src_valid_mark=1
sysctl -w net.ipv6.conf.all.disable_ipv6=0
sysctl -w net.ipv6.conf.all.forwarding=1
sysctl -w net.ipv6.conf.default.forwarding=1
EOF
# Make ExecStartPre script executable
chmod +x /usr/local/bin/firezone-gateway-init
# Reload systemd
sudo systemctl daemon-reload
# Enable the service to start on boot
sudo systemctl enable firezone-gateway
# Start the service
sudo systemctl start firezone-gateway
}
install-firezone )
"""
end