Scapy is an interactive packet manipulation program/library for Python. This
repository contains Scapy packet header definitions ("layers") for
SCION and Inter-Domain In-band Network Telemetry (ID-INT).
Just start Scapy by running sudo ./scapy-scion
and the new headers are available at the
interactive command line.
Supported headers:
- SCION (with path types EmptyPath, SCION, and OneHopPath)
- SCION Hop-by-Hop and End-to-End Options Header
- SCMP
- BFD over SCION
- INT-MD over UDP
- ID-INT
Some SCION tools built with Scapy are available in tools.
- Python >= 3.10
- Scapy (2.5.0)
- Additional Python packages:
- cryptography (39.0.0)
python3 -m venv .venv
. .venv/bin/activate
pip install -e .[extras]
python3 -m unittest
SCION headers are encapsulated in UDP. Since SCION does not use a well-known set of UDP ports, the
presence of SCION is detected heuristically using Scapy's guess_payload_class()
method. Since
guess_payload_class()
must be overridden in the layer above SCION (UDP), we provide a replacement
for scapy.layers.inet.UDP
in scapy_scion.layers.scion.UDP
. scion.UDP
is a subclass of
inet.UDP
that tries to decode its payload as SCION. If unsuccessful the default guessing mechanism
is invoked. In addition to the heuristic, the default port ranges of the SCION open-source
stack are bound to the SCION layer.
Importing scapy_scion.layers.scion
breaks the association of IP/IPv6 with inet.UDP
and
replaces it with scion.UDP
. Make sure to import scion.UDP
insted of inet.UDP
when using this
library.
- Ping the target AS.
Replace 127.0.0.27:30255
with the address of your SCION daemon and the destination AS with the AS
you want to send packets to.
bin/scion ping --sciond 127.0.0.27:30255 2-ff00:0:211,127.0.0.1
- Launch Scapy in a second terminal and capture one of the echo requests.
Replace IP 127.0.0.25
and port 31014
with the internal address of your border router.
sudo ./scapy-scion
pkts = sniff(iface="lo",
filter="host 127.0.0.25 and port 31014",
lfilter=lambda pkt: pkt.haslayer(SCMP) and pkt[SCMP].type==128,
prn=lambda pkt: pkt.summary(), count=1)
- Extract the IP/UDP underlay and the SCION header.
p = pkts[0][IP]
p[SCION].remove_payload()
del p[IP].len
del p[IP].chksum
del p[UDP].len
del p[UDP].chksum
del p[SCION].nh
del p[SCION].plen
- Build a new packet (e.g., a new echo request) and send it.
Changing conf.L3Socket
to L3RawSocket
is required in order to send packets to local
applications.
Refer to this FAQ.
req = p/SCMP(message=EchoRequest(id=0xabcd))/Raw(b"Hello!")
req[SCION].dl = 0
req[SCION].dst_host = "127.0.0.2"
conf.L3socket = L3RawSocket
resp = sr1(req, iface="lo", timeout=1)
resp.show()