Compare commits
No commits in common. "2bdc0f1c8c0bccc72670808d60b5ab8b6e616fd0" and "f119df524c791697f32cc21db8835d17c4472c92" have entirely different histories.
2bdc0f1c8c
...
f119df524c
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,2 @@
|
||||||
private.nix
|
private.nix
|
||||||
private/
|
private/
|
||||||
/result
|
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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; })
|
||||||
|
|
|
@ -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" ];
|
||||||
|
|
Loading…
Reference in a new issue