OpenStack-Neutron-Fwaas-代码【二】
上一节从代码层面来讲解了fwaas的流程,这里通过具体查看iptables规则来说下应用规则的流程:
1.首先通过命令获取当前路由中的规则
- #ip netns exec qrouter-[router-uuid] iptables-save -c >> rules
2.查看文件,这里我给定一个实例文件,这里因为我们只关心filter表,其他表去除
- # Generated by iptables-save v1.4.21 on Fri May 22 15:59:01 2015
- *filter
- :INPUT ACCEPT [6425:953808]
- :FORWARD ACCEPT [5:408]
- :OUTPUT ACCEPT [9:972] #这里往上是三个内置链
- :neutron-filter-top - [0:0] #这是唯一一个非包装链
- :neutron-l3-agent-FORWARD - [0:0]
- :neutron-l3-agent-INPUT - [0:0]
- :neutron-l3-agent-OUTPUT - [0:0]
- :neutron-l3-agent-fwaas-defau - [0:0]
- :neutron-l3-agent-iv4f7e1ffb5 - [0:0]
- :neutron-l3-agent-local - [0:0]
- :neutron-l3-agent-ov4f7e1ffb5 - [0:0]
- :neutron-openvswi-FORWARD - [0:0]
- :neutron-openvswi-INPUT - [0:0]
- :neutron-openvswi-OUTPUT - [0:0]
- :neutron-openvswi-ia45dd659-2 - [0:0]
- :neutron-openvswi-local - [0:0]
- :neutron-openvswi-oa45dd659-2 - [0:0]
- :neutron-openvswi-sg-chain - [0:0]
- :neutron-openvswi-sg-fallback - [0:0]
- :neutron-vpn-agen-FORWARD - [0:0]
- :neutron-vpn-agen-INPUT - [0:0]
- :neutron-vpn-agen-OUTPUT - [0:0]
- :neutron-vpn-agen-fwaas-defau - [0:0]
- :neutron-vpn-agen-iv4f7e1ffb5 - [0:0]
- :neutron-vpn-agen-local - [0:0]
- :neutron-vpn-agen-ov4f7e1ffb5 - [0:0] #这里是包装链,包装名称通过os.path.basename(inspect.stack()[-1][1])[:16]获取
- [15606:1868567] -A INPUT -j neutron-vpn-agen-INPUT
- [15621:1870099] -A INPUT -j neutron-l3-agent-INPUT
- [10406:1260231] -A INPUT -j neutron-openvswi-INPUT #往上三个将input包装链作为跳转规则添加到内置input链中
- [5:408] -A FORWARD -j neutron-filter-top
- [5:408] -A FORWARD -j neutron-vpn-agen-FORWARD
- [5:408] -A FORWARD -j neutron-l3-agent-FORWARD
- [0:0] -A FORWARD -j neutron-openvswi-FORWARD #往上三个将forward包装链作为跳转规则添加到内置forward链中
- [9:972] -A OUTPUT -j neutron-filter-top
- [9:972] -A OUTPUT -j neutron-vpn-agen-OUTPUT
- [9:972] -A OUTPUT -j neutron-l3-agent-OUTPUT
- [0:0] -A OUTPUT -j neutron-openvswi-OUTPUT #往上三个将output包装链作为跳转规则添加到内置output链中
- [14:1380] -A neutron-filter-top -j neutron-vpn-agen-local
- [14:1380] -A neutron-filter-top -j neutron-l3-agent-local
- [0:0] -A neutron-filter-top -j neutron-openvswi-local
- [0:0] -A neutron-l3-agent-FORWARD -o qr-+ -j neutron-l3-agent-iv4f7e1ffb5
- [0:0] -A neutron-l3-agent-FORWARD -i qr-+ -j neutron-l3-agent-ov4f7e1ffb5 #将neutron-l3-agent-ov4f7e1ffb5链作为跳转规则添加到neutron-l3-agent-FORWARD
- [0:0] -A neutron-l3-agent-FORWARD -o qr-+ -j neutron-l3-agent-fwaas-defau
- [0:0] -A neutron-l3-agent-FORWARD -i qr-+ -j neutron-l3-agent-fwaas-defau #将neutron-l3-agent-fwaas-defau链作为跳转规则添加到neutron-l3-agent-FORWARD
- [0:0] -A neutron-l3-agent-INPUT -d 127.0.0.1/32 -p tcp -m tcp --dport 9697 -j ACCEPT #默认规则
- [0:0] -A neutron-l3-agent-fwaas-defau -j DROP #neutron-l3-agent-fwaas-defau链中只有一条drop规则
- [0:0] -A neutron-l3-agent-iv4f7e1ffb5 -m state --state INVALID -j DROP
- [0:0] -A neutron-l3-agent-iv4f7e1ffb5 -m state --state RELATED,ESTABLISHED -j ACCEPT #这两条规则是在初始化neutron-l3-agent-iv4f7e1ffb5链的时候添加的
- [0:0] -A neutron-l3-agent-iv4f7e1ffb5 -s 10.10.10.0/24 -d 192.168.1.0/24 -p tcp -j DROP #界面添加的用户规则
- [0:0] -A neutron-l3-agent-ov4f7e1ffb5 -m state --state INVALID -j DROP
- [0:0] -A neutron-l3-agent-ov4f7e1ffb5 -m state --state RELATED,ESTABLISHED -j ACCEPT #这两条规则是在初始化neutron-l3-agent-ov4f7e1ffb5链的时候添加的
- [0:0] -A neutron-l3-agent-ov4f7e1ffb5 -s 10.10.10.0/24 -d 192.168.1.0/24 -p tcp -j DROP #界面添加的用户规则 ,可以看到是同时将界面规则添加到出入链中
- [0:0] -A neutron-openvswi-FORWARD -i qg-a45dd659-23 -j neutron-openvswi-sg-chain
- [0:0] -A neutron-openvswi-FORWARD -o qg-a45dd659-23 -j neutron-openvswi-sg-chain
- [10406:1260231] -A neutron-openvswi-INPUT -j neutron-openvswi-oa45dd659-2
- [0:0] -A neutron-openvswi-ia45dd659-2 -m state --state INVALID -j DROP
- [0:0] -A neutron-openvswi-ia45dd659-2 -m state --state RELATED,ESTABLISHED -j RETURN
- [0:0] -A neutron-openvswi-ia45dd659-2 -s 192.168.1.12/32 -p udp -m udp --sport 67 --dport 68 -j RETURN
- [0:0] -A neutron-openvswi-ia45dd659-2 -j neutron-openvswi-sg-fallback
- [983:322818] -A neutron-openvswi-oa45dd659-2 -p udp -m udp --sport 68 --dport 67 -j RETURN
- [0:0] -A neutron-openvswi-oa45dd659-2 -p tcp -m tcp --dport 22 -j RETURN
- [125:41000] -A neutron-openvswi-oa45dd659-2 -p udp -m udp --sport 67 --dport 68 -j DROP
- [0:0] -A neutron-openvswi-oa45dd659-2 -m state --state INVALID -j DROP
- [0:0] -A neutron-openvswi-oa45dd659-2 -m state --state RELATED,ESTABLISHED -j RETURN
- [9298:896413] -A neutron-openvswi-oa45dd659-2 -j neutron-openvswi-sg-fallback
- [0:0] -A neutron-openvswi-sg-chain -i qg-a45dd659-23 -j neutron-openvswi-ia45dd659-2
- [0:0] -A neutron-openvswi-sg-chain -o qg-a45dd659-23 -j neutron-openvswi-oa45dd659-2
- [0:0] -A neutron-openvswi-sg-chain -j ACCEPT
- [9298:896413] -A neutron-openvswi-sg-fallback -j DROP
- [0:0] -A neutron-vpn-agen-FORWARD -o qr-+ -j neutron-vpn-agen-iv4f7e1ffb5
- [0:0] -A neutron-vpn-agen-FORWARD -i qr-+ -j neutron-vpn-agen-ov4f7e1ffb5
- [0:0] -A neutron-vpn-agen-FORWARD -o qr-+ -j neutron-vpn-agen-fwaas-defau
- [0:0] -A neutron-vpn-agen-FORWARD -i qr-+ -j neutron-vpn-agen-fwaas-defau
- [0:0] -A neutron-vpn-agen-INPUT -d 127.0.0.1/32 -p tcp -m tcp --dport 9697 -j ACCEPT
- [0:0] -A neutron-vpn-agen-fwaas-defau -j DROP
- [0:0] -A neutron-vpn-agen-iv4f7e1ffb5 -m state --state INVALID -j DROP
- [0:0] -A neutron-vpn-agen-iv4f7e1ffb5 -m state --state RELATED,ESTABLISHED -j ACCEPT
- [0:0] -A neutron-vpn-agen-iv4f7e1ffb5 -s 10.10.10.0/24 -d 192.168.1.0/24 -p tcp -j DROP
- [0:0] -A neutron-vpn-agen-ov4f7e1ffb5 -m state --state INVALID -j DROP
- [0:0] -A neutron-vpn-agen-ov4f7e1ffb5 -m state --state RELATED,ESTABLISHED -j ACCEPT
- [0:0] -A neutron-vpn-agen-ov4f7e1ffb5 -s 10.10.10.0/24 -d 192.168.1.0/24 -p tcp -j DROP
- COMMIT
- # Completed on Fri May 22 16:48:38 2015
3. 代码中应用规则是这样的流程
代码路径:neutron\agent\linux\iptables_manager.py
- def _apply_synchronized(self):
- """Apply the current in-memory set of iptables rules.
- This will blow away any rules left over from previous runs of the
- same component of Nova, and replace them with our current set of
- rules. This happens atomically, thanks to iptables-restore.
- """
- s = [('iptables', self.ipv4)]
- if self.use_ipv6:
- s += [('ip6tables', self.ipv6)]
- for cmd, tables in s:
- args = ['%s-save' % (cmd,), '-c']
- if self.namespace:
- args = ['ip', 'netns', 'exec', self.namespace] + args
- all_tables = self.execute(args, root_helper=self.root_helper) #将已有的规则保存到all_tables对象中
- all_lines = all_tables.split('\n')
- # Traverse tables in sorted order for predictable dump output
- for table_name in sorted(tables):
- table = tables[table_name]
- start, end = self._find_table(all_lines, table_name) #查表,实际看下保存的结果就可以很容易的看出他的数据结构了
- all_lines[start:end] = self._modify_rules( # 【3.1】重点看下这个方法
- all_lines[start:end], table, table_name)
- args = ['%s-restore' % (cmd,), '-c']
- if self.namespace:
- args = ['ip', 'netns', 'exec', self.namespace] + args
- try:
- self.execute(args, process_input='\n'.join(all_lines),
- root_helper=self.root_helper) #将更新好的规则重新应用
- except RuntimeError as r_error:
- with excutils.save_and_reraise_exception():
- try:
- line_no = int(re.search(
- 'iptables-restore: line ([0-9]+?) failed',
- str(r_error)).group(1))
- context = IPTABLES_ERROR_LINES_OF_CONTEXT
- log_start = max(0, line_no - context)
- log_end = line_no + context
- except AttributeError:
- # line error wasn't found, print all lines instead
- log_start = 0
- log_end = len(all_lines)
- log_lines = ('%7d. %s' % (idx, l)
- for idx, l in enumerate(
- all_lines[log_start:log_end],
- log_start + 1)
- )
- LOG.error(_("IPTablesManager.apply failed to apply the "
- "following set of iptables rules:\n%s"),
- '\n'.join(log_lines))
- LOG.debug(_("IPTablesManager.apply completed with success"))
【3.1】 过滤规则
- def _modify_rules(self, current_lines, table, table_name):
- # Chains are stored as sets to avoid duplicates.
- # Sort the output chains here to make their order predictable.
- unwrapped_chains = sorted(table.unwrapped_chains) #排序非包装链,我们知道就只有一个
- chains = sorted(table.chains) #排序包装链
- remove_chains = table.remove_chains
- rules = table.rules
- remove_rules = table.remove_rules
- if not current_lines:
- fake_table = ['# Generated by iptables_manager',
- '*' + table_name, 'COMMIT',
- '# Completed by iptables_manager']
- current_lines = fake_table
- # Fill old_filter with any chains or rules we might have added,
- # they could have a [packet:byte] count we want to preserve.
- # Fill new_filter with any chains or rules without our name in them.
- old_filter, new_filter = [], []
- for line in current_lines:
- (old_filter if self.wrap_name in line else
- new_filter).append(line.strip()) #将原有规则过滤的包数和字节数保存
- rules_index = self._find_rules_index(new_filter)
- all_chains = [':%s' % name for name in unwrapped_chains] #添加完内置链后第一个添加非包装链
- all_chains += [':%s-%s' % (self.wrap_name, name) for name in chains] #添加包装链
- # Iterate through all the chains, trying to find an existing
- # match.
- our_chains = []
- for chain in all_chains:
- chain_str = str(chain).strip()
- old = self._find_last_entry(old_filter, chain_str)
- if not old:
- dup = self._find_last_entry(new_filter, chain_str)
- new_filter = [s for s in new_filter if chain_str not in s.strip()]
- # if no old or duplicates, use original chain
- if old or dup:
- chain_str = str(old or dup)
- else:
- # add-on the [packet:bytes]
- chain_str += ' - [0:0]'
- our_chains += [chain_str] #添加所有的自定义链
- # Iterate through all the rules, trying to find an existing
- # match.
- our_rules = []
- bot_rules = []
- for rule in rules: #开始添加规则了
- rule_str = str(rule).strip() #查看下IptablesRule对象后,会看到实现了_str__方法,返回经过处理的字符串
- # Further down, we weed out duplicates from the bottom of the
- # list, so here we remove the dupes ahead of time.
- old = self._find_last_entry(old_filter, rule_str)
- if not old:
- dup = self._find_last_entry(new_filter, rule_str)
- new_filter = [s for s in new_filter if rule_str not in s.strip()]
- # if no old or duplicates, use original rule
- if old or dup:
- rule_str = str(old or dup)
- # backup one index so we write the array correctly
- if not old:
- rules_index -= 1
- else:
- # add-on the [packet:bytes]
- rule_str = '[0:0] ' + rule_str
- if rule.top:
- # rule.top == True means we want this rule to be at the top.
- our_rules += [rule_str]
- else:
- bot_rules += [rule_str]
- our_rules += bot_rules #直接添加规则。规则之间的逻辑顺序其实在创建规则的时候已经给定了(因为已经给定了这个规则所在的链)
- new_filter[rules_index:rules_index] = our_rules #替换规则,注意添加完了后文件中的行数变化了
- new_filter[rules_index:rules_index] = our_chains #替换链,位置是在规则前面
- def _strip_packets_bytes(line):
- # strip any [packet:byte] counts at start or end of lines
- if line.startswith(':'):
- # it's a chain, for example, ":neutron-billing - [0:0]"
- line = line.split(':')[1]
- line = line.split(' - [', 1)[0]
- elif line.startswith('['):
- # it's a rule, for example, "[0:0] -A neutron-billing..."
- line = line.split('] ', 1)[1]
- line = line.strip()
- return line
- seen_chains = set()
- def _weed_out_duplicate_chains(line):
- # ignore [packet:byte] counts at end of lines
- if line.startswith(':'):
- line = _strip_packets_bytes(line)
- if line in seen_chains:
- return False
- else:
- seen_chains.add(line)
- # Leave it alone
- return True
- seen_rules = set()
- def _weed_out_duplicate_rules(line):
- if line.startswith('['):
- line = _strip_packets_bytes(line)
- if line in seen_rules:
- return False
- else:
- seen_rules.add(line)
- # Leave it alone
- return True
- def _weed_out_removes(line):
- # We need to find exact matches here
- if line.startswith(':'):
- line = _strip_packets_bytes(line)
- for chain in remove_chains:
- if chain == line:
- remove_chains.remove(chain)
- return False
- elif line.startswith('['):
- line = _strip_packets_bytes(line)
- for rule in remove_rules:
- rule_str = _strip_packets_bytes(str(rule))
- if rule_str == line:
- remove_rules.remove(rule)
- return False
- # Leave it alone
- return True
- # We filter duplicates. Go through the chains and rules, letting
- # the *last* occurrence take precedence since it could have a
- # non-zero [packet:byte] count we want to preserve. We also filter
- # out anything in the "remove" list.
- new_filter.reverse()
- new_filter = [line for line in new_filter
- if _weed_out_duplicate_chains(line) and
- _weed_out_duplicate_rules(line) and
- _weed_out_removes(line)]
- new_filter.reverse()
- # flush lists, just in case we didn't find something
- remove_chains.clear()
- for rule in remove_rules:
- remove_rules.remove(rule) #善后工作
- return new_filter #返回过滤完的规则列表
OpenStack-Neutron-Fwaas-代码【二】的更多相关文章
- [转] Neutron FWaaS
OpenStack Neutron FWaaS 学习 ( by quqi99 ) 作者:张华 发表于:2013-06-24 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息 ...
- openstack——neutron网络服务
一.neutron 介绍: Neutron 概述 传统的网络管理方式很大程度上依赖于管理员手工配置和维护各种网络硬件设备:而云环境下的网络已经变得非常复杂,特别是在多租户场景里,用户随时都可能需要 ...
- 深入浅出新一代云网络——VPC中的那些功能与基于OpenStack Neutron的实现(一)
VPC的概念与基于vxlan的overlay实现很早就有了,标题中的"新"只是一个和传统网络的相对概念.但从前年开始,不同于以往基础网络架构的新一代SDN网络才真正越来越多的走进国 ...
- openstack Neutron分析(3)—— neutron-dhcp-agent源码分析
1.neutron dhcp3个主要部件分别为什么?2.dhcp模块包含哪些内容?3.Dnsmasq配置文件是如何创建和更新的?4.DHCP agent的信息存放在neutron数据库的哪个表中? 扩 ...
- openstack neutron L3 HA
作者:Liping Mao 发表于:2014-08-20 版权声明:能够随意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 近期Assaf Muller写了一篇关于Neutro ...
- OpenStack Neutron 之 Load Balance
OpenStack Neutron 之 Load Balance 负载均衡(Load Balance)是 OpenStack Neutron 支持的功能之一.负载均衡能够将网络请求分发到多个实际处理请 ...
- Openstack Neutron OVS ARP Responder
ARP – Why do we need it? In any environment, be it the physical data-center, your home, or a virtual ...
- Openstack Neutron L2 Population
Why do we need it, whatever it is? VM unicast, multicast and broadcast traffic flow is detailed in m ...
- 分享非常有用的Java程序 (关键代码) (二)---列出文件和目录
原文:分享非常有用的Java程序 (关键代码) (二)---列出文件和目录 File dir = new File("directoryName"); String[] child ...
- openstack neutron中涉及的网络设备
一.openstack neutron网络设备介绍 Bridge(网桥) 用于将两个LAN连接起来,主要靠的MAC地址学习机制.当网桥的Port收到包时会将包的源mac和port ID关联起来记入ma ...
随机推荐
- Windows Server 2012设置VMWare以服务方式启动(注销后也可以运行,开机也可以自动运行)
场景:要用一台服务器(Windows Server 2012),加装了一张双口的千兆网卡,安装一个虚拟机,使用爱快在虚拟机里当做软路由. - 那么问题来了,我这台是只能远程的,如果软路由没启动,怎么办 ...
- Face The Right Way [POJ3276] [开关问题]
题意: 有n头奶牛排成一排,有的朝前(F)有的朝后(B),现在你可以使k头奶牛一次性翻转朝向(n>=k>=1),问你最少的翻转次数和此时对应的k值. Input Line 1: A sin ...
- CentOS裸机环境下安装php-7.3.1
安装步骤如下 安装必要的软件 获取源码 编译安装 安装过程可能遇到的一些问题 编译参数详解 安装步骤如下 安装必要的软件 yum install -y autoconf automake libtoo ...
- 需要优化代码的leetcode
1 关于验证字符串的问题: 2
- Python 学习笔记6 变量-元组
我们在上一篇中了解了变量list(列表), 今天我们来介绍下元组.元组是由括号和逗号,组织起来的一个元素的集合.和list不同的是,它其中的元素是不能被修改的,和其他语言中的常量相类似. 需要注意的是 ...
- en-zh(科学技术)science and technology-2
研究:长期不吃早餐,患心脏病风险增加87% Skipping breakfast could raise risk of heart disease by 87% Skipping breakfast ...
- VUE-005-axios常用请求参数设置方法
在前后端分离的开发过程中,经常使用 axios 进行后端接口的访问. 个人习惯常用的请求参数设置方法如下所示: // POST方法:data在请求体中 addRow(data) { return th ...
- css阴影框
选中div浮动的阴影框.example-card:hover {box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);transform: translate3d(0, ...
- 【mybatis】mybatis中 <if test=>等于的条件怎么写
- app启动过程
调用main函数之前: App开始启动后,系统首先加载可执行文件(自身App的所有.o文件的集合),然后加载动态链接库dyld.交由 ImageLoader 读取 image,其中包含了我们的类.方法 ...