From 2e1afa6e79b548ae1fa57dd4fd2dbb9388610906 Mon Sep 17 00:00:00 2001 From: Jamil Bou Kheir Date: Sat, 26 Dec 2020 12:12:20 -0600 Subject: [PATCH] read pubkey from wireguard privkey --- apps/fg_vpn/lib/fg_vpn/cli.ex | 7 +++++++ apps/fg_vpn/lib/fg_vpn/config.ex | 14 +++++++++++--- apps/fg_vpn/test/fg_vpn/cli_test.exs | 6 ++++++ apps/fg_vpn/test/fg_vpn/config_test.exs | 12 ++++++++---- config/releases.exs | 11 +++-------- pkg/debian/DEBIAN/postinst | 25 +------------------------ 6 files changed, 36 insertions(+), 39 deletions(-) diff --git a/apps/fg_vpn/lib/fg_vpn/cli.ex b/apps/fg_vpn/lib/fg_vpn/cli.ex index 13f8b7273..57c082057 100644 --- a/apps/fg_vpn/lib/fg_vpn/cli.ex +++ b/apps/fg_vpn/lib/fg_vpn/cli.ex @@ -58,6 +58,13 @@ defmodule FgVpn.CLI do {privkey, pubkey} end + def pubkey(privkey) when is_nil(privkey), do: nil + + def pubkey(privkey) when is_binary(privkey) do + exec("echo #{privkey} | wg pubkey") + |> String.trim() + end + defp exec(cmd) do case System.cmd("bash", ["-c", cmd]) do {result, 0} -> diff --git a/apps/fg_vpn/lib/fg_vpn/config.ex b/apps/fg_vpn/lib/fg_vpn/config.ex index 8ba0d7c81..10b1ce44a 100644 --- a/apps/fg_vpn/lib/fg_vpn/config.ex +++ b/apps/fg_vpn/lib/fg_vpn/config.ex @@ -55,6 +55,7 @@ defmodule FgVpn.Config do def read_privkey do read_config_file() |> extract_privkey() + |> (&{&1, CLI.pubkey(&1)}).() end defp extract_privkey(config_str) do @@ -95,10 +96,14 @@ defmodule FgVpn.Config do end defp interface_to_config(config) do - # XXX: Use config listen_port here + listen_port = + Application.get_env(:fg_http, :vpn_endpoint) + |> String.split(":") + |> List.last() + ~s""" [Interface] - ListenPort = 51820 + ListenPort = #{listen_port} PrivateKey = #{config[:privkey]} PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o #{ config[:default_int] @@ -136,13 +141,16 @@ defmodule FgVpn.Config do end defp read_and_rewrite_config do + {privkey, pubkey} = read_privkey() || CLI.genkey() + config = %{ default_int: CLI.default_interface(), - privkey: read_privkey() || elem(CLI.genkey(), 0), + privkey: privkey, peers: read_peers() || [] } write!(config) + Application.put_env(:fg_vpn, :pubkey, pubkey) config end diff --git a/apps/fg_vpn/test/fg_vpn/cli_test.exs b/apps/fg_vpn/test/fg_vpn/cli_test.exs index 9b4e0a401..8e6a6803d 100644 --- a/apps/fg_vpn/test/fg_vpn/cli_test.exs +++ b/apps/fg_vpn/test/fg_vpn/cli_test.exs @@ -13,4 +13,10 @@ defmodule FgVpn.CLITest do assert is_binary(privkey) assert is_binary(pubkey) end + + test "pubkey" do + {privkey, pubkey} = CLI.genkey() + + assert pubkey == CLI.pubkey(privkey) + end end diff --git a/apps/fg_vpn/test/fg_vpn/config_test.exs b/apps/fg_vpn/test/fg_vpn/config_test.exs index 8bb1f5cff..33d0e949a 100644 --- a/apps/fg_vpn/test/fg_vpn/config_test.exs +++ b/apps/fg_vpn/test/fg_vpn/config_test.exs @@ -2,6 +2,8 @@ defmodule FgVpn.ConfigTest do use ExUnit.Case, async: true alias FgVpn.Config + @test_privkey "GMqk2P3deotcQqgqJHfLGB1JtU//f1FgX868bfPKSVc=" + @empty """ """ @@ -16,16 +18,18 @@ defmodule FgVpn.ConfigTest do @privkey """ [Interface] ListenPort = 51820 - PrivateKey = test-privkey + PrivateKey = GMqk2P3deotcQqgqJHfLGB1JtU//f1FgX868bfPKSVc= """ + @rendered_privkey "kPCNOTbBoHC/j5daxhMHcZ+PeNr6oaA8qIWcBuFlM0s=" + @rendered_config """ # This file is being managed by the fireguard systemd service. Any changes # will be overwritten eventually. [Interface] ListenPort = 51820 - PrivateKey = rendered-privkey + PrivateKey = kPCNOTbBoHC/j5daxhMHcZ+PeNr6oaA8qIWcBuFlM0s= PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o noop -j MASQUERADE PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o noop -j MASQUERADE @@ -59,7 +63,7 @@ defmodule FgVpn.ConfigTest do assert %{ peers: [], default_int: _, - privkey: "test-privkey" + privkey: @test_privkey } = :sys.get_state(test_pid) end @@ -105,7 +109,7 @@ defmodule FgVpn.ConfigTest do test "renders config" do assert Config.render(%{ default_int: "noop", - privkey: "rendered-privkey", + privkey: @rendered_privkey, peers: ["test-pubkey"] }) == @rendered_config end diff --git a/config/releases.exs b/config/releases.exs index 1bdc1bac4..4cf514e6a 100644 --- a/config/releases.exs +++ b/config/releases.exs @@ -28,13 +28,6 @@ live_view_signing_salt = /opt/fireguard/config.env """ -pubkey = - System.get_env("PUBKEY") || - raise """ - Environment variable PUBKEY is missing. Please generate - with the "wg" utility. - """ - ssl_cert_file = System.get_env("SSL_CERT_FILE") || raise """ @@ -66,7 +59,9 @@ wg_listen_port = System.get_env("WG_LISTEN_PORT" || "51820") wg_listen_address = System.get_env("WG_LISTEN_ADDRESS") || "localhost" url_host = System.get_env("URL_HOST") || "localhost" -config :fg_vpn, pubkey: pubkey +# Will be replaced when FgVpn starts up and config is rewritten +config :fg_vpn, pubkey: nil + config :fg_http, disable_signup: disable_signup config :fg_http, FgHttp.Repo, diff --git a/pkg/debian/DEBIAN/postinst b/pkg/debian/DEBIAN/postinst index 171c712f0..df88e8c46 100755 --- a/pkg/debian/DEBIAN/postinst +++ b/pkg/debian/DEBIAN/postinst @@ -29,9 +29,8 @@ sudo -i -u postgres psql -c "CREATE ROLE ${db_user} WITH LOGIN PASSWORD '${db_pa sudo -i -u postgres psql -c "CREATE DATABASE fireguard;" || true sudo -i -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE fireguard to ${db_user};" || true -# Generate WireGuard priv/pubkeys +# Generate WireGuard privkey privkey=$(wg genkey) -pubkey=$(echo ${privkey} | wg pubkey) # Write FireGuard SSL files mkdir -p /opt/fireguard/ssl @@ -67,12 +66,6 @@ SECRET_KEY_BASE="${secret_key_base}" # user has privileges to create and modify tables. DATABASE_URL="ecto://${db_user}:${db_password}@127.0.0.1/fireguard" -# The public key for the WireGuard interface controlled by FireGuard. -# This should match what's in the WireGuard config at -# /etc/wireguard/wg-fireguard.conf. -# Re-generate this using the "wg" utility, e.g. "wg genkey | wg pubkey" -PUBKEY="${pubkey}" - # The HTTPS port to listen on. Defaults to 8800. HTTPS_LISTEN_PORT=8800 @@ -102,21 +95,5 @@ URL_HOST=${hostname} DISABLE_SIGNUP=yes EOT -# Grab default route interface -default_int=$(route | grep '^default' | grep -o '[^ ]*$') - -# Write WireGuard config file -# XXX: Figure out whether to write config using postinst script or via Elixir -# process. Elixir process decouples packaging logic from configuration -# management a bit more. -cat <> /opt/fireguard/wg-fireguard.conf -[Interface] -ListenPort = 51820 -PrivateKey = ${privkey} -PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ${default_int} -j MASQUERADE -PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ${default_int} -j MASQUERADE - -EOT - systemctl enable fireguard systemctl start fireguard