FreeBSD NAT

备注

我使用 ThinkPad X220笔记本 为局域网内主机临时提供NAT网络转换,方便局域网主机联网更新系统

  • wlan0 是外网接口(无线网络)

  • em0 是内网接口,连接内部局域网

本文以快速实践完成为主

内核转发

  • 开启内核转发功能,既允许数据包在不同网卡间流动:

激活IP forwarding
# 添加内核IP转发配置
echo 'net.inet.ip.forwarding=1' | sudo tee -a /etc/sysctl.conf

# 刷新
sysctl -f /etc/sysctl.conf

# 如果临时生效,可以使用一条命令: sysctl net.inet.ip.forwarding=1

设置pf防火墙规则

针对pf网关直连网卡

pf 提供了一个非常简单的方法,能够直接将其连接局域网的网段IP地址NAT出去:

  • 最简单的PF规则 /etc/pf.conf

设置NAT的 最简单 /etc/pf.conf
# 定义网卡变量
ext_if = "wlan0"
int_if = "em0"

# 定义局域网网段
localnet = $int_if:network

# 执行 NAT 转换
nat on $ext_if from $localnet to any -> ($ext_if)

# 默认规则:允许所有流量通过(作为网关的基础配置)
pass all

或者更为复杂一些,效果相同

设置NAT的 /etc/pf.conf
ext_if = "wifibox0"
int_if = "ue0"
int_addr = "192.168.7.101"
int_network = "192.168.7.0/24"
set skip on lo

scrub in all

# NAT traffic from internal network to external network through external interface
nat on $ext_if from $int_if:network to any -> ($ext_if)

### Filters ###
# Permit keep-state packets for UDP and TCP on external interfaces
pass out quick on $ext_if proto udp all keep state
pass out quick on $ext_if proto tcp all modulate state flags S/SA

# Permit any packets from internal network to this host
pass in quick on $int_if inet from $int_network to $int_addr

# Permit established sessions from internal network to any (incl. the Internet)
pass in quick on $int_if inet from $int_network to any keep state
# If you want to limit the number of sessions per NAT, nodes per NAT (simultaneously), and sessions per source IP
#pass in quick on $int_if inet from $int_network to any keep state (max 30000, source-track rule, max-src-nodes 100, max-src-states 500 )

# Permit and log all packets from clients in private network through NAT
pass in quick log on $int_if all

# Pass any other packets
pass in all
pass out all

备注

localnet = $int_if:network 配置巧妙地将内网接口 em0network 定义为本地局域网网段,也就是说,当 em0 配置了 192.168.6.100/24 ,就会自动获得 192.168.6.0/24 网段作为 network 变量。此时上文配置的 localnet 就是 192.168.6.0/24 能够被NAT出internet

警告

上述通过pf主机的内网网卡接口获得的 network 网段只针对直接连接的局域网网段,如果有更多内网网段(如 192.168.7.0/24 ,则因为不在范围内,NAT规则会直接跳过

扩大局域网网段NAT

在企业内部,通常内网有很多网段。例如,我在homelab中,就分配了2个网段 192.168.6.0/24192.168.7.0/24 ,要通过pf实现NAT,需要使用 Table 来扩大来源的 nat 规则:

使用Table扩大NAT内网网段
# 定义网卡变量
ext_if = "wlan0"
int_if = "em0"

# 扩大内网网段定义
table <my_internal_nets> { 192.168.7.0/24, 192.168.6.0/24 }
# 执行 NAT 转换: 针对表里的所有网段
nat on $ext_if from <my_internal_nets> to any -> ($ext_if)

# 默认规则:允许所有流量通过(作为网关的基础配置)
pass all

此时 table <my_internal_nets> 能够非常灵活地定义多个内网网段,这样就能够为局域网多个网段提供NAT

启用PF使NAT生效

  • /etc/rc.conf 中启用PF:

设置 /etc/rc.conf 启用PF
pf_enable="YES"
pf_rules="/etc/pf.conf"
pflog_enable="YES"
  • 启动PF服务

启动
service pf start
# 如果 PF 已经在运行,使用以下命令重新加载规则:
# pfctl -f /etc/pf.conf

参考