原文: http://www.pppei.net/blog/post/331
从萌生更换公司网关的想法,到选择、测试、部署陆陆续续用时两个月有余。选择的标准是open and free。这期间不断在查阅一些资料,测试了7、8个各开源防火墙产品。这些产品中大多是基于linux,少量基于BSD。基于linux的给我印象比较深的有ipfire、Zentyal。ipfire很轻量,功能上也能满足,但由于限速是基于linux 的tc,且并没有对tc的操作进行抽象,设置起来反而不如直接使用命令行脚本,所以只是把ipfire列入了候选名单。
zentyal 是基于Ubuntu的,看上去就是Ubuntu+webmin,安装后连X桌面都有,显的很庞大,功能自然不用说,linux有的功能它全有了,包括文件共享、邮件、IM等等,这样看来的确给中小企业节约了时间和成本,如果公司只有50-100来个人这种方案也是不错的选择,一台服务器涵盖企业常见应用。随着企业的成长可能这样的模式会带来一些问题,比如性能、存储空间等等 ,为了需求的增长去升级网关的硬件,显得有点不和谐。过度的集成恐怕日后会有不少问题要面对。既然目的是要选一款网关产品,就不要过度的想让它集成太多与“网关”无关的功能,免除一些不必要的麻烦。
最后目光集中到了pfsense身上,pfsense基于BSD,前身是m0n0wall,它专注构建企业级的安全网关,口碑也不错,国内还有pfsense的社区。pfsense虽然功能强大易用,可还是需要有一定的基础去驾驭它。经常看到有人会遇到各种问题无法解决,最终甚至放弃了pfsense,原因多是不能正确认识pfsense,不能自行分析解决问题。一般企来对网关产品的需求无非是NAT、防火墙、流量管理、流量监控、上网行为管理、vpn、热备、负载均衡。这些功能pfsense都可以做到,而且大多都是强项,下面我结合自身的一点实践,介绍一下我关注过的一些功能,并分享一点点经验。
1.NAT(PAT)
NAT不用过多阐述就是能让所有员工共用公司网络连接互联网。这里不得不提下pfsense NAT功能的一个软肋,就是对PPTP的支持有限,内网同一时刻只能有一个用户连接到外网某台特定的pptp服务器,这时其它用户不能再连接这台pptp服务器。如果其它用户连接这台服务器之外的其它pptp服务器,是不存在问题的。这是因为pptp传输数据时用了GRE(通用路由封装)协议,GRE自身和TCP/UDP处于同一级别(但GRE没有实现OSI中对4层定义的功能,不能认为它是4层协议),GRE和tcp/udp一样自己的数据被封装在ip包中,用IP来承载传输。通常网关对TCP/UDP进行NAT后会保留一个含有源、目的端口的一张状态表,避免内网多个用户使用同一源端口时发生冲突,也为返回的数据提供可以被准确转发到内网用户的依据。特殊的是GRE没有类似端口这样的信息,pfsense只是简单的转换GRE数据包中的IP地址,NAT转换表中不会出现端口信息。当内网某用户已经与外网pptp服务器建立了连接,再有用户尝试连接,服务器端返回的GRE协商数据到达pfsense网关后,这个数据包会按照 之前建立的NAT表转发,于是这个包没有被发送到发起连接的用户,而是转发给了第一个与该pptp服务器建立连接的用户。简单来说就是没有端口信息,NAT表中只能有一条到某一IP的转换条目,无法区分出内网不同用户,也就导致了其它用户无法再连接该pptp服务器。
pfsense的NAT、策略路由、防火墙等功能是通过BSD系统的 pf (packet filter)来实现的,归根结底这是 pf 的一个缺陷。目前这个问题没办法直接解决,只能用个变通方法,即将pptp 1723端口和gre协议的流量重定向到一台Linux服务器。linux 有专门的内核模块解决这个问题, 使用modprobe 加载 ip_conntrack_pptp、nf_nat_pptp 两个模块(iptables的nat 可以对服务器端和客户端的GRE协议的Call id进行转换,实现多个内网用户连接同一台pptp服务器),然后在pfsense中将此linux服务器的IP加到pfsense gateway中,在再firewall rule 的高级里将tcp 1723 和gre协议流量转发给这台linux服务器。
2.防火墙
前面提到了pfsense的防火墙、策略路由、NAT等功能都是用BSD下的PF(packet filter)实现的,这也可能是为什么这个项目叫做pfsense的原因。我的防火墙规则是这样的,pfsense网关共三个网卡分别用于WAN、LAN、DMZ,WAN只允许访问DMZ区域中服务器的80等服务端口,DMZ只允许访问互连网,LAN允许访问anywhere。
防火墙规则的高级选项中有很多实用功能,比如7层过滤、重定向、连接数限制、速度限制等,我也是使用了这个方法,对用户进行限速的,请转下一节。
3.流量管理
pfsense 有三种流量管理方法。
一是Queue,这种方式适合做QOS(服务质量保证),对数据进行分类,根据不同数据的不同特性,提供不同的服务质量,比如IP电话的语音数据,需要低网络延时,而某用户的下载流量只关心总带宽,这时就可以将ip电话的数据标记出来放到低延时的队列里,下载的流量放到只保证带宽的队列里,网关会用不同的算法转发相应的数据包,达到预定的服务质量。如果要实现对每个IP分别限速,就要为每个ip都建立一个队列,然后将每个IP的数据对应到唯这个队列上;
二是使用Captive portal,这种方式更适合用在无线网络环境中,用户需要打开浏览器输入用户名密码之后才能正常上网,同时为每个用户分配固定的带宽。只要开启了Captive portal,即使关闭了认证,也还是要打开浏览器在弹出的页面上点击确定后才能上网,用在有线环境里太影响用户体验,而且目前Captive portal 只有全局一个实例,2.1版可以针对不同的端口启用不同的实例;
三是使用防火墙的高功特性(这种方法是根据IP地址分别进行限速的)。在防火墙规则中限速有一个缺点,限速和访问控制策略偶合在了一块,失去了灵活性,配置的时候要谨慎一点不然可能会出现限速失效的情况,举个例子,为说明简单这里限速指的是下载限速:
①——-permit tcp any
②——-permit any to any and speed limit 2M from Lan——
策略①中没有做流量限制,②中每用户的下载都限制在了2M。防火墙规则匹配是自上到下,匹配成功就不再向下进行,因此去往1.1.1.1的流量匹配了第一条策略,没做限速,第二条规则中的限速也就失效了。
另外再对速度做个说明,同样的策略在第一条上加上限速:
①——-permit
②——-permit any to any and speed limit 2M from Lan——
去往1.1.1.1的流量还会匹配策略①,其它的流量匹配策略②,那么如果用户同时有从1.1.1.1下载的流量和其它从其它地方下载的流量,从1.1.1.1下载.限制在2M,从其它地方下载也被限制在2M,因为是同时产生的流量,所以加起来用户得到了4M带宽。其实结果并不是这样的,在防火墙规则中限速时要先定义limiter,然后在规则中引用。内部是这样实现的,BSD的 PF(packet filter)没有限速功能,定义出来的limiter其实是另一个防火墙实现:IPFW中的组件,这个组件实现了限速,而且这个组件支持PIPE(管道)。PF中将匹配到的下载流量通过PIPE送到IPFW的Limiter中,limiter会根据定义时规定的参照值(源、目的ip,下载参照目的IP),为每个ip生成一个bukket,数据通过bukket的速度是它所属Limiter的速率。回到上面的例子规则 ①②中下载2M的limiter为同一个,同时匹配了两条规则的数据,通过PIPE被送到同一个Limiter中,这个limiter会根据目的ip生成一个BUKKET,这个bukket最大速度2M,用户得到的带宽最大也只是2M。如果规则①中使用了其它limiter比如下载3M的limiter,那么用户最终得到的带宽就是5M了。
实施方法前边也都说过了,很简单了Firewall ->Traffic Shaper -> limiter 下创建Limiter(需单独为上传下载创建limiter) ,然后在Firewall -> rule->Lan 规则的高级特性 In/Out 中应用limiter。
这里再对Limiter 的源地址和目的地址做个说明,因为limiter是被应用在Lan接口的Rule里,相对pfsense来说,用户发往 Lan口的流量为In,pfsense通过Lan口发给用户的流量为OUT,因此限制上传的limiter因该应用在In方向,limiter的参照值应该为“源IP”,下载的Limiter应该应用在OUT方向,因为是转发给用户的所以这个limiter的参数值应该是“目的IP”。
还有人可能会有疑问应用在Lan口只是转发给用户的速度慢了,从Wan口进来的流量一样不受限制。这种想法是错的,因为TCP有流控机质,UDP的话就要看上层应用的质量了。
在应用了新策略后,之前已经建立的连接是不会受这些规则影响的,可能得不到你想要的效果,需要在Diagnostics->States -> reset status 下清理一下pfsense的状态,中断用户的连接,就能看到效果了。
如果你更习惯在命令行操作,给出一些常用命令,不用和web界面死磕了:
pfctl -sn
pfctl -sr
pfctl -sa
pfctl -ss
pfctl -F nat #重置防火墙状态(清空NAT状态表)
ipfw pipe show #显示limiter的状态
4.流量监控
pfsense 自身可以显示出当前每个ip的流量情况,web页面中默认只能显示流量最高的10个,并根据接口的实时流量绘制一张曲线图。我对页面进行了一点修改现在可以显示30个ip的流量,目前足够用了,还想实现按ip、上传、下载流量排序的功能,试了试有点超出我能力范围了,如果懂js就不是什么难事了,pfssense的php代码放在/usr/local/www/ ,函数库放在/etc/inc下,配置文件放在/conf下,想改就自己动手吧。
如果要充计历史流量数据,需要安装附加的package,有两个选择,一个是bandwidthd,另一个是ntop,前者很轻量,后者有点笨重,cpu占用也有点高,而且生成的数据我很难看懂,相反bandwidthd的数据很直观。目前两者都在用 bandwidthd统计Lan口,ntop统计 Wan和DMZ口,看不懂也无所谓,嘿嘿。
从命令行查看每IP实时流量可以用以下命令:
rate -i <接口> -nlq 1 -Aba 30 -c 192.168.1.0/24
5.上网行为管理
上网行为管理我觉得应该包括URL过滤、应用层协议识别控制。
首先说URL过滤,pfsense URL过滤用squid + squid guard实现的(需从package中自行安装 ),squid guard 支持正则表达式,我想我就不用说太多了吧,想过滤哪些url 、怎么过滤不都是自己说了算吗。
如果启用url过滤,建议打开Transparent proxy 的选项,这样会在PF的TRANSLATION RULES 中把发往 80的流量重定向到squid的3128端口,不用在用户端做任何的设置。
这里可能会有一个问题,看到社区中有人提到,就是使用了squid 进行 url 过滤,防火墙Rule里的限速就失效了。因为我对PF并不是很精通,我估计原因是这样的,www数据进入Lan接口先通过 TRANSLATION RULES ,数据包在TRANSLATION RULES 里把目的地址改写成了127.0.0.1,端口改写成了3128,然后数据才会继续通过filter rule ,由于某种不能了解的特殊性,没有匹配到任何规则,导致了限速失效。原因明白了对策就很简单了,在Lan接口上新建一个策略源地址为Lan subnet 目的地址为127.0.0.1 端口为3128,高级特性的In/Out中应用对应的limiter就可以了。
应用层协议识别不是pfsense强项,我试图用layer7的特性过滤p2p应用,在上班时间cpu占用到了P(双核),忘记是哪个进程了,所以我个人建议不要用pfsense的这个功能。如果非要对7层进行控制,可以用国产的免费产品panabit ,也是其于freebsd 的,功能非常丰富强大,可以集成到pfsense中去,不过也会有cpu占用率到100%的问题,且免费版有200用户(250?)的限制。
6.vpn
这个在企业应用中很普遍了,pfsense可以构建remote vpn(可以用pptp l2tp openvpn) ,供用户在公司以外的地方可以访问公司内网资源,还可以构建site to site vpn 互联公司分部(site2site只能用openvpn)。用openvpn 做sitetosite 有很多优势,比如可以选择性下发路由信息,可以选择使用tcp还是udp,不会像pptp 那样对NAT不友好。
我已经测试并使用了openvpn 集成 windows AD验证。pptp 和l2tp 不能直接使用AD验证,要通过radius间接实现,测试过程中我在AD上安装了radius服务,radius从Ad中进行用户验证。
另外强调下,pfsense是不能用作pptp 或l2tp的客户端的,只能用在当运营商线路需要pptp或l2tp验证的情况。
7.热备
有两个角度理解热备,1.线路热备 2.硬件热备。
这部分我没有测试就简单说一下吧,硬件failover通过CARP协议实现的,使用一个虚拟的IP做为用户网关,活动网关拥有该ip的控制权,活动网关死机备用网关自动接管该IP,用户端基本不会有感知。pfsense提供了一个强大的特性,它可以做到两台网关的配置同步,只需修改一台网关的设置,备用网关会自动同步活动网关的配置,方便至极。
线路热备建议配合firewall rule让一部分用户走其中一台线,另一部分用户走另一条线,同时检测运营商线路质量,如果延时大于预设值或丢包大于预设值更或者是网关不可用了,将该线路视为不可用,该规则自动失效所有用户数据自动切换到另一条线路。这样即没有浪费又达到了热备的效果。
8.负载均衡
一样的,包括线路负载均衡和硬件负载均衡,除此还多出一个服务器负载均衡。
同样这部分功能没有测试,简单概括一下了。服务器负载均衡用在公司有多台服务器对向提供相同服务时,定义一个服务器池,将这些服务器加入池中,用户连接按照指定的算法分配到池中的不同服务器上。
线路负载均衡上一节中提到了,如果不用firewall rule分配流量,而是通过两条指向不同运营商的路由来实现会存在这样一个问题,数据在发送方被拆为更小的包,在接收方要按顺序进行排序重组,如果一条线路快一线路慢或一条质量好一条质量差,用户会有很明显示的感觉,被慢的线路托慢了。所以建议使用第7节中所说的方法,将用户手动的分配到不同的线路中去。
9.其它应用
snort:入侵检测,实际应用中没有看到任何效果,alert中一直是空的,没有深究。
nrpe:使用内网的nagios对pfsense进行磁盘、负载、外网线路延时等数据进行监控报警。
总结:
pfsense 将BSD系统的网络功能优势发辉到了极致,虽然它并没有强大到无所不能、没有任何瑕疵,但作为一款开源免费的防火墙产品已经可以让我内牛满面了。在使用pfsense前,最好对自己的需求进行分析,如果觉得可以满足目前和将来的需求,我强列推荐您使用pfsense。同时希望这篇文章可以对你了解使用pfsense起到帮助作用,有也就知足了。最后提醒您远离ISA、远离昂贵商业产品。