diff --git a/apps/fg_http/lib/fg_http/application.ex b/apps/fg_http/lib/fg_http/application.ex index 3039d8b6e..f805eaadf 100644 --- a/apps/fg_http/lib/fg_http/application.ex +++ b/apps/fg_http/lib/fg_http/application.ex @@ -9,11 +9,15 @@ defmodule FgHttp.Application do children = case Application.get_env(:fg_http, :minimal) do true -> - [FgHttp.Repo] + [ + FgHttp.Repo, + FgHttp.Vault + ] _ -> [ FgHttp.Repo, + FgHttp.Vault, {Phoenix.PubSub, name: FgHttp.PubSub}, FgHttpWeb.Endpoint ] diff --git a/apps/fg_http/lib/fg_http/devices/device.ex b/apps/fg_http/lib/fg_http/devices/device.ex index 04dcca366..1e65a6ec8 100644 --- a/apps/fg_http/lib/fg_http/devices/device.ex +++ b/apps/fg_http/lib/fg_http/devices/device.ex @@ -12,9 +12,9 @@ defmodule FgHttp.Devices.Device do field :name, :string field :public_key, :string field :allowed_ips, :string - field :preshared_key, :string + field :preshared_key, FgHttp.Encrypted.Binary + field :private_key, FgHttp.Encrypted.Binary field :server_public_key, :string - field :private_key, :string field :last_ip, EctoNetwork.INET field :last_seen_at, :utc_datetime_usec diff --git a/apps/fg_http/lib/fg_http/encrypted/binary.ex b/apps/fg_http/lib/fg_http/encrypted/binary.ex new file mode 100644 index 000000000..34f4e5673 --- /dev/null +++ b/apps/fg_http/lib/fg_http/encrypted/binary.ex @@ -0,0 +1,7 @@ +defmodule FgHttp.Encrypted.Binary do + @moduledoc """ + Configures how to encrpyt Binaries to the DB. + """ + + use Cloak.Ecto.Binary, vault: FgHttp.Vault +end diff --git a/apps/fg_http/lib/fg_http/vault.ex b/apps/fg_http/lib/fg_http/vault.ex new file mode 100644 index 000000000..8ab5ced69 --- /dev/null +++ b/apps/fg_http/lib/fg_http/vault.ex @@ -0,0 +1,7 @@ +defmodule FgHttp.Vault do + @moduledoc """ + Manages encrypted DB fields. + """ + + use Cloak.Vault, otp_app: :fg_http +end diff --git a/apps/fg_http/mix.exs b/apps/fg_http/mix.exs index 0aa6d40d9..e4bf53e3e 100644 --- a/apps/fg_http/mix.exs +++ b/apps/fg_http/mix.exs @@ -45,6 +45,7 @@ defmodule FgHttp.MixProject do defp deps do [ {:phoenix, "~> 1.5"}, + {:cloak_ecto, "~> 1.1"}, {:excoveralls, "~> 0.13", only: :test}, {:floki, ">= 0.0.0", only: :test}, {:argon2_elixir, "~> 2.0"}, diff --git a/apps/fg_http/priv/repo/migrations/20200228145810_create_devices.exs b/apps/fg_http/priv/repo/migrations/20200228145810_create_devices.exs index 0b210ab17..90d613bd6 100644 --- a/apps/fg_http/priv/repo/migrations/20200228145810_create_devices.exs +++ b/apps/fg_http/priv/repo/migrations/20200228145810_create_devices.exs @@ -6,8 +6,8 @@ defmodule FgHttp.Repo.Migrations.CreateDevices do add :name, :string, null: false add :public_key, :string, null: false add :allowed_ips, :string - add :preshared_key, :string, null: false - add :private_key, :string, null: false + add :preshared_key, :bytea, null: false + add :private_key, :bytea, null: false add :server_public_key, :string, null: false add :last_ip, :inet add :user_id, references(:users, on_delete: :delete_all), null: false diff --git a/config/dev.exs b/config/dev.exs index 87c2649ad..ce768f21d 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -88,3 +88,19 @@ config :phoenix, :stacktrace_depth, 20 # Initialize plugs at runtime for faster development compilation config :phoenix, :plug_init_mode, :runtime config :fg_vpn, :server_process_opts, name: {:global, :fg_vpn_server} + +config :fg_http, FgHttp.Vault, + ciphers: [ + default: { + Cloak.Ciphers.AES.GCM, + # In AES.GCM, it is important to specify 12-byte IV length for + # interoperability with other encryption software. See this GitHub + # issue for more details: + # https://github.com/danielberkompas/cloak/issues/93 + # + # In Cloak 2.0, this will be the default iv length for AES.GCM. + tag: "AES.GCM.V1", + key: Base.decode64!("XXJ/NGevpvkG9219RYsz21zZWR7CZ//CqA0ARPIBqys="), + iv_length: 12 + } + ] diff --git a/config/releases.exs b/config/releases.exs index 30576f3e6..9d8727d5f 100644 --- a/config/releases.exs +++ b/config/releases.exs @@ -99,6 +99,23 @@ config :fg_vpn, # to start each relevant endpoint: # config :fg_http, FgHttpWeb.Endpoint, server: true + +config :fg_http, FgHttp.Vault, + ciphers: [ + default: { + Cloak.Ciphers.AES.GCM, + # In AES.GCM, it is important to specify 12-byte IV length for + # interoperability with other encryption software. See this GitHub + # issue for more details: + # https://github.com/danielberkompas/cloak/issues/93 + # + # In Cloak 2.0, this will be the default iv length for AES.GCM. + tag: "AES.GCM.V1", + key: Base.decode64!(System.fetch_env!("WG_ENCRYPTION_KEY")), + iv_length: 12 + } + ] + # # Then you can assemble a release by calling `mix release`. # See `mix help release` for more information. diff --git a/config/test.exs b/config/test.exs index 0b757d273..d365336ab 100644 --- a/config/test.exs +++ b/config/test.exs @@ -44,3 +44,19 @@ config :logger, level: :warn config :fg_vpn, execute_iface_cmds: System.get_env("CI") === "true" + +config :fg_http, FgHttp.Vault, + ciphers: [ + default: { + Cloak.Ciphers.AES.GCM, + # In AES.GCM, it is important to specify 12-byte IV length for + # interoperability with other encryption software. See this GitHub + # issue for more details: + # https://github.com/danielberkompas/cloak/issues/93 + # + # In Cloak 2.0, this will be the default iv length for AES.GCM. + tag: "AES.GCM.V1", + key: Base.decode64!("XXJ/NGevpvkG9219RYsz21zZWR7CZ//CqA0ARPIBqys="), + iv_length: 12 + } + ] diff --git a/mix.lock b/mix.lock index 31967cf2a..8f0f03193 100644 --- a/mix.lock +++ b/mix.lock @@ -3,6 +3,8 @@ "bamboo": {:hex, :bamboo, "1.7.1", "7f0946e8c9081ce10d347cdba33c247c7c1c4f7dddc194ab0633603ef879bbdf", [:mix], [{:hackney, ">= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.4", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.1", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "5fb34c3ab638fc409deec47c1e91f9d78ad95bf22ccb153588b434e1ff1aa730"}, "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, "certifi": {:hex, :certifi, "2.5.3", "70bdd7e7188c804f3a30ee0e7c99655bc35d8ac41c23e12325f36ab449b70651", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "ed516acb3929b101208a9d700062d520f3953da3b6b918d866106ffa980e1c10"}, + "cloak": {:hex, :cloak, "1.0.3", "af8acef9e08e744441e961921c95a660074f9689892e18445ad8a60d5059aa10", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:pbkdf2, "~> 2.0", [hex: :pbkdf2, repo: "hexpm", optional: true]}], "hexpm", "130afd15b845f4cabb0be8df64ec93a59ff30657c539d454f7f747145c4e2452"}, + "cloak_ecto": {:hex, :cloak_ecto, "1.1.1", "ca5aa80182da821beb5f893139f89cd8e6247e16545e773cb642d94f0f30ec4f", [:mix], [{:cloak, "~> 1.0.0", [hex: :cloak, repo: "hexpm", optional: false]}, {:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:pbkdf2, "~> 2.0", [hex: :pbkdf2, repo: "hexpm", optional: true]}], "hexpm", "6c28f3e5319cd3f1d7c433e8acfe00460602f0d7d690c5d4c1679c8d89e39526"}, "comeonin": {:hex, :comeonin, "5.3.2", "5c2f893d05c56ae3f5e24c1b983c2d5dfb88c6d979c9287a76a7feb1e1d8d646", [:mix], [], "hexpm", "d0993402844c49539aeadb3fe46a3c9bd190f1ecf86b6f9ebd71957534c95f04"}, "connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, "cowboy": {:hex, :cowboy, "2.8.0", "f3dc62e35797ecd9ac1b50db74611193c29815401e53bac9a5c0577bd7bc667d", [:rebar3], [{:cowlib, "~> 2.9.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "4643e4fba74ac96d4d152c75803de6fad0b3fa5df354c71afdd6cbeeb15fac8a"}, diff --git a/pkg/ubuntu-20.04/DEBIAN/postinst b/pkg/ubuntu-20.04/DEBIAN/postinst index 8acb5babe..66ed8fba9 100755 --- a/pkg/ubuntu-20.04/DEBIAN/postinst +++ b/pkg/ubuntu-20.04/DEBIAN/postinst @@ -24,6 +24,8 @@ db_user=fireguard # DB_URL connect string, so use hex. db_password="$(openssl rand -hex 16)" +db_key="$(openssl rand -base64 32)" + # Setup DB sudo -i -u postgres psql -c "CREATE ROLE ${db_user} WITH LOGIN PASSWORD '${db_password}';" || true sudo -i -u postgres psql -c "CREATE DATABASE fireguard;" || true @@ -74,6 +76,9 @@ WG_LISTEN_PORT=51820 # default egress interface if not set. WG_ENDPOINT_ADDRESS= +# The Base64-encoded key for encrypted database fields. +WG_ENCRYPTION_KEY=${db_key} + # SSL certificate file and key path. Self-signed certs are generated for you on # install, but it's highly recommended to replace these with valid certs. # Free certs can be obtained at https://letsencrypt.org.