学习FreeBSD 从入门到跑路:使用 Qjail 管理 Jail
本文介绍了在FreeBSD系统中使用Qjail工具管理Jail环境的方法。主要内容包括:1. Qjail的安装与配置,包括网络接口设置和基础系统部署;2. Jail的基本操作,如创建、启动、停止、备份和删除Jail;3. 系统更新方法,包括基础系统、Ports和源代码的更新;4. 高级配置选项,如SysVIPC启用和SSH服务设置;5. 实践示例,展示了如何在Jail中部署PostgreSQL数据
学习FreeBSD 从入门到跑路里面的一章:使用 Qjail 管理 Jail 。发现推荐使用了Qjail,于是略作了解,发现还是挺不错的。
学到这么几点:
1 ezjail 在 2015 年更新至 3.4.2 后未再进行关键更新,其 ports 更新依赖 portsnap,现已废弃。所以要用Qjail
2 Qjail 下载base.txz 要求文件版本与宿主机一致
3 可以使用国内镜像,如:
# 从镜像服务器下载 FreeBSD 基础系统文件
# fetch https://mirrors.ustc.edu.cn/freebsd/release/amd64/15.0-RELEASE/base.txz
# 使用 qjail 安装基础系统到指定 jail
# qjail install base.txz
4 使用gitup更新源代码和源代码树。gitup可以自行安装。
# 更新源代码树
# gitup src
# 更新 Ports 树
# gitup ports
11.3 使用 Qjail 管理 Jail
文档地址:11.3 使用 Qjail 管理 Jail | FreeBSD 中文社区
Qjail 是用于部署 Jail 环境的工具,源自 ezjail 3.1。
常见的 Jail 管理工具包括 ezjail、Qjail 和 iocage。
ezjail 在 2015 年更新至 3.4.2 后未再进行关键更新,其 ports 更新依赖 portsnap,现已废弃。
iocage 依赖 ZFS 文件系统,因此使用 UFS 文件系统的用户无法使用。
Qjail 不存在这些方面的限制。
ezjail 不支持 Jail 的 vnet 功能,而 iocage 和 Qjail 支持该功能。
ezjail 和 Qjail 使用 sh 编写,iocage 使用 Python 编写。
下文中部署的 Jail 在概念上结构如下图:
预留 jail 的 ip
在 /etc/rc.conf 文件中添加如下配置
cloned_interfaces="lo1" # 克隆出 lo1,尽量和宿主机网络配置分开。①
ifconfig_lo1_alias0="inet 192.168.1.0-9" # 此处示例选择 `192.168.1.0/24` 网段,旨在为 jail 创建一个与宿主机实际网络分离的独立网段,请根据您的实际网络环境调整 IP 地址范围
注意
① 如果要生成多个接口,也应在同一行中以空格分隔描述,而不是另外创建多行,例如 cloned_interfaces="lo1 lo2" 。分行书写时,只有第一行会生效。
运行以下命令重启所有网络接口:
# service netif restart
lo1 将获得 10 个 IP 地址,其中 1-9 号 IP 将用于分配给各个 jail。
安装 Qjail 工具
-
使用 pkg 安装:
# pkg install qjail
-
或者使用 Ports 安装:
# cd /usr/ports/sysutils/qjail/
# make install clean
设置系统服务开机启动 qjail:
# sysrc qjail_enable=YES
部署 Qjail 使用的目录结构
在使用 Qjail 之前,首先需要部署 Qjail 所使用的目录结构,可通过以下两种方式完成:
附录:从官方镜像站自动下载
# qjail install
此时 Qjail 会从 FreeBSD 官网下载 base.txz 文件,示例输出如下:
# qjail install
resolving server address: ftp.freebsd.org:80
requesting http://ftp.freebsd.org/pub/FreeBSD/releases/amd64/amd64/15.0-RELEASE/base.txz
remote size / mtime: 195363380 / 1652346155
...
附录:从境内镜像站下载
由于境内网络访问限制,也可以使用镜像站手动下载,以中国科学技术大学镜像为例(注意下载文件版本号,Qjail 要求文件版本与宿主机一致,此处示例为 FreeBSD amd64 15.0)。
# 从镜像服务器下载 FreeBSD 基础系统文件
# fetch https://mirrors.ustc.edu.cn/freebsd/release/amd64/15.0-RELEASE/base.txz
# 使用 qjail 安装基础系统到指定 jail
# qjail install base.txz
部署好 Qjail 的目录结构后 /usr/jails 目录下会自动生成 sharedfs template archive flavors 四个目录:
-
sharedfs 包含一份只读的操作系统可执行文件库,通过 nullfs 挂载,在各个 jail 之间共享,以节省存储空间
-
template 包含操作系统的配置文件,将被复制到每个 jail 的基本文件系统中
-
archive 保存 jail archive 命令产生的存档文件
-
flavors 包含系统风格(flavors)和用户创建的自定义风格,其实就是自己定义的配置文件等
部署 jail
# qjail create -n lo1 -4 192.168.1.1 jail1
-
-n指定使用 lo1 作为网络接口 -
-4指定 ipv4 地址
生成 jail1 后,/usr/jails/ 目录下会创建 jail1 目录(/usr/jails/jail1/)用于保存对应文件。
可以在前述的 flavors 目录中创建自定义配置文件,以便在部署新的 jail 时自动复制。例如,新建 /usr/jails/flavors/default/usr/local/etc/pkg/repos/FreeBSD.conf,则之后创建的 jail 会自动复制该文件,即
# qjail create -n lo1 -4 192.168.1.2 jail2
建立 jail2 后,自动建立 /usr/jails/jail2/usr/local/etc/pkg/repos/FreeBSD.conf,即修改了之后所有 jail 的默认 pkg 镜像。但对应 jail1 并没有生成这个文件,因为生成 jail1 时,还没有在 flavors 目录中写入相应文件。
Qjail 基本用法
-
列出 Qjail 管理的 jail
# qjail list
-
启用 jail
# qjail start # 启动所有 jail
# qjail start jail1 # 启动 jail1
-
停止 jail
# qjail stop # 停止所有 jail
# qjail stop jail1 # 停止 jail1
-
重启 jail
# qjail restart # 重启所有 jail
# qjail restart jail1 # 重启 jail1
-
进入 jail 控制台
# qjail console jail1 # 进入 jail1 控制台
进入 jail 控制台后,将以 jail 中的 root 账户身份操作(无需输入密码)。由于 jail 可能开启对外服务,为安全起见,建议设置 root 账户密码。
-
备份 jail
# qjail archive -A # 备份所有 jail
# qjail archive jail1 # 备份 jail1
-
从备份中恢复 jail
# qjail restore jail1 # 从备份中恢复 jail1
-
删除 jail
# qjail delete jail1 # 删除 jail1
# qjail delete -A # 删除所有 jail
更新 jail
下面更新 jail 的部分不针对单个 jail,而是针对每个 jail,因为这些文件利用 nullfs 共享一份。
更新 jail 中的基本系统
即上面提到的 sharedfs 中的文件
# qjail update -b
更新 ports
这里有 -p(小写)、-P(大写)两个选项,-p(小写)使用 portsnap 更新 jail 的 ports tree。-P(大写)使用宿主机的 ports 更新 jail 的 ports。若主机已有 ports,则建议使用 -P(大写),避免重复下载 ports。
复制
# qjail update -P # 这里注意要大写
更新系统源代码
# qjail update -S # 大写
更新过程
请先自行安装配置 gitup。
开始更新:
# 获取并安装 FreeBSD 系统更新
# freebsd-update fetch install
# 更新源代码树
# gitup src
# 更新 Ports 树
# gitup ports
# 停止所有 qjail jail
# qjail stop
# 更新 qjail 基础系统
# qjail update -b
# 更新 qjail 源代码
# qjail update -S
# 更新 qjail Ports
# qjail update -P
# 启动所有 qjail jail
# qjail start
jail 设置
Qjail 可以用 qjail config 命令对每个 jail 另作设置,运行 qjail config 前须先停用指定的 jail。
qjail config 命令选项较多,这里列出几个常用的,更多的请参考手册页
qjail -- Utility for deployment of jail environments
-h
# qjail config -h jail1
快速开启 jail1 的 ssh 服务,新建一个 wheel 组用户,用户名和密码同 jail 名,首次用这个用户登录要求修改密码。也可以在登录 jail 控制台后,自行配置 sshd 服务。
-m -M
# qjail config -m jail1
设置 jail1 需手动启动(manual 状态),qjail_enable="YES" 写入 /etc/rc.conf 后在系统启动时会自动启动各个 jail,设为手动启动后则不会在系统启动时自动启动相应的 jail,须用 qjail start jailname 启动。
对应小写的 -m 选项,有大写的 -M 选项,作用为关闭手动启动状态,即清除 manual 状态,可以在系统启动时自动启用 jail。Qjail 中有大量类似的选项,小写字母的选项启用某个功能,大写字母的选项关闭对应功能。如果下文中同时出现小写和大写的选项就不再过多作出说明。
-r -R
# qjail config -r jail1
将 jail1 设为不允许启动(norun 状态),相当于禁用该 jail。
-y -Y
# qjail config -y jail1
启用该 jail 的 SysV IPC,在 jail 中安装 PostgreSQL 时,需要打开这个选项,PostgreSQL 运行基于这个功能。
网络设定
注意
有的教程里会教你用
qjail config -k jailname打开 raw_sockets 功能来打开外网访问的能力,其实这是个误区。raw_sockets 只是像 ping 一类的工具需要使用而已,并不是说网络访问一定要打开 raw_sockets。而且在 jail 中打开 raw_sockets 本身有安全风险,这是 jail 环境默认的一种安全设计。所以除非你一定要在 jail 中用 ping 之类的工具,否则无论是用什么方式构建的 jail 都不建议打开 raw_sockets 功能。
此时的 jail 还不能连接网络,因为 jail 绑定在 lo1 网络接口上,lo1 并不能直接访问外网,接下来通过 pf 设定网络,其中 em0 为外网接口
-
在
/etc/pf.conf中写入
nat pass on em0 inet from lo1 to any -> em0 # 使 jail 可以访问网络,从 lo1 接口发出的连接通过 nat 转发到 em0
rdr pass on em0 inet proto tcp from any to em0 port 22 -> 192.168.1.1 port 22 # 使宿主机外可以访问指定 jail,端口重定向,将连接到 em0 上 22 端口上的 tcp 连接重定向到 192.168.1.1 地址(即 jail1)的 22 端口上
-
启动防火墙
# 启用防火墙服务 pf 开机自启动
# service pf enable
# 启动防火墙服务 pf
# service pf start
此时,绑定在 lo1 上的 jail 可以访问宿主机外网络,宿主机外网络可以通过宿主机 22 号端口连接 jail1 的 22 号端口。
示例:部署 PostgreSQL jail
假设已经如上文所述预留 jail ip,并成功运行 qjail install 命令。
这里以 PostgreSQL 15 为例,其它版本也适用。
宿主机中操作
在 jail 中创建并启用 PostgreSQL:
# 创建名为 postgres 的 jail,绑定到 lo1 接口,IPv4 地址为 192.168.1.3
# qjail create -n lo1 -4 192.168.1.3 postgres
# 配置 postgres jail,启用 SysV IPC
# qjail config -y postgres
# 启动 postgres jail
# qjail start postgres
编辑 /etc/pf.conf 文件:
nat pass on em0 inet from lo1 to any ->em0 # 上文已作说明
rdr pass on em0 inet proto tcp from any to em0 port 5432 -> 192.168.1.3 port 5432 # 不建议写下此句,作用为使宿主机外可以访问 jail 中的 postgresql,此处应考虑安全和实际需要开启端口转发,不建议直接向外提供 postgresql 连接
启动防火墙服务 pf:
# service pf start
进入名为 postgres 的 jail 的控制台:
# qjail console postgres
jail 控制台中的操作
下面命令皆在 jail 控制台下运行,pkg 安装与否使用镜像请自行决定,若使用镜像可以在 jail 控制台中如同宿主机般进行设置,请参考相关文章。
-
使用 pkg 安装:
# pkg install postgresql15-server
-
或者使用 Ports 安装
# cd /usr/ports/databases/postgresql15-server/
# make install clean
配置 PostgreSQL:
# service postgresql enable # 设置 PostgreSQL 服务开机自启动
# mkdir -p -m 0700 /var/db/postgres/data15 # 注意版本号
# chown postgres:postgres /var/db/postgres/data15 # 这个目录应属于 postgres 用户
# su postgres # 这里切换到 postgres 用户,注意下面提示符的变化
$ initdb -A scram-sha-256 -E UTF8 -W -D /var/db/postgres/data15
$ exit # 回到 jail root 用户,注意提示符变化
# service postgresql start # 立刻启动 PostgreSQL 服务
此处使用 initdb 而非安装时提示的 /usr/local/etc/rc.d/postgresql initdb,目的是避免在设置数据库密码时反复修改 pg_hba.conf 文件。下面对各选项进行简要说明:
-
-A为本地用户指定在pg_hba.conf中使用的默认认证方法 -
-E选择模板数据库的编码。 -
-W让 initdb 提示要求为数据库超级用户给予一个口令 -
-D指定数据库集簇应该存放的目录
至此 PostgreSQL 服务已经可以运行。
如果在上述过程中未使用 qjail config -y postgres 命令开启 SysV IPC,可能会出现如下错误:
初始化数据库集簇时的错误
启动 PostgreSQL 时的错误
此时在宿主机控制台下执行 qjail config -y postgres 即可修正错误,具体如下:
复制
# 停止 postgres jail
# qjail stop postgres
# 配置 postgres jail,启用 SysV IPC
# qjail config -y postgres
# 启动 postgres jail
# qjail start postgres
再次进入 jail 的控制台就可以正常初始化数据库集簇和运行 PostgreSQL 服务了。
实践
预留 jail 的 ip
在 /etc/rc.conf 文件中添加如下配置
cloned_interfaces="qjail1" # 克隆出 lo1,尽量和宿主机网络配置分开。①
ifconfig_qjail1_alias0="inet 192.168.100.0-255" # 此处示例选择 `192.168.1.0/24` 网段,旨在为 jail 创建一个与宿主机实际网络分离的独立网段,请根据您的实际网络环境调整 IP 地址范围
手册上写的不对,应该这样
# add qjail
cloned_interfaces="igb0" # 克隆出 lo1,尽量和宿主机网络配置分开。①
ifconfig_igb0_alias0="inet 192.168.100.1 netmask 255.255.255.0" # 此处示例选择 `192.168.100.0/24` 网段
#defaultrouter="192.168.1.1"
重启网络接口
# service netif restart
对我的系统来说,重启网络之后,路由丢了,我又重新加上的
sudo route add default 192.168.1.1
安装qjail
sudo pkg install qjail
安装好后提示
Message from qjail-5.5_1:
--
Use the qjail utility to deploy small or large numbers of jails quickly.
First issue "rehash" command to enable the qjail command (if using csh).
Then issue
"man qjail-intro" To read the qjail introduction.
"man qjail" For qjail usage details.
"man qjail-drive-traffic For example of driving public traffic to jails.
"man qjail-vnet-howto" For example of creating vnet jails.
"man qjail-ipv6-testing" For example of testing jails with ipv6 addresses.
设置开机启动
sudo sysrc qjail_enable=YES
部署目录结构
从官方源直接部署
qjail install
如果速度慢,可以从镜像站点下载base.txz然后部署
qjail install base.txz
会自动部署到/usr/jails目录。
部署好 Qjail 的目录结构后 /usr/jails 目录下会自动生成 sharedfs template archive flavors 四个目录:
-
sharedfs 包含一份只读的操作系统可执行文件库,通过 nullfs 挂载,在各个 jail 之间共享,以节省存储空间
-
template 包含操作系统的配置文件,将被复制到每个 jail 的基本文件系统中
-
archive 保存 jail archive 命令产生的存档文件
-
flavors 包含系统风格(flavors)和用户创建的自定义风格,其实就是自己定义的配置文件等
部署 jail
# qjail create -n lo1 -4 192.168.1.1 jail1
-
-n指定使用 lo1 作为网络接口 -
-4指定 ipv4 地址
我是用的这句
qjail create -4 192.168.100.5 jail5
秒创建完成:Successfully created jail5
Qjail 基本用法
-
列出 Qjail 管理的 jail
复制
# qjail list
-
启用 jail
复制
# qjail start # 启动所有 jail
# qjail start jail1 # 启动 jail1
-
停止 jail
复制
# qjail stop # 停止所有 jail
# qjail stop jail1 # 停止 jail1
-
重启 jail
复制
# qjail restart # 重启所有 jail
# qjail restart jail1 # 重启 jail1
-
进入 jail 控制台
复制
# qjail console jail1 # 进入 jail1 控制台
进入 jail 控制台后,将以 jail 中的 root 账户身份操作(无需输入密码)。由于 jail 可能开启对外服务,为安全起见,建议设置 root 账户密码。
-
备份 jail
复制
# qjail archive -A # 备份所有 jail
# qjail archive jail1 # 备份 jail1
-
从备份中恢复 jail
复制
# qjail restore jail1 # 从备份中恢复 jail1
-
删除 jail
复制
# qjail delete jail1 # 删除 jail1
# qjail delete -A # 删除所有 jail
实践,创建,列表,启动
skywalk@fb5:/usr/jails $ sudo qcreate -4 192.168.100.5 jail5
Password:
Successfully created jail5
skywalk@fb5:/usr/jails $ sudo qlist
STATUS JID NIC IP Jailname
------ ---- ------ --------------- --------------------------------------------
DS N/A igb0 192.168.100.5 jail5
skywalk@fb5:/usr/jails $ sudo qjail start
Jail successfully started jail5
skywalk@fb5:/usr/jails $ sudo qjail list
STATUS JID NIC IP Jailname
------ ---- ------ --------------- --------------------------------------------
DR 25 igb0 192.168.100.5 jail5
skywalk@fb5:/usr/jails $ sudo qjail console
Syntax: qjail console [-z zone] [-u userid] [-c cmd] jailname
-z [Apply to this zone] = :zone name:
-c [execute this command in jail] = :command to execute:
-u [user to login as] = :username:
[Jailname of running jail to login to]
skywalk@fb5:/usr/jails $ sudo qjail console jail5
FreeBSD 14.3-RELEASE (GENERIC) releng/14.3-n271432-8c9ce319fef7
Welcome to FreeBSD!
Release Notes, Errata: https://www.FreeBSD.org/releases/
Security Advisories: https://www.FreeBSD.org/security/
FreeBSD Handbook: https://www.FreeBSD.org/handbook/
FreeBSD FAQ: https://www.FreeBSD.org/faq/
Questions List: https://www.FreeBSD.org/lists/questions/
FreeBSD Forums: https://forums.FreeBSD.org/
Documents installed with the system are in the /usr/local/share/doc/freebsd/
directory, or can be installed later with: pkg install en-freebsd-doc
For other languages, replace "en" with a language code like de or fr.
Show the version of FreeBSD installed: freebsd-version ; uname -a
Please include that output and any error messages when posting questions.
Introduction to manual pages: man man
FreeBSD directory layout: man hier
To change this login announcement, see motd(5).
root@jail5:~ # uname -a
FreeBSD jail5 14.3-RELEASE FreeBSD 14.3-RELEASE releng/14.3-n271432-8c9ce319fef7 GENERIC amd64
更新
更新 jail 中的基本系统
即上面提到的 sharedfs 中的文件,注意,更新的时候需要停止jail
# qjail update -b
更新 ports
这里有 -p(小写)、-P(大写)两个选项,-p(小写)使用 portsnap 更新 jail 的 ports tree。-P(大写)使用宿主机的 ports 更新 jail 的 ports。若主机已有 ports,则建议使用 -P(大写),避免重复下载 ports。
需要先自己更新宿主机的ports系统。
# qjail update -P # 这里注意要大写
更新系统源代码
复制
# qjail update -S # 大写
一体化命令,先更新宿主机:
sudo freebsd-update fetch install
sudo pkg install gitup
sudo gitup release
sudo gitup ports
再停掉jail并更新
# 停止所有 qjail jail
# qjail stop
# 更新 qjail 基础系统
# qjail update -b
# 更新 qjail 源代码
# qjail update -S
# 更新 qjail Ports
# qjail update -P
# 启动所有 qjail jail
# qjail start
但是我测试的时候,gitup ports没成功过,报错:
sudo gitup ports
# Scanning local repository...
# Host: git.freebsd.org
# Port: 443
# Repository Path: /ports.git
# Target Directory: /usr/ports
# Want: c71c571a6d22f2792581f9be7838c32d73c47409
# Branch: main
gitup: fetch_pack: malformed pack data:
: Inappropriate file type or format
jial设置
Qjail 中有大量的选项,小写字母的选项启用某个功能,大写字母的选项关闭对应功能。
快速启动ssh
qjail config -h jail1
快速开启 jail1 的 ssh 服务,新建一个 wheel 组用户,用户名和密码同 jail 名,首次用这个用户登录要求修改密码。也可以在登录 jail 控制台后,自行配置 sshd 服务。
sudo qjail config -h jail5
我试了一下,没搞定,账户登录没搞定。
ssh jail5@192.168.100.5
不过我的jail5 启动后,就自动开了sshd服务了。
启用该 jail 的 SysV IPC
# qjail config -y jail1
启用该 jail 的 SysV IPC,在 jail 中安装 PostgreSQL 时,需要打开这个选项,PostgreSQL 运行基于这个功能。
sudo qjail config -y jail5
jail中安装数据库例子
jail 控制台中的操作
下面命令皆在 jail 控制台下运行,pkg 安装与否使用镜像请自行决定,若使用镜像可以在 jail 控制台中如同宿主机般进行设置,请参考相关文章。
-
使用 pkg 安装:
复制
# pkg install postgresql15-server
-
或者使用 Ports 安装
复制
# cd /usr/ports/databases/postgresql15-server/
# make install clean
配置 PostgreSQL:
复制
# service postgresql enable # 设置 PostgreSQL 服务开机自启动
# mkdir -p -m 0700 /var/db/postgres/data15 # 注意版本号
# chown postgres:postgres /var/db/postgres/data15 # 这个目录应属于 postgres 用户
# su postgres # 这里切换到 postgres 用户,注意下面提示符的变化
$ initdb -A scram-sha-256 -E UTF8 -W -D /var/db/postgres/data15
$ exit # 回到 jail root 用户,注意提示符变化
# service postgresql start # 立刻启动 PostgreSQL 服务
此处使用 initdb 而非安装时提示的 /usr/local/etc/rc.d/postgresql initdb,目的是避免在设置数据库密码时反复修改 pg_hba.conf 文件。下面对各选项进行简要说明:
-
-A为本地用户指定在pg_hba.conf中使用的默认认证方法 -
-E选择模板数据库的编码。 -
-W让 initdb 提示要求为数据库超级用户给予一个口令 -
-D指定数据库集簇应该存放的目录
至此 PostgreSQL 服务已经可以运行。
如果在上述过程中未使用 qjail config -y postgres 命令开启 SysV IPC,可能会出现如下错误:
初始化数据库集簇时的错误
启动 PostgreSQL 时的错误
此时在宿主机控制台下执行 qjail config -y postgres 即可修正错误,具体如下:
复制
# 停止 postgres jail
# qjail stop postgres
# 配置 postgres jail,启用 SysV IPC
# qjail config -y postgres
# 启动 postgres jail
# qjail start postgres
再次进入 jail 的控制台就可以正常初始化数据库集簇和运行 PostgreSQL 服务了。
总结
发现自己对jail和网络的理解和认识还是有些欠缺,网络配置那块应该还是可以继续改进的,原来文档里面的配置应该是对的,抽空再去做实验。
做完这个实验后,发现原来的jial虚拟机192.168.1.12ping不通了,也无法ssh过来了....
个人猜测是配置qjail的网络时,把1.12这台机器的弄不通了....试试怎么改回去。
更多推荐
所有评论(0)