diff --git a/.ci/functional_test.sh b/.ci/functional_test.sh index e8b69335e..3b8634e5c 100755 --- a/.ci/functional_test.sh +++ b/.ci/functional_test.sh @@ -70,7 +70,7 @@ fi echo "Testing FzVpn.Interface module works with WireGuard" fz_bin="/opt/firezone/embedded/service/firezone/bin/firezone" ok_res=":ok" -set_interface=`sudo $fz_bin rpc "IO.inspect(FzVpn.Interface.set(\"wg-fz-test\", nil, %{}))"` +set_interface=`sudo $fz_bin rpc "IO.inspect(FzVpn.Interface.set(\"wg-fz-test\", %{}))"` del_interface=`sudo $fz_bin rpc "IO.inspect(FzVpn.Interface.delete(\"wg-fz-test\"))"` if [[ "$set_interface" != $ok_res || "$del_interface" != $ok_res ]]; then diff --git a/.env.sample b/.env.sample index eca42d26f..2d0802e57 100644 --- a/.env.sample +++ b/.env.sample @@ -18,7 +18,6 @@ PROXY_FORWARDED=true # export AUTH_OIDC="{\"google\":{\"discovery_document_uri\":\"https://accounts.google.com/.well-known/openid-configuration\",\"client_id\":\"1032390727302-u0lg90d3i1ive15lv7qgtbkka0hnsmgr.apps.googleusercontent.com\",\"client_secret\":\"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\",\"redirect_uri\":\"https://example.com/session\",\"response_type\":\"code\",\"scope\":\"openid email profile\",\"label\":\"Google\"},\"okta\":{\"discovery_document_uri\":\"https://accounts.google.com/.well-known/openid-configuration\",\"client_id\":\"CLIENT_ID\",\"client_secret\":\"CLIENT_SECRET\",\"redirect_uri\":\"https://example.com/session\",\"response_type\":\"code\",\"scope\":\"openid email profile\",\"label\":\"Okta\"}}" # Convenient overrides for live testing Firezone in dev -# WG_PATH=/path/to/wg # FZ_VPN_WGADAPTER_MODULE=FzVpn.Interface.WGAdapter.Live # NFT_PATH=/path/to/nft # EGRESS_INTERFACE=eth0 diff --git a/apps/fz_http/lib/fz_http/devices.ex b/apps/fz_http/lib/fz_http/devices.ex index 1bd0bbd5a..76e6c6da5 100644 --- a/apps/fz_http/lib/fz_http/devices.ex +++ b/apps/fz_http/lib/fz_http/devices.ex @@ -145,7 +145,13 @@ defmodule FzHttp.Devices do def as_config(device) do wireguard_port = Application.fetch_env!(:fz_vpn, :wireguard_port) - server_public_key = Application.fetch_env!(:fz_vpn, :wireguard_public_key) + server_public_key = Application.get_env(:fz_vpn, :wireguard_public_key) + + if is_nil(server_public_key) do + Logger.error( + "No server public key found! This will break device config generation. Is fz_vpn alive?" + ) + end """ [Interface] diff --git a/apps/fz_vpn/README.md b/apps/fz_vpn/README.md index 03a8a1f64..6922cac98 100644 --- a/apps/fz_vpn/README.md +++ b/apps/fz_vpn/README.md @@ -1,3 +1,3 @@ # FzVpn -Elixir/OTP frontend to `wg` cli. +Elixir/OTP frontend to WireGuard. diff --git a/apps/fz_vpn/lib/fz_vpn/interface.ex b/apps/fz_vpn/lib/fz_vpn/interface.ex index 1b6e875f0..123c421be 100644 --- a/apps/fz_vpn/lib/fz_vpn/interface.ex +++ b/apps/fz_vpn/lib/fz_vpn/interface.ex @@ -3,7 +3,6 @@ defmodule FzVpn.Interface do This module has functions to create interfaces, set configurations on them, and get peer info via [WireGuard](https://wireguard.com) """ - import FzCommon.CLI import FzVpn.Interface.WGAdapter alias Wireguardex.DeviceConfigBuilder @@ -12,41 +11,21 @@ defmodule FzVpn.Interface do require Logger @doc """ - Creates an interface with a name, listening port, ipv4 address, ipv6 address, - and MTU. + Set an interface by name with its peers. If the interface does not exist, it + will be created. - If successful `{:ok, {private_key, public_key}}` is returned. If the interface - creation fails, `{:error, error_info}` will be logged and returned. - """ - def create(name, listen_port, ipv4_address, ipv6_address, mtu) do - private_key = Wireguardex.generate_private_key() - public_key = Wireguardex.get_public_key(private_key) + ## Options - result = - DeviceConfigBuilder.device_config() - |> DeviceConfigBuilder.listen_port(listen_port) - |> DeviceConfigBuilder.private_key(private_key) - |> DeviceConfigBuilder.public_key(public_key) - |> wg_adapter().set_device(name) - - case result do - :ok -> - ip_cmds(name, ipv4_address, ipv6_address, mtu) - {:ok, {private_key, public_key}} - - {:error, error_info} -> - Logger.error("Failed to create interface #{name}: #{error_info}") - result - end - end - - @doc """ - Set an interface's private key and peers. + * `:private_key` - the interface's private key will be set + * `:listen_port - the interface's listening port will be set If successful we return an :ok status. If interface fails to be set, `{:error, error_info}` will be logged and returned. """ - def set(name, private_key, peers) do + def set(name, peers, opts \\ []) do + private_key = opts[:private_key] + listen_port = opts[:listen_port] + peer_configs = for {public_key, settings} <- peers do PeerConfigBuilder.peer_config() @@ -58,6 +37,7 @@ defmodule FzVpn.Interface do result = DeviceConfigBuilder.device_config() |> DeviceConfigBuilder.private_key(private_key) + |> DeviceConfigBuilder.listen_port(listen_port) |> DeviceConfigBuilder.peers(peer_configs) |> wg_adapter().set_device(name) @@ -78,7 +58,35 @@ defmodule FzVpn.Interface do retrieved, return `{:error, error_info}`. """ def get(name) do - wg_adapter().get_device(name) + result = wg_adapter().get_device(name) + + case result do + {:ok, device} -> + {:ok, device} + + {:error, error_info} -> + Logger.error("Failed to get interface #{name}: #{error_info}") + result + end + end + + @doc """ + Get a list of interface names. + + If successful we return `{:ok, [Device]}. If getting the list fails, return + '{:error, error_info}'. + """ + def list_names do + result = wg_adapter().list_devices() + + case result do + {:ok, iface_names} -> + {:ok, iface_names} + + {:error, error_info} -> + Logger.error("Failed to get list of interface names: #{error_info}") + result + end end @doc """ @@ -193,18 +201,4 @@ defmodule FzVpn.Interface do defp persistent_keepalive_to_str(n) when is_nil(n) or n == 0, do: "off" defp persistent_keepalive_to_str(n), do: to_string(n) - - defp ip_cmds(name, ipv4_address, ipv6_address, mtu) do - if !is_nil(ipv4_address) do - exec!("ip address replace #{ipv4_address} dev #{name}") - end - - if !is_nil(ipv6_address) do - exec!("ip -6 address replace #{ipv6_address} dev #{name}") - end - - if !is_nil(mtu) do - exec!("ip link set mtu #{mtu} up dev #{name}") - end - end end diff --git a/apps/fz_vpn/lib/fz_vpn/interface/wg_adapter/live.ex b/apps/fz_vpn/lib/fz_vpn/interface/wg_adapter/live.ex index 0a4b49869..beda35d30 100644 --- a/apps/fz_vpn/lib/fz_vpn/interface/wg_adapter/live.ex +++ b/apps/fz_vpn/lib/fz_vpn/interface/wg_adapter/live.ex @@ -5,6 +5,12 @@ defmodule FzVpn.Interface.WGAdapter.Live do use GenServer + defdelegate get_device(name), to: Wireguardex + defdelegate list_devices, to: Wireguardex + defdelegate set_device(config, name), to: Wireguardex + defdelegate delete_device(name), to: Wireguardex + defdelegate remove_peer(name, public_key), to: Wireguardex + # Stub out a GenServer start and init for now. # Track state around the WireGuard calls if needed later. @@ -12,20 +18,4 @@ defmodule FzVpn.Interface.WGAdapter.Live do @impl GenServer def init(_), do: {:ok, %{}} - - def get_device(name) do - Wireguardex.get_device(name) - end - - def set_device(config, name) do - Wireguardex.set_device(config, name) - end - - def delete_device(name) do - Wireguardex.delete_device(name) - end - - def remove_peer(name, public_key) do - Wireguardex.remove_peer(name, public_key) - end end diff --git a/apps/fz_vpn/lib/fz_vpn/interface/wg_adapter/sandbox.ex b/apps/fz_vpn/lib/fz_vpn/interface/wg_adapter/sandbox.ex index 29db297a6..2b3ae8962 100644 --- a/apps/fz_vpn/lib/fz_vpn/interface/wg_adapter/sandbox.ex +++ b/apps/fz_vpn/lib/fz_vpn/interface/wg_adapter/sandbox.ex @@ -13,6 +13,10 @@ defmodule FzVpn.Interface.WGAdapter.Sandbox do GenServer.call(__MODULE__, {:get_device, name}) end + def list_devices do + GenServer.call(__MODULE__, {:list_devices}) + end + def set_device(config, name) do GenServer.call(__MODULE__, {:set_device, config, name}) end @@ -35,11 +39,17 @@ defmodule FzVpn.Interface.WGAdapter.Sandbox do {:reply, {:ok, Map.get(devices, name)}, devices} end + @impl GenServer + def handle_call({:list_devices}, _from, devices) do + {:reply, {:ok, Map.keys(devices)}, devices} + end + @impl GenServer def handle_call({:set_device, config, name}, _from, devices) do public_key = if config.private_key do - Wireguardex.get_public_key(config.private_key) + {:ok, public_key} = Wireguardex.get_public_key(config.private_key) + public_key end peers = diff --git a/apps/fz_vpn/lib/fz_vpn/keypair.ex b/apps/fz_vpn/lib/fz_vpn/keypair.ex new file mode 100644 index 000000000..b663d2f62 --- /dev/null +++ b/apps/fz_vpn/lib/fz_vpn/keypair.ex @@ -0,0 +1,33 @@ +defmodule FzVpn.Keypair do + @moduledoc """ + Utilities for persisting / generating keypairs. + """ + + def load_or_generate_private_key do + path = Application.fetch_env!(:fz_vpn, :wireguard_private_key_path) + + private_key = + if File.exists?(path) && File.stat!(path).size > 0 do + File.read!(path) + |> String.trim() + else + key = Wireguardex.generate_private_key() + write_private_key(path, key) + key + end + + set_public_key(private_key) + private_key + end + + defp set_public_key(private_key) do + {:ok, public_key} = Wireguardex.get_public_key(private_key) + Application.put_env(:fz_vpn, :wireguard_public_key, public_key, persistent: true) + end + + defp write_private_key(path, private_key) do + File.touch!(path) + File.chmod!(path, 0o600) + File.write!(path, private_key) + end +end diff --git a/apps/fz_vpn/lib/fz_vpn/server.ex b/apps/fz_vpn/lib/fz_vpn/server.ex index a3c02b8d2..e4b96a171 100644 --- a/apps/fz_vpn/lib/fz_vpn/server.ex +++ b/apps/fz_vpn/lib/fz_vpn/server.ex @@ -7,6 +7,7 @@ defmodule FzVpn.Server do require Logger alias FzVpn.Interface + alias FzVpn.Keypair @process_opts Application.compile_env(:fz_vpn, :server_process_opts, []) @init_timeout 1_000 @@ -17,6 +18,7 @@ defmodule FzVpn.Server do @impl GenServer def init(_config) do + setup_interface() {:ok, peers} = GenServer.call(http_pid(), :load_peers, @init_timeout) config = peers_to_config(peers) apply_config_diff(config) @@ -56,6 +58,12 @@ defmodule FzVpn.Server do :global.whereis_name(:fz_http_server) end + defp setup_interface do + private_key = Keypair.load_or_generate_private_key() + listen_port = Application.fetch_env!(:fz_vpn, :wireguard_port) + Interface.set(iface_name(), %{}, private_key: private_key, listen_port: listen_port) + end + defp delete_old_peers(old_config, new_config) do for public_key <- Map.keys(old_config) -- Map.keys(new_config) do Interface.remove_peer(iface_name(), public_key) @@ -72,8 +80,8 @@ defmodule FzVpn.Server do end end - defp set_peers(config) do - Interface.set(iface_name(), nil, config) + defp set_peers(peers) do + Interface.set(iface_name(), peers) end defp peers_to_config(peers) do diff --git a/apps/fz_vpn/mix.exs b/apps/fz_vpn/mix.exs index e3462c92d..cbbbf11f3 100644 --- a/apps/fz_vpn/mix.exs +++ b/apps/fz_vpn/mix.exs @@ -43,7 +43,7 @@ defmodule FzVpn.MixProject do {:fz_common, in_umbrella: true}, {:credo, "~> 1.4", only: [:dev, :test], runtime: false}, {:excoveralls, "~> 0.13", only: :test}, - {:wireguardex, "~> 0.3.0"} + {:wireguardex, "~> 0.3.1"} ] end end diff --git a/apps/fz_vpn/test/fz_vpn/interface_test.exs b/apps/fz_vpn/test/fz_vpn/interface_test.exs index 954d8288c..1f242be76 100644 --- a/apps/fz_vpn/test/fz_vpn/interface_test.exs +++ b/apps/fz_vpn/test/fz_vpn/interface_test.exs @@ -2,24 +2,27 @@ defmodule FzVpn.InterfaceTest do use ExUnit.Case, async: true alias FzVpn.Interface + alias FzVpn.Server - test "create interface" do - name = "wg-create" - {:ok, key_pair} = Interface.create(name, nil, nil, nil, nil) - {private_key, public_key} = key_pair - {:ok, device} = Interface.get(name) - - assert device.name == name && device.private_key == private_key && - device.public_key == public_key + setup_all do + # remove the interface added on server init + :ok = Interface.delete(Server.iface_name()) end test "delete interface" do name = "wg-delete" - :ok = Interface.set(name, nil, []) - :ok = Interface.delete(name) - {:ok, device} = Interface.get(name) + :ok = Interface.set(name, %{}) - assert is_nil(device) + assert :ok == Interface.delete(name) + end + + test "list interface names" do + expected_names = ["wg0-list", "wg1-list"] + Enum.each(expected_names, fn name -> Interface.set(name, %{}) end) + {:ok, names} = Interface.list_names() + Enum.each(expected_names, fn name -> :ok = Interface.delete(name) end) + + assert names == expected_names end test "remove peer from interface" do @@ -33,9 +36,10 @@ defmodule FzVpn.InterfaceTest do } } - :ok = Interface.set(name, nil, peers) + :ok = Interface.set(name, peers) :ok = Interface.remove_peer(name, public_key) {:ok, device} = Interface.get(name) + :ok = Interface.delete(name) assert device.peers == [] end @@ -76,8 +80,9 @@ defmodule FzVpn.InterfaceTest do } } - :ok = Interface.set(name, nil, peers) + :ok = Interface.set(name, peers) interface_info = Interface.dump(name) + :ok = Interface.delete(name) assert interface_info == @expected_interface_info end diff --git a/config/config.exs b/config/config.exs index 2b3b40ede..e58a5f584 100644 --- a/config/config.exs +++ b/config/config.exs @@ -95,10 +95,9 @@ config :hammer, # This will be changed per-env config :fz_vpn, stats_push_service_enabled: true, - wireguard_psk_dir: "/tmp", - wireguard_public_key: "cB2yQeCxHO/qCH8APoM2D2Anf4Yd7sRLyfS7su71K3M=", + wireguard_private_key_path: "priv/.wg_dummy_private_key", wireguard_interface_name: "wg-firezone", - wireguard_port: "51820", + wireguard_port: 51820, wireguard_endpoint: "127.0.0.1", wg_adapter: FzVpn.Interface.WGAdapter.Sandbox, server_process_opts: [name: {:global, :fz_vpn_server}] diff --git a/config/runtime.exs b/config/runtime.exs index 9884de8eb..8178b671f 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -35,12 +35,11 @@ if config_env() == :prod do phoenix_port = String.to_integer(System.fetch_env!("PHOENIX_PORT")) admin_email = System.fetch_env!("ADMIN_EMAIL") default_admin_password = System.fetch_env!("DEFAULT_ADMIN_PASSWORD") + wireguard_private_key_path = System.fetch_env!("WIREGUARD_PRIVATE_KEY_PATH") wireguard_interface_name = System.fetch_env!("WIREGUARD_INTERFACE_NAME") wireguard_port = String.to_integer(System.fetch_env!("WIREGUARD_PORT")) nft_path = System.fetch_env!("NFT_PATH") egress_interface = System.fetch_env!("EGRESS_INTERFACE") - wireguard_public_key = System.fetch_env!("WIREGUARD_PUBLIC_KEY") - wireguard_psk_dir = System.fetch_env!("WIREGUARD_PSK_DIR") wireguard_dns = System.get_env("WIREGUARD_DNS") wireguard_allowed_ips = System.fetch_env!("WIREGUARD_ALLOWED_IPS") wireguard_persistent_keepalive = System.fetch_env!("WIREGUARD_PERSISTENT_KEEPALIVE") @@ -177,8 +176,7 @@ if config_env() == :prod do cli: FzWall.CLI.Live config :fz_vpn, - wireguard_psk_dir: wireguard_psk_dir, - wireguard_public_key: wireguard_public_key, + wireguard_private_key_path: wireguard_private_key_path, wireguard_interface_name: wireguard_interface_name, wireguard_port: wireguard_port diff --git a/mix.lock b/mix.lock index 322945691..ff5ab13c7 100644 --- a/mix.lock +++ b/mix.lock @@ -79,5 +79,5 @@ "ueberauth_keycloak_strategy": {:git, "https://github.com/firezone/ueberauth_keycloak.git", "8a028d6c949604b25a083d4137affa0472ff919c", []}, "ueberauth_okta": {:hex, :ueberauth_okta, "0.3.0", "236175e9f6bd5b13fcefc9f291b74e380a5698a4b699105b6e74f2747c137363", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}, {:oauth2, "~> 2.0", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.7", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "f871dc6f41da34ea4d3cbc6cad3f8c4f2ebf7b5d3fef38f861ca99ecae3607b2"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, - "wireguardex": {:hex, :wireguardex, "0.3.0", "d0b029a7c9ccce22575f576b462d3236355129f3eee0b2e1587eab3bce9188b3", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.5.1", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "0e1165dcff67da443e7ef56a9be0d59cf48aaadfaa3e551c20012f0144ccd152"}, + "wireguardex": {:hex, :wireguardex, "0.3.1", "2924d96fcb38f66a13382edc4b405da9b64177862e4e1db3e4fa7634577e50a4", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.5.1", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "800d4d4122de2f140cd289272c181fe09a455a51cf85ca248f981cd3bdb2e2ac"}, } diff --git a/omnibus/config/projects/firezone.rb b/omnibus/config/projects/firezone.rb index 7ed08f4c3..107facb1e 100644 --- a/omnibus/config/projects/firezone.rb +++ b/omnibus/config/projects/firezone.rb @@ -44,7 +44,6 @@ dependency 'erlang' dependency 'elixir' dependency 'openssl' dependency 'postgresql' -dependency 'wireguard-tools' dependency 'firezone' dependency 'firezone-ctl' dependency 'firezone-scripts' diff --git a/omnibus/config/software/wireguard-tools.rb b/omnibus/config/software/wireguard-tools.rb deleted file mode 100644 index 8ce351ad5..000000000 --- a/omnibus/config/software/wireguard-tools.rb +++ /dev/null @@ -1,45 +0,0 @@ -# rubocop:disable Naming/FileName -# frozen_string_literal: true - -# Copyright 2021 Firezone -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -name 'wireguard-tools' -description 'wireguard userspace utilities' -default_version '1.0.20210424' - -default_src_url = "https://github.com/WireGuard/wireguard-tools/archive/refs/tags/v#{version}.tar.gz" - -version '1.0.20210424' do - source url: default_src_url, sha256: '6b32b5deba067b9a920f008a006f001fa1ec903dc69fcaa5674b5a043146c1f7' -end - -relative_path "wireguard-tools-#{version}/src" -license 'GPL-2.0' - -build do - env = with_standard_compiler_flags(with_embedded_path).merge( - 'PREFIX' => "#{install_dir}/embedded", - 'WITH_BASHCOMPLETION' => 'no', - 'WITH_SYSTEMDUNITS' => 'no', - 'WITH_WGQUICK' => 'no', - 'SYSCONFDIR' => '/etc/firezone', - 'RUNSTATEDIR' => '/var/opt/firezone/run' - ) - - make "-j #{workers}", env: env - make "-j #{workers} install", env: env -end -# rubocop:enable Naming/FileName diff --git a/omnibus/cookbooks/firezone/libraries/config.rb b/omnibus/cookbooks/firezone/libraries/config.rb index 0f201abf0..9169d1ffe 100644 --- a/omnibus/cookbooks/firezone/libraries/config.rb +++ b/omnibus/cookbooks/firezone/libraries/config.rb @@ -116,8 +116,6 @@ class Firezone 'cookie_signing_salt' => node['firezone'] && node['firezone']['cookie_signing_salt'] || SecureRandom.base64(6), 'cookie_encryption_salt' => node['firezone'] && node['firezone']['cookie_encryption_salt'] || \ SecureRandom.base64(6), - 'wireguard_private_key' => node['firezone'] && node['firezone']['wireguard_private_key'] || \ - `#{node['firezone']['install_directory']}/embedded/bin/wg genkey`.chomp, 'database_encryption_key' => node['firezone'] && node['firezone']['database_encryption_key'] || \ SecureRandom.base64(32), 'default_admin_password' => node['firezone'] && node['firezone']['default_admin_password'] || \ @@ -215,7 +213,6 @@ class Firezone # NOTE: All these variables must be Strings env = { 'EGRESS_INTERFACE' => attributes['egress_interface'], - 'WG_PATH' => "#{attributes['install_directory']}/embedded/bin/wg", 'NFT_PATH' => "#{attributes['install_directory']}/embedded/sbin/nft", 'MIX_ENV' => 'prod', 'DATABASE_NAME' => attributes['database']['name'], @@ -237,8 +234,6 @@ class Firezone 'WIREGUARD_DNS' => attributes['wireguard']['dns'].to_s, 'WIREGUARD_ALLOWED_IPS' => attributes['wireguard']['allowed_ips'].to_s, 'WIREGUARD_PERSISTENT_KEEPALIVE' => attributes['wireguard']['persistent_keepalive'].to_s, - 'WIREGUARD_PUBLIC_KEY' => attributes['wireguard_public_key'], - 'WIREGUARD_PSK_DIR' => "#{attributes['var_directory']}/cache/psks", 'WIREGUARD_IPV4_ENABLED' => attributes['wireguard']['ipv4']['enabled'].to_s, 'WIREGUARD_IPV4_NETWORK' => attributes['wireguard']['ipv4']['network'], 'WIREGUARD_IPV4_ADDRESS' => attributes['wireguard']['ipv4']['address'], @@ -259,6 +254,10 @@ class Firezone 'OUTBOUND_EMAIL_CONFIGS' => attributes['outbound_email']['configs'].to_json, 'OUTBOUND_EMAIL_FROM' => attributes['outbound_email']['from'], + # XXX: Remove this in the future when we're fairly sure that users won't upgrade across + # the <= 0.4.4 to >= 0.4.5 version boundary. + 'WIREGUARD_PRIVATE_KEY_PATH' => "#{node['firezone']['var_directory']}/cache/wg_private_key", + # Auth 'LOCAL_AUTH_ENABLED' => attributes['authentication']['local']['enabled'].to_s, 'OKTA_AUTH_ENABLED' => attributes['authentication']['okta']['enabled'].to_s, diff --git a/omnibus/cookbooks/firezone/recipes/config.rb b/omnibus/cookbooks/firezone/recipes/config.rb index 3e99f2c97..94868369e 100644 --- a/omnibus/cookbooks/firezone/recipes/config.rb +++ b/omnibus/cookbooks/firezone/recipes/config.rb @@ -40,10 +40,6 @@ Firezone::Config.load_or_create_secrets!( node ) -pkey = node['firezone']['wireguard_private_key'] -wg = "#{node['firezone']['install_directory']}/embedded/bin/wg" -node.default['firezone']['wireguard_public_key'] = `echo '#{pkey}' | #{wg} pubkey`.chomp - Firezone::Config.audit_config(node['firezone']) Firezone::Config.maybe_turn_on_fips(node) @@ -103,15 +99,7 @@ file "#{node['firezone']['config_directory']}/secrets.json" do end file "#{node['firezone']['var_directory']}/cache/wg_private_key" do - owner 'root' - group 'root' - mode '0600' - content node['firezone']['wireguard_private_key'] - action :create_if_missing -end - -directory "#{node['firezone']['var_directory']}/cache/psks" do - owner 'root' + owner node['firezone']['user'] group node['firezone']['group'] - mode '0770' + mode '0600' end diff --git a/omnibus/cookbooks/firezone/recipes/setcap.rb b/omnibus/cookbooks/firezone/recipes/setcap.rb index 8926bc717..f2f4839b6 100644 --- a/omnibus/cookbooks/firezone/recipes/setcap.rb +++ b/omnibus/cookbooks/firezone/recipes/setcap.rb @@ -11,7 +11,6 @@ include_recipe 'firezone::config' nft_path = "#{node['firezone']['install_directory']}/embedded/sbin/nft" -wg_path = "#{node['firezone']['install_directory']}/embedded/bin/wg" file nft_path do # Ensure phoenix app can control nftables @@ -21,20 +20,8 @@ file nft_path do action :touch end -file wg_path do - # Ensure phoenix app can control WireGuard interface - mode '0700' - owner node['firezone']['user'] - group node['firezone']['group'] - action :touch -end - # setcap must be performed after the file resource above otherwise # it gets reset execute 'setcap_nft' do command "setcap 'cap_net_admin,cap_net_raw+eip' #{nft_path}" end - -execute 'setcap_wg' do - command "setcap 'cap_net_admin,cap_net_raw,cap_dac_read_search+eip' #{wg_path}" -end diff --git a/omnibus/cookbooks/firezone/templates/sv-wireguard-run.erb b/omnibus/cookbooks/firezone/templates/sv-wireguard-run.erb index b42d52ff4..49884c863 100644 --- a/omnibus/cookbooks/firezone/templates/sv-wireguard-run.erb +++ b/omnibus/cookbooks/firezone/templates/sv-wireguard-run.erb @@ -3,8 +3,6 @@ exec 2>&1 <%= "export OPENSSL_FIPS=1" if node['firezone']['fips_enabled'] == true %> export WIREGUARD_INTERFACE_NAME=<%= node['firezone']['wireguard']['interface_name'] %> -export WG_PATH=<%= node['firezone']['install_directory'] %>/embedded/bin/wg -export WIREGUARD_PRIVATE_KEY_PATH=<%= node['firezone']['var_directory'] %>/cache/wg_private_key export WIREGUARD_IPV4_ENABLED=<%= node['firezone']['wireguard']['ipv4']['enabled'] %> export WIREGUARD_IPV4_ADDRESS=<%= node['firezone']['wireguard']['ipv4']['address'] %> export WIREGUARD_IPV4_NETWORK=<%= node['firezone']['wireguard']['ipv4']['network'] %> diff --git a/omnibus/files/firezone-scripts/wireguard b/omnibus/files/firezone-scripts/wireguard index 0c7ae47c2..de1466817 100755 --- a/omnibus/files/firezone-scripts/wireguard +++ b/omnibus/files/firezone-scripts/wireguard @@ -22,8 +22,6 @@ setup_interface() ip -6 address replace ${WIREGUARD_IPV6_ADDRESS} dev ${WIREGUARD_INTERFACE_NAME} fi ip link set mtu ${WIREGUARD_INTERFACE_MTU} up dev ${WIREGUARD_INTERFACE_NAME} - ${WG_PATH} set ${WIREGUARD_INTERFACE_NAME} private-key ${WIREGUARD_PRIVATE_KEY_PATH} - ${WG_PATH} set ${WIREGUARD_INTERFACE_NAME} listen-port ${WIREGUARD_LISTEN_PORT} } add_routes() diff --git a/priv/.wg_dummy_private_key b/priv/.wg_dummy_private_key new file mode 100644 index 000000000..3721eb35c --- /dev/null +++ b/priv/.wg_dummy_private_key @@ -0,0 +1 @@ +wIq2WRxCctZAt9WB642jTTl/HFys9Ntht033s/0YKXI=