Skip to content

Commit f199ac1

Browse files
Filter for packetcapture service (#273)
Added tcpdump-like filtering for packetcapture service
1 parent 9b03a6c commit f199ac1

31 files changed

+1168
-1943
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ swagger-codegen*
88
cmake-build-debug/*
99
Vagrantfile
1010
libyang/*
11+
12+
cmake-build-debug/

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ off on commits in the Polycube repository:
1212
Mauricio Vásquez Bernal mauriciovasquezbernal@gmail.com
1313
Nico Caprioli nico.caprioli@gmail.com
1414
Riccardo Marchi riccardo.marchi4@gmail.com
15+
Riccardo Rusca riccardo.rusca11@gmail.com
1516
Sebastiano Miano mianosebastiano@gmail.com
1617
Simone Magnani simonemagnani.96@gmail.com
1718
Yunsong Lu roamer@yunsong.lu

Documentation/installation.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ Install dependencies
9999

100100
# Install polycube dependencies
101101
sudo apt-get -y install git build-essential cmake bison flex \
102-
libelf-dev libllvm5.0 llvm-5.0-dev libclang-5.0-dev \
102+
libelf-dev libllvm5.0 llvm-5.0-dev libclang-5.0-dev libpcap-dev \
103103
libnl-route-3-dev libnl-genl-3-dev uuid-dev pkg-config \
104104
autoconf libtool m4 automake libssl-dev kmod jq bash-completion \
105105
gnupg2

Documentation/polycubectl/polycubectl.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Refer to :doc:`Quick Start <../quickstart>`.
4141
pbforwarder service Policy-Based Forwarder Service
4242
bridge service Bridge Service
4343
nat service NAT Service
44+
packetcapture service Packetcapture Service
4445

4546
connect command Connect ports
4647
disconnect command Disconnect ports
Lines changed: 97 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
Packetcapture service
22
=====================
33

4-
Packetcapture is a transparent service that allows to capture packets flowing through the interface it is attached to, apply (simple) filters and obtain capture in *.pcap* format. In particular, the service supports either saving captured packets in the local filesystem (e.g., useful in case of high network traffic) or it can interact and deliver packets to a remote client that stores them in the remote filesystem.
4+
Packetcapture is a transparent service that allows to capture packets flowing through the interface it is attached to, apply filters and obtain capture in *.pcap* format. In particular, the service supports either saving captured packets in the local filesystem (e.g., useful in case of high network traffic) or it can interact and deliver packets to a remote client that stores them in the remote filesystem.
55

66
An example of a client that uses the REST api of the packetcapture service is available in '*Packetcapture_Client*' directory.
77

88
Features
99
--------
10+
1011
- Transparent service, can be attached to any interface of any Polycube service
11-
- Support for (simple) IPv4 filters: source prefix, destination prefix, source port, destination port and layer 4 protocol.
12+
- Support for filters (i.e., source prefix, destination prefix, source port, destination port, layer 4 protocol, etc.).
1213
- Support partial capture of packets (i.e., snaplen)
1314
- Support localmode (store data locally) or network mode (send packets to a remote client) operations
1415

1516
Limitations
1617
-----------
17-
- No IPv6 filtering
18+
1819
- Traffic is returned as is, without any anonimization primitive.
1920

21+
2022
How to use
2123
----------
2224
The packetcapture service is a transparent service, it can be attached to a cube port.
@@ -37,13 +39,14 @@ This service can operate in four working modes (actually, the forth mode is just
3739
- turn packet capture off: **capture=off**
3840

3941
*capture* option indicates the direction of the packets that the service must capture.
40-
The direction of the captured packets is independent of the operation in "nework mode" or "non network mode".
42+
The direction of the captured packets is independent of the operation in "network mode" or "non network mode".
4143

4244
In this example the service named '*mysniffer*' will work in bidirectional mode.
4345

4446

4547
Attach to a cube port
4648
^^^^^^^^^^^^^^^^^^^^^
49+
4750
::
4851

4952
# Attach the service to a cube port
@@ -56,70 +59,76 @@ Now the packetcapture service is attached to the port *toveth1* of the bridge *b
5659

5760

5861

59-
Filters
62+
Filter
6063
-------
61-
Traffic can be selected by means of the following filters:
64+
Traffic can be selected by adding filters with syntax (tcpdump like):
65+
66+
polycubectl <service name> set filter=<string value>
67+
68+
-if the filter contains only one word you can put it normally
69+
-if the filter contains more than a word you have to put the string inside the ""
70+
71+
-if you want to capture all the traffic you can put as filter: all
72+
73+
polycubectl <service name> set filter=all
74+
75+
- default filter captures no packets (the eBPF datapath simply returns ok)
76+
77+
Filter can be viewed using the command **polycubectl mysniffer filter show**
78+
Snaplen can be viewed using the command **polycubectl mysniffer snaplen show**
79+
80+
For further details of the implementation of the filter see :doc:`Packetcapture filter <packetcapture-filter>`
6281

63-
- source prefix
64-
- destination prefix
65-
- source port
66-
- destination port
67-
- later 4 protocol
82+
For more details about the filters supported by libpcap (hence, the syntax allowed to specify filters) see `pcap-filter <https://linux.die.net/man/7/pcap-filter>`__
83+
84+
85+
Examples of possible filters
86+
----------------------------
6887

69-
Source prefix filter
70-
^^^^^^^^^^^^^^^^^^^^
7188
::
7289

7390
# Example of the source prefix filter
74-
polycubectl mysniffer filters set src=10.10.10.10/24
91+
polycubectl mysniffer set filter="ip src 10.0.2.11"
7592

76-
Destination prefix filter
77-
^^^^^^^^^^^^^^^^^^^^^^^^^
7893
::
79-
80-
# Example of the destination prefix filter
81-
polycubectl mysniffer filters set dst=10.10.10.10/24
8294

83-
Source port filter
84-
^^^^^^^^^^^^^^^^^^
85-
::
86-
8795
# Example of the source port filter
88-
polycubectl mysniffer filters set sport=80
96+
polycubectl mysniffer set filter="src port 80"
8997

90-
Destination port filter
91-
^^^^^^^^^^^^^^^^^^^^^^^
92-
::
93-
94-
# Example of the destination port filter
95-
polycubectl mysniffer filters set dport=80
9698

97-
Layer 4 protocol filter
98-
^^^^^^^^^^^^^^^^^^^^^^^
9999
::
100100
101101
# Example of the layer 4 protocol filter
102-
polycubectl mysniffer filters set l4proto=tcp
102+
polycubectl mysniffer set filter=tcp
103103

104-
Snaplen filter
105-
^^^^^^^^^^^^^^
106104
::
107105
108106
# Example of the snaplen filter
109-
# In this case we capture only the first 80 bytes of each packet
110-
polycubectl mysniffer filters set snaplen=80
107+
# In this case we capture only the first 80 bytes of each packet
108+
polycubectl mysniffer set snaplen=80
111109

112110

113-
Filters can be viewed using the command **polycubectl mysniffer filters show**
114-
115111
Get the capture dump
116112
--------------------
117-
When the service is not set in *networkmode*, the dump is automatically written in a resilient way in the temporary user folder.
113+
When the service is not set in *networkmode*, the dump is by default written in a resilient way in the temporary user folder.
114+
The folder where the dump is written can be changed by using the syntax:
115+
116+
polycubectl <service name> set dump="<string value>"
117+
118+
::
119+
120+
# Example of new dump folder
121+
polycubectl mysniffer set dump="/home/user_name/Desktop/capture"
122+
123+
At the end of the file name will be added the file extension ".pcap"
124+
125+
If a file with the same name already exists it will be overwritten otherwise it will be created
118126

119127
The path of the capture file can be shown using the command: **polycubectl mysniffer show dump**
120128

121129
Otherwise, if the service is set in network mode, the capture file can be requested through the use of the provided Python client, or queried simply through the service API.
122130

131+
123132
How to use the demo client
124133
^^^^^^^^^^^^^^^^^^^^^^^^^^
125134
::
@@ -137,3 +146,51 @@ Set network mode
137146

138147
# Start sniffer in local model
139148
polycubectl mysniffer set networkmode=false
149+
150+
151+
Implementation details
152+
----------------------
153+
The pipeline to convert into C code the filtering string entered in the packetcapture service is the following:
154+
155+
**pcap filter** → *libpcap* → **cBPF** → *cbpf2c* → **C code**
156+
157+
More in details, the first step is to obtain the cBPF (assembly) code from the filtering string, using the ``libpcap``/``tcpdump`` format. The filtering string is read from ``polycubed`` REST interface, then it is compiled in cBPF using the ``pcap_compile_nopcap()`` function that returns a ``bpf_program`` structure containing a list of ``bpf_insn``.
158+
159+
Then, the code creates a ``sock_fprog`` structure called ``cbpf`` that contains all the required filter blocks.
160+
161+
The second step (traslation from cBPF to C) starts with the validation of the cBPF code.
162+
Function ``_cbpf_dump()`` is called for each filtering block and it returns a string containing the equivalent C code for that block.
163+
164+
Inside ``_cbpf_dump()``, a switch statement creates two variables, ``op`` (operation) and ``fmt`` (operand) depending on the type of instruction of the block (e.g.,return, load, store, alu op. etc.); the above variables will be used to generate the final C code.
165+
166+
This ASM-to-C traslator is ispired to a similar project proposed by `Cloudflare <https://blog.cloudflare.com/xdpcap/>`_; however, in Polycube the translator is written in C/C++ (the CLoudfare one is in Go); furthermore, in Polycube the final output of the translator is a C equivalent of the packet filter, while in the latest version of the Cloudfare project, the final outcome of the translation are eBPF assembly instructions.
167+
168+
The C output facilitates any further modification of the code, e.g., with when additional processing steps are needed, although it impacts on the overall filter conversion time as it requires one additional processing pass involving CLANG/LLVM to convert the C code into eBPF assembly.
169+
170+
171+
Example of C code generated
172+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
173+
As a example, we list here is the generated C code for the filter ``icmp``:
174+
175+
::
176+
177+
L0: if ((data + 14) > data_end) {
178+
return RX_DROP;
179+
}
180+
a = ntohs(* ((uint16_t *) &data[12]));
181+
L1: if (a == 0x0800) {
182+
goto L2;
183+
} else {
184+
goto L5;
185+
}
186+
L2: if ((data + 24) > data_end) {
187+
return RX_DROP;
188+
}
189+
a = * ((uint8_t *) &data[23]);
190+
L3: if (a == 0x01) {
191+
goto L4;
192+
} else {
193+
goto L5;
194+
}
195+
L4: return pcn_pkt_controller(ctx, md, reason);
196+
L5: return RX_OK;

scripts/pre-requirements.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ PACKAGES+=" sudo" # needed for pcn-iptables, when building docker image
3030
PACKAGES+=" kmod" # needed for pcn-iptables, when using lsmod to unload conntrack if not needed
3131
PACKAGES+=" jq bash-completion" # needed for polycubectl bash autocompletion
3232
PACKAGES+=" libpcre3-dev" # needed for libyang
33+
PACKAGES+=" libpcap-dev" # needed for packetcapture filter
34+
3335

3436
if [ "$MODE" == "pcn-k8s" ]; then
3537
PACKAGES+=" curl" # needed for pcn-k8s to download a binary

src/libs/bcc

Submodule bcc updated 249 files

src/services/pcn-packetcapture/datamodel/packetcapture.yang

Lines changed: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ module packetcapture {
3030
description "Packet capture status";
3131
}
3232

33-
leaf anomimize {
33+
leaf anonimize {
3434
type boolean;
3535
default false;
3636
}
@@ -43,40 +43,18 @@ module packetcapture {
4343
leaf networkmode {
4444
type boolean;
4545
default false;
46-
description "operative mode";
46+
description "Operating mode";
4747
}
4848

49-
container filters {
50-
leaf snaplen {
51-
type uint32;
52-
default 262144;
53-
description "Snapshot length";
54-
}
55-
56-
leaf src {
57-
type inet:ipv4-prefix;
58-
description "IP source filter";
59-
}
60-
61-
leaf dst {
62-
type inet:ipv4-prefix;
63-
description "IP destination filter";
64-
}
65-
66-
leaf l4proto {
67-
type string;
68-
description "Level 4 protocol filter";
69-
}
70-
71-
leaf sport {
72-
type uint16;
73-
description "Source port filter";
74-
}
75-
76-
leaf dport {
77-
type uint16;
78-
description "Destination port filter";
79-
}
49+
leaf snaplen {
50+
type uint32;
51+
default 262144;
52+
description "Snapshot length";
53+
}
54+
55+
leaf filter {
56+
type string;
57+
description "filtering string (e.g., 'host 1.2.3.4 and src port 80')";
8058
}
8159

8260
container globalheader {

src/services/pcn-packetcapture/src/CMakeLists.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ aux_source_directory(base BASE_SOURCES)
66

77
include_directories(serializer)
88

9+
find_library(PCAP_LIBRARY
10+
NAMES pcap)
11+
912
if (NOT DEFINED POLYCUBE_STANDALONE_SERVICE OR POLYCUBE_STANDALONE_SERVICE)
1013
find_package(PkgConfig REQUIRED)
1114
pkg_check_modules(POLYCUBE libpolycube)
@@ -19,11 +22,11 @@ add_library(pcn-packetcapture SHARED
1922
${SERIALIZER_SOURCES}
2023
${API_SOURCES}
2124
${BASE_SOURCES}
22-
Filters.cpp
2325
Globalheader.cpp
2426
Packet.cpp
2527
Packetcapture.cpp
26-
Packetcapture-lib.cpp)
28+
Packetcapture-lib.cpp
29+
cbpf2c.cpp)
2730

2831
# load ebpf datapath code a variable
2932
load_file_as_variable(pcn-packetcapture
@@ -39,10 +42,12 @@ load_file_as_variable(pcn-packetcapture
3942
packetcapture_datamodel)
4043

4144
target_link_libraries(pcn-packetcapture ${POLYCUBE_LIBRARIES})
45+
target_link_libraries(pcn-packetcapture ${PCAP_LIBRARY})
4246

4347
# Specify shared library install directory
4448

4549
set(CMAKE_INSTALL_LIBDIR /usr/lib)
50+
set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY})
4651

4752
install(
4853
TARGETS

0 commit comments

Comments
 (0)