How To: Execute Firefox in a jail using iocage and ssh/jailme

Revisiting this nice thread after my recent 11.0 reinstall. I originally followed the jailme route, but decided to switch to the ssh-based one because having to use xhost felt wrong. But I still seem to need xhost, even when using ssh. Without it, I get an "Invalid MIT-MAGIC-COOKIE-1 keyUnable to init server: Broadway display type not supported: browser:10.0 Error: cannot open display: browser:10.0" error. I followed the instructions, and don't remember having to use xhost when I last used X11 forwarding (which admittedly was some while back), so I'm wondering what is going on here.
The howtodo says that it needs xauth(1) for the ssh method. It is working for me as described. I am not sure if things have changed with FreeBSD 11.0. I am still using FreeBSD 10.3. I guess you just might have overlooked a small detail somewhere.
Then, come back to the host and configure de client side of ssh(1). It is quite boring to have to type password each time. So setup a public key authentication.
% ssh-keygen -t rsa -b 4096 -C "" -f ~/.ssh/injail
% ssh jailuser@ mkdir .ssh
% cat ~/.ssh/ | ssh jailuser@ 'cat >> .ssh/authorized_keys'
I have stumbled over ssh-copy-id(1) in a text book. This could handle the task of line 2 and 3. I wonder if there is at least a single person who knows all the nice tools we have. It is not me :D.
I am not sure if things have changed with FreeBSD 11.0. I am still using FreeBSD 10.3.
By the way, just to answer my own question, the nice guide works fine on FreeBSD11.0. Merci beaucoup , hukadan.
Thanks for the useful guide. Some minor differences encountered (FreeBSD 11), though:
  • instead of pfctl, I did service pf start and service pflog start
  • before doing anything with iocage, I had to iocage fetch
  • to get hostname set correctly, I had to iocage set host_hostname=myjail myjail. Otherwise it would just stubbornly default to the jail UUID, which for instance prevented X11 forwarding from working
Hello! I thank you very much for this awesome guide and I'd like to necro this since I stumbled upon some issues.
I can start Links in textmode but as soon as I do:
jailme $myjail firefox --new-instance

I get:
JavaScript error: jar:file:///usr/local/lib/firefox/omni.ja!/components/XULStore.js, line 70: Error: Can't find profile directory.
Together with a GTK-window stating:
Your Firefox profile cannot be loaded. It may be missing or inaccessible.

I tried copying my ~/.mozilla folder over to a /usr/home directory in my jail but the problem was still there.
Does anyone have any ideas?

I don't need to have Xorg or something like that installed in the jail since it's supposed to use the system's own Xorg, yes?
I start www/firefox by /usr/local/sbin/jailme fox firefox 2>/dev/null & using x11/dmenu. I have just tried, it works from the command line, too.
EDIT: I checked out that it works when starting from an completely empty home in the jail. And it will use the system's Xorg.
Hi! Today I noticed that the first Firefox session (of the Xsession), in jail, gave the code:
libGL error: failed to open drm device: No such file or directory

And through a quick search I got reminded that the devices are related to /etc/devfs.rules so what I did was to put: add path 'dri*' unhide in the jail section of /etc/devfs.rules.

Problem solved. :D
on linux all that would do no good. bsd i'm not sure.

changing root (jail) ONLY CHANGES __DEFAULT disk. the root application running can still mount (drives, memory, etc) just like processes running in the booted /

doing that assumes you'll limit access to a non-root user inside the jail. but you can do that without a jail: it's called: LOGIN. (noting you can log in as a new user for each application your run, if you like to keep apps separated)

jails are very useful if your getting around /lib "dependency issues" though, to provide alternate roots.

freebsd has added some new features but they aren't meant to provide what your thinking. there isn't documentation on "jail breaks" for no reason. the fact is "jails" are a misnomer that lead people to believe they are something they are not. (or rather not yet - there are some who firmly believe chroot(1) should be hacked until it works like a jail %100 :)

now for freebsd ... the kernel and libc may not make "every options" changeable on a per user / per process basis, but *might* make "copies" of the feature per / (per root). so: if you can filter network access using libc (or using kernel options) per user do that. only provide a whole disk copy of a new libc/login root if your libc / kernel simply don't support the (filter option) your looking for as a regular option (not requiring a whole mini OS disk copy)

what that means is: if your (root user) can set ulimit, if he/she can firewall based on application or based on UID, or of your user can do the equivalent by adding personal firewall rules (added to roots post-op), that's all you need.
I have a problem with Motivation here.

I've run linux with a firewall, (freebsd a little), redhat debian slackare, other, and sometimes found a glitch had my firewall left open (NOT suggested).

I've never had a system freaked by my web browser or otherwise in 30 years.

So I have problems with a suggestion people should run their desktop inside a jail. I don't think it will be helpful in general: but it will make their life more complicated surely.

the worst i've had browser wise is

#1 hacks doing irreversible changes causing forced upgrades (ie, website requiring html6 support, broken on html7, that have no alternate html5 page - bad web HACKS)

#2 a debian linux webbrowser that consumed memory until it crashed: firefox-2.0 (they compiled it incorrecly).
> cute fuzzy wrote: "Just tried it on both the host system and the jailed one. It works, but stressing it a bit causes a core dump due to "illegal hardware instruction" (on both). But it is not a news for me, other QT5-related programs also had this problem on my system some time ago (in fact I use their QT4 version)."

ditto. i tried qupzilla and it'd been ruined by versional issues in Qt that were unresolvable by lib version/depends. in linux LFS this is. it was fresh, i liked seeing what the gz author did - amazing he got as far as he did. (note: it's a fresh project not intended to be a full web solution)

That Qt is NOT APPLE QT which apple still makes and puts in new products. That's kde (german/novell/anthem) Qt they copylefted from Apple's free 1.x release to the public to help Win95 users. it contained NO gui at the time. the GUI is totally KDE related, not Qt at all :)
i hate to add on more here but one more thought.

by watching traffic i'm sure that china (by ip) and others continually polled my PC's ports (portscanned) and tried to upload viruses to my FTP server and APACHE server

lesson here is: follow BSD's security guide essentials (ie, freebsd says to enable a firewall, and if they haven't already done it for you, do it). if they say "don't visit promiscous web sites" or sites that issue warnings, then don't :) if you see bogus messages: just close the browser popup window. the simple essentials will do fine. don't open PDF (unless in safe mode) or Word documents you find on the internet unless your running as a un-elevated user and $HOME doesn't contain your valued save files (or you have a backup).

beyond that, i wouldn't worry unless your running servers that due to configuration allow "login", "upload", or something where a virus could be activated.

yes attacks are run but if you follow the essentials that are mentioned - your covered for home use

(if you ever develop on a sensitive server system by then you'll know what to do after reading many docs. but really: you don't run web browsers on a sensitive system because they're inherently broken ware)
(if you ever develop on a sensitive server system by then you'll know what to do after reading many docs. but really: you don't run web browsers on a sensitive system because they're inherently broken ware)

So basically, in your first message you say that you do not see the point because you never had any problem caused by a browser. Then in your third message you admonish us to never run a browser on a sensitive system. So maybe in the your fifth message you will acknowledge that this how-to was well advised.

As far as the how-to is concerned, one way to improve performance over ssh could be to use a very small key size. I am not sure what's the lowest size allowed by sshd is but use the absolute minimum since this is not even exposed to the outside world.

I personally think that web browsers have become quite reliable sandboxes at this point, we're far from the ActiveX days. What I mistrust is user's judgement with downloaded files (same for email attachments). Therefore, such a jail to be useful should also include LibreOffice, a PDF viewer and an image viewer so that files can be checked in a secured environment before being used by the host.

In a corporate environment I would have an intermediary jail scan the files using an antivirus before copying them to a location mounted by the host. I would also recreate the browser jail every time to start from a fresh system at every session. There could also be a browser in the host restricted to internal and whitelisted websites, while the jail browser would be able browse the whole internet.

I find jails so inspiring, they have already become one of my preferred features of FreeBSD. There seems to be no limit to what can be achieved in terms of having a system exactly matching your needs.

Great how-to!
Wanting to achieve something similar, I read through this thread, but believe I have found a simpler solution, taking some inspiration from debguy's earlier post. Perhaps my solution is not as secure as running the web browser in a jail, however it may well be 'good enough' and has minimum complexity, requiring neither a jail, nor having to use ssh, nor having to xhost + the display server.

Let's recap what I was trying to do when I found this useful and interesting thread. I have a single computer running freebsd 11 and X11. I want to have a 'clean' userid that is used for doing things like online banking. And I want to have a 'dirty' userid that can be used for general browsing anywhere on the web that might be exposed to picking up website browser exploits.

So I start by making two userids: 'clean' and 'dirty'. They both get separate home directories, and I set up the permissions so that neither can gain access to each others home directories, eg:-

drwxr-x--- 22 clean clean 1536 2 Jun 20:26 clean
drwxr-x--- 18 dirty dirty 3072 2 Jun 20:35 dirty

Assuming the machine is set up to run an X display manager (eg xdm), login as 'dirty'.
The X server is hence started as a process owned by 'dirty' userid.
Now dirty can start X clients like a browser without any further issue.
Most of time on the machine is spent logged in as 'dirty', but if I want to do something like read email or do some online banking, I would prefer to login as 'clean' and run a separate instance of the browser.

We can arrange for the 'clean' userid to also be able to run X clients on the same X display.
In an xterm, login as 'clean' by running

# login clean

Once logged in as 'clean', it will be found that attempts to run a client (eg another xterm) will be
rejected by the display server due to failed authorisation.

We don't need to resort to ssh'ing to localhost or unlocking the X server using xhost +;
there is instead a simpler method using xauth. The 'dirty' userid already has an xauth security
token to be allowed to run clients on the X server it started. This token can be exported by 'dirty' userid
and imported by 'clean' userid, which will then allow 'clean' to run clients on the X server owned by 'dirty'.

To set this up do the following:
1. in an xterm logged in as 'dirty', run
# xauth extract - $DISPLAY > /tmp/myauth
(Note that $DISPLAY should already have been set to :0)

2. In a separate xterm logged in as 'clean', run the command
# xauth merge /tmp/myauth
# export DISPLAY=:0 (I'm running bash)

Delete /tmp/myauth afterwards.

And hey presto, the 'clean' userid is now able to start any X client it desires running on the X server
owned by 'dirty' userid. So the 'clean' userid can now start a separate instance of the web browser.

Because there are two isloated home directories, each with their own browser cache and config,
there is no collision in the filesystem. And ps shows that the two web browser instances result in process trees owned by the two different userids, so there should be address space isolation between the two browser instances. Now 'clean' can go ahead and do his online banking, and 'dirty' can go mess around looking at general websites, in isolation from each other.

The nice thing about this approach is its simplicity; we don't need a jail, we don't need to ssh back in, and we don't need to open the server to other connections using xhost +. We just use the filesystem permissions and xauth security provided by the X server. I'm not qualified to say whether an approach like this would be safe from exploits like spectre and meltdown, but it might be good enough to keep a first level of isolation between websites that you want to keep private and general browsing. Especially if you don't go searching for dodgy warez sites in the 'dirty' browser ;-)

I would be interested in people's thoughts on this approach...
And before anyone spots my obvious mistake...
I should have said: if I login over the X display manager (xdm,wdm etc..) the X server process itself is owned by root, not the 'dirty' id. Of course if some website code running in the 'dirty' browser manages to get root then all bets are off, but I'm not sure a jail gives any greater protection under those circumstances, as was pointed out earlier...
Minor annoyance number 1 is that if the X server is re-started, the 'clean' userid must re-import the xauth token before it can start clients again. This can likely be scripted, I'll have a think.

Minor annoyance number 2 is that 'clean' must start his clients manually from a terminal eg by typing 'firefox'. Running a second X server eg using Xnest or Xephyr may provide a nice way to give 'clean' his own complete desktop in a separate (potentially fullscreen) window. I'll have a play with that tomorrow and post an update.
I played around a bit more, I found that Xephyr provides a nice way to make a nested X server, within which a second instance of the window manager can be started. What this essentially provides is two display servers used by two different userids on the system; both are able to run separate instances of the desktop and web brower. We can then choose to keep all activities that might pick up web exploits in one browser/userid and reserve the second browser/userid for 'safe' websites like online banking. So I think this approximates the original idea of running the untrusted web browser in a jail or sandbox. The scope of any exploits run in that untrusted browser are limited to the access rights of the userid who owns its pid. As long as any exploit loaded from the web into its browser can't get root.

And the ultimate step... if we really, really don't trust this dirty web browser, is to run it on a separate dedicated machine, and present its display surface on the same desktop through the nested x-server over ssh.
I am currently running 12.1-RELEASE and tried accomplish the same setup. I encountered the same error as yggdrasil. The solution was: in the jailed environment the /etc/hosts file needs the ip+hostname of the jail so it can resolve itself, and in sshd_config in the jail we need to set "X11UseLocalhost no" - then xforwarding works. However, I'd like to get jailme to work, I get

Unable to init server: Could not connect: Abstract UNIX domain socket addresses not supported on this system
Error: cannot open display: :0.0

I am running xdm on ttyv8 and then "exec startxfce4" in ~/.xinitrc so I wonder how I can run "startx -- -listen tcp" (or whatever I have to do to get that functionality)
hoorrray, two steps later my system is working as expected, how nice! The jailed applications, mainly browsers, now run via "ssh -Y", via jailme or with xephyr. Two things to remark:
*) on the hardware I added my hostname + IP-address to /etc/hosts
*) /usr/local/etc/X11/xdm/Xservers now contains the (only) the line: ":0 local /usr/local/bin/X -listen tcp :0"
did anyone manage to get this setup running with vnet jail + jailme - is it even possible if the jail has its own ip stack?
This method is not working under FreeBSD 13.0-STABLE. For example the PF rules for adding NAT is getting rejected. Please make the necessary changes to your tutorial & make it compatible for FreeBSD 13.0-STABLE.
Unable to init server: Could not connect: Abstract UNIX domain socket addresses not supported on this system
You'll like need to do xhost + on your host; otherwise, you can't properly connect to your X11. Alternatively, you can transfer the magic cookie, I believe.