分享免费的编程资源和教程

网站首页 > 技术教程 正文

Netronome智能网卡实现ACL Firewall

goqiw 2024-11-21 15:14:14 技术教程 67 ℃ 0 评论

Netronome网卡Firewall设计

本文Netronome Firewall主要是验证Netronome智能网卡P4功能,以Firewall功能特性实现简单的ACL防火墙功能,整体上分为数据平面和控制平面。

如上图所示,数据平面使用P4设计了基于v1model架构的pipeline,控制平面基于ONOS控制器,由于Netronome提供nfp-sdk6-rte对P4runtime支持较差(有人验证Ternary matching和Packet-Out都不支持,具体支持个人也没验证过,不过nfp-sdk版本多年不更新...),这里基于nfp-sdk6-rte中的rtecli命令行在ONOS中包了个南向协议,并且加了个驱动来纳管Netronome智能网卡,实现了基本的设备连接、pipeline配置和流表增删功能。

这里驱动没有按ONOS规范设计,仅简化为了满足ONOS纳管设备要求,其实按驱动行为规范实现,我这里图简便简化处理了,也有人在智能网卡侧跑一个代理将Openflow或P4runtime转成rtecli来管理,实现复杂了点,我没采用该方案。

Firewall测试直接用netns隔离vf,并配置ip,实现L2互通,然后配置ACL来验证,更复杂的组网场景理论上结合智能网卡的真实物理口(p0&p4)和丰富的vf接口和pipeline中fwd表项或对pipeline重新设计也能得到应用。

数据面设计

数据面基于v1model架构,设计包含两个表的P4 Pipeline: t_acl -> t_fwd,先执行t_acl表判断流量是否满足acl规则,再执行t_fwd表进行转发(目前仅实现端口转发和二层转发),具体局部table设计如下:

  • acl表
direct_counter(CounterType.packets_and_bytes) t_acl_counter;

action allow() {
    t_acl_counter.count();
}

action deny() {
    mark_to_drop();
    t_acl_counter.count();
}

action nop() {
    t_acl_counter.count();
}

// acl table
table t_acl {
    key = {
        standard_metadata.ingress_port   :   ternary;
        hdr.ethernet.src_addr            :   ternary;
        hdr.ethernet.dst_addr            :   ternary;
        hdr.ethernet.ether_type          :   ternary;
        hdr.ipv4.src_addr                :   ternary;
        hdr.ipv4.dst_addr                :   ternary;
        hdr.ipv4.protocol                :   ternary;
        hdr.tcp.src_port                 :   ternary;
        hdr.tcp.dst_port                 :   ternary;
        hdr.udp.src_port                 :   ternary;
        hdr.udp.dst_port                 :   ternary;
    }
    actions = {
        allow;
        deny;
        nop;
    }
    size = 1024;
    default_action = nop();
    counters = t_acl_counter;
}
  • fwd表
direct_counter(CounterType.packets_and_bytes) t_fwd_counter;

action fwd(port_t port) {
    standard_metadata.egress_spec = port;
    t_fwd_counter.count();
}

table t_fwd {
    key = {
        standard_metadata.ingress_port   :   ternary;
        hdr.ethernet.dst_addr            :   ternary;
    }
    actions = {
        fwd;
    }
    default_action = fwd(0);
    counters = t_fwd_counter;
    size = 1024;

}

控制面设计

控制面基于ONOS,实现基本的设备纳管,Pipeline配置和流表增删功能,主要包括:rtecli南向协议、rtecli驱动和实现Firewall的app,如下几个模块的实现描述.

  • rtecli南向协议

rtecli南向协议通过将rtecli命令行包装了一下,提供基本的design load(pipeline配置)、设备连接、流表增删等功能.

  • rtecli驱动

rtecli驱动基于onos中驱动行为机制,编写了rtecli驱动使用的xml并实现基本的驱动行为,实现基本的Handshaker.

  • Firewall app

Firewall onos app为标准的ONOS app,onos版本基于2.4.0,提供onos cli命令对ACL防火墙策略和端口/L2转发配置提供命令行(后面可能会增加北向接口和UI),Firewall服务提供核心的ACL防火墙流表和端口/L2转发流表实现(通过rtecli控制智能网卡,将acl策略和fwd表下发/删除流表).

nfp-sdk6-rte启动

# mod reload
sudo modprobe -r -v nfp && sudo modprobe nfp nfp_pf_netdev=0 nfp_dev_cpp=1

# start nfp-sdk6-rte
sudo systemctl start nfp-sdk6-rte

# check nfp-sdk6-rte status
sudo systemctl status nfp-sdk6-rte

通过ip a已经可以看到默认创建的4个vf接口,可启动nfp-sdk6-rte设置NUM_VFS环境变量来设置启动vf数目

10: vf0_0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether d6:61:9c:56:1c:92 brd ff:ff:ff:ff:ff:ff
11: vf0_1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether fe:a2:d2:49:f6:cd brd ff:ff:ff:ff:ff:ff
12: vf0_2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 26:1d:8e:b3:36:13 brd ff:ff:ff:ff:ff:ff
13: vf0_3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 6a:ec:a4:ba:13:f4 brd ff:ff:ff:ff:ff:ff

onos & firewall app启动

# install nfp sdk, 由于onos南向通过rtecli来和智能网卡通信,所以也要安装nfp-sdk
sudo dpkg -i nfp-sdk_6.1.0.1-preview-3243-2_amd64.deb

# onos 启动
make onos-run

# firewall app编译
make app-build

# firewall app加载
make app-reload

netcfg配置

make netcfg-firewall

firewall-app/src/main/resources/nfp_nics.json配置文件:

{
  "apps": {
    "cn.pcl.firewall": {
      "nfp_nics":  [
        {
          "dp_id": "rtecli:nfp-nic1",
          "driver": "rtecli",
          "rte_host": "172.16.30.15",
          "rte_port": "20206",
          "nffw_path": "path of firewall.nffw",
          "design_path": "path of pif_design.json",
          "p4cfg_path": ""
        }
      ]
    }
  }
}

vf接口netns隔离

sudo ip netns add ns0
sudo ip netns add ns1
sudo ip netns add ns2
sudo ip netns add ns3

sudo ip link set vf0_0 netns ns0
sudo ip link set vf0_1 netns ns1
sudo ip link set vf0_2 netns ns2
sudo ip link set vf0_3 netns ns3

配置ip及checksum

# 配置ip
sudo ip netns exec ns0 /bin/bash
ifconfig vf0_0 192.168.10.5 netmask 255.255.255.0 up

# checksum off
ethtool -K vf0_0 tx off
ethtool -K vf0_0 rx off
# 配置ip
sudo ip netns exec ns1 /bin/bash
ifconfig vf0_0 192.168.10.10 netmask 255.255.255.0 up

# checksum off
ethtool -K vf0_1 tx off
ethtool -K vf0_1 rx off

测试

L2互通

# login onos cli
make onos-cli

# apply fwd flow rules
fwd -d=00:15:4d:00:00:00 add rtecli:nfp-nic1 fwd 768
fwd -d=00:15:4d:00:00:01 add rtecli:nfp-nic1 fwd 769

# show fwd flow rules
fwd show rtecli:nfp-nic1                                                                                                                                                                   09:54:46
===================================================================
|    ID    |                MATCH            |       ACTION       |
===================================================================
|    ID    | IngressPort |       DstMac      |  Action  | Output  |
-------------------------------------------------------------------
| FWD-1000 |             | 00:15:4d:00:00:00 | fwd      | 768     |
| FWD-1001 |             | 00:15:4d:00:00:01 | fwd      | 769     |
-------------------------------------------------------------------
  • icmp
sudo ip netns exec ns0 /bin/bash
ping 192.168.10.10
PING 192.168.10.10 (192.168.10.10) 56(84) bytes of data.
64 bytes from 192.168.10.10: icmp_seq=1 ttl=64 time=0.273 ms
64 bytes from 192.168.10.10: icmp_seq=2 ttl=64 time=0.220 ms
64 bytes from 192.168.10.10: icmp_seq=3 ttl=64 time=0.215 ms
64 bytes from 192.168.10.10: icmp_seq=4 ttl=64 time=0.212 ms
64 bytes from 192.168.10.10: icmp_seq=5 ttl=64 time=0.209 ms
64 bytes from 192.168.10.10: icmp_seq=6 ttl=64 time=0.213 ms
sudo ip netns exec ns1 /bin/bash
ping 192.168.10.5
PING 192.168.10.5 (192.168.10.5) 56(84) bytes of data.
64 bytes from 192.168.10.5: icmp_seq=1 ttl=64 time=0.252 ms
64 bytes from 192.168.10.5: icmp_seq=2 ttl=64 time=0.218 ms
64 bytes from 192.168.10.5: icmp_seq=3 ttl=64 time=0.212 ms
64 bytes from 192.168.10.5: icmp_seq=4 ttl=64 time=0.213 ms
64 bytes from 192.168.10.5: icmp_seq=5 ttl=64 time=0.213 ms
64 bytes from 192.168.10.5: icmp_seq=6 ttl=64 time=0.208 ms
64 bytes from 192.168.10.5: icmp_seq=7 ttl=64 time=0.212 ms
  • tcp
sudo ip netns exec ns1 /bin/bash
iperf -s -i 1
sudo ip netns exec ns0 /bin/bash
iperf -c 192.168.10.10 -i 1
------------------------------------------------------------
Client connecting to 192.168.10.10, TCP port 5001
TCP window size: 85.0 KByte (default)
------------------------------------------------------------
[  3] local 192.168.10.5 port 35252 connected with 192.168.10.10 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0- 1.0 sec   958 MBytes  8.03 Gbits/sec
[  3]  1.0- 2.0 sec   972 MBytes  8.15 Gbits/sec
[  3]  2.0- 3.0 sec   934 MBytes  7.83 Gbits/sec
[  3]  3.0- 4.0 sec   938 MBytes  7.87 Gbits/sec
[  3]  4.0- 5.0 sec   926 MBytes  7.77 Gbits/sec
[  3]  5.0- 6.0 sec   927 MBytes  7.78 Gbits/sec
[  3]  6.0- 7.0 sec   918 MBytes  7.70 Gbits/sec
[  3]  7.0- 8.0 sec   921 MBytes  7.73 Gbits/sec
[  3]  8.0- 9.0 sec   913 MBytes  7.66 Gbits/sec
[  3]  0.0-10.0 sec  9.12 GBytes  7.83 Gbits/sec
   
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size:  128 KByte (default)
------------------------------------------------------------
[  4] local 192.168.10.10 port 5001 connected with 192.168.10.5 port 35252
[ ID] Interval       Transfer     Bandwidth
[  4]  0.0- 1.0 sec   954 MBytes  8.01 Gbits/sec
[  4]  1.0- 2.0 sec   973 MBytes  8.16 Gbits/sec
[  4]  2.0- 3.0 sec   933 MBytes  7.83 Gbits/sec
[  4]  3.0- 4.0 sec   939 MBytes  7.88 Gbits/sec
[  4]  4.0- 5.0 sec   927 MBytes  7.78 Gbits/sec
[  4]  5.0- 6.0 sec   925 MBytes  7.76 Gbits/sec
[  4]  6.0- 7.0 sec   918 MBytes  7.70 Gbits/sec
[  4]  7.0- 8.0 sec   921 MBytes  7.73 Gbits/sec
[  4]  8.0- 9.0 sec   913 MBytes  7.66 Gbits/sec
[  4]  9.0-10.0 sec   927 MBytes  7.78 Gbits/sec
[  4]  0.0-10.0 sec  9.12 GBytes  7.83 Gbits/sec
  • udp
sudo ip netns exec ns1 /bin/bash
iperf -s -i 1 -u
sudo ip netns exec ns0 /bin/bash
iperf -c 192.168.10.10 -i 1 -u
------------------------------------------------------------
Client connecting to 192.168.10.10, UDP port 5001
Sending 1470 byte datagrams
UDP buffer size:  208 KByte (default)
------------------------------------------------------------
[  3] local 192.168.10.5 port 35162 connected with 192.168.10.10 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0- 1.0 sec   129 KBytes  1.06 Mbits/sec
[  3]  1.0- 2.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  2.0- 3.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  3.0- 4.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  4.0- 5.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  5.0- 6.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  6.0- 7.0 sec   129 KBytes  1.06 Mbits/sec
[  3]  7.0- 8.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  8.0- 9.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  9.0-10.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  0.0-10.0 sec  1.25 MBytes  1.05 Mbits/sec
[  3] Sent 893 datagrams
[  3] Server Report:
[  3]  0.0-10.0 sec  1.25 MBytes  1.05 Mbits/sec   0.001 ms    0/  893 (0%)
------------------------------------------------------------
Server listening on UDP port 5001
Receiving 1470 byte datagrams
UDP buffer size:  208 KByte (default)
------------------------------------------------------------
[  3] local 192.168.10.10 port 5001 connected with 192.168.10.5 port 35162
[ ID] Interval       Transfer     Bandwidth        Jitter   Lost/Total Datagrams
[  3]  0.0- 1.0 sec   128 KBytes  1.05 Mbits/sec   0.003 ms    0/   89 (0%)
[  3]  1.0- 2.0 sec   128 KBytes  1.05 Mbits/sec   0.002 ms    0/   89 (0%)
[  3]  2.0- 3.0 sec   128 KBytes  1.05 Mbits/sec   0.002 ms    0/   89 (0%)
[  3]  3.0- 4.0 sec   128 KBytes  1.05 Mbits/sec   0.001 ms    0/   89 (0%)
[  3]  4.0- 5.0 sec   128 KBytes  1.05 Mbits/sec   0.001 ms    0/   89 (0%)
[  3]  5.0- 6.0 sec   129 KBytes  1.06 Mbits/sec   0.001 ms    0/   90 (0%)
[  3]  6.0- 7.0 sec   128 KBytes  1.05 Mbits/sec   0.002 ms    0/   89 (0%)
[  3]  7.0- 8.0 sec   128 KBytes  1.05 Mbits/sec   0.001 ms    0/   89 (0%)
[  3]  8.0- 9.0 sec   128 KBytes  1.05 Mbits/sec   0.002 ms    0/   89 (0%)
[  3]  9.0-10.0 sec   128 KBytes  1.05 Mbits/sec   0.001 ms    0/   89 (0%)
[  3]  0.0-10.0 sec  1.25 MBytes  1.05 Mbits/sec   0.001 ms    0/  893 (0%)

ACL防火墙

场景1

# login onos cli
make onos-cli

# apply acl flow rules
acl -t=ipv4 --ipDst=192.168.10.10 add rtecli:nfp-nic1 deny

# show acl flow rules
acl show rtecli:nfp-nic1
========================================================================================================================================================
|    ID    |                                                             MATCH                                                                | ACTION |
========================================================================================================================================================
|    ID    | IngressPort |       SrcMac      |       DstMac      | EthType | Protocol |      SrcIp      |       DstIp     | SrcPort | DstPort | Action |
--------------------------------------------------------------------------------------------------------------------------------------------------------
| ACL-1000 |             |                   |                   | ipv4    |          |                 | 192.168.10.10   |         |         | deny   |
--------------------------------------------------------------------------------------------------------------------------------------------------------
  • imcp
ping 192.168.10.10
PING 192.168.10.10 (192.168.10.10) 56(84) bytes of data.
^C
--- 192.168.10.10 ping statistics ---
11 packets transmitted, 0 received, 100% packet loss, time 10218ms
ping 192.168.10.5
PING 192.168.10.5 (192.168.10.5) 56(84) bytes of data.
^C
--- 192.168.10.5 ping statistics ---
9 packets transmitted, 0 received, 100% packet loss, time 8186ms
  • tcp
sudo ip netns exec ns1 /bin/bash
iperf -s -i 1
sudo ip netns exec ns0 /bin/bash
iperf -c 192.168.10.10 -i 1
# iperf client
connect failed: Connection timed out

# iperf server 看不到client端连接日志
  • udp
sudo ip netns exec ns1 /bin/bash
iperf -s -i 1 -u
sudo ip netns exec ns0 /bin/bash
iperf -c 192.168.10.10 -i 1 -u
# iperf client 正常发包(udp无连接)
# iperf server 看不到client端连接日志

场景2

# login onos cli
make onos-cli

acl -t=ipv4 --protocol=icmp --ipDst=192.168.10.10 add rtecli:nfp-nic1 deny

acl show rtecli:nfp-nic1
========================================================================================================================================================
|    ID    |                                                             MATCH                                                                | ACTION |
========================================================================================================================================================
|    ID    | IngressPort |       SrcMac      |       DstMac      | EthType | Protocol |      SrcIp      |       DstIp     | SrcPort | DstPort | Action |
--------------------------------------------------------------------------------------------------------------------------------------------------------
| ACL-1000 |             |                   |                   | ipv4    | icmp     |                 | 192.168.10.10   |         |         | deny   |
--------------------------------------------------------------------------------------------------------------------------------------------------------
  • icmp
ping 192.168.10.10
PING 192.168.10.10 (192.168.10.10) 56(84) bytes of data.

^C
--- 192.168.10.10 ping statistics ---
11 packets transmitted, 0 received, 100% packet loss, time 10235ms
ping 192.168.10.5
PING 192.168.10.5 (192.168.10.5) 56(84) bytes of data.
^C
--- 192.168.10.5 ping statistics ---
9 packets transmitted, 0 received, 100% packet loss, time 8186ms
  • tcp
iperf -c 192.168.10.10 -i 1
------------------------------------------------------------
Client connecting to 192.168.10.10, TCP port 5001
TCP window size: 85.0 KByte (default)
------------------------------------------------------------
[  3] local 192.168.10.5 port 35256 connected with 192.168.10.10 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0- 1.0 sec   883 MBytes  7.41 Gbits/sec
[  3]  1.0- 2.0 sec   917 MBytes  7.69 Gbits/sec
[  3]  2.0- 3.0 sec   918 MBytes  7.70 Gbits/sec
[  3]  3.0- 4.0 sec   915 MBytes  7.67 Gbits/sec
[  3]  4.0- 5.0 sec   921 MBytes  7.72 Gbits/sec
[  3]  5.0- 6.0 sec   910 MBytes  7.63 Gbits/sec
[  3]  6.0- 7.0 sec   926 MBytes  7.77 Gbits/sec
[  3]  7.0- 8.0 sec   919 MBytes  7.71 Gbits/sec
[  3]  8.0- 9.0 sec   920 MBytes  7.72 Gbits/sec
[  3]  9.0-10.0 sec   906 MBytes  7.60 Gbits/sec
[  3]  0.0-10.0 sec  8.92 GBytes  7.66 Gbits/sec
iperf -s -i 1
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size:  128 KByte (default)
------------------------------------------------------------

[  4] local 192.168.10.10 port 5001 connected with 192.168.10.5 port 35256
[ ID] Interval       Transfer     Bandwidth
[  4]  0.0- 1.0 sec   881 MBytes  7.39 Gbits/sec
[  4]  1.0- 2.0 sec   916 MBytes  7.68 Gbits/sec
[  4]  2.0- 3.0 sec   918 MBytes  7.70 Gbits/sec
[  4]  3.0- 4.0 sec   916 MBytes  7.68 Gbits/sec
[  4]  4.0- 5.0 sec   919 MBytes  7.71 Gbits/sec
[  4]  5.0- 6.0 sec   911 MBytes  7.64 Gbits/sec
[  4]  6.0- 7.0 sec   925 MBytes  7.76 Gbits/sec
[  4]  7.0- 8.0 sec   920 MBytes  7.72 Gbits/sec
[  4]  8.0- 9.0 sec   921 MBytes  7.72 Gbits/sec
[  4]  9.0-10.0 sec   906 MBytes  7.60 Gbits/sec
[  4]  0.0-10.0 sec  8.92 GBytes  7.66 Gbits/sec

场景3

# login onos cli
make onos-cli

acl -t=ipv4 --protocol=tcp --ipDst=192.168.10.10 --tpDst=5001 add rtecli:nfp-nic1 deny

acl show rtecli:nfp-nic1                                                                                                                                                                         09:32:35
========================================================================================================================================================
|    ID    |                                                             MATCH                                                                | ACTION |
========================================================================================================================================================
|    ID    | IngressPort |       SrcMac      |       DstMac      | EthType | Protocol |      SrcIp      |       DstIp     | SrcPort | DstPort | Action |
--------------------------------------------------------------------------------------------------------------------------------------------------------
| ACL-1000 |             |                   |                   | ipv4    | icmp     |                 | 192.168.10.10   |         |         | deny   |
| ACL-1001 |             |                   |                   | ipv4    | tcp      |                 | 192.168.10.10   |         |  5001   | deny   |
--------------------------------------------------------------------------------------------------------------------------------------------------------
iperf -c 192.168.10.10 -i 1
connect failed: Connection timed out

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表