浮动IP端口转发以支持端口范围

https://blueprints.launchpad.net/neutron/+spec/floatingips-portforwarding-ranges

在NAT中使用端口范围可以简化规则创建过程,因为它用一个条目代替了iptables中的许多条目。此外,一些用户在请求具有一些端口暴露到互联网的虚拟机时,更喜欢请求暴露一个端口范围,以避免针对网络配置向操作员提出许多请求。因此,他们通常会请求一部分外部端口来部署他们的应用程序,以便他们能够在不联系任何人或在OpenStack中配置的情况下,随时选择和更改他们想要的端口。

此外,FTP、视频会议系统、流媒体等应用程序使用多个端口(顺序端口)。

因此,在一个配置中启用所有这些(请求/需要的端口范围)会更容易。

问题描述

  • 目前,如果用户想要创建涵盖多个端口的NAT规则,他/她需要逐个创建它们,在某些用例中这很繁琐。

  • 通过iptables [1](和其他网络系统/应用程序)配置NAT时,操作员可以在配置规则时使用端口范围;因此,网络工程师在他们的NAT配置中使用端口范围是很自然的。

提议的变更

更改浮动IP端口转发API,以允许使用端口范围来创建NAT规则。更改如下所示。今天,当用户创建端口转发规则时,他/她通过API或CLI创建一个规则,并发送一个JSON,例如

{
  "port_forwarding": {
    "protocol": "tcp",
    "internal_ip_address": "172.16.0.7",
    "internal_port": 80,
    "internal_port_id": "b67a7746-dc69-45b4-9b84-bb229fe198a0",
    "external_port": 8080,
    "description": "desc"
  }
}

外部/内部端口是整数,如果用户希望在浮动IP上为许多端口创建端口转发,他/她需要多次发送此JSON以适应他/她想要的端口数量。

建议更改API/CLI以接受外部/内部端口范围中的字符串。这将允许用户使用端口范围创建规则(而不是执行多次调用)。因此,用户不再需要创建100条规则来在他们的虚拟机上实现100个端口转发,他/她可以只发送一个JSON,例如

{
  "port_forwarding": {
    "protocol": "tcp",
    "internal_ip_address": "172.16.0.7",
    "internal_port_range": "8000:8100",
    "internal_port_id": "b67a7746-dc69-45b4-9b84-bb229fe198a0",
    "external_port_range": "9000:9100",
    "description": "desc"
  }
}

API仍然会接受 internal_portexternal_port 属性,以保持向后兼容性。

新的预期响应将是一个JSON,例如

{
  "port_forwarding": {
    "protocol": "tcp",
    "internal_ip_address": "172.16.0.7",
    "internal_port_range": "8000:8100",
    "internal_port_id": "b67a7746-dc69-45b4-9b84-bb229fe198a0",
    "external_port_range": "9000:9100",
    "description": "desc",
    "id": "825ade3c-9760-4880-8080-8fc2dbab9acc"
  }
}

将创建新的验证,以避免用户输入端口中的无效范围。以下是系统执行的所有验证的摘要

  • 只允许N(外部端口[s])到N(内部端口[s])或N(外部端口[s])到1(内部端口)。因此,所有其他组合(1:N、N:M、M:N)都不允许,并且会生成错误。

  • 在定义端口范围时,该范围内的端口不能被同一浮动IP和协议的任何其他端口转发规则使用。

  • 有效的端口是1到65535之间的数字。所有其他情况都将生成错误。即使“0”是一个有效的端口,我们也不会允许使用它,因为它已被保留。

  • 定义端口范围的符号如下:<port_range_begin>[:<port_range_end>];任何不符合此定义的都会生成错误。

  • 在进行请求时,用户可以选择发送带有 internal_port_range(字符串)或 internal_port(整数)的JSON,对于外部端口也是如此,同时发送 internal_port_rangeinternal_port 将引发验证错误。

数据模型影响

今天,port_forwarding表模式如下

id

floatingip_id

external_port

internal_neutron_port_id

protocol

socket

A1

C2

80

A2

tcp

172.16.0.7:8080

B1

C2

81

B2

tcp

172.16.0.7:8081

为了使port_forwarding表更像PortForwarding对象和JSON,port_forwarding表将被更新,将socket列拆分为三个新列(internal_ip_address、internal_port_start、internal_port_end),此外,external_port列将被拆分为两个新列(external_port_start和external_port_end)。新的表如下所示

id

floatingip_id

external_port

external_port_start

external_port_end

internal_neutron_port_id

protocol

internal_ip_address

internal_port_start

internal_port_end

socket

A1

C2

80

80

80

A2

tcp

172.16.0.7

8080

8080

172.16.0.7:8080

B1

C2

81

81

81

B2

tcp

172.16.0.7

8081

8081

172.16.0.7:8081

遗留数据迁移将通过 alembic 迁移升级脚本完成。

我们有5个步骤来进行数据迁移

  1. 创建 internal_ip_addressinternal_port_startexternal_port_startinternal_port_endexternal_port_end 列,值为NULL;

  2. 为表中的每个条目选择id、socket和external_port列;

  3. 对于每个条目,通过‘:’分割socket值,并将结果放入新的 internal_ip_addressinternal_port_start 列中,与socket相同的id。将 internal_port_start 列的值迁移到 internal_port_end 列,并将 external_port 列的值迁移到 external_port_startexternal_port_end 列;

  4. 将socket列更改为nullable;

  5. 将external_port列更改为nullable;

子资源扩展

它将被创建为一个扩展,覆盖参数(external_port和internal_port),以便也接受其验证中的端口范围。新的子资源的属性映射如下

SUB_RESOURCE_ATTRIBUTE_MAP = {
    'port_forwarding': {
        'parameters': {
            'external_port_range': {
                'allow_post': True, 'allow_put': True,
                'validate': {'type:port_range': None},
                'is_visible': True,
                'is_sort_key': True,
                'is_filter': True},
            'internal_port_range': {
                'allow_post': True, 'allow_put': True,
                'validate': {'type:port_range': None},
                'is_visible': True},
        }
    }
}

REST API 影响

无。

实现

负责人

主要负责人

其他贡献者

工作项

  1. API扩展(neutron-lib)

  2. DB扩展/数据迁移(neutron)

  3. 扩展Neutron API,为端口范围添加新的验证(neutron)

  4. 扩展l3代理,将范围应用于iptable规则(neutron)

  5. 扩展 floating ip port forwarding 命令,以接受和验证CLI中的范围(python-openstackclient)

  6. 将PortForwarding对象中的端口类型从int更改为string(openstacksdk)

  7. 测试

  8. 文档

未来版本中完成

1) 删除neutron数据库的port_forwarding表中的“socket”和“external_port”列,因为这些列在wallaby版本之后不再使用。

依赖项

参考资料