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 unittestSCION 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()