- 论坛徽章:
- 0
|
本帖最后由 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
复制代码 |
|