network options working for basic functionality
This commit is contained in:
parent
e4cdc2cae5
commit
392375b046
9 changed files with 348 additions and 221 deletions
159
nixos/network/config.nix
Normal file
159
nixos/network/config.nix
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
{ config, pkgs, lib, vmixLib, ... }:
|
||||
with vmixLib.network;
|
||||
let
|
||||
vmixCfg = config.vmix;
|
||||
# creates a /30 network from available range for veth-pair wan interfaces
|
||||
mkVethIPv4Range = index: availableIPv4Range:
|
||||
let
|
||||
vethIPv4RangeLength = 30;
|
||||
in
|
||||
(calc.cidr.subnet (vethIPv4RangeLength - (calc.cidr.length availableIPv4Range)) index availableIPv4Range);
|
||||
|
||||
namespaceGlobalService = {
|
||||
"ns.net.vmix@" = {
|
||||
description = "network namespace %I for vmix";
|
||||
before = [ "network.target" ];
|
||||
path = with pkgs; [ iproute2 utillinux ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
PrivateNetwork = true;
|
||||
ExecStart = (pkgs.writeShellScript "ns.net.vmix-start" ''
|
||||
NAMESPACE="$1.vmix"
|
||||
ip netns add $NAMESPACE
|
||||
umount /var/run/netns/$NAMESPACE
|
||||
mount --bind /proc/self/ns/net /var/run/netns/$NAMESPACE
|
||||
'') + " %I";
|
||||
ExecStop = "${pkgs.iproute2}/bin/ip netns del %I.vmix";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mkLanService = networkName: lanName: cfg:
|
||||
let
|
||||
lanCfg = cfg // { name = lanName; namespace = "${networkName}"; };
|
||||
lanInterfaceName = "brx-${lanCfg.name}";
|
||||
lanInterfaceIPAddress = calc.cidr.host 1 lanCfg.ipv4.range;
|
||||
netmask = calc.cidr.netmask lanCfg.ipv4.range;
|
||||
networkPrefix = builtins.elemAt (lib.splitString "/" lanCfg.ipv4.range) 1;
|
||||
|
||||
createLanInterface = pkgs.writeShellScript "create-lan-${lanCfg.name}-vmix" ''
|
||||
ip link add ${lanInterfaceName} type bridge
|
||||
ip address add ${lanInterfaceIPAddress}/${networkPrefix} dev ${lanInterfaceName}
|
||||
ip link set ${lanInterfaceName} up
|
||||
'';
|
||||
deleteLanInterface = pkgs.writeShellScript "delete-lan-${lanCfg.name}-vmix" "ip link del ${lanInterfaceName}";
|
||||
|
||||
lanDomainName = "${lanCfg.name}.vmix";
|
||||
lanDnsmasqConf = pkgs.writeText "dnsmasq-${lanCfg.name}.conf" (''
|
||||
listen-address=${lanInterfaceIPAddress}
|
||||
dhcp-range=${lanCfg.ipv4.dhcp.startAddress},${lanCfg.ipv4.dhcp.endAddress},${netmask},12h
|
||||
interface=${lanInterfaceName}
|
||||
bind-interfaces
|
||||
except-interface=lo
|
||||
dhcp-authoritative
|
||||
domain=${lanDomainName}
|
||||
domain-needed
|
||||
localise-queries
|
||||
no-hosts
|
||||
expand-hosts
|
||||
dhcp-leasefile=/tmp/dhcp.leases
|
||||
'' +
|
||||
lib.concatStringsSep "\n" (lib.optionals (lanCfg.ipv4.dns.upstream != []) ([ "no-resolv" ] ++ (builtins.map (dnsServer: "server=${dnsServer}") lanCfg.ipv4.dns.upstream)))
|
||||
);
|
||||
in
|
||||
{
|
||||
"lan.net.vmix@${lanCfg.name}.${lanCfg.namespace}" = rec {
|
||||
bindsTo = [ "ns.net.vmix@${lanCfg.namespace}.service" ];
|
||||
after = bindsTo;
|
||||
wantedBy = [ "net.vmix@${lanCfg.namespace}.target" ];
|
||||
unitConfig.JoinsNamespaceOf = "ns.net.vmix@${lanCfg.namespace}.service";
|
||||
path = with pkgs; [ iproute2 ];
|
||||
serviceConfig = {
|
||||
ExecStartPre = createLanInterface;
|
||||
ExecStart = "${pkgs.dnsmasq}/bin/dnsmasq -d -C ${lanDnsmasqConf}";
|
||||
ExecReload = pkgs.writeShellScript "reload-dnsmasq" "kill -HUP $MAINPID";
|
||||
ExecStopPost = deleteLanInterface;
|
||||
Restart = "on-failure";
|
||||
RestartSec = "5";
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = true;
|
||||
ProtectHome = true;
|
||||
PrivateNetwork = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mkWanService = networkName: cfg:
|
||||
let
|
||||
wanCfg = cfg // { namespace = networkName; };
|
||||
vethInNSToHost.iface = "vhost";
|
||||
vethOnHostToNS.iface = "vn-${wanCfg.namespace}";
|
||||
vethOnHostToNS.ipv4.address = calc.cidr.host 1 wanCfg.ipv4.range;
|
||||
vethInNSToHost.ipv4.address = calc.cidr.host 2 wanCfg.ipv4.range;
|
||||
networkPrefix = builtins.elemAt (lib.splitString "/" wanCfg.ipv4.range) 1;
|
||||
iptablesMark = builtins.toString (ipv4ToInt vethOnHostToNS.ipv4.address);
|
||||
|
||||
createWanCommands = ''
|
||||
ip link add ${vethOnHostToNS.iface} type veth peer name ${vethInNSToHost.iface}
|
||||
ip link set ${vethInNSToHost.iface} netns ${wanCfg.namespace}.vmix
|
||||
|
||||
ip address add ${vethOnHostToNS.ipv4.address}/${networkPrefix} dev ${vethOnHostToNS.iface}
|
||||
ip netns exec ${wanCfg.namespace}.vmix ip address add ${vethInNSToHost.ipv4.address}/${networkPrefix} dev ${vethInNSToHost.iface}
|
||||
|
||||
iptables -A FORWARD -i ${vethOnHostToNS.iface} -j ACCEPT
|
||||
iptables -A FORWARD -o ${vethOnHostToNS.iface} -j ACCEPT
|
||||
#iptables -A INPUT -i ${vethOnHostToNS.iface} -j DROP
|
||||
|
||||
iptables -t mangle -A PREROUTING -i ${vethOnHostToNS.iface} -j MARK --set-mark ${iptablesMark}
|
||||
iptables -t nat -A POSTROUTING -m mark --mark ${iptablesMark} -j MASQUERADE
|
||||
|
||||
ip link set ${vethOnHostToNS.iface} up
|
||||
ip netns exec ${wanCfg.namespace}.vmix ip link set ${vethInNSToHost.iface} up
|
||||
ip netns exec ${wanCfg.namespace}.vmix ip r add default via ${vethOnHostToNS.ipv4.address}
|
||||
'';
|
||||
|
||||
createWan = pkgs.writeShellScript "create-wan-${wanCfg.namespace}-vmix" createWanCommands;
|
||||
|
||||
deleteWan =
|
||||
let
|
||||
createdIptablesRules = lib.filter (line: (lib.hasPrefix "iptables" line)) (lib.splitString "\n" createWanCommands);
|
||||
delIptablesRules = builtins.map (rule: lib.replaceStrings [ "-A" ] [ "-D"] rule) createdIptablesRules;
|
||||
in
|
||||
pkgs.writeShellScript "delete-wan-${wanCfg.namespace}-vmix" (''
|
||||
ip link del ${vethOnHostToNS.iface}
|
||||
'' + (lib.concatStringsSep "\n" delIptablesRules));
|
||||
in
|
||||
{
|
||||
"wan.net.vmix@${wanCfg.namespace}" = rec {
|
||||
bindsTo = [ "ns.net.vmix@${wanCfg.namespace}.service" ];
|
||||
after = bindsTo;
|
||||
wantedBy = [ "net.vmix@${wanCfg.namespace}.target" ];
|
||||
path = with pkgs; [ iproute2 iptables ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStart = createWan;
|
||||
ExecStop = deleteWan;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mkMacvlanService = networkName: macvlanName: cfg:
|
||||
{};
|
||||
|
||||
mkNetworkServices = networkName: cfg:
|
||||
let
|
||||
netCfg = cfg // { name = networkName; };
|
||||
in
|
||||
(lib.concatMapAttrs (mkLanService netCfg.name) netCfg.lans)
|
||||
// (mkWanService netCfg.name (netCfg.wan // { ipv4.range = (mkVethIPv4Range netCfg.index vmixCfg.global.net.wan.ipv4.range); }))
|
||||
// (lib.concatMapAttrs (mkMacvlanService netCfg.name) netCfg.bridges.macvlans);
|
||||
|
||||
networkNames = builtins.attrNames vmixCfg.networks;
|
||||
|
||||
networkServices = pkgs.unstable.lib.mergeAttrsList (lib.imap0 (index: networkName: (mkNetworkServices networkName (vmixCfg.networks.${networkName} // { inherit index;}))) networkNames);
|
||||
in
|
||||
{
|
||||
config.systemd.services = namespaceGlobalService // networkServices;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue