Skip to content

Commit

Permalink
Filter implementation for packetcapture service
Browse files Browse the repository at this point in the history
  • Loading branch information
riccardo committed Feb 22, 2020
1 parent b0be98d commit 6f81c12
Show file tree
Hide file tree
Showing 29 changed files with 1,273 additions and 1,870 deletions.
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
[submodule "src/components/iptables/iptables"]
path = src/components/iptables/iptables
url = https://github.com/polycube-network/iptables.git
branch = polycube
branch = polycube
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ off on commits in the Polycube repository:
Mauricio Vásquez Bernal mauriciovasquezbernal@gmail.com
Nico Caprioli nico.caprioli@gmail.com
Riccardo Marchi riccardo.marchi4@gmail.com
Riccardo Rusca riccardo.rusca11@gmail.com
Sebastiano Miano mianosebastiano@gmail.com
Simone Magnani simonemagnani.96@gmail.com
Yunsong Lu roamer@yunsong.lu
Expand Down
65 changes: 65 additions & 0 deletions Documentation/services/pcn-packetcapture/packetcapture-filter.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
Packetcapture service filter
============================

Packetcapture filter is a tcpdump like filter that allows to insert a specific rule using tcpdump syntax.


How it needs
------------
In order to use it you have to install **libpcap-dev**

::

sudo apt-get install libpcap-dev


How it works
------------
The pipeline to convert the filter entered in the packetcapture service to C code is:

**pcap filter** → *libpcap* → **cBPF** → *cbpf2c* → **C code**


More in details, the first step is to obtain the cBPF code from the string value of the filter inserted,
it can be done using the pcap_compile_nopcap function that returns a bpf_program structure containing the bpf_insn.

Then will be created a sock_fprog structure called cbpf that will contains all the filter blocks needed.

The second step (traslation from cBPF to C) starts with the validation of the cBPF code, and then for each filter block
is called _cbpf_dump function that will return a string containing the equivalent C code for that block.

Inside the _cbpf_dump function there is a switch statement that will prepare two variables, op (operation) and fmt (operand),
depending on the type of instruction of the block (e.g.,return, load, store, alu op. etc.), then they will be used to
generate the C code

For reference see: `cloudflare project <https://blog.cloudflare.com/xdpcap/>`__


Example of C code generated
---------------------------
Here is the generated C code for the filter "icmp":

::

L0: //(ldh)
if((data + 14) > data_end){
return RX_DROP;
}
a = ntohs(* ((uint16_t *) &data[12]));
L1: if(a == 0x0800) {
goto L2;
}else{
goto L5;
}
L2: //(ldb)
if((data + 24) > data_end){
return RX_DROP;
}
a = * ((uint8_t *) &data[23]);
L3: if(a == 0x01) {
goto L4;
}else{
goto L5;
}
L4: return pcn_pkt_controller(ctx, md, reason);
L5: return RX_OK;
60 changes: 31 additions & 29 deletions Documentation/services/pcn-packetcapture/packetcapture.rst
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
Packetcapture service
=====================

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

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

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

Expand All @@ -20,6 +20,11 @@ Limitations
How to use
----------
The packetcapture service is a transparent service, it can be attached to a cube port.
In order to use it you have to install **libpcap-dev**

::

sudo apt-get install libpcap-dev

Create the service
^^^^^^^^^^^^^^^^^^
Expand All @@ -37,7 +42,7 @@ This service can operate in four working modes (actually, the forth mode is just
- turn packet capture off: **capture=off**

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

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

Expand All @@ -56,61 +61,58 @@ Now the packetcapture service is attached to the port *toveth1* of the bridge *b



Filters
Filter
-------
Traffic can be selected by means of the following filters:
Traffic can be selected by adding filters with syntax (tcpdump like):

polycubectl <service name> set filter=<string value>

-if the filter contains only one word you can put it normally
-if the filter contains more than a word you have to put the string inside the ""

-if you want to capture all the traffic you can put as filter: all

polycubectl <service name> set filter=all

- default filter captures no packets (the eBPF datapath simply returns ok)

- source prefix
- destination prefix
- source port
- destination port
- later 4 protocol
For further details of the implementation of the filter see :doc:`Packetcapture filter <packetcapture-filter>`

For reference see: `pcap-filter <https://linux.die.net/man/7/pcap-filter>`__

Source prefix filter
^^^^^^^^^^^^^^^^^^^^
::

# Example of the source prefix filter
polycubectl mysniffer filters set src=10.10.10.10/24

Destination prefix filter
^^^^^^^^^^^^^^^^^^^^^^^^^
::
# Example of the destination prefix filter
polycubectl mysniffer filters set dst=10.10.10.10/24
polycubectl mysniffer set filter="ip src 10.0.2.11"

Source port filter
^^^^^^^^^^^^^^^^^^
::
# Example of the source port filter
polycubectl mysniffer filters set sport=80
polycubectl mysniffer set filter="src port 80"

Destination port filter
^^^^^^^^^^^^^^^^^^^^^^^
::
# Example of the destination port filter
polycubectl mysniffer filters set dport=80

Layer 4 protocol filter
^^^^^^^^^^^^^^^^^^^^^^^
::
# Example of the layer 4 protocol filter
polycubectl mysniffer filters set l4proto=tcp
polycubectl mysniffer set filter=tcp

Snaplen filter
^^^^^^^^^^^^^^
::
# Example of the snaplen filter
# In this case we capture only the first 80 bytes of each packet
polycubectl mysniffer filters set snaplen=80
polycubectl mysniffer set snaplen=80


Filters can be viewed using the command **polycubectl mysniffer filters show**
Filter can be viewed using the command **polycubectl mysniffer filter show**
Snaplen can be viewed using the command **polycubectl mysniffer snaplen show**

Get the capture dump
--------------------
Expand All @@ -136,4 +138,4 @@ Set network mode
polycubectl mysniffer set networkmode=true

# Start sniffer in local model
polycubectl mysniffer set networkmode=false
polycubectl mysniffer set networkmode=false
60 changes: 60 additions & 0 deletions src/libs/polycube/include/polycube/services/bcc_exception.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2015 PLUMgrid, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <cstdio>
#include <string>

namespace ebpf {

class StatusTuple {
public:
StatusTuple(int ret) : ret_(ret) {}

StatusTuple(int ret, const char *msg) : ret_(ret), msg_(msg) {}

StatusTuple(int ret, const std::string &msg) : ret_(ret), msg_(msg) {}

template <typename... Args>
StatusTuple(int ret, const char *fmt, Args... args) : ret_(ret) {
char buf[2048];
snprintf(buf, sizeof(buf), fmt, args...);
msg_ = std::string(buf);
}

void append_msg(const std::string& msg) {
msg_ += msg;
}

int code() { return ret_; }

std::string msg() { return msg_; }

private:
int ret_;
std::string msg_;
};

#define TRY2(CMD) \
do { \
StatusTuple __stp = (CMD); \
if (__stp.code() != 0) { \
return __stp; \
} \
} while (0)

} // namespace ebpf
67 changes: 67 additions & 0 deletions src/libs/polycube/include/polycube/services/file_desc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <unistd.h>

namespace ebpf {

/// FileDesc is a helper class for managing open file descriptors. Copy is
/// disallowed (call dup instead), and cleanup happens automatically.
class FileDesc {
public:
explicit FileDesc(int fd = -1) : fd_(fd) {}
FileDesc(FileDesc &&that) : fd_(-1) { *this = std::move(that); }
FileDesc(const FileDesc &that) = delete;

~FileDesc() {
if (fd_ >= 0)
::close(fd_);
}

FileDesc &operator=(int fd) {
if (fd_ >= 0)
::close(fd_);
fd_ = fd;
return *this;
}
FileDesc &operator=(FileDesc &&that) {
if (fd_ >= 0)
::close(fd_);
fd_ = that.fd_;
that.fd_ = -1;
return *this;
}
FileDesc &operator=(const FileDesc &that) = delete;

FileDesc dup() const {
if (fd_ >= 0) {
int dup_fd = ::dup(fd_);
return FileDesc(dup_fd);
} else {
return FileDesc(-1);
}
}

operator int() { return fd_; }
operator int() const { return fd_; }

private:
int fd_;
};

} // namespace ebpf
Loading

0 comments on commit 6f81c12

Please sign in to comment.