crappy quality ezjail replacement

root / mkjail

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/usr/bin/perl
# A simple script for creating single-service jails.
# Warning: Somewhat dumb/bruteforce/single-purpose. Be warned.
#
#
# Usage example: mkjail /srv/jails/derp epair3 192.168.0.1/24 2a01:44b::4/64 2a01:44b::5/128

use warnings;
use File::Basename;
use File::Spec;

my $datadir = '/var/jails'; # directory where the script state is kept
my $services = '/srv'; #directory where the jail special jail configuration is kept
mkdir $datadir;
mkdir "$datadir/conf"; # let's pretend we actually use all of these
mkdir "$datadir/fstab";
mkdir "$datadir/bak";

my $jaildir = shift @ARGV or die "Missing parameter: jail directory";
my $jailepair = shift @ARGV or die "Missing parameter: jail epair device";
my @jailip = @ARGV; # IP addresses for this jail

my $jail = basename $jaildir || dirname $jaildir; # depending on whether it ends with '/' or not
$jaildir = File::Spec->rel2abs($jaildir);

(-f "$datadir/template.txz") ||
	die 'Download base.txz from ftp://ftp.freebsd.org/pub/FreeBSD/releases/$(uname -p)/$(uname -r)/base.txz' .
	"\nunpack *only* the etc/ and var/ subdirectories, add the files you need in all jails (e.g. /etc/resolv.conf, /etc/rc.conf), pack it with tar cJf template.txz and put it in $datadir.";

my @mounts  = qw(bin lib libexec sbin usr); # directories to just mount read-only from the host
my @special = qw(dev etc root var proc tmp data); # special directories that aren't just simply read-only mounted from the host

open my $fstab, '>', "$datadir/fstab/$jail" or die "$!";

mkdir $jaildir or die "mkdir: '$jaildir': $!"; # Create jail root directory

foreach (@special, @mounts) { # create specials, mounts and "data"
	mkdir "$jaildir/$_" or die "mkdir: $jail/$_: $!"
}

foreach (@mounts) {
	# if you need a prettier version, pipe through "column -t"
	print $fstab "/$_ $jaildir/$_ nullfs ro 0 0\n";
}

# Code for special directories:

# /data
system "ln", ("-s", "--", "$jaildir/data", "$services/$jail"); # /srv/$jail -> jail/data

# /proc
print $fstab "procfs $jaildir/proc procfs rw 0 0\n";

# /tmp
chmod 041777, "$jaildir/tmp";

# /etc, /var - Download base.txz to create a template.txz
system "tar", ("-xpf", "$datadir/template.txz", "-C", $jaildir, "./etc", "./var");

system "chflags", ("schg", "$jaildir/var/empty");

# /dev
# Don't bother with mknod, rely on devfs + devfsrules_jail from /etc/default/devfs.rules
# Splitting the config file makes it easier to update parts of it via a script.
# Old trick I learned from debian.
open my $jailconf, '>', "$datadir/conf/50-$jail.conf";

# Template. Generated file will need some manual post-processing.
print $jailconf <<EOT
### EDIT ME ####
$jail {
  host.hostname = "$jail";
  mount.devfs;
  devfs_ruleset = 4; # "devfsrules_jail" -- Requires devfs_load_rulesets="YES" in /etc/rc.conf
  path = "$jaildir";
  mount.fstab = "$datadir/fstab/$jail";
  vnet = "new"; #requires VIMAGE to be enabled; don't use in combination with pf.
  vnet.interface = "${jailepair}b";

  # Make sure to replace epairX by the jail specific, unique epair number and adjust the IP addresses
  exec.prestart  = "$datadir/bin/host-hook \$path ${jailepair} pre-start";
  exec.poststart = "$datadir/bin/host-hook \$path ${jailepair} post-start";
  exec.prestop   = "$datadir/bin/host-hook \$path ${jailepair} pre-stop";
  exec.poststop  = "$datadir/bin/host-hook \$path ${jailepair} post-stop";

  exec.start = "/bin/sh /etc/rc";
  exec.stop = "/bin/sh /etc/rc.shutdown";

}
# cat $datadir/conf/*.conf > /etc/jail.conf when you're done
EOT
;

open my $rcconf, '>>', "$jaildir/etc/rc.conf";

print $rcconf <<EOT

## These lines were automatically appended by mkjail
ifconfig_lo0="up" # This takes care of both IPv4 and IPv6
#defaultrouter="" # You probably need to configure this unless you have a template rc.conf in your template tarball.
EOT
;

my $i = 0;
foreach (@jailip) {
	my $inet = "inet6";
	$inet = "inet" if /\d+\.\d+\.\d+\.\d+/;

	print $rcconf "ifconfig_${jailepair}b='$inet $_'\n" and next unless $i++;
	print $rcconf "ifconfig_${jailepair}b_alias$i='$inet $_'\n";
}

# /root
chmod 0700, "$jaildir/root";

close $jailconf;
close $fstab;
close $rcconf;

print "Please make sure to edit /etc/rc.conf inside your jail.\n";