profiles/ds-lite: Connect to Netcologne with PPP DS-Lite
This commit is contained in:
		| @@ -6,6 +6,7 @@ | ||||
|       ./hardware-configuration.nix | ||||
|  | ||||
|       ./dns.nix | ||||
|       ./ds-lite-ncfttb.nix | ||||
|       ./mdns.nix | ||||
|       ./net-dsl.nix | ||||
|       ./net-gastnetz.nix | ||||
| @@ -16,7 +17,7 @@ | ||||
|       ./net-printer.nix | ||||
|       ./net-voip.nix | ||||
|       ./ntp.nix | ||||
|       ./ppp.nix | ||||
|       ./ppp-ncfttb.nix | ||||
|       ./scan-to-gpg.nix | ||||
|       ./wg-clerie.nix | ||||
|     ]; | ||||
|   | ||||
							
								
								
									
										18
									
								
								hosts/carbon/ds-lite-ncfttb.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								hosts/carbon/ds-lite-ncfttb.nix
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| { ... }: | ||||
|  | ||||
| { | ||||
|  | ||||
|   profiles.clerie.ds-lite = { | ||||
|     enable = true; | ||||
|     wanInterfaceName = "ppp-ncfttb"; | ||||
|     tunnelInterfaceName = "ds-lite-ncfttb"; | ||||
|     lanInterfaces = [ | ||||
|       { | ||||
|         name = "net-heimnetz"; | ||||
|         sla_id = 201; | ||||
|         prefix_len = 64; | ||||
|       } | ||||
|     ]; | ||||
|   }; | ||||
|  | ||||
| } | ||||
							
								
								
									
										12
									
								
								pkgs/ds-lite-dhcpcd-hook/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								pkgs/ds-lite-dhcpcd-hook/default.nix
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| { pkgs, ... }: | ||||
|  | ||||
| pkgs.writeShellApplication { | ||||
|   name = "ds-lite-dhcpcd-hook"; | ||||
|   text = builtins.readFile ./ds-lite-dhcpcd-hook.sh; | ||||
|   runtimeInputs = with pkgs; [ | ||||
|     iproute2 | ||||
|     jq | ||||
|     dig | ||||
|     gawk | ||||
|   ]; | ||||
| } | ||||
							
								
								
									
										102
									
								
								pkgs/ds-lite-dhcpcd-hook/ds-lite-dhcpcd-hook.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								pkgs/ds-lite-dhcpcd-hook/ds-lite-dhcpcd-hook.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| set -euo pipefail | ||||
|  | ||||
| # Setting up required environment variables | ||||
| # shellcheck disable=SC2154 | ||||
| WAN_INTERFACE_NAME="${DS_LITE_WAN_INTERFACE_NAME}" | ||||
| # shellcheck disable=SC2154 | ||||
| TUNNEL_INTERFACE_NAME="${DS_LITE_TUNNEL_INTERFACE_NAME}" | ||||
|  | ||||
| log_dhcp () { | ||||
| 	echo "<ds-lite-dhcpcd-hook> ${WAN_INTERFACE_NAME}: $1" | ||||
| } | ||||
|  | ||||
| log_tunnel () { | ||||
| 	echo "<ds-lite-dhcpcd-hook> ${WAN_INTERFACE_NAME} (${TUNNEL_INTERFACE_NAME}): $1" | ||||
| } | ||||
|  | ||||
| # Check if the event calling this hook is for the wan interface | ||||
| # exit immediately if not | ||||
| # shellcheck disable=SC2154 | ||||
| if [[ "$interface" != "$WAN_INTERFACE_NAME" ]]; then | ||||
| 	exit | ||||
| fi | ||||
|  | ||||
| # Make sure the event calling this hook carries the environment variable | ||||
| # in question. The environment variable is not provided with every call | ||||
| # and we just want to exit if it is not provided | ||||
| # shellcheck disable=SC2154 | ||||
| if [[ ! -v new_dhcp6_aftr_name ]]; then | ||||
| 	# Variable is not set | ||||
| 	exit | ||||
| fi | ||||
| # shellcheck disable=SC2154 | ||||
| if [[ -z "${new_dhcp6_aftr_name}" ]]; then | ||||
| 	# Variable is empty, can't do anything | ||||
| 	exit | ||||
| fi | ||||
|  | ||||
| # shellcheck disable=SC2154 | ||||
| AFTR_NAME="$new_dhcp6_aftr_name" | ||||
|  | ||||
| log_dhcp "Received new AFTR_NAME ${AFTR_NAME}" | ||||
|  | ||||
| # Make sure we have a nameserver to resolve aftr name against | ||||
| # shellcheck disable=SC2154 | ||||
| if [[ ! -v new_dhcp6_name_servers ]]; then | ||||
| 	# Variable is not set | ||||
| 	exit | ||||
| fi | ||||
| # shellcheck disable=SC2154 | ||||
| if [[ -z "${new_dhcp6_name_servers}" ]]; then | ||||
| 	# Variable is empty, can't do anything | ||||
| 	exit | ||||
| fi | ||||
|  | ||||
| # shellcheck disable=SC2154 | ||||
| NAME_SERVERS="$new_dhcp6_name_servers" | ||||
|  | ||||
| log_dhcp "Received new NAME_SERVERS ${NAME_SERVERS}" | ||||
|  | ||||
| # Select first nameserver | ||||
| NAME_SERVER="$(echo "${NAME_SERVERS}" | awk '{print $1;}')" | ||||
|  | ||||
| log_dhcp "Selected NAME_SERVER ${NAME_SERVER}" | ||||
|  | ||||
| # Figure out a usable IPv6 address on the wan interface, to origin our DNS requests and tunnel | ||||
| WAN_INTERFACE_ADDRESS="$(ip --json address show "${WAN_INTERFACE_NAME}" | jq -r '.[0].addr_info[] | select(.family == "inet6" and .scope == "global" and .mngtmpaddr == true) | .local')" | ||||
|  | ||||
| log_dhcp "Using WAN_INTERFACE_ADDRESS ${WAN_INTERFACE_ADDRESS}" | ||||
|  | ||||
| AFTR_ADDRESS="$(dig "@${NAME_SERVER}" -b "${WAN_INTERFACE_ADDRESS}" AAAA "${AFTR_NAME}" +short | head -1)" | ||||
|  | ||||
| log_dhcp "Resolved AFTR_NAME ${AFTR_NAME} to ${AFTR_ADDRESS}" | ||||
|  | ||||
| # Check if there is already a tunnel interface | ||||
| if TUNNEL_INTERFACE_CONFIG="$(ip --json link show "${TUNNEL_INTERFACE_NAME}")"; then | ||||
| 	TUNNEL_INTERFACE_OPERSTATE="$(echo "${TUNNEL_INTERFACE_CONFIG}" | jq -r '.[0].operstate')" | ||||
| 	TUNNEL_INTERFACE_ORIGIN_ADDRESS="$(echo "${TUNNEL_INTERFACE_CONFIG}" | jq -r '.[0].address')" | ||||
| 	TUNNEL_INTERFACE_REMOTE_ADDRESS="$(echo "${TUNNEL_INTERFACE_CONFIG}" | jq -r '.[0].broadcast')" | ||||
|  | ||||
| 	# Reconfigure tunnel interface, if not already in state we want | ||||
| 	if [[ "${TUNNEL_INTERFACE_ORIGIN_ADDRESS}" != "${WAN_INTERFACE_ADDRESS}" || "${TUNNEL_INTERFACE_REMOTE_ADDRESS}" != "${AFTR_ADDRESS}" || "${TUNNEL_INTERFACE_OPERSTATE}" != "UNKNOWN" ]]; then | ||||
| 		log_tunnel "Bad configuration, fixing tunnel parameter" | ||||
|  | ||||
| 		ip tunnel change "${TUNNEL_INTERFACE_NAME}" mode ipip6 local "${WAN_INTERFACE_ADDRESS}" remote "${AFTR_ADDRESS}" | ||||
| 		ip link set "$TUNNEL_INTERFACE_NAME" up | ||||
| 	else | ||||
| 		log_tunnel "Tunnel already configured" | ||||
| 	fi | ||||
| else | ||||
| 	log_tunnel "Setting up DS-Lite tunnel" | ||||
|  | ||||
| 	ip tunnel add "${TUNNEL_INTERFACE_NAME}" mode ipip6 local "${WAN_INTERFACE_ADDRESS}" remote "${AFTR_ADDRESS}" | ||||
| 	ip link set "$TUNNEL_INTERFACE_NAME" up | ||||
| fi | ||||
|  | ||||
| log_tunnel "Setting default route" | ||||
|  | ||||
| ip route replace default dev "${TUNNEL_INTERFACE_NAME}" | ||||
|  | ||||
| log_tunnel "Tunnel setup finished" | ||||
| @@ -14,6 +14,7 @@ final: prev: { | ||||
|   chromium-incognito = final.callPackage ./chromium-incognito {}; | ||||
|   convert-flac-dir-to-mp3 = final.callPackage ./convert-flac-dir-to-mp3 {}; | ||||
|   curl-timings = final.callPackage ./curl-timings {}; | ||||
|   ds-lite-dhcpcd-hook = final.callPackage ./ds-lite-dhcpcd-hook {}; | ||||
|   factorio-launcher = final.callPackage ./factorio-launcher {}; | ||||
|   feeds-dir = final.callPackage ./feeds-dir {}; | ||||
|   generate-blocked-prefixes = final.callPackage ./generate-blocked-prefixes {}; | ||||
|   | ||||
							
								
								
									
										20
									
								
								pkgs/overrides/ds-lite-dhcpcd.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								pkgs/overrides/ds-lite-dhcpcd.nix
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| final: prev: | ||||
| prev.dhcpcd.overrideAttrs (finalAttrs: prevAttrs: { | ||||
|  | ||||
|   configureFlags = [ | ||||
|     "--sysconfdir=/etc/ds-lite-dhcpcd" | ||||
|     "--localstatedir=/var" | ||||
|     "--disable-fork" | ||||
|     "--disable-privsep" | ||||
|     "--dbdir=/var/lib/ds-lite-dhcpcd" | ||||
|     "--rundir=/var/run/ds-lite-dhcpcd" | ||||
|     "--with-default-hostname=ds-lite" | ||||
|     "--disable-ipv4" | ||||
|     "--disable-arp" | ||||
|     "--disable-arpping" | ||||
|     "--disable-ipv4ll" | ||||
|     "--disable-ntp" | ||||
|   ]; | ||||
|  | ||||
| }) | ||||
|  | ||||
| @@ -1,4 +1,5 @@ | ||||
| final: prev: { | ||||
|   dino = import ./dino.nix final prev; | ||||
|   ds-lite-dhcpcd = import ./ds-lite-dhcpcd.nix final prev; | ||||
|   xmppc = import ./xmppc.nix final prev; | ||||
| } | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
|     ./cybercluster-vm | ||||
|     ./desktop | ||||
|     ./dn42-router | ||||
|     ./ds-lite | ||||
|     ./fem-net | ||||
|     ./firefox | ||||
|     ./gpg-ssh | ||||
|   | ||||
							
								
								
									
										150
									
								
								profiles/ds-lite/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								profiles/ds-lite/default.nix
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | ||||
| { config, lib, pkgs, ... }: | ||||
|  | ||||
| with lib; | ||||
|  | ||||
| let | ||||
|  | ||||
|   cfg = config.profiles.clerie.ds-lite; | ||||
|  | ||||
|  | ||||
|   dsLiteDhcpcdConfig = '' | ||||
|     allowinterfaces ${cfg.wanInterfaceName} ${concatMapStringsSep " " (interface: interface.name) cfg.lanInterfaces} | ||||
|  | ||||
|     option dhcp6_name_servers | ||||
|     option dhcp6_aftr_name | ||||
|  | ||||
|     waitip 6 | ||||
|  | ||||
|     ipv6only | ||||
|     ipv6ra_noautoconf | ||||
|     noipv6rs | ||||
|  | ||||
|     interface ${cfg.wanInterfaceName} | ||||
|       ipv6ra_autoconf | ||||
|       ipv6rs | ||||
|       ia_pd 1/::/48 ${concatMapStringsSep " " (interface: "${interface.name}/${toString interface.sla_id}/${toString interface.prefix_len}") cfg.lanInterfaces} | ||||
|  | ||||
|     ${concatMapStrings (interface: '' | ||||
|     interface ${interface.name} | ||||
|       nolink | ||||
|     '') cfg.lanInterfaces} | ||||
|   ''; | ||||
|  | ||||
|   dsLiteDhcpcdConfigFile = pkgs.writeTextFile { | ||||
|     name = "dhcpcd.conf"; | ||||
|     text = dsLiteDhcpcdConfig; | ||||
|   }; | ||||
|  | ||||
|   dsLiteDhcpcdHookWrapperFile = pkgs.writeShellScript "ds-lite-dhcpcd-hook-wrapper" '' | ||||
|     DS_LITE_WAN_INTERFACE_NAME=${lib.escapeShellArg cfg.wanInterfaceName}; | ||||
|     export DS_LITE_WAN_INTERFACE_NAME | ||||
|     DS_LITE_TUNNEL_INTERFACE_NAME=${lib.escapeShellArg cfg.tunnelInterfaceName}; | ||||
|     export DS_LITE_TUNNEL_INTERFACE_NAME | ||||
|  | ||||
|     exec ${lib.getExe pkgs.ds-lite-dhcpcd-hook} | ||||
|   ''; | ||||
|  | ||||
| in { | ||||
|  | ||||
|   options.profiles.clerie.ds-lite = { | ||||
|     enable = mkEnableOption "DS-Lite setup"; | ||||
|     wanInterfaceName = mkOption { | ||||
|       type = types.str; | ||||
|       description = "Interface with IPv6 connectivity to provider"; | ||||
|     }; | ||||
|     tunnelInterfaceName = mkOption { | ||||
|       type = types.str; | ||||
|       description = "Interface with IPv4 connectivity to provider"; | ||||
|     }; | ||||
|     lanInterfaces = mkOption { | ||||
|       type = with types; listOf (submodule ({ ... }: { | ||||
|         options = { | ||||
|           name = mkOption { | ||||
|             type = types.str; | ||||
|           }; | ||||
|           sla_id = mkOption { | ||||
|             type = types.ints.unsigned; | ||||
|           }; | ||||
|           prefix_len = mkOption { | ||||
|             type = types.ints.between 48 128; | ||||
|           }; | ||||
|         }; | ||||
|       })); | ||||
|       default = []; | ||||
|       description = "Interfaces to provisn with an IPv6 prefix"; | ||||
|     }; | ||||
|   }; | ||||
|  | ||||
|   config = mkIf cfg.enable { | ||||
|     systemd.services.ds-lite-dhcpcd = { | ||||
|       description = "DS-Lite dhcpcd"; | ||||
|  | ||||
|       wantedBy = [ "multi-user.target" ]; | ||||
|  | ||||
|       environment = { | ||||
|       }; | ||||
|  | ||||
|       serviceConfig = { | ||||
|         Type = "simple"; | ||||
|         User = "ds-lite"; | ||||
|         Group = "ds-lite"; | ||||
|         StateDirectory = "ds-lite-dhcpcd"; | ||||
|         RuntimeDirectory = "ds-lite-dhcpcd"; | ||||
|  | ||||
|         ExecStart = "${pkgs.ds-lite-dhcpcd}/bin/dhcpcd --ipv6only --nobackground --config ${dsLiteDhcpcdConfigFile} --script ${dsLiteDhcpcdHookWrapperFile}"; | ||||
|  | ||||
|         Restart = "always"; | ||||
|         AmbientCapabilities = [ | ||||
|           "CAP_NET_ADMIN" | ||||
|           "CAP_NET_RAW" | ||||
|           "CAP_NET_BIND_SERVICE" | ||||
|         ]; | ||||
|         ReadWritePaths = [ | ||||
|           "/proc/sys/net/ipv6" | ||||
|         ]; | ||||
|         DeviceAllow = ""; | ||||
|         LockPersonality = true; | ||||
|         MemoryDenyWriteExecute = true; | ||||
|         PrivateDevices = true; | ||||
|         PrivateMounts = true; | ||||
|         PrivateTmp = true; | ||||
|         PrivateUsers = false; | ||||
|         ProtectClock = true; | ||||
|         ProtectControlGroups = true; | ||||
|         ProtectHome = "tmpfs"; # allow exceptions to be added to ReadOnlyPaths, etc. | ||||
|         ProtectHostname = true; | ||||
|         ProtectKernelLogs = true; | ||||
|         ProtectKernelModules = true; | ||||
|         ProtectKernelTunables = true; | ||||
|         ProtectProc = "invisible"; | ||||
|         ProtectSystem = "strict"; | ||||
|         RemoveIPC = true; | ||||
|         RestrictAddressFamilies = [ | ||||
|           "AF_UNIX" | ||||
|           "AF_INET" | ||||
|           "AF_INET6" | ||||
|           "AF_NETLINK" | ||||
|           "AF_PACKET" | ||||
|         ]; | ||||
|         RestrictNamespaces = true; | ||||
|         RestrictRealtime = true; | ||||
|         RestrictSUIDSGID = true; | ||||
|         SystemCallFilter = [ | ||||
|           "@system-service" | ||||
|           "~@keyring" | ||||
|           "~@memlock" | ||||
|           "~@mount" | ||||
|         ]; | ||||
|         SystemCallArchitectures = "native"; | ||||
|         UMask = "0027"; | ||||
|       }; | ||||
|     }; | ||||
|  | ||||
|     users.users.ds-lite = { | ||||
|       isSystemUser = true; | ||||
|       group = "ds-lite"; | ||||
|     }; | ||||
|     users.groups.ds-lite = { }; | ||||
|   }; | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user