You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adds Wireshark pipes support, cleanup OSX tcpdump handling. (#1959)
* Adds Wireshark pipes support, cleanup OSX tcpdump handling.
* SniffSource now only opens a socket on calling `start`.
* WrpcapSink only opens a PcapWriter on calling `start`.
* Adds WiresharkSink for streaming packets to Wireshark through a pipe.
* Adds `fd` parameter to `utils.get_temp_file`, which allows a temporary
file to be used without closing and re-opening it.
* Adds `utils.get_temp_dir` (used for tests)
* Adds `use_tempfile` parameter to `utils.tcpdump`, which causes it to
use a temporary file to store packets.
* `utils.tcpdump` now only uses a temporary file by default for calling
tcpdump on OSX (to work around Apple's broken version of tcpdump).
stdin is now used with other tools which are not impacted by this bug
(eg: tshark).
* Adds `read_stdin_opts` parameter to `utils.tcpdump`, which allows
callers to control the options used for reading packets over stdin
(previously hard-coded to `-r -`).
* `utils.wireshark` now uses a pipe rather than a temporary file.
Wireshark itself has options to save this file to disk if desired.
Also cleans up the tests a little:
* Removes `os.remove("test.png")` (which seems to be unused).
* Uses a temporary directory for some pipetool tests.
Includes fixup:
* spelling
* Documentation for WiresharkSink, Pipetools sinks and wireshark():
* Enable `manpages_url`, so we can use manpage links.
* Pipetools: Revise Sinks section to use `py:class` style documentation.
This makes cross-references to specific sinks much easier.
* Add documentation for `WiresharkSink`.
* Pipetools: Revise Link object section with some word-smithing.
* Usage/wireshark:
* improve wordsmithing
* remove hard coded references to `google.com` (which trigger DNS
lookups), and use an RFC 5737 netmask instead.
* set a source IP address (otherwise, this gets the host's IP address).
* remove `Ether` layer, as Wireshark supports `DLT_RAW` (which triggers
getting the host's MAC address).
* elaborate on mixed `linktype` issues.
* Pipetool: fixups:
* `QueueSink.recv`: add `block` and `timeout` parameters
* `WrpcapSink`, `WiresharkSink`: add `linktype` parameter
* `WiresharkSink`: add `args` parameter
* tests: sleep longer to work-around race conditions on Windows
* utils: many fixups
* `{Raw,}PcapWriter._write_packet`:
* Remove unused support for `packet` as tuple, as `write` will always
unroll iterators for us (and do it better).
* Always set the `usec` parameter if `sec` was unset.
* Set `usec=0` if `sec` was set, but `usec` was unset (instead of using
the current time's usec value
* PEP-8 fixup, add docstring.
* Only write the header if there is a packet
* `PcapWriter._write_packet`: support packet as bytes
* `RawPcapWriter.close`: write the file header here if not already written
* `tcpdump()`:
* Add `linktype` parameter, like `wrpcap(linktype=...)`
* Add `wait` parameter, which controls whether a program should be run in
the background. Defaults to `True` (run in foreground).
* Throw an error if `prog` is not a string.
* Copy `read_stdin_opts` (for thread safety).
* `tdecode()`: Add `args` parameter (defaults to `-V`, as before), pass
other `tcpdump()` kwargs.
* `wireshark()`: Run in the background by default, pass other `tcpdump()`
kwargs.
* Add tests that hit `wireshark`, `tdecode`, `tcpdump` with new parameters,
and try to pass packets as bytes.
@@ -790,6 +790,7 @@ Two methods are hooks to be overloaded:
790
790
791
791
* The ``master_filter()`` method is called each time a packet is sniffed and decides if it is interesting for the automaton. When working on a specific protocol, this is where you will ensure the packet belongs to the connection you are being part of, so that you do not need to make all the sanity checks in each transition.
792
792
793
+
.. _pipetools:
793
794
794
795
PipeTools
795
796
=========
@@ -882,7 +883,10 @@ class ConsoleSink(Sink)
882
883
Sources
883
884
^^^^^^^
884
885
885
-
A Source is a class that generates some data. They are several source types integrated with Scapy, usable as-is, but you may also create yours.
886
+
A Source is a class that generates some data.
887
+
888
+
There are several source types integrated with Scapy, usable as-is, but you may
889
+
also create yours.
886
890
887
891
Default Source classes
888
892
~~~~~~~~~~~~~~~~~~~~~~
@@ -951,25 +955,165 @@ For instance, here is how TransformDrain is implemented::
951
955
Sinks
952
956
^^^^^
953
957
958
+
Sinks are destinations for messages.
959
+
960
+
A :py:class:`Sink` receives data like a :py:class:`Drain`, but doesn't send any
961
+
messages after it.
962
+
963
+
Messages on the low entry come from :py:meth:`~Sink.push`, and messages on the
964
+
high entry come from :py:meth:`~Sink.high_push`.
965
+
954
966
Default Sink classes
955
967
~~~~~~~~~~~~~~~~~~~~
956
968
957
-
- Sink : does not do anything. This must be extended to create custom sinks
958
-
- ConsoleSink : Print messages on low and high entries
959
-
- RawConsoleSink : Print messages on low and high entries, using os.write
960
-
- TermSink : Print messages on low and high entries on a separate terminal
961
-
- QueueSink: Collect messages from high and low entries and queue them. Messages are unqueued with the .recv() method.
969
+
.. py:class:: Sink
970
+
971
+
Does nothing; interface to extend for custom sinks.
972
+
973
+
All sinks have the following constructor parameters:
974
+
975
+
:param name: a human-readable name for the element
976
+
:type name: str
977
+
978
+
All sinks should implement at least one of these methods:
979
+
980
+
.. py:method:: push
981
+
982
+
Called by :py:class:`PipeEngine` when there is a new message for the
983
+
low entry.
984
+
985
+
:param msg: The message data
986
+
:returns: None
987
+
:rtype: None
988
+
989
+
.. py:method:: high_push
990
+
991
+
Called by :py:class:`PipeEngine` when there is a new message for the
992
+
high entry.
993
+
994
+
:param msg: The message data
995
+
:returns: None
996
+
:rtype: None
997
+
998
+
.. py:class:: ConsoleSink
999
+
1000
+
Prints messages on the low and high entries to ``stdout``.
1001
+
1002
+
.. py:class:: RawConsoleSink
1003
+
1004
+
Prints messages on the low and high entries, using :py:func:`os.write`.
1005
+
1006
+
:param newlines: Include a new-line character after printing each packet.
1007
+
Defaults to True.
1008
+
:type newlines: bool
1009
+
1010
+
.. py:class:: TermSink
1011
+
1012
+
Prints messages on the low and high entries, on a separate terminal (xterm
1013
+
or cmd).
1014
+
1015
+
:param keepterm: Leaves the terminal window open after :py:meth:`~Pipe.stop`
1016
+
is called. Defaults to True.
1017
+
:type keepterm: bool
1018
+
:param newlines: Include a new-line character after printing each packet.
1019
+
Defaults to True.
1020
+
:type newlines: bool
1021
+
:param openearly: Automatically starts the terminal when the constructor is
1022
+
called, rather than waiting for :py:meth:`~Pipe.start`.
1023
+
Defaults to True.
1024
+
:type openearly: bool
1025
+
1026
+
.. py:class:: QueueSink
1027
+
1028
+
Collects messages on the low and high entries into a :py:class:`Queue`.
1029
+
1030
+
Messages are dequeued with :py:meth:`recv`.
1031
+
1032
+
Both high and low entries share the same :py:class:`Queue`.
1033
+
1034
+
.. py:method:: recv
1035
+
1036
+
Reads the next message from the queue.
1037
+
1038
+
If no message is available in the queue, returns None.
1039
+
1040
+
:param block: Blocks execution until a packet is available in the queue.
1041
+
Defaults to True.
1042
+
:type block: bool
1043
+
:param timeout: Controls how long to wait if ``block=True``. If None
1044
+
(the default), this method will wait forever. If a
1045
+
non-negative number, this is a number of seconds to
1046
+
wait before giving up (and returning None).
1047
+
:type timeout: None, int or float
1048
+
1049
+
.. py:class:: WiresharkSink
1050
+
1051
+
Streams :py:class:`Packet` from the low entry to Wireshark.
1052
+
1053
+
Packets are written into a ``pcap`` stream (like :py:class:`WrpcapSink`),
1054
+
and streamed to a new Wireshark process on its ``stdin``.
1055
+
1056
+
Wireshark is run with the ``-ki -`` arguments, which cause it to treat
1057
+
``stdin`` as a capture device. Arguments in :py:attr:`args` will be
1058
+
appended after this.
1059
+
1060
+
Extends :py:mod:`WrpcapSink`.
1061
+
1062
+
:param linktype: See :py:attr:`WrpcapSink.linktype`.
1063
+
:type linktype: None or int
1064
+
:param args: See :py:attr:`args`.
1065
+
:type args: None or list[str]
1066
+
1067
+
.. py:attribute:: args
1068
+
1069
+
Additional arguments for the Wireshark process.
1070
+
1071
+
This must be either ``None`` (the default), or a ``list`` of ``str``.
1072
+
1073
+
This attribute has no effect after calling :py:meth:`PipeEngine.start`.
1074
+
1075
+
See :manpage:`wireshark(1)` for more details.
1076
+
1077
+
.. py:class:: WrpcapSink
1078
+
1079
+
Writes :py:class:`Packet` on the low entry to a ``pcap`` file.
1080
+
1081
+
Ignores all messages on the high entry.
1082
+
1083
+
.. note::
1084
+
1085
+
Due to limitations of the ``pcap`` format, all packets **must** be of
1086
+
the same link type. This class will not mutate packets to conform with
1087
+
the expected link type.
1088
+
1089
+
:param fname: Filename to write packets to.
1090
+
:type fname: str
1091
+
:param linktype: See :py:attr:`linktype`.
1092
+
:type linktype: None or int
1093
+
1094
+
.. py:attribute:: linktype
1095
+
1096
+
Set an explicit link-type (``DLT_``) for packets. This must be an
1097
+
``int`` or ``None``.
1098
+
1099
+
This is the same as the :py:func:`wrpcap` ``linktype`` parameter.
1100
+
1101
+
If ``None`` (the default), the linktype will be auto-detected on the
1102
+
first packet. This field will *not* be updated with the result of this
1103
+
auto-detection.
1104
+
1105
+
This attribute has no effect after calling :py:meth:`PipeEngine.start`.
1106
+
962
1107
963
1108
Create a custom Sink
964
1109
~~~~~~~~~~~~~~~~~~~~
965
1110
966
-
To create a custom sink, one must extend the ``Sink`` class.
1111
+
To create a custom sink, one must extend :py:class:`Sink` and implement
Copy file name to clipboardExpand all lines: doc/scapy/usage.rst
+56-8Lines changed: 56 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1533,28 +1533,76 @@ Viewing packets with Wireshark
1533
1533
Problem
1534
1534
^^^^^^^
1535
1535
1536
-
You have generated or sniffed some packets with Scapy and want to view them with `Wireshark <http://www.wireshark.org>`_, because of its advanced packet dissection abilities.
1536
+
You have generated or sniffed some packets with Scapy.
1537
+
1538
+
Now you want to view them with `Wireshark <https://www.wireshark.org>`_, because
1539
+
of its advanced packet dissection capabilities.
1537
1540
1538
1541
Solution
1539
1542
^^^^^^^^
1540
1543
1541
-
That's what the ``wireshark()`` function is for:
1544
+
That's what :py:func:`wireshark` is for!
1545
+
1546
+
.. code-block:: python3
1542
1547
1543
-
>>> packets = Ether()/IP(dst=Net("google.com/30"))/ICMP() # first generate some packets
Wireshark will start in the background and show your packets.
1551
+
# Show them with Wireshark
1552
+
wireshark(packets)
1553
+
1554
+
Wireshark will start in the background, and show your packets.
1547
1555
1548
1556
Discussion
1549
1557
^^^^^^^^^^
1550
1558
1551
-
The ``wireshark()`` function generates a temporary pcap-file containing your packets, starts Wireshark in the background and makes it read the file on startup.
1559
+
.. py:function:: wireshark(pktlist, ...)
1560
+
1561
+
With a :py:class:`Packet` or :py:class:`PacketList`, serialises your
1562
+
packets, and streams this into Wireshark via ``stdin`` as if it were a
1563
+
capture device.
1564
+
1565
+
Because this uses ``pcap`` format to serialise the packets, there are some
1566
+
limitations:
1567
+
1568
+
* Packets must be all of the same ``linktype``.
1569
+
1570
+
For example, you can't mix :py:class:`Ether` and :py:class:`IP` at the
1571
+
top layer.
1572
+
1573
+
* Packets must have an assigned (and supported) ``DLT_*`` constant for the
1574
+
``linktype``. An unsupported ``linktype`` is replaced with ``DLT_EN10MB``
1575
+
(Ethernet), and will display incorrectly in Wireshark.
1576
+
1577
+
For example, can't pass a bare :py:class:`ICMP` packet, but you can send
1578
+
it as a payload of an :py:class:`IP` or :py:class:`IPv6` packet.
1579
+
1580
+
With a filename (passed as a string), this loads the given file in
1581
+
Wireshark. This needs to be in a format that Wireshark supports.
1582
+
1583
+
You can tell Scapy where to find the Wireshark executable by changing the
1584
+
``conf.prog.wireshark`` configuration setting.
1585
+
1586
+
This accepts the same extra parameters as :py:func:`tcpdump`.
1587
+
1588
+
.. seealso::
1589
+
1590
+
:py:class:`WiresharkSink`
1591
+
A :ref:`PipeTools sink <pipetools>` for live-streaming packets.
1552
1592
1553
-
Please remember that Wireshark works with Layer 2 packets (usually called "frames"). So we had to add an ``Ether()`` header to our ICMP packets. Passing just IP packets (layer 3) to Wireshark will give strange results.
1593
+
:manpage:`wireshark(1)`
1594
+
Additional description of Wireshark's functionality, and its
1595
+
command-line arguments.
1554
1596
1555
-
You can tell Scapy where to find the Wireshark executable by changing the ``conf.prog.wireshark`` configuration setting.
1597
+
`Wireshark's website`__
1598
+
For up-to-date releases of Wireshark.
1556
1599
1600
+
`Wireshark Protocol Reference`__
1601
+
Contains detailed information about Wireshark's protocol dissectors, and
1602
+
reference documentation for various network protocols.
0 commit comments