Index: libexec/rc/rc.d/wireguard =================================================================== --- /dev/null +++ libexec/rc/rc.d/wireguard @@ -0,0 +1,114 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# PROVIDE: wireguard +# REQUIRE: LOGIN +# KEYWORD: shutdown +# +# Add the following lines to /etc/rc.conf.local or /etc/rc.conf +# to enable this service: +# +# wireguard_enable: Set to YES to enable wireguard. +# wireguard_iface: Optional name of wireguard interface. +# wireguard_local_hostname: Optional name to drop from peer list +# wireguard_local_route: Route to be passed to route(8) +# wireguard_peers: List of names of peers to configure. +# wireguard_peer_P_allowed_ips: Accepted IPs for remote peer. +# wireguard_peer_P_endpoint: Expected IP:port for remote peer. +# wireguard_peer_P_public_key: Wireguard public key. + +# the private key will be created on first use +# the public key will be derived from the private key on first load + +# peers go here +wireguard_peers="wintermute straylight continuity" + +# each peer has mandatory, and optional parameters +# mandatory: public_key +# optional: allowed_ips, endpoint, ... pre / post scripts + +# wireguard_peer_continuity_allowed_ips=10.0.0.8/32 +# wireguard_peer_continuity_endpoint=172.16.1.8:54321 +# wireguard_peer_continuity_public_key="jZ+j0du3r3MZJRXXrzUXRT62R+/FUNeraI+F9YfmzD0=" + +. /etc/rc.subr + +name=wireguard +rcvar=wireguard_enable +desc="configure wireguard network interface" + +load_rc_config $name + +: ${wireguard_enable="NO"} +: ${wireguard_iface="wg0"} +: ${wireguard_local_hostname="`hostname -s`"} + +# required_modules=if_wg + +command=/usr/bin/true +start_cmd="${name}_start" +stop_cmd="${name}_stop" +start_precmd="${name}_precmd" + +wireguard_precmd() +{ + if checkyesno wireguard_enable; then + # create private key material if not already present + test -d /etc/wireguard || mkdir -m 0750 /etc/wireguard + umask 077 + if ! test -O /etc/wireguard/private.key; then + # ensure a new public key is minted when interface is created + rm -f /etc/wireguard/public.key + echo "wg: generating new private key" + /usr/bin/openssl rand -base64 32 -out /etc/wireguard/private.key + fi + fi +} + +wireguard_start() +{ + local MYNAME MYPORT MYIP PEER ENDPOINT ALLOWED PUBKEY + MYNAME=${wireguard_local_hostname} + eval MYPORT=\${wireguard_peer_${MYNAME}_endpoint##*:} + eval MYIP=\${wireguard_peer_${MYNAME}_allowed_ips%%/*} + + # bring up the interface with private key but obscure it from stdout + /sbin/ifconfig ${wireguard_iface} create \ + listen-port ${MYPORT} \ + private-key $(cat /etc/wireguard/private.key) \ + | sed -E -e 's/public-key:.+/public-key: .../' + + # generate the public key for posterity + if ! test -e /etc/wireguard/public.key; then + echo -n "wg: deriving public key: " + /sbin/ifconfig ${wireguard_iface} \ + | egrep -o public-key:.+ \ + | cut -wf 2 \ + | tee /etc/wireguard/public.key + echo -e + fi + + # create peer entries + for PEER in $(echo ${wireguard_peers} | sed -e s/${MYNAME}//); do + eval ALLOWED=\$wireguard_peer_${PEER}_allowed_ips + eval PUBKEY=\$wireguard_peer_${PEER}_public_key + eval ENDPOINT=\$wireguard_peer_${PEER}_endpoint + /sbin/ifconfig ${wireguard_iface} peer \ + public-key ${PUBKEY} \ + endpoint ${ENDPOINT} \ + allowed-ips ${ALLOWED} + done + + # assign IP to interface and update routing + /sbin/ifconfig ${wireguard_iface} ${MYIP} + /sbin/route add ${wireguard_local_route} ${MYIP} +} + +wireguard_stop() +{ + /sbin/ifconfig ${wireguard_iface} destroy +} + +run_rc_command "$1"