From 58e48457ad1cd75bd39e7e8d3cfe730f6dc931d7 Mon Sep 17 00:00:00 2001
From: Jamil
Date: Wed, 3 Aug 2022 12:34:30 -0700
Subject: [PATCH] Revert "Add initial rough version of port based rules (#874)"
(#888)
This reverts commit 55a311adecddac5472e77af7ac655bc197d16158.
---
apps/fz_http/lib/fz_http/int4range.ex | 90 -----------
apps/fz_http/lib/fz_http/rules.ex | 10 +-
apps/fz_http/lib/fz_http/rules/rule.ex | 24 +--
.../fz_http/lib/fz_http/rules/rule_setting.ex | 8 +-
.../live/rule_live/rule_list_component.ex | 22 +--
.../rule_live/rule_list_component.html.heex | 35 +---
.../20220726205646_add_rule_port_range.exs | 51 ------
apps/fz_http/test/fz_http/events_test.exs | 25 +--
.../test/fz_http/repo/notifier_test.exs | 10 +-
apps/fz_http/test/fz_http/rules_test.exs | 59 -------
apps/fz_http/test/support/test_helpers.ex | 6 -
apps/fz_wall/lib/fz_wall/cli/helpers/nft.ex | 145 ++++-------------
apps/fz_wall/lib/fz_wall/cli/helpers/sets.ex | 52 ++----
apps/fz_wall/lib/fz_wall/cli/live.ex | 151 ++++++++++--------
apps/fz_wall/lib/fz_wall/cli/sandbox.ex | 1 +
.../fz_wall/test/fz_wall/cli/sandbox_test.exs | 4 +
16 files changed, 142 insertions(+), 551 deletions(-)
delete mode 100644 apps/fz_http/lib/fz_http/int4range.ex
delete mode 100644 apps/fz_http/priv/repo/migrations/20220726205646_add_rule_port_range.exs
diff --git a/apps/fz_http/lib/fz_http/int4range.ex b/apps/fz_http/lib/fz_http/int4range.ex
deleted file mode 100644
index 8f489273b..000000000
--- a/apps/fz_http/lib/fz_http/int4range.ex
+++ /dev/null
@@ -1,90 +0,0 @@
-defmodule FzHttp.Int4Range do
- @moduledoc """
- Ecto type for Postgres' Int4Range type
- """
- # Note: we represent a port range as a string: lower - upper for ease of use
- # with Phoenix LiveView and nftables
- use Ecto.Type
- @format_error "Range Error: Bad format"
-
- def type, do: :int4range
-
- def cast(str) when is_binary(str) do
- # We need to handle this case since postgre notifies
- # before inserting the range in the database using this format
- parse_str =
- if String.starts_with?(str, ["[", "("]) do
- &parse_bracket/1
- else
- &parse_range/1
- end
-
- case parse_str.(str) do
- {:ok, range} -> cast(range)
- err -> err
- end
- end
-
- def cast([num, num]) when is_number(num) do
- {:ok, Integer.to_string(num)}
- end
-
- def cast([lower, upper]) when upper >= lower, do: {:ok, "#{lower} - #{upper}"}
- def cast([_, _]), do: {:error, message: "Range Error: Lower bound higher than upper bound"}
-
- def load(%Postgrex.Range{
- lower: lower,
- upper: upper,
- lower_inclusive: lower_inclusive,
- upper_inclusive: upper_inclusive
- }) do
- upper = if upper != :unbound, do: upper - to_num(!upper_inclusive), else: nil
- lower = if lower != :unbound, do: lower + to_num(!lower_inclusive), else: nil
- cast([lower, upper])
- end
-
- def dump(range) when is_binary(range) do
- {:ok, range_list} = parse_range(range)
- dump(range_list)
- end
-
- def dump([lower, upper]) do
- {:ok,
- %Postgrex.Range{lower: lower, upper: upper, upper_inclusive: true, lower_inclusive: true}}
- end
-
- def dump(_), do: :error
-
- defp parse_range(range) do
- res =
- String.trim(range)
- |> String.split("-", trim: true, parts: 2)
- |> Enum.map(&String.trim/1)
- |> Enum.map(&Integer.parse/1)
-
- case res do
- [{lower, _}, {upper, _}] -> {:ok, [lower, upper]}
- [{num, _}] -> {:ok, [num, num]}
- _ -> {:error, message: @format_error}
- end
- end
-
- defp parse_bracket(bracket) do
- res =
- Regex.named_captures(
- ~r/(?[\[|(])\s*(?\d+),\s*(?\d+)\s*(?[\]|\)])/,
- bracket
- )
-
- if is_nil(res) || Enum.any?(["lower", "upper", "start", "end"], &is_nil(res[&1])) do
- {:error, message: @format_error}
- else
- lower = String.to_integer(res["lower"]) + to_num(res["start"] == "(")
- upper = String.to_integer(res["upper"]) - to_num(res["end"] == ")")
- {:ok, [lower, upper]}
- end
- end
-
- defp to_num(b) when b, do: 1
- defp to_num(_b), do: 0
-end
diff --git a/apps/fz_http/lib/fz_http/rules.ex b/apps/fz_http/lib/fz_http/rules.ex
index abaebae9a..b9edc319e 100644
--- a/apps/fz_http/lib/fz_http/rules.ex
+++ b/apps/fz_http/lib/fz_http/rules.ex
@@ -4,7 +4,7 @@ defmodule FzHttp.Rules do
"""
import Ecto.Query, warn: false
- import Ecto.Changeset
+
alias FzHttp.{Repo, Rules.Rule, Rules.RuleSetting, Telemetry}
def list_rules, do: Repo.all(Rule)
@@ -38,14 +38,6 @@ defmodule FzHttp.Rules do
|> Rule.changeset(attrs)
end
- def defaults(changeset) do
- %{port_type: get_field(changeset, :port_type)}
- end
-
- def defaults do
- defaults(new_rule())
- end
-
def create_rule(attrs \\ %{}) do
result =
attrs
diff --git a/apps/fz_http/lib/fz_http/rules/rule.ex b/apps/fz_http/lib/fz_http/rules/rule.ex
index 301e28ebb..f67d0de07 100644
--- a/apps/fz_http/lib/fz_http/rules/rule.ex
+++ b/apps/fz_http/lib/fz_http/rules/rule.ex
@@ -7,15 +7,11 @@ defmodule FzHttp.Rules.Rule do
import Ecto.Changeset
@exclusion_msg "Destination overlaps with an existing rule"
- @port_range_msg "Port is not within valid range"
- @port_type_msg "Please specify a port-range for the given port type"
schema "rules" do
field :uuid, Ecto.UUID, autogenerate: true
field :destination, EctoNetwork.INET, read_after_writes: true
field :action, Ecto.Enum, values: [:drop, :accept], default: :drop
- field :port_type, Ecto.Enum, values: [:tcp, :udp], default: nil
- field :port_range, FzHttp.Int4Range, default: nil
belongs_to :user, FzHttp.Users.User
timestamps(type: :utc_datetime_usec)
@@ -26,19 +22,9 @@ defmodule FzHttp.Rules.Rule do
|> cast(attrs, [
:user_id,
:action,
- :destination,
- :port_type,
- :port_range
+ :destination
])
|> validate_required([:action, :destination])
- |> check_constraint(:port_range,
- message: @port_range_msg,
- name: :port_range_is_within_valid_values
- )
- |> check_constraint(:port_type,
- message: @port_type_msg,
- name: :port_range_needs_type
- )
|> exclusion_constraint(:destination,
message: @exclusion_msg,
name: :destination_overlap_excl_usr_rule
@@ -47,13 +33,5 @@ defmodule FzHttp.Rules.Rule do
message: @exclusion_msg,
name: :destination_overlap_excl
)
- |> exclusion_constraint(:destination,
- message: @exclusion_msg,
- name: :destination_overlap_excl_port
- )
- |> exclusion_constraint(:destination,
- message: @exclusion_msg,
- name: :destination_overlap_excl_usr_rule_port
- )
end
end
diff --git a/apps/fz_http/lib/fz_http/rules/rule_setting.ex b/apps/fz_http/lib/fz_http/rules/rule_setting.ex
index 253dd7401..46d0740bc 100644
--- a/apps/fz_http/lib/fz_http/rules/rule_setting.ex
+++ b/apps/fz_http/lib/fz_http/rules/rule_setting.ex
@@ -12,23 +12,19 @@ defmodule FzHttp.Rules.RuleSetting do
field :action, Ecto.Enum, values: [:drop, :accept]
field :destination, :string
field :user_id, :integer
- field :port_type, Ecto.Enum, values: [:tcp, :udp], default: nil
- field :port_range, FzHttp.Int4Range, default: nil
end
def parse(rule) when is_struct(rule) do
%__MODULE__{
destination: decode(rule.destination),
action: rule.action,
- user_id: rule.user_id,
- port_type: rule.port_type,
- port_range: rule.port_range
+ user_id: rule.user_id
}
end
def parse(rule) when is_map(rule) do
%__MODULE__{}
- |> cast(rule, [:action, :destination, :user_id, :port_type, :port_range])
+ |> cast(rule, [:action, :destination, :user_id])
|> apply_changes()
end
end
diff --git a/apps/fz_http/lib/fz_http_web/live/rule_live/rule_list_component.ex b/apps/fz_http/lib/fz_http_web/live/rule_live/rule_list_component.ex
index dcab05dd8..72b3533a0 100644
--- a/apps/fz_http/lib/fz_http_web/live/rule_live/rule_list_component.ex
+++ b/apps/fz_http/lib/fz_http_web/live/rule_live/rule_list_component.ex
@@ -12,7 +12,6 @@ defmodule FzHttpWeb.RuleLive.RuleListComponent do
{:ok,
socket
|> assign(assigns)
- |> assign(Rules.defaults())
|> assign(
action: action(assigns.id),
rule_list: rule_list(assigns),
@@ -21,23 +20,12 @@ defmodule FzHttpWeb.RuleLive.RuleListComponent do
)}
end
- @impl Phoenix.LiveComponent
- def handle_event("change", %{"rule" => rule_params}, socket) do
- changeset = Rules.new_rule(rule_params)
-
- {:noreply,
- socket
- |> assign(:changeset, changeset)
- |> assign(Rules.defaults(changeset))}
- end
-
@impl true
def handle_event("add_rule", %{"rule" => rule_params}, socket) do
case Rules.create_rule(rule_params) do
{:ok, _rule} ->
{:noreply,
- assign(socket, changeset: Rules.new_rule(), rule_list: rule_list(socket.assigns))
- |> assign(Rules.defaults())}
+ assign(socket, changeset: Rules.new_rule(), rule_list: rule_list(socket.assigns))}
{:error, changeset} ->
{:noreply, assign(socket, changeset: changeset)}
@@ -86,12 +74,4 @@ defmodule FzHttpWeb.RuleLive.RuleListComponent do
defp user_options(users) do
Enum.map(users, fn {id, email} -> {email, id} end)
end
-
- defp port_type_options do
- %{TCP: :tcp, UDP: :udp}
- end
-
- defp port_type_display(nil), do: nil
- defp port_type_display(:tcp), do: "TCP"
- defp port_type_display(:udp), do: "UDP"
end
diff --git a/apps/fz_http/lib/fz_http_web/live/rule_live/rule_list_component.html.heex b/apps/fz_http/lib/fz_http_web/live/rule_live/rule_list_component.html.heex
index d90884117..78aa0d8e2 100644
--- a/apps/fz_http/lib/fz_http_web/live/rule_live/rule_list_component.html.heex
+++ b/apps/fz_http/lib/fz_http_web/live/rule_live/rule_list_component.html.heex
@@ -6,7 +6,7 @@
- <.form let={f} for={@changeset} id={"#{@action}-form"} phx-change="change" phx-target={@myself} phx-submit="add_rule">
+ <.form let={f} for={@changeset} id={"#{@action}-form"} phx-target={@myself} phx-submit="add_rule">
<%= hidden_input f, :action, value: @action %>
@@ -23,31 +23,6 @@
prompt: "Optional user scope" %>
-
-
- <%= select f,
- :port_type,
- port_type_options(),
- prompt: "Optional port range" %>
-
-
- <%= error_tag f, :port_type %>
-
-
-
-
- <%= text_input f, :port_range,
- class: "input #{input_error_class(f, :port_range)}",
- placeholder: "Port Range",
- disabled: @port_type == nil %>
-
-
- Formatted as 'start - stop' or 'port' e.g. 20-80 or 80 (Requires port type)
-
-
- <%= error_tag f, :port_range %>
-
-
<%= submit "Add", class: "button is-primary" %>
@@ -63,8 +38,6 @@
| Destination |
User Scope |
- Port Type |
- Port Range |
|
@@ -79,12 +52,6 @@
<%= @users[rule.user_id] %>
|
-
- <%= port_type_display(rule.port_type) %>
- |
-
- <%= if rule.port_range != nil, do: rule.port_range %>
- |
+ "#{nft()} 'add chain inet #{@table_name} forward " <>
"{ type filter hook forward priority 0 ; policy accept ; }'"
)
@@ -115,20 +83,6 @@ defmodule FzWall.CLI.Helpers.Nft do
setup_masquerade()
end
- @doc """
- Adds a regular nftable chain(not base)
- """
- def add_chain(chain_name) do
- exec!("#{nft()} 'add chain inet #{@table_name} #{chain_name}'")
- end
-
- @doc """
- Deletes a regular nftable chain(not base)
- """
- def delete_chain(chain_name) do
- exec!("#{nft()} 'delete chain inet #{@table_name} #{chain_name}'")
- end
-
defp setup_masquerade do
if masquerade_ipv4?() do
setup_masquerade(:ipv4)
@@ -206,7 +160,7 @@ defmodule FzWall.CLI.Helpers.Nft do
)
handle ->
- exec!("#{nft()} delete rule inet #{@table_name} #{@main_chain} handle #{handle}")
+ exec!("#{nft()} delete rule inet #{@table_name} forward handle #{handle}")
end
end
@@ -218,55 +172,14 @@ defmodule FzWall.CLI.Helpers.Nft do
Regex.run(regex, rules, capture: :all_names)
end
- defp filter_set_type(:ip, false), do: "ipv4_addr"
- defp filter_set_type(:ip6, false), do: "ipv6_addr"
+ defp set_type(:ip), do: "ipv4_addr"
+ defp set_type(:ip6), do: "ipv6_addr"
- defp filter_set_type(ip_type, true),
- do: "#{filter_set_type(ip_type, false)} . inet_proto . inet_service"
-
- defp dev_set_type(ip_type), do: filter_set_type(ip_type, false)
-
- defp rule_filter_match_str(type, dest_set, action, false) do
+ defp rule_match_str(type, nil, dest_set, action) do
"#{type} daddr @#{dest_set} ct state != established #{action}"
end
- defp rule_filter_match_str(type, dest_set, action, true) do
- "#{type} daddr . meta l4proto . th dport @#{dest_set} ct state != established #{action}"
- end
-
- defp rule_dev_match_str(ip_type, source_set, jump_chain) do
- "#{ip_type} saddr @#{source_set} jump #{jump_chain}"
- end
-
- defp insert_rule(chain, rule_str) do
- exec!("""
- #{nft()} 'insert rule inet #{@table_name} #{chain} #{rule_str}'
- """)
- end
-
- defp delete_elem_exec(set, elem) do
- exec!("""
- #{nft()} 'delete element inet #{@table_name} #{set} { #{elem} }'
- """)
- end
-
- defp add_set(name, type) do
- exec!("""
- #{nft()} 'add set inet #{@table_name} #{name} { type #{type} ; flags interval ; }'
- """)
- end
-
- defp add_elem_exec(set, elem) do
- exec!("""
- #{nft()} 'add element inet #{@table_name} #{set} { #{elem} }'
- """)
- end
-
- def get_elem(ip) do
- "#{standardized_inet(ip)}"
- end
-
- def get_elem(ip, proto, ports) do
- "#{standardized_inet(ip)} . #{proto} . #{ports}"
+ defp rule_match_str(type, source_set, dest_set, action) do
+ "#{type} saddr @#{source_set} #{rule_match_str(type, nil, dest_set, action)}"
end
end
diff --git a/apps/fz_wall/lib/fz_wall/cli/helpers/sets.ex b/apps/fz_wall/lib/fz_wall/cli/helpers/sets.ex
index 5689980a3..82e41f896 100644
--- a/apps/fz_wall/lib/fz_wall/cli/helpers/sets.ex
+++ b/apps/fz_wall/lib/fz_wall/cli/helpers/sets.ex
@@ -4,52 +4,34 @@ defmodule FzWall.CLI.Helpers.Sets do
"""
@actions [:drop, :accept]
- @ip_types [:ip, :ip6]
+ @types [:ip, :ip6]
- def list_filter_sets(user_id) do
- Enum.flat_map(
- [true, false],
- fn layer4 ->
- cross(@ip_types, @actions)
- |> Enum.map(fn {ip_type, action} ->
- %{
- name: get_filter_set_name(user_id, ip_type, action, layer4),
- ip_type: ip_type,
- action: action,
- layer4: layer4
- }
- end)
- end
- )
+ def list_dest_sets(user_id) do
+ cross(@types, @actions)
+ |> Enum.map(fn {type, action} ->
+ %{name: get_dest_set_name(user_id, type, action), type: type}
+ end)
end
- def list_dev_sets(user_id) do
- Enum.map(@ip_types, fn type -> %{name: get_device_set_name(user_id, type), ip_type: type} end)
+ def list_sets(nil), do: list_dest_sets(nil)
+
+ def list_sets(user_id) do
+ list_dest_sets(user_id) ++
+ Enum.map(@types, fn type -> %{name: get_device_set_name(user_id, type), type: type} end)
end
- def get_ip_types do
- @ip_types
+ def get_types do
+ @types
end
def get_actions do
@actions
end
- def get_device_set_name(user_id, type), do: "user#{user_id}_#{type}_devices"
- def get_user_chain(nil), do: "forward"
- def get_user_chain(user_id), do: "user#{user_id}"
-
- def get_filter_set_name(nil, ip_type, action, false),
- do: "#{ip_type}_#{action}"
-
- def get_filter_set_name(user_id, ip_type, action, false),
- do: "user#{user_id}_#{ip_type}_#{action}"
-
- def get_filter_set_name(nil, ip_type, action, true),
- do: "#{ip_type}_#{action}_layer4"
-
- def get_filter_set_name(user_id, ip_type, action, true),
- do: "user#{user_id}_#{ip_type}_#{action}_layer4"
+ def get_dest_set_name(nil, type, action), do: "#{type}_#{action}"
+ def get_dest_set_name(user_id, type, action), do: "user_#{user_id}_#{type}_#{action}"
+ def get_device_set_name(nil, _type), do: nil
+ def get_device_set_name(user_id, type), do: "user_#{user_id}_#{type}_devices"
def cross([x | a], [y | b]) do
[{x, y}] ++ cross([x], b) ++ cross(a, [y | b])
diff --git a/apps/fz_wall/lib/fz_wall/cli/live.ex b/apps/fz_wall/lib/fz_wall/cli/live.ex
index 5f179c441..7ab11214d 100644
--- a/apps/fz_wall/lib/fz_wall/cli/live.ex
+++ b/apps/fz_wall/lib/fz_wall/cli/live.ex
@@ -8,6 +8,7 @@ defmodule FzWall.CLI.Live do
import FzWall.CLI.Helpers.Sets
import FzWall.CLI.Helpers.Nft
+ import FzCommon.CLI
import FzCommon.FzNet, only: [ip_type: 1]
require Logger
@@ -18,81 +19,60 @@ defmodule FzWall.CLI.Live do
teardown_table()
setup_table()
setup_chains()
- setup_rules(nil)
+ setup_rules()
end
@doc """
Adds user sets and rules.
"""
def add_user(user_id) do
- add_user_set(user_id)
- add_chain(get_user_chain(user_id))
- set_jump_rule(user_id)
- setup_rules(user_id)
- end
-
- defp add_user_set(user_id) do
- list_dev_sets(user_id)
- |> Enum.map(fn set_spec -> add_dev_set(set_spec.name, set_spec.ip_type) end)
- end
-
- defp delete_user_set(user_id) do
- list_dev_sets(user_id)
- |> Enum.map(fn set_spec -> delete_set(set_spec.name) end)
+ add_sets(user_id)
+ add_rules(user_id)
end
@doc """
Remove user sets and rules.
"""
def delete_user(user_id) do
- delete_jump_rules(user_id)
- delete_user_set(user_id)
- delete_chain(get_user_chain(user_id))
- delete_filter_sets(user_id)
+ delete_rules(user_id)
+ delete_sets(user_id)
end
@doc """
Adds general sets and rules.
"""
- def setup_rules(user_id) do
- add_filter_sets(user_id)
- add_filter_rules(user_id)
- end
-
- def set_jump_rule(user_id) do
- list_dev_sets(user_id)
- |> Enum.each(fn set_spec ->
- insert_dev_rule(set_spec.ip_type, set_spec.name, get_user_chain(user_id))
- end)
+ def setup_rules do
+ add_sets(nil)
+ add_rules(nil)
end
@doc """
Adds device ip to the user's sets.
"""
def add_device(device) do
- list_dev_sets(device.user_id)
- |> Enum.each(fn set_spec -> add_elem(set_spec.name, device[set_spec.ip_type]) end)
+ get_types()
+ |> Enum.each(fn type -> add_to_set(device.user_id, device[type], type) end)
end
@doc """
Adds rule ip to its corresponding sets.
"""
def add_rule(rule) do
- modify_elem(&add_elem/4, rule)
+ add_to_set(rule.user_id, rule.destination, proto(rule.destination), rule.action)
end
@doc """
Delete rule destination ip from its corresponding sets.
"""
def delete_rule(rule) do
- modify_elem(&delete_elem/4, rule)
+ remove_from_set(rule.user_id, rule.destination, proto(rule.destination), rule.action)
end
@doc """
Eliminates device rules from its corresponding sets.
"""
def delete_device(device) do
- get_ip_types()
+ get_types()
|> Enum.each(fn type -> remove_from_set(device.user_id, device[type], type) end)
end
@@ -103,35 +83,54 @@ defmodule FzWall.CLI.Live do
|> delete_elem(ip)
end
- defp add_filter_sets(user_id) do
- list_filter_sets(user_id)
- |> Enum.each(fn set_spec ->
- add_filter_set(set_spec.name, set_spec.ip_type, set_spec.layer4)
- end)
+ defp remove_from_set(user_id, ip, type, action) do
+ get_dest_set_name(user_id, type, action)
+ |> delete_elem(ip)
end
- defp delete_filter_sets(user_id) do
- list_filter_sets(user_id)
- |> Enum.each(fn set_spec -> delete_set(set_spec.name) end)
+ defp add_to_set(_user_id, nil, _type), do: :no_ip
+
+ defp add_to_set(user_id, ip, type) do
+ get_device_set_name(user_id, type)
+ |> add_elem(ip)
end
- defp add_filter_rules(user_id) do
- list_filter_sets(user_id)
- |> Enum.each(fn set_spec ->
- insert_filter_rule(
- get_user_chain(user_id),
- set_spec.ip_type,
- set_spec.name,
- set_spec.action,
- set_spec.layer4
+ defp add_to_set(user_id, ip, type, action) do
+ get_dest_set_name(user_id, type, action)
+ |> add_elem(ip)
+ end
+
+ defp add_sets(user_id) do
+ list_sets(user_id)
+ |> Enum.each(&add_set/1)
+ end
+
+ defp delete_sets(user_id) do
+ list_sets(user_id)
+ |> Enum.each(&delete_set/1)
+ end
+
+ defp add_rules(user_id) do
+ cross(get_types(), get_actions())
+ |> Enum.each(fn {type, action} ->
+ insert_rule(
+ type,
+ get_device_set_name(user_id, type),
+ get_dest_set_name(user_id, type, action),
+ action
)
end)
end
- defp delete_jump_rules(user_id) do
- list_dev_sets(user_id)
- |> Enum.each(fn set_spec ->
- remove_dev_rule(set_spec.ip_type, set_spec.name, get_user_chain(user_id))
+ defp delete_rules(user_id) do
+ cross(get_types(), get_actions())
+ |> Enum.each(fn {type, action} ->
+ remove_rule(
+ type,
+ get_device_set_name(user_id, type),
+ get_dest_set_name(user_id, type, action),
+ action
+ )
end)
end
@@ -142,24 +141,36 @@ defmodule FzWall.CLI.Live do
Enum.each(rules, &add_rule/1)
end
- defp proto(ip) do
- case ip_type("#{ip}") do
- "IPv4" -> :ip
- "IPv6" -> :ip6
- "unknown" -> raise "Unknown protocol."
+ def egress_address do
+ case :os.type() do
+ {:unix, :linux} ->
+ cmd = "ip address show dev #{egress_interface()} | grep 'inet ' | awk '{print $2}'"
+
+ exec!(cmd)
+ |> String.trim()
+ |> String.split("/")
+ |> List.first()
+
+ {:unix, :darwin} ->
+ cmd = "ipconfig getifaddr #{egress_interface()}"
+
+ exec!(cmd)
+ |> String.trim()
+
+ _ ->
+ raise "OS not supported (yet)"
end
end
- defp modify_elem(action, rule) do
- ip_type = proto(rule.destination)
- port_type = rule.port_type
- layer4 = port_type != nil
+ defp egress_interface do
+ Application.fetch_env!(:fz_wall, :egress_interface)
+ end
- action.(
- get_filter_set_name(rule.user_id, ip_type, rule.action, layer4),
- rule.destination,
- port_type,
- rule.port_range
- )
+ defp proto(ip) do
+ case ip_type("#{ip}") do
+ "IPv4" -> "ip"
+ "IPv6" -> "ip6"
+ "unknown" -> raise "Unknown protocol."
+ end
end
end
diff --git a/apps/fz_wall/lib/fz_wall/cli/sandbox.ex b/apps/fz_wall/lib/fz_wall/cli/sandbox.ex
index a7ee5670f..4c1a57183 100644
--- a/apps/fz_wall/lib/fz_wall/cli/sandbox.ex
+++ b/apps/fz_wall/lib/fz_wall/cli/sandbox.ex
@@ -13,4 +13,5 @@ defmodule FzWall.CLI.Sandbox do
def delete_device(_device), do: @default_returned
def add_user(_user), do: @default_returned
def delete_user(_user), do: @default_returned
+ def egress_address, do: "10.0.0.1"
end
diff --git a/apps/fz_wall/test/fz_wall/cli/sandbox_test.exs b/apps/fz_wall/test/fz_wall/cli/sandbox_test.exs
index 0417dfd74..8a5ca1bda 100644
--- a/apps/fz_wall/test/fz_wall/cli/sandbox_test.exs
+++ b/apps/fz_wall/test/fz_wall/cli/sandbox_test.exs
@@ -2,4 +2,8 @@ defmodule FzWall.CLI.SandboxTest do
use ExUnit.Case, async: true
import FzWall.CLI
+
+ test "egress_address()" do
+ assert is_binary(cli().egress_address())
+ end
end
|