How to configure a FreeBSD Jail with vnet and ZFS

last updated in Categories ,

How do I install and configure a FreeBSD jail with vnet? How do I create FreeBSD jail with /etc/jail.conf without using iocage command or ezjail command line tool?

Introduction: Jails were introduced in FreeBSD 4.x by Poul-Henning Kamp. FreeBSD jail is nothing but operating system-level virtualization that allows partitioning a FreeBSD based Unix server. These mini systems called jails. Jails have their own root user and access rights. Jails can use network subsystem virtualization infrastructure or share existing network. FreeBSD jails are a powerful way to increase the security. Usually, you create jail per services such as web server, VPN server, database server and more. This page shows how to configure a FreeBSD Jail with vnet and ZFS. The following instructions tested on FreeBSD version 11.2.

How to configure a FreeBSD Jail with vnet and ZFS

The procedure to create a FreeBSD jail is as follows as of 11.2:

  1. Compile a FreeBSD kernel to include VIMAGE support
  2. Install jib and jng
  3. Create a zfs data set for basejail
  4. Configuring the jail.conf on the host
  5. Enable and start jail service

Let us see all steps in details to configure a FreeBSD Jail with vnet and ZFS.

Step 1. Configure/compile vnet kernel

You must compile FreeBSD kernel. You need a VIMAGE enabled FreeBSD kernel. You must have FreeBSD src installed in /usr/src/ directory. Use the cp command as follows to copy kernel config:
$ sudo cp -v /usr/src/share/examples/jails/VIMAGE /usr/src/sys/amd64/conf/VIMAGE
$ cd /usr/src/

Compile it:
$ sudo make KERNCONF=VIMAGE kernel
You can specify the maximum number of jobs that make may have running at any one time by passing the -j option. For example:
$ sudo make -j 16 KERNCONF=VIMAGE kernel
You must reboot the FreeBSD box:
$ sudo reboot
Verify new kernel version:
$ uname -v
FreeBSD 11.2-RELEASE #0: Wed Jul 11 21:35:37 IST 2018 root@nas04:/usr/obj/usr/src/sys/VIMAGE

Install required tools:
$ sudo cp -v /usr/src/share/examples/jails/{jib,jng} /usr/sbin/

Step 2. Create a zfs data set for jails

You need to set up the filesystem. Use the zpool command to get list of configured zfs:
# zpool list
Sample outputs:

NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
zroot  21.8T  68.7G  21.7T        -         -     0%     0%  1.00x  ONLINE  -

Type the following zfs command for zroot mounted at /jails/:
# zfs create -o mountpoint=/jails zroot/jails
Next create a zfs data set:
# zfs create zroot/jails/fullbasejail
Grab the FreeBSD 11.2 base files by visiting this page, and any other parts of FreeBSD you want in jails. Use the curl command or wget command or fetch command:
# cd /tmp
# wget https://download.freebsd.org/ftp/releases/amd64/11.2-RELEASE/base.txz
# wget https://download.freebsd.org/ftp/releases/amd64/11.2-RELEASE/lib32.txz

Use the tar command to unpack the base.txz and lib32.txz tarball fetched from FreeBSD’s ftp mirrors:
# tar -zxvf /tmp/download/11.2-RELEASE/base.txz -C /jails/fullbasejail
# tar -zxvf /tmp/download/11.2-RELEASE/lib32.txz -C /jails/fullbasejail

Update your FreeBSD base install

Apply updates to FreeBSD base install using the freebsd-update command:
# freebsd-update -b /jails/fullbasejail fetch install
Compare the system against a “known good” index of the installed release:
# freebsd-update -b /jails/fullbasejail IDS
Sample outputs:

Looking up update.FreeBSD.org mirrors... 3 mirrors found.
Fetching metadata signature for 11.2-RELEASE from update5.freebsd.org... done.
Fetching metadata index... done.
Fetching 1 metadata files... done.
Inspecting system... 
done.

Step 3. Configure the base jail

You just configured a base jail for quick deployment. One can clone basejail to create a new jail:
# zfs snapshot zroot/jails/fullbasejail@11.2-RELEASE-p0
List snapshots:
zfs list -t snapshot
Finally create a new jail named rsnapshot from the zfs snapshot:
# zfs send -R zroot/jails/fullbasejail@11.2-RELEASE-p0 | zfs receive zroot/jails/rsnapshot

How to configure basic jail settings

You need to make sure your jail has the right timezone, dns servers, a hostname, ip address and other stuff in rc.conf. Please note that you need to be in /jails/rsnapshot/ directory (adjust paths according to your setup):
# cd /jails/rsnapshot
Setup a dns by creating a file named etc/resolv.conf inside /jails/rsnapshot/:
# vi etc/resolv.conf
Append the following (set dns nameserver as per your setup):
nameserver 192.168.2.254
nameserver 192.168.2.18

Save and close the file in vim/vi text editor. Setup timezone for your FreeBSD jail using the ln command (I am setting up to IST):
# ln -v usr/share/zoneinfo/Asia/Kolkata etc/localtime
etc/localtime => usr/share/zoneinfo/Asia/Kolkata

Next you need to setup rc.conf inside /jails/rsnapshot/:
# vi etc/rc.conf
Sample settings:

# jail hostname #
host_hostname="rsnapshot"
 
# jail ip address and routing #
ifconfig_ng0_rsnapshot="inet 192.168.2.30 netmask 255.255.255.0"
defaultrouter="192.168.2.254"
 
# Start or stop services #
cron_flags="$cron_flags -J 15"
sendmail_enable="NONE"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
syslogd_flags="-c -ss"
ipv6_activate_all_interfaces="NO"
sshd_enable="YES"

Save and close the file.

How to configuring the jail.conf on the host

Edit or create the /etc/jail.conf as follows:
# vi /etc/jail.conf
Append the following config:

rsnapshot {
        host.hostname = "rsnapshot";   # hostname
        path = "/jails/rsnapshot";     # root directory
        exec.clean;
        exec.system_user = "root";
        exec.jail_user = "root";
        # ##########################################################################  
        # netgraph/vnet config info
        # ng0 is my vnet
        # idb1 is my physical network interface connected to the LAN (use ifconfig)
        # jng is located in /usr/sbin/
        # rsnapshot is my jail name
        # ##########################################################################  
        vnet; 
        vnet.interface = "ng0_rsnapshot";               # vnet interface(s)
        exec.prestart += "jng bridge rsnapshot igb1";   # bridge interface(s)
        exec.poststop += "jng shutdown rsnapshot";      # destroy interface(s)
 
        # Standard stuff
        exec.start += "/bin/sh /etc/rc";
        exec.stop = "/bin/sh /etc/rc.shutdown";
        exec.consolelog = "/var/log/jail_rsnapshot_console.log";
        mount.devfs;          #mount devfs
        allow.raw_sockets;    #allow ping-pong
        devfs_ruleset="5";    #devfs ruleset for this jail
        mount.devfs;
}

Save and close the file.

Turn on jail service

# sysrc jail_enable=YES

Create /etc/devfs.rules

# vi /etc/devfs.rules
Append or edit the file as follows to allow /dev/tun access inside jail (see /etc/defaults/devfs.rules):
[devfsrules_jail_rsnapshot=5]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add path 'tun*' unhide
add path zfs unhide

Save and close the file.

Start the jail

# service jail start
# service jail status

How to login to my jail

To list running jails run:
# jls
Use jid or jailname as follows
# jexec 1
# jexec rsnapshot

Add a new user using the pw command:
# pw useradd -n vivek -G wheel -s /bin/tcsh -m -d /home/vivek
# passwd vivek

Update or install packages
# pkg update && pkg upgrade
# pkg install most

Verify networking:
# ifconfig
# sockstat -4
# ping -c 2 cyberciti.biz

How to configure a FreeBSD Jail with vnet and verify it

Conclusion

You just configure a FreeBSD Jail with vnet along with ZFS. I suggest you read this page for more info and man pages by typing the following man command:
$ man jail
$ man devfs.conf

Posted by: Vivek Gite

The author is the creator of nixCraft and a seasoned sysadmin, DevOps engineer, and a trainer for the Linux operating system/Unix shell scripting. Get the latest tutorials on SysAdmin, Linux/Unix and open source topics via RSS/XML feed or weekly email newsletter.

Join the discussion at www.nixcraft.com