-
Notifications
You must be signed in to change notification settings - Fork 33
Example #4 Traffic filter
This example shows how P4Pi can be used as a simple stateless firewall or a traffic filter.
The source code of the example is available under P4Pi examples.
This example works as a stateless traffic filter with support for IPv4 TCP and UDP packets. Rules can be applied for many header fields, and these rules can block packets passing through the P4Pi. When the switch receives a packet it checks if any blocking rule is valid for the packet. If so, it gets dropped. Currently, the following fields are supported:
- srcMAC
- dstMAC
- ethProtocol
- srcIP
- dstIP
- ipProtocol
- tcpSrcPort
- tcpDstPort
- udpSrcPort
- udpDstPort
We use blocklisting, which involves defining which entities should be blocked. So by default, we allow everything to pass through the switch. (See Functionalities to be added during the hackathon or later chapter for improvement ideas)
The following figure depicts the default setup of a P4Pi node:
For more detailed information check the Simple L2 Switch example
Connect your laptop to the wireless access point called "p4pi". After that your laptop will get an IP address assigned by the DHCP service (from the default address pool 192.168.4.0/24).
echo 'traffic_filter' > /root/t4p4s-switch
sudo systemctl restart t4p4s.service
If no rules are added, everything will pass through the switch. You can check it by running the following commands.
Start an iperf server inside the gigport network namespace:
sudo ip netns exec gigport iperf -s -B 192.168.4.150
And try to connect to it from your laptop.
iperf -c 192.168.4.150 -t 30 -i 1
You can also test UDP traffic with iperf, or use netcat for both cases.
The next step is to launch P4Runtime shell, that is used to insert blocklist rules. In the SSH terminal run:
t4p4s-p4rtshell traffic_filter
Insert a rule to block all TCP traffic
te = table_entry["MyIngress.ip_proto_filter"](action="MyIngress.drop")
te.match["hdr.ipv4.protocol"] = "6"
te.insert
P4Pi
sudo ip netns exec gigport iperf -s -B 192.168.4.150
And connect to it from your laptop.
iperf -c 192.168.4.150 -t 30 -i 1
Because TCP flows are blocked, it will not connect.
Let's check that UDP still works.
sudo ip netns exec gigport iperf -s 192.168.4.150 -u -p 5003
And connect to it from your laptop.
iperf -c 192.168.4.150 -t 30 -i 1 -u -p 5003
Any of the previously discussed header fields can be used in the rules. Try to block the UDP 12345 port. (hint: use the udp_dstPort_filter table). Help for the table entry creation:
te = table_entry["MyIngress.table_name"](action="MyIngress.function_name")
te.match["name_of_the_field_to_match"] = "value_as_string"
te.match["if_there_are_more_keys_to_match"] = "value_as_string"
te.action["action_function_parameter_name"] = "value_as_string"
te.insert
The following figure depicts another setup where P4Pi node acts as a low level relay or proxy between your laptop and your home router (or a private network) connected to the 1GE wired Ethernet port.
.
We first launch the traffic filter program. In the SSH terminal:
echo 'traffic_filter' > /root/t4p4s-switch
sudo systemctl restart t4p4s.service
Internet access should work properly on your laptop.
The next step is to launch P4Runtime shell, that is used to create rules. In the SSH terminal run:
t4p4s-p4rtshell traffic_filter
Try to block HTTP traffic
te = table_entry["MyIngress.tcp_dstPort_filter"](action="MyIngress.drop")
te.match["hdr.tcp.dstPort"] = "80"
te.insert
Internet access should work properly on your laptop, however, no HTTP website will load. (HTTPS still works fine).
- Try to modify the P4 code to change the blocklist behavior to allowlist. Instead of allowing everything by default, block all traffic and allow only flows that match the inserted rules.
- Add support for IPv6
-
Bmv2 Exercises