Pubsub bash on a freebsd 14.1-BETA 3 running on linux (because we can)

People takes for profound thougths which only quality is the obscurity of their redaction is obscure complication.
Complication is a big spaghetty code, complexity is a lot of small code interacting like a nicely dressed lasagna.

-- Fridriech Ecthebest Nietzsche in Howto to code with a hammer (1880)


So in the last episode of last mad coder designs a pubsub protocol and implements it in bash, we experienced how easy doing a « it works for me »©® prototype in bash was thanks to socat/netcat/nc.

I had numerous feedback (it's a lie) from software urbanist architect of security claiming a prototype doeth not exists until there is a clear path of secured deployment in a container, on a container with cryptography and strong authentication.

So, today, I will illustrate -the corporately wrong, funny BUT totally legitimate- way to deploy it and secure it in the lazy lasagna devops way. And since, freebsd 14.1-BETA3 has been released, we have qemu and and jails on our plate.

The plan is the following :
  • Installing a customized freeBSD on linux in less than 15 minutes
  • Connecting it with a modern linux as a host
  • deploy a BSD thin jails the root way in a container (which makes as much sense as deploying docker in an openstack/kubernetes infrastructure except you need only one computer to experiment)


Installing freeBSD 14.1 Beta3 on linux with bash



Well, long story short : every release of freeBSD comes with a qcow2 image usable by qemu, and I have a script that does tailor a minimal image of freeBSD for my need including:
  • installing what I need to code (python3, git, bash)
  • customizing the keyboard to french
  • booting a non graphical comsole to be able to have « natural cut'n paste » between host and guest for a « unique improved CLI experience »,
  • and adding 1.5Gb to the root partition
The script (in bash) is fairly easy to customize, and you will need to do so if your keyboard is not french. It just asks at the beginning the default password for the user «user» and «root», doas is installed and configured as a passwordless sudo for user. Ports are not installed because it takes way to much time to call this experience fun anymore (plus ports architecture has been migrated and are now done a better way my script would not use).
Once the script finishes it boots directly into a consoled freeBSD 14.1-beta3 that can be left by login as root and typing
poweroff
.

The freebsd can be rebooted fast by using the generated ./start_14.1_BETA3.sh script. But right now, we need an openzfs partition to be able to make thin jails.

As a foreword, qemu docs are not very usable, even me (running the family comfy linumint that is debian based) uses the best linux documentation in town : the archlinux documentation. Whatever the linux I must admin, that is always my first source of information before reading the upstream docs/man pages because they redact their documentations in a readable way. Kudo archlinux !

Configuring a zfs based thinjail with freeBSD



So, following archlinux doc we make a 2Gb additionnal space for the zfs partition before having the fun of playing with freeBSD's gpart.
 qemu-img resize FreeBSD-14.1-BETA3-amd64.qcow2 +2G

Time to login as root on freeBSD by running ./start_14.1_BETA3.sh.

The violent drive resizing needs some repairing that are fixed with :
fsck -y
gpart recover ada0
[root@freebsd-14 ~]# gpart show
=>      34  19915958  ada0  GPT  (9.5G)
        34       122     1  freebsd-boot  (61K)
       156     66584     2  efi  (33M)
     66740   2097152     3  freebsd-swap  (1.0G)
   2163892  13557796     4  freebsd-ufs  (6.5G)
  15721688   4194304        - free -  (2.0G)

Now is time to add a zfs partition in the 5th «p»artiton
gpart add -t freebsd-zfs -a 4k ada0
gpart show
=>      34  19915958  ada0  GPT  (9.5G)
        34       122     1  freebsd-boot  (61K)
       156     66584     2  efi  (33M)
     66740   2097152     3  freebsd-swap  (1.0G)
   2163892  13557796     4  freebsd-ufs  (6.5G)
  15721688   4194304     5  freebsd-zfs  (2.0G)

Good, we reboot in single user mode, and repair the butechring we made with
fsck -f -y
** /dev/gpt/rootfs
** Last Mounted on /
** Root file system
** Phase 1 - Check Blocks and Sizes
** Phase 2 - Check Pathnames

UPDATE FILESYSTEM TO TRACK DIRECTORY DEPTH? yes

** Phase 3 - Check Connectivity
** Phase 4 - Check Reference Counts
** Phase 5 - Check Cyl groups
52073 files, 1058127 used, 581220 free (68 frags, 72644 blocks, 0.0% fragmentation)

***** FILE SYSTEM IS CLEAN *****

***** FILE SYSTEM WAS MODIFIED *****
** /dev/gpt/efiesp
** Phase 1 - Read FAT and checking connectivity
** Phase 2 - Checking Directories
** Phase 3 - Checking for Lost Files
Next free cluster in FSInfo block (2) not free
Fix? yes
4 files, 31 MiB free (64236 clusters)
Good, filesystem is clean, we reboot and login as admin to finish setting up zfs
# echo 'zfs_enable="YES"' >> /etc/rc.conf
# service zfs start
ZFS filesystem version: 5
ZFS storage pool version: features support (5000)
zpool create zroot /dev/ada0p5

Back in the track of the awesome FreeBSD handbook on jails we are gonna setup the system for thin jails relying on zfs for snapshoting.. We activate the jails subsystem :
sysrc jail_enable="YES"
sysrc jail_parallel_start="YES"
then create the dir structure with zfs underlying (a nice couche of lasagna).
zfs create -o mountpoint=/usr/local/jails zroot/jails
zfs create zroot/jails/media
zfs create zroot/jails/templates
zfs create zroot/jails/containers
zfs list
NAME                     USED  AVAIL  REFER  MOUNTPOINT
zroot                    261K  1.75G    24K  /zroot
zroot/jails               96K  1.75G    24K  /usr/local/jails
zroot/jails/containers    24K  1.75G    24K  /usr/local/jails/containers
zroot/jails/media         24K  1.75G    24K  /usr/local/jails/media
zroot/jails/templates     24K  1.75G    24K  /usr/local/jails/templates


What I love before using automation, is doing stuff the root way, thus, when you have a problem, you can understand how it fails. Hence the reason we don't use the promising AppJails I will evocate later (really later).

So let's to the zfs snapshot for our base :

[root@freebsd-14 ~]# zfs create -p zroot/jails/templates/14.1-BETA3
[root@freebsd-14 ~]# fetch https://download.freebsd.org/ftp/releases/amd64/amd64/14.1-BETA3/base.txz -o /usr/local/jails/media/14.1-BETA3-base.txz
/usr/local/jails/media/14.1-BETA3-base.txz             197 MB 1078 kBps 03m08s
[root@freebsd-14 ~]# tar -xf /usr/local/jails/media/14.1-BETA3-base.txz -C /usr/local/jails/templates/14.1-BETA3 --unlink
[root@freebsd-14 ~]# cp /etc/resolv.conf /usr/local/jails/templates/14.1-BETA3/etc/resolv.conf
[root@freebsd-14 ~]# freebsd-update -b /usr/local/jails/templates/14.1-BETA3 fetch install
src component not installed, skipped
Looking up update.FreeBSD.org mirrors... 3 mirrors found.
Fetching public key from update2.freebsd.org... done.
Fetching metadata signature for 14.1-BETA3 from update2.freebsd.org... done.
Fetching metadata index... done.
Fetching 1 metadata files... done.
Inspecting system... done.
Preparing to download files... done.

No updates needed to update system to 14.1-BETA3-p0.

WARNING: FreeBSD 14.1-BETA3 is approaching its End-of-Life date.
It is strongly recommended that you upgrade to a newer
release within the next 1 week.
No updates are available to install.
[root@freebsd-14 ~]# zfs snapshot zroot/jails/templates/14.1-BETA3@base
[root@freebsd-14 ~]# zfs clone zroot/jails/templates/14.1-BETA3@base zroot/jails/containers/pubsub
(reverse-i-search)`res': cp /etc/resolv.conf /usr/local/jails/templates/14.1-BETA3/etc/^Csolv.conf
[root@freebsd-14 ~]# /etc/rc.d/jail restart
Stopping jails:.
Starting jails: pubsub.
We install the dependencies :
jexec pubsub pkg install socat
jexec pubsub pkg install bash
jexec pubsub pkg install perl5
jexec pubsub pkg install ucspi-tcp
Here is the content of /etc/jail.conf
pubsub {
  # STARTUP/LOGGING
  exec.start = "/bin/sh /etc/rc";
  exec.stop = "/bin/sh /etc/rc.shutdown";
  exec.consolelog = "/var/log/jail_console_${name}.log";

  # PERMISSIONS
  allow.raw_sockets;
  exec.clean;
  mount.devfs;

  # HOSTNAME/PATH
  host.hostname = "${name}";
  path = "/usr/local/jails/containers/${name}";

  # NETWORK
  ip4 = inherit;
  interface = em0;
}

A basic jail ... with bash ... using the latest BETA that soon will be obsolete :D

We add a user pubsub (regular with login/pass:
jexec pubsub pkg install perl
And download the script, and test it works !
 curl https://gist.githubusercontent.com/jul/e9dcfdfb2490f6df3930dfe8ee29ead1/raw/1ddd6411c1ae8894f506fb4fcb0db0f2af6f45bb/pubsub.sh > /usr/local/jails/containers/pubsub/home/pubsub/pubsub.sh
chmod +x /usr/local/jails/containers/pubsub/home/pubsub/pubsub.sh
jexec pubsub pkg install perl
Nice. Now, is the time for PERVERSION !

Gluing stuff together to make an « production ready prototype complying with all corporate bells and whistles »



What we need ?
  • to avoid traffic being evesdropped (SSL)
  • modular authentication/authorization and login
but before this ... we need our qemu instance to get clean communication with the linux host and play the « software defined tricks ».
As soon as you don't have a material interface plugged in hardware, it is software defined networking and we will begin with qemu manual...
We choose the simplest form of connection bridging qemu to the host with a tap interface. First we create the network interface in linux (fix your dhcp leases, and let your firewall talk to both ips). Addedum And configuring a darn simple bridge because of modern linux and its culture of not documenting properly is to be updated as a story in its whole.

Right now, we ALMOST have readied the playground to add « a true secure design ISO 27000 paperwork compliant with pieces of ITIL and ISO 14000 death by one thousand cut :D

We just need a WORKING BRIDGE that works the intended way .... and is making me regret the simplicity of slackware (my first distro). But I don't have the juice to finish today : I hate networking. So, the next episode comes next : DNS, TLS1.3, RBAC with pam hell \o/ and a python library to use the protocol as a noob that codes in python.

No comments: