-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #148 from seed-labs/development
Development
- Loading branch information
Showing
47 changed files
with
2,782 additions
and
277 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
FROM ubuntu:20.04 | ||
|
||
ARG DEBIAN_FRONTEND=noninteractive | ||
RUN echo 'exec zsh' > /root/.bashrc | ||
|
||
RUN apt-get update && apt-get install -y --no-install-recommends curl dnsutils ipcalc iproute2 iputils-ping jq mtr-tiny nano netcat tcpdump termshark vim-nox zsh | ||
RUN curl -L https://grml.org/zsh/zshrc > /root/.zshrc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
version: "3.4" | ||
services: | ||
test: | ||
build: | ||
context: . | ||
dockerfile: Dockerfile | ||
image: handsonsecurity/seedemu-base | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
FROM handsonsecurity/seedemu-base | ||
|
||
ARG DEBIAN_FRONTEND=noninteractive | ||
|
||
RUN mkdir -p /usr/share/doc/bird2/examples/ | ||
RUN touch /usr/share/doc/bird2/examples/bird.conf | ||
RUN apt-get update && apt-get install -y --no-install-recommends bird2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
version: "3.4" | ||
services: | ||
test: | ||
build: | ||
context: . | ||
dockerfile: Dockerfile | ||
image: handsonsecurity/seedemu-router | ||
|
||
|
120 changes: 120 additions & 0 deletions
120
examples/C03-bring-your-own-internet/bring-your-own-internet-client.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#!/usr/bin/env python3 | ||
# encoding: utf-8 | ||
|
||
from seedemu import * | ||
|
||
for i in range(0, 4): | ||
############################################################################### | ||
emu = Emulator() | ||
base = Base() | ||
routing = Routing() | ||
ebgp = Ebgp() | ||
ibgp = Ibgp() | ||
ospf = Ospf() | ||
web = WebService() | ||
dhcp = DHCPService() | ||
ovpn = OpenVpnRemoteAccessProvider() | ||
|
||
A=3*i | ||
B=3*i | ||
C=2*i | ||
D=10*(i-1) | ||
|
||
############################################################################### | ||
|
||
ix100 = base.createInternetExchange(100) | ||
ix101 = base.createInternetExchange(101) | ||
ix102 = base.createInternetExchange(102+A) | ||
ix103 = base.createInternetExchange(103+A) | ||
ix104 = base.createInternetExchange(104+A) | ||
|
||
############################################################################### | ||
# Create Transit Autonomous Systems | ||
|
||
## Tier 1 ASes | ||
Makers.makeTransitAs(base, 2+B, [100, 101, 102+A], | ||
[(100, 101), (101, 102+A)] | ||
) | ||
|
||
Makers.makeTransitAs(base, 3+B, [100, 103+A, 104+A], | ||
[(100, 103+A), (103+A, 104+A)] | ||
) | ||
|
||
Makers.makeTransitAs(base, 4+B, [100, 102+A, 104+A], | ||
[(100, 104+A), (102+A, 104+A)] | ||
) | ||
|
||
## Tier 2 ASes | ||
Makers.makeTransitAs(base, 51+C, [102+A, 103+A], [(102+A, 103+A)]) | ||
Makers.makeTransitAs(base, 52+C, [101, 104+A], [(101, 104+A)]) | ||
|
||
|
||
############################################################################### | ||
# Create single-homed stub ASes. "None" means create a host only | ||
|
||
Makers.makeStubAs(emu, base, 165+D, 100, [web, None]) | ||
Makers.makeStubAs(emu, base, 166+D, 100, [web, dhcp, None]) | ||
|
||
Makers.makeStubAs(emu, base, 167+D, 101, [None, None]) | ||
Makers.makeStubAs(emu, base, 168+D, 101, [web, None, None]) | ||
|
||
Makers.makeStubAs(emu, base, 169+D, 102+A, [None, web]) | ||
|
||
Makers.makeStubAs(emu, base, 170+D, 103+A, [web, None]) | ||
Makers.makeStubAs(emu, base, 171+D, 103+A, [web, dhcp, None]) | ||
Makers.makeStubAs(emu, base, 172+D, 103+A, [web, None]) | ||
|
||
Makers.makeStubAs(emu, base, 173+D, 104+A, [web, None]) | ||
Makers.makeStubAs(emu, base, 174+D, 104+A, [None, None]) | ||
|
||
############################################################################### | ||
# Peering via RS (route server). The default peering mode for RS is PeerRelationship.Peer, | ||
# which means each AS will only export its customers and their own prefixes. | ||
# We will use this peering relationship to peer all the ASes in an IX. | ||
# None of them will provide transit service for others. | ||
|
||
ebgp.addRsPeers(102+A, [2+B, 4+B]) | ||
ebgp.addRsPeers(104+A, [3+B, 4+B]) | ||
|
||
# To buy transit services from another autonomous system, | ||
# we will use private peering | ||
ebgp.addPrivatePeering(100, 2+B, 3+B, PeerRelationship.Peer) | ||
ebgp.addPrivatePeering(100, 3+B, 4+B, PeerRelationship.Peer) | ||
ebgp.addPrivatePeering(100, 2+B, 4+B, PeerRelationship.Peer) | ||
|
||
|
||
ebgp.addPrivatePeerings(100, [2+B], [165+D, 166+D], PeerRelationship.Provider) | ||
ebgp.addPrivatePeerings(100, [3+B], [165+D], PeerRelationship.Provider) | ||
|
||
ebgp.addPrivatePeerings(101, [2+B], [52+C], PeerRelationship.Provider) | ||
ebgp.addPrivatePeerings(101, [52+C], [167+D, 168+D], PeerRelationship.Provider) | ||
|
||
ebgp.addPrivatePeerings(102+A, [2+B, 4+B], [51+C, 169+D], PeerRelationship.Provider) | ||
ebgp.addPrivatePeerings(102+A, [51+C], [169+D], PeerRelationship.Provider) | ||
|
||
ebgp.addPrivatePeerings(103+A, [3+B], [170+D, 171+D, 172+D ], PeerRelationship.Provider) | ||
|
||
ebgp.addPrivatePeerings(104+A, [3+B, 4+B], [52+C], PeerRelationship.Provider) | ||
ebgp.addPrivatePeerings(104+A, [4+B], [173+D], PeerRelationship.Provider) | ||
ebgp.addPrivatePeerings(104+A, [52+C], [174+D], PeerRelationship.Provider) | ||
|
||
############################################################################### | ||
base.setNameServers(['10.153.0.53']) | ||
|
||
# Add layers to the emulator | ||
emu.addLayer(base) | ||
emu.addLayer(routing) | ||
emu.addLayer(ebgp) | ||
emu.addLayer(ibgp) | ||
emu.addLayer(ospf) | ||
emu.addLayer(web) | ||
emu.addLayer(dhcp) | ||
|
||
# Save it to a component file, so it can be used by other emulators | ||
emu.dump('base-component.bin') | ||
|
||
# Uncomment the following if you want to generate the final emulation files | ||
emu.render() | ||
#print(dns.getZone('.').getRecords()) | ||
emu.compile(Docker(), './output_'+str(i), override=True) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# SCION Examples | ||
|
||
This directory contains examples of using the SCION Internet architecture within the SEED-Emulator. | ||
|
||
## Contributors | ||
The following persons have contributed to the SCION emulation layers: | ||
``` | ||
Lars-Christian Schulz (OVGU Magdeburg) | ||
Thorben Krüger (OVGU Magdeburg) | ||
Marten Gartner (OVGU Magdeburg) | ||
Tony John (OVGU Magdeburg) | ||
Robin Wehner (OVGU Magdeburg) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
# SCION Internet Architecture | ||
|
||
SCION (Scalability, Control, and Isolation On Next-generation networks) is a new secure and reliable inter-domain routing protocol. SCION offers inter-domain path control with explicit trust by grouping ASes in Isolation Domains (ISDs) and embedding the cryptographically secured AS-level path into packet headers. | ||
|
||
This example demonstrates how to create a small SCION Internet topology in the SEED emulator. | ||
|
||
## Step 0: Install SCION PKI tool | ||
We rely on an external tool called `scion-pki` to generate the cryptographic material necessary for SCION. You can install `scion-pki` in a number of ways: | ||
|
||
### Install SCION Packages | ||
[deb packages](https://docs.scionlab.org/content/install/pkg.html) are available for Debian and Ubuntu (x86, x86-64, arm32, and arm64). | ||
|
||
Example installation on Ubuntu: | ||
```bash | ||
sudo apt-get install apt-transport-https ca-certificates | ||
echo "deb [trusted=yes] https://packages.netsec.inf.ethz.ch/debian all main" | sudo tee /etc/apt/sources.list.d/scionlab.list | ||
sudo apt-get update | ||
sudo apt-get install scion-tools | ||
``` | ||
|
||
### Compile from source | ||
To compile from source you need an up-to-date version of the [Go programming language](https://go.dev/doc/install). The SCION source code is available on GitHub: https://github.com/scionproto/scion. | ||
[Detailed build instructions](https://docs.scion.org/en/latest/build/setup.html) are available, but on Ubuntu systems it is usually enough to run the following commands. | ||
```bash | ||
git clone https://github.com/scionproto/scion.git | ||
cd scion | ||
go build -o bin ./scion-pki/cmd/scion-pki | ||
``` | ||
|
||
Once you have installed a copy of `scion-pki` make sure to add it to the `PATH` environment variable before you continue. | ||
|
||
## Step 1: Import emulator components for SCION | ||
|
||
```python | ||
from seedemu.compiler import Docker | ||
from seedemu.core import Emulator | ||
from seedemu.layers import ScionBase, ScionRouting, ScionIsd, Scion | ||
from seedemu.layers.Scion import LinkType as ScLinkType | ||
``` | ||
|
||
SCION support in the emulator relies on four emulation layers: | ||
- The `ScionBase` layer extends the `Base` layer by adding Isolation Domains (ISDs). We will use the base layer to declare ISDs. | ||
- The `ScionRouting` layer extends the `Routing` layer with support for SCION inter-AS routing. It installs and configures the SCION routing daemons on routers and control service hosts (see Step 3 below). Additionally, it installs the SCION host stack on all hosts. | ||
- The `ScionIsd` layer manages the trust relationships between ASes. Each AS must be assigned to an ISD and given a role of either core or regular non-core AS. The `ScionIsd` layer invokes the `scion-pki` tool to generate the secret keys and certificates necessary for the SCION control plane. | ||
- The `Scion` layer is the equivalent to the `Ebgp` layer for a BGP-based Internet. We use it to define links between ASes within and across ISDs. | ||
|
||
Initialization is as usual: | ||
```python | ||
emu = Emulator() | ||
base = ScionBase() | ||
routing = ScionRouting() | ||
scion_isd = ScionIsd() | ||
scion = Scion() | ||
``` | ||
|
||
## Step 2: Create isolation domains | ||
|
||
```python | ||
base.createIsolationDomain(1) | ||
``` | ||
|
||
Each SCION AS is member of an isolation domain (ISD). ISDs manage the trust relationship between ASes. ASes in the same ISD have to trust each other to a higher degree than they would trust an AS from a foreign ISD. An ISD is identified by a globally unique numerical 16-bit ID. In this example we create a single ISD with identifier 1. In the emulator ISDs may optionally have a descriptive label as well. | ||
|
||
## Step 3: Create autonomous systems | ||
|
||
```python | ||
as150 = base.createAutonomousSystem(150) | ||
``` | ||
|
||
SCION ASes are created in the same way as BGP ASes. The `ScionBase` layer automatically returns SCION-enabled ASes. Within the emulator we use ASNs from the 32-bit BGP ASN namespace. | ||
|
||
### Step 3.1: Add the AS to an ISD | ||
|
||
```python | ||
scion_isd.addIsdAs(1, 150, is_core=True) | ||
``` | ||
|
||
We use the `ScionIsd` layer to assign AS 150 to the ISD we have created. By specifying `is_core=True` we make AS 150 a core AS of its ISD. Every ISD must have at least one core AS. Please note that it is currently not possible to assign an AS to multiple ISDs at the same time as the semantics of multi-ISD ASes have not been finalized yet in SCION. | ||
|
||
For non-core ASes must additionally specify which core AS is signing the non-core AS's certificates with a call to `scion_isd.setCertIssuer()`. | ||
|
||
### Step 3.2: Create the internal network and border routers | ||
|
||
```python | ||
as150.createNetwork('net0') | ||
as150_router = as150.createRouter('br0') | ||
as150_router.joinNetwork('net0').joinNetwork('ix100') | ||
``` | ||
|
||
The `ScionRouting` layer upgrades all routers to SCION border routers, so we can add routers as usual. In this example, border router `br0` connects to three networks: (1) the internal network `net0`, (2) the internet exchange `ix100`, and (3) a cross-connect network to AS 153. | ||
|
||
In addition to the border routers each SCION AS has at least one control service. The control service contains the beacon, certificate, and path servers necessary for SCION control plane operations. AS 150 as one control service called `cs1`. | ||
|
||
```python | ||
as150.createControlService('cs1').joinNetwork('net0') | ||
``` | ||
|
||
## Step 4: Set up inter-AS routing | ||
|
||
```python | ||
scion.addIxLink(100, (1, 150), (1, 151), ScLinkType.Core) | ||
scion.addIxLink(100, (1, 151), (1, 152), ScLinkType.Core) | ||
scion.addIxLink(100, (1, 152), (1, 150), ScLinkType.Core) | ||
scion.addXcLink((1, 150), (1, 153), ScLinkType.Transit) | ||
``` | ||
|
||
Inter-AS routing in SCION is based on fixed "links" which are combined during the beaconing process to form end-to-end paths. SCION links are roughly equivalent to BGP peering sessions. | ||
|
||
The `Scion` layer exposes two methods `addIxLink()` and `addXcLink()` for setting up SCION links over an IX and via direct cross-connect links, respectively. In both methods, we must specify the two endpoints of the link as pairs of ISD and ASN. The order of endpoints matters as SCION transit links are directional (for beaconing purposes, packets are still forwarded in both directions) from `a` to `b`. The reason we must name ASes by ASN and ISD is that only the pair of ISD and ASN uniquely identifies a SCION AS, i.e., a link from (1, 150) to (1, 151) is completely different from a hypothetical link between (2, 150) and (2, 151). | ||
|
||
Besides the endpoints every SCION link has a type. Currently there are three types: | ||
- `Core` links connect core ASes of the same or different ISDs. The core ASes of every ISD must all be reachable by one another via core links. The BGP analogy to core links is peering between Tier 1 ASes. | ||
- `Transit` links connect core ASes to non-core ASes in the same ISD. They model Internet transit as sold from a provider AS to a customer AS. | ||
- `Peering` links are used for any other type of peering between two ASes of the same or different ISDs. | ||
|
||
In our example topology we have three core ASes with fully-meshed core-peering and an additional non-core AS 153 that obtains transit through AS 150. | ||
|
||
## Step 5: Render and compile | ||
|
||
```python | ||
emu.addLayer(base) | ||
emu.addLayer(routing) | ||
emu.addLayer(scion_isd) | ||
emu.addLayer(scion) | ||
|
||
emu.render() | ||
|
||
emu.compile(Docker(), './output') | ||
``` | ||
|
||
Rendering and compiling the topology for Docker works as usual. Graphing the SCION links is supported as well. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
#!/usr/bin/env python3 | ||
|
||
from seedemu.compiler import Docker | ||
from seedemu.core import Emulator | ||
from seedemu.layers import ScionBase, ScionRouting, ScionIsd, Scion | ||
from seedemu.layers.Scion import LinkType as ScLinkType | ||
|
||
# Initialize | ||
emu = Emulator() | ||
base = ScionBase() | ||
routing = ScionRouting() | ||
scion_isd = ScionIsd() | ||
scion = Scion() | ||
|
||
# SCION ISDs | ||
base.createIsolationDomain(1) | ||
|
||
# Internet Exchange | ||
base.createInternetExchange(100) | ||
|
||
# AS-150 | ||
as150 = base.createAutonomousSystem(150) | ||
scion_isd.addIsdAs(1, 150, is_core=True) | ||
as150.createNetwork('net0') | ||
as150.createControlService('cs1').joinNetwork('net0') | ||
as150_router = as150.createRouter('br0') | ||
as150_router.joinNetwork('net0').joinNetwork('ix100') | ||
as150_router.crossConnect(153, 'br0', '10.50.0.2/29') | ||
|
||
# AS-151 | ||
as151 = base.createAutonomousSystem(151) | ||
scion_isd.addIsdAs(1, 151, is_core=True) | ||
as151.createNetwork('net0') | ||
as151.createControlService('cs1').joinNetwork('net0') | ||
as151.createRouter('br0').joinNetwork('net0').joinNetwork('ix100') | ||
|
||
# AS-152 | ||
as152 = base.createAutonomousSystem(152) | ||
scion_isd.addIsdAs(1, 152, is_core=True) | ||
as152.createNetwork('net0') | ||
as152.createControlService('cs1').joinNetwork('net0') | ||
as152.createRouter('br0').joinNetwork('net0').joinNetwork('ix100') | ||
|
||
# AS-153 | ||
as153 = base.createAutonomousSystem(153) | ||
scion_isd.addIsdAs(1, 153, is_core=False) | ||
scion_isd.setCertIssuer((1, 153), issuer=150) | ||
as153.createNetwork('net0') | ||
as153.createControlService('cs1').joinNetwork('net0') | ||
as153_router = as153.createRouter('br0') | ||
as153_router.joinNetwork('net0') | ||
as153_router.crossConnect(150, 'br0', '10.50.0.3/29') | ||
|
||
# Inter-AS routing | ||
scion.addIxLink(100, (1, 150), (1, 151), ScLinkType.Core) | ||
scion.addIxLink(100, (1, 151), (1, 152), ScLinkType.Core) | ||
scion.addIxLink(100, (1, 152), (1, 150), ScLinkType.Core) | ||
scion.addXcLink((1, 150), (1, 153), ScLinkType.Transit) | ||
|
||
# Rendering | ||
emu.addLayer(base) | ||
emu.addLayer(routing) | ||
emu.addLayer(scion_isd) | ||
emu.addLayer(scion) | ||
|
||
emu.render() | ||
|
||
# Compilation | ||
emu.compile(Docker(), './output') |
Oops, something went wrong.