Compare commits

..

No commits in common. "2bdc0f1c8c0bccc72670808d60b5ab8b6e616fd0" and "f119df524c791697f32cc21db8835d17c4472c92" have entirely different histories.

5 changed files with 28 additions and 26 deletions

1
.gitignore vendored
View file

@ -1,3 +1,2 @@
private.nix private.nix
private/ private/
/result

View file

@ -188,17 +188,17 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1687589315, "lastModified": 1687562820,
"narHash": "sha256-yHeWC/6OatjLN56VfCw1gjnzZd++uyYIkJBbDckWj/E=", "narHash": "sha256-cks0WUe/27kBlQDNulKA4ZHTggN9k/jGWhFDrMiEV8k=",
"owner": "chayleaf", "owner": "chayleaf",
"repo": "nixos-router", "repo": "nixos-router",
"rev": "b28e10ec8d247babd9ff461bb14725e504d3badf", "rev": "5048633a6f38c6787cba1a010359ff5246ec532b",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "chayleaf", "owner": "chayleaf",
"repo": "nixos-router", "repo": "nixos-router",
"rev": "b28e10ec8d247babd9ff461bb14725e504d3badf", "rev": "5048633a6f38c6787cba1a010359ff5246ec532b",
"type": "github" "type": "github"
} }
}, },
@ -273,6 +273,7 @@
"original": { "original": {
"owner": "chayleaf", "owner": "chayleaf",
"repo": "notnft", "repo": "notnft",
"rev": "f090546a7c190557c2081129b7e49a595f2ab76f",
"type": "github" "type": "github"
} }
}, },

View file

@ -23,11 +23,11 @@
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
notnft = { notnft = {
url = "github:chayleaf/notnft"; url = "github:chayleaf/notnft/f090546a7c190557c2081129b7e49a595f2ab76f";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
nixos-router = { nixos-router = {
url = "github:chayleaf/nixos-router"; url = "github:chayleaf/nixos-router/5048633a6f38c6787cba1a010359ff5246ec532b";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
nixos-mailserver = { nixos-mailserver = {
@ -210,12 +210,12 @@
"aarch64-linux" "aarch64-linux"
] (system: let self = overlay self (import nixpkgs { inherit system; }); in self ); ] (system: let self = overlay self (import nixpkgs { inherit system; }); in self );
nixosImages.router = let pkgs = import nixpkgs { system = "aarch64-linux"; overlays = [ overlay ]; }; in { nixosImages.router = let pkgs = import nixpkgs { system = "aarch64-linux"; overlays = [ overlay ]; }; in {
emmcImage = pkgs.callPackage ./system/hardware/bpi-r3/image.nix { emmcImage = pkgs.callPackage ./system/hardware/bpi_r3/image.nix {
inherit (nixosConfigurations.router-emmc) config; inherit (nixosConfigurations.router-emmc) config;
rootfsImage = nixosConfigurations.router-emmc.config.system.build.rootfsImage; rootfsImage = nixosConfigurations.router-emmc.config.system.build.rootfsImage;
bpiR3Stuff = pkgs.bpiR3StuffEmmc; bpiR3Stuff = pkgs.bpiR3StuffEmmc;
}; };
sdImage = pkgs.callPackage ./system/hardware/bpi-r3/image.nix { sdImage = pkgs.callPackage ./system/hardware/bpi_r3/image.nix {
inherit (nixosConfigurations.router-sd) config; inherit (nixosConfigurations.router-sd) config;
rootfsImage = nixosConfigurations.router-sd.config.system.build.rootfsImage; rootfsImage = nixosConfigurations.router-sd.config.system.build.rootfsImage;
bpiR3Stuff = pkgs.bpiR3StuffSd; bpiR3Stuff = pkgs.bpiR3StuffSd;

View file

@ -82,4 +82,4 @@ in
CONFIG_AIRTIME_POLICY=y CONFIG_AIRTIME_POLICY=y
''; '';
}); });
} // (import ../system/hardware/bpi-r3/pkgs.nix { inherit pkgs pkgs' lib sources; }) } // (import ../system/hardware/bpi_r3/pkgs.nix { inherit pkgs pkgs' lib sources; })

View file

@ -47,6 +47,8 @@ let
wan_table = 1; wan_table = 1;
# vpn table, assign an id but don't actually add a rule for it, so it is the default # vpn table, assign an id but don't actually add a rule for it, so it is the default
vpn_table = 2; vpn_table = 2;
# iot table without a route into the internet
iot_table = 3;
dnatRuleMode = rule: dnatRuleMode = rule:
if rule.mode != "" then rule.mode if rule.mode != "" then rule.mode
@ -60,8 +62,7 @@ let
# wans = external interfaces (internet) # wans = external interfaces (internet)
# lans = internal interfaces (lan) # lans = internal interfaces (lan)
# netdevIngressWanRules = additional rules for ingress (netdev) # netdevIngressWanRules = additional rules for ingress (netdev)
# inetInboundWanRules = additional rules for input from wan (inet) # inetInboundWanRules = additional rules for input from wan (inet), i.e. stuff meant directly for the router and not for any other device
# inetInboundLanRules = same for lan
# inetForwardRules = additional forward rules besides allow lan->wan forwarding # inetForwardRules = additional forward rules besides allow lan->wan forwarding
# inetSnatRules = snat rules (changing source address, usually just called nat) # inetSnatRules = snat rules (changing source address, usually just called nat)
# inetDnatRules = dnat rules (changing destination address, i.e. port forwarding) # inetDnatRules = dnat rules (changing destination address, i.e. port forwarding)
@ -75,7 +76,6 @@ let
lans, lans,
netdevIngressWanRules ? [], netdevIngressWanRules ? [],
inetInboundWanRules ? [], inetInboundWanRules ? [],
inetInboundLanRules ? [],
inetForwardRules ? [], inetForwardRules ? [],
inetSnatRules ? [], inetSnatRules ? [],
inetDnatRules ? [], inetDnatRules ? [],
@ -99,7 +99,6 @@ let
ingress_lan_common = add chain ingress_lan_common = add chain
# there are some issues with this, disable it for lan # there are some issues with this, disable it for lan
# [(is.eq (fib (f: with f; [ saddr mark iif ]) (f: f.oif)) missing) (log "${logPrefix}oif missing ") drop] # [(is.eq (fib (f: with f; [ saddr mark iif ]) (f: f.oif)) missing) (log "${logPrefix}oif missing ") drop]
inetInboundLanRules
[(jump "ingress_common")]; [(jump "ingress_common")];
ingress_wan_common = add chain ingress_wan_common = add chain
@ -179,6 +178,7 @@ let
} // extraInetEntries); } // extraInetEntries);
}; };
mkFlushRules = {}: with notnft.dsl; ruleset [ (flush ruleset) ];
unbound-python = pkgs.python3.withPackages (ps: with ps; [ pydbus dnspython requests pytricia nftables ]); unbound-python = pkgs.python3.withPackages (ps: with ps; [ pydbus dnspython requests pytricia nftables ]);
# parse a.b.c.d/x into { address, prefixLength } # parse a.b.c.d/x into { address, prefixLength }
@ -387,9 +387,13 @@ in {
} ]; } ];
ipv4.routes = [ ipv4.routes = [
{ extraArgs = [ netCidr4 "dev" "br0" "proto" "kernel" "scope" "link" "src" gatewayAddr4 "table" wan_table ]; } { extraArgs = [ netCidr4 "dev" "br0" "proto" "kernel" "scope" "link" "src" gatewayAddr4 "table" wan_table ]; }
# allow iot to contact ips inside the network
{ extraArgs = [ netCidr4 "dev" "br0" "proto" "kernel" "scope" "link" "src" gatewayAddr4 "table" iot_table ]; }
]; ];
ipv6.routes = [ ipv6.routes = [
{ extraArgs = [ netCidr6 "dev" "br0" "proto" "kernel" "metric" "256" "pref" "medium" "table" wan_table ]; } { extraArgs = [ netCidr6 "dev" "br0" "proto" "kernel" "metric" "256" "pref" "medium" "table" wan_table ]; }
# allow iot to contact ips inside the network
{ extraArgs = [ netCidr6 "dev" "br0" "proto" "kernel" "metric" "256" "pref" "medium" "table" iot_table ]; }
]; ];
ipv4.kea.enable = true; ipv4.kea.enable = true;
ipv6.radvd.enable = true; ipv6.radvd.enable = true;
@ -401,6 +405,9 @@ in {
rules = [ rules = [
{ ipv6 = false; extraArgs = [ "fwmark" wan_table "table" wan_table ]; } { ipv6 = false; extraArgs = [ "fwmark" wan_table "table" wan_table ]; }
{ ipv6 = true; extraArgs = [ "fwmark" wan_table "table" wan_table ]; } { ipv6 = true; extraArgs = [ "fwmark" wan_table "table" wan_table ]; }
# don't add vpn_table as it should be the default
{ ipv6 = false; extraArgs = [ "fwmark" iot_table "table" iot_table ]; }
{ ipv6 = true; extraArgs = [ "fwmark" iot_table "table" iot_table ]; }
# below is dnat config # below is dnat config
] ++ builtins.concatLists (map (rule: let ] ++ builtins.concatLists (map (rule: let
table = if rule.inVpn then 0 else wan_table; table = if rule.inVpn then 0 else wan_table;
@ -423,6 +430,7 @@ in {
# nftables rules # nftables rules
# things to note: this has the code for switching between rtables # things to note: this has the code for switching between rtables
# otherwise, boring stuff # otherwise, boring stuff
nftables.stopJsonRules = mkFlushRules {};
nftables.jsonRules = mkRules { nftables.jsonRules = mkRules {
selfIp4 = gatewayAddr4; selfIp4 = gatewayAddr4;
selfIp6 = gatewayAddr6; selfIp6 = gatewayAddr6;
@ -455,7 +463,7 @@ in {
# allow dnat ("ct status dnat" doesn't work) # allow dnat ("ct status dnat" doesn't work)
]; ];
inetInboundWanRules = with notnft.dsl; with payload; [ inetInboundWanRules = with notnft.dsl; with payload; [
[(is.eq tcp.dport 22) accept] [(is.eq th.dport 22) accept]
[(is.eq ip.saddr (cidr netnsCidr4)) accept] [(is.eq ip.saddr (cidr netnsCidr4)) accept]
[(is.eq ip6.saddr (cidr netnsCidr6)) accept] [(is.eq ip6.saddr (cidr netnsCidr6)) accept]
]; ];
@ -471,11 +479,9 @@ in {
# those tables get populated by unbound # those tables get populated by unbound
force_unvpn4 = add set { type = f: f.ipv4_addr; flags = f: with f; [ interval ]; }; force_unvpn4 = add set { type = f: f.ipv4_addr; flags = f: with f; [ interval ]; };
force_unvpn6 = add set { type = f: f.ipv6_addr; flags = f: with f; [ interval ]; };
force_vpn4 = add set { type = f: f.ipv4_addr; flags = f: with f; [ interval ]; }; force_vpn4 = add set { type = f: f.ipv4_addr; flags = f: with f; [ interval ]; };
force_unvpn6 = add set { type = f: f.ipv6_addr; flags = f: with f; [ interval ]; };
force_vpn6 = add set { type = f: f.ipv6_addr; flags = f: with f; [ interval ]; }; force_vpn6 = add set { type = f: f.ipv6_addr; flags = f: with f; [ interval ]; };
allow_iot4 = add set { type = f: f.ipv4_addr; flags = f: with f; [ interval ]; };
allow_iot6 = add set { type = f: f.ipv6_addr; flags = f: with f; [ interval ]; };
prerouting = add chain { type = f: f.filter; hook = f: f.prerouting; prio = f: f.filter; policy = f: f.accept; } ([ prerouting = add chain { type = f: f.filter; hook = f: f.prerouting; prio = f: f.filter; policy = f: f.accept; } ([
[(mangle meta.mark ct.mark)] [(mangle meta.mark ct.mark)]
@ -518,12 +524,7 @@ in {
++ [ ++ [
[(is.eq ip.daddr "@block4") drop] [(is.eq ip.daddr "@block4") drop]
[(is.eq ip6.daddr "@block6") drop] [(is.eq ip6.daddr "@block6") drop]
# this doesn't work... it still gets routed, even though iot_table doesn't have a default route [(is.eq ether.saddr cfg.vacuumMac) (mangle meta.mark iot_table)]
# instead of debugging that, simply change the approach
# [(is.eq ip.saddr vacuumAddress4) (is.ne ip.daddr) (mangle meta.mark iot_table)]
# [(is.eq ether.saddr cfg.vacuumMac) (mangle meta.mark iot_table)]
[(is.eq ether.saddr cfg.vacuumMac) (is.ne ip.daddr (cidr netCidr4)) (is.ne ip.daddr "@allow_iot4") (log "iot4 ") drop]
[(is.eq ether.saddr cfg.vacuumMac) (is.ne ip6.daddr (cidr netCidr6)) (is.ne ip6.daddr "@allow_iot6") (log "iot6 ") drop]
[(mangle ct.mark meta.mark)] [(mangle ct.mark meta.mark)]
]); ]);
}; };
@ -571,6 +572,7 @@ in {
}; };
router.networkNamespaces.wan = { router.networkNamespaces.wan = {
# this is the even more boring nftables config # this is the even more boring nftables config
nftables.stopJsonRules = mkFlushRules {};
nftables.jsonRules = mkRules { nftables.jsonRules = mkRules {
selfIp4 = wanNetnsAddr4; selfIp4 = wanNetnsAddr4;
selfIp6 = wanNetnsAddr6; selfIp6 = wanNetnsAddr6;
@ -625,7 +627,7 @@ in {
(is.eq icmpv6.type (f: with f; set [ nd-neighbor-solicit nd-neighbor-advert ])) (is.eq icmpv6.type (f: with f; set [ nd-neighbor-solicit nd-neighbor-advert ]))
accept] accept]
# SSH # SSH
[(is.eq tcp.dport 22) accept] [(is.eq th.dport 22) accept]
]; ];
}; };
}; };
@ -681,7 +683,7 @@ in {
environment.MDNS_ACCEPT_NAMES = "^.*\\.local\\.$"; environment.MDNS_ACCEPT_NAMES = "^.*\\.local\\.$";
# load vpn_domains.json and vpn_ips.json, as well as unvpn_domains.json and unvpn_ips.json # load vpn_domains.json and vpn_ips.json, as well as unvpn_domains.json and unvpn_ips.json
# resolve domains and append it to ips and add it to the nftables sets # resolve domains and append it to ips and add it to the nftables sets
environment.NFT_QUERIES = "vpn:force_vpn4,force_vpn6;unvpn:force_unvpn4,force_unvpn6;iot:allow_iot4,allow_iot6"; environment.NFT_QUERIES = "vpn:force_vpn4,force_vpn6;unvpn:force_unvpn4,force_unvpn6";
# it needs to run after nftables has been set up because it sets up the sets # it needs to run after nftables has been set up because it sets up the sets
after = [ "nftables-default.service" ]; after = [ "nftables-default.service" ];
wants = [ "nftables-default.service" ]; wants = [ "nftables-default.service" ];