Skip to main content

A Flexible Network Data Analysis Framework

Project description

NFStream: a Flexible Network Data Analysis Framework

nfstream is a Python package providing fast, flexible, and expressive data structures designed to make working with online or offline network data both easy and intuitive. It aims to be the fundamental high-level building block for doing practical, real world network data analysis in Python. Additionally, it has the broader goal of becoming a common network data processing framework for researchers providing data reproducibility across experiments.

Live Notebook live notebook
Project Website website
Discussion Channel Gitter
Latest Release latest release
Supported Versions python3
Project License License
Build Status Github WorkFlows Travis CI
Code Quality Quality
Code Coverage Coverage

Main Features

  • Performance: nfstream is designed to be fast (x10 faster with PyPy support) with a small CPU and memory footprint.
  • Layer-7 visibility: nfstream deep packet inspection engine is based on nDPI. It allows nfstream to perform reliable encrypted applications identification and metadata extraction (e.g. TLS, QUIC, TOR, HTTP, SSH, DNS, etc.).
  • Flexibility: add a flow feature in 2 lines as an NFPlugin.
  • Machine Learning oriented: add your trained model as an NFPlugin.

How to use it?

  • Dealing with a big pcap file and just want to aggregate it as network flows? nfstream make this path easier in few lines:
from nfstream import NFStreamer
my_awesome_streamer = NFStreamer(source="facebook.pcap", # or network interface (source="eth0")
                                 snaplen=65535,
                                 idle_timeout=30,
                                 active_timeout=300,
                                 plugins=(),
                                 dissect=True,
                                 max_tcp_dissections=80,
                                 max_udp_dissections=16,
                                 statistics=False,
                                 account_ip_padding_size=False,
                                 enable_guess=True,
                                 decode_tunnels=True,
                                 bpf_filter=None,
                                 promisc=True
)

for flow in my_awesome_streamer:
    print(flow)  # print it.
    print(flow.to_namedtuple()) # convert it to a namedtuple.
    print(flow.to_json()) # convert it to json.
    print(flow.keys()) # get flow keys.
    print(flow.values()) # get flow values.
NFEntry(id=0,
        bidirectional_first_seen_ms=1472393122365,
        bidirectional_last_seen_ms=1472393123665,
        src2dst_first_seen_ms=1472393122365,
        src2dst_last_seen_ms=1472393123408,
        dst2src_first_seen_ms=1472393122668,
        dst2src_last_seen_ms=1472393123665,
        src_ip='192.168.43.18',
        src_ip_type=1,
        dst_ip='66.220.156.68',
        dst_ip_type=0,
        version=4,
        src_port=52066,
        dst_port=443,
        protocol=6,
        vlan_id=4,
        bidirectional_packets=19,
        bidirectional_raw_bytes=5745,
        bidirectional_ip_bytes=5479,
        bidirectional_duration_ms=1300,
        src2dst_packets=9,
        src2dst_raw_bytes=1345,
        src2dst_ip_bytes=1219,
        src2dst_duration_ms=1300,
        dst2src_packets=10,
        dst2src_raw_bytes=4400,
        dst2src_ip_bytes=4260,
        dst2src_duration_ms=997,
        expiration_id=0,
        master_protocol=91,
        app_protocol=119,
        application_name='TLS.Facebook',
        category_name='SocialNetwork',
        client_info='facebook.com',
        server_info='*.facebook.com,*.facebook.net,*.fb.com,\
                     *.fbcdn.net,*.fbsbx.com,*.m.facebook.com,\
                     *.messenger.com,*.xx.fbcdn.net,*.xy.fbcdn.net,\
                     *.xz.fbcdn.net,facebook.com,fb.com,messenger.com',
        j3a_client='bfcc1a3891601edb4f137ab7ab25b840',
        j3a_server='2d1eb5817ece335c24904f516ad5da12')
from nfstream import NFStreamer
my_awesome_streamer = NFStreamer(source="facebook.pcap", statistics=True)
for flow in my_awesome_streamer:
    print(flow)
NFEntry(id=0,      
        bidirectional_first_seen_ms=1472393122365,
        bidirectional_last_seen_ms=1472393123665,
        src2dst_first_seen_ms=1472393122365,
        src2dst_last_seen_ms=1472393123408,
        dst2src_first_seen_ms=1472393122668,
        dst2src_last_seen_ms=1472393123665,
        src_ip='192.168.43.18',
        src_ip_type=1,
        dst_ip='66.220.156.68',
        dst_ip_type=0,
        version=4,
        src_port=52066,
        dst_port=443,
        protocol=6,
        vlan_id=4,
        bidirectional_packets=19,
        bidirectional_raw_bytes=5745,
        bidirectional_ip_bytes=5479,
        bidirectional_duration_ms=1300,
        src2dst_packets=9,
        src2dst_raw_bytes=1345,
        src2dst_ip_bytes=1219,
        src2dst_duration_ms=1300,
        dst2src_packets=10,
        dst2src_raw_bytes=4400,
        dst2src_ip_bytes=4260,
        dst2src_duration_ms=997,
        expiration_id=0,
        bidirectional_min_raw_ps=66,
        bidirectional_mean_raw_ps=302.36842105263156,
        bidirectional_stdev_raw_ps=425.53315715259754,
        bidirectional_max_raw_ps=1454,
        src2dst_min_raw_ps=66,
        src2dst_mean_raw_ps=149.44444444444446,
        src2dst_stdev_raw_ps=132.20354676701294,
        src2dst_max_raw_ps=449,
        dst2src_min_raw_ps=66,
        dst2src_mean_raw_ps=440.0,
        dst2src_stdev_raw_ps=549.7164925870628,
        dst2src_max_raw_ps=1454,
        bidirectional_min_ip_ps=52,
        bidirectional_mean_ip_ps=288.36842105263156,
        bidirectional_stdev_ip_ps=425.53315715259754,
        bidirectional_max_ip_ps=1440,
        src2dst_min_ip_ps=52,
        src2dst_mean_ip_ps=135.44444444444446,
        src2dst_stdev_ip_ps=132.20354676701294,
        src2dst_max_ip_ps=435,
        dst2src_min_ip_ps=52,
        dst2src_mean_ip_ps=426.0,
        dst2src_stdev_ip_ps=549.7164925870628,
        dst2src_max_ip_ps=1440,
        bidirectional_min_piat_ms=0,
        bidirectional_mean_piat_ms=72.22222222222223,
        bidirectional_stdev_piat_ms=137.34994188549086,
        bidirectional_max_piat_ms=398,
        src2dst_min_piat_ms=0,
        src2dst_mean_piat_ms=130.375,
        src2dst_stdev_piat_ms=179.72036811192467,
        src2dst_max_piat_ms=415,
        dst2src_min_piat_ms=0,
        dst2src_mean_piat_ms=110.77777777777777,
        dst2src_stdev_piat_ms=169.51458475436397,
        dst2src_max_piat_ms=1,
        bidirectional_syn_packets=2,
        bidirectional_cwr_packets=0,
        bidirectional_ece_packets=0,
        bidirectional_urg_packets=0,
        bidirectional_ack_packets=18,
        bidirectional_psh_packets=9,
        bidirectional_rst_packets=0,
        bidirectional_fin_packets=0,
        src2dst_syn_packets=1,
        src2dst_cwr_packets=0,
        src2dst_ece_packets=0,
        src2dst_urg_packets=0,
        src2dst_ack_packets=8,
        src2dst_psh_packets=4,
        src2dst_rst_packets=0,
        src2dst_fin_packets=0,
        dst2src_syn_packets=1,
        dst2src_cwr_packets=0,
        dst2src_ece_packets=0,
        dst2src_urg_packets=0,
        dst2src_ack_packets=10,
        dst2src_psh_packets=5,
        dst2src_rst_packets=0,
        dst2src_fin_packets=0,
        master_protocol=91,
        app_protocol=119,
        application_name='TLS.Facebook',
        category_name='SocialNetwork',
        client_info='facebook.com',
        server_info='*.facebook.com,*.facebook.net,*.fb.com,\
                     *.fbcdn.net,*.fbsbx.com,*.m.facebook.com,\
                     *.messenger.com,*.xx.fbcdn.net,*.xy.fbcdn.net,\
                     *.xz.fbcdn.net,facebook.com,fb.com,messenger.com',
        j3a_client='bfcc1a3891601edb4f137ab7ab25b840',
        j3a_server='2d1eb5817ece335c24904f516ad5da12')
  • From pcap to Pandas DataFrame?
my_dataframe = NFStreamer(source='devil.pcap').to_pandas(ip_anonymization=False)
my_dataframe.head(5)
  • From pcap to csv file?
flows_rows_count = NFStreamer(source='devil.pcap').to_csv(path="devil.pcap.csv",
                                                          sep="|",
                                                          ip_anonymization=False)
  • Didn't find a specific flow feature? add a plugin to nfstream in few lines:
from nfstream import NFPlugin

class packet_with_666_size(NFPlugin):
    def on_init(self, pkt): # flow creation with the first packet
        if pkt.raw_size == 666:
            return 1
        else:
            return 0

    def on_update(self, pkt, flow): # flow update with each packet belonging to the flow
        if pkt.raw_size == 666:
            flow.packet_with_666_size += 1

streamer_awesome = NFStreamer(source='devil.pcap', plugins=[packet_with_666_size()])
for flow in streamer_awesome:
    print(flow.packet_with_666_size) # see your dynamically created metric in generated flows

Run your Machine Learning models

In the following, we want to run an early classification of flows based on a trained machine learning model than takes as features the 3 first packets size of a flow.

Computing required features

from nfstream import NFPlugin

class feat_1(NFPlugin):
    def on_init(self, obs):
        entry.feat_1 = obs.raw_size

class feat_2(NFPlugin):
    def on_update(self, obs, entry):
        if entry.bidirectional_packets == 2:
            entry.feat_2 = obs.raw_size

class feat_3(NFPlugin):
    def on_update(self, obs, entry):
        if entry.bidirectional_packets == 3:
            entry.feat_3 = obs.raw_size

Trained model prediction

class model_prediction(NFPlugin):
    def on_update(self, obs, entry):
        if entry.bidirectional_packets == 3:
            entry.model_prediction = self.user_data.predict_proba([entry.feat_1,
                                                                   entry.feat_2,
                                                                   entry.feat_3])
            # optionally we can trigger NFStreamer to immediately expires the flow
            # entry.expiration_id = -1

Start your ML powered streamer

my_model = function_to_load_your_model() # or whatever
ml_streamer = NFStreamer(source='devil.pcap',
                         plugins=[feat_1(volatile=True),
                                  feat_2(volatile=True),
                                  feat_3(volatile=True),
                                  model_prediction(user_data=my_model)
                                  ])
for flow in ml_streamer:
     print(flow.model_prediction) # now you will see your trained model prediction.

Installation

Using pip

Binary installers for the latest released version are available:

python3 -m pip install nfstream

Build from sources

If you want to build nfstream from sources on your local machine:

linux Linux

sudo apt-get update
sudo apt-get install autoconf automake libtool pkg-config libpcap-dev flex bison
sudo apt-get install libusb-1.0-0-dev libdbus-glib-1-dev libbluetooth-dev libnl-genl-3-dev
git clone https://github.com/aouinizied/nfstream.git
cd nfstream
python3 -m pip install -r requirements.txt
python3 setup.py bdist_wheel

osx MacOS

brew install autoconf automake libtool pkg-config
git clone https://github.com/aouinizied/nfstream.git
cd nfstream
python3 -m pip install -r requirements.txt
python3 setup.py bdist_wheel

Contributing

Please read Contributing for details on our code of conduct, and the process for submitting pull requests to us.

Authors

Zied Aouini created nfstream and these fine people have contributed.

Ethics

nfstream is intended for network data research and forensics. Researchers and network data scientists can use these framework to build reliable datasets, train and evaluate network applied machine learning models. As with any packet monitoring tool, nfstream could potentially be misused. Do not run it on any network of which you are not the owner or the administrator.

License

This project is licensed under the GPLv3 License - see the License file for details

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

nfstream-5.1.6-pp36-pypy36_pp73-macosx_10_15_x86_64.whl (442.8 kB view details)

Uploaded PyPy macOS 10.15+ x86-64

nfstream-5.1.6-cp38-cp38-manylinux2014_aarch64.whl (1.4 MB view details)

Uploaded CPython 3.8

nfstream-5.1.6-cp38-cp38-manylinux1_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.8

nfstream-5.1.6-cp38-cp38-macosx_10_15_x86_64.whl (442.8 kB view details)

Uploaded CPython 3.8 macOS 10.15+ x86-64

nfstream-5.1.6-cp37-cp37m-manylinux2014_aarch64.whl (1.4 MB view details)

Uploaded CPython 3.7m

nfstream-5.1.6-cp37-cp37m-manylinux1_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.7m

nfstream-5.1.6-cp37-cp37m-macosx_10_15_x86_64.whl (442.8 kB view details)

Uploaded CPython 3.7m macOS 10.15+ x86-64

nfstream-5.1.6-cp36-cp36m-manylinux2014_aarch64.whl (1.4 MB view details)

Uploaded CPython 3.6m

nfstream-5.1.6-cp36-cp36m-manylinux1_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.6m

nfstream-5.1.6-cp36-cp36m-macosx_10_15_x86_64.whl (442.8 kB view details)

Uploaded CPython 3.6m macOS 10.15+ x86-64

File details

Details for the file nfstream-5.1.6-pp36-pypy36_pp73-manylinux1_x86_64.whl.

File metadata

  • Download URL: nfstream-5.1.6-pp36-pypy36_pp73-manylinux1_x86_64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: PyPy
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/49.1.2 requests-toolbelt/0.9.1 tqdm/4.47.0 PyPy/7.3.1

File hashes

Hashes for nfstream-5.1.6-pp36-pypy36_pp73-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 26a369cc66c9e6f9999cb67bb585eb782592ca9b2fab3bd2a72a3ad033d783c2
MD5 ddbbc329000e4fb574afff073fe83295
BLAKE2b-256 cbbc60bfcea25597aadfccef9872378cc408bace3221f8aeb9e93ccbdfa1107b

See more details on using hashes here.

File details

Details for the file nfstream-5.1.6-pp36-pypy36_pp73-macosx_10_15_x86_64.whl.

File metadata

  • Download URL: nfstream-5.1.6-pp36-pypy36_pp73-macosx_10_15_x86_64.whl
  • Upload date:
  • Size: 442.8 kB
  • Tags: PyPy, macOS 10.15+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/49.1.2 requests-toolbelt/0.9.1 tqdm/4.47.0 PyPy/7.3.1

File hashes

Hashes for nfstream-5.1.6-pp36-pypy36_pp73-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 2f53dd740d2293f64adfc6eb802ef08754416340fd91b701698fb3ba2247c415
MD5 f04866356ebb77bd9fb97084dc4059bf
BLAKE2b-256 e993ad75e0ff26921c67541095d703dd81765200f07e34292ee1d116b108a077

See more details on using hashes here.

File details

Details for the file nfstream-5.1.6-cp38-cp38-manylinux2014_aarch64.whl.

File metadata

  • Download URL: nfstream-5.1.6-cp38-cp38-manylinux2014_aarch64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: CPython 3.8
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.23.0 setuptools/49.1.2 requests-toolbelt/0.9.1 tqdm/4.46.0 CPython/3.8.0

File hashes

Hashes for nfstream-5.1.6-cp38-cp38-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 854291b05ad323fb112030780e8acd7eb1c69b7309063e0c7753057f1448e0b9
MD5 d4097156febe0974cb3fede13f600765
BLAKE2b-256 f5f9bf00212af358728097fb264ce791ef70c4059510a0deec8ac82f406988a8

See more details on using hashes here.

File details

Details for the file nfstream-5.1.6-cp38-cp38-manylinux1_x86_64.whl.

File metadata

  • Download URL: nfstream-5.1.6-cp38-cp38-manylinux1_x86_64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: CPython 3.8
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/49.1.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.8.3

File hashes

Hashes for nfstream-5.1.6-cp38-cp38-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 531eb963a1e3fd9eb0442f911e49c4dbbb4e177cc528ec451270c5995c95dc9d
MD5 f5f9dba00e3cdc1812639cdd3031a504
BLAKE2b-256 3ed4ce37f9da40889049037b1e62e820378108210a1467beabcc930ddf63a98c

See more details on using hashes here.

File details

Details for the file nfstream-5.1.6-cp38-cp38-macosx_10_15_x86_64.whl.

File metadata

  • Download URL: nfstream-5.1.6-cp38-cp38-macosx_10_15_x86_64.whl
  • Upload date:
  • Size: 442.8 kB
  • Tags: CPython 3.8, macOS 10.15+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/49.1.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.8.3

File hashes

Hashes for nfstream-5.1.6-cp38-cp38-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 7ab56f46d360677e7b31052c251f2b55e7046cc3f3933907c1e0849306f5026a
MD5 3bb7bfdf750550377c00b69dd3ee869c
BLAKE2b-256 336f8ed59c17bfabf12a1b36c8e919b6c8386d1f23677431232825479b42a6c7

See more details on using hashes here.

File details

Details for the file nfstream-5.1.6-cp37-cp37m-manylinux2014_aarch64.whl.

File metadata

  • Download URL: nfstream-5.1.6-cp37-cp37m-manylinux2014_aarch64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: CPython 3.7m
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.23.0 setuptools/49.1.2 requests-toolbelt/0.9.1 tqdm/4.46.0 CPython/3.7.5

File hashes

Hashes for nfstream-5.1.6-cp37-cp37m-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ad88e5a1c67f991bcd121df8db2dc5481c87f1b0d79abbe83550173596c9a5ea
MD5 2599c155a07d40703a4fe4800dacdc49
BLAKE2b-256 753740e0f4ea9ef5a4693f925ce34c2883a6871198d44d548aa06623291daebe

See more details on using hashes here.

File details

Details for the file nfstream-5.1.6-cp37-cp37m-manylinux1_x86_64.whl.

File metadata

  • Download URL: nfstream-5.1.6-cp37-cp37m-manylinux1_x86_64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: CPython 3.7m
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/49.1.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.7.7

File hashes

Hashes for nfstream-5.1.6-cp37-cp37m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 4797f46dc29f76dbf02164227dec227435ec162c83547c458061dfda82d5c0ba
MD5 60571e1cbec6e48d4cdb3ad8e58666b3
BLAKE2b-256 1366d793e4607fe67a1280d61dc5161656f0735ff26ff010ab330a1db475a440

See more details on using hashes here.

File details

Details for the file nfstream-5.1.6-cp37-cp37m-macosx_10_15_x86_64.whl.

File metadata

  • Download URL: nfstream-5.1.6-cp37-cp37m-macosx_10_15_x86_64.whl
  • Upload date:
  • Size: 442.8 kB
  • Tags: CPython 3.7m, macOS 10.15+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/49.1.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.7.8

File hashes

Hashes for nfstream-5.1.6-cp37-cp37m-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 d49e281bb059214521e88eb89585c28629f1b035a35f4bd02de9243ac5b16911
MD5 b9da6fba2d1ac676141f13c63e784e97
BLAKE2b-256 bcddf3bf5711a3df4182a05b9c5917af0cb858264e2c4d96eb578f5adaa6b654

See more details on using hashes here.

File details

Details for the file nfstream-5.1.6-cp36-cp36m-manylinux2014_aarch64.whl.

File metadata

  • Download URL: nfstream-5.1.6-cp36-cp36m-manylinux2014_aarch64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: CPython 3.6m
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.23.0 setuptools/49.1.2 requests-toolbelt/0.9.1 tqdm/4.46.0 CPython/3.6.9

File hashes

Hashes for nfstream-5.1.6-cp36-cp36m-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 d6cec6ecd3da0f5d8b890248af03209bf6ac698058708de5b7892c5248c4160d
MD5 ea04fa40adc18414488ac9d8a6a530ce
BLAKE2b-256 e7adf26d0de27506e471df707b2d516661c05ac38d1dfa4fb46c16e16f07247f

See more details on using hashes here.

File details

Details for the file nfstream-5.1.6-cp36-cp36m-manylinux1_x86_64.whl.

File metadata

  • Download URL: nfstream-5.1.6-cp36-cp36m-manylinux1_x86_64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: CPython 3.6m
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/49.1.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.6.10

File hashes

Hashes for nfstream-5.1.6-cp36-cp36m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 a8f92e86cef9605d5c536e6c5de4008c1372633ab41d45325216cea180279470
MD5 6f95eeb274a44d9b8f49e19751085427
BLAKE2b-256 c8e8add84838301dd487807a4e6f0f0a1a8f00ba89c04a035fe2e01bcaebf0dc

See more details on using hashes here.

File details

Details for the file nfstream-5.1.6-cp36-cp36m-macosx_10_15_x86_64.whl.

File metadata

  • Download URL: nfstream-5.1.6-cp36-cp36m-macosx_10_15_x86_64.whl
  • Upload date:
  • Size: 442.8 kB
  • Tags: CPython 3.6m, macOS 10.15+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/49.1.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.6.11

File hashes

Hashes for nfstream-5.1.6-cp36-cp36m-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 7fde1675a4f9711e39a5f366377d293442d965e38114584d268896d8d48a9e89
MD5 557ea3dce8ac958f5733dbe253f90d53
BLAKE2b-256 bee7eea56e472cfd9954117e6262fd70f6d0763b88ddc222502b02d9c14e5db0

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page