电脑技术学习

用ipfilter实现透明代理

dn001
本人(作者)属新手上路, 才学习了没几天, 刚刚配好了一台代理服务器, 对于高手来讲实在是小菜一碟, 本没有什么可以值得炫耀的. 应 href="http://www.Linuxforum.net">中国Linux论坛 FreeBSD世界版主 href="mailto:yjs@oldhand.org">r00t 的要求, 对配置过程做了一个记录, 不免贻笑大方.
文中如有什么错误, 请与作者
联系. 本文着重介绍配置透明代理, 基本不涉及网络服务器, 含dns, web, email的配置, 这些服务器对于防火墙的要求, 请参照其它介绍.



采用本文内容, 如果造成任何损失, 作者概不负责.



Reference:


IP Filter Based Firewalls HOWTO [ href="http://www.obfuscation.org/ipf/ipf-howto.pdf" target=_blank>PDF
| target=_blank>HTML ] (本文中简称 HOWTO)

target=_blank>Quick CableNet Connections with FreeBSD - By, Leon



系统构成


Gateway:


系统安装FreeBSD 4.5. PENTIUM-S 100, 80M内存, 4G硬盘. 安装双网卡.





Dlink DFE5000TX一块古老的网卡, 老得Windows 98都需要厂家的驱动, Windows 2000厂家都不提供驱动了, 不过BSD/Linux还都支持这块网卡, FreeBSD中为dc0. 该网卡连接内部网络.

Dlink DFE530TX, FreeBSD中为vr0. 该网卡连接 ADSL Modem.


网内客户机


本文中有时称为ClIEnt, 安装Windows XP



网络结构


Gateway dc0分配地址192.168.0.1/24, 通过HUB连接内网Windows XP客户机
192.168.0.4/24, vr0连接ADSL Modem, 通过pppoe拨号上网.采用动态地址.



本文假定Gateway 的 pppoe和DNS已经正常工作, 有关这方面的介绍, 请参照其它文章.



Gateway设置


编译内核




cd /usr/src/sys/i386/conf

cp GENERIC KERNEL1

vi KERNEL1






修改该内核配置文件, 增加如下配置









options IPFILTER
# ipfilter support


options IPFILTER_LOG
# ipmon( log support


options IPFILTER_DEFAULT_BLOCK
# block all packets by default


options RANDOM_IP_ID
# RANDOM_IP_ID causes the ID field in IP packets to be
randomized



# instead of incremented by 1 with each packet generated.


options BRIDGE



options ICMP_BANDLIM
# Rate limit bad replies






#options TCP_DROP_SYNFIN
# drop TCP packets with SYN+FIN



# 该参数可以提高系统的安全性,但在作web server时不建议使用,详见LINT





取消内核中所有与IPFIREWALL有关的配置









# options IPFIREWALL
# firewall


# options IPFIREWALL_VERBOSE
# enable logging to syslogd(


# options IPFIREWALL_FORWARD
# enable transparent proxy support


# options IPFIREWALL_VERBOSE_LIMIT=100
# limit verbosity


# options IPFIREWALL_DEFAULT_TO_ACCEPT
# allow everything by default






# options DUMMYNET






调整网络参数





options NMBCLUSTERS=32768



系统安装时该参数很小, 会影响网络的性能. 这个数值只是我简单的配置, 做服务器可能要更大. 具体说明详见 href="http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/index.html" target=_blank>FreeBSD HandBook "http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/configtuning-kernel-limits.html" target=_blank>6.10.2 Network Limits





标示该内核





ident KERNEL1





编译内核





cd /usr/src

make buildkernel KERNCONF=KERNEL1

make installkernel KERNCONF=KERNEL1

(这两个命令可以合并为 make kernel KERNCONF=KERNEL1)





修改配置文件


/etc/rc.conf


删除该文件中有关ipfw的配置, 或者将





firewall_enable="NO"





增加如下配置









gateway_enable="YES"
# enable gateway


named_enable=YES"
# enable naming service


ipfilter_enable="YES"
# Stateful firewall


ipfilter_program="/sbin/ipf"



ipfilter_rules="/etc/ipf.conf"
# 新增加的规则文件, 有人习惯文件名 .rule



ipfilter_flag=""



ipnat_enable="YES"
# Network Address Translation



ipnat_program="/sbin/ipnat"



ipnat_rules="/etc/ipnat.conf"
# 新增加的规则文件, 有人习惯文件名 .rule



ipmon_enable="NO"
# Firewall logging, 我没有开放, 如果是重要的服务器, 应该开放.



ipmon_program="/sbin/ipmon"



ipmon_flag="-Ds"







/etc/ipf.conf


该文件为防火墙配置文件, 本文主要介绍实现透明代理, 从网络的角度讲是代理Client, 因此关闭了Internet方向的Server
In的所有端口. 这个配置, 允许内网dc0的所有操作, 允许对外Internet的所有请求, 但外网Internet只允许对内网请求的回应, 其他包一律丢弃.





# 默认规则, 关闭阻止所有的包, 关闭所有的通路, 再一步一步打开允许的通道.

# 如果内核设置了 IPFILTER_DEFAULT_BLOCK, 可以省略.

block in all
block out all



# 允许内网的信息自由通过.

pass in quick on dc0 from 192.168.0.0/24 to any

pass out quick on dc0 from any to 192.168.0.0/24



# 允许本机的信息自由通过.

pass in quick on lo0 all

pass out quick on lo0 all



# 禁止外网的无效地址通过

block in quick on tun0 from 192.168.0.0/16 to any

block in quick on tun0 from 10.0.0.0/8 to any

block in quick on tun0 from 172.16.0.0/12 to any

block in quick on tun0 from 127.0.0.0/8 to any

block in quick on tun0 from 0.0.0.0/8 to any

block in quick on tun0 from 192.0.2.0/14 to any

block in quick on tun0 from 204.152.64.0/23 to any

block in quick on tun0 from 224.0.0.0/3 to any



# 对外网信息的处理, 允许内网包发送到外网, 并且允许外网对这些包的回应信息通过

pass out quick on tun0 proto tcp from any to any flags S/SAFR keep state keep frags

pass out quick on tun0 proto udp from any to any keep state keep frags

pass out quick on tun0 proto icmp from any to any keep state keep frags





/etc/ipnat.conf


该文件为NAT配置文件.
本文中pppoe通过DHCP方式获得地址, 因此无法在规则中给出外网的地址, 先用0代替.





# ftp proxy, 为 active 方式的FTP使用, 稍后再作介绍. 请注意, proxy的设置一定要在portmap之前.

#map tun0 192.168.0.0/24 -> 0/32 proxy port ftp ftp/tcp



# IKE proxy, 为ESP (Encapsulating Security Protocol) 使用

# map tun0 192.168.0.0/24 -> 0/32 proxy port 500 ipsec/udp



# RealAudio proxy, 只可用于PNM模式, RealPlayer G2已经使用RTSP.

#map tun0 192.168.0.0/24 -> 0/32 proxy port 7070 raudio/tcp



# 允许内部的UDP/TCP包通过,并且允许外网回应包通过

# 到外网采用指定范围的端口

# map tun0 192.168.0.0/24 -> 0/32 portmap tcp/udp 40000:60000

# 到外网由系统自动分配端口

map tun0 192.168.0.0/24 -> 0/32 portmap tcp/udp auto



# 允许内部ICMP通过,并且允许回应包通过

map tun0 192.168.0.0/24 -> 0/32



# 允许net2phone, 将呼入的呼叫转到指定机器

# rdr tun0 0/0 port 6801 -> 192.168.0.4 port 6801 udp



# 允许squid

# rdr dc0 0/0 port 80 -> 127.0.0.1 port 3128 tcp






/etc/sysctl.conf




net.inet.ip.forwarding=1
net.inet.ip.sourceroute=0
net.ip.accept_sourceroute=0



# To definding against sequence number attacks

# based on rfc 1948 by randomize initial sequence number

net.inet.tcp.strict_rfc1948=1



# To verisy that an incoming packet arrives on an interface

# that has an address matching the packets destination address

net.inet.ip.check_interface=1



# To Drop SYN packets destine to non-listening tcp/upd port.

# This will create a blackhole and protect against stealth port scans

net.inet.tcp.blackhole=2

net.inet.udp.blackhole=1



# Increase TCP Windows size for increase in network performance

# Ref: http://www.psc.edu/networking/perf_tune.html

net.inet.tcp.recvspace=65535

net.inet.tcp.sendspace=65535





DNS


修改文件 /etc/resolv.conf, 增加一条



nameserver DNS_SERVER_IP



如果内网有DNS Server, 应指向该服务器. 如果gateway本身为DNS Server, 为127.0.0.1, 必须配置named.conf. 一般最简单的配置就是指向ISP的DNS Server.



客户机设置


将客户机的Gateway 和 DNS Server都设置为Gateway机器的地址 192.168.0.1



系统测试


Gateway修改完配置后需要启动. 命令 shutdown -r now

客户机Windows XP不需重启, Windows 98要重启.



启动步骤




连接internet, 命令ppp -dedicated <XXXXX >

同步防火墙. 我们在设置规则的时候并不知道网络地址, 只有连接成功后才知道确切的地址, 命令ipf
-y可以使ipfilter更新地址, 之后ipfilter就会使用tun0的具体地址. 每次重新连接pppoe后, 都需要进行同步.


Gatewat测试




测试内网, ping 192.168.0.4看是否正常.

测试internet. 运行ifconfig -a
察看tun0的地址及其对应的gateway/router的地址, 假如为a.b.c.d. ping a.b.c.d看是否正常.

测试DNS是否正常, 运行nslookup yahoo.com.cn, 看是否正常.

测试网络, 运行traceroute yahoo.com.cn, 看是否正常. 我的机器没装Xwindow, 因此无法使用浏览器进行测试.

其它有用的测试命令,
ipfstat -hio 显示规则被“击中”的情况.
ipfstat -t 显示防火墙的连接状态.

ipnat -l 显示NAT的状态.
netstat -r 显示路由表.
netstat -i
显示网络的情况, 如果有错误或有大量的冲突包, 应该设法解决.
vmstat 显示系统内存的状态, 如果资源不足, 应增加资源或减少一些服务.


客户机测试




ping 192.168.0.1看是否正常.

tracert a.b.c.d看是否正常. BSD/Linux用traceroute命令, 若不正常, 是防火墙或NAT的问题.

nslookup yahoo.com.cn看是否正常. 若不正常, 是DNS设置的问题.

ping yahoo.com.cn看是否正常.

浏览器上网, 看是否正常.(注意,浏览器不应设置proxy)


经过测试, 证明Windows XP使用如下工具工作正常.





浏览器: IE6, Netscape 4.72, Netscape 6

Email: OutLook Express, 含 hotmail 和 pop3 邮件的收发.

MSN, 含数据和语音通话.


安全测试


请参照



target=_blank>http://www.cert.org/security-improvement/practices/p060.html

href="http://web.ranum.com/pubs/fwtest/">http://web.ranum.com/pubs/fwtest/



相关话题


RealPlayer的问题


系统完成后, 发现RealPlayer在防火墙后无法听音乐, 总是不停地buffering, 直到timeout.
这是因为默认方式下, RealPlayer8 使用了UDP Port 6970-7170接收数据, 该数据被我们的防火墙无情的挡住了,
由于NAT的存在, 简单地允许这样的数据包也无法保证Client工作正常.



ipfilter 提供了一个proxy给我们, 规则为上面已经列出来了, 但是有关资料显示该proxy只支持古老的 PNM RealAudio方式, RealPlayer G2已经使用 RTSP 方式. 该proxy并不支持.
好在RealPlayer提供与防火墙兼容的模式, 可以设置为只使用TCP Port
7070, 7071, 554 三个端口连接Server, 与我们的防火墙正好吻合. 在防火墙工作正常后, RealPlayer 8 的设置方法是:





启动RealPlayer

选择菜单 View -> Perferences -> Transport

选择Auto-Configure, RealPlayer可以自动为你设置为TCP
Only的方式. 也可以手工设置, 去除UDP的方式, 只用TCP的方式.


其他版本的设置方法, 请参照 target=_blank>http://service.real.com/firewall/adminfw.html



QQ的问题


网上有关QQ问题谈得很多, 我使用的是MSN,
因才对QQ不是很了解, 只能做一下简单的分析. 理论上讲, 通过服务器转发或向外发送一般是没有什么问题的, 问题一般出现在无法正常收到对方以UDP方式发送的消息,
该消息无法通过我们的防火墙.
不过这种说法对防火墙来讲不公平, 增加一条规则允许该UDP的包通过非常简单. 问题实际是在NAT上, 我们使用了192.168.0.0/16这样的内部地址. 当QQ向服务器注册时, 实际使用的是Gateway的地址, 但是如果内部有多个人使用QQ,
服务器也会把这些QQ号码连接到这个IP上, 其他用户根据服务器提供的地址从外部发送UDP包到了Gateway,
Gateway就不知道应该把消息转发给谁. 因此这并不是一个简单的允许数据包通过的问题. 与此相同的问题还有netmeeting. 解决的方法, 一是允许用户全部通过服务器转发, 防火墙能够很好地处理这样的问题. 我相信MSN就是这么做的. 但这需要QQ
service provider的合作, 而且对他们的服务器会有更高的要求. 另一种方法是类似ftp client的解决方式, 在Gateway上增加proxy. 我没有QQ的资料, 不能妄下结论.



FTP的问题


FTP协议



这是一个由于FTP协议所造成的问题, 让我们先看一下FTP协议.
FTP一般需要使用两个端口, 端口21只是一个命令端口, 真正传送数据的时候, 还需要另外一个数据端口. 问题就出现在第二个数据端口上.
打开这个数据端口的时候有两种方式, 一种是passive(PASV command)方式, 由FTP Server端提供一个连接的IP/Port, FTP
Client连接到这个IP/Port上进行数据传输. 另一种是active(PORT command)方式, 由FTP Client提供IP/Port,
再由FTP Server回叫至Client提供的地址. 具体采用哪一种方式, 是由FTP
Client决定的, Client通过PASV或PORT命令通知Server采用什么方式. 正是这样的握手方式, 给Server端和Client端都造成了麻烦. 这个问题的具体描述详见
target=_blank>http://www.daemonnews.org/200109/ftpnat.html



FTP Server



Server端一般不希望使用passive方式, 这种方式要求防火墙动态地打开PASV的端口.
而active方式对于Server的防火墙没有什么特殊的要求. 但是FTP
Server是不能选择的, 除非声明不支持passive方式. 一般的解决方法是, 在防火墙上固定地打开一些端口, 如 15001-19999, 每次通信, FTP
Server软件可以从这些端口中选择一个作为PASV的端口通知FTP Client. 如果你的FTP
Server不支持指定passive端口范围, 你应该考虑更换FTP Server了. 这种方式防火墙需要增加规则



pass in quick on tun0 proto tcp from any to 0/32 port 15000>< 20000
flags S keep state keep frags



FTP Client



根据上面的协议规则, 如果FTP Client采用passive方式, 对于防火墙来讲没有什么特殊的要求, 我们可以把问题留给FTP Server.



好消息是,一般的FTP Client软件都支持passive方式, 我使用的网络蚂蚁(netant), 网际快车(FlashGet)默认方式都是passive,
WS_FTP是可以设置的, 这样防火墙就不需要特殊处理了. Unix下需要设置



FTP_PASSIVE_MODE=yes; export FTP_PASSIVE_MODE



坏消息是, 浏览器的FTP使用的是active方式, 而且好像还不能更改. 不过现在直接使用浏览器FTP的人已经是很少了
------ 我从来就不用浏览器下载.
还有, 有一些FTP站点, 不支持passive方式. 我曾经访问过一些私人的FTP站点, 就无法使用passive下载, 也许是他们在设计防火墙的时候没有考虑吧.



支持active模式可以通过在NAT上增加proxy解决的. Linux通过增加ip_conntrack_ftp解决, ipnat已经完成了这一功能, 我们只需要增加一条规则就可以了.
那就是我前面ipnat.conf中的第一条规则. 该proxy可以还提供反向FTP代理, 用于FTP Server. 可惜的是, 这样有可能造成安全隐患,详见 target=_blank>http://www.false.net/ipfilter/2001_11/0273.html.
我曾经与其他一些ipfilter的使用者讨论过这个问题, 一般认为, 如果gateway兼做对外的FTP Server, 需要对外提供FTP服务的话, 最好还是不要开放这一proxy, 内部用户只允许使用passive方式.
如果仅仅是做一个对外的代理服务器, 即FTP只对内部机器开放, 开放这一proxy应该是安全的.

标签: