jails VNET jail with exec.jail_user

I'm trying to set up a VNET jail that runs a single process as an unprivileged user via exec.jail_user. I'm running into difficulties getting the address and routing tables set up inside the jail. As an unprivileged user, I cannot add a ifconfig and route commands to exec.start as described in the handbook. The only option I can see is to allow the jail to be run as run (i.e., omit exec.jail_user) then drop privileges using su -m username /path/to/app or daemon -u username /path/to/app. Those options seem like hacks and not the intended way to accomplish this.

I attempted to be clever by adding jexec commands using exec.created, but this indicated that the interface does not exist in the jail, which I found confusing. Here is a config with my attempts. It's likely that I'm just doing something wrong or overlooked something in the documentation, but I'm not sure how to proceed. Any advice, troubleshooting tips, or solutions would be appreciated.

Bash:
# freebsd-version -kru
15.0-RELEASE-p4
15.0-RELEASE-p4
15.0-RELEASE-p4

Bash:
postgres {
  # Logging
  exec.consolelog = "/var/log/jail_console_${name}.log";

  # Permissions
  allow.raw_sockets;
  exec.clean;
  mount.devfs;
  devfs_ruleset = 5;

  # Postgres requires access shared memory
  # The new setting will provide the jail its own namespace
  sysvshm = new;

  # Path/Hostname
  path = "/jail/${name}";
  host.hostname = "${name}";

  # User
  exec.jail_user = "postgres";

  # Debug
  persist;

  # Mounts
  mount = "/zdata/postgres /jail/postgres/var/db/postgres nullfs rw 0 0";

  # VNET
  vnet;
  vnet.interface = "${epair}b";

  # Networks/Interfaces
  $id = "11";
  $ip = "10.10.80.${id}/24";
  $gateway = "10.10.80.1";
  $bridge = "vnet80";
  $epair = "epair${id}";

  # Host network setup
  exec.prestart += "/sbin/ifconfig ${epair} create up";
  exec.prestart += "/sbin/ifconfig ${epair}a up descr jail:${name}";
  exec.prestart += "/sbin/ifconfig ${bridge} addm ${epair}a up";

  # Jail network setup - Added an ifconfig -a for debugging
  exec.created  = "jexec ${name} /bin/sh -c '/sbin/ifconfig -a'";
  exec.created += "jexec ${name} /bin/sh -c '/sbin/ifconfig ${epair}b ${ip} up'";
  exec.created += "jexec ${name} /bin/sh -c '/sbin/route add default ${gateway}'";

  # Jail network setup - works fine without exec.jail_user
#  exec.start    = "/sbin/ifconfig ${epair}b ${ip} up";
#  exec.start    += "/sbin/route add default ${gateway}";

  #exec.start    = "/usr/local/bin/pg_ctl -D /var/db/postgres/data -l /var/db/postgres/logfile start";
  #exec.stop     = "/usr/local/bin/pg_ctl -D /var/db/postgres/data -l /var/db/postgres/logfile stop";

  exec.poststop = "/sbin/ifconfig ${bridge} deletem ${epair}a";
  exec.poststop += "/sbin/ifconfig ${epair}a destroy";
}

If I attempt to start the jail using the above config, I receive the following:
Bash:
# jail -v -c postgres
postgres: run command: /sbin/mount -t nullfs -o rw /zdata/postgres /jail/postgres/var/db/postgres
postgres: run command: /sbin/mount -t devfs -oruleset=5 . /jail/postgres/dev
postgres: run command: /sbin/ifconfig epair11 create up
epair11a
postgres: run command: /sbin/ifconfig epair11a up descr jail:postgres
postgres: run command: /sbin/ifconfig vnet80 addm epair11a up
postgres: jail_set(JAIL_CREATE) name=postgres allow.raw_sockets devfs_ruleset=5 sysvshm=new path=/jail/postgres host.hostname=postgres persist vnet=new
postgres: created
postgres: run command: /bin/sh -c jexec postgres /bin/sh -c '/sbin/ifconfig -a'
lo0: flags=8008<LOOPBACK,MULTICAST> metric 0 mtu 16384
        options=680003<RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>
        groups: lo
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
postgres: run command: /bin/sh -c jexec postgres /bin/sh -c '/sbin/ifconfig epair11b 10.10.80.11/24 up'
ifconfig: interface epair11b does not exist
jail: postgres: /bin/sh -c jexec postgres /bin/sh -c '/sbin/ifconfig epair11b 10.10.80.11/24 up': failed
postgres: removed
postgres: run command: /sbin/umount /jail/postgres/dev
postgres: run command: /sbin/umount -t nullfs /jail/postgres/var/db/postgres
 
I have only just tried messing about with executing programs in jails and have found that jexec does not work in an iocage jail.

Instead I need to run something like

iocage exec JAILNAME ifconfig

as an example.
 
Maybe you should set up doas or mdo (mac_do) to execute ifconfig and route as root user in the jail.

Alternatively, remove vnet.interface=epair11b and do it manually in exec.created and exec.prestop, like:
Code:
exec.created += "/sbin/ifconfig ${epair}b vnet ${name}";
exec.created+= "jexec ${name} /sbin/ifconfig ${epair}b up";
exec.created += "jexec ${name} /sbin/ifconfig ${epair}b inet 10.10.80.${id}/24";
exec.created += "jexec ${name} /sbin/route add default ${gateway}";
exec.prestop += "jexec ${name} ${epair}b down";
exec.prestop += "/sbin/ifconfig ${epair}b -vnet ${name}";
 
Back
Top