diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 468017499..6d99a6a4a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,3 +1,8 @@ +# We're running on a self-hosted runner, so only allow one workflow to run at a +# time. +# XXX: Remove this when self-hosted ephemeral runners are implmented. +concurrency: ci + name: CI on: - push diff --git a/apps/fz_http/lib/fz_http/devices.ex b/apps/fz_http/lib/fz_http/devices.ex index 3d0431e79..c4a47caa8 100644 --- a/apps/fz_http/lib/fz_http/devices.ex +++ b/apps/fz_http/lib/fz_http/devices.ex @@ -8,6 +8,7 @@ defmodule FzHttp.Devices do alias FzHttp.{Devices.Device, Repo, Users.User} @ipv4_prefix "10.3.2." + @ipv6_prefix "fd00:3:2::" def list_devices do Repo.all(Device) @@ -49,11 +50,15 @@ defmodule FzHttp.Devices do @ipv4_prefix <> Integer.to_string(device.address) end + def ipv6_address(%Device{} = device) do + @ipv6_prefix <> Integer.to_string(device.address) + end + def to_peer_list do for device <- Repo.all(Device) do %{ public_key: device.public_key, - allowed_ips: ipv4_address(device) + allowed_ips: "#{ipv4_address(device)}/32, #{ipv6_address(device)}/128" } end end diff --git a/apps/fz_http/lib/fz_http_web/live/device_live/index.html.heex b/apps/fz_http/lib/fz_http_web/live/device_live/index.html.heex index 8f9b9b26c..c7df50c50 100644 --- a/apps/fz_http/lib/fz_http_web/live/device_live/index.html.heex +++ b/apps/fz_http/lib/fz_http_web/live/device_live/index.html.heex @@ -20,7 +20,7 @@ <%= live_patch(device.name, to: Routes.device_show_path(@socket, :show, device)) %> - <%= FzHttp.Devices.ipv4_address(device) %> + <%= FzHttp.Devices.ipv4_address(device) %>, <%= FzHttp.Devices.ipv6_address(device) %> <%= device.public_key %> <% end %> diff --git a/apps/fz_http/lib/fz_http_web/live/device_live/index_live.ex b/apps/fz_http/lib/fz_http_web/live/device_live/index_live.ex index 811994f58..0ae0bbd0e 100644 --- a/apps/fz_http/lib/fz_http_web/live/device_live/index_live.ex +++ b/apps/fz_http/lib/fz_http_web/live/device_live/index_live.ex @@ -37,7 +37,7 @@ defmodule FzHttpWeb.DeviceLive.Index do {:ok, device} -> @events_module.device_created( device.public_key, - Devices.ipv4_address(device) + {Devices.ipv4_address(device), Devices.ipv6_address(device)} ) {:noreply, diff --git a/apps/fz_http/lib/fz_http_web/live/device_live/show.html.heex b/apps/fz_http/lib/fz_http_web/live/device_live/show.html.heex index 25f87ebf6..a60db4732 100644 --- a/apps/fz_http/lib/fz_http_web/live/device_live/show.html.heex +++ b/apps/fz_http/lib/fz_http_web/live/device_live/show.html.heex @@ -33,7 +33,7 @@
Interface IP:
-
<%= FzHttp.Devices.ipv4_address(@device) %>
+
<%= FzHttp.Devices.ipv4_address(@device) %>, <%= FzHttp.Devices.ipv6_address(@device) %>
Public key: @@ -72,7 +72,7 @@

 [Interface]
 PrivateKey = <%= @device.private_key %>
-Address = <%= FzHttp.Devices.ipv4_address(@device) %>
+Address = <%= FzHttp.Devices.ipv4_address(@device) %>/32, <%= FzHttp.Devices.ipv6_address(@device) %>/128
 DNS = 1.1.1.1, 1.0.0.1
 
 [Peer]
diff --git a/apps/fz_http/test/fz_http/devices_test.exs b/apps/fz_http/test/fz_http/devices_test.exs
index bb251bb4f..87f6e7f63 100644
--- a/apps/fz_http/test/fz_http/devices_test.exs
+++ b/apps/fz_http/test/fz_http/devices_test.exs
@@ -85,7 +85,7 @@ defmodule FzHttp.DevicesTest do
     test "renders all peers", %{device: device} do
       assert Devices.to_peer_list() |> List.first() == %{
                public_key: device.public_key,
-               allowed_ips: Devices.ipv4_address(device)
+               allowed_ips: "#{Devices.ipv4_address(device)}/32, #{Devices.ipv6_address(device)}/128"
              }
     end
   end
diff --git a/apps/fz_vpn/lib/fz_vpn/cli/live.ex b/apps/fz_vpn/lib/fz_vpn/cli/live.ex
index d4fb1548d..82ca4bfc5 100644
--- a/apps/fz_vpn/lib/fz_vpn/cli/live.ex
+++ b/apps/fz_vpn/lib/fz_vpn/cli/live.ex
@@ -33,8 +33,8 @@ defmodule FzVpn.CLI.Live do
     {privkey, pubkey(privkey)}
   end
 
-  def add_peer(pubkey, ip) do
-    set("peer #{pubkey} allowed-ips #{ip}")
+  def add_peer(pubkey, {ipv4, ipv6}) do
+    set("peer #{pubkey} allowed-ips #{ipv4}/32,#{ipv6}/128")
   end
 
   def delete_peer(pubkey) do
diff --git a/apps/fz_vpn/lib/fz_vpn/config.ex b/apps/fz_vpn/lib/fz_vpn/config.ex
index eb7d20cb0..b6fe1e84f 100644
--- a/apps/fz_vpn/lib/fz_vpn/config.ex
+++ b/apps/fz_vpn/lib/fz_vpn/config.ex
@@ -6,8 +6,8 @@ defmodule FzVpn.Config do
   # Render peers list into server config
   def render(config) do
     Enum.join(
-      for {public_key, ip} <- config do
-        "peer #{public_key} allowed-ips #{ip}"
+      for {public_key, {ipv4, ipv6}} <- config do
+        "peer #{public_key} allowed-ips #{ipv4}/32,#{ipv6}/128"
       end,
       " "
     )
diff --git a/apps/fz_vpn/lib/fz_vpn/server.ex b/apps/fz_vpn/lib/fz_vpn/server.ex
index 06de97f8f..dac629de3 100644
--- a/apps/fz_vpn/lib/fz_vpn/server.ex
+++ b/apps/fz_vpn/lib/fz_vpn/server.ex
@@ -62,9 +62,9 @@ defmodule FzVpn.Server do
   end
 
   @impl GenServer
-  def handle_cast({:device_created, pubkey, ip}, config) do
-    cli().add_peer(pubkey, ip)
-    {:noreply, Map.put(config, pubkey, ip)}
+  def handle_cast({:device_created, pubkey, inet}, config) do
+    cli().add_peer(pubkey, inet)
+    {:noreply, Map.put(config, pubkey, inet)}
   end
 
   @doc """
diff --git a/apps/fz_vpn/test/fz_vpn/config_test.exs b/apps/fz_vpn/test/fz_vpn/config_test.exs
index d7094e352..e50de1dd7 100644
--- a/apps/fz_vpn/test/fz_vpn/config_test.exs
+++ b/apps/fz_vpn/test/fz_vpn/config_test.exs
@@ -2,7 +2,7 @@ defmodule FzVpn.ConfigTest do
   use ExUnit.Case, async: true
   alias FzVpn.Config
 
-  @populated_config "peer test-pubkey allowed-ips test-allowed-ips"
+  @populated_config "peer test-pubkey allowed-ips test-ipv4/32,test-ipv6/128"
 
   describe "render" do
     test "renders default config" do
@@ -12,7 +12,7 @@ defmodule FzVpn.ConfigTest do
     end
 
     test "renders populated config" do
-      config = %{"test-pubkey" => "test-allowed-ips"}
+      config = %{"test-pubkey" => {"test-ipv4", "test-ipv6"}}
 
       assert Config.render(config) == @populated_config
     end
diff --git a/omnibus/cookbooks/firezone/recipes/network.rb b/omnibus/cookbooks/firezone/recipes/network.rb
index ee21079bb..762b60316 100644
--- a/omnibus/cookbooks/firezone/recipes/network.rb
+++ b/omnibus/cookbooks/firezone/recipes/network.rb
@@ -44,10 +44,18 @@ if wg_exists.status.exitstatus == 1
   end
 end
 
-execute 'setup_wireguard_ip' do
-  # XXX: Make this configurable
-  if_addr = '10.3.2.1/24'
-  command "ip address replace #{if_addr} dev #{wg_interface}"
+execute 'wireguard_ipv4' do
+  addr = '10.3.2.1/24'
+  command "ip address replace #{addr} dev #{wg_interface}"
+end
+
+execute 'wireguard_ipv6' do
+  addr = 'fd00:3:2::1/120'
+  command "ip -6 address replace #{addr} dev #{wg_interface}"
+end
+
+execute 'set_mtu' do
+  command "ip link set mtu 1420 up dev #{wg_interface}"
 end
 
 execute 'set_wireguard_interface_private_key' do
@@ -59,15 +67,15 @@ execute 'set_listen_port' do
   command "#{wg_path} set #{wg_interface} listen-port #{listen_port}"
 end
 
-execute 'set_mtu' do
-  command "ip link set mtu 1420 up dev #{wg_interface}"
-end
-
 route '10.3.2.0/24' do
   # XXX: Make this configurable
   device wg_interface
 end
 
+route 'fd00:3:2::0/120' do
+  device wg_interface
+end
+
 replace_or_add "IPv4 packet forwarding" do
   path "/etc/sysctl.conf"
   pattern "^#net.ipv4.ip_forward=1"