上一节从代码层面来讲解了fwaas的流程,这里通过具体查看iptables规则来说下应用规则的流程:

1.首先通过命令获取当前路由中的规则

  1. #ip netns exec qrouter-[router-uuid] iptables-save -c >> rules

2.查看文件,这里我给定一个实例文件,这里因为我们只关心filter表,其他表去除

  1. # Generated by iptables-save v1.4.21 on Fri May 22 15:59:01 2015
  2. *filter
  3. :INPUT ACCEPT [6425:953808]
  4. :FORWARD ACCEPT [5:408]
  5. :OUTPUT ACCEPT [9:972] #这里往上是三个内置链
  6.  
  7. :neutron-filter-top - [0:0] #这是唯一一个非包装链
  8.  
  9. :neutron-l3-agent-FORWARD - [0:0]
  10. :neutron-l3-agent-INPUT - [0:0]
  11. :neutron-l3-agent-OUTPUT - [0:0]
  12. :neutron-l3-agent-fwaas-defau - [0:0]
  13. :neutron-l3-agent-iv4f7e1ffb5 - [0:0]
  14. :neutron-l3-agent-local - [0:0]
  15. :neutron-l3-agent-ov4f7e1ffb5 - [0:0]
  16. :neutron-openvswi-FORWARD - [0:0]
  17. :neutron-openvswi-INPUT - [0:0]
  18. :neutron-openvswi-OUTPUT - [0:0]
  19. :neutron-openvswi-ia45dd659-2 - [0:0]
  20. :neutron-openvswi-local - [0:0]
  21. :neutron-openvswi-oa45dd659-2 - [0:0]
  22. :neutron-openvswi-sg-chain - [0:0]
  23. :neutron-openvswi-sg-fallback - [0:0]
  24. :neutron-vpn-agen-FORWARD - [0:0]
  25. :neutron-vpn-agen-INPUT - [0:0]
  26. :neutron-vpn-agen-OUTPUT - [0:0]
  27. :neutron-vpn-agen-fwaas-defau - [0:0]
  28. :neutron-vpn-agen-iv4f7e1ffb5 - [0:0]
  29. :neutron-vpn-agen-local - [0:0]
  30. :neutron-vpn-agen-ov4f7e1ffb5 - [0:0] #这里是包装链,包装名称通过os.path.basename(inspect.stack()[-1][1])[:16]获取
  31. [15606:1868567] -A INPUT -j neutron-vpn-agen-INPUT
  32. [15621:1870099] -A INPUT -j neutron-l3-agent-INPUT
  33. [10406:1260231] -A INPUT -j neutron-openvswi-INPUT #往上三个将input包装链作为跳转规则添加到内置input链中
  34. [5:408] -A FORWARD -j neutron-filter-top
  35. [5:408] -A FORWARD -j neutron-vpn-agen-FORWARD
  36. [5:408] -A FORWARD -j neutron-l3-agent-FORWARD
  37. [0:0] -A FORWARD -j neutron-openvswi-FORWARD #往上三个将forward包装链作为跳转规则添加到内置forward链中
  38. [9:972] -A OUTPUT -j neutron-filter-top
  39. [9:972] -A OUTPUT -j neutron-vpn-agen-OUTPUT
  40. [9:972] -A OUTPUT -j neutron-l3-agent-OUTPUT
  41. [0:0] -A OUTPUT -j neutron-openvswi-OUTPUT #往上三个将output包装链作为跳转规则添加到内置output链中
  42. [14:1380] -A neutron-filter-top -j neutron-vpn-agen-local
  43. [14:1380] -A neutron-filter-top -j neutron-l3-agent-local
  44. [0:0] -A neutron-filter-top -j neutron-openvswi-local
  45. [0:0] -A neutron-l3-agent-FORWARD -o qr-+ -j neutron-l3-agent-iv4f7e1ffb5
  46. [0:0] -A neutron-l3-agent-FORWARD -i qr-+ -j neutron-l3-agent-ov4f7e1ffb5 #将neutron-l3-agent-ov4f7e1ffb5链作为跳转规则添加到neutron-l3-agent-FORWARD
  47. [0:0] -A neutron-l3-agent-FORWARD -o qr-+ -j neutron-l3-agent-fwaas-defau
  48. [0:0] -A neutron-l3-agent-FORWARD -i qr-+ -j neutron-l3-agent-fwaas-defau #将neutron-l3-agent-fwaas-defau链作为跳转规则添加到neutron-l3-agent-FORWARD
  49. [0:0] -A neutron-l3-agent-INPUT -d 127.0.0.1/32 -p tcp -m tcp --dport 9697 -j ACCEPT #默认规则
  50.  
  51. [0:0] -A neutron-l3-agent-fwaas-defau -j DROP #neutron-l3-agent-fwaas-defau链中只有一条drop规则
  52. [0:0] -A neutron-l3-agent-iv4f7e1ffb5 -m state --state INVALID -j DROP
  53. [0:0] -A neutron-l3-agent-iv4f7e1ffb5 -m state --state RELATED,ESTABLISHED -j ACCEPT #这两条规则是在初始化neutron-l3-agent-iv4f7e1ffb5链的时候添加的
  54. [0:0] -A neutron-l3-agent-iv4f7e1ffb5 -s 10.10.10.0/24 -d 192.168.1.0/24 -p tcp -j DROP #界面添加的用户规则
  55. [0:0] -A neutron-l3-agent-ov4f7e1ffb5 -m state --state INVALID -j DROP
  56. [0:0] -A neutron-l3-agent-ov4f7e1ffb5 -m state --state RELATED,ESTABLISHED -j ACCEPT #这两条规则是在初始化neutron-l3-agent-ov4f7e1ffb5链的时候添加的
  57. [0:0] -A neutron-l3-agent-ov4f7e1ffb5 -s 10.10.10.0/24 -d 192.168.1.0/24 -p tcp -j DROP #界面添加的用户规则 ,可以看到是同时将界面规则添加到出入链中
  58. [0:0] -A neutron-openvswi-FORWARD -i qg-a45dd659-23 -j neutron-openvswi-sg-chain
  59. [0:0] -A neutron-openvswi-FORWARD -o qg-a45dd659-23 -j neutron-openvswi-sg-chain
  60. [10406:1260231] -A neutron-openvswi-INPUT -j neutron-openvswi-oa45dd659-2
  61. [0:0] -A neutron-openvswi-ia45dd659-2 -m state --state INVALID -j DROP
  62. [0:0] -A neutron-openvswi-ia45dd659-2 -m state --state RELATED,ESTABLISHED -j RETURN
  63. [0:0] -A neutron-openvswi-ia45dd659-2 -s 192.168.1.12/32 -p udp -m udp --sport 67 --dport 68 -j RETURN
  64. [0:0] -A neutron-openvswi-ia45dd659-2 -j neutron-openvswi-sg-fallback
  65. [983:322818] -A neutron-openvswi-oa45dd659-2 -p udp -m udp --sport 68 --dport 67 -j RETURN
  66. [0:0] -A neutron-openvswi-oa45dd659-2 -p tcp -m tcp --dport 22 -j RETURN
  67. [125:41000] -A neutron-openvswi-oa45dd659-2 -p udp -m udp --sport 67 --dport 68 -j DROP
  68. [0:0] -A neutron-openvswi-oa45dd659-2 -m state --state INVALID -j DROP
  69. [0:0] -A neutron-openvswi-oa45dd659-2 -m state --state RELATED,ESTABLISHED -j RETURN
  70. [9298:896413] -A neutron-openvswi-oa45dd659-2 -j neutron-openvswi-sg-fallback
  71. [0:0] -A neutron-openvswi-sg-chain -i qg-a45dd659-23 -j neutron-openvswi-ia45dd659-2
  72. [0:0] -A neutron-openvswi-sg-chain -o qg-a45dd659-23 -j neutron-openvswi-oa45dd659-2
  73. [0:0] -A neutron-openvswi-sg-chain -j ACCEPT
  74. [9298:896413] -A neutron-openvswi-sg-fallback -j DROP
  75. [0:0] -A neutron-vpn-agen-FORWARD -o qr-+ -j neutron-vpn-agen-iv4f7e1ffb5
  76. [0:0] -A neutron-vpn-agen-FORWARD -i qr-+ -j neutron-vpn-agen-ov4f7e1ffb5
  77. [0:0] -A neutron-vpn-agen-FORWARD -o qr-+ -j neutron-vpn-agen-fwaas-defau
  78. [0:0] -A neutron-vpn-agen-FORWARD -i qr-+ -j neutron-vpn-agen-fwaas-defau
  79. [0:0] -A neutron-vpn-agen-INPUT -d 127.0.0.1/32 -p tcp -m tcp --dport 9697 -j ACCEPT
  80. [0:0] -A neutron-vpn-agen-fwaas-defau -j DROP
  81. [0:0] -A neutron-vpn-agen-iv4f7e1ffb5 -m state --state INVALID -j DROP
  82. [0:0] -A neutron-vpn-agen-iv4f7e1ffb5 -m state --state RELATED,ESTABLISHED -j ACCEPT
  83. [0:0] -A neutron-vpn-agen-iv4f7e1ffb5 -s 10.10.10.0/24 -d 192.168.1.0/24 -p tcp -j DROP
  84. [0:0] -A neutron-vpn-agen-ov4f7e1ffb5 -m state --state INVALID -j DROP
  85. [0:0] -A neutron-vpn-agen-ov4f7e1ffb5 -m state --state RELATED,ESTABLISHED -j ACCEPT
  86. [0:0] -A neutron-vpn-agen-ov4f7e1ffb5 -s 10.10.10.0/24 -d 192.168.1.0/24 -p tcp -j DROP
  87. COMMIT
  88. # Completed on Fri May 22 16:48:38 2015

  

3. 代码中应用规则是这样的流程

代码路径:neutron\agent\linux\iptables_manager.py

  1. def _apply_synchronized(self):
  2. """Apply the current in-memory set of iptables rules.
  3.  
  4. This will blow away any rules left over from previous runs of the
  5. same component of Nova, and replace them with our current set of
  6. rules. This happens atomically, thanks to iptables-restore.
  7.  
  8. """
  9. s = [('iptables', self.ipv4)]
  10. if self.use_ipv6:
  11. s += [('ip6tables', self.ipv6)]
  12.  
  13. for cmd, tables in s:
  14. args = ['%s-save' % (cmd,), '-c']
  15. if self.namespace:
  16. args = ['ip', 'netns', 'exec', self.namespace] + args
  17. all_tables = self.execute(args, root_helper=self.root_helper) #将已有的规则保存到all_tables对象中
  18. all_lines = all_tables.split('\n')
  19. # Traverse tables in sorted order for predictable dump output
  20. for table_name in sorted(tables):
  21. table = tables[table_name]
  22. start, end = self._find_table(all_lines, table_name) #查表,实际看下保存的结果就可以很容易的看出他的数据结构了
  23. all_lines[start:end] = self._modify_rules( # 【3.1】重点看下这个方法
  24. all_lines[start:end], table, table_name)
  25.  
  26. args = ['%s-restore' % (cmd,), '-c']
  27. if self.namespace:
  28. args = ['ip', 'netns', 'exec', self.namespace] + args
  29. try:
  30. self.execute(args, process_input='\n'.join(all_lines),
  31. root_helper=self.root_helper) #将更新好的规则重新应用
  32. except RuntimeError as r_error:
  33. with excutils.save_and_reraise_exception():
  34. try:
  35. line_no = int(re.search(
  36. 'iptables-restore: line ([0-9]+?) failed',
  37. str(r_error)).group(1))
  38. context = IPTABLES_ERROR_LINES_OF_CONTEXT
  39. log_start = max(0, line_no - context)
  40. log_end = line_no + context
  41. except AttributeError:
  42. # line error wasn't found, print all lines instead
  43. log_start = 0
  44. log_end = len(all_lines)
  45. log_lines = ('%7d. %s' % (idx, l)
  46. for idx, l in enumerate(
  47. all_lines[log_start:log_end],
  48. log_start + 1)
  49. )
  50. LOG.error(_("IPTablesManager.apply failed to apply the "
  51. "following set of iptables rules:\n%s"),
  52. '\n'.join(log_lines))
  53. LOG.debug(_("IPTablesManager.apply completed with success"))

【3.1】 过滤规则

  1. def _modify_rules(self, current_lines, table, table_name):
  2. # Chains are stored as sets to avoid duplicates.
  3. # Sort the output chains here to make their order predictable.
  4. unwrapped_chains = sorted(table.unwrapped_chains) #排序非包装链,我们知道就只有一个
  5. chains = sorted(table.chains) #排序包装链
  6. remove_chains = table.remove_chains
  7. rules = table.rules
  8. remove_rules = table.remove_rules
  9.  
  10. if not current_lines:
  11. fake_table = ['# Generated by iptables_manager',
  12. '*' + table_name, 'COMMIT',
  13. '# Completed by iptables_manager']
  14. current_lines = fake_table
  15.  
  16. # Fill old_filter with any chains or rules we might have added,
  17. # they could have a [packet:byte] count we want to preserve.
  18. # Fill new_filter with any chains or rules without our name in them.
  19. old_filter, new_filter = [], []
  20. for line in current_lines:
  21. (old_filter if self.wrap_name in line else
  22. new_filter).append(line.strip()) #将原有规则过滤的包数和字节数保存
  23.  
  24. rules_index = self._find_rules_index(new_filter)
  25.  
  26. all_chains = [':%s' % name for name in unwrapped_chains] #添加完内置链后第一个添加非包装链
  27. all_chains += [':%s-%s' % (self.wrap_name, name) for name in chains] #添加包装链
  28.  
  29. # Iterate through all the chains, trying to find an existing
  30. # match.
  31. our_chains = []
  32. for chain in all_chains:
  33. chain_str = str(chain).strip()
  34.  
  35. old = self._find_last_entry(old_filter, chain_str)
  36. if not old:
  37. dup = self._find_last_entry(new_filter, chain_str)
  38. new_filter = [s for s in new_filter if chain_str not in s.strip()]
  39.  
  40. # if no old or duplicates, use original chain
  41. if old or dup:
  42. chain_str = str(old or dup)
  43. else:
  44. # add-on the [packet:bytes]
  45. chain_str += ' - [0:0]'
  46.  
  47. our_chains += [chain_str] #添加所有的自定义链
  48.  
  49. # Iterate through all the rules, trying to find an existing
  50. # match.
  51. our_rules = []
  52. bot_rules = []
  53. for rule in rules: #开始添加规则了
  54. rule_str = str(rule).strip() #查看下IptablesRule对象后,会看到实现了_str__方法,返回经过处理的字符串
  55. # Further down, we weed out duplicates from the bottom of the
  56. # list, so here we remove the dupes ahead of time.
  57.  
  58. old = self._find_last_entry(old_filter, rule_str)
  59. if not old:
  60. dup = self._find_last_entry(new_filter, rule_str)
  61. new_filter = [s for s in new_filter if rule_str not in s.strip()]
  62.  
  63. # if no old or duplicates, use original rule
  64. if old or dup:
  65. rule_str = str(old or dup)
  66. # backup one index so we write the array correctly
  67. if not old:
  68. rules_index -= 1
  69. else:
  70. # add-on the [packet:bytes]
  71. rule_str = '[0:0] ' + rule_str
  72.  
  73. if rule.top:
  74. # rule.top == True means we want this rule to be at the top.
  75. our_rules += [rule_str]
  76. else:
  77. bot_rules += [rule_str]
  78.  
  79. our_rules += bot_rules #直接添加规则。规则之间的逻辑顺序其实在创建规则的时候已经给定了(因为已经给定了这个规则所在的链)
  80.  
  81. new_filter[rules_index:rules_index] = our_rules #替换规则,注意添加完了后文件中的行数变化了
  82. new_filter[rules_index:rules_index] = our_chains #替换链,位置是在规则前面
  83.  
  84. def _strip_packets_bytes(line):
  85. # strip any [packet:byte] counts at start or end of lines
  86. if line.startswith(':'):
  87. # it's a chain, for example, ":neutron-billing - [0:0]"
  88. line = line.split(':')[1]
  89. line = line.split(' - [', 1)[0]
  90. elif line.startswith('['):
  91. # it's a rule, for example, "[0:0] -A neutron-billing..."
  92. line = line.split('] ', 1)[1]
  93. line = line.strip()
  94. return line
  95.  
  96. seen_chains = set()
  97.  
  98. def _weed_out_duplicate_chains(line):
  99. # ignore [packet:byte] counts at end of lines
  100. if line.startswith(':'):
  101. line = _strip_packets_bytes(line)
  102. if line in seen_chains:
  103. return False
  104. else:
  105. seen_chains.add(line)
  106.  
  107. # Leave it alone
  108. return True
  109.  
  110. seen_rules = set()
  111.  
  112. def _weed_out_duplicate_rules(line):
  113. if line.startswith('['):
  114. line = _strip_packets_bytes(line)
  115. if line in seen_rules:
  116. return False
  117. else:
  118. seen_rules.add(line)
  119.  
  120. # Leave it alone
  121. return True
  122.  
  123. def _weed_out_removes(line):
  124. # We need to find exact matches here
  125. if line.startswith(':'):
  126. line = _strip_packets_bytes(line)
  127. for chain in remove_chains:
  128. if chain == line:
  129. remove_chains.remove(chain)
  130. return False
  131. elif line.startswith('['):
  132. line = _strip_packets_bytes(line)
  133. for rule in remove_rules:
  134. rule_str = _strip_packets_bytes(str(rule))
  135. if rule_str == line:
  136. remove_rules.remove(rule)
  137. return False
  138.  
  139. # Leave it alone
  140. return True
  141.  
  142. # We filter duplicates. Go through the chains and rules, letting
  143. # the *last* occurrence take precedence since it could have a
  144. # non-zero [packet:byte] count we want to preserve. We also filter
  145. # out anything in the "remove" list.
  146. new_filter.reverse()
  147. new_filter = [line for line in new_filter
  148. if _weed_out_duplicate_chains(line) and
  149. _weed_out_duplicate_rules(line) and
  150. _weed_out_removes(line)]
  151. new_filter.reverse()
  152.  
  153. # flush lists, just in case we didn't find something
  154. remove_chains.clear()
  155. for rule in remove_rules:
  156. remove_rules.remove(rule) #善后工作
  157.  
  158. return new_filter #返回过滤完的规则列表

  

OpenStack-Neutron-Fwaas-代码【二】的更多相关文章

  1. [转] Neutron FWaaS

    OpenStack Neutron FWaaS 学习 ( by quqi99 ) 作者:张华  发表于:2013-06-24 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息 ...

  2. openstack——neutron网络服务

    一.neutron 介绍:   Neutron 概述 传统的网络管理方式很大程度上依赖于管理员手工配置和维护各种网络硬件设备:而云环境下的网络已经变得非常复杂,特别是在多租户场景里,用户随时都可能需要 ...

  3. 深入浅出新一代云网络——VPC中的那些功能与基于OpenStack Neutron的实现(一)

    VPC的概念与基于vxlan的overlay实现很早就有了,标题中的"新"只是一个和传统网络的相对概念.但从前年开始,不同于以往基础网络架构的新一代SDN网络才真正越来越多的走进国 ...

  4. openstack Neutron分析(3)—— neutron-dhcp-agent源码分析

    1.neutron dhcp3个主要部件分别为什么?2.dhcp模块包含哪些内容?3.Dnsmasq配置文件是如何创建和更新的?4.DHCP agent的信息存放在neutron数据库的哪个表中? 扩 ...

  5. openstack neutron L3 HA

    作者:Liping Mao  发表于:2014-08-20 版权声明:能够随意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 近期Assaf Muller写了一篇关于Neutro ...

  6. OpenStack Neutron 之 Load Balance

    OpenStack Neutron 之 Load Balance 负载均衡(Load Balance)是 OpenStack Neutron 支持的功能之一.负载均衡能够将网络请求分发到多个实际处理请 ...

  7. 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 ...

  8. Openstack Neutron L2 Population

    Why do we need it, whatever it is? VM unicast, multicast and broadcast traffic flow is detailed in m ...

  9. 分享非常有用的Java程序 (关键代码) (二)---列出文件和目录

    原文:分享非常有用的Java程序 (关键代码) (二)---列出文件和目录 File dir = new File("directoryName"); String[] child ...

  10. openstack neutron中涉及的网络设备

    一.openstack neutron网络设备介绍 Bridge(网桥) 用于将两个LAN连接起来,主要靠的MAC地址学习机制.当网桥的Port收到包时会将包的源mac和port ID关联起来记入ma ...

随机推荐

  1. Windows Server 2012设置VMWare以服务方式启动(注销后也可以运行,开机也可以自动运行)

    场景:要用一台服务器(Windows Server 2012),加装了一张双口的千兆网卡,安装一个虚拟机,使用爱快在虚拟机里当做软路由. - 那么问题来了,我这台是只能远程的,如果软路由没启动,怎么办 ...

  2. Face The Right Way [POJ3276] [开关问题]

    题意: 有n头奶牛排成一排,有的朝前(F)有的朝后(B),现在你可以使k头奶牛一次性翻转朝向(n>=k>=1),问你最少的翻转次数和此时对应的k值. Input Line 1: A sin ...

  3. CentOS裸机环境下安装php-7.3.1

    安装步骤如下 安装必要的软件 获取源码 编译安装 安装过程可能遇到的一些问题 编译参数详解 安装步骤如下 安装必要的软件 yum install -y autoconf automake libtoo ...

  4. 需要优化代码的leetcode

    1  关于验证字符串的问题: 2

  5. Python 学习笔记6 变量-元组

    我们在上一篇中了解了变量list(列表), 今天我们来介绍下元组.元组是由括号和逗号,组织起来的一个元素的集合.和list不同的是,它其中的元素是不能被修改的,和其他语言中的常量相类似. 需要注意的是 ...

  6. en-zh(科学技术)science and technology-2

    研究:长期不吃早餐,患心脏病风险增加87% Skipping breakfast could raise risk of heart disease by 87% Skipping breakfast ...

  7. VUE-005-axios常用请求参数设置方法

    在前后端分离的开发过程中,经常使用 axios 进行后端接口的访问. 个人习惯常用的请求参数设置方法如下所示: // POST方法:data在请求体中 addRow(data) { return th ...

  8. css阴影框

    选中div浮动的阴影框.example-card:hover {box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);transform: translate3d(0, ...

  9. 【mybatis】mybatis中 <if test=>等于的条件怎么写

  10. app启动过程

    调用main函数之前: App开始启动后,系统首先加载可执行文件(自身App的所有.o文件的集合),然后加载动态链接库dyld.交由 ImageLoader 读取 image,其中包含了我们的类.方法 ...