INTRODUCTION :
___________________________________________________________
___________________________________________________________
In my previous article Defend Your Network And Privacy : VPN Gateway With FreeBSD, we made a FreeBSD
router acting as a VPN gateway, and providing DNS cache and encryption, and DHCP. It was further hardened by restricting users privileges, increasing memory protection, adding randomness in the
IP stack and system processes, enabling swap encryption, creating an SSH Eliptic Curve key, and increasing securelevel. However, there was still some room for improvement.
One of the greatest FreeBSD's features is Jails. Jails enable us to create a separate environnement, with its own users and processes, its own IP address and hostname, that cannot access the running host system. A jail is especially useful for a service exposed to the internet such as a webserver, but at some extent for any network service. Indeed jailing a DHCP server for instance may not prevent an exploit from a malicious client on the LAN side, but it will at least not give automatically full takeover over the host. A jail is not meant to prevent a criminal from craking the service running inside it, indeed a jail cannot do anything about the last MySQL or PHP vulnerability, but rather will contain the intruder once he gets in. It is an additional strong security layer an intruder will have to try breaking to access the host, and it will give you time to spot the intrusion. It can make all the difference between the hack of a network service running on the host with a complete takeover of the running host and the remaining network, and between an intrusion confined into a jail, unable to access the host or to do lateral moves on the network. Jails are not a bullet proof invincible security feature however, but they still are very strong if properly used.
In the following we will harden our FreeBSD gateway a little more. We will move into jails the DNS cache Unbound, as well as DNSCrypt-proxy. While we are at it, we will move into another jail the DHCP server, and finally in a third jail, we will install and configure the Network Intrusion Detections System (NIDS) Snort.
One of the greatest FreeBSD's features is Jails. Jails enable us to create a separate environnement, with its own users and processes, its own IP address and hostname, that cannot access the running host system. A jail is especially useful for a service exposed to the internet such as a webserver, but at some extent for any network service. Indeed jailing a DHCP server for instance may not prevent an exploit from a malicious client on the LAN side, but it will at least not give automatically full takeover over the host. A jail is not meant to prevent a criminal from craking the service running inside it, indeed a jail cannot do anything about the last MySQL or PHP vulnerability, but rather will contain the intruder once he gets in. It is an additional strong security layer an intruder will have to try breaking to access the host, and it will give you time to spot the intrusion. It can make all the difference between the hack of a network service running on the host with a complete takeover of the running host and the remaining network, and between an intrusion confined into a jail, unable to access the host or to do lateral moves on the network. Jails are not a bullet proof invincible security feature however, but they still are very strong if properly used.
In the following we will harden our FreeBSD gateway a little more. We will move into jails the DNS cache Unbound, as well as DNSCrypt-proxy. While we are at it, we will move into another jail the DHCP server, and finally in a third jail, we will install and configure the Network Intrusion Detections System (NIDS) Snort.
DESCRIPTION :
___________________________________________________________
___________________________________________________________
The FreeBSD gateway we will harden is structured as below :
- (jailed) DHCP server to distribute network parameters to your LAN
- (jailed) DNS cache/server to speed up DNS requests
- (jailed) DNS encryption so that every outgoing request is encrypted on port 443
- (jailed) Network Intrusion Detection System (Snort) to warn you about suspicious traffic
- (host) VPN gateway to your VPN provider
It has been validated and working for the FreeBSD VPN gateway configured in my previous article, but it should be applicable to any FreeBSD router.
- (jailed) DHCP server to distribute network parameters to your LAN
- (jailed) DNS cache/server to speed up DNS requests
- (jailed) DNS encryption so that every outgoing request is encrypted on port 443
- (jailed) Network Intrusion Detection System (Snort) to warn you about suspicious traffic
- (host) VPN gateway to your VPN provider
It has been validated and working for the FreeBSD VPN gateway configured in my previous article, but it should be applicable to any FreeBSD router.
PREREQUISITES :
___________________________________________________________
___________________________________________________________
- A working FreeBSD router, preferably FreeBSD 10.1-RELEASE or better.
- A warm cup of coffee (I always function better with it!)
The network map is a typical home network with one or two computers, and one DSL router from the ISP :
I am using the usual router, a Shuttle DS437, which is a fanless low energy router (10W idle). FreeBSD 10.1-RELEASE finally properly recognise the network card chipset RTL8111G! That's a good news, it is no longer required to use a STABLE or CURRENT version.
- A warm cup of coffee (I always function better with it!)
The network map is a typical home network with one or two computers, and one DSL router from the ISP :
I am using the usual router, a Shuttle DS437, which is a fanless low energy router (10W idle). FreeBSD 10.1-RELEASE finally properly recognise the network card chipset RTL8111G! That's a good news, it is no longer required to use a STABLE or CURRENT version.
SUMMARY :
___________________________________________________________
___________________________________________________________
-
INTRODUCTION
- CREATING JAILS
- JAIL-DNS
- JAIL-DHCP
- JAIL-SNORT
DESCRIPTION
PREREQUISITES
CONCLUSION
LINKS
1. CREATING JAILS
___________________________________________________________
___________________________________________________________
There is different ways to build a jail. You can use a package dedicated to jail building and management such as ezjail, or build jails from sources manually. If the latter, you can unpack
sources from the CD installation media, or download them using subversion package. We will use this last method. If you want an example with ezjail + DHCP + Bind,
check this blog.
Also, for jails to work properly, no process on the host should listen on all interfaces (usually *:port). On the default FreeBSD install, NTP and Syslog are concerned. Please check this procedure if not already done, before going forward.
We have to choose a path for building our jail, it can be for instance /usr/jail/jail-dns, as it will prepare the next jail we will setup. Then we install subversion, and download the sources:
Once it's done, we can build our jail. For the first jail it takes a long time to do the buildworld step, but this step has to be done only once:
Once the jail building process is done, there is a minimal set of files to create, or copy from the host, for the jail to run:
Create a minimal /etc/rc.conf:
At this point, to build further jails, some steps can be skipped (like buildworld). It is basically as follow:
Do not forget to add a minimal /etc/rc.conf as well. The whole process is easily scriptable, and more friendly to use when scripted. Now that at least a jail is created, let us continue to the next step to configure our DNS jail.
Also, for jails to work properly, no process on the host should listen on all interfaces (usually *:port). On the default FreeBSD install, NTP and Syslog are concerned. Please check this procedure if not already done, before going forward.
We have to choose a path for building our jail, it can be for instance /usr/jail/jail-dns, as it will prepare the next jail we will setup. Then we install subversion, and download the sources:
$ DIR=/usr/jail/jail-dns
$ sudo mkdir -p $DIR
$ sudo pkg install subversion
$ svn checkout http://svn0.eu.freebsd.org/base/release/10.1.0 /usr/src
$ sudo mkdir -p $DIR
$ sudo pkg install subversion
$ svn checkout http://svn0.eu.freebsd.org/base/release/10.1.0 /usr/src
Once it's done, we can build our jail. For the first jail it takes a long time to do the buildworld step, but this step has to be done only once:
$ cd /usr/src
$ sudo make buildworld
$ sudo make installworld DESTDIR=$DIR
$ sudo make distribution DESTDIR=$DIR
$ sudo mount -t devfs devfs $DIR/dev
$ sudo make buildworld
$ sudo make installworld DESTDIR=$DIR
$ sudo make distribution DESTDIR=$DIR
$ sudo mount -t devfs devfs $DIR/dev
Once the jail building process is done, there is a minimal set of files to create, or copy from the host, for the jail to run:
$ sudo cp /etc/localtime $DIR/etc/
$ sudo cp /etc/resolv.conf $DIR/etc/
$ touch $DIR/etc/fstab
$ sudo cp /etc/resolv.conf $DIR/etc/
$ touch $DIR/etc/fstab
Create a minimal /etc/rc.conf:
$ sudo vi $DIR/etc/rc.conf
# IP not defined here, but on the host
network_interfaces=""
# Sendmail : disabled
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
# Syslog : do not open network socket
syslogd_flags="-ss"
network_interfaces=""
# Sendmail : disabled
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
# Syslog : do not open network socket
syslogd_flags="-ss"
At this point, to build further jails, some steps can be skipped (like buildworld). It is basically as follow:
$ DIR=/usr/jail/jail-xxx
$ sudo mkdir -p $DIR
$ cd /usr/src
$ sudo make installworld DESTDIR=$DIR
$ sudo make distribution DESTDIR=$DIR
$ sudo mount -t devfs devfs $DIR/dev
$ sudo mkdir -p $DIR
$ cd /usr/src
$ sudo make installworld DESTDIR=$DIR
$ sudo make distribution DESTDIR=$DIR
$ sudo mount -t devfs devfs $DIR/dev
Do not forget to add a minimal /etc/rc.conf as well. The whole process is easily scriptable, and more friendly to use when scripted. Now that at least a jail is created, let us continue to the next step to configure our DNS jail.
2. JAIL-DNS
___________________________________________________________
___________________________________________________________
As our first step, we need to define the jail's IP address (10.0.0.2) and hostname (jail-dns), and enable jails use in /etc/rc.conf. We also need to add the jail's IP address as an
alias for our LAN network interface re0:
As the re0 alias will be created at next boot, if we want to use it now without rebooting, we have to create it:
The last main configuration file for jail, /etc/jail.conf:
Everything above the line "jail-dns {" is global and effective for every jail. The variable "$name" is automatically populated with the jail name to which it applies, which means that if we have many jails, it will be applied to each jail using the jail's name. Of course if you want a jail hostname different than the jail name, you can move the "host.hostname = your-name" inside the individual jail config between the brackets. About the securelevel, if you do not specify it, the jail default securelevel will be the same as the host. If the host has a securelevel equals to 1, the jail will have the same. You can comment it out at first, and once your jail is fully working, set it to 3 at the end.
Now let's start our jail and check it is running:
First things to do once your jail is live, rebuild the database mail aliases, change root password, and eventually create an additional unprivileged user. Accounts inside the jail are only jail's account. For instance Jail's root account is not the host's root account and has no power on the host. It is advised to set a different password in the jail. We can also update it before going further:
We need to enable the DNS cache Unbound, which is part of the base system. We also need to install the package dnscrypt-proxy. To install a package, you can either drop a shell into the jail, or install it from the host as below:
Either way, we will continue from within the jail (notice the prompt going from $ to #):
Setting up Unbound and Dnscrypt startup parameters (you can choose the DNS server of your choice):
Create Unbound file unbound.conf:
Create Unbound file forward.conf:
Modify /etc/resolv.conf to not point to the host anymore, but on our own IP address instead:
Prevent any automatic file configuration modification by the system:
Start Unbound and DNSCrypt, and check it is working with a randomly chosen DNS name:
Log off from the jail, modify the /etc/resolv.conf of the host to point to your jail-dns, and if working disable your host Unbound and DNSCrypt if already installed:
Eventually delete dnscrypt-proxy from the host if installed:
Our first jail is operational.
$ sudo vi /etc/rc.conf
# Jails
jail_enable="YES"
ifconfig_re0_alias0="inet 10.0.0.2 netmask 255.255.255.0"
jail_enable="YES"
ifconfig_re0_alias0="inet 10.0.0.2 netmask 255.255.255.0"
As the re0 alias will be created at next boot, if we want to use it now without rebooting, we have to create it:
$ sudo ifconfig re0 10.0.0.2 alias
The last main configuration file for jail, /etc/jail.conf:
$ sudo vi /etc/jail.conf
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.clean;
mount.devfs;
path = /usr/jail/$name;
host.hostname = $name;
jail-dns {
ip4.addr = 10.0.0.2;
securelevel=3;
}
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.clean;
mount.devfs;
path = /usr/jail/$name;
host.hostname = $name;
jail-dns {
ip4.addr = 10.0.0.2;
securelevel=3;
}
Everything above the line "jail-dns {" is global and effective for every jail. The variable "$name" is automatically populated with the jail name to which it applies, which means that if we have many jails, it will be applied to each jail using the jail's name. Of course if you want a jail hostname different than the jail name, you can move the "host.hostname = your-name" inside the individual jail config between the brackets. About the securelevel, if you do not specify it, the jail default securelevel will be the same as the host. If the host has a securelevel equals to 1, the jail will have the same. You can comment it out at first, and once your jail is fully working, set it to 3 at the end.
Now let's start our jail and check it is running:
$ sudo service jail start
$ jls
JID IP Address Hostname Path
1 10.0.0.2 jail-dns /usr/jail/jail-dns
$ jls
JID IP Address Hostname Path
1 10.0.0.2 jail-dns /usr/jail/jail-dns
First things to do once your jail is live, rebuild the database mail aliases, change root password, and eventually create an additional unprivileged user. Accounts inside the jail are only jail's account. For instance Jail's root account is not the host's root account and has no power on the host. It is advised to set a different password in the jail. We can also update it before going further:
$ sudo jexec jail-dns newaliases
$ sudo jexec jail-dns passwd
$ sudo jexec jail-dns adduser
$ sudo freebsd-update -b /usr/jail/jail-dns fetch install
$ sudo jexec jail-dns passwd
$ sudo jexec jail-dns adduser
$ sudo freebsd-update -b /usr/jail/jail-dns fetch install
We need to enable the DNS cache Unbound, which is part of the base system. We also need to install the package dnscrypt-proxy. To install a package, you can either drop a shell into the jail, or install it from the host as below:
$ sudo pkg -j jail-dns install dnscrypt-proxy
Either way, we will continue from within the jail (notice the prompt going from $ to #):
$ sudo jexec jail-dns sh
# hostname
jail-dns
# hostname
jail-dns
Setting up Unbound and Dnscrypt startup parameters (you can choose the DNS server of your choice):
# vi /etc/rc.conf
# DNS
dnscrypt_proxy_enable="YES"
dnscrypt_proxy_resolver="dnscrypt.eu-dk"
dnscrypt_proxy_flags='-a 10.0.0.2:40'
local_unbound_enable="YES"
dnscrypt_proxy_enable="YES"
dnscrypt_proxy_resolver="dnscrypt.eu-dk"
dnscrypt_proxy_flags='-a 10.0.0.2:40'
local_unbound_enable="YES"
Create Unbound file unbound.conf:
# vi /etc/unbound/unbound.conf
server:
username: unbound
directory: /var/unbound
chroot: /var/unbound
pidfile: /var/run/local_unbound.pid
auto-trust-anchor-file: /var/unbound/root.key
do-not-query-localhost: no
interface: 10.0.0.2
access-control: 10.0.0.1/24 allow
include: /etc/unbound/forward.conf
username: unbound
directory: /var/unbound
chroot: /var/unbound
pidfile: /var/run/local_unbound.pid
auto-trust-anchor-file: /var/unbound/root.key
do-not-query-localhost: no
interface: 10.0.0.2
access-control: 10.0.0.1/24 allow
include: /etc/unbound/forward.conf
Create Unbound file forward.conf:
# vi /etc/unbound/forward.conf
forward-zone:
name: .
forward-addr: 10.0.0.2@40
name: .
forward-addr: 10.0.0.2@40
Modify /etc/resolv.conf to not point to the host anymore, but on our own IP address instead:
# vi /etc/resolv.conf
options edns0
nameserver 10.0.0.2
nameserver 10.0.0.2
Prevent any automatic file configuration modification by the system:
# chflags uchg /etc/unbound/forward.conf
# chflags uchg /etc/unbound/unbound.conf
# chflags uchg /etc/resolv.conf
# chflags uchg /etc/unbound/unbound.conf
# chflags uchg /etc/resolv.conf
Start Unbound and DNSCrypt, and check it is working with a randomly chosen DNS name:
# service dnscrypt-proxy start
# service local_unbound start
# host www.bsdnow.tv
www.bsdnow.tv has address 65.39.148.220
# service local_unbound start
# host www.bsdnow.tv
www.bsdnow.tv has address 65.39.148.220
Log off from the jail, modify the /etc/resolv.conf of the host to point to your jail-dns, and if working disable your host Unbound and DNSCrypt if already installed:
# CTRL + D
$ sudo vi /etc/resolv.conf
$ sudo vi /etc/resolv.conf
options edns0
nameserver 10.0.0.2
nameserver 10.0.0.2
$ host www.bsdnow.tv
www.bsdnow.tv has address 65.39.148.220
$ sudo service local_unbound stop
$ sudo service dnscrypt-proxy stop
$ host www.bsdnow.tv
www.bsdnow.tv has address 65.39.148.220
$ sudo vi /etc/rc.conf
www.bsdnow.tv has address 65.39.148.220
$ sudo service local_unbound stop
$ sudo service dnscrypt-proxy stop
$ host www.bsdnow.tv
www.bsdnow.tv has address 65.39.148.220
$ sudo vi /etc/rc.conf
# Comment all existing DNS entries related to Unbound and DNSCrypt
#dnscrypt_proxy_enable="YES"
#dnscrypt_proxy_resolver="dnscrypt.eu-dk"
#dnscrypt_proxy_flags='-a 127.0.0.1:40'
#local_unbound_enable="YES"
#dnscrypt_proxy_enable="YES"
#dnscrypt_proxy_resolver="dnscrypt.eu-dk"
#dnscrypt_proxy_flags='-a 127.0.0.1:40'
#local_unbound_enable="YES"
Eventually delete dnscrypt-proxy from the host if installed:
$ sudo pkg delete dnscrypt-proxy
$ sudo pkg autoremove
$ sudo pkg autoremove
Our first jail is operational.
3. JAIL-DHCP
___________________________________________________________
___________________________________________________________
Follow again the steps in CREATING JAILS to create jail-dhcp at /usr/jail/jail-dhcp
We now want to create a DHCP server jail with the IP address 10.0.0.3 and hostname jail-dhcp. We again need to add the jail's IP address as an alias for our LAN network interface re0:
Creating the alias:
DHCP needs full access to the network interface to operate, which is restricted by default in jails. To unlock proper access to network interfaces, we have to modify /etc/devfs.conf:
This enables us to create the jail in /etc/jail.conf:
Now let's start our jail and check it is running:
First things to do once your jail is live, rebuild the database mail aliases, change root password, eventually create an additional unprivileged user, and update the jail:
We install the package isc-dhcp42-server from the host as below:
We continue from within the jail:
Main DHCP configuration:
Finally we have to modify /etc/rc.conf to enable dhcp server at startup, and specify additional system configuration. We do not enable chroot, as we are already in jail:
Let's start our server:
Check with a client computer on your LAN that you get an IP address, gateway (10.0.0.1), and DNS server (10.0.0.2), from 10.0.0.3.
We now want to create a DHCP server jail with the IP address 10.0.0.3 and hostname jail-dhcp. We again need to add the jail's IP address as an alias for our LAN network interface re0:
$ sudo vi /etc/rc.conf
# Jails
jail_enable="YES"
ifconfig_re0_alias0="inet 10.0.0.2 netmask 255.255.255.0"
ifconfig_re0_alias1="inet 10.0.0.3 netmask 255.255.255.0"
jail_enable="YES"
ifconfig_re0_alias0="inet 10.0.0.2 netmask 255.255.255.0"
ifconfig_re0_alias1="inet 10.0.0.3 netmask 255.255.255.0"
Creating the alias:
$ sudo ifconfig re0 10.0.0.3 alias
DHCP needs full access to the network interface to operate, which is restricted by default in jails. To unlock proper access to network interfaces, we have to modify /etc/devfs.conf:
$ sudo vi /etc/devfs.conf
[devfsrules_unhide_bpf=5]
add path 'bpf*' unhide
[devfsrules_jail_dhcp=6]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add include $devfsrules_unhide_bpf
add path 'bpf*' unhide
[devfsrules_jail_dhcp=6]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add include $devfsrules_unhide_bpf
This enables us to create the jail in /etc/jail.conf:
$ sudo vi /etc/jail.conf
jail-dhcp {
ip4.addr = 10.0.0.3;
securelevel=3;
devfs_ruleset = 6;
}
ip4.addr = 10.0.0.3;
securelevel=3;
devfs_ruleset = 6;
}
Now let's start our jail and check it is running:
$ sudo service jail restart
$ jls
JID IP Address Hostname Path
3 10.0.0.2 jail-dns /usr/jail/jail-dns
4 10.0.0.3 jail-dhcp /usr/jail/jail-dhcp
$ jls
JID IP Address Hostname Path
3 10.0.0.2 jail-dns /usr/jail/jail-dns
4 10.0.0.3 jail-dhcp /usr/jail/jail-dhcp
First things to do once your jail is live, rebuild the database mail aliases, change root password, eventually create an additional unprivileged user, and update the jail:
$ sudo jexec jail-dhcp newaliases
$ sudo jexec jail-dhcp passwd
$ sudo jexec jail-dhcp adduser
$ sudo freebsd-update -b /usr/jail/jail-dhcp fetch install
$ sudo jexec jail-dhcp passwd
$ sudo jexec jail-dhcp adduser
$ sudo freebsd-update -b /usr/jail/jail-dhcp fetch install
We install the package isc-dhcp42-server from the host as below:
$ sudo pkg -j jail-dhcp install isc-dhcp42-server
We continue from within the jail:
$ sudo jexec jail-dhcp sh
# hostname
jail-dhcp
# hostname
jail-dhcp
Main DHCP configuration:
# vi /usr/local/etc/dhcpd.conf
option domain-name-servers 10.0.0.2;
subnet 10.0.0.0 netmask 255.255.255.0 {
option routers 10.0.0.1;
range 10.0.0.100 10.0.0.200;
}
subnet 10.0.0.0 netmask 255.255.255.0 {
option routers 10.0.0.1;
range 10.0.0.100 10.0.0.200;
}
Finally we have to modify /etc/rc.conf to enable dhcp server at startup, and specify additional system configuration. We do not enable chroot, as we are already in jail:
# vi /etc/rc.conf
# DHCP
dhcpd_enable="YES"
dhcpd_flags="-q"
dhcpd_conf="/usr/local/etc/dhcpd.conf"
dhcpd_ifaces="re0"
dhcpd_withumask="022"
dhcpd_chuser_enable="YES"
dhcpd_withuser="dhcpd"
dhcpd_withgroup="dhcpd"
dhcpd_chroot_enable="NO"
dhcpd_devfs_enable="YES"
dhcpd_enable="YES"
dhcpd_flags="-q"
dhcpd_conf="/usr/local/etc/dhcpd.conf"
dhcpd_ifaces="re0"
dhcpd_withumask="022"
dhcpd_chuser_enable="YES"
dhcpd_withuser="dhcpd"
dhcpd_withgroup="dhcpd"
dhcpd_chroot_enable="NO"
dhcpd_devfs_enable="YES"
Let's start our server:
# service isc-dhcpd start
# CTRL + D
$ sudo sockstat -4
dhcpd dhcpd 40216 6 udp4 10.0.0.3:67 *:*
dhcpd dhcpd 40216 20 udp4 10.0.0.3:32984 *:*
# CTRL + D
$ sudo sockstat -4
dhcpd dhcpd 40216 6 udp4 10.0.0.3:67 *:*
dhcpd dhcpd 40216 20 udp4 10.0.0.3:32984 *:*
Check with a client computer on your LAN that you get an IP address, gateway (10.0.0.1), and DNS server (10.0.0.2), from 10.0.0.3.
3. JAIL-SNORT
___________________________________________________________
___________________________________________________________
Follow again the steps in CREATING JAILS to create jail-snort at /usr/jail/jail-snort
Snort is a Network Intrusion Detection System (NIDS) analysing your network flow, looking for suspicious or known bad traffic (malware, intruder, information leak, malformed packets, etc...). Snort is only useful if you check its logs, and needs tweaking at first to eliminate false prositives pertaining to your network. There is less documentation about running Snort in jail on FreeBSD 10.x. Fortunately, once you know how to configure Snort on the host, it is not very hard to make it running inside a jail. Let's see how to proceed.
We want a Snort jail with the IP address 10.0.0.4 and hostname jail-snort:
Creating the alias:
Snort, like DHCP, needs full access to the network interface to operate:
Time to create the jail in /etc/jail.conf:
Now let's start our jail and check it is running:
Same as before:
We install the package snort:
We continue from within the jail:
We will create various folders and files needed for Snort to start:
Now, you have to create a free account at https://www.snort.org/. You will be able in your account profile to get an "oinkcode", needed to retrieve the Snort registered rules, the real Snort core ruleset. The free oinkcode gives you access to rules 30 days old, while a paid subscription (30$/year for personnal use) gives you access to the latest ruleset. Pick the free one for testing, and once operational if you are serious about intrusion detection, the paid subscription sounds reasonable. The Community ruleset (a single file) does not require an oinkcode.
Once you have your oinkcode, we can configure and use Pulledpork by uncommenting the lines below:
Then run pulledpork:
If successful, you may consider adding it to crontab to update your rules periodically (i.e : every morning at 10AM):
It's time to configure Snort main configuration file snort.conf. The full file is not included, only parts that need to be modified:
Then we will add a custom rule to be able to test snort's alert log:
Now test Snort configuration with the -T parameter:
If there is no error, start Snort in console mode to display on screen what it is doing:
On a LAN computer, do a ping to an external website like google for instance, and check your console. Then stop Snort with CTRL+C, and check the file /var/log/snort/alert:
It's working. Edit back your local.rules file and comment your ICMP rule. Now we can allow snort to start when the jail initializes:
We can start Snort normally as any other service:
When Snort starts, the active memory goes from 5-7MB to 128MB on my router, then goes down to an avereage of 20MB later. From now on you will probably have false positives, and there is a file to take care of them. Let's imagine we have the following alert we want to suppress:
... [**] [138:5:1] SENSITIVE-DATA Email Addresses [**] ... {TCP} 10.0.0.101:55471 -> ...
You can see in bold that this rule can be identified by "138:5". Now all you have to do is to edit the file threshold.conf:
Below is a full example. Do not copy/paste them directly as these may not trigger false positives on your network:
A restart is needed for the exclusions to take effect. When in doubt about the remote IP address in an alert, do a Whois on it to help you figure out if it's suspicious or expected traffic.
Snort is a Network Intrusion Detection System (NIDS) analysing your network flow, looking for suspicious or known bad traffic (malware, intruder, information leak, malformed packets, etc...). Snort is only useful if you check its logs, and needs tweaking at first to eliminate false prositives pertaining to your network. There is less documentation about running Snort in jail on FreeBSD 10.x. Fortunately, once you know how to configure Snort on the host, it is not very hard to make it running inside a jail. Let's see how to proceed.
We want a Snort jail with the IP address 10.0.0.4 and hostname jail-snort:
$ sudo vi /etc/rc.conf
# Jails
jail_enable="YES"
ifconfig_re0_alias0="inet 10.0.0.2 netmask 255.255.255.0"
ifconfig_re0_alias1="inet 10.0.0.3 netmask 255.255.255.0"
ifconfig_re0_alias2="inet 10.0.0.4 netmask 255.255.255.0"
jail_enable="YES"
ifconfig_re0_alias0="inet 10.0.0.2 netmask 255.255.255.0"
ifconfig_re0_alias1="inet 10.0.0.3 netmask 255.255.255.0"
ifconfig_re0_alias2="inet 10.0.0.4 netmask 255.255.255.0"
Creating the alias:
$ sudo ifconfig re0 10.0.0.4 alias
Snort, like DHCP, needs full access to the network interface to operate:
$ sudo vi /etc/devfs.conf
[devfsrules_jail_snort=7]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add include $devfsrules_unhide_bpf
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add include $devfsrules_unhide_bpf
Time to create the jail in /etc/jail.conf:
$ sudo vi /etc/jail.conf
jail-snort {
ip4.addr = 10.0.0.4;
securelevel=3;
devfs_ruleset = 7;
}
ip4.addr = 10.0.0.4;
securelevel=3;
devfs_ruleset = 7;
}
Now let's start our jail and check it is running:
$ sudo service jail restart
$ jls
JID IP Address Hostname Path
5 10.0.0.2 jail-dns /usr/jail/jail-dns
6 10.0.0.3 jail-dhcp /usr/jail/jail-dhcp
7 10.0.0.4 jail-snort /usr/jail/jail-snort
$ jls
JID IP Address Hostname Path
5 10.0.0.2 jail-dns /usr/jail/jail-dns
6 10.0.0.3 jail-dhcp /usr/jail/jail-dhcp
7 10.0.0.4 jail-snort /usr/jail/jail-snort
Same as before:
$ sudo jexec jail-snort newaliases
$ sudo jexec jail-snort passwd
$ sudo jexec jail-snort adduser
$ sudo freebsd-update -b /usr/jail/jail-snort fetch install
$ sudo jexec jail-snort passwd
$ sudo jexec jail-snort adduser
$ sudo freebsd-update -b /usr/jail/jail-snort fetch install
We install the package snort:
$ sudo pkg -j jail-snort install snort
We continue from within the jail:
$ sudo jexec jail-snort sh
# hostname
jail-snort
# hostname
jail-snort
We will create various folders and files needed for Snort to start:
# mkdir /usr/local/etc/snort/rules/iplists
# touch /usr/local/etc/snort/rules/iplists/default.blacklist
# touch /usr/local/etc/snort/rules/white_list.rules
# touch /usr/local/etc/snort/rules/black_list.rules
# touch /usr/local/etc/snort/rules/iplists/default.blacklist
# touch /usr/local/etc/snort/rules/white_list.rules
# touch /usr/local/etc/snort/rules/black_list.rules
Now, you have to create a free account at https://www.snort.org/. You will be able in your account profile to get an "oinkcode", needed to retrieve the Snort registered rules, the real Snort core ruleset. The free oinkcode gives you access to rules 30 days old, while a paid subscription (30$/year for personnal use) gives you access to the latest ruleset. Pick the free one for testing, and once operational if you are serious about intrusion detection, the paid subscription sounds reasonable. The Community ruleset (a single file) does not require an oinkcode.
Once you have your oinkcode, we can configure and use Pulledpork by uncommenting the lines below:
# cp /usr/local/etc/pulledpork/pulledpork.conf.sample /usr/local/etc/pulledpork/pulledpork.conf
# vi /usr/local/etc/pulledpork/pulledpork.conf
# vi /usr/local/etc/pulledpork/pulledpork.conf
# Below replace -oinkcode- with your oinkcode (i.e 455d6c4a5s666s4s478f5s66... without -)
# Registered Ruleset
rule_url=https://www.snort.org/reg-rules/|snortrules-snapshot.tar.gz|-oinkcode-
# NEW Community ruleset:
rule_url=https://s3.amazonaws.com/snort-org/www/rules/community/|community-rules.tar.gz|Community
# NEW For IP Blacklisting! Note the format is urltofile|IPBLACKLIST|-oinkcode-
# This format MUST be followed to let pulledpork know that this is a blacklist
rule_url=http://labs.snort.org/feeds/ip-filter.blf|IPBLACKLIST|-oinkcode-
# Registered Ruleset
rule_url=https://www.snort.org/reg-rules/|snortrules-snapshot.tar.gz|-oinkcode-
# NEW Community ruleset:
rule_url=https://s3.amazonaws.com/snort-org/www/rules/community/|community-rules.tar.gz|Community
# NEW For IP Blacklisting! Note the format is urltofile|IPBLACKLIST|-oinkcode-
# This format MUST be followed to let pulledpork know that this is a blacklist
rule_url=http://labs.snort.org/feeds/ip-filter.blf|IPBLACKLIST|-oinkcode-
Then run pulledpork:
# /usr/local/bin/pulledpork.pl -k -c /usr/local/etc/pulledpork/pulledpork.conf -K /usr/local/etc/snort/rules/ -o /usr/local/etc/snort/rules/
If successful, you may consider adding it to crontab to update your rules periodically (i.e : every morning at 10AM):
# crontab -e
* 10 * * * /usr/local/bin/pulledpork.pl -k -c /usr/local/etc/pulledpork/pulledpork.conf -K /usr/local/etc/snort/rules/ -o /usr/local/etc/snort/rules/
It's time to configure Snort main configuration file snort.conf. The full file is not included, only parts that need to be modified:
# vi /usr/local/etc/snort/snort.conf
ipvar HOME_NET [10.0.0.0/24]
ipvar DNS_SERVERS [10.0.0.2]
dynamicpreprocessor directory /usr/local/lib/snort_dynamicpreprocessor/
dynamicengine /usr/local/lib/snort_dynamicengine/libsf_engine.so
#include $PREPROC_RULE_PATH/sensitive-data.rules
var WHITE_LIST_PATH ./rules
var BLACK_LIST_PATH ./rules
output alert_unified2: filename snort.alert, limit 128, nostamp
output log_unified2: filename snort.log, limit 128, nostamp
# site specific rules
include $RULE_PATH/local.rules
include $RULE_PATH/community.rules
include $RULE_PATH/VRT-app-detect.rules
include $RULE_PATH/VRT-blacklist.rules
include $RULE_PATH/VRT-browser-chrome.rules
include $RULE_PATH/VRT-browser-firefox.rules
include $RULE_PATH/VRT-browser-ie.rules
include $RULE_PATH/VRT-browser-other.rules
include $RULE_PATH/VRT-browser-plugins.rules
include $RULE_PATH/VRT-browser-webkit.rules
include $RULE_PATH/VRT-content-replace.rules
include $RULE_PATH/VRT-decoder.rules
include $RULE_PATH/VRT-dos.rules
include $RULE_PATH/VRT-exploit-kit.rules
include $RULE_PATH/VRT-file-executable.rules
include $RULE_PATH/VRT-file-flash.rules
include $RULE_PATH/VRT-file-identify.rules
include $RULE_PATH/VRT-file-image.rules
include $RULE_PATH/VRT-file-java.rules
include $RULE_PATH/VRT-file-multimedia.rules
include $RULE_PATH/VRT-file-office.rules
include $RULE_PATH/VRT-file-other.rules
include $RULE_PATH/VRT-file-pdf.rules
include $RULE_PATH/VRT-indicator-compromise.rules
include $RULE_PATH/VRT-indicator-obfuscation.rules
include $RULE_PATH/VRT-indicator-scan.rules
include $RULE_PATH/VRT-indicator-shellcode.rules
include $RULE_PATH/VRT-malware-backdoor.rules
include $RULE_PATH/VRT-malware-cnc.rules
include $RULE_PATH/VRT-malware-other.rules
include $RULE_PATH/VRT-malware-tools.rules
include $RULE_PATH/VRT-netbios.rules
include $RULE_PATH/VRT-os-linux.rules
include $RULE_PATH/VRT-os-mobile.rules
include $RULE_PATH/VRT-os-other.rules
include $RULE_PATH/VRT-os-solaris.rules
include $RULE_PATH/VRT-os-windows.rules
include $RULE_PATH/VRT-policy-multimedia.rules
include $RULE_PATH/VRT-policy-other.rules
include $RULE_PATH/VRT-policy-social.rules
include $RULE_PATH/VRT-policy-spam.rules
include $RULE_PATH/VRT-preprocessor.rules
include $RULE_PATH/VRT-protocol-dns.rules
include $RULE_PATH/VRT-protocol-finger.rules
include $RULE_PATH/VRT-protocol-ftp.rules
include $RULE_PATH/VRT-protocol-icmp.rules
include $RULE_PATH/VRT-protocol-imap.rules
include $RULE_PATH/VRT-protocol-nntp.rules
include $RULE_PATH/VRT-protocol-pop.rules
include $RULE_PATH/VRT-protocol-rpc.rules
include $RULE_PATH/VRT-protocol-scada.rules
include $RULE_PATH/VRT-protocol-services.rules
include $RULE_PATH/VRT-protocol-snmp.rules
include $RULE_PATH/VRT-protocol-telnet.rules
include $RULE_PATH/VRT-protocol-tftp.rules
include $RULE_PATH/VRT-protocol-voip.rules
include $RULE_PATH/VRT-pua-adware.rules
include $RULE_PATH/VRT-pua-other.rules
include $RULE_PATH/VRT-pua-p2p.rules
include $RULE_PATH/VRT-pua-toolbars.rules
include $RULE_PATH/VRT-scada.rules
include $RULE_PATH/VRT-sensitive-data.rules
include $RULE_PATH/VRT-server-apache.rules
include $RULE_PATH/VRT-server-iis.rules
include $RULE_PATH/VRT-server-mail.rules
include $RULE_PATH/VRT-server-mssql.rules
include $RULE_PATH/VRT-server-mysql.rules
include $RULE_PATH/VRT-server-oracle.rules
include $RULE_PATH/VRT-server-other.rules
include $RULE_PATH/VRT-server-samba.rules
include $RULE_PATH/VRT-server-webapp.rules
include $RULE_PATH/VRT-sql.rules
include $RULE_PATH/VRT-x11.rules
ipvar DNS_SERVERS [10.0.0.2]
dynamicpreprocessor directory /usr/local/lib/snort_dynamicpreprocessor/
dynamicengine /usr/local/lib/snort_dynamicengine/libsf_engine.so
#include $PREPROC_RULE_PATH/sensitive-data.rules
var WHITE_LIST_PATH ./rules
var BLACK_LIST_PATH ./rules
output alert_unified2: filename snort.alert, limit 128, nostamp
output log_unified2: filename snort.log, limit 128, nostamp
# site specific rules
include $RULE_PATH/local.rules
include $RULE_PATH/community.rules
include $RULE_PATH/VRT-app-detect.rules
include $RULE_PATH/VRT-blacklist.rules
include $RULE_PATH/VRT-browser-chrome.rules
include $RULE_PATH/VRT-browser-firefox.rules
include $RULE_PATH/VRT-browser-ie.rules
include $RULE_PATH/VRT-browser-other.rules
include $RULE_PATH/VRT-browser-plugins.rules
include $RULE_PATH/VRT-browser-webkit.rules
include $RULE_PATH/VRT-content-replace.rules
include $RULE_PATH/VRT-decoder.rules
include $RULE_PATH/VRT-dos.rules
include $RULE_PATH/VRT-exploit-kit.rules
include $RULE_PATH/VRT-file-executable.rules
include $RULE_PATH/VRT-file-flash.rules
include $RULE_PATH/VRT-file-identify.rules
include $RULE_PATH/VRT-file-image.rules
include $RULE_PATH/VRT-file-java.rules
include $RULE_PATH/VRT-file-multimedia.rules
include $RULE_PATH/VRT-file-office.rules
include $RULE_PATH/VRT-file-other.rules
include $RULE_PATH/VRT-file-pdf.rules
include $RULE_PATH/VRT-indicator-compromise.rules
include $RULE_PATH/VRT-indicator-obfuscation.rules
include $RULE_PATH/VRT-indicator-scan.rules
include $RULE_PATH/VRT-indicator-shellcode.rules
include $RULE_PATH/VRT-malware-backdoor.rules
include $RULE_PATH/VRT-malware-cnc.rules
include $RULE_PATH/VRT-malware-other.rules
include $RULE_PATH/VRT-malware-tools.rules
include $RULE_PATH/VRT-netbios.rules
include $RULE_PATH/VRT-os-linux.rules
include $RULE_PATH/VRT-os-mobile.rules
include $RULE_PATH/VRT-os-other.rules
include $RULE_PATH/VRT-os-solaris.rules
include $RULE_PATH/VRT-os-windows.rules
include $RULE_PATH/VRT-policy-multimedia.rules
include $RULE_PATH/VRT-policy-other.rules
include $RULE_PATH/VRT-policy-social.rules
include $RULE_PATH/VRT-policy-spam.rules
include $RULE_PATH/VRT-preprocessor.rules
include $RULE_PATH/VRT-protocol-dns.rules
include $RULE_PATH/VRT-protocol-finger.rules
include $RULE_PATH/VRT-protocol-ftp.rules
include $RULE_PATH/VRT-protocol-icmp.rules
include $RULE_PATH/VRT-protocol-imap.rules
include $RULE_PATH/VRT-protocol-nntp.rules
include $RULE_PATH/VRT-protocol-pop.rules
include $RULE_PATH/VRT-protocol-rpc.rules
include $RULE_PATH/VRT-protocol-scada.rules
include $RULE_PATH/VRT-protocol-services.rules
include $RULE_PATH/VRT-protocol-snmp.rules
include $RULE_PATH/VRT-protocol-telnet.rules
include $RULE_PATH/VRT-protocol-tftp.rules
include $RULE_PATH/VRT-protocol-voip.rules
include $RULE_PATH/VRT-pua-adware.rules
include $RULE_PATH/VRT-pua-other.rules
include $RULE_PATH/VRT-pua-p2p.rules
include $RULE_PATH/VRT-pua-toolbars.rules
include $RULE_PATH/VRT-scada.rules
include $RULE_PATH/VRT-sensitive-data.rules
include $RULE_PATH/VRT-server-apache.rules
include $RULE_PATH/VRT-server-iis.rules
include $RULE_PATH/VRT-server-mail.rules
include $RULE_PATH/VRT-server-mssql.rules
include $RULE_PATH/VRT-server-mysql.rules
include $RULE_PATH/VRT-server-oracle.rules
include $RULE_PATH/VRT-server-other.rules
include $RULE_PATH/VRT-server-samba.rules
include $RULE_PATH/VRT-server-webapp.rules
include $RULE_PATH/VRT-sql.rules
include $RULE_PATH/VRT-x11.rules
Then we will add a custom rule to be able to test snort's alert log:
# vi /usr/local/etc/snort/local.rules
# Test rule : any ping will trigger it
alert icmp any any -> any any (msg:"ICMP test"; sid:10000001;)
alert icmp any any -> any any (msg:"ICMP test"; sid:10000001;)
Now test Snort configuration with the -T parameter:
# snort -A console -q -c /usr/local/etc/snort/snort.conf -i re0 -T
If there is no error, start Snort in console mode to display on screen what it is doing:
# snort -A console -q -c /usr/local/etc/snort/snort.conf -i re0
On a LAN computer, do a ping to an external website like google for instance, and check your console. Then stop Snort with CTRL+C, and check the file /var/log/snort/alert:
# vi /var/log/snort/alert
11/28-19:30:57.065893 [**] [1:10000001:0] ICMP test [**] [Priority: 0] {ICMP} 10.0.0.53 -> 64.233.182.94
11/28-19:30:58.066761 [**] [1:10000001:0] ICMP test [**] [Priority: 0] {ICMP} 10.0.0.53 -> 64.233.182.94
11/28-19:30:58.066761 [**] [1:10000001:0] ICMP test [**] [Priority: 0] {ICMP} 10.0.0.53 -> 64.233.182.94
It's working. Edit back your local.rules file and comment your ICMP rule. Now we can allow snort to start when the jail initializes:
# vi /etc/rc.conf
# Snort
snort_enable="YES"
snort_flags="-A fast -b -D"
snort_enable="YES"
snort_flags="-A fast -b -D"
We can start Snort normally as any other service:
# service snort start
When Snort starts, the active memory goes from 5-7MB to 128MB on my router, then goes down to an avereage of 20MB later. From now on you will probably have false positives, and there is a file to take care of them. Let's imagine we have the following alert we want to suppress:
... [**] [138:5:1] SENSITIVE-DATA Email Addresses [**] ... {TCP} 10.0.0.101:55471 -> ...
You can see in bold that this rule can be identified by "138:5". Now all you have to do is to edit the file threshold.conf:
# vi /usr/local/etc/snort/threshold.conf
suppress gen_id 138, sig_id 5, track by_src, ip 10.0.0.0/24
Below is a full example. Do not copy/paste them directly as these may not trigger false positives on your network:
### ID 119 ###
# ----------------------------------------------------------
# Suppress Oversized request URI directory
suppress gen_id 119, sig_id 15, track by_src, ip 10.0.0.0/24
# Suppress Long Header
suppress gen_id 119, sig_id 19, track by_src, ip 10.0.0.0/24
# Suppress Unknown Header
suppress gen_id 119, sig_id 31, track by_src, ip 10.0.0.0/24
# Suppress Unescaped Space in HTTP URI
suppress gen_id 119, sig_id 33, track by_src, ip 10.0.0.0/24
### ID 120 ###
# ----------------------------------------------------------
# Suppress No Content Length or Transfer Encoding in HTTP Response
suppress gen_id 120, sig_id 3, track by_dst, ip 10.0.0.0/24
### ID 128 ###
# ----------------------------------------------------------
# Suppress (spp_ssh) Protocol mismatch
suppress gen_id 128, sig_id 4, track by_src, ip 10.0.0.0/24
### ID 129 ###
# ----------------------------------------------------------
# Suppress Bad Segment
suppress gen_id 129, sig_id 5, track by_src, ip 10.0.0.0/24
# Suppress Consecutive TCP small segments exceeding threshold
suppress gen_id 129, sig_id 12, track by_src, ip 10.0.0.0/24
# Suppress Reset outside window
suppress gen_id 129, sig_id 15, track by_src, ip 10.0.0.0/24
# Suppress TCP session without 3-way handshake
suppress gen_id 129, sig_id 20, track by_src, ip 10.0.0.0/24
# ----------------------------------------------------------
# Suppress Oversized request URI directory
suppress gen_id 119, sig_id 15, track by_src, ip 10.0.0.0/24
# Suppress Long Header
suppress gen_id 119, sig_id 19, track by_src, ip 10.0.0.0/24
# Suppress Unknown Header
suppress gen_id 119, sig_id 31, track by_src, ip 10.0.0.0/24
# Suppress Unescaped Space in HTTP URI
suppress gen_id 119, sig_id 33, track by_src, ip 10.0.0.0/24
### ID 120 ###
# ----------------------------------------------------------
# Suppress No Content Length or Transfer Encoding in HTTP Response
suppress gen_id 120, sig_id 3, track by_dst, ip 10.0.0.0/24
### ID 128 ###
# ----------------------------------------------------------
# Suppress (spp_ssh) Protocol mismatch
suppress gen_id 128, sig_id 4, track by_src, ip 10.0.0.0/24
### ID 129 ###
# ----------------------------------------------------------
# Suppress Bad Segment
suppress gen_id 129, sig_id 5, track by_src, ip 10.0.0.0/24
# Suppress Consecutive TCP small segments exceeding threshold
suppress gen_id 129, sig_id 12, track by_src, ip 10.0.0.0/24
# Suppress Reset outside window
suppress gen_id 129, sig_id 15, track by_src, ip 10.0.0.0/24
# Suppress TCP session without 3-way handshake
suppress gen_id 129, sig_id 20, track by_src, ip 10.0.0.0/24
A restart is needed for the exclusions to take effect. When in doubt about the remote IP address in an alert, do a Whois on it to help you figure out if it's suspicious or expected traffic.
CONCLUSION :
___________________________________________________________
___________________________________________________________
Snort is cool stuff, above all when you can use professionnal rules for free (30 days old though). It is located at a very privileged network point where all traffic flows both ways, and is
therefore in a unique position to catch malicious data. It's free, easier to setup with tools like pulledpork, and can be greatly improved with email notification,
and with a web based interface.
Jailing most important network related services, provides strong additional security layers! However it also comes with trade-off, with an host and three jails, we have four systems to keep updated (that means running freebsd-update four times). Also, when upgrading for instance from FreeBSD 10.1 to 10.x, once the host is upgraded, every jail will have to be upgraded from sources as well. Then, jails are very rectricted by default, but by granting more accesses to the network interfaces as we did for DHCP and Snort, we increase the risks. Indeed if a jail with such right is hacked, there is no need for the intruder to break out of the jail, he can just sniff out all of your traffic. Lastly, if a jail is well restricted, but is allowed to access everything in the firewall rules, the security is greatly diminished. Security is a whole process, with user restrictions, folder and file rights, OS hardening, updates, firewall rules, NIDS, etc... Jails are only a piece of it, they should not be underestimated, neither should they be overestimated.
See you for my next article! :-)
Jailing most important network related services, provides strong additional security layers! However it also comes with trade-off, with an host and three jails, we have four systems to keep updated (that means running freebsd-update four times). Also, when upgrading for instance from FreeBSD 10.1 to 10.x, once the host is upgraded, every jail will have to be upgraded from sources as well. Then, jails are very rectricted by default, but by granting more accesses to the network interfaces as we did for DHCP and Snort, we increase the risks. Indeed if a jail with such right is hacked, there is no need for the intruder to break out of the jail, he can just sniff out all of your traffic. Lastly, if a jail is well restricted, but is allowed to access everything in the firewall rules, the security is greatly diminished. Security is a whole process, with user restrictions, folder and file rights, OS hardening, updates, firewall rules, NIDS, etc... Jails are only a piece of it, they should not be underestimated, neither should they be overestimated.
See you for my next article! :-)
LINKS
___________________________________________________________
___________________________________________________________
http://www.freebsd.org
https://www.snort.org
http://dan.langille.org
https://github.com
https://whois.domaintools.com
http://www.cyberciti.biz
https://www.snort.org
http://dan.langille.org
https://github.com
https://whois.domaintools.com
http://www.cyberciti.biz
Follow me @gkweb76