+ -
当前位置:首页 → 问答吧 → Pf文档翻译(第二部分, 请帮助找出错误、校对)

Pf文档翻译(第二部分, 请帮助找出错误、校对)

时间:2003-12-26

来源:互联网

PF: Network Address Translation

Introduction

Network Address Translation ( NAT 网络地址转换) 是将整个网络映射成单个IP地址的方法。当你从ISP那里分配的IP地址少于你的网络所需求的IP地址时,你可以使用NAT。关于NAT的具体说明请参考:RFC 1631。

NAT允许你使用那些保留的有优势的IP地址段,具体说明请参考:RFC 1918。

基本上,你的内部网将使用一个或多个这些保留的IP 地址段。它们是:

10.0.0.0/8 (10.0.0.0 - 10.255.255.255)
172.16.0.0/12 (172.16.0.0 - 172.31.255.255)
192.168.0.0/16 (192.168.0.0 - 192.168.255.255)

OpenBSD系统使用NAT最少需要二块网卡适配器, 一块连接Internet, 另一块连接你的内部网。NAT从内部网转换请求,所有这样将出现在你的OpenBSD NAT系统里。

How NAT Works

当内部网的一个客户端连接到Internet上的机器时,它发出IP数据包通向那台机器。这些数据包中包含了通向目的机器的所有地址信息。NAT是这些有关信息中其中的一片。

? Source IP address (for example, 192.168.1.35)
? Source TCP or UDP port (for example, 2132)

当数据包通过NAT gateway时, 它们会被标示成看起来是NAT gateway自己发出的数据包。The NAT gateway将这些改变记录在一个状态信息表, 这样它可以: a、在返回的数据包反转这些改变;b、确定返回的数据包能通过the firewall并且不会被blocked。例如,下面这些改变将会执行:

? Source IP(源IP地址): replaced with the external address of the gateway (for example, 24.5.0.5) (将会被the gateway的IP地址替换)
? Source port(源端口号): replaced with a randomly chosen, unused port on the gateway (for example, 53136)(将会被the gateway里的一个未使用的随机端口号替换)

不管是内部网的机器还是Internet上的机器都不会知道这些转发设置。对于内部网的机器来说,The NAT system只是一个简单的Internet gateway。对于Internet上的主机来说, 所接收的数据包都是从the NAT system上发送出来的;它完全没有意识到内部网里机器的存在。
当Internet上的主机响应内部网里机器发去的数据包时,这些数据包的目地地址是NAT gateway的对外IP地址(24.5.0.5)传输端口号是53136。The NAT gateway将查找状态信息表决定回应的数据包来匹配一个已确定的连接。唯一的基于IP/port联合的匹配将告诉PF这些数据包属于内部网中192.168.1.35主机发起的连接。PF将对内部网发出的数据包进行相应的改变并对转发回应的数据包。

相似的操作也会发生在没有源端口号的ICMP数据包传输上。

Enabling NAT
在OpenBSD gateway上启用NAT, 除了将它进入活动的PF外, 你还必须启动IP forwarding:

# sysctl -w net.inet.ip.forwarding=1
# sysctl -w net.inet6.ip6.forwarding=1 (if using IPv6)

要想使用这些改变保存长久, 就将下面这些行加进/etc/sysctl.conf

net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1

在默认安装里,这些行会出现但都被注释掉了(前面放置了一个# )。去掉#, 保存文件。当重启机器后IP forwarding会被启动。

Configuring NAT
在/etc/pf.conf里, NAT规则的基本格式是这样的:

nat on extif [af] from src_addr [port src_port] to \
dst_addr [port dst_port] -> ext_addr

extif
外部的网络接口名。
af
地址类型,是IPv4或IPv6。PF通常基于来源/目的地地址决定这个参数。
src_addr
将被转发的源地址(内部网IP地址)。源地址规定是:
? 一个IPv4 或IPv6 地址。
? 一个CIDR网络段
? 当规则装载时能被DNS解析的有效域名。所有结果的IP地址将被代替进规则链中。
? 网络接口名。在载入时被分到了接口的任何IP地址将被代替进规则。
? 网络接口名后跟/netmask(e.g /24)。从CIDR网络段中每个接口上的IP地址都与netmask组合将被代替进规则链中。
? 网络接口名后跟:network关键字。当规则载入时, CIDR网络结果(e.g. 192.168.0.0/24)将被代替进规则链中。
? 一个table
? 任何上面的都使用了!(“not”)的标识
? 使用list设置地址
? 关键字意指所有地址

src_port
源端口在第四层数据包头。Ports指定为:
? 端口号在1 到 65535之间
? 从/etc/services里的有效服务
? 使用list设置ports
? 一个范围:
l        != ( 不等于)
l        <  ( 小于 )
l        >  ( 大于 )
l        <= ( 小于等于)
l        >= ( 大于等于)
l        >< ( 范围 range )
l        <> ( 逆范围 inverse range )
         最后两个是二进制操作符(它们要两个参数),不能将两个参数放在范围内(the range)。
         在nat规则中平常并不使用ports 选项,因为目的使用NAT, 所有传输不注意ports是否使用了。

dst_addr
数据包将传输到的目的地址。目的地址的指定同源地址的指定格式是一样的。

dst_port
目的端口位于数据包的第四层包头。端口同源端口指定格式一样。

ext_addr
   在NAT gateway里数据包将要被转发的外部地址(或转发地址),地址的指定格式为:
? 一个IPv4 或IPv6 地址
? 一个CIDR网络段
? 当载入规则时能被DNS有效解析的域名
? 对外网络接口名。在载入时接口分配到的IP地址被替换进规则中。
? 在一对括号中()的对外网络接口名。它告诉PF当接口名分配的IP地址改变时更新规则。当对外网络接口从一个DHCP获得IP地址或使用拨号上网, 规则链在每次IP地址变更时不能及时重载时这个选项就非常有用处。
? 网络接口外后跟:network关键字。当规则载入时, CIDR网络结果(e.g. 192.168.0.0/24)将被代替进规则链中。
? 使用list设置地址
这将导致大部分基础规则链与下面这行很相似:
nat on tl0 from 192.168.1.0/24 to any -> 24.5.0.5

这条规则说为在tl0接口上所有来自于192.168.0.1/24的数据包执行NAT,将这些数据包的源地址替换成24.5.0.5。

当上面的规则是正确时, 它不推荐使用。当外网或内网的网络号码改变时,维护工作会很困难。相比用下面这行替代维护就简单一些了(tl0是对外网络接口, dc0是内部网络接口)

nat on tl0 from dc0/24 to any -> tl0

这个优势是相当清楚的, 当你改变IP地址或网络接口时并不需要更改这条规则。

在上面当为一个接口名指定转换地址时, 在pf.conf载入时就已确定, 并不能即时动态地更改。如果你使用DHCP配置你的对外网络接口, 这会出现问题。当你分配的IP地址发生改变而NAT还继续使用旧的IP地址转发外出的数据包时,这会导致外出的连接被中断。在这里, 你要告诉PF动态更新在括号里网络接口的转发地址。

nat on tl0 from dc0/24 to any -> (tl0)

这样做有一个主要的局限性:当网络接口放在括号里时,Only the first IP alias on an interface is evaluated。只有接口上第一个IP别名被求值(使用)。

Bidriectional Mapping( 1:1 mapping)
双向映射能使用binat规则建立。一个binat规则确定在内部网IP地址和外部IP地址之间的1对1映射。这非常有用, 例如,为内部网里的web服务器提供一个外部IP地址。从Internet上到外部IP地址的连接将被转发到内部网的IP地址上,从web服务器的连接(如DNS查询)将被转发到外部IP地址上。TCP和UDP端口从来没有被使用binat规则修改,它们使用nat规则。(TCP and UDP ports are never modified with binat rules as they are with nat rules)。

例如:
    web_serv_int = "192.168.1.100"
web_serv_ext = "24.5.0.6"

binat on tl0 from $web_serv_int to any -> $web_serv_ext   

Translation Rule Exceptions
当转发规则没有使用no关键字时会出现异常。例如,如果上面的NAT例子改成下面这样:

no nat on tl0 from 192.168.1.10 to any
nat on tl0 from 192.168.1.0/24 to any -> 24.2.74.79

这时整个192.168.1.0/24网络除192.168.1.10外的数据包都被转发到外部地址上。

第一个机器规则成功;如果它是一个no规则,那时数据包将不被转发。关键字no同样可以用在binat和rdr规则中。
Checking NAT Status
查看活跃的NAT转发状态,pfctl使用-s state选项。这个选项将显示当前所有nat会话:

# pfctl -s state
TCP 192.168.1.35:2132 -> 24.5.0.5:53136 -> 65.42.33.245:22 TIME_WAIT:TIME_WAIT
UDP 192.168.1.35:2491 -> 24.5.0.5:60527 -> 24.2.68.33:53 MULTIPLE:SINGLE

解释说明(只第一行):
TCP
连接使用的网络协议
192.168.1.35:2132
内部网机器的IP地址 ( 192.168.1.35), 在地址后显示的是源端口号:2132. 这也是在IP头要被替换的地址。
24.5.0.5:53136
数据包将被转发到的IP地址(24.5.0.5)和端口(53136)。
65.42.33.245:22
内部网里机器connected to 的IP地址和端口号。
TIME_WAIT:TIME_WAIT
   这标示PF信任的TCP连接的状态。


PF: Redirection ( rdr )
Introduction
当你在办公室里运行NAT时可以使用你的网络里的所有机器。那当你的机器在NAT网关后面而它需要访问外面的机器时该怎么办?这就需要使用重定向了。重定向允许进来的传输能发送到NAT网关后的机器上。

看看这个例子:
  
rdr on tl0 proto tcp from any to any port 80 -> 192.168.1.20

这一行将TCP端口80的传输重定向到内部网里的机器192.168.1.20上。即使192.168.1.20这台内部网里的机器在网关后面, 但外界仍可以方问它!

上面rdr规则中的from any to any这一部分也十分有用。如果你知道有哪些地址或分支网络能通过端口号80访问web服务器, 在这里可以进行限制:

rdr on tl0 proto tcp from 27.146.49.0/24 to any port 80 -> \
192.168.1.20

这一行只重定向指定的分支子网。注意这暗示你可以将不同的请求重定向到内部网里不同的机器上。这很实用。例如,有些用户需要从远程终端访问他们的桌面计算机, 如果你知道远程主机和桌面计算机连接双方使用的IP地址和端口号,在网关上就可以这样做:

rdr on tl0 proto tcp from 27.146.49.14 to any port 80 -> \
192.168.1.20
rdr on tl0 proto tcp from 16.114.4.89 to any port 80 -> \
192.168.1.22
rdr on tl0 proto tcp from 24.2.74.178 to any port 80 -> \
192.168.1.23


Redirection and Packet Filtering
应知道即使数据包匹配了一个rdr规则但仍需要通过过滤设置,这些数据包将会被定义的过滤规则通过或阻塞。同样也应知道数据包匹配一个rdr规则会将它们的目的地址或目的端口号改变成匹配的rdr规则中指定的重定向的地址或端口号。考虑这种情况:

? 192.0.2.1 - host on the Internet (Internet上的主机)
? 24.65.1.13 - external address of OpenBSD router (OpenBSD路由器的外网IP地址)
? 192.168.1.5 - internal IP address of web server(内部网里的web服务器)

重定向规则:

rdr on tl0 proto tcp from 192.0.2.1 to 24.65.1.13 port 80 -> 192.168.1.5 8000

在rdr规则处理前数据包:

? 源地址:192.0.2.1
? 源端口号:4028 (操作系统随意选择的一个端口号)
? 目的地址:24.65.1.13
? 目的端口号: 80

在rdr规则处理后数据包:

? 源地址:192.0.2.1
? 源端口号:4028
? 目的地址:192.168.1.5
? 目的端口号:8000

过滤器将查看经过rdr规则处理后的IP数据包。

Security Implications
重定向有安全含意。在防火墙上打开一个漏洞来访问内部网,保护内部网机器打开的潜在的危险端口。例如如果连接到内部网的一个web服务器上,在web服务器上有一个漏洞被发现或在web服务器上运行CGI脚本,那互联网上的攻击者就可能会危及服务器的安全。在这里, 攻击者有一个通向内部网的后门,它可以正确的通过防火墙的检测。

将外面能访问的机器分离到一个子网上可以将这些风险减到最小。这个网络通常会涉及到Demilitarized Zone ( DMZ ) 或 Private Service Network ( PSN )。这样,如果WEB服务器有危险,我们可以非常严格地过滤进出DMZ/PSN网络传输的数据包。

Redirection and Reflection
通常, 重定向规则用于互联网上的主机请求连接到内部网或局域网里的一个私有IP地址的服务器上,像这样:

server = 192.168.1.40

          rdr on $ext_if proto tcp from any to $ext_if port 80 -> $server port 80

但当在局域网里的一个客户端上测试这个重定向连接时, 它却不会工作。原因是重定向规则只用于通过指定接口的数据包上(在本例中,外网接口$ext_if)。可是局域网里的客户端连接到防火墙的外网地址上的数据包并不会到达外网接口处。在防火墙上的TCP/IP栈对进入的数据包的自身地址、别名及它们的目的地址进行比较并且当它们通过内网接口后尽快地探测这些连接。这样的数据包并不能通过外网接口,栈也不会模拟这样一条通道。因此, PF从来没有在外网接口上看到过这些数据包,在外网接口上指定的重定向规则也不会发生作用。

在内网接口上加入第二条重定向规则也不会发生预期的效果。当本地客户端连接到防火墙的外网接口时,TCP握手的初始包通过内网接口到达防火墙。 应用重定向规则并将目的地址替换成本地服务器的地址。数据包转回通过内网接口并到达本地服务器上。但是源地址并没有被转换。防火墙从没看到回应的数据包并对这些数据包做相应的改变。客户端从来没有接收到任何应答的数据包。TCP握手失败, 不能确定任何连接。

Still, it's often desirable for clients on the LAN to connect to the same internal server as external clients and to do so transparently。下面是几个解决方案:

Split-Horizon DNS
很容易配置DNS服务器对来自本地主机的查询和外部查询进行不同的回答,使本地主机能直接查询收到内部服务器地址。它们可以直接连接到本地服务器上,防火墙根本不会包括在内。当数据包不必再发送到防火墙时这就简化了本地传输。

Moving the Server Into a Separate Local Network
在防火墙上加入一个网络接口并将服务器从客户端的网络中移到DMZ中,这样可以对本地客户羰的连接与来自外部的连接进行相同的重定向操作。使用分支子网有几个优势条件,从本地主机中分离出服务器改善了网络的安全性。服务器曾经受到危险(在我们的假设中能直接从Internet上直接访问它),现在本地连接不能直接访问它, 所以的连接都要通过防火墙的检验。

TCP Proxying
普通的TCP代理可以设置在防火墙上,向前监听端口或在内网接口上取得一个连接进行重定向到它监听的端口上。当本地客户端连接到防火墙时,代理接受连接,确定第二个连接到本地服务器上,在这两个连接中传送数据。

简单的代理可以使用inetd(8) 和nc(1)创建。现在/etc/inetd.conf 入口为本地回路地址(127.0.0.1)创建一个监听端口并将它绑定在端口号5000上。在服务器192.168.1.0上连接从端口80连接进来。

127.0.0.1:5000 stream tcp nowait nobody /usr/bin/nc nc -w \
20 192.168.1.10 80

下面的重定向规则将本地服务器的端口80连接定向到代理上:

rdr on $int_if proto tcp from $int_net to $ext_if port 80 -> \
127.0.0.1 port 5000


RDR and NAT Combination
在内网接口上加入一个NAT规则,可以完成上面缺乏的源地址转换记录。

rdr on $int_if proto tcp from $int_net to $ext_if port 80 -> \
$server
no nat on $int_if proto tcp from $int_if to $int_net
nat on $int_if proto tcp from $int_net to $server port 80 -> \
$int_if

当客户端发出的起始数据包被转发回内网接口时会被再次传输。将客户端的源地址改成防火墙的内网地址,内部服务器将回应发到防火墙,防火墙反转NAT和RDR传输并将它们转发到客户端。这样为每个反映创建两个单独的状态的构造很复杂。注意防止将NAT规则应用到别的传输上, 例如从外部主机(通过别的重定向)或防火墙自身发起的连接。注意上面那个rdr规则会因为目地地址是内网地址而去查看TCP/IP栈中到达内网接口的数据包。阻止栈发出的ICMP重定向信息(告诉客户端目地地址能直接到达,破坏the reflection),在防火墙上关闭重定向,使用:

# sysctl -w net.inet.ip.redirect=0
# sysctl -w net.inet6.ip6.redirect=0 (if using IPv6)

基本上, 可以代替前面提到的解决方案。      

作者: rianren   发布时间: 2003-12-26

热门下载

更多