介绍
当运行可供公众使用的Web服务器时,在使您的内容可访问和建立安全配置之间取得平衡可能变得困难。 有许多不同的领域,应该仔细审查。 其中之一是过程隔离和可见性。
所谓firejail一个项目旨在通过提供利用内核命名空间来执行分离策略的轻量级安全机制容器在这方面提供帮助。 这使得chroot环境非常轻量级。
在本指南中,我们将向您展示如何使用firejail来隔离自己chroot环境中的进程。 为了演示这个例子,我们将设置两个chroot环境,一个使用Nginx Web服务器提供WordPress,另一个使用MySQL数据库来处理站点数据。 这两个实例将有自己的文件系统和安装,并且将通过桥接网络设备进行通信。
先决条件和目标
在本指南中,我们将使用64位Ubuntu 14.04服务器作为我们的基本安装。 这将使我们能够利用预建firejail
封装,将使我们能够轻松地创建的chroot环境。
要获取安装一个良好的基础,确保你已经完成了对Ubuntu 14.04的初始服务器设置在这里。
我们将在我们的主机系统上设置两个chroot环境。 这些实际上是Debian的稳定的环境,选择了,因为Debian的环境更为良好的测试选择debootstrap
,我们将要使用的工具。
我们的主机将配置一个公共IP地址,并作为桥接网络的网关,我们将设置与jails通信。 被监控环境将仅配置为使用桥接接口,并且只能通过主机上的NAT规则访问更宽的互联网。
我们将要配置的三个环境将具有以下属性:
环境 | 公网IP地址 | 网桥IP地址 |
---|---|---|
主办 | 192.0.2.1 | 10.10.20.1 |
网络服务器 | (没有) | 10.10.20.10 |
数据库服务器 | (没有) | 10.10.20.20 |
请注意,上面红色的值应该替换为主机服务器的公共IP地址。 然而,网桥IP地址应该按原样使用,因为我们将在整个指南中设置此接口和这些地址。
在本指南中,所有的命令将root用户来执行。
下载并配置主机计算机组件
要开始,我们需要下载一些我们将使用到我们的服务器的工具。
首先,我们需要下载.deb
软件包的firejail程序。 找到最新.deb
的上包名称的网站下载页和替换URL的文件名部分的下方与该版本。 以下网址是包的直接下载链接:
cd ~
wget http://downloads.sourceforge.net/project/firejail/firejail/firejail_0.9.8.1_1_amd64.deb
当该文件已被下载,使用安装它dpkg
:
dpkg -i firejail*
firejail程序安装后,我们需要从Ubuntu的默认存储库中获取一些额外的软件包。 具体而言,我们需要debootstrap
工具,这将有助于我们创造我们的chroot文件系统和bridge-utils
,这将使我们能够创造我们的监狱将用来通信的网络桥接口:
apt-get update
apt-get install debootstrap bridge-utils
配置网桥接口
在我们开始使用实际的jail之前,我们将设置桥接网络接口。
我们可以创建一个新的接口brctl
那是一部分命令bridge-utils
软件包。 我们的桥将被称为br0
:
brctl addbr br0
接下来,我们需要使接口向上。 随着激活接口,我们分配一个CIDR网络范围。 我们的主机服务器将有10.10.20.1这个接口上的地址:
ifconfig br0 10.10.20.1/24
随着接口的启动和运行,我们需要告诉内核允许在我们的接口之间的IP转发或路由。 我们可以通过键入以下内容为此会话启用此功能:
echo "1" > /proc/sys/net/ipv4/ip_forward
现在,我们需要建立一个iptables
规则将允许发往端口80我们的主机服务器上的流量路由到我们将我们的监狱之一内安装Web服务器。 我们的Web服务器将有10.10.20.10我们的桥接接口的IP地址:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to 10.10.20.10:80
这会在“nat”表中的“PREROUTING”链的底部添加一条规则。 当往端口80命中一个TCP包,将流量重定向到端口80上的10.10.20.10
通过网络地址转换。
我们还需要设置一系列规则,允许我们的数据库和Web服务器查询Internet,以便他们可以从WordPress更新组件。 我们将通过增加一个伪装的规则,将允许我们开始br0
接口路由通信成功通过我们的主机:
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
然后,我们可以通过调整FORWARD链中的规则来锁定我们的接口之间的通信。
首先,我们应该反映我们的成立,使我们可以明确地允许从80端口到我们以前的NAT规则br0
网络:
iptables -A FORWARD -i eth0 -o br0 -p tcp -m tcp --dport 80 -j ACCEPT
我们还希望允许与我们已建立的连接相关的入站流量:
iptables -A FORWARD -i eth0 -o br0 -m state --state RELATED,ESTABLISHED -j ACCEPT
我们要允许始发上的所有流量转发br0
为了让我们的监狱彼此和外界通信接口:
iptables -A FORWARD -i br0 -j ACCEPT
最后,我们将放弃所有其他的转发连接,以便转发只允许从出站连接br0
网络。 这项政策的例外情况已在上述规则中确定。
iptables -P FORWARD DROP
现在我们的主机系统配置了桥接接口,它将用于与被监控的环境进行通信。
创建Chroot目录结构
现在,我们准备创建我们的chroot目录结构。
正如我们之前所说,我们的Web服务器和我们的数据库服务器将在完全独立的文件系统中操作。 我们将一个名为目录中保留这两个文件系统/jails
。 现在创建该目录:
mkdir /jails
移动到刚刚创建的目录:
cd /jails
现在,我们需要创建将被我们的监控操作系统使用的文件结构。 要做到这一点,我们将使用debootstrap
工具。 此实用程序用于在现有文件系统中引导Debian环境。 它通过从Debian仓库中拉下包并将它们“安装”到正确的位置来实现。
虽然debootstrap
可以用来引导Ubuntu的环境中,我们将选择稳定的Debian装置代替。 由于该工具是为与Debian一起工作而创建的,因此这些环境是这个工具最好的测试。
我们将把我们的数据库环境安装到一个名为“db”的目录中。 要创建适当的目录结构,并下载并安装必需的软件包,请键入:
debootstrap --arch=amd64 stable db
现在,我们有我们的下建立文件系统/jails/db
目录下,我们可以使用rsync
的结构复制到我们的网络服务器可以使用另一个目录。 新目录将被称为“www”。 请确保在后面的命令中注意斜杠(/)。 这将在第一目录中的内容复制到第二个,而不是复制目录本身:
rsync -azvh db/ www
现在,我们有,我们可以用我们使用两种chroot目录结构firejail
程序。
使用Firejail设置WordPress数据库
现在,我们有我们的目录结构,我们可以用firejail
我们中创建一个chroot环境/jails/db
目录结构。
要创建chroot环境并在其中启动bash会话,我们只需要指定chroot根目录的位置和我们要用于会话的主机名:
firejail --chroot=/jails/db --name=db
Parent pid 17390, child pid 17391
Interface IP Mask Status
lo 127.0.0.1 255.0.0.0 UP
eth0 192.0.2.1 255.255.255.0 UP
eth1 10.128.1.228 255.255.0.0 UP
br0 10.10.20.1 255.255.255.0 UP
Child process initialized
[root@db ~]$
该命令将输出父pid,子pid和在此jail会话中配置的接口(我们尚未限制或配置此处的接口)。 然后,它会把你放进一个命令提示符在你的监狱环境中。
我们需要做的第一件事是更新我们的包数据库,并在chroot环境中安装MySQL服务器。 你可以通过键入:
apt-get update
apt-get install mysql-server
在更新过程中,您应该看到正在检查Debian存储库。 这是因为我们的chroot环境是Debian安装。
在安装过程中,将要求您选择并确认根MySQL帐户的密码。
当安装完成后,我们应该通过键入以下内容生成MySQL数据目录结构:
mysql_install_db
接下来,使用包含的脚本锁定某些不安全的默认值:
mysql_secure_installation
系统将要求您提供安装期间设置的根MySQL密码。 然后,系统会询问您是否要更改密码。 如果您对选择感到满意,请选择“否”。 对于其余提示,只需按ENTER键选择默认选项。
创建WordPress数据库和用户
接下来,我们要为WordPress设置一个单独的数据库。 使用MySQL root帐户登录MySQL服务器。 在提示时输入您为该用户选择的密码:
mysql -u root -p
你将被放入MySQL提示符。 创建一个新的数据库供WordPress使用:
CREATE DATABASE wordpress;
接下来,我们将创建一个用户从Web服务器监狱使用此数据库。 Web服务器将有10.10.20.10桥接口上的IP地址,所以我们需要用该地址该用户相关联。 为此用户分配安全密码。 然后,我们将授予此用户处理我们创建的数据库的能力:
CREATE USER 'wordpressuser'@'10.10.20.10' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpressuser'@'10.10.20.10';
现在,我们只需刷新特权表并退出:
FLUSH PRIVILEGES;
exit
修改MySQL设置绑定到网桥地址
接下来,我们需要修改MySQL配置文件。 现在使用编辑器打开它:
nano /etc/mysql/my.conf
此文件分为几个部分。 找到以这样开头的部分:
[mysqld]
你应该看到一个名为指令bind-address
被设置为127.0.0.1
目前。 我们想启动我们的MySQL实例侦听桥接接口。 该监狱的该接口上的地址为10.10.20.20,所以我们应该修改它看起来像这样:
bind-address = 10.10.20.20
保存并在完成后关闭文件。
现在,我们可以停止当前运行的MySQL实例并退出此jail:
service mysql stop
exit
使用Firejail设置WordPress Web服务器
现在我们的数据库已配置,我们可以移动到将用于Web服务器的jail。 现在使用firejail在此jail环境中启动会话:
firejail --chroot=/jail/www --name=www
我们需要做的第一件事是更新我们的本地包数据库,并安装Nginx Web服务器和PHP组件。 这些是处理动态请求并连接到MySQL数据库所必需的:
apt-get update
apt-get install nginx php5-fpm php5-mysql
配置PHP
我们将从编辑PHP处理器的配置文件开始,以禁用可能是安全问题的功能:
nano /etc/php5/fpm/php.ini
查找cgi.fix_pathinfo
文件中的指令。 它将被注释掉并设置为“1”。 我们需要取消注释,并将其更改为“0”:
cgi.fix_pathinfo=0
保存并在完成后关闭文件。
配置Nginx
现在我们需要设置Nginx来正确地提供WordPress文件。 这包括在建立一个新的文档根目录/var/www/html
,设置的server_name
,以我们的主机系统的公网IP地址,并配置PHP处理。
打开默认的Nginx配置文件:
vim /etc/nginx/sites-available/default
我们需要做出的更改的摘要如下:
- 取消对
listen 80
指示明确指定的端口号。 - 更改的值
root
以指向/var/www/html
,我们将保持我们的WordPress文件的位置。 - 修改
index
参数来寻找一个index.php
先于其他索引文件的文件。 - 更改的值
server_name
以指向主机服务器的IP地址或域名 - 调整为最后的值
try_files
指令来请求传递到index.php
文件时,他们没有发现作为文件或目录。 这是位于内侧location /
块。 - 取消注释所有错误页面指令以允许错误页面。
- 取消对
location ~ \.php$
块中,包括fastcgi_split_path_info
指令,fastcgi_pass
插座线,fastgci_index
和include fastcgi_params
指令,并添加try_files
试图给出的要求,否则返回404指令。
完成上述更改后,该文件应类似于下面的内容(为了简洁,已删除了注释):
server {
listen 80;
root /var/www/html;
index index.php index.html index.htm;
server_name 192.0.2.1;
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location /doc/ {
alias /usr/share/doc/;
autoindex on;
allow 127.0.0.1;
allow ::1;
deny all;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/www;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}
您可以粘贴这里显示的所有内容,如果这更容易。 您只需要调整server_name
指令引用您的主机系统的公网IP地址或域名。
保存并在完成后关闭文件。
下载和配置WordPress文件
现在Nginx被配置为正确地提供文件,我们可以下载,配置和安装它们。
首先切换到root用户的主目录并下载最新的WordPress tarball:
cd ~
wget http://wordpress.org/latest.tar.gz
解压压缩包中的内容,创建一个名为~/wordpress
:
tar xzvf latest.tar.gz
将示例配置文件复制到将要检查的有效配置文件名:
cd ~/wordpress
cp wp-config-sample.php wp-config.php
现在,在文本编辑器中打开新的配置文件:
nano wp-config.php
在内部,我们需要更改与数据库存储相关联的值。 我们需要在配置选项中填写我们在MySQL数据库中做出的选择的详细信息。
除了密码字段(您应该早已修改为您自己的值)之外,您可以使用下面显示的值:
/** The name of the database for WordPress */
define('DB_NAME', 'wordpress');
/** MySQL database username */
define('DB_USER', 'wordpressuser');
/** MySQL database password */
define('DB_PASSWORD', 'password');
/** MySQL hostname */
define('DB_HOST', '10.10.20.20');
完成后,保存并关闭文件。
接下来,我们需要创建/var/www/html
是我们在Nginx的配置文件作为文档根引用的目录。 然后我们将所有的WordPress文件复制到该目录:
mkdir -p /var/www/html
cp -r ~/wordpress/* /var/www/html
现在我们可以将文件的所有权授予Web用户:
cd /var/www/html
chown -R www-data:www-data /var/www/html/*
您的Web服务器监控现在已完全配置。 我们可以通过键入以下命令正常关闭我们的Web服务器和PHP进程:
service nginx stop
service php5-fpm stop
现在,退出jail以返回主机服务器会话:
exit
启动Jails
我们现在有我们的jail完全配置。 我们可以使用我们的网桥接口单独启动它们。
首先,我们将启动数据库服务器,因为它更简单。 我们需要像以前一样指定chroot根位置。 这一次,我们也将使用--net
参数指定桥接口。 我们将结合使用与--ip
参数指定的确切地址,我们想给这所监狱( 10.10.20.20
,如果从我们的配置还记得)。
我们也将通过--private
标志安装新/tmp
, /root
,和/home/user
目录中的监狱中。 然后,我们需要指定我们想要在jail中启动的进程,并将其放到后台,并以结尾“&”。
我们应该开始的过程是MySQL服务器的过程,也是一个sleep inf
过程。 这将保持jail无限期运行,而不是在以前的进程完成时退出。 总的来说,命令看起来像这样:
firejail --chroot=/jails/db --private --net=br0 --ip=10.10.20.20 \
"/etc/init.d/mysql start; \
sleep inf" &
jail将启动,指定的进程将开始顺序执行。 您可以通过使用该看到这个过程的结果--list
的选项firejail
:
firejail --list
21913:root:firejail --chroot=/jails/db --private --net=br0 --ip=10.10.20.20 /etc/init.d/mysql
21916:root:bash -c /etc/init.d/mysql start; sleep inf
21970:root:/bin/sh /usr/bin/mysqld_safe
22322:syslog:/usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/
22323:root:logger -t mysqld -p daemon.error
22409:root:sleep inf
如您所见,进程树可从我们的主机系统中获得。 因为我们可以看到sleep inf
运行,并且看到了MySQL的过程仍有上涨,我们可以看到,监狱已完成引导。
对于Web服务器监控,需要进行相同的基本设置。 我们将需要指定的chroot根位置,桥接接口与被分配的实际IP地址( 10.10.20.10
)和--private
标志。
在流程列表方面,我们有很多额外的考虑。 首先,将/var/log
在监狱目录在每次启动时动态创建的。 因此,我们的Nginx文件中的日志指令指向不存在的位置。 我们可以在尝试启动Nginx之前创建这些位置。
此外,Nginx进程依赖于系统记录器。 我们将启动该rsyslog
前Nginx的过程也是如此。 启动Nginx后,我们还需要记住启动我们的PHP处理器,这将在需要时将请求传递到数据库jail。 同样,我们想结束sleep inf
,使监狱坚持过去那里的服务已经启动点。
最后,我们的命令启动我们的Web服务器监狱将如下所示:
firejail --chroot=/jails/www --private --net=br0 --ip=10.10.20.10 \
"mkdir -p /var/log/nginx; \
touch /var/log/nginx/error.log; \
touch /var/log/nginx/access.log; \
/etc/init.d/rsyslog start; \
/etc/init.d/nginx start; \
/etc/init.d/php5-fpm start; \
sleep inf" &
这可能需要为Web服务器监狱片刻开机,保持与检查firejail --list
,看看是否进程达到的sleep inf
状态。
现在,如果您在Web浏览器中转到主机服务器的公共IP地址或域名,您应该看到WordPress初始安装页面:
http://host_server_domain_or_IP
填写适当的值,并在准备好后点击底部的“安装WordPress”。 您将需要使用新创建的管理帐户登录。 之后,您将被带到WordPress仪表板:
如果一切都按预期工作,这意味着安装成功。 我们现在可以努力使此配置可重复和持久。
制作Firejail实例服务
现在我们已经完成配置并运行了,我们希望确保在重新启动后可以轻松地返回这里。 为此,我们有一些领域需要我们解决。 这些包括:
- 配置host-to-jail和jail-to-jail网络在启动时出现。
- 使我们的
iptables
变化执着。 - 配置我们的jail在主机服务器启动时自动启动。
我们可以立即开始这三个。
在引导时配置Jails的网络
我们将重点关注的第一件事是使桥接网络正常运行。 这是必要的,我们担心我们的防火墙规则之前,在我们开始监狱环境。
我们需要配置实际的桥接连接。 要获得此连接和运行在系统启动,我们需要修改/etc/network/interfaces
文件。 立即打开此文件:
nano /etc/network/interfaces
在里面,你会看到一些部分,决定哪些接口在启动时启动,以及描述每个接口的其他行。 通过附加开始br0
网络到第二年底auto
行开始,我们将在引导时定义的接口:
auto eth0 eth1 br0
接下来,我们需要设置一个定义接口的部分。 由于这是一个网桥接口,并且不像常规网桥一样组合两个网络,我们将手动定义我们的接口,这意味着我们将给出用于配置网络的确切命令。
从节标题开始:
iface br0 inet manual
根据这一点,我们将使用pre-up
, up
, post-down
,并down
指令来定义应该在每个阶段中运行的命令。 对于pre-up
和up
的命令,我们要建立的桥梁,然后使界面了我们手动先前做的方式相同。 在$IFACE
将被动态替换br0
当命令运行,所以你不应该在这里进行修改:
iface br0 inet manual
pre-up brctl addbr $IFACE
up ifconfig $IFACE 10.10.20.1/24
对于post-down
和down
命令,我们只是想扭转这些命令。 我们将接口退回,然后删除桥:
iface br0 inet manual
pre-up brctl addbr $IFACE
up ifconfig $IFACE 10.10.20.1/24
down ifconfig $IFACE down
post-down brctl delbr $IFACE
我们br0
接口现在定义,我们已经将其设置为开机时自动启动。 保存并在完成后关闭文件。
设置IPTables以允许限制转发到Jails
接下来,我们需要使用我们之前添加的规则来设置iptables。 幸运的是,这是与的帮助下简单iptables-persistent
包。
键入以下命令安装软件包:
apt-get install iptables-persistent
在安装过程中将询问您是否要保存当前的IPv4和IPv6规则集。 在这些提示选择Yes,自动保存当前的规则集。 这些将在启动时自动重新应用。
如果您需要调整在引导时应用的规则,请进行您要使用的更改,然后键入:
/etc/init.d/iptables-persistent save
将更新当前规则集。
我们的iptables规则现在设置为在服务器引导时恢复。 但是,还有一个我们还没有解决的问题:我们需要确保我们的内核允许转发。
之前,我们也有同样的“1”变成了一个文件/proc
虚拟文件系统,以使这种能力。 为了使这一变化在下次启动时自动发生,编辑sysctl.conf
文件:
nano /etc/sysctl.conf
取消注释以下行:
net.ipv4.ip_forward=1
保存并在完成后关闭文件。
创建一个Upstart脚本来启动WordPress Jails
要配置我们的jails在启动时启动,我们需要创建一个upstart脚本。 我们将调用我们的脚本firejail_wp.conf
。
打开这个名称在一个文件中/etc/init
在文本编辑器的目录:
nano /etc/init/firejail_wp.conf
在内部,我们首先填写这项服务的简要说明:
description "WordPress jail"
接下来,我们配置此服务必须为true的情况才能自动启动。 我们要确保文件系统是可用的,我们还需要确保br0
网络已经建立。 如果br0
网络下来,我们两个firejail命令就会失败。
要做到这一点,我们将使用start on
指令和local-filesystems
和net-device-up
符来构建我们的出发条件。 我们还将配置我们的脚本,以便在机器进入重新引导或关闭模式(由不是1-5的任何运行级别指示)时停止:
description "WordPress jail"
start on (local-filesystems and net-device-up IFACE=br0)
stop on runlevel [!12345]
最后,我们需要建立启动此服务时将执行的实际命令。 由于服务运行的方式,我们将把firejail命令放在外部脚本中,所以我们只需要在这里引用脚本名称:
description "WordPress jail"
start on (local-filesystems and net-device-up IFACE=br0)
stop on runlevel [!12345]
exec /startjails.sh
完成后,保存并关闭文件。
现在,我们需要创建我们刚刚引用的实际脚本文件。 使用文本编辑器在此位置打开文件:
nano /startjails.sh
因为这是一个bash脚本,从标准shebang调用bash开始:
#!/bin/bash
接下来,我们将添加我们的两个firejail命令,一个小修改。 由于未知的原因,在由upstart启动时,在受监视的环境中运行Nginx初始化脚本有一个问题。 当通过任何其他方法调用时,此问题不存在。
为了解决这个问题,我们将简单地调用Nginx可执行文件,而不是内部的Jailed init脚本。 除此之外,命令与我们之前使用的命令完全一样:
#!/bin/bash
firejail --chroot=/jails/db --private --net=br0 --ip=10.10.20.20 "/etc/init.d/mysql start; sleep inf" &
firejail --chroot=/jails/www --private --net=br0 --ip=10.10.20.10 "mkdir -p /var/log/nginx; touch /var/log/nginx/error.log; touch /var/log/nginx/access.log; /etc/init.d/rsyslog start; /usr/sbin/nginx; /etc/init.d/php5-fpm start; sleep inf" &
还需要一个命令来确保这是一个正在进行的服务,而不是在jails启动后立即结束的任务。 我们需要添加sleep inf
作为脚本中的最后一行。 这将允许upstart正确地管理服务:
#!/bin/bash
firejail --chroot=/jails/db --private --net=br0 --ip=10.10.20.20 "/etc/init.d/mysql start; sleep inf" &
firejail --chroot=/jails/www --private --net=br0 --ip=10.10.20.10 "mkdir -p /var/log/nginx; touch /var/log/nginx/error.log; touch /var/log/nginx/access.log; /etc/init.d/rsyslog start; /usr/sbin/nginx; /etc/init.d/php5-fpm start; sleep inf" &
sleep inf
完成后,保存并关闭文件。
现在,我们只需要使这个文件可执行,以便upstart脚本可以启动它:
chmod +x /startjails.sh
通过这一步,WordPress监禁环境被完全配置为在启动时启动。
您可以重新启动主机服务器以尝试:
shutdown -r now
如果一切都已正确配置,您将能够在一切有时间启动后访问您的WordPress网站。
结论
本指南只是一个例子,你可以使用一个工具,如firejail的许多事情之一。 虽然有很多其他方法为您的服务器设置隔离组件,firejail是一个伟大的解决方案,因为它的灵活性和能力用最少的资源处理这么多不同的情况。