added stuff
This commit is contained in:
parent
6d31f5b5a1
commit
7d4f626b7d
907 changed files with 70990 additions and 0 deletions
140
nyx/lib/network/dag.nix
Normal file
140
nyx/lib/network/dag.nix
Normal file
|
@ -0,0 +1,140 @@
|
|||
# Adjusted from https://gitlab.com/rycee/nur-expressions/blob/b34e2e548da574c7bd4da14d1779c95b62349a3a/lib/dag.nix (MIT)
|
||||
# A generalization of Nixpkgs's `strings-with-deps.nix`.
|
||||
#
|
||||
# The main differences from the Nixpkgs version are
|
||||
#
|
||||
# - not specific to strings, i.e., any payload is OK,
|
||||
#
|
||||
# - the addition of the function `entryBefore` indicating a
|
||||
# "wanted by" relationship.
|
||||
{lib, ...}: let
|
||||
inherit (lib) mkOption filterAttrs mapAttrsToList toposort mapAttrs any types;
|
||||
|
||||
types' =
|
||||
types
|
||||
// {
|
||||
dagOf = subType:
|
||||
types.attrsOf (types.submodule {
|
||||
options = {
|
||||
data = mkOption {
|
||||
type = subType;
|
||||
description = "Entry value.";
|
||||
};
|
||||
|
||||
before = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = "Entries to guarantee before.";
|
||||
};
|
||||
|
||||
after = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = "Entries to guarantee after.";
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
dag = {
|
||||
# Takes an attribute set containing entries built by
|
||||
# entryAnywhere, entryAfter, and entryBefore to a
|
||||
# topologically sorted list of entries.
|
||||
#
|
||||
# Internally this function uses the `toposort` function in
|
||||
# `<nixpkgs/lib/lists.nix>` and its value is accordingly.
|
||||
#
|
||||
# Specifically, the result on success is
|
||||
#
|
||||
# { result = [{name = ?; data = ?;} …] }
|
||||
#
|
||||
# For example
|
||||
#
|
||||
# nix-repl> topoSort {
|
||||
# a = entryAnywhere "1";
|
||||
# b = entryAfter ["a" "c"] "2";
|
||||
# c = entryBefore ["d"] "3";
|
||||
# d = entryBefore ["e"] "4";
|
||||
# e = entryAnywhere "5";
|
||||
# } == {
|
||||
# result = [
|
||||
# { data = "1"; name = "a"; }
|
||||
# { data = "3"; name = "c"; }
|
||||
# { data = "2"; name = "b"; }
|
||||
# { data = "4"; name = "d"; }
|
||||
# { data = "5"; name = "e"; }
|
||||
# ];
|
||||
# }
|
||||
# true
|
||||
#
|
||||
# And the result on error is
|
||||
#
|
||||
# {
|
||||
# cycle = [ {after = ?; name = ?; data = ?} … ];
|
||||
# loops = [ {after = ?; name = ?; data = ?} … ];
|
||||
# }
|
||||
#
|
||||
# For example
|
||||
#
|
||||
# nix-repl> topoSort {
|
||||
# a = entryAnywhere "1";
|
||||
# b = entryAfter ["a" "c"] "2";
|
||||
# c = entryAfter ["d"] "3";
|
||||
# d = entryAfter ["b"] "4";
|
||||
# e = entryAnywhere "5";
|
||||
# } == {
|
||||
# cycle = [
|
||||
# { after = ["a" "c"]; data = "2"; name = "b"; }
|
||||
# { after = ["d"]; data = "3"; name = "c"; }
|
||||
# { after = ["b"]; data = "4"; name = "d"; }
|
||||
# ];
|
||||
# loops = [
|
||||
# { after = ["a" "c"]; data = "2"; name = "b"; }
|
||||
# ];
|
||||
# } == {}
|
||||
# true
|
||||
topoSort = dag: let
|
||||
dagBefore = dag: name:
|
||||
mapAttrsToList (n: v: n) (
|
||||
filterAttrs (n: v: any (a: a == name) v.before) dag
|
||||
);
|
||||
normalizedDag =
|
||||
mapAttrs (n: v: {
|
||||
name = n;
|
||||
data = v.data;
|
||||
after = v.after ++ dagBefore dag n;
|
||||
})
|
||||
dag;
|
||||
before = a: b: any (c: a.name == c) b.after;
|
||||
sorted = toposort before (mapAttrsToList (n: v: v) normalizedDag);
|
||||
in
|
||||
if sorted ? result
|
||||
then {result = map (v: {inherit (v) name data;}) sorted.result;}
|
||||
else sorted;
|
||||
|
||||
# Create a DAG entry with no particular dependency information.
|
||||
entryAnywhere = data: {
|
||||
inherit data;
|
||||
before = [];
|
||||
after = [];
|
||||
};
|
||||
|
||||
# Ordering of after and before flipped from the original
|
||||
entryBetween = after: before: data: {
|
||||
inherit data before after;
|
||||
};
|
||||
|
||||
entryAfter = after: data: {
|
||||
inherit data after;
|
||||
before = [];
|
||||
};
|
||||
|
||||
entryBefore = before: data: {
|
||||
inherit data before;
|
||||
after = [];
|
||||
};
|
||||
};
|
||||
in {
|
||||
inherit (dag) entryBefore entryBetween entryAfter entryAnywhere topoSort;
|
||||
inherit (types') dagOf;
|
||||
}
|
177
nyx/lib/network/firewall.nix
Normal file
177
nyx/lib/network/firewall.nix
Normal file
|
@ -0,0 +1,177 @@
|
|||
{
|
||||
dag,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.options) mkOption mkEnableOption;
|
||||
inherit (lib.strings) optionalString concatMapStringsSep concatStringsSep;
|
||||
inherit (lib.attrsets) filterAttrs mapAttrsToList;
|
||||
inherit (lib.lists) concatLists;
|
||||
inherit (lib) types;
|
||||
inherit (dag) dagOf topoSort;
|
||||
|
||||
mkTable = desc: body:
|
||||
mkOption {
|
||||
default = {};
|
||||
description = "Containers for chains, sets, and other stateful objects.";
|
||||
type = types.submodule ({config, ...}: {
|
||||
options =
|
||||
{
|
||||
enable = mkEnableOption desc;
|
||||
objects = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = "Objects associated with this table.";
|
||||
default = [];
|
||||
};
|
||||
}
|
||||
// body;
|
||||
|
||||
config = let
|
||||
buildChainDag = chain:
|
||||
concatMapStringsSep "\n" ({
|
||||
name,
|
||||
data,
|
||||
}: let
|
||||
protocol =
|
||||
if builtins.isNull data.protocol
|
||||
then ""
|
||||
else data.protocol;
|
||||
field =
|
||||
if builtins.isNull data.field
|
||||
then ""
|
||||
else data.field;
|
||||
inherit (data) policy;
|
||||
values = map toString data.value;
|
||||
value =
|
||||
if builtins.isNull data.value
|
||||
then ""
|
||||
else
|
||||
(
|
||||
if builtins.length data.value == 1
|
||||
then builtins.head values
|
||||
else "{ ${concatStringsSep ", " values} }"
|
||||
);
|
||||
in ''
|
||||
${protocol} ${field} ${value} ${policy} comment ${name}
|
||||
'') ((topoSort chain).result or (throw "Cycle in DAG"));
|
||||
|
||||
buildChain = chainType: chain:
|
||||
mapAttrsToList (chainName: chainDag: ''
|
||||
chain ${chainName} {
|
||||
type ${chainType} hook ${chainName} priority 0;
|
||||
|
||||
${buildChainDag chainDag}
|
||||
}
|
||||
'') (filterAttrs (_: g: builtins.length (builtins.attrNames g) > 0) chain);
|
||||
in {
|
||||
objects = let
|
||||
chains = concatLists [
|
||||
(
|
||||
if config ? filter
|
||||
then buildChain "filter" config.filter
|
||||
else []
|
||||
)
|
||||
(
|
||||
if config ? nat
|
||||
then buildChain "nat" config.nat
|
||||
else []
|
||||
)
|
||||
(
|
||||
if config ? route
|
||||
then buildChain "route" config.route
|
||||
else []
|
||||
)
|
||||
];
|
||||
in
|
||||
chains;
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
mkChain = _: description:
|
||||
mkOption {
|
||||
inherit description;
|
||||
default = {};
|
||||
type = dagOf (types.submodule {
|
||||
options = {
|
||||
protocol = mkOption {
|
||||
default = null;
|
||||
description = "Protocol to match.";
|
||||
type = with types;
|
||||
nullOr (either (enum [
|
||||
"ether"
|
||||
"vlan"
|
||||
"arp"
|
||||
"ip"
|
||||
"icmp"
|
||||
"igmp"
|
||||
"ip6"
|
||||
"icmpv6"
|
||||
"tcp"
|
||||
"udp"
|
||||
"udplite"
|
||||
"sctp"
|
||||
"dccp"
|
||||
"ah"
|
||||
"esp"
|
||||
"comp"
|
||||
])
|
||||
str);
|
||||
};
|
||||
|
||||
field = mkOption {
|
||||
default = null;
|
||||
description = "Field value to match.";
|
||||
type = with types;
|
||||
nullOr (enum [
|
||||
"dport"
|
||||
"sport"
|
||||
"daddr"
|
||||
"saddr"
|
||||
"type"
|
||||
"state"
|
||||
"iifname"
|
||||
"pkttype"
|
||||
]);
|
||||
};
|
||||
|
||||
value = mkOption {
|
||||
default = null;
|
||||
description = "Associated value.";
|
||||
type = with types; let
|
||||
valueType = oneOf [port str];
|
||||
in
|
||||
nullOr (coercedTo valueType (value: [value]) (listOf valueType));
|
||||
};
|
||||
|
||||
policy = mkOption {
|
||||
description = "What to do with matching packets.";
|
||||
type = types.enum [
|
||||
"accept"
|
||||
"reject"
|
||||
"drop"
|
||||
"log"
|
||||
];
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
mkRuleset = ruleset:
|
||||
concatStringsSep "\n" (mapAttrsToList (name: table:
|
||||
optionalString (builtins.length table.objects > 0) ''
|
||||
table ${name} nixos {
|
||||
${concatStringsSep "\n" table.objects}
|
||||
}
|
||||
'')
|
||||
ruleset);
|
||||
|
||||
mkIngressChain = mkChain "Process all packets before they enter the system";
|
||||
mkPrerouteChain = mkChain "Process all packets entering the system";
|
||||
mkInputChain = mkChain "Process packets delivered to the local system";
|
||||
mkForwardChain = mkChain "Process packets forwarded to a different host";
|
||||
mkOutputChain = mkChain "Process packets sent by local processes";
|
||||
mkPostrouteChain = mkChain "Process all packets leaving the system";
|
||||
in {
|
||||
inherit mkTable mkRuleset mkIngressChain mkPrerouteChain mkInputChain mkForwardChain mkOutputChain mkPostrouteChain;
|
||||
}
|
13
nyx/lib/network/namespacing.nix
Normal file
13
nyx/lib/network/namespacing.nix
Normal file
|
@ -0,0 +1,13 @@
|
|||
_: let
|
||||
makeServiceNsPhysical = name: {
|
||||
systemd.services."${name}".serviceConfig.NetworkNamespacePath = "/var/run/netns/physical";
|
||||
};
|
||||
makeSocketNsPhysical = name: {
|
||||
systemd.sockets."${name}".socketConfig.NetworkNamespacePath = "/var/run/netns/physical";
|
||||
};
|
||||
unRestrictNamespaces = name: {
|
||||
systemd.sockets."${name}".socketConfig.RestrictNamespaces = "~net";
|
||||
};
|
||||
in {
|
||||
inherit makeSocketNsPhysical makeServiceNsPhysical unRestrictNamespaces;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue