《The BOOK Of PF》中文版 —— 18. 更大更棘手的网络环境

内部资料,请勿转载,多谢。
主题已锁定
头像
whoami
铁 Fe
帖子: 76
注册时间: 2010-06-03 13:23

《The BOOK Of PF》中文版 —— 18. 更大更棘手的网络环境

帖子 whoami » 2010-07-13 9:44

更大更棘手的网络环境
本章我们将基于前面的基础继续探讨,同时尝试模拟如何应对大型网络或者有特定要求的应用程序或用户的网络的环境。 本章的所有范例中假设你的PF主机提供对本地网络的包过滤服务。 我们主要从Unixd的视角进行讨论, 重点为SSH, email, 和Web服务, 也会顺带探讨一下其它情况。
当你的用户对网络有其它需要时: 过滤服务
时过境迁, 可能是单位网络不断增长或者你自己决定使用BSD和PF来管理你的网络构架。
本章主要探讨用PF主机负责包过滤和其它外部可访问的服务。规则集的复杂程度取决于你的网络设计—和特定的网络服务, 以及多有多少网络IP地址。
下面几页的内容讨论的是为包过滤及提供对外服务的简单环境。我们将配置官方、可路由地址(译者注:公网地址),然后讨论仅有一个可路由地址的情况,以及怎样配置PF来实现对外的服务。
内部有一个Web和一个Mail服务器的环境—可路由地址
你的网络环境有多复杂? 你的网络环境需要多复杂?
我们还是以前面第三章的情况作为基本环境,但是搬来了三个新邻居: 一台邮件服务器, 一台web服务器, 还有一台文件服务器(fileserver)。
本例中我们使用官方可路由地址, 因为这样更简单一些。使用可路由地址还有一些其它的优势: 使用可路由地址,我们用两台新主机为我们的域example.com提供域名解析服务(DNS) , 一台作为master, 另一台作为authoritative slave。详说明1
说明
对DNS来说,在任何情况下至少拥有一台在你本地网络外的authoritative slave服务器都是有意义的。 (事实是, 你无法随意使用一些顶级的域名,除非你已经注册了)。 也许你还想将一台备用的邮件服务器放在别的地方。搭建网络时脑子里记住这些细节。不过, 这些细节对我们编写PF规则影响不大。
在现阶段我们保持网络环境相对简单一些。我们将新的服务器加入原来的网络作为客户端, 尽管它们可能布置在不同的房间内, 但实际上位于同一网段或作为客户端连接到同一台交换机上。 概念上, 这个新网络像图5-1。
因为我们的网络在前面做了基本设置, 我们现在仅需为开启的服务设置规则集。还是一样,为了规则易读,我们从基本的规则集入手,然后设置一些宏。
我们需要的这些宏来自规范。
它们是web服务器 (webserver = "192.0.2.227") 和其提供的服务 (webports = "{ http, https }"); 邮件服务器 (emailserver = "192.0.2.225") 和其提供的服务 (email = "{ smtp, pop3, imap, imap3, imaps, pop3s }"); 最后是, 域名服务器(nameservers = "{ 192.0.2.221, 192.0.2.223 }").
我们这里假设不需要从外部访问这里的文件服务器(fileserver),除非我们的本地服务必须设置为对外可见 , 例如为我们的域服务的一个authoritative slave域名服务器。
说明1
实际example.com网络使用的192.0.2.0/24地址是作为RFC 3330保留的文档使用地址,在本例中我们使用这个地址的目的主要是为了区别于本书其它地方NAT实例中使用的RFC 1918“私有”地址空间。
附件
f5-1.png
未完待续、请勿转载、欢迎纠错、多谢!;)
[email]WHOAMi@点点儿[/email]

头像
whoami
铁 Fe
帖子: 76
注册时间: 2010-06-03 13:23

帖子 whoami » 2010-07-13 9:48

因为我们定义了宏,我们可以方便地添加pass规则。我们先处理web服务器, 让外部可以访问它,用下面的规则

代码: 全选

pass proto tcp from any to $webserver port $webports synproxy state
注意这里的synproxy state选项。当一个新连接被创建时, PF通常让通讯的双方自己处理连接的设置, 如果一个数据包匹配放行规则PF就直接放行。如果启用了synproxy, PF 则负责初始化连接的设置,只在连接被正确地建立后才将这个连接交予通讯的双方自行处理。 这里PF充当了双方三次握手的中介或代理,这样有助于防范SYN-flood或类似的恶意攻击,这些攻击可能导致服务器资源枯竭。不过, 与默认的keep state相比,SYN代理会稍微增加一些资源消耗, 而且也明显地提升了防火墙的负载。
同样, 我们也允许外部访问邮件服务器:

代码: 全选

pass proto tcp from any to $emailserver port $email synproxy state
这里需要注意的是,这条规则允许处于任何位置的客户端全可以访问该邮件服务器,它们拥有和本地主机同样的访问权限, 包含一些没有加密运行的电子邮件检索协议(email-retrieval protocols)。这在真实的环境中再平常不过了, 但是如果你正在搭建一个新的网络平台,你可能需要考虑如何选择。
要让邮件服务器正常工作, 它还需要能将邮件发送到外部:

代码: 全选

pass log proto tcp from $emailserver to any port smtp synproxy state
别忘了在你的过滤规则集最开始设置一个 block all 规则, 这意味着只放行邮件服务器发起的的SMTP通讯出站,如果本地网络的其它主机要向外发送邮件或者接收邮件, 它们则需要使用指定的邮件服务器。这是一个好方法,例如, 它可以尽量确保避免那些病态的垃圾邮件发送者跑到你的网络里、占用你的资源来发送他们的垃圾邮件。
最后, 我们的域名服务器需要被外部的客户端访问,这些客户端需要查询有关example.com的信息以及其它需要提供的域名的信息:

代码: 全选

pass inet proto { tcp, udp } from any to $nameservers port domain
将所有需要从外部访问的规则整合进规则集后, 我们的规则集最终看起来像这样:

代码: 全选

ext_if = "ep0" # macro for external interface - use tun0 or pppoe0 for PPPoE
int_if = "ep1" # macro for internal interface
localnet = $int_if:network
webserver = "192.0.2.227"
webports = "{ http, https }"
emailserver = "192.0.2.225"
email = "{ smtp, pop3, imap, imap3, imaps, pop3s }"
nameservers = "{ 192.0.2.221, 192.0.2.223 }"
client_out = "{ ssh, domain, pop3, auth, nntp, http,\
https, cvspserver, 2628, 5999, 8000, 8080 }"
udp_services = "{ domain, ntp }"
icmp_types = "{ echoreq, unreach }"
block all
pass quick inet proto { tcp, udp } from $localnet to any port $udp_services
pass log inet proto icmp all icmp-type $icmp_types
pass inet proto tcp from $localnet to any port $client_out
pass inet proto { tcp, udp } from any to $nameservers port domain
pass proto tcp from any to $webserver port $webports synproxy state
pass log proto tcp from any to $emailserver port $email synproxy state
pass log proto tcp from $emailserver to any port smtp synproxy state
这还是相当简单的设置, 但遗憾的是, 它存在一个潜在的安全缺陷。 这个网络设计方案中, 所有的服务器和你的客户端一样,全布置在同一个本地网络中, 如果你有仅供内部网络使用的服务,你需要限制该服务只能从内部网络访问。理论上,这意味着攻击者仅需攻陷一台你的本地主机就可以获取所有的资源,这等同于授予攻击者与内网用户同等的权限。这就依赖于每个主机或资源对非认证访问的限制了,这个工作量就很难说了,有可能很简单、也可能很难实施。
下一小节我们将探讨如何将服务器和本地网络隔离开。
未完待续、请勿转载、欢迎纠错、多谢!;)
[email]WHOAMi@点点儿[/email]

头像
whoami
铁 Fe
帖子: 76
注册时间: 2010-06-03 13:23

帖子 whoami » 2010-07-13 9:53

一种物理级别上的分割: 介绍DMZ
在前一小节我们向大家展示了如何在内网提供服务以及通过实用的PF规则集选择对外提供哪些服务。不过, 你可以在保证对外服务的同时更精确地控制访问内网的通讯, 也就是通过我们介绍的这种物理上的分割方法。
要实现物理和逻辑上的分割还是很简单的。将那些提供外网访问的机器布置在一个单独的网络上, 也就是连接到网关的一个单独的接口上。实际效果是在一个单独的网络上,既不属于本地网络一部分、也不属于的Internet。 概念上这个被隔离的网络看起来像图f5-2.
说明
你可以将这个小型网络看作是敌对双方中间相对平静的缓冲地带, 所以这也无怪乎几年前有人创造了一个短语De-Militarized Zone, 或者简称为DMZ, 用这个短语描述这种类型的配置再恰当不过了,所以这个短语目前成为了术语保留下来。
对地址分配来说, 无论是从官方IP地址里分割出一部分给新的DMZ网络使用, 还是将无需外网访问和不需要有可路由地址的部分移到NATed环境里, 无论哪种方式, 你最终要至少要在一块以上的接口上进行过滤。在你后面会看到, 如果你的官方IP地址很少,事实上也完全可能将DMZ网络全部设置在NAT环境里。
规则集本身无需太大的改动。如果需要, 你可以修改每个接口的配置。基本的规则集保持了逻辑性, 但是你可能需要调整宏定义 (webserver, mailserver, nameservers, 或许还有其它地方) 来适应你新的网络布局。

在我们的例子中, 我们可以选择将已经分配给服务器的IP地址范围分割出来, 如果我们想留点空间以备后续的网络增容, 我们可以给新的 dmz_if 设置一个 /25 子网,地址/子网掩码是 192.0.2.129/255.255.255.128。在那种配置下, 设置好单独的物理DMZ分区后,你根本无需修改你的过滤规则集。
可能你这样考虑是因为懒得调整或者是为了避免给长期稳定的运行留下隐患; 但无论怎样, 基本原则就是你必须明确地将DMZ和内网客户端分开。
通过编辑pass规则,只将那些与服务有关的通讯放行到提供相应服务的接口上是好方法:

代码: 全选

pass in on $ext_if proto { tcp, udp } from any to $nameservers port domain
pass in on $int_if proto { tcp, udp } from $localnet to $nameservers port domain
pass out on $dmz_if proto { tcp, udp } from any to $nameservers port domain
pass in on $ext_if proto tcp from any to $webserver port $webports
pass in on $int_if proto tcp from $localnet to $webserver port $webports
pass out on $dmz_if proto tcp from any to $webserver port $webports
pass in log on $ext_if proto tcp from any to $mailserver port smtp
pass in log on $int_if proto tcp from $localnet to $mailserver port $email
pass out log on $dmz_if proto tcp from any to $mailserver port smtp
pass in on $dmz_if from $mailserver to any port smtp
pass out log on $ext_if proto tcp from $mailserver to any port smtp
你也可以根据本地网络的特定接口创建其它的pass规则, 但是即便你不修改,它们还是能继续工作。
附件
f5-2.PNG
未完待续、请勿转载、欢迎纠错、多谢!;)
[email]WHOAMi@点点儿[/email]

头像
whoami
铁 Fe
帖子: 76
注册时间: 2010-06-03 13:23

帖子 whoami » 2010-07-13 9:53

分摊负载: 重定向到一个地址池
一旦你设置好了外部世界可以访问的服务, 一个可能的情况就是随着时间的推移, 你的服务器中的一台或多台也已久经历练而且负载越来越大或者超过了单台服务器所能应付的流量。
有几种方式可以让多台机器提供同样的服务内容、共同分担负载, 还包含用自我微调服务的几种方式。如何运行一个web服务器的细节并不在本书的范围内,不过, 就网络负载平衡来说, PF提供了将通讯重定向到几个地址构成的地址池的基本功能。
拿本例中的webserver来说, 我们已经为这个公网IP地址设置了一个宏 (webserver = "192.0.2.227"), 反过来说这个主机名,可能是http://www.example.com, 也被你的用户保存在他们的书签了。
当流量达到需要分担负载时, 设置一些相同或等效的服务器,然后在你的规则集里设置重定向规则。 首先, 添加一个web服务器池的宏:

代码: 全选

webpool = "{ 192.0.2.214, 192.0.2.215, 192.0.2.216, 192.0.2.217 }"
然后指定重定向, 这意味着一旦应用该规则,你原来的web服务器就已经退役了:

代码: 全选

rdr on $ext_if from any to $webserver port $webports -> $webpool \
round-robin sticky-address
这里的round-robin选项的意思是PF依次将负载均衡到地址池内的机器上。 这里的sticky-address选项确保了一个新建立的客户端连接将永远重定向到地址池内的同一台机器上,也就是最初建立连接时提供服务的那台机器。
如果服务依赖于特定的客户端或特定的进程参数(这里指如果客户端被重定向到地址池中的另一台服务器上数据可能会丢失的情况),固定地址(译者注:这里还是指固定到位于同一个IP的同一台服务器)就十分必要的。 而在其它情况下, 即便并非绝对需要负载均衡时, 随机地选择重定向地址也是也是不错的做法:

代码: 全选

rdr on $ext_if from any to $webserver port $webports -> $webpool random
这里值得一提的是即使是由官方地址构成几个大型地址池, 在负载均衡地址池和Ineternet间有路由地址也已经引入了NAT。这种技术在不同的基于NAT的设定中工作得很好, 但是转到NAT存在一些额外的可能性及挑战。
未完待续、请勿转载、欢迎纠错、多谢!;)
[email]WHOAMi@点点儿[/email]

头像
whoami
铁 Fe
帖子: 76
注册时间: 2010-06-03 13:23

帖子 whoami » 2010-07-13 9:54

用hoststated保证负载均衡正确
当你通过round-robin重定向运行了一段时间的负载均衡后, 你也许会注意到这个重定向不能自动适应外部条件的变化。一个例子就是在一台或多台列在名单内的重定向主机无法访问时,除非采取特殊的措施, 否则不管通讯能否抵达目的主机或者目标主机是否已经无力处理服务请求,PF仍会将通讯重定向到名单内提供的IP地址上。很显然, 需要一个可监控的解决方案, 而幸运的是, OpenBSD的基本系统提供了一个主机状态进程hoststated。 hoststated和PF配置相互作用, 提供了一个将失效主机从池中剔除的功能。

要在你的规则集中引入hoststated, 不管怎样,需要对规则集进行一下小调整。 hoststated工作在services范畴内,并且期望能在PF的表格内添加或删除主机的IP地址。
hoststated进程通过一个特定的重定向锚hoststated与你的规则集相互作用。我们来看一下怎样让我们的规则集工作得更佳出色一些, 我们先复习一下负载均衡规则集。
在你的pf.conf文件的最前面, 在NAT部分前面加入下行:

代码: 全选

rdr-anchor "hoststated/*"
在那个负载均衡规则集里, 我们已经对webserver池进行了定义

代码: 全选

webpool = "{ 192.0.2.214, 192.0.2.215, 192.0.2.216, 192.0.2.217 }"
而这个重定向

代码: 全选

rdr on $ext_if from any to $webserver port $webports -> $webpool \
round-robin sticky-address
可以使配置与hoststated共同工作, 我们需要将webpool表格格式的定义改成像这样

代码: 全选

table <webpool> persist { 192.0.2.214, 192.0.2.215, 192.0.2.216, 192.0.2.217 }
然后改变重定向以便使用新的 <webpool> 表格:

代码: 全选

rdr on $ext_if from any to $webserver port $webports -> <webpool> \
round-robin sticky-address
一旦处理好了pf.conf的相关内容, 我们现在该处理hoststated自己的配置文件hoststated.conf 了。这个配置文件的语法和pf.conf的语法极其相似,所以它很容易阅读和理解。首先, 我们添加后面要用到的宏定义:

代码: 全选

table webpool {
        check http "/status.html" code 200
        timeout 300
        real port 80
        host $web1
        host $web2
        host $web3
        host $web4
}
所有这些全对应于我们在pf.conf文件中的定义, 除了最后一个。 (大家一会儿就会知道其作用了。) hoststated的默认检查间隔是10秒, 这意味着一台主机在被记录为离线前至多就宕机了10秒钟。
谨慎起见, 为了最小化可察觉的宕机时间,我们用下面这行将检查时间间隔设置为5秒:

代码: 全选

interval 5 # check hosts every 5 seconds
现在我们设置一个名为webpool表格,它使用这些宏来匹配我们刚在PF的配置文件中设置的表格:

代码: 全选

table webpool {
        check http "/status.html" code 200
        timeout 300
        real port 80
        host $web1
        host $web2
        host $web3
        host $web4
}
除了定义成员主机, 我们的表格还指定了hoststated应该通过向一台主机请求/status.html文件以检查其是否可用, 它使用的是HTTP协议, 并且期望主机返回一个值200。这是一台正在运行的web服务器应该返回的结果。
现在不奇怪了吧? hoststated将把不工作的主机从表格内剔除。但是如果webpool表格内所有的主机全宕机了会怎样呢? 幸运的是开发者们也考虑了这种情况,且引入了备份服务表格的概念。这是www服务定义的最后部分, 用表格sorry作为backup表格:

代码: 全选

table sorry {
        check icmp
        real port 80
        host $sorry_server
}
service www {
        virtual ip $webserver port 80
        table webpool
        backup table sorry
}
在sorry表格内的主机是webpool表格为空时被接管的。这意味着你需要设置一个服务,当web池内的所有主机失效时它可以提供一条信息“Sorry, we’re down”。
如果你想在启动时启用hoststated, 将这行

代码: 全选

hoststated_flags="" # for normal use: ""
加入到rc.conf.local文件。然而, 多数情况下你是通过hoststatectl管理程序来操控hoststated。除了可以监视状态, hoststatectl还可以让你重新导入hoststated的配置以及选择禁用或启用主机, 表格, 和服务, 并且它甚至可以让你交互式地查看服务状态,像这样:

代码: 全选

$ sudo hoststatectl show summary
Type         Id      Name                 Avlblty    Status
service       0      www                             active
table         0      webpool                         active (2 hosts up)
host          3      192.0.2.217          0.00%      down
host          2      192.0.2.216          100.00%    up
host          1      192.0.2.215          0.00%      down
host          0      192.0.2.214          100.00%    up
table         1      sorry                           active (1 hosts up)
host          4      192.0.2.200          100.00%    up
这里的web池严重退化, 4台主机里仅有两台还在工作。幸好backup表格还在工作。只要有一台主机还在工作这里的表格就全在。对于那些没有任何内容的表格, 状态列显示为空。
要让hoststatectl以host-centered的格式显示主机信息 :

代码: 全选

$ sudo hoststatectl show hosts
Type       Id     Name                  Avlblty  Status
service     0     www                            active
table       0     webpool                        active (2 hosts up)
host        3     192.0.2.217           0.00%    down
                  total: 0/6 checks
host        2     192.0.2.216           100.00%  up
                  total: 0/6 checks
host        1     192.0.2.215           0.00%    down
                  total: 0/6 checks
host        0     192.0.2.214           100.00%  up
                  total: 6/6 checks
table       1     sorry                          active (1 hosts up)
host        4     192.0.2.200           100.00%  up
                  total: 6/6 checks
如果你想将一台主机从池中取出以便进行维护或需要对其进行时间比较长的操作, 你可以用下面的命令禁用它:

代码: 全选

$ sudo hoststatectl host disable 192.168.103.1
多数情况下, 上面的命令会得到操作完全成功的显示。一旦你完成对机器的维护,你就需要让其重新上线, 你可以用下列命令重新激活它,使它成为hoststated池的一个成员:

代码: 全选

$ sudo hoststatectl host enable 192.168.103.1
再说一遍, 你应该确认看到了命令成功的信息,它表明操作完全成功。
除了我们在这里演示的基本负载均衡, 在最近的一些OpenBSD版本中hoststated得到了进一步的扩展,它还提供了一些适合应付复杂设定的其它功能。现在它能为HTTP和HTTPS处理7层代理或中继。 这包括了处理hearder扩展和rewrite的协议, 而且甚至可以处理session和cookie。
要处理此类协议,你需要为应用程序进行定制。下面是一个简单的HTTPS中继,它为从客户端到web服务器的加密web通讯提供负载均衡。

代码: 全选

protocol httpssl {
                protocol http
                         header append "$REMOTE_ADDR" to "X-Forwarded-For"
                         header append "$SERVER_ADDR:$SERVER_PORT" to "X-Forwarded-By"
                         header change "Keep-Alive" to "$TIMEOUT"
                         url hash "sessid"
                         cookie hash "sessid"
                         path filter "*command=*" from "/cgi-bin/index.cgi"

                         ssl { sslv2, ciphers "MEDIUM:HIGH" }
                         tcp { nodelay, sack, socket buffer 65536, backlog 128 }
}
这个协议处理程序定义向我们展示了在HTTP headers上的简单操作以及处理优化连接的SSL和特定TCP参数。 这里的header选项作用于协议headers, 要插入变量值可以通过附加到已存在的headers (append)中, 或者将其更换为新值 (change)。 这里的url hash和cookie hash用于负载平衡,目的是选择将请求发送给目标池中的具体哪一台主机。path filter指定了任何获得的请求中如果包含了以第一对引号内的“字符串”作为第二个引号内的"字符串"的子串,则此请求将被丢弃。 而ssl选项指定只接受第二号版本的SSL,而且key的长度在中-高的范围内, 或者, 换句话说, 128位或更多。详说明2 最后, 这里的tcp选项指定ToS标签应该设置为nodelay(不延迟), 指定了用于确认选择的方法 (RFC 2018) 和设定的socket buffer大小以及负载平衡程序最大允许的连接数。
relay定义使用的协议处理程序使用的模式应该符合我们前面的www服务的service定义:

代码: 全选

relay wwwssl {
              # Run as a SSL accelerator
              listen on $webserver port 443 ssl
              protocol httpssl
              table webhosts loadbalance
}
不过, 启用SSL的web应用程序可能受益于稍微不同的参数设定。
最后, 对于网络中运行hoststate的基于CARP故障转移的主机(请参阅 “冗余和故障转移: CARP and pfsync” page 97)可以通过设置CARP demotion counter来指定关闭或启动时的接口组或组,这样就可以将hoststated设置为与CARP相互配合使用。像所有OpenBSD系统的组件一样, hoststated的相关内容及其风格,你可在其用户手册上查阅。对于那些我们这里没有涉及的选项和思考角度来说 (不太多了), 我推荐您仔细阅读hoststated的用户手册, hoststated.conf文件, 还有hoststatectl以及通过自己动手尝试找出适合你自己的配置。
说明2
请参阅OpenSSL的用户手册以获取更多的相关cipher选项的解释。
未完待续、请勿转载、欢迎纠错、多谢!;)
[email]WHOAMi@点点儿[/email]

头像
whoami
铁 Fe
帖子: 76
注册时间: 2010-06-03 13:23

帖子 whoami » 2010-07-13 9:56

Web服务器和邮件服务器位于内网—NAT版本
我们回溯到第三章,来了三个新邻居: 一台邮件服务器, 一台web服务器, 和一台文件服务器。时过境迁, 外部可见的地址没有了或太贵了, 而且在一台机器上运行其它的服务成为首选,防火墙也不定需要了。
这意味着我们回到了在网关上做NAT的情形。幸运的是, PF的重定向机制使服务器即使在网关内也很容易布置。这个特定的网络和我们在前面设置example.com是一样的: 我们需要运行一个web服务器,这个服务器提供明文的数据 (http) 和加密的数据 (https), 此外我们想要一台邮件服务器,这台服务器在收发email的同时还允许内部和外部的客户端使用一些我们熟知的提交和检索协议:

代码: 全选

webserver = "192.168.2.7"
webports = "{ http, https }"
emailserver = "192.168.2.5"
email = "{ smtp, pop3, imap, imap3, imaps, pop3s }"
rdr on $ext_if proto tcp from any to $ext_if port $webports -> $webserver
rdr on $ext_if proto tcp from any to $ext_if port $email -> $emailserver
pass proto tcp from any to $webserver port $webports synproxy state
pass proto tcp from any to $emailserver port $email synproxy state
pass proto tcp from $emailserver to any port smtp synproxy state
再说一遍, 我们在新规则里使用了标签synproxy,它的意思是在将连接通讯直接交给通信双方前,PF将作为代理处理初始化连接过程 (三次握手)。就像我们在前面看到的那样,这可以保护服务器抵挡基于SYN的攻击。
未完待续、请勿转载、欢迎纠错、多谢!;)
[email]WHOAMi@点点儿[/email]

头像
whoami
铁 Fe
帖子: 76
注册时间: 2010-06-03 13:23

帖子 whoami » 2010-07-13 9:56

NAT下的DMZ
所有的服务器全设置在NAT环境下时, 给DMZ区域分配的有效地址构成的地址池看起来比前面Page 49上我们探讨的“一种物理级别上的分割: 介绍DMZ”大得多, 但是应用的原则是一样的。当你将这些服务器移到一个物理上的独立网络, 你需要确认你的规则集的宏定义是无误的, 如果需要请自行调整。

就像使用的是可路由地址一样, 你要限制你的规则集中的放行规则,确保所有服务相关的访问实际上被重定向到提供服务的接口上:

代码: 全选

pass in on $ext_if proto { tcp, udp } from any to $nameservers port domain
pass in on $int_if proto { tcp, udp } from $localnet to $nameservers port domain
pass out on $dmz_if proto { tcp, udp } from any to $nameservers port domain
pass in on $ext_if proto tcp from any to $webserver port $webports
pass in on $int_if proto tcp from $localnet to $webserver port $webports
pass out on $dmz_if proto tcp from any to $webserver port $webports
pass in log on $ext_if proto tcp from any to $mailserver port smtp
pass in log on $int_if proto tcp from $localnet to $mailserver port $email
pass out log on $dmz_if proto tcp from any to $mailserver port smtp
pass in on $dmz_if from $mailserver to any port smtp
pass out log on $ext_if proto tcp from $mailserver to any port smtp
如果你的本地网络还需要一些其它的特定放行规则,你可以选择这样做,但是如果你不修改这里的规则集,它们会继续工作。(译者:这里是否是说作者的规则集已经考虑的比较全面了?:confused:
未完待续、请勿转载、欢迎纠错、多谢!;)
[email]WHOAMi@点点儿[/email]

头像
whoami
铁 Fe
帖子: 76
注册时间: 2010-06-03 13:23

帖子 whoami » 2010-07-13 9:57

重定向以实现负载均衡
基于重定向的负载均衡规则来自于第50页的“分摊负载: 重定向到一个地址池”,它在NAT情况下一样工作的很好,这里所谓的NAT环境也就是:网关上的外部接口是公网的IP地址,而重定向地址在一个私有的地址范围内。
可路由地址与NAT版本的之间的主要区别是: 在你添加了webpool的定义后

代码: 全选

webpool = "{ 192.168.2.7, 192.168.2.8, 192.168.2.9, 192.168.2.10 }"
你要编辑现有的重定向, 它们那时会变成

代码: 全选

rdr on $ext_if from any to $webserver port $webports -> $webpool \
round-robin sticky-address
从这规则生效时开始, NAT下DMZ区域的服务器行为特征就和原来的具有官方、可路由地址的那些服务器很相似了。(译者:这里的意思应该是服务器的性能和限制类似,不受是否在NAT环境下工作的影响。)
未完待续、请勿转载、欢迎纠错、多谢!;)
[email]WHOAMi@点点儿[/email]

头像
whoami
铁 Fe
帖子: 76
注册时间: 2010-06-03 13:23

帖子 whoami » 2010-07-13 9:59

回到单个的NAT网络
也许你听到某些情况下设置一个小型网络要比设置一个大型网络更麻烦的说法时会吃惊。
我们现在回到所有的服务器全作为客户端位于同一个物理网络上, 在“Web服务器和邮件服务器位于内网—NAT版本”里在一定程度上服务器工作的很好, 如果你感兴趣的是将外部的访问NAT到内部的服务器上,所有的工作都很完美。

为了免得你往前搜索以前的文章, 这里列出的基本的配置:

代码: 全选

webserver = "192.168.2.7"
webports = "{ http, https }"
emailserver = "192.168.2.5"
email = "{ smtp, pop3, imap, imap3, imaps, pop3s }"
nat on $ext_if from $localnet to any -> ($ext_if)
rdr on $ext_if proto tcp from any to $ext_if port $webports -> $webserver
rdr on $ext_if proto tcp from any to $ext_if port $email -> $emailserver
pass proto tcp from any to $webserver port $webports synproxy state
pass proto tcp from any to $emailserver port $email synproxy state
pass proto tcp from $emailserver to any port smtp synproxy state
如果你尝试从本地主机用服务器的官方地址访问它, 你马上会发现来自本地主机的重定向请求根本无法抵达外部接口。 这是因为所有的重定向和地址转换都发生在外部接口上。

网关在内部接口接收来自本地网络的数据包, 它们的目标地址被设定为外部接口的地址(whoami:这里应该是指网关的外部接口地址)。 网关认出这个地址是它自己本身的一个地址,然后就尝试处理这个请求,就像已将其定向到一个本地服务(译者注:可能有的读者在这理解上有困难,你可以暂时将其理解为PF认为该通讯的方向原本就是由外至内的,也就是外部主机发的服务请求,因为PF会将这个请求转发到内部服务器——如果您还不理解请自行参考英文原著,并请将您认为合适的翻译方法贡献出来)。 所以, 重定向对来自内部网络的通讯工作不正常。

幸运的是, 可能通过几个方法来解决这个问题。
因为这个问题相当的普遍,所以PF用户指南里列出了4种不同的解决方法,详说明3 包括我们前面描述的将你的服务移到一个DMZ区域。因为本书是有关PF方面的, 我们将精力放在基于PF的解决方案上,
这个方案在重定向和NAT规则里将本地网络视为一个特殊情况来处理。

我们要截取来自本地网络(访问本地服务器)的网络数据包,并正确处理这些数据包, 确保所有返回的通讯被定向到真正的连接发起方那里。

这意味着要想让来自内部的服务请求像我们期望的那样正确重定向, 我们需要添加一条特定的重定向规则,这条规则可以看作是处理外部请求规则的镜像:

代码: 全选

rdr on $int_if proto tcp from $localnet to $ext_if port $webports -> $webserver
rdr on $int_if proto tcp from $localnet to $ext_if port $email -> $emailserver
no nat on $int_if proto tcp from $int_if to $localnet
nat on $int_if proto tcp from $localnet to $webserver port $webports -> $int_if
nat on $int_if proto tcp from $localnet to $emailserver port $email -> $int_if
通过这种方法, 我们“修正”了规则的重定向和地址转换的逻辑以便让它按照我们的要求运行, 这样我们就一点也不需要修改pass规则了。 我感觉很幸运,通过在email或IRC上与一些网络管理员的交流,到目前为止他们对上面的这5条规则的反馈都是正面的。
说明3
请参考《PF用户手册》里的"重定向与映射"
未完待续、请勿转载、欢迎纠错、多谢!;)
[email]WHOAMi@点点儿[/email]

头像
whoami
铁 Fe
帖子: 76
注册时间: 2010-06-03 13:23

帖子 whoami » 2010-07-13 9:59

在接口组上过滤
你的网络上可能有几个子网,除了email,web,file和打印,它们不需要和内部网络相关作用。 怎样处理处理来让于这些子网的通讯取决于你的网络规划。 一个有效的方法就是分别将这些特权相对较少的网络作为一个单独的本地网络,也就是在常规的过滤网关上为每个这样的网络设置其单独的接口, 然后为其建立一个规则集,仅允许我们需要的通讯与之互动, 同时其它网络也接到这个主网关上。
我们可以在网关上将逻辑上类似的接口组成一个接口组,并且将过滤规则应用在接口组上 ,而不是应用于单个接口上。从OpenBSD 3.6开始,用户可以通过ifconfig group选项实现接口组操作,在FreeBSD 7.0或更新的版本中也可以进行同样的设置。
所有已经配置的网络接口都可以被设定为一个或多个接口组的成员。有些接口自动自动属于默认的接口组。例如, 所有的IEEE 802.11无线网络接口都属于wlan接口组, 而语默认路由相关的接口都属于egress接口组。幸好一个接口可以同时属于几个组, 你可以通过适当的ifconfig命令将一个接口加入到接口组中

代码: 全选

# ifconfig sis2 group untrusted
(或者在OpenBSD中你也可以将这行放入hostname.sis2文件,在FreeBSD7.0或更新的版本中将ifconfig_sis2=这行放在rc.conf文件里也可以起到同样的效果)。
一旦生效后, 你可以在过滤规则里像处理单个接口那样处理接口组:

代码: 全选

pass in on untrusted to any port $webports
pass out on egress to any port $webports
值得一提的是在接口组上过滤让我们可以编写与无关硬件的基本过滤规则。如果将接口置入正确的组内,同样适用于那些hostname.if文件或者ifconfig_if= 这些行,基于接口组的规则集可以完全在机器之间平滑的地移植,不管这些机器是否有基于硬件的配置。
(译者:这段感觉翻译的很生硬,欢迎读者提供更好的翻译,如果懒得阅读原文,请理解主要含义,也就是用配置接口组取代对每个接口的配置可以减少规则的编写量及可能产生的错误,减少错误排查的难度,以及完全摆脱基于硬件的规则编写——我想最后一条是作者的主要想表达的意思。)
用宏作为接口组
在那些没有接口组概念的系统上, 你可以通过创建宏来实现部分类似接口组的功能, 如下:

代码: 全选

untrusted = "{ ath0 ath1 wi0 ep0 }"
egress = "sk0"
whoami:
我还没有仔细看NetBSD的用户指南,这里可能就是指NetBSD或者DragonFly BSD了,因为前面已经说了仅有BSD系统可以使用PF,原文这里的意思是宏并不能完全取代接口组,可能作者的本意是想说在规则的编写上宏和接口组还是有差别的,因为对我来说接口组是一个新概念,所以不敢下定论。这里请读者注意。
未完待续、请勿转载、欢迎纠错、多谢!;)
[email]WHOAMi@点点儿[/email]

主题已锁定

在线用户

正浏览此版面之用户: 没有注册用户 和 1 访客