From 33f0698f1e5c064c31fa88fa17a7eb93ceaf1066 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Thu, 14 Mar 2019 06:46:09 +0100 Subject: [PATCH] tuto2: wg working --- .gitignore | 2 ++ Makefile | 16 +++++---- pkg/debian-tuto2/Dockerfile | 6 ++++ pkg/debian-tuto2/default.script | 60 +++++++++++++++++++++++++++++++ pkg/debian-tuto2/isolinux.cfg | 30 ++++++++++++++++ pkg/debian-tuto2/sshd_config | 2 +- token-validator/handler.go | 2 +- token-validator/wg.go | 46 ++++++++++++++++++------ tuto2.yml | 62 ++++++++++++++++++++++++++------- 9 files changed, 196 insertions(+), 30 deletions(-) create mode 100755 pkg/debian-tuto2/default.script create mode 100644 pkg/debian-tuto2/isolinux.cfg diff --git a/.gitignore b/.gitignore index 8028011..983f55f 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ server-kernel tuto2-cmdline tuto2-initrd.img tuto2.iso +tuto2-srs.iso +tuto2-srs.iso.gz tuto2-kernel tuto2-state/ tuto3-cmdline diff --git a/Makefile b/Makefile index df6e308..cfce479 100644 --- a/Makefile +++ b/Makefile @@ -33,14 +33,18 @@ tuto2-initrd.img: tuto2.yml tuto2-cmdline: tuto2.yml linuxkit build $< -tuto2.iso: pkg/debian-tuto2/isolinux.cfg tuto2-kernel tuto2-initrd.img tuto2-cmdline +tuto2.iso: tuto2.yml tuto2-kernel tuto2-initrd.img tuto2-cmdline + linuxkit build -format iso-bios $< + +tuto2-srs.iso: tuto2.iso pkg/debian-tuto2/isolinux.cfg $(eval TDIR := $(shell mktemp -d)) - mkdir $(TDIR)/boot/ $(TDIR)/isolinux/ - cp tuto2-kernel $(TDIR)/boot/kernel - cp tuto2-initrd.img $(TDIR)/boot/tuto2ird.img + bsdtar xf $< -C $(TDIR) cp pkg/debian-tuto2/isolinux.cfg /usr/share/syslinux/isolinux.bin /usr/share/syslinux/ldlinux.c32 /usr/share/syslinux/vesamenu.c32 /usr/share/syslinux/menu.c32 /usr/share/syslinux/libcom32.c32 /usr/share/syslinux/libutil.c32 /usr/share/syslinux/poweroff.c32 $(TDIR)/isolinux/ - $(eval CMDLINE := $(shell cat tuto2-cmdline)) + $(eval CMDLINE := $(shell cat tuto2-cmdline | sed 's/console=ttyS0 //;s#root=/dev/sr0 ##;s#root=/dev/sda1 ##;s#adlin.format=/dev/sda ##;')) sed -i 's##$(CMDLINE)#' $(TDIR)/isolinux/isolinux.cfg - genisoimage -o $@ -l -J -R -c isolinux/boot.cat -b isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table -joliet-long -input-charset utf8 -V AdLin2 $(TDIR) + mkisofs -o $@ -l -J -R -c isolinux/boot.cat -b isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table -joliet-long -input-charset utf8 -V AdLin2 $(TDIR) rm -rf $(TDIR) isohybrid $@ + +tuto2-srs.iso.gz: tuto2-srs.iso + gzip -9 < $< > $@ diff --git a/pkg/debian-tuto2/Dockerfile b/pkg/debian-tuto2/Dockerfile index a4ab110..1cdfe16 100644 --- a/pkg/debian-tuto2/Dockerfile +++ b/pkg/debian-tuto2/Dockerfile @@ -2,10 +2,13 @@ FROM debian RUN apt-get update && apt-get install --no-install-recommends -y \ busybox \ + ca-certificates \ console-data \ cron \ + curl \ ifupdown \ kbd \ + kmod \ nano \ openssh-server \ python \ @@ -15,10 +18,13 @@ RUN apt-get update && apt-get install --no-install-recommends -y \ vim.tiny \ && rm -rf /var/lib/apt/lists/* +RUN curl -L -o /tmp/wireguard.deb http://httpredir.debian.org/debian/pool/main/w/wireguard/wireguard-tools_0.0.20190227-1_amd64.deb && dpkg -i /tmp/wireguard.deb; rm /tmp/wireguard.deb + RUN rm -rf /etc/init.d/ && \ mkdir /overlay && \ ln -sf /init /sbin/init && \ ln -sf /lib/systemd/system/systemd-netwkord.service /etc/systemd/system/multi-user.target.wants/systemd-networkd.service +COPY default.script /etc/udhcpc/default.script COPY issue /etc/issue COPY sshd_config /etc/ssh/sshd_config diff --git a/pkg/debian-tuto2/default.script b/pkg/debian-tuto2/default.script new file mode 100755 index 0000000..5790c61 --- /dev/null +++ b/pkg/debian-tuto2/default.script @@ -0,0 +1,60 @@ +#!/bin/sh +# Busybox udhcpc dispatcher script. Copyright (C) 2009 by Axel Beckert. +# +# Based on the busybox example scripts and the old udhcp source +# package default.* scripts. + +RESOLV_CONF="/etc/resolv.conf" + +case $1 in + bound|renew) + /bin/ip address add dev $interface $ip/$subnet + + if [ -n "$router" ]; then + echo "$0: Resetting default routes" + while /bin/ip route del default via 0.0.0.0 dev $interface; do :; done + + metric=0 + for i in $router; do + /bin/ip route add default via $i dev $interface metric $metric + metric=$(($metric + 1)) + done + fi + + # Update resolver configuration file + R="" + [ -n "$domain" ] && R="domain $domain +" + for i in $dns; do + echo "$0: Adding DNS $i" + R="${R}nameserver $i +" + done + + if [ -x /sbin/resolvconf ]; then + echo -n "$R" | resolvconf -a "${interface}.udhcpc" + else + echo -n "$R" > "$RESOLV_CONF" + fi + ;; + + deconfig) + if [ -x /sbin/resolvconf ]; then + resolvconf -d "${interface}.udhcpc" + fi + /bin/ip a del dev $interface + ;; + + leasefail) + echo "$0: Lease failed: $message" + ;; + + nak) + echo "$0: Received a NAK: $message" + ;; + + *) + echo "$0: Unknown udhcpc command: $1"; + exit 1; + ;; +esac diff --git a/pkg/debian-tuto2/isolinux.cfg b/pkg/debian-tuto2/isolinux.cfg new file mode 100644 index 0000000..735f25c --- /dev/null +++ b/pkg/debian-tuto2/isolinux.cfg @@ -0,0 +1,30 @@ +DEFAULT vesamenu.c32 + +MENU RESOLUTION 1024 768 + +menu background #00000000 * * +menu color title * #FF22BBCC * +menu color sel * #FFFFFFFF #FF22BBCC * +menu color hotsel 1;7;37;40 #ffffffff #76a1d0ff * +menu tabmsg Press ENTER to boot or TAB to edit a menu entry + +prompt 0 +timeout 0 + +menu title Welcome to the EPITA ADvanced LINux administration course! + +LABEL tutorial-nohdd + MENU LABEL ^Erase my first drive if necessary, then enter tutorial + KERNEL /boot/kernel + APPEND adlin.format=/dev/sda root=/dev/sda1 root=/dev/sr0 + +LABEL tutorial-hdd + MENU LABEL Enter tutorial without erasing ^disk + KERNEL /boot/kernel + APPEND root=/dev/sda1 root=/dev/sr0 + +MENU SEPARATOR + +LABEL poweroff + MENU LABEL ^Shutdown + KERNEL poweroff.c32 diff --git a/pkg/debian-tuto2/sshd_config b/pkg/debian-tuto2/sshd_config index 982d908..466b890 100644 --- a/pkg/debian-tuto2/sshd_config +++ b/pkg/debian-tuto2/sshd_config @@ -11,7 +11,7 @@ # default value. #Port 22 -#AddressFamily any +AddressFamily inet #ListenAddress 0.0.0.0 #ListenAddress :: diff --git a/token-validator/handler.go b/token-validator/handler.go index eb7e659..d645294 100644 --- a/token-validator/handler.go +++ b/token-validator/handler.go @@ -92,7 +92,7 @@ func rawHandler(f func(*http.Request, httprouter.Params, []byte) (interface{}, e // Read the body if r.ContentLength < 0 || r.ContentLength > 6553600 { - http.Error(w, fmt.Sprintf("{errmsg:\"Request too large or request size unknown\"}", err), http.StatusRequestEntityTooLarge) + http.Error(w, "{errmsg:\"Request too large or request size unknown\"}", http.StatusRequestEntityTooLarge) return } var body []byte diff --git a/token-validator/wg.go b/token-validator/wg.go index b1ed842..9e7158a 100644 --- a/token-validator/wg.go +++ b/token-validator/wg.go @@ -8,6 +8,7 @@ import ( "encoding/json" "fmt" "io" + "log" "net/http" "strings" "time" @@ -30,7 +31,7 @@ func init() { return getTunnelInfo(student.Id), nil })) router.POST("/api/wg/", apiAuthHandler(genWgToken)) - router.POST("/api/wg/:token", apiHandler(getWgTunnelInfo)) + router.POST("/api/wg/:token", getWgTunnelInfo) } func showWgTunnel(student Student, ps httprouter.Params, body []byte) (interface{}, error) { @@ -68,32 +69,57 @@ type PubTunnel struct { PubKey []byte } -func getWgTunnelInfo(ps httprouter.Params, body []byte) (interface{}, error) { +func getWgTunnelInfo(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + if addr := r.Header.Get("X-Forwarded-For"); addr != "" { + r.RemoteAddr = addr + } + log.Printf("%s \"%s %s\" [%s]\n", r.RemoteAddr, r.Method, r.URL.Path, r.UserAgent()) + + // Read the body + if r.ContentLength < 0 || r.ContentLength > 6553600 { + http.Error(w, "{errmsg:\"Request too large or request size unknown\"}", http.StatusRequestEntityTooLarge) + return + } + // Access wg infos tokenhex := []byte(ps.ByName("token")) tokendec := make([]byte, hex.DecodedLen(len(tokenhex))) n, err := hex.Decode(tokendec, tokenhex) if err != nil { - return nil, err + http.Error(w, fmt.Sprintf("{errmsg:%q}", err), http.StatusBadRequest) + return } token, err := GetTunnelToken(tokendec[:n]) if err != nil { - return nil, err + http.Error(w, fmt.Sprintf("{errmsg:%q}", err), http.StatusBadRequest) + return } var pt PubTunnel - if err := json.Unmarshal(body, &pt); err != nil { - return nil, err + if err := json.NewDecoder(r.Body).Decode(&pt); err != nil { + http.Error(w, fmt.Sprintf("{errmsg:%q}", err), http.StatusBadRequest) + return } token.PubKey = pt.PubKey _, err = token.Update() if err != nil { - return nil, err + http.Error(w, fmt.Sprintf("{errmsg:%q}", err), http.StatusBadRequest) + return } - return getTunnelInfo(token.IdStudent), nil + tinfo := getTunnelInfo(token.IdStudent) + + w.Header().Set("Content-Type", "text/plain") + w.Write([]byte(fmt.Sprintf(`[Peer] +PublicKey = %s +Endpoint = %s:%d +AllowedIPs = ::/0 +PersistentKeepalive = 5 +# MyIPv6=%s1/%d +# GWIPv6=%s +`, base64.StdEncoding.EncodeToString(tinfo.SrvPubKey), "82.64.31.248", tinfo.SrvPort, tinfo.CltIPv6, 64, tinfo.SrvGW6))) } @@ -206,9 +232,9 @@ func GenWGConfig(w io.Writer) (error) { w.Write([]byte(fmt.Sprintf(`[Peer] #IdStudent = %d -#TokenText = %s PublicKey = %s -AllowedIPs = %s/%d`, t.IdStudent, t.TokenText, base64.StdEncoding.EncodeToString(t.PubKey), studentIP(t.IdStudent), 80))) +AllowedIPs = %s/%d +`, t.IdStudent, base64.StdEncoding.EncodeToString(t.PubKey), studentIP(t.IdStudent), 80))) } return nil diff --git a/tuto2.yml b/tuto2.yml index 4ba93f4..d5534d7 100644 --- a/tuto2.yml +++ b/tuto2.yml @@ -1,11 +1,11 @@ kernel: - image: linuxkit/kernel:4.9.85 + image: linuxkit/kernel:4.20.3 # cmdline: "console=ttyS0 console=tty0" # cmdline: "console=tty0 console=ttyS0 root=/dev/sda1 root=/dev/sr0 adlin.net=easy" - cmdline: "console=tty0 console=ttyS0 root=/dev/sda1 root=/dev/sr0" + cmdline: "console=tty0 console=ttyS0 root=/dev/sda1 root=/dev/sr0 adlin.format=/dev/sda quiet" init: - - nemunaire/adlin-tuto2:8f13bab1bcb9b7b3f977ffd0f32bf596412b7094-dirty + - nemunaire/adlin-tuto2:35a9354900bb9a419e9e54758c069e8b97472ec5-dirty files: - path: etc/hostname @@ -16,6 +16,7 @@ files: - path: etc/resolv.conf contents: | nameserver 9.9.9.9 + nameserver 1.1.1.1 mode: "0644" - path: etc/systemd/network/49-main.link @@ -27,15 +28,13 @@ files: mode: "0644" - path: etc/systemd/network/50-dhcp.network - contents: "" - mode: "0644" - - - path: etc/systemd/network/.50-dhcp contents: | [Match] Name=eth0 [Network] DHCP=yes + IPv6AcceptRA=no + LinkLocalAddressing=no mode: "0644" - path: init @@ -61,7 +60,7 @@ files: INITP=$(cmdline init) [ -z "$INITP" ] && INITP=/lib/systemd/systemd - + WGTOKEN=$(cmdline adlin.token) ROOTFS=$(cmdline root) @@ -74,6 +73,7 @@ files: [ -b "$ROOTFS" ] || { echo "Invalid provided rootfs: not a valid block device."; exit 1; } } + mkdir -p /overlay /bin/mount -n -t tmpfs none /overlay /bin/mkdir -p /overlay/rwdata @@ -93,10 +93,7 @@ files: mkdir -p ${ovr_rwdata}/work /bin/mount -n -t overlay -o upperdir=${ovr_rwdata}/data,workdir=${ovr_rwdata}/work,lowerdir=${ovr_robase} overlay ${ovr_combined} || { echo "Unable to create overlayfs."; exit 3; } - grep adlin.net=easy /proc/cmdline > /dev/null && mount --bind ${ovr_combined}/etc/systemd/network/.50-dhcp ${ovr_combined}/etc/systemd/network/50-dhcp.network - /bin/umount -n /proc - /bin/umount -n /dev /bin/mkdir -p ${ovr_combined}/overlay/rwdata /bin/mount -n --move ${ovr_rwdata} ${ovr_combined}/overlay/rwdata @@ -106,8 +103,49 @@ files: cd ${ovr_combined} + mount --move /dev dev mount --move . / /bin/umount -n /overlay + + # Setting up wireguard tunnel + [ -z "${WGTOKEN}" ] && [ -f "etc/adlin.token" ] && WGTOKEN=$(cat etc/adlin.token) + [ -z "${WGTOKEN}" ] && { + echo -n "You didn't define your token to connect the network. Please copy it here now: " + read WGTOKEN + } + echo -n "${WGTOKEN}" > etc/adlin.token + /sbin/sysctl -w net.ipv6.conf.eth0.autoconf=0 + /bin/ip link set up dev eth0 + /bin/busybox udhcpc -n -q + [ -f "etc/wireguard/adlin.conf" ] && WGPRVKEY=$(sed 's/^.*PrivateKey *= *//p;d' etc/wireguard/adlin.conf) + [ -z "${WGPRVKEY}" ] && WGPRVKEY=$(/usr/bin/wg genkey) + WGPUBKEY=$(echo $WGPRVKEY | /usr/bin/wg pubkey) + while ! { echo "[Interface]\nPrivateKey = ${WGPRVKEY}"; /usr/sbin/chroot . /usr/bin/curl -f -d '{"pubkey": "'$WGPUBKEY'"}' https://adlin.nemunai.re/api/wg/$(echo -n "$WGTOKEN" | /usr/bin/sha512sum | /usr/bin/cut -d ' ' -f 1); } > etc/wireguard/adlin.conf + do + echo "" + echo "****************************************" + echo "******* SWITCHING TO RESCUE MODE *******" + echo "****************************************" + echo "" + echo "Sorry, I was unable to establish a connection to adlin.nemunai.re." + echo "Please verify that your primary network interface can obtain an IPv4 through DHCP." + echo "" + echo "Dropping to a shell, please fix your network, then press Ctrl+D or exit to retry." + echo "" + echo "****************************************" + echo "" + /bin/busybox cttyhack /usr/sbin/chroot . /bin/sh + echo "Retrying connection..." + done + /sbin/modprobe wireguard + /bin/ip link add dev wg0 type wireguard + /usr/bin/wg setconf wg0 etc/wireguard/adlin.conf + /bin/ip address add dev wg0 $(sed 's/^.*MyIPv6=//p;d' etc/wireguard/adlin.conf) + /bin/ip link set up dev wg0 + /bin/ip -6 route del default + /bin/ip -6 route add default via $(sed 's/^.*GWIPv6=//p;d' etc/wireguard/adlin.conf) pref high + + # To the user exec /usr/sbin/chroot . "${INITP}" mode: "0755" @@ -149,7 +187,7 @@ files: - path: etc/shadow contents: | - root:$6$fCh6fLfB$wTiBuIJB2/QLl37VlJ16MsqGmfSDct8ALRpY8kemFC2T4N4eZgdlTnEqTuYn5i4FMc5GoDBx1nfENHQqm0Zgm.:17594:0:99999:7::: + root:$6$B0qzwsEh$vfWGpIFUrKGrkT0PVtGhhomBwc.60IBIxjMLyG8mz.NJLFRryjqLK9sA/mzxNSaQViiHsYYrsgmcWVHblfdHg1:17968:0:99999:7::: daemon:*:17575:0:99999:7::: bin:*:17575:0:99999:7::: sys:*:17575:0:99999:7:::