Compare commits

...

25 Commits
main ... PoC

Author SHA1 Message Date
Solène Rapenne
a6f69992ae vether to veb 2023-07-22 12:35:29 +02:00
Solène Rapenne
081dc7c687 prepare for PF filters 2023-06-22 00:05:48 +02:00
Solène Rapenne
3bdecb99b9 add the host to the clipboard selection 2023-06-21 19:18:25 +02:00
Solène Rapenne
1b77a7c05e configure sndiod correctly 2023-06-14 13:55:22 +02:00
Solène Rapenne
a211195afd update requirements and hosts changes 2023-06-14 13:38:00 +02:00
Solène Rapenne
11349c8a7c use Xephyr to run programs securely 2023-06-14 13:37:48 +02:00
Solène Rapenne
8d0da7d78e reduce the load on disk 2023-06-13 18:52:12 +02:00
Solène Rapenne
25c0f4acb5 fix the VM existence check in deletion 2023-06-11 17:17:39 +02:00
Solène Rapenne
bdd27b2178 check for TCP/22 instead of using ICMP to determine if a VM is available 2023-06-11 17:17:14 +02:00
Solène Rapenne
44090345ae template configuration auto start 2023-06-11 17:16:46 +02:00
Solène Rapenne
7c4be65a7f helper to generate desktop files 2023-06-11 17:16:29 +02:00
Solène Rapenne
33c518e632 add NFS support 2023-06-11 17:16:04 +02:00
Solène Rapenne
8f561d8c9b explain how to install / uninstall 2023-06-10 10:50:22 +02:00
Solène Rapenne
f67126c1f8 no need for ansible finally, yet 2023-06-10 10:50:09 +02:00
Solène Rapenne
8049a2f8bb wait a bit more for ssh to be available 2023-06-10 10:41:41 +02:00
Solène Rapenne
7a877ba8ab persistent rc.local per kube 2023-06-10 10:41:14 +02:00
Solène Rapenne
2891e32e75 improve doc 2023-06-10 09:55:02 +02:00
Solène Rapenne
f1e69bf5ea allow to connect from ssh without DISPLAY 2023-06-09 23:50:53 +02:00
Solène Rapenne
3cfec305be add working persistency for kubes 2023-06-09 23:50:37 +02:00
Solène Rapenne
507689f9c7 default memory of 1GB, better for toying at the moment 2023-06-09 22:54:50 +02:00
Solène Rapenne
cba65368c2 MAC addresses are not random hexa numbers! 2023-06-09 22:54:31 +02:00
Solène Rapenne
3c6afb0096 trying on current, it's worse 2023-06-09 08:36:34 +02:00
Solène Rapenne
eb39bcf1e7 investigating ARP problems 2023-06-08 23:01:37 +02:00
Solène Rapenne
97e3b13ac2 seems to work a bit 2023-06-08 19:56:42 +02:00
Solène Rapenne
d0a9623a29 shell based PoC 2023-06-08 19:08:50 +02:00
14 changed files with 625 additions and 1 deletions

19
bin/README.md Normal file
View File

@ -0,0 +1,19 @@
# Host setup
1. add the openkubsd anchor in `/etc/pf.conf`
2. run `./setup.sh` as root
# Setup information
OpenKuBSD will store everything in `/var/openkubsd/`, and make a few changes in `/etc/`
- overwrite /etc/exports
- overwrite /etc/vm.conf
- overwrite /etc/dhcpd.conf
- overwrite /etc/hostname.vether0
- overwrite /etc/hostname.bridge0
- rcctl enable vmd dhcpd portmap mountd nfsd
- add `net.inet.ip.forwarding=1` to /etc/sysctl.conf
- modify `/etc/hosts` at the end of the file, after an automatically added comment `# OpenKuBSD`
If you want to remove OpenKuBSD, undo the changes above.

89
bin/configure_template.sh Executable file
View File

@ -0,0 +1,89 @@
#!/bin/sh
set -x
FILE=$(mktemp /tmp/file.XXXXXXXXXXXXXXXXXXXXX)
cat <<EOF >$FILE
sed -i 's/^#X11Forwarding no/X11Forwarding yes/' /etc/ssh/sshd_config
echo "permit nopass keepenv user" > /etc/doas.conf
echo 'https://cdn.openbsd.org/pub/OpenBSD/' > /etc/installurl
if ! grep 'library_aslr=NO' /etc/rc.conf.local >/dev/null
then
echo 'library_aslr=NO' >> /etc/rc.conf.local
fi
pkg_add openbox neofetch xneko dillo firefox-esr chromium claws-mail-- thunar keepassxc-- lagrange clic catgirl dino aerc xfce4-terminal stumpwm xclip mousepad
# we want sshd to be started by rc.local
# so copied/mounted /home is ready
rcctl disable sshd
# enable sndiod with a higher buffer to prevent stuttering
rcctl enable sndiod
rcctl set sndiod flags -b34000
cat <<NESTED >/etc/stumpwmrc
(setf *startup-message* nil)
(defun st-kill-empty (a)
(if (= 0 (length (screen-windows (current-screen))))
(stumpwm:quit)))
(stumpwm:add-hook stumpwm:*destroy-window-hook* 'st-kill-empty)
NESTED
cat <<NESTED >/etc/rc.local
#!/bin/sh
HOST=\\\$(awk '/^host-name/ { print \\\$2}' /var/db/dhcpleased/vio0)
hostname "\\\${HOST}.kube"
# this triggers in non-templates
if sysctl hw.disknames | grep sd1 >/dev/null
then
mount -o noatime -u /usr/local
mount -o noatime -u /usr/X11R6
mount -o noatime -u /usr
mount -o noatime -u /tmp
mount -o noatime -u /var
mount -o noatime -u /
if ! dumpfs /dev/rsd1c >/dev/null 2>/dev/null
then
echo "Formatting the empty disk"
fdisk -iy sd1c
disklabel -d sd1
newfs /dev/rsd1c
mount /dev/sd1c /mnt/
cd /home/ && pax -rw -p e . /mnt && cd -
umount /mnt
fi
echo "fsck and mounting the disk on /home"
fsck_ffs -y /dev/rsd1c
mount -o rw,nodev,noatime,nosuid /dev/sd1c /home
install -d -o root /home/openkubsd/
if ! test -f /home/openkubsd/rc.local
then
printf '#!/bin/sh\n\n# use this file to add Kube specific boot commands\n' > /home/openkubsd/rc.local
chmod +x /home/openkubsd/rc.local
fi
/home/openkubsd/rc.local
install -d -o user /shared/
mount 10.100.0.1:/var/openkubsd/shared/\\\$(hostname -s) /shared/
fi
/etc/rc.d/sshd -f start
NESTED
chmod +x /etc/rc.local
# stop the template
halt
EOF
./connect.sh openbsd-template "xterm -e /bin/sh -c 'sleep 5 && exit'"
cat $FILE | ssh -o StrictHostKeyChecking=no root@openbsd-template.kube "cat >/$FILE"
ssh -o StrictHostKeyChecking=no root@openbsd-template.kube "sh /$FILE"
rm "$FILE"

62
bin/connect.sh Executable file
View File

@ -0,0 +1,62 @@
#!/bin/sh
if [ -z "$1" ]
then
echo "Pick an host:"
awk '/.kube/ { print " - "$2 }' /etc/hosts
exit 0
fi
HOST="${1}"
if echo "$HOST" | grep -v kube$
then
HOST="${HOST}.kube"
fi
if ! grep "$HOST" /etc/hosts >/dev/null
then
echo "$HOST doesn't exist"
exit 1
fi
doas ./start_kube.sh "${HOST%.kube}"
if ! echo polling-port | nc -w 1$HOST 22 >/dev/null 2>/dev/null
then
printf "waiting 30s"
for i in $(seq 1 30)
do
echo polling-port | nc -w 1 $HOST 22 >/dev/null 2>/dev/null && break
printf "."
sleep 1
if ! vmctl show ${HOST%.kube} | grep running >/dev/null
then
printf "\n$HOST isn't running"
exit 1
fi
done
fi
ID=$(vmctl show "${HOST%.kube}" | awk 'END { print $2 }')
# uncomment to set a dedicated X server per program
ID="${ID}$(( $(date +%s) % 3600))"
ssh-keygen -R "$HOST" >/dev/null 2>/dev/null
if [ -n "$DISPLAY" ]
then
PROG="${2:-xterm}"
VM_INFO="$$ $HOST $ID $PROG"
echo "$VM_INFO" >> /tmp/kubes.txt
Xephyr -xkb-layout fr -once -terminate 1 -title "[${HOST}] - ${PROG}" -resizeable -reset -br ":${ID}" &
export DISPLAY=":${ID}"
ssh -o StrictHostKeyChecking=no -Y "user@${HOST}" "stumpwm" &
WAIT_FOR=$!
ssh -o StrictHostKeyChecking=no -Y "user@${HOST}" "${PROG}"
wait $WAIT_FOR
kill $(jobs -p)
sed -i "/^$$/d" /tmp/kubes.txt
fi

31
bin/copy_clipboard.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/sh
SOURCE=$(zenity \
--list --radiolist --width=600 \
--title="Copy clipboard between programs" \
--text="Choose a clipboard to copy from" \
--print-column=4 \
--column="From" --column="PID" --column="Kube name" --column="Local X server" --column="Program running" \
TRUE 1 $(hostname) 0.0 Host \
$(awk '{ print "FALSE "$0 }' /tmp/kubes.txt))
if [ -z "$SOURCE" ]
then
exit 0
fi
DESTINATION=$(zenity \
--list --radiolist --width=600 \
--title="Copy clipboard between programs" \
--text="Choose a destination clipboard" \
--print-column=4 \
--column="To" --column="PID" --column="Kube name" --column="Local X server" --column="Program running" \
TRUE 1 $(hostname) 0.0 Host \
$(awk -v orig="${SOURCE}" '$3!=orig { print "FALSE "$0 }' /tmp/kubes.txt))
if [ -z "$DESTINATION" ]
then
exit 0
fi
env DISPLAY=":$SOURCE" xclip -o - | env DISPLAY=":$DESTINATION" xclip

61
bin/create_kube.sh Executable file
View File

@ -0,0 +1,61 @@
#!/bin/sh
set -e
if [[ "$(id -u)" -ne "0" ]]
then
echo "you must run $0 as root"
exit 1
fi
NAME=${1:-kube}
DISK=/var/openkubsd/disks/${NAME}.qcow2
# create a qcow2 file for /home
if test -f "${DISK}"
then
echo "$DISK already exist, this shouldn't happen"
exit 1
fi
# generate a MAC address
MAC="$(hexdump -n3 -e'/3 "00:60:2F" 3/1 ":%02X"' /dev/random)"
NEXT_IP=$(/var/openkubsd/bin/get_ip.sh)
# create a derived disk from the template
rm -f /var/openkubsd/derived/${NAME}.qcow2
vmctl create -b /var/openkubsd/templates/openbsd-template.qcow2 /var/openkubsd/derived/${NAME}.qcow2
vmctl create -s 60G "${DISK}"
# create the vm.conf file
cat <<EOF >/var/openkubsd/vm.conf.d/vms/${NAME}.conf
vm "${NAME}" {
disk /var/openkubsd/derived/${NAME}.qcow2
disk $DISK
interface locked lladdr $MAC switch kubes
memory 1G
disable
}
EOF
cat <<EOF >/var/openkubsd/dhcpd.d/${NAME}.conf
host ${NAME} {
hardware ethernet $MAC;
fixed-address $NEXT_IP;
option host-name "$NAME";
}
EOF
# generate PF rules
cat <<EOF >/var/openkubsd/pf/kube_${NAME}.conf
match out on egress from ${NEXT_IP} to any nat-to (egress)
EOF
# generate NFS
install -d -o solene "/var/openkubsd/shared/${NAME}"
# TODO: manage an ARP entry file with permanent keyword
/var/openkubsd/bin/recreate_conf.sh

94
bin/create_template.sh Executable file
View File

@ -0,0 +1,94 @@
#!/bin/sh
DIR="$(mktemp -d /tmp/openkubsd-new-template.XXXXXXXXXXXXXXXXXXXXX)"
NAME=openbsd-template
DISK=/var/openkubsd/templates/${NAME}.qcow2
if [[ "$(id -u)" -ne "0" ]]
then
echo "you must run $0 as root"
exit 1
fi
if ! rcctl check vmd
then
echo "vmd isn't running"
exit 1
fi
cd $DIR || exit 1
if [[ -f "$DISK" ]]
then
echo "$DISK already exist"
exit 1
fi
# download upobsd
curl -OL https://raw.githubusercontent.com/rapenne-s/upobsd/master/upobsd.sh
# download bsd.rd
curl -OL https://cdn.openbsd.org/pub/OpenBSD/7.3/amd64/bsd.rd
# create install.conf
cat <<EOF >install.conf
System hostname = $NAME
Password for root = hunter2
Public ssh key for root = ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOIZKLFQXVM15viQXHYRjGqE6LLfvETMkjjgSz0mxMzS
Change the default console to com0 = yes
Which speed should com0 use = 19200
Allow root ssh login = prohibit-password
Setup a user = user
Password for user = *************
Public ssh key for user = ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOIZKLFQXVM15viQXHYRjGqE6LLfvETMkjjgSz0mxMzS
What timezone are you in = Europe/Paris
Location of sets = http
HTTP Server = 10.100.0.1
EOF
# update bsd.rd
chmod +x upobsd.sh
./upobsd.sh -f bsd.rd -i install.conf
# create disk
vmctl create -s 60G "${DISK}"
# generate a MAC address
MAC="$(hexdump -n3 -e'/3 "00:60:2F" 3/1 ":%02X"' /dev/random)"
NEXT_IP=$(/var/openkubsd/bin/get_ip.sh)
# run install
cat <<EOF >/var/openkubsd/vm.conf.d/vms/${NAME}.conf
vm "${NAME}" {
disk ${DISK}
boot device disk
boot ${DIR}/bsd.rd
memory 1G
interface locked lladdr $MAC switch kubes
disable
}
EOF
cat <<EOF >/var/openkubsd/dhcpd.d/${NAME}.conf
host ${NAME} {
hardware ethernet $MAC;
fixed-address $NEXT_IP;
option host-name "$NAME";
}
EOF
/var/openkubsd/bin/recreate_conf.sh
vmctl start "${NAME}"
vmctl wait "${NAME}"
cat <<EOF >/var/openkubsd/vm.conf.d/vms/${NAME}.conf
vm "${NAME}" {
disk ${DISK}
interface locked lladdr $MAC switch kubes
disable
}
EOF
/var/openkubsd/bin/recreate_conf.sh
rm -fr "$DIR"

41
bin/generate_desktop.sh Executable file
View File

@ -0,0 +1,41 @@
#!/bin/sh
KUBE="$1"
CMD="$2"
if [ -z "$1" ] || [ -z "$2" ]
then
echo "you must give the Kube and the command to run"
exit 1
fi
NAME="${1}: ${2}"
if [ -n "$3" ]
then
NAME="${1}: ${3}"
fi
mkdir -p ~/.local/share/applications
DEST="~/.local/share/applications/${1}-${2}.desktop"
TMPFILE="/tmp/${1}-${2}.desktop"
test -f "$DEST" && xdg-desktop-menu uninstall "$DEST"
cat <<EOF > "${TMPFILE}"
[Desktop Entry]
Type=Application
Exec=/bin/sh connect.sh "$1" "$2"
Path=/home/solene/dev/openkubsd/bin/
Name=${NAME}
Categories=OpenKuBSD
Terminal=False
Type=Application
EOF
xdg-desktop-menu install "${TMPFILE}"
rm "${TMPFILE}"
echo "$2 on $1 desktop file generated"

14
bin/get_ip.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
SUBNET=$(awk '/^subnet/ { print $2 }' /var/openkubsd/dhcpd.d/00_base.conf | cut -d '.' -f 1-3)
IP_LIST=$(grep fixed-address /var/openkubsd/dhcpd.d/*conf | awk '{ print $3 }' | awk -F '.' '{ print $4 }' | tr -d ';' | sort -n)
# .1 is the gateway
for i in $(seq 2 240)
do
if ! echo "${IP_LIST}" | grep "^${i}$" >/dev/null
then
echo "${SUBNET}.${i}"
break
fi
done

51
bin/recreate_conf.sh Executable file
View File

@ -0,0 +1,51 @@
#!/bin/sh
if [[ "$(id -u)" -ne "0" ]]
then
echo "you must run $0 as root"
exit 1
fi
cd /var/openkubsd/vm.conf.d/vms/
cat *.conf > ../vms.conf
cd /var/openkubsd/dhcpd.d/
cat *.conf > /etc/dhcpd.conf
cd /var/openkubsd/pf/
cat *.conf > /var/openkubsd/pf/CONF
HOSTS=$(find /var/openkubsd/dhcpd.d/ -not -name 00_base.conf -type f -exec cat {} + | grep -E "(^host|fixed-address)" | tr -d ';' | paste - - | awk '{ print $5" "$2".kube" }')
HOSTS_FILE=$(awk '/OpenKuBSD/ { stop=1 }; stop!=1 { print }' /etc/hosts)
cat <<EOF >/etc/hosts
$HOSTS_FILE
# OpenKuBSD
$HOSTS
EOF
# generate /etc/exports
HOSTS=$(find /var/openkubsd/dhcpd.d/ -not -name 00_base.conf -type f -exec cat {} + | grep -E "(^host)" | tr -d ';' | awk '{ print $2 }' | grep -v openbsd-template)
TMPFILE=$(mktemp /tmp/exports.XXXXXXXXXXXXXXXXXXXXXXXXXX)
for host in $HOSTS
do
echo "/var/openkubsd/shared/${host} ${host}.kube" >> "$TMPFILE"
done
mv $TMPFILE /etc/exports
rcctl reload vmd
rcctl restart dhcpd
# if /etc/exports was empty
# services didn't start
if ! rcctl check nfsd
then
rcctl start nfsd portmap
fi
# reload new config
# showmount -e to see the shares
rcctl reload mountd
pfctl -a openkubsd -f /var/openkubsd/pf/CONF

24
bin/remove_kube.sh Executable file
View File

@ -0,0 +1,24 @@
#!/bin/sh
if [[ "$(id -u)" -ne "0" ]]
then
echo "you must run $0 as root"
exit 1
fi
NAME=${1:-kube}
if vmctl show $NAME | awk '{ print $NF }' | grep "^${NAME}$"
then
if vmctl show $NAME | grep running >/dev/null
then
vmctl stop -fw $NAME || exit 1
fi
rm /var/openkubsd/dhcpd.d/${NAME}.conf
rm /var/openkubsd/vm.conf.d/vms/${NAME}.conf
rm /var/openkubsd/derived/${NAME}.qcow2
rm /var/openkubsd/disks/${NAME}.qcow2
/var/openkubsd/bin/recreate_conf.sh
else
echo "$NAME doesn't exist"
fi

23
bin/remove_template.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/sh
if [[ "$(id -u)" -ne "0" ]]
then
echo "you must run $0 as root"
exit 1
fi
NAME=openbsd-template
DISK=/var/openkubsd/templates/${NAME}.qcow2
if grep -r "$DISK" /var/openkubsd/vm.conf.d/vms/ | grep -v "/var/openkubsd/vm.conf.d/vms/${NAME}.conf"
then
echo "The configuration files above still need $NAME"
exit 1
fi
vmctl stop -fw $NAME
rm "/var/openkubsd/vm.conf.d/vms/${NAME}.conf"
rm "/var/openkubsd/dhcpd.d/${NAME}.conf"
rm "$DISK"
./recreate_conf.sh

91
bin/setup.sh Executable file
View File

@ -0,0 +1,91 @@
#!/bin/sh
if [[ "$(id -u)" -ne "0" ]]
then
echo "you must run $0 as root"
exit 1
fi
# create some directories
install -d -o root -g wheel -m 755 /var/openkubsd/
install -d -o root -g wheel -m 755 /var/openkubsd/bin/
install -d -o root -g wheel -m 755 /var/openkubsd/dhcpd.d/
install -d -o root -g wheel -m 755 /var/openkubsd/vm.conf.d/
install -d -o root -g wheel -m 755 /var/openkubsd/vm.conf.d/vms/
install -d -o root -g wheel -m 700 /var/openkubsd/pf/
install -d -o root -g wheel -m 700 /var/openkubsd/disks/
install -d -o root -g wheel -m 700 /var/openkubsd/derived/
install -d -o root -g wheel -m 755 /var/openkubsd/templates/
install -d -o 1000 -m 755 /var/openkubsd/shared/
install -o root -g wheel -m 555 ./get_ip.sh /var/openkubsd/bin/
install -o root -g wheel -m 555 ./recreate_conf.sh /var/openkubsd/bin/
if ! grep net.inet.ip.forwarding=1 /etc/sysctl.conf
then
echo net.inet.ip.forwarding=1 >> /etc/sysctl.conf
sysctl net.inet.ip.forwarding=1
fi
# generate NAT PF rule
cat <<EOF >/var/openkubsd/pf/nat
match out on egress from vport0:network to any nat-to (egress)
pass in proto { udp tcp } from vport0:network to any port domain \
rdr-to 9.9.9.9 port domain
EOF
# generate network interfaces
cat <<EOF >/etc/hostname.vport0
inet 10.100.0.1 255.255.255.0
up
EOF
sh /etc/netstart vport0
cat <<EOF >/etc/hostname.veb0
add vport0
up
EOF
sh /etc/netstart veb0
# Configure vmd to use a switch
cat <<EOF >/etc/vm.conf
include "/var/openkubsd/vm.conf.d/switch.conf"
include "/var/openkubsd/vm.conf.d/vms.conf"
EOF
cat <<EOF >/var/openkubsd/vm.conf.d/switch.conf
switch "kubes" {
interface veb0
locked lladdr
}
EOF
test -f /var/openkubsd/vm.conf.d/vms.conf || touch /var/openkubsd/vm.conf.d/vms.conf
# Prepare base DHCPD configuration
cat <<EOF >/var/openkubsd/dhcpd.d/00_base.conf
option domain-name-servers 9.9.9.9;
subnet 10.100.0.0 netmask 255.255.255.0 {
option routers 10.100.0.1;
range 10.100.0.240 10.100.0.245;
}
EOF
# check for the PF anchor
if pfctl -a "openkubsd" -sr 2>&1 | grep "does not exist"
then
echo "anchor openkubsd missing in pf.conf"
exit 1
fi
# load the NAT rule into the anchor
pfctl -a openkubsd -f /var/openkubsd/pf/nat
# restart vmd
rcctl enable dhcpd
rcctl set dhcpd flags vport0
rcctl restart dhcpd
rcctl enable vmd
rcctl restart vmd
rcctl enable nfsd portmap mountd
rcctl start nfsd portmap portmap

22
bin/start_kube.sh Executable file
View File

@ -0,0 +1,22 @@
#!/bin/sh
if [[ "$(id -u)" -ne "0" ]]
then
echo "you must run $0 as root"
exit 1
fi
NAME=${1:-kube}
if vmctl status $NAME | grep running >/dev/null
then
exit 0
fi
set -x
# create a derived disk from the template
arp -d $NAME.kube
rm -f /var/openkubsd/derived/${NAME}.qcow2
vmctl create -b /var/openkubsd/templates/openbsd-template.qcow2 /var/openkubsd/derived/${NAME}.qcow2
vmctl start $NAME

View File

@ -6,6 +6,8 @@ This document is meant to explain what should happen when an user is doing XYZ.
- USER edits the file to add a new template
- USER runs the `openkubsd apply`
- configure dhcp server
- configure PF
- create a new qcow2 file
- install the OS
- deploy ssh key
@ -23,8 +25,8 @@ This document is meant to explain what should happen when an user is doing XYZ.
- USER edits the file to add the new VM
- USER runs the `openkubsd apply`
- run the command that generates a fresh derived disk from the template
- create a new qcow2 file for /home
- configure dhcp server
- generate the PF rules
- allow host NFS
- prevent IP spoofing