There are other ways you can do this but the following instructions I know work and should get you up and running. I spent a lot of time myself trying different solutions and this is the most portable/bulletproof solution that should work with pretty much any setup. This is the sort of thing I wish I had found when I was setting up jails.
The following includes using ezjail to set things up but it's not required, I've simply included it for people that may be starting from scratch (although it makes deploying jails in the future take about 30 seconds once you know what you're doing). Following these instructions you should be able to get up and running in 5 - 10 minutes. I've included what to add to your config files but you can start all these things manually from the shell without a reboot. Even though we're using ezjail I highly recommend reading the handbook section on jails so you have a solid understanding of what's going on.
External Resources:
FreeBSD Jails Handbook
ezjail website
Step 1.
Installing ezjail
Now we're going to install the basejail that all jails you create will use.
Note: You can add a -P flag to have the ports collection installed in the basejail for all your jails to use. You can add the ports collection to the basejail at a later time also. The -P flag will also later update the ports collection of the basejail using portsnap.
Step 2.
Next we'll create the jail for our webserver.
Step 3.
Add the following to your hosts rc.conf (or manually via ifconfig)
ee /etc/rc.conf
To add your jails IP to a cloned loopback device via the shell enter the following at the shell prompt (this is not required if you plan on rebooting after all your configuration files are setup). Also unless you have your rc.conf setup this will not persist through a reboot.
Step 4.
Setup PF NAT, change ext_if to reflect what your interface is (check via ifconfig).
ee /etc/pf.conf
Some useful PF commands to check to make sure everything is working and setup correctly:
If you haven't setup your network device via the shell prompt you now need to reboot so FreeBSD can load all your changed configuration files.
Step 5.
Once all the proceeding is running we can enter the jail.
Setup the jails resolv.conf (you can use different nameservers here). Your hosts /etc/resolv.conf can be copied to your jail if you don't want to use the google nameservers.
ee /etc/resolv.conf (inside the jail, note resolv doesn't have a trailing "e")
Your jail should have network access now. If not type exit to return to the hosts shell and make sure your NAT rules are loaded.
If no rules are displayed it means that either PF isn't enabled or there is an error in your pf.conf. At the shell prompt type "pfctl -vnf /etc/pf.conf" to check your pf.conf for errors. If there are no errors make sure PF is enabled "pfctl -e". You should also remove any blocking rules from your pf.conf to ensure that isn't causing a problem.
Note: You can't ping from inside jails because raw sockets are disabled. If dig and whois work then your jails network access is working. If you need to use ping you can change the following setting on your host.
You will need to restart your jail for the changes to take affect. Make sure to disable raw sockets once you are done testing.
Step 6.
Now that all the basics are setup we can add a redirect for incoming traffic. This will redirect port 80 on the host system to the jail which is running the webserver (you can change these ports to match whatever application you are running in your jail). Your full /etc/pf.conf on the host should now look something like this:
Step 7.
With everything up and running we can further tweak the jail. Check the timezone the jail is using via the date command. The jail should be synchronized to the hosts clock but the timezone may differ. If the timezone is incorrect simply use tzsetup in the jails shell to select the correct timezone.
Your JAILS /etc/rc.conf can look something like this:
Finishing Up
You should now be able to go back and add jails and services that you want very easily. Take a look at ezjail flavours to tailor a jails initial setup to your needs. Also once you have things setup you can edit your hosts pf.conf to actually block certain traffic and test to make sure that works accordingly. But both of those things are beyond the scope of this HowTo though.
I hope this helps people out.
The following includes using ezjail to set things up but it's not required, I've simply included it for people that may be starting from scratch (although it makes deploying jails in the future take about 30 seconds once you know what you're doing). Following these instructions you should be able to get up and running in 5 - 10 minutes. I've included what to add to your config files but you can start all these things manually from the shell without a reboot. Even though we're using ezjail I highly recommend reading the handbook section on jails so you have a solid understanding of what's going on.
External Resources:
FreeBSD Jails Handbook
ezjail website
Step 1.
Installing ezjail
Code:
cd /usr/ports/sysutils/ezjail/ && make install clean
man ezjail-admin at the shell prompt to get a basic understanding of the commands
Now we're going to install the basejail that all jails you create will use.
Code:
ezjail-admin install
Note: You can add a -P flag to have the ports collection installed in the basejail for all your jails to use. You can add the ports collection to the basejail at a later time also. The -P flag will also later update the ports collection of the basejail using portsnap.
Step 2.
Next we'll create the jail for our webserver.
Code:
ezjail-admin create WEBSERVER 10.1.1.1
Step 3.
Add the following to your hosts rc.conf (or manually via ifconfig)
ee /etc/rc.conf
Code:
#Setup interface all jails will use
#Make sure this netmask is unique in your rc.conf
cloned_interfaces="lo1"
ifconfig_lo1="inet 10.1.1.1 netmask 255.255.255.0"
#Future jails can look like the following, aliases should always use 255.255.255.255 netmask
#ifconfig_lo1_alias0="inet 10.1.1.2 netmask 255.255.255.255"
# Enable port forwarding and packet filtering
pf_enable="YES"
pf_rules="/etc/pf.conf"
# Jails
ezjail_enable="YES"
To add your jails IP to a cloned loopback device via the shell enter the following at the shell prompt (this is not required if you plan on rebooting after all your configuration files are setup). Also unless you have your rc.conf setup this will not persist through a reboot.
Code:
ifconfig lo1 create
ifconfig lo1 inet 10.1.1.1 netmask 255.255.255.0
Step 4.
Setup PF NAT, change ext_if to reflect what your interface is (check via ifconfig).
ee /etc/pf.conf
Code:
#INTERFACES
ext_if="em0"
int_if = "lo1"
jailnet = $int_if:network
# NAT
nat on $ext_if from $jailnet to any -> ($ext_if)
Some useful PF commands to check to make sure everything is working and setup correctly:
Code:
pfctl -e Enable PF
pfctl -vnf /etc/pf.conf Check /etc/pf.conf for errors, but do not load ruleset
pfctl -F all -f /etc/pf.conf Flush all rules (nat, filter, state, table, etc.) and reload from the file /etc/pf.conf
If you haven't setup your network device via the shell prompt you now need to reboot so FreeBSD can load all your changed configuration files.
Step 5.
Once all the proceeding is running we can enter the jail.
Code:
ezjail-admin console WEBSERVER
Setup the jails resolv.conf (you can use different nameservers here). Your hosts /etc/resolv.conf can be copied to your jail if you don't want to use the google nameservers.
ee /etc/resolv.conf (inside the jail, note resolv doesn't have a trailing "e")
Code:
# google nameservers
nameserver 8.8.8.8
nameserver 8.8.4.4
Your jail should have network access now. If not type exit to return to the hosts shell and make sure your NAT rules are loaded.
Code:
pfctl -s nat
If no rules are displayed it means that either PF isn't enabled or there is an error in your pf.conf. At the shell prompt type "pfctl -vnf /etc/pf.conf" to check your pf.conf for errors. If there are no errors make sure PF is enabled "pfctl -e". You should also remove any blocking rules from your pf.conf to ensure that isn't causing a problem.
Note: You can't ping from inside jails because raw sockets are disabled. If dig and whois work then your jails network access is working. If you need to use ping you can change the following setting on your host.
Code:
sysctl security.jail.allow_raw_sockets=1
You will need to restart your jail for the changes to take affect. Make sure to disable raw sockets once you are done testing.
Code:
sysctl security.jail.allow_raw_sockets=0
Step 6.
Now that all the basics are setup we can add a redirect for incoming traffic. This will redirect port 80 on the host system to the jail which is running the webserver (you can change these ports to match whatever application you are running in your jail). Your full /etc/pf.conf on the host should now look something like this:
Code:
#INTERFACES
ext_if="em0"
int_if = "lo1"
jailnet = $int_if:network
# Name and IP of jails
WEBSERVER="10.1.1.1"
# NAT
nat on $ext_if from $jailnet to any -> ($ext_if)
# Redirect any packets requesting port 80 or 443 to jailed webserver
rdr pass on $ext_if inet proto tcp to port http -> $WEBSERVER port http
rdr pass on $ext_if inet proto tcp to port https -> $WEBSERVER port https
Step 7.
With everything up and running we can further tweak the jail. Check the timezone the jail is using via the date command. The jail should be synchronized to the hosts clock but the timezone may differ. If the timezone is incorrect simply use tzsetup in the jails shell to select the correct timezone.
Your JAILS /etc/rc.conf can look something like this:
Code:
rpcbind_enable="NO" # Disable the RPC daemon
cron_flags="$cron_flags -J 15" # Prevent lots of jails running cron jobs at the same time
syslogd_flags="-ss" # Disable syslogd listening for incoming connections
sendmail_enable="NONE" # Completely disable sendmail
clear_tmp_enable="YES" # Clear /tmp at startup
Finishing Up
You should now be able to go back and add jails and services that you want very easily. Take a look at ezjail flavours to tailor a jails initial setup to your needs. Also once you have things setup you can edit your hosts pf.conf to actually block certain traffic and test to make sure that works accordingly. But both of those things are beyond the scope of this HowTo though.
I hope this helps people out.