From d291098e50b2817508a3f4b9eeb44f01a7e6195f Mon Sep 17 00:00:00 2001 From: Robert Pufky Date: Sat, 3 Jul 2021 21:06:25 -0700 Subject: [PATCH] Initial wireguard-initramfs commit. --- Makefile | 47 +++++++++++++++++++++++++ README.md | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++ config | 40 +++++++++++++++++++++ hooks | 46 ++++++++++++++++++++++++ init-bottom | 21 +++++++++++ init-premount | 86 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 337 insertions(+) create mode 100644 Makefile create mode 100644 config create mode 100755 hooks create mode 100755 init-bottom create mode 100755 init-premount diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..348a673 --- /dev/null +++ b/Makefile @@ -0,0 +1,47 @@ +# Makefile for wireguard initramfs boot. + +# You can set these variables from the command line, and also +# from the environment for the first two. +TARGETDIR = /etc/wireguard-initramfs +INITRAMFS = /usr/share/initramfs-tools + +help: + @echo "USAGE:" + @echo " make install" + @echo " Install wireguard-initramfs and default configuration files." + @echo " Requires additional configuration!" + @echo + @echo " make uninstall" + @echo " Remove wireguard-initramfs from initramfs, leaves " + @echo " $(TARGETDIR). Does not need to be installed." + @echo + +.PHONY: help Makefile + +install: + @if ! [ "$(shell id -u)" = 0 ]; then echo "You must be root to perform this action."; exit 1; fi + @echo "Installing wireguard-initramfs ..." + @apt update && apt install initramfs-tools + @mkdir -p "$(TARGETDIR)" + @touch "$(TARGETDIR)/private_key" + @chmod 0400 "$(TARGETDIR)/private_key" + @cp -v config "$(TARGETDIR)/config" + @chmod 0644 "$(TARGETDIR)/config" + @cp -v hooks "$(INITRAMFS)/hooks/wireguard" + @cp -v init-premount "$(INITRAMFS)/scripts/init-premount/wireguard" + @cp -v init-bottom "$(INITRAMFS)/scripts/init-bottom/wireguard" + @echo "Done." + @echo + @echo "Setup $(TARGETDIR)/config and run:" + @echo + @echo " update-initramfs -u && update-grub" + @echo "Done." + +uninstall: + @if ! [ "$(shell id -u)" = 0 ]; then echo "You must be root to perform this action."; exit 1; fi + @echo "Uninstalling wireguard-initramfs ..." + @rm -f "$(INITRAMFS)/hooks/wireguard" + @rm -f "$(INITRAMFS)/scripts/init-premount/wireguard" + @rm -f "$(INITRAMFS)/scripts/init-bottom/wireguard" + @echo "Done." + @echo diff --git a/README.md b/README.md index 3ea2b0c..f9ef2c7 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,99 @@ # wireguard-initramfs Use dropbear over wireguard. +Start wireguard network during kernel init; enabling dropbear use over wireguard! + +Enables wireguard networking during kernel boot, before encrypted partitions +are mounted. Combined with [dropbear](https://github.com/mkj/dropbear) this +can enable FULLY ENCRYPTED remote booting without storing key material or +exposing ports on the remote network. An Internet connection simply needs to +exist that can reach the wireguard endpoint. + +Normal dropbear connections can still be used, as well as DNS resolution to +find wireguard endpoints. This essentially enables the creation of a fully +encrypted remote managed node, with the ability to prevent all local access. + +## Requirements +Working knowledge of Linux. Understanding of networking and how Dropbear, +Wireguard work. + +1. [Debian Bullseye](debian.org) (any version with wireguard support should work, but untested). +1. [Dropbear](https://github.com/mkj/dropbear) installed, configured and in a "known working" state. +1. [Wireguard](https://www.wireguard.com/) installed, configured and in a "known working" state. + +## Install +Installation is automated via make. Download, extract contents, and install on +target machine. + +Grab the latest release, untarball, and install. +```bash +wget https://github.com/r-pufky/wireguard-initramfs/archive/refs/tags/2021-07-03.tar.gz +tar xvf 2021-07-03.tar.gz +cd wireguard-initramfs-2021-07-03; make install +``` + +## Configure +Configuration is explained within `/etc/wireguard-initramfs/config`. Be sure to +set the private key as well. + +Restricting dropbear connections to **only** wireguard: + Confirm wireguard/dropbear work without restriction first. + + Set dropbear listen address to only wireguard client interface address. + Using example configuration: + + /etc/dropbear-initramfs/config + ```bash + DROPBEAR_OPTIONS='... -p 172.31.255.10:22 ...' + ``` + +Refer to [wg set man page](https://man7.org/linux/man-pages/man8/wg.8.html) for +additional information. + +:warning: +Most installs do not currently encrypt `/boot`; and therefore the client's +private key should be considered **untrusted/compromised**. It is highly +recommended that a separate wireguard network is used to for remote unlocking. + +Rebuild initramfs to use: +```bash +update-initramfs -u +update-grub +reboot +``` + +Any static errors will abort the build. Mis-configurations will not be caught; +test this where you can easily get physical access to the machine if something +goes wrong. + +## FAQ +Q: **I want to use this, but without dropbear** + +> A: Supported; just remove the pre-requisite dependency for `init-bottom`: +> +> `/usr/share/initramfs-tools/init-bottom/wireguard` +> ```bash +> #PREREQ="dropbear" +> PREREQ="" +> ``` +> +> and rebuild the initramfs image. + +Q: **I want to restrict dropbear to only wireguard** + +> A: Supported. Confirm wireguard works before restricting normal networks. +> +> Restricting dropbear connections to **only** wireguard: +> Confirm wireguard/dropbear work without restriction first. +> +> Set dropbear listen address to only wireguard client interface address. +> Using example configuration: +> +> /etc/dropbear-initramfs/config +> ```bash +> DROPBEAR_OPTIONS='... -p 172.31.255.10:22 ...' +> ``` + +## Bug / Patches / Contributions? +All are welcome, please submit a pull request or open a bug! + +Know debian packaging? Create a .deb package for this! diff --git a/config b/config new file mode 100644 index 0000000..1175a2d --- /dev/null +++ b/config @@ -0,0 +1,40 @@ +# Wireguard initramfs configuration. +# +# NOTE: As most systems do not encrypt /boot, private key material is exposed +# and compromised/untrusted. Boot wireguard network should be +# **different** & untrusted, versus the network used after booting. +# +# Be sure to test wireguard config with a running system before setting +# options. See: https://manpages.debian.org/unstable/wireguard-tools/wg.8.en.html +# +# Restricting dropbear connections to **only** wireguard: +# Confirm wireguard/dropbear work without restriction first. +# +# Set dropbear listen address to only wireguard client interface address. +# Using example configuration: +# +# /etc/dropbear-initramfs/config +# ... +# DROPBEAR_OPTIONS='... -p 172.31.255.10:22 ...' +# + +# Wireguard interface name. +INTERFACE=example_vpn + +# CIDR wireguard interface address. +INTERFACE_ADDR=172.31.255.10/32 + +# Peer public key (server's public key) +PEER_PUBLIC_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +# IP:PORT of the peer (server); any reachable IP/DNS. +PEER_ENDPOINT=wg.example.com:51820 + +# Client Private key. Specify location of file containing only the private key. +CLIENT_PRIVATE_KEYFILE=/etc/wireguard-initramfs/private_key + +# Keepalives. Required to ensure connection for non-exposed ports. +PERSISTENT_KEEPALIVES=25 + +# CIDR IP's allowed on wireguard connection, typically the peer (server) +ALLOWED_IPS=172.31.255.254/32 diff --git a/hooks b/hooks new file mode 100755 index 0000000..f56a29d --- /dev/null +++ b/hooks @@ -0,0 +1,46 @@ +#!/bin/sh + +PREREQ="" + +prereqs() { + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +. /usr/share/initramfs-tools/hook-functions + +CONFIG='/etc/wireguard-initramfs/config' + +# Validate and copy configuration to initramfs +if [ ! -s "${CONFIG}" ]; then + echo "Wireguard initramfs config required. Missing: ${CONFIG}" + return 1 +fi +. "${CONFIG}" +if [ ! -s "${CLIENT_PRIVATE_KEYFILE}" ]; then + echo "Wireguard client private key required. Missing: ${CLIENT_PRIVATE_KEYFILE}" + return 1 +fi + +# Copy latest versions of shared objects needed for DNS resolution +for so in $(ldconfig -p | sed -nr 's/^\s*libnss_files\.so\.[0-9]+\s.*=>\s*//p'); do + copy_exec "${so}" +done +for so in $(ldconfig -p | sed -nr 's/^\s*libnss_dns\.so\.[0-9]+\s.*=>\s*//p'); do + copy_exec "${so}" +done + +# Copy config and host keys +mkdir -p -- "${DESTDIR}/etc/wireguard" +cp -p "${CONFIG}" "${DESTDIR}/etc/wireguard" +cp -p "${CLIENT_PRIVATE_KEYFILE}" "${DESTDIR}/etc/wireguard/private_key" + +# Add modules and wireguard exec +manual_add_modules wireguard +copy_exec /usr/bin/wg /sbin diff --git a/init-bottom b/init-bottom new file mode 100755 index 0000000..bf9971a --- /dev/null +++ b/init-bottom @@ -0,0 +1,21 @@ +#!/bin/sh + +PREREQ="dropbear" + +prereqs() { + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +. /scripts/functions + +. /etc/wireguard/config +log_begin_msg 'Stopping wireguard boot network' +ip link delete dev ${INTERFACE} +log_end_msg diff --git a/init-premount b/init-premount new file mode 100755 index 0000000..f5b3346 --- /dev/null +++ b/init-premount @@ -0,0 +1,86 @@ +#!/bin/sh + +PREREQ="udev" + +prereqs() { + echo "${PREREQ}" +} + +case "${1}" in + prereqs) + prereqs + exit 0 + ;; +esac + +. /scripts/functions + +if [ ! -e /sbin/wg ]; then + log_failure_msg 'Wireguard binary not found, skipping setup' + exit 0 +fi +if [ ! -e /etc/wireguard/config ]; then + log_failure_msg 'Wireguard config not found, skipping setup' + exit 0 +fi +if [ ! -e /etc/wireguard/private_key ]; then + log_failure_msg 'Wireguard client private key not found, skipping setup' + exit 0 +fi + +log_begin_msg 'Loading wireguard config' +. /etc/wireguard/config + +if [ -z ${INTERFACE} ]; then + log_failure_msg 'Interface name is not defined!' + return 1 +fi + +if [ -z ${INTERFACE_ADDR} ]; then + log_failure_msg 'Interface address is not defined!' + return 1 +fi + +if [ -z ${PEER_PUBLIC_KEY} ]; then + log_failure_msg 'Peer Public Key is not defined!' + return 1 +fi + +if [ -z ${PEER_ENDPOINT} ]; then + log_failure_msg 'Peer endpoint is not defined!' + return 1 +fi + +if [ -z ${PERSISTENT_KEEPALIVES} ]; then + log_failure_msg 'Persistent Keep Alives is not defined!' + return 1 +fi + +if [ -z ${ALLOWED_IPS} ]; then + log_failure_msg 'Allowed IPs is not defined!' + return 1 +fi +log_end_msg + +log_begin_ms 'Starting wireguard' + +# Ensure networking is started (idempotent) and setup DNS. +configure_networking +touch /etc/resolv.conf +for adapter in /run/net-*.conf; do + source "${adapter}" + echo nameserver "${IPV4DNS0}" >> /etc/resolv.conf + echo nameserver "${IPV4DNS1}" >> /etc/resolv.conf +done + +ip link add dev ${INTERFACE} type wireguard +/sbin/wg set ${INTERFACE} \ + private-key /etc/wireguard/private_key \ + peer ${PEER_PUBLIC_KEY} \ + endpoint ${PEER_ENDPOINT} \ + persistent-keepalive ${PERSISTENT_KEEPALIVES} \ + allowed-ips ${ALLOWED_IPS} +ip addr add ${INTERFACE_ADDR} dev ${INTERFACE} +ip link set ${INTERFACE} up +ip route add ${ALLOWED_IPS} dev ${INTERFACE} +log_end_msg