Skip to content

Commit

Permalink
added the Darknet example
Browse files Browse the repository at this point in the history
  • Loading branch information
kevin-w-du committed Aug 9, 2021
1 parent ed85ab8 commit 9bfb8ee
Show file tree
Hide file tree
Showing 2 changed files with 293 additions and 0 deletions.
210 changes: 210 additions & 0 deletions examples/B07-darknet-tor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
# Darknet (Tor Network)


In this example, we show how to deploy a Darknet (Tor) inside the
SEED Emulator. We first create several types of Tor nodes,
and deploy them in randomly selected autonomous systems.
See the comments in the code for detailed explanation of the code.
Here is the table of contents:


- [Deploy a Tor network inside the emulator](#deploy-tor)
- [Protect sender's identity](#sender-anonymity)
- [Protect server's identity](#server-anonymity-contract)
- [Visit the secret web server](#visit-secret-server)
- [Notes on lab designs](#note-lab-design)


<a name="deploy-tor"></a>
## Deploy a Tor Network inside the Emulator

Typically, a Tor network contain 5 types of nodes: DA (Dir Authority) node,
CLIENT node, RELAY node, EXIT node, HS (Hidden Service) node.
In our example, we will create the following nodes.

```python
vnodes = {
"da-1": TorNodeType.DA,
"da-2": TorNodeType.DA,
"da-3": TorNodeType.DA,
"da-4": TorNodeType.DA,
"da-5": TorNodeType.DA,
"client-1": TorNodeType.CLIENT,
"client-2": TorNodeType.CLIENT,
"relay-1": TorNodeType.RELAY,
"relay-2": TorNodeType.RELAY,
"relay-3": TorNodeType.RELAY,
"relay-4": TorNodeType.RELAY,
"exit-1": TorNodeType.EXIT,
"exit-2": TorNodeType.EXIT,
"hidden-service": TorNodeType.HS
}
```

- DA (Dir Authority) node: DA nodes maintain the information of all the Tor nodes,
and they are responsible for generating paths (called Tor circuits) for clients.
There can be multiple DA nodes, CLIENT only needs to work with one DA node each time.
All the nodes need to know the DA servers. This is done
by putting DA’s fingerprints in their configuration files.
The fingerprints contain the IP address and the public key of DA.

- CLIENT node: This node will run a SOCKS5 proxy server. It helps outside machines
to connect to the Tor network without using any Tor-aware software. If outside
machines already have Tor-ware software, such as Tor browser, they do not need to go
through any CLIENT node, because they are basically CLIENT nodes.

- RELAY node: This node relays the traffic to the next node.

- EXIT node: The exit nodes are the final relays in the Tor circuit. They are the
nodes that send the data to the destination.

- HS (Hidden Service) node: This type of node is used to protect the server's
location. See [this section](#server-anonymity-contract) for details.


<a name="sender-anonymity"></a>
## Protect Sender's Identity

We can use the Tor network to protect the sender 's identity, i.e. if you
visit a website using Tor, the website will not know where the request
come from. Moreover, even if somebody can monitor some of the relay nodes,
it is still difficult for them to correlate the source and the destination.

To use the Tor network, we need to use a Tor-aware software,
such as a Tor browser, or we can use a Tor proxy. On the CLIENT
nodes, we already run such a proxy (Tor socket proxy), which listens to
port 9050. Through these proxies, we can connect to
the Tor network. To find the IP addresses of these
proxies, we can list all the container names, as
the IP addresses are included in the container names
as the suffix.

```
$ docker ps --format "{{.ID}} {{.Names}}" | grep Tor
b1827bb8e0c6 as161h-Tor-client-2-10.161.0.73
71c4fecd57ab as153h-Tor-client-1-10.153.0.74
...
142bfc0d9025 as160h-Tor-relay-3-10.160.0.74
4378a36764d2 as170h-Tor-webserver-10.170.0.73
983f6b0898d8 as154h-Tor-exit-1-10.154.0.74
...
1e04ae3c66c2 as154h-Tor-da-1-10.154.0.73
18229e6850f8 as151h-Tor-hidden-service-10.151.0.73
f91ba9d89fef as160h-Tor-da-2-10.160.0.73
```

From the list above, we can find the names with `Tor-client`;
these are proxy nodes. Let us pick `Tor-client-1`, whose IP address
is `10.153.0.74`. The port number for the proxy is `9050`.


We then go to any container (say its IP address is `a.b.c.d`),
and try to access a web server (e.g., `http://10.163.0.71`)
via the proxy. We can use the `curl` command and specify the proxy.

```
# curl --socks5-hostname 10.153.0.74:9050 http://10.163.0.71
<h1>webservice_0 at 163</h1>
```

If we turn on `tcpdump` on the target server `10.163.0.71`, we can find out
that the request does not come from the IP address `a.b.c.d`; instead, it
comes from one of the Tor nodes.
If we use the Map client to visualize
the traffic, we can use the filter `tcp && port 80` to see the
last leg of the traffic. If we visit the same server from a different
container, we can see that the Tor node in the last leg is likely a
different node.


**Note:** The last node should be an EXIT node, but in our observation,
it can be DA, RELAY, or EXIT nodes. Not sure whether this is by design.
It could be that the number of EXIT nodes in our setup is too small.


<a name="server-anonymity"></a>
## Protect Server's Identity/Location

Tor can also protect the server's identity (or location).
This is through Tor's hidden service.
In our emulator, we first create a web server, and then use
the hidden service node to protect the web server.
In the following code, we create a web server node, put
some content inside its `hello.html` page.

```
html = """
<html><body>
<h1>This is the secret web server!</h1>
</body></html>
"""
# Create a web server: we will use Tor to protect this server
emu.getLayer('WebService').install("webserver")
emu.getVirtualNode('webserver').setDisplayName('Tor-webserver') \
.setFile(content=html, path="/var/www/html/hello.html")
```

We then create a HS (Hidden Service) node, and link
this node to our secret web server. If we want to visit the protected
web server, our request will reach this HS node, which will then
forward our traffic to the final destination.
The following code create the HS node and like to the web server.

```
tor.install('hidden-service').setRole(TorNodeType.HS).linkByVnode("webserver", 80)
```

<a name="visit-secret-server"></a>
## Visit the Secret Web Server

To visit this anonymous web server, we need to know its onion address.
We can find this address from the hidden-server container. It is
stored in the `/tor/HS[random]/hs/hostname` file. In our case,
we see the following:
```
u5evj5gmyrsf7hkpaoi6iqclks5qn52x2wrvikx24osuutwxswjnjbid.onion
```

Now, we can visit this server from any container using `curl`, a Tor proxy,
and the onion address. We should be able to get the content put inside
the `hello.html` page:

```
curl --socks5-hostname 10.153.0.74:9050 http://u5evj5gmyrsf7hkpaoi6iqclks5qn52x2wrvikx24osuutwxswjnjbid.onion/hello.html
<html><body>
<h1>This is the secret web server!</h1>
</body></html>
```

We can go to the web-server container, go to its `/var/www/html` folder,
modify the `hello.html` file. Then we visit it again, and we will see that
the content returned will be changed accordingly. This confirms that
the content does come from the web server.



Notice: Sometimes, maybe you would see the
"cannot resolve [random].onion address" error message when you use the `curl` command.
That's because the Tor network may not be stable (or the number of DA nodes is too low).
It would continuously calculate the consensus.
You can keep trying it until it works, or restart the containers.
You can also monitor the Tor network by connecting to its control port to see what
happens inside Tor. You can install a tool called `nyx`,
and run `nyx -i <ip of CLIENT node>:9051` to connect to the
CLIENT node's control port. This way, you can monitor all the connections.
When you try to use `curl` to connect to the Tor network,
you can see what has caused the issue.


<a name="note-lab-design"></a>
## Note for Lab Design (Furture Work)

When we design labs based on Darknet, we need to find ways to show students that Tor is
protecting the communication. We need to show how the Tor works internally.
We can use a tool called `nyx` (see notes above) to
connect to the control port of CLIENT node. This tool will show the path
and all connections.

We can also put a sniffer on each RELAY node to track where packets go.
83 changes: 83 additions & 0 deletions examples/B07-darknet-tor/darknet-tor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env python3
# encoding: utf-8

from seedemu import *
import random


emu = Emulator()

# Load the base layer from the mini Internet example
emu.load('../B00-mini-internet/base-component.bin')


#################################################################
# Create a secret web server. We will use Tor to protect its location

# The following content will be put inside the protected web server
html = """
<html><body>
<h1>This is the secret web server!</h1>
</body></html>
"""

# Create a web server: we will use Tor to protect this server
emu.getLayer('WebService').install("webserver")
emu.getVirtualNode('webserver').setDisplayName('Tor-webserver') \
.setFile(content=html, path="/var/www/html/hello.html")

#################################################################
# Create a Tor component

# Create the Tor service layer
tor = TorService()

# Different types of Tor nodes (virtual nodes)
vnodes = {
"da-1": TorNodeType.DA,
"da-2": TorNodeType.DA,
"da-3": TorNodeType.DA,
"da-4": TorNodeType.DA,
"da-5": TorNodeType.DA,
"client-1": TorNodeType.CLIENT,
"client-2": TorNodeType.CLIENT,
"relay-1": TorNodeType.RELAY,
"relay-2": TorNodeType.RELAY,
"relay-3": TorNodeType.RELAY,
"relay-4": TorNodeType.RELAY,
"exit-1": TorNodeType.EXIT,
"exit-2": TorNodeType.EXIT,
"hidden-service": TorNodeType.HS
}

# Create the virtual nodes
for i, (name, nodeType) in enumerate(vnodes.items()):
if nodeType == TorNodeType.HS:
tor.install(name).setRole(nodeType).linkByVnode("webserver", 80)
else:
tor.install(name).setRole(nodeType)

# Customize the display names.
emu.getVirtualNode(name).setDisplayName("Tor-{}".format(name))



#################################################################
# Bind virtual nodes to physical nodes

as_list = [150, 151, 152, 153, 154, 160, 161, 162, 163, 164, 170, 171]
for i, (name, nodeType) in enumerate(vnodes.items()):
# Pick an autonomous system randomly from the list,
# and create a new host for each Tor node
asn = random.choice(as_list)
emu.addBinding(Binding(name, filter=Filter(asn=asn), action=Action.NEW))

# Bind the web server node to a physical node
emu.addBinding(Binding("webserver", filter=Filter(asn=170), action=Action.NEW))


#################################################################

emu.addLayer(tor)
emu.render()
emu.compile(Docker(), './output')

0 comments on commit 9bfb8ee

Please sign in to comment.