1个ipfw规则脚本(feebsd+ipfw+dummynet+http透明代理)
本帖最后由 kkkggg 于 2013-11-21 17:01 编辑备忘。
dummynet的动态带宽分配功能很好用。在共享上网的环境下,要限制某些上传流量过大堵塞网络的ip的时候,按ip数动态分配带宽比按优先级或分配固定带宽的方式要更有效。
下面先简单描述一下数据包经过本防火墙规则匹配的流程,方便理清规则制定思路。复杂的地方在于本规则同时使用了透明代理和单ip流量控制以及状态规则。
以下规则适用于系统参数net.inet.ip.fw.one_pass为1时的情况。即数据包只在同一方向放行一次。
如果把数据包按经过接口方向划分类别的话,ipfw规则主要有in和out两大方向,再乘以接口数就等于数据包接口方向类型总数。每种类型的数据包只匹配于同种类型的规则(一条规则可能属于多种类型)。比方说通常一个数据包从内网传输到外网被看做是经过一个方向,但实际上这个数据包要至少匹配ipfw规则中的两种规则:内网in方向和外网out两种规则。
一般情况下(有一块内网网卡,一块外网网卡)的ipfw规则按接口方向分为6类
环路接口in
环路接口out
内网接口in
外网接口out
外网接口in
内网接口out
#环路接口in
放行所有数据包
#环路接口out
放行所有数据包
#内网接口in
拒绝指定的数据包
check-state
skipto跳转需要放行并进行上行流量控制的数据包到拒绝规则后面,并加上keep-state
拒绝未匹配到的数据包
动态单个ip上行流量控制(因为涉及http代理,所以在这里进行每个ip上行流量控制。因为在外网接口那里已经分不出经过代理的http数据包原始源ip,无法很好的为每个ip分配带宽)
#外网接口out
skipto跳转不需要http代理的数据包到fwd规则后面
fwd重定向访问http端口的数据包到本地http代理服务端口
nat源地址转换
#外网接口in
拒绝指定的数据包
nat目的地址转换
#内网接口out
check-stat
放行所有数据包
制定规则时,可以先按各个方向分别制定规则,然后把各个方向的规则根据优先级顺序拼在一起。规则匹配次数不一样,对CPU造成的负荷不一样。所以应该把匹配最频繁、最多数量的数据包的规则尽量靠前。check-state规则在每个方向上都进行匹配,要特别小心。由于本规则在内网in和外网out方向均有跳转语句,且跳转到的规则动作不同。要想两个这方向的规则互不影响的话,要把外网out规则放到前面,check-state放到中间,带状态的内网in规则放到后面。
下面是规则代码,nat用的是libalias#定义网络接口名变量
ext_if="tun0"
int_if="xl0"
lan_net="10.0.0.0/22"
#定义细分类端口变量(规则中不直接引用此类变量名,只为方便标识,后面会合并到主要分类中)
general_tcp_ports="25,53,110,143,443,636,993,995" #smtp,dns,pop3,imap,https,ldap,ipops,imaps
general_udp_ports="53,123" #dns,ntp
msn_tcp_ports="569,1503,1863,5061,7001"
government_tcp_ports="5222,5678,7002,7888,8980" #某些政府服务器端口
working_tcp_ports="212,1433,3306" #,mssql,mysql
qq_udp_ports="8000"
#定义主要分类端口变量(会在规则中直接引用的变量名)
http_proxy_ports="80"
#用户组1额外开放的端口
group1_tcp_ports="22,6618,8000,8080,9898" #ssh,酷狗,手机软件,手机软件,手机软件
group1_udp_ports="3545,6618" #酷狗,酷狗
#定义特殊应用1的目的端口
special_app1_tcp_ports="8080" #手机QQ
#合并先前的细类,注意引号内不能有空格,一条规则端口参数项最多为30个
permitted_tcp_ports_1="$general_tcp_ports,$msn_tcp_ports,$government_tcp_ports,$working_tcp_ports"
permitted_udp_ports_1="$general_udp_ports,$qq_udp_ports"
#本机开启服务端口
localhost_tcp_service="3000,3128,10000" #ntop,squid,webmin
localhost_udp_service="53,123" #dns,dhcp,ntp
#清空系统中已有的规则
ipfw -q flush
ipfw -q table all flush
ipfw -q pipe flush
#定义ip地址表
#定义私有网络地址表priv_net
ipfw table 5 add 127.0.0.0/8
ipfw table 5 add 192.168.0.0/16
ipfw table 5 add 172.16.0.0/12
ipfw table 5 add 10.0.0.0/8
#定义拒绝的外网源地址
ipfw table 10 add 200.0.0.1/32 #sample
#定义无网络权限客户机ip
ipfw table 15 add 10.0.1.25/32 #xxx
#定义拒绝访问目的地址ip
ipfw table 20 add 220.164.144.207
#无限制端口服务器地址
ipfw table 25 add 202.105.113.38/32
#定义允许访问所有tcp端口的目的地址(http端口数据包依然要通过代理服务)
ipfw table 30 add 116.228.70.245/32 #圆通物流
#定义高访问权限客户机ip地址(除了不允许访问的外网ip不能访问外)
ipfw table 35 add 10.0.0.9/32 #test
ipfw table 35 add 10.0.0.63/32 #voip
#定义不经过squid代理,直接访问的服务器ip地址
ipfw table 40 add 202.128.247.44/32 #海关物品编码查询
ipfw table 40 add 58.61.142.185/32 #顺丰快递查单
ipfw table 40 add 14.17.29.0/24 #qq离线文件服务器
ipfw table 40 add 113.108.0.0/19 #qq离线文件服务器
ipfw table 40 add 113.142.0.0/19 #qq离线文件服务器
ipfw table 40 add 115.236.128.0/19 #qq离线文件服务器
ipfw table 40 add 124.115.10.0/24 #qq离线文件服务器
ipfw table 40 add 182.131.0.0/19 #qq离线文件服务器
ipfw table 40 add 182.140.128.0/19 #qq离线文件服务器
ipfw table 40 add 119.146.200.0/27 #网易云阅读
#定义不经过squid代理的客户机ip
ipfw table 45 add 10.0.1.64/32 #xxx
#定义访问与$special_app1_tcp_ports端口对应的地址
ipfw table 50 add 121.14.64.0/18 #手机QQ
#定义用户组group1地址
ipfw table 55 add 10.0.0.3/32 #xxx
ipfw table 55 add 10.0.1.64/32 #xxx
#规则开始
#允许本地lo0接口双向访问
ipfw -q add 100 allow all from any to any via lo0
#放行发往内网的数据包
ipfw -q add 200 allow all from any to $lan_net out xmit $int_if
#丢弃指定外网ip发过来的数据包
ipfw -q add 300 deny ip from table\(10\) to any in recv $ext_if
#拒绝无网络权限客户机ip
ipfw -q add 400 reject ip from table\(15\) to any in recv $int_if
#丢弃ip分片包
ipfw -q add 500 deny ip from any to any in frag
#拒绝欺骗数据包进入
ipfw -q add 600 deny ip from me to any in
#ipfw -q add 700 deny ip from table\(5\) to any in recv $ext_if
#NAT接收到的外网接口的数据包
ipfw -q nat 1 config if $ext_if #nat绑定到外网接口
ipfw -q add 999 nat 1 ip from any to any in recv $ext_if #nat从外网来的数据包
#放行管理员客户机
#ipfw -q add 1100 allow ip from 10.0.1.10/32 to any in
#ipfw -q add 1200 allow ip from any to 10.0.1.10/32 out
#允许内网ssh连接本机(没使用状态规则,避免刷新规则时断开连接)
ipfw -q add 1300 allow tcp from any to me 22 in recv $int_if
#ipfw -q add 1400 allow tcp from me 22 to any out xmit $int_if
#允许本机dhcp服务
ipfw -q add 1500 allow udp from any 68 to any 67 in recv $int_if
#ipfw -q add 1600 allow udp from me 67 to any 68 out xmit $int_if
#让不使用http代理的数据包跳过下面的2999转发规则
ipfw -q add 1700 skipto 3999 tcp from any to table\(25\) out recv $int_if #无限制外网ip
ipfw -q add 1800 skipto 3999 tcp from table\(35\) to any out recv $int_if #无限制用户
ipfw -q add 1900 skipto 3999 tcp from any to table\(40\) $http_proxy_ports out recv $int_if #访问指定不使用http代理的服务器地址
ipfw -q add 2000 skipto 3999 tcp from table\(45\) to any $http_proxy_ports out recv $int_if #指定不使用http代理的客户机
#转发从内网接口进入的要出去的端口为$http_proxy_ports的非本机数据包到本机的3128端口(squid代理)
ipfw -q add 2999 fwd 127.0.0.1,3128 tcp from $lan_net to not me $http_proxy_ports out recv $int_if
#NAT要从外网接口出去的数据包
ipfw -q add 3999 nat 1 ip from $lan_net to any out xmit $ext_if
#状态检查
ipfw -q add 4999 check-state
#拒绝访问指定目的地址
ipfw -q add 5100 reject ip from any to table\(20\) in recv $int_if
#允许指定放行的上行数据跳到规则10100进行流量控制
#放行访问指定本地服务端口的数据包(带状态)
ipfw -q add 5200 skipto 10100 udp from any to me $localhost_udp_service in recv $int_if keep-state
ipfw -q add 5300 skipto 10100 tcp from any to me $localhost_tcp_service in setup recv $int_if keep-state
#放行访问任意端口的指定服务器地址
ipfw -q add 5400 skipto 10100 ip from any to table\(25\) in recv $int_if keep-state
#放行内网进入,访问网页代理端口$http_proxy_ports的数据包
ipfw -q add 5500 skipto 10100 tcp from any to any $http_proxy_ports in recv $int_if
#放行内网进入,$permitted_tcp_ports_1指定tcp端口的数据包
ipfw -q add 5600 skipto 10100 tcp from any to any $permitted_tcp_ports_1 in setup recv $int_if keep-state
#放行内网进入,$permitted_udp_ports_1指定udp端口的数据包
ipfw -q add 5700 skipto 10100 udp from any to any $permitted_udp_ports_1 in recv $int_if keep-state
#允许访问所有tcp端口的指定目的地址(http依然要通过代理)
ipfw -q add 5800 skipto 10100 tcp from any to table\(30\) in setup recv $int_if keep-state
#放行高访问权限客户机
ipfw -q add 5900 skipto 10100 ip from table\(35\) to any in recv $int_if keep-state
#放行指定group1用户组指定tcp端口的数据包
ipfw -q add 6000 skipto 10100 tcp from table\(55\) to any $group1_tcp_ports in setup recv $int_if keep-state
#放行指定group1用户组指定udp端口的数据包
ipfw -q add 6100 skipto 10100 udp from table\(55\) to any $group1_udp_ports in recv $int_if keep-state
#放行访问特殊应用1目的地址和tcp端口的数据包
ipfw -q add 6200 skipto 10100 tcp from any to table\(50\) $special_app1_tcp_ports in setup recv $int_if keep-state #手机QQ
#放行icmp
ipfw -q add 6300 skipto 10100 icmp from any to any in recv $int_if keep-state
#拒绝以上规则未匹配到的内网数据包并返馈回源地址
ipfw -q add 9999 reject ip from $lan_net to any in recv $int_if
#流量控制(包括http代理在内的本机外出数据包没有到达这里的流量控制规则)
#内网接口上绑定队列
ipfw -q add 10100 queue 1 ip from $lan_net to not me in recv $int_if
ipfw -q add 10200 queue 1 tcp from $lan_net to me 3128 in recv $int_if #直接访问本机http代理的数据包
#为队列指定pipe下,设定源地址匹配掩码,按实时ip数平分带宽
ipfw -q queue 1 config pipe 1 mask src-ip 0x000003ff
#设定管道带宽(adsl上传带宽本应为500Kbit左右,但要为本机发出的数据包留出部分带宽,否则http代理可能无法正常工作)
ipfw -q pipe 1 config bw 420Kbit/s
#最后一条
ipfw -q add 65000 allow ip from any to any
页:
[1]