FreeBSD Jail 使用 ipfw 进行 NAT 与端口转发

Pader2020年1月18日 发表于 系统与硬件 Jail VNET NAT VNET Jail FreeBSD NAT

虽然 VNET 很好,但是在虚拟机中使用时你可能没那么多IP,而你即希望每个 Jail 都有独立的网络栈,又想要他们可以访问外网,此时 NAT 就派上用场了。

通过 NAT 将 Jail 置于子网段中,与主网段隔绝,通过 NAT 和端口转发来处理,对外一致以主机IP端口来访问,对内又有独立的网络栈,另外这种形式在虚拟机中使用不需要网卡开启混杂模式、MAC伪装等要求,兼容性,稳定性都更好。

为 Jail 创建网段

首先 Jail 需要创建 epair 网卡接口,并启用 vnet 指定 epairNb 接口,不同的是此时的 epair0a 不需要加到主网卡的桥接中去,而是作为独立的接口存在,然后为 epair0a 与 epair0b 都添加上虚拟网段的 IP。

Jail 配置示例:

exec.clean;
exec.system_user = "root";
exec.jail_user = "root";
exec.start += "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
mount.devfs;
enforce_statfs = "2";
path="/usr/jails/${name}";

wise {
	jid = 100;
	host.hostname = "wise.bsd";
	exec.consolelog = "/var/log/jail_test_console.log";
	allow.raw_sockets;
	# 注意以下 vnet 配置
	vnet;
        vnet.interface = "epair${jid}b";
        exec.prestart += "ifconfig epair${jid} create inet 172.16.0.1/24 name vnet_${name}";
        exec.poststop += "ifconfig vnet_${name} destroy";
	devfs_ruleset = "4";
}

Jail 中的 /etc/rc.conf 示例:

ifconfig_epair100b="inet 172.16.0.2 netmask 255.255.255.0"
defaultrouter="172.16.0.1"

此时虚拟网段就创建好了,接下来借助 ipfw 来配置 NAT。

ipfw NAT 配置

启用 ipfw 及内核 NAT,如果不使用内核 NAT 则使用用户层的 natd,详情参考:https://www.freebsd.org/doc/handbook/firewalls-ipfw.html

/etc/rc.conf

firewall_enable="YES"
firewall_type="/etc/ipfw.rules"
firewall_nat_enable="YES"

如果 ipfw 想使用默认通过模式(默认是拒绝,需要在 /boot/loader.conf 中加入以下内容并重启)

net.inet.ip.fw.default_to_accept=1

在 /etc/ipfw.rules 规则中加入:

其中 nat 数字 99 是自定义数字,代表一个 NAT 配置表,以下配置指定 172.16.0.0/24 的网段与外网互通,并且将主机的 8080 端口转发到 Jail 的 172.16.0.2:8080,主机的 8443 转发到 172.16.0.6:8443

add 02000 nat 99 ip4 from 172.16.0.0/24 to any out via em0
add 02001 nat 99 ip4 from any to any in via em0
nat 99 config if em0 same_ports redirect_port tcp 172.16.0.2:80 8080 redirect_port tcp 172.16.0.6:8443 8443

启动 ipfw 与 jail

service ipfw start
service jail start wise

在 Jail 里安装一个 nginx 并启动后访问主机的 8080 端口试试吧。

多 Jail 网段共存

对于多 Jail 网段共存有几种形式,一是各 Jail 互相独立不能互访,二是 Jail 分成一组一组,每组之内的可以互访,三是所有 Jail 在一组里。二和三形式类似,这里介绍一下互相独立和可以互访的实现形式。

    1. 互相独立

和之前的形式类似,但此时将掩码设为 30,在 30 的情况下,每个网段有 4 个 IP 可用,如 172.16.0.0/30,则有 0,1,2,3 可用,下一个段是  4,5,6,7,再下一个段是 8,9,10,11,此时为每个 Jail 的 epairNa 指定第二个IP,Jail 内为网卡指定为第三个IP,掩码皆为 30 即可。

如主机 epair0a inet 172.16.0.1/30, Jail 内 epair0b inet 172.16.0.2/30,网关设为 172.16.0.1 即可,第二个 Jail 主机 epair1a inet 172.16.0.5/30,Jail 内 epair1b inet 172.16.0.6/30,网关设为 172.16.0.5 即可。

    2. 一组互访

互访形式要稍微复杂点,但总体的思路是建立一个桥接接口如 bridge0,将主机上的 epairNa 接口全加入此桥接接口的成员组中,然后 bridge0 接口添加一个IP做为总体的网关(Jail内网关全指定为此 bridge0 的 IP),掩码根据所需,一般设为 24,其它类似。

实现示例,在主机 /etc/rc.conf 中加入,注意不需要将真实网卡添加到成员。

# Gateway for jails
cloned_interfaces="bridge0"
ifconfig_bridge0="inet 172.16.0.1/24"

此时 jail 原设定 exec 部分在建立 epair 接口后需将接口添加至 bridge0 成员中,修改部分如下:

        exec.prestart += "ifconfig epair${jid} create inet 172.16.0.2/24 name vnet_${name}";
        exec.prestart += "ifconfig bridge0 addm vnet_${name}";

Jail 内 /etc/rc.conf 配置:

ifconfig_epair100b="inet 172.16.0.3 netmask 255.255.255.0"
defaultrouter="172.16.0.1"

此时多个 Jail 就形成一个局域网可以互访了,要设置多个局域网只需建立多个桥接接口,在掩码,网段网关上隔开即可。

评论 共有 0 条评论

暂无评论,快发表你的评论吧。