mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-03-22 02:41:55 +00:00
passing tests
This commit is contained in:
@@ -28,14 +28,14 @@ defmodule FzHttp.Rules do
|
||||
def allowlist do
|
||||
Repo.all(
|
||||
from r in Rule,
|
||||
where: r.action == :allow
|
||||
where: r.action == :accept
|
||||
)
|
||||
end
|
||||
|
||||
def denylist do
|
||||
Repo.all(
|
||||
from r in Rule,
|
||||
where: r.action == :deny
|
||||
where: r.action == :drop
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ defmodule FzHttp.Rules.Rule do
|
||||
|
||||
schema "rules" do
|
||||
field :destination, EctoNetwork.INET
|
||||
field :action, Ecto.Enum, values: [:deny, :allow], default: :deny
|
||||
field :action, Ecto.Enum, values: [:drop, :accept], default: :drop
|
||||
|
||||
timestamps(type: :utc_datetime_usec)
|
||||
end
|
||||
|
||||
@@ -45,10 +45,10 @@ defmodule FzHttpWeb.RuleLive.RuleListComponent do
|
||||
defp action(id) do
|
||||
case id do
|
||||
:allowlist ->
|
||||
:allow
|
||||
:accept
|
||||
|
||||
:denylist ->
|
||||
:deny
|
||||
:drop
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
defmodule FzHttp.Repo.Migrations.CreateRules do
|
||||
use Ecto.Migration
|
||||
|
||||
@create_query "CREATE TYPE action_enum AS ENUM ('deny', 'allow')"
|
||||
@create_query "CREATE TYPE action_enum AS ENUM ('drop', 'accept')"
|
||||
@drop_query "DROP TYPE action_enum"
|
||||
|
||||
def change do
|
||||
@@ -9,7 +9,7 @@ defmodule FzHttp.Repo.Migrations.CreateRules do
|
||||
|
||||
create table(:rules) do
|
||||
add :destination, :inet, null: false
|
||||
add :action, :action_enum, default: "deny", null: false
|
||||
add :action, :action_enum, default: "drop", null: false
|
||||
|
||||
timestamps(type: :utc_datetime_usec)
|
||||
end
|
||||
|
||||
@@ -27,7 +27,7 @@ defmodule FzHttp.RulesTest do
|
||||
test "creates rule" do
|
||||
{:ok, rule} = Rules.create_rule(%{destination: "::1"})
|
||||
assert !is_nil(rule.id)
|
||||
assert rule.action == :deny
|
||||
assert rule.action == :drop
|
||||
end
|
||||
end
|
||||
|
||||
@@ -47,11 +47,11 @@ defmodule FzHttp.RulesTest do
|
||||
setup [:create_rules]
|
||||
|
||||
@iptables_rules [
|
||||
{"1.1.1.0/24", :deny},
|
||||
{"2.2.2.0/24", :deny},
|
||||
{"3.3.3.0/24", :deny},
|
||||
{"4.4.4.0/24", :deny},
|
||||
{"5.5.5.0/24", :deny}
|
||||
{"1.1.1.0/24", :drop},
|
||||
{"2.2.2.0/24", :drop},
|
||||
{"3.3.3.0/24", :drop},
|
||||
{"4.4.4.0/24", :drop},
|
||||
{"5.5.5.0/24", :drop}
|
||||
]
|
||||
|
||||
test "prints all rules to iptables format", %{rules: _rules} do
|
||||
@@ -60,7 +60,7 @@ defmodule FzHttp.RulesTest do
|
||||
end
|
||||
|
||||
describe "allowlist/0" do
|
||||
setup [:create_allow_rule]
|
||||
setup [:create_accept_rule]
|
||||
|
||||
test "returns allow rules", %{rule: rule} do
|
||||
assert Rules.allowlist() == [rule]
|
||||
@@ -68,7 +68,7 @@ defmodule FzHttp.RulesTest do
|
||||
end
|
||||
|
||||
describe "denylist/0" do
|
||||
setup [:create_deny_rule]
|
||||
setup [:create_drop_rule]
|
||||
|
||||
test "returns deny rules", %{rule: rule} do
|
||||
assert Rules.denylist() == [rule]
|
||||
@@ -79,7 +79,7 @@ defmodule FzHttp.RulesTest do
|
||||
# describe "iptables_spec/1 IPv4" do
|
||||
# setup [:create_rule4]
|
||||
#
|
||||
# @ipv4tables_spec {"10.0.0.1", "10.10.10.0/24", :deny}
|
||||
# @ipv4tables_spec {"10.0.0.1", "10.10.10.0/24", :drop}
|
||||
#
|
||||
# test "returns IPv4 tuple", %{rule4: rule} do
|
||||
# assert @ipv4tables_spec = Rules.iptables_spec(rule)
|
||||
@@ -89,7 +89,7 @@ defmodule FzHttp.RulesTest do
|
||||
# describe "iptables_spec/1 IPv6" do
|
||||
# setup [:create_rule6]
|
||||
#
|
||||
# @ipv6tables_spec {"::1", "::/0", :deny}
|
||||
# @ipv6tables_spec {"::1", "::/0", :drop}
|
||||
#
|
||||
# test "returns IPv6 tuple", %{rule6: rule} do
|
||||
# assert @ipv6tables_spec = Rules.iptables_spec(rule)
|
||||
|
||||
@@ -2,10 +2,10 @@ defmodule FzHttpWeb.RuleLive.IndexTest do
|
||||
use FzHttpWeb.ConnCase, async: true
|
||||
|
||||
describe "allowlist" do
|
||||
setup :create_allow_rule
|
||||
setup :create_accept_rule
|
||||
|
||||
@destination "1.2.3.4"
|
||||
@allow_params %{"rule" => %{"action" => "allow", "destination" => @destination}}
|
||||
@allow_params %{"rule" => %{"action" => "accept", "destination" => @destination}}
|
||||
|
||||
test "adds to allowlist", %{authed_conn: conn} do
|
||||
path = Routes.rule_index_path(conn, :index)
|
||||
@@ -13,7 +13,7 @@ defmodule FzHttpWeb.RuleLive.IndexTest do
|
||||
|
||||
test_view =
|
||||
view
|
||||
|> form("#allow-form")
|
||||
|> form("#accept-form")
|
||||
|> render_submit(@allow_params)
|
||||
|
||||
assert test_view =~ @destination
|
||||
@@ -25,11 +25,11 @@ defmodule FzHttpWeb.RuleLive.IndexTest do
|
||||
|
||||
test_view =
|
||||
view
|
||||
|> form("#allow-form")
|
||||
|> form("#accept-form")
|
||||
|> render_submit(%{
|
||||
"rule" => %{
|
||||
"destination" => "not a valid destination",
|
||||
"action" => "allow"
|
||||
"action" => "accept"
|
||||
}
|
||||
})
|
||||
|
||||
@@ -50,10 +50,10 @@ defmodule FzHttpWeb.RuleLive.IndexTest do
|
||||
end
|
||||
|
||||
describe "denylist" do
|
||||
setup :create_deny_rule
|
||||
setup :create_drop_rule
|
||||
|
||||
@destination "1.2.3.4"
|
||||
@deny_params %{"rule" => %{"action" => "deny", "destination" => @destination}}
|
||||
@deny_params %{"rule" => %{"action" => "drop", "destination" => @destination}}
|
||||
|
||||
test "adds to denylist", %{authed_conn: conn, rule: _rule} do
|
||||
path = Routes.rule_index_path(conn, :index)
|
||||
@@ -61,7 +61,7 @@ defmodule FzHttpWeb.RuleLive.IndexTest do
|
||||
|
||||
test_view =
|
||||
view
|
||||
|> form("#deny-form")
|
||||
|> form("#drop-form")
|
||||
|> render_submit(@deny_params)
|
||||
|
||||
assert test_view =~ @destination
|
||||
@@ -73,11 +73,11 @@ defmodule FzHttpWeb.RuleLive.IndexTest do
|
||||
|
||||
test_view =
|
||||
view
|
||||
|> form("#deny-form")
|
||||
|> form("#drop-form")
|
||||
|> render_submit(%{
|
||||
"rule" => %{
|
||||
"destination" => "not a valid destination",
|
||||
"action" => "deny"
|
||||
"action" => "drop"
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -60,13 +60,13 @@ defmodule FzHttp.TestHelpers do
|
||||
{:ok, session: session}
|
||||
end
|
||||
|
||||
def create_allow_rule(_) do
|
||||
rule = Fixtures.rule(%{action: :allow})
|
||||
def create_accept_rule(_) do
|
||||
rule = Fixtures.rule(%{action: :accept})
|
||||
{:ok, rule: rule}
|
||||
end
|
||||
|
||||
def create_deny_rule(_) do
|
||||
rule = Fixtures.rule(%{action: :deny})
|
||||
def create_drop_rule(_) do
|
||||
rule = Fixtures.rule(%{action: :drop})
|
||||
{:ok, rule: rule}
|
||||
end
|
||||
|
||||
|
||||
@@ -1,76 +1,80 @@
|
||||
defmodule FzWall.CLI.Live do
|
||||
@moduledoc """
|
||||
A low-level module for interacting with the iptables CLI.
|
||||
A low-level module for interacting with the nftables CLI.
|
||||
|
||||
Rules operate on the iptables forward chain to deny outgoing packets to
|
||||
Rules operate on the nftables forward chain to deny outgoing packets to
|
||||
specified IP addresses, ports, and protocols from FireZone device IPs.
|
||||
|
||||
Note that iptables chains and rules are mutually exclusive between IPv4 and IPv6.
|
||||
"""
|
||||
|
||||
import FzCommon.CLI
|
||||
require Logger
|
||||
|
||||
@table_name "firezone"
|
||||
@egress_interface_cmd "route | grep '^default' | grep -o '[^ ]*$'"
|
||||
@setup_chain_cmd "iptables -N firezone && iptables6 -N firezone"
|
||||
@teardown_chain_cmd "iptables -F firezone &&\
|
||||
iptables -X firezone &&\
|
||||
iptables6 -F firezone &&\
|
||||
iptables6 -X firezone"
|
||||
|
||||
@doc """
|
||||
Sets up the FireZone iptables chain.
|
||||
Sets up the FireZone nftables table, base chain, and counts traffic
|
||||
"forward" is the Netfilter hook we want to tie into.
|
||||
"""
|
||||
def setup do
|
||||
exec!(@setup_chain_cmd)
|
||||
exec!("#{nft()} add table ip #{@table_name}")
|
||||
|
||||
exec!(
|
||||
"#{nft()} 'add chain ip #{@table_name} forward { type filter hook forward priority 0 ; }'"
|
||||
)
|
||||
|
||||
exec!("#{nft()} 'add rule ip #{@table_name} forward counter accept'")
|
||||
end
|
||||
|
||||
@doc """
|
||||
Flushes and removes the FireZone iptables chain.
|
||||
Flushes and removes the FireZone nftables table and base chain.
|
||||
"""
|
||||
def teardown do
|
||||
exec!(@teardown_chain_cmd)
|
||||
exec!("#{nft()} delete table ip #{@table_name}")
|
||||
end
|
||||
|
||||
@doc """
|
||||
Adds iptables rule.
|
||||
Adds nftables rule.
|
||||
"""
|
||||
def add_rule({4, s, d, :deny}) do
|
||||
exec!("iptables -A firezone -s #{s} -d #{d} -j DROP")
|
||||
end
|
||||
|
||||
def add_rule({4, d, :deny}) do
|
||||
exec!("iptables -A firezone -d #{d} -j DROP")
|
||||
end
|
||||
|
||||
def add_rule({4, s, d, :allow}) do
|
||||
exec!("iptables -A firezone -s #{s} -d #{d} -j ACCEPT")
|
||||
end
|
||||
|
||||
def add_rule({6, s, d, :deny}) do
|
||||
exec!("iptables6 -A firezone -s #{s} -d #{d} -j DROP")
|
||||
end
|
||||
|
||||
def add_rule({6, s, d, :allow}) do
|
||||
exec!("iptables6 -A firezone -s #{s} -d #{d} -j ACCEPT")
|
||||
def add_rule({dest, action}) do
|
||||
exec!("#{nft()} 'add rule ip #{@table_name} forward ip daddr #{dest} #{action}'")
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes iptables rule.
|
||||
Deletes nftables rule.
|
||||
"""
|
||||
def delete_rule({4, s, d, :deny}) do
|
||||
exec!("#{nft()} -D firezone -s #{s} -d #{d} -j DROP")
|
||||
def delete_rule_spec({dest, action} = rule_spec) do
|
||||
case get_rule_handle("ip daddr #{dest} #{action}") do
|
||||
{:ok, handle_num} ->
|
||||
exec!("#{nft()} delete rule #{@table_name} forward handle #{handle_num}")
|
||||
|
||||
{:error, cmd_output} ->
|
||||
raise("""
|
||||
######################################################
|
||||
Could not get handle to delete rule!
|
||||
Rule spec: #{rule_spec}
|
||||
|
||||
Current chain:
|
||||
#{cmd_output}
|
||||
######################################################
|
||||
""")
|
||||
end
|
||||
end
|
||||
|
||||
def delete_rule({4, s, d, :allow}) do
|
||||
exec!("iptables -D firezone -s #{s} -d #{d} -j ACCEPT")
|
||||
def get_rule_handle(rule_str) do
|
||||
cmd_output = exec!("#{nft()} list table #{@table_name}")
|
||||
|
||||
case rule_handle_regex(~r/#{rule_str}.*# handle (?<num>\d+)/, cmd_output) do
|
||||
[handle] ->
|
||||
{:ok, handle}
|
||||
|
||||
[] ->
|
||||
{:error, cmd_output}
|
||||
end
|
||||
end
|
||||
|
||||
def delete_rule({6, s, d, :deny}) do
|
||||
exec!("iptables6 -D firezone -s #{s} -d #{d} -j DROP")
|
||||
end
|
||||
|
||||
def delete_rule({6, s, d, :allow}) do
|
||||
exec!("iptables6 -D firezone -s #{s} -d #{d} -j ACCEPT")
|
||||
defp rule_handle_regex(regex, cmd_output) do
|
||||
Regex.run(regex, cmd_output, capture: :all_names)
|
||||
end
|
||||
|
||||
def restore(_rules) do
|
||||
|
||||
Reference in New Issue
Block a user