Getting FreeBSD Jail to Run


In this short article, I discuss the way to run a full-blown FreeBSD jail, with some common tunings to get it more “normal”.


I assume the host has two network interfaces.  The “vtnet0” is Internet-facing and “vtnet1” is the intranet, where the jail will be running on.  This way, the jail does not have direct access to the Internet.  I also assume we set up the jail at “/root/myjail”.  You can define other locations you want.

Installing a Jail

To run an operating system, one need to install it on some media.  In context of a jail, we install it to a directory.  The FreeBSD handbook tells you to install from source and it is not necessary since BSD system files are mostly tar balls.  Download what you require like this.  For a minimal system, you will need the “base.txz”.  Hmm, no, “kernel.txz” is not required for the jail.

# mkdir /root/myjail
# tar Jxvf base.txz -C /root/myjail

Running a Jail

To run a jail, in particular, with networking, try the following command.

# jail -c path=/root/myjail name=myjail \
  interface=vtnet1 ip4.addr= \
  exec.start="/bin/sh /etc/rc"

Where are We?螢幕快照 2017-10-15 下午11.00.02

Here is what it looks like.  No, we are not inside the jail.  The so-called resource configuration script completed execution and we get back to the shell of the host.

Attaching to Jail

Attaching to a jail is simple.  We can simply start one more process in the jail.  (There is no such requirement all processes originate from the same process tree.)

# jexec myjail /bin/tcsh

When finished, you can get out by hanging up the shell (Ctrl-D).  That’s right, you won’t kill the jail by doing this.

Intranet Connection

Inside the jail, try ping other places, like the host IP…

# ping
ping: ssend socket: Operation not permitted

To allow ping, you need to change the following, in the host.  If you want to allow this from the beginning, the “allow.raw_sockets=1” option can be passed when the jail is initiated next time.

# jail -m name=myjail allow.raw_sockets=1

Internet Connection

The Intranet now works.  What about going to the Internet?

# ping
PING ( 56 data bytes

Seems there is something wrong with the routing.  Modify the PF rules in the host.  Put this line before the first block / pass statement.  (I assume you have a PF firewall installed.). After you reload the rules (“service pf reload”), it should work.

nat pass vtnet0 from vtnet1:network to any -> (vtnet0)

Domain Name Resolve

Let’s randomly pick a domain name to ping.

# ping
ping: cannot resolve Host name lookup failure

Ask your network administrators if there are suggested name servers.  If you have nothing in concern, use anything that works.  For my laziness, I use the shortest IP addresses I can recite.  Do this inside the guest:

# cat >> /etc/resolv.conf << EOF

Or, in the host:

# cat >> /root/myjail/etc/resolv.conf << EOF

Listing Processes

System tools like “ps” does not work by default:

# ps
ps: empty file: invalid argument

I think there could be better ways.  But the simplest way is to mount the device file system:

# mount -t devfs devfs /root/myjail/dev

Please note it is not necessary a good idea to people you don’t trust.


Proxy Server with FreeBSD and Squid (Part 2)


Previously, I discussed how to configure a Squid proxy.  The proxy is opaque that the web browsers have to be configured.  I continue to explain how a proxy can be made transparent; when web browsers go to the Internet, the requests gets intercepted and be processed by the proxy.  Like before, I use PF firewall and let it redirect the packets for me.

Step 1: Configure Network Gateway

In order to configure a a network router, it needs to have two network interfaces, virtual or physical.  One of them connects to the external world (through another router, maybe).  Another one connects to the intranet.  In PF, it is recommended to set up macros to determine the external and internal interfaces.  An example rule set will be as follows, where a Realtek was used as external and a Broadcom as internal.

nat pass on $extif from $intif:network to any -> ($extif)
pass in quick from $intif:network to any
pass out quick

In order for a FreeBSD server act as a router, it has to have the gateway variable enabled in /etc/rc.conf:


Once these are configured, reload the firewall rules for a smoke test.  Good luck.

Step 2: Configure Network Clients

Pick a computer and configure its network traffic through the router.  Technically, we change the gateway.

Microsoft Windows: Control Panel > Network and Sharing Centre > Network Interfaces > Properties > TCP/IP Version 4 > Configure > Gateway

Mac OS X: System Preference > Network > Gateway

FreeBSD: Update variable “defaultrouter” in /etc/rc.conf, then reboot

Everything should behave similar, except the network goes through the router.  Hopefully, the network link LEDs could give you some hints.  (Sorry being lazy not telling the proper way…)

Step 3: Packet Redirection and Squid

In PF configuration, add this line right after the NAT rule, and then reload:

rdr pass on $intif proto tcp from any to any port 80 -> ($intif) port 3129

In Squid configuration, add this line right after the original http port statement:

http_port 3129 intercept

I may explain what ‘intercept’ mode means in the next article…

Step 4: Testing

Use the client configured in the step 2 to browse the web.  Like last time, there should be some pages cached.  But make sure you visit pages that are not encrypted (like https); otherwise the proxy will not take effect.

Step 5: To be Continued

In the part 3 of this series, I will explain how to to intercept HTTPS connections as well.