253 lines
7.5 KiB
Markdown
253 lines
7.5 KiB
Markdown
+++
|
||
title = "Playing with containers and Tor"
|
||
author = ["Elia el Lazkani"]
|
||
date = 2021-06-21
|
||
lastmod = 2021-06-21
|
||
tags = ["docker", "linux", "ubuntu", "fedora", "proxy", "privoxy"]
|
||
categories = ["container", "text-editors"]
|
||
draft = false
|
||
+++
|
||
|
||
As my followers well know, by now, I am a tinkerer at heart. Why do I do things ? No one knows ! I don't even know.
|
||
|
||
All I know, all I can tell you is that I like to see what can I do with the tools I have at hand. How can I bend them to my will.
|
||
Why, you may ask. The answer is a bit complicated; part of who I am, part of what I do as a DevOps. End line is, this time I was curious.
|
||
|
||
I went down a road that taught me so much more about _containers_, _docker_, _docker-compose_ and even _Linux_ itself.
|
||
|
||
The question I had was simple, **can I run a container only through Tor running in another container?**
|
||
|
||
<!--more-->
|
||
|
||
|
||
## Tor {#tor}
|
||
|
||
I usually like to start topics that I haven't mentioned before with definitions. In this case, what is [Tor](https://2019.www.torproject.org/index.html.en), you may ask ?
|
||
|
||
> Tor is free software and an open network that helps you defend against traffic analysis, a form of network surveillance that threatens personal freedom and privacy, confidential business activities and relationships, and state security.
|
||
|
||
Although that _home_ page is obscure because it was replaced by the new _design_ of the website.
|
||
Although I love what **Tor** has done with all the services they offer, don't get me wrong.
|
||
But giving so much importance on the browser only and leaving the rest for dead when it comes to website, I have to say, I'm a bit sad.
|
||
|
||
Anyway, let's share the love for **Tor** and thank them for the beautiful project they offered humanity.
|
||
|
||
Now that we thanked them, let's abuse it.
|
||
|
||
|
||
### Tor in a container {#tor-in-a-container}
|
||
|
||
The task I set to discover relied on **Tor** being containerized.
|
||
The first thing I do is, simply, not re-invent the wheel.
|
||
Let's find out if someone already took that task.
|
||
|
||
With a litte bit of search, I found the [dperson/torproxy](https://hub.docker.com/r/dperson/torproxy) docker image.
|
||
It isn't ideal but I _believe_ it is written to be rebuilt.
|
||
|
||
Can we run it ?
|
||
|
||
```bash
|
||
docker run -it -p 127.0.0.1:8118:8118 -d dperson/torproxy
|
||
```
|
||
|
||
```bash
|
||
curl -Lx http://localhost:8118 http://jsonip.com/
|
||
```
|
||
|
||
And this is **definitely** not your IP. Don't take _my word_ for it!
|
||
Go to [http://jsonip.com/](http://jsonip.com/) in a browser and see for yourself.
|
||
|
||
Now that we **know** we can run **Tor** in a container effectively, let's kick it up a _notch_.
|
||
|
||
|
||
## docker-compose {#docker-compose}
|
||
|
||
I will be _testing_ and making changes as I go along. For this reason, it's a good idea to use [docker-compose](https://docs.docker.com/compose/) to do this.
|
||
|
||
> Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration.
|
||
|
||
_Now_ that we saw what the **docker** team has to say about **docker-compose**, let's go ahead and use it.
|
||
|
||
First, let's implement what we just ran _ad-hoc_ in **docker-compose**.
|
||
|
||
```yaml
|
||
---
|
||
version: '3.9'
|
||
services:
|
||
torproxy:
|
||
image: dperson/torproxy
|
||
container_name: torproxy
|
||
restart: unless-stopped
|
||
```
|
||
|
||
|
||
## Air-gapped container {#air-gapped-container}
|
||
|
||
The next piece of the puzzle is to figure out **if** and **how** can we create an _air-gapped container_.
|
||
|
||
It turns out, we can create an `internal` network in _docker_ that has no access to the internet.
|
||
|
||
First, the _air-gapped container_.
|
||
|
||
```yaml
|
||
air-gapped:
|
||
image: ubuntu
|
||
container_name: air-gapped
|
||
restart: unless-stopped
|
||
command:
|
||
- bash
|
||
- -c
|
||
- sleep infinity
|
||
networks:
|
||
- no-internet
|
||
```
|
||
|
||
Then comes the network.
|
||
|
||
```yaml
|
||
networks:
|
||
no-internet:
|
||
driver: bridge
|
||
internal: true
|
||
```
|
||
|
||
Let's put it all together in a `docker-compose.yaml` file and run it.
|
||
|
||
```bash
|
||
docker-compose up -d
|
||
```
|
||
|
||
Keep that terminal open, and let's put the _hypothesis_ to the test and see if rises up to be a _theory_.
|
||
|
||
```bash
|
||
docker exec air-gapped apt-get update
|
||
```
|
||
|
||
Aaaaand...
|
||
|
||
```text
|
||
Err:1 http://archive.ubuntu.com/ubuntu focal InRelease
|
||
Temporary failure resolving 'archive.ubuntu.com'
|
||
Err:2 http://security.ubuntu.com/ubuntu focal-security InRelease
|
||
Temporary failure resolving 'security.ubuntu.com'
|
||
Err:3 http://archive.ubuntu.com/ubuntu focal-updates InRelease
|
||
Temporary failure resolving 'archive.ubuntu.com'
|
||
Err:4 http://archive.ubuntu.com/ubuntu focal-backports InRelease
|
||
Temporary failure resolving 'archive.ubuntu.com'
|
||
Reading package lists...
|
||
W: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/focal/InRelease Temporary failure resolving 'archive.ubuntu.com'
|
||
W: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/focal-updates/InRelease Temporary failure resolving 'archive.ubuntu.com'
|
||
W: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/focal-backports/InRelease Temporary failure resolving 'archive.ubuntu.com'
|
||
W: Failed to fetch http://security.ubuntu.com/ubuntu/dists/focal-security/InRelease Temporary failure resolving 'security.ubuntu.com'
|
||
W: Some index files failed to download. They have been ignored, or old ones used instead.
|
||
```
|
||
|
||
looks like it's real peeps, **hooray** !
|
||
|
||
|
||
## Putting everything together {#putting-everything-together}
|
||
|
||
Okay, now let's put everything together. The list of changes we need to make are minimal.
|
||
First, I will list them, then I will simply write them out in **docker-compose**.
|
||
|
||
- Create an `internet` network for the **Tor** container
|
||
- Attach the `internet` network to the **Tor** container
|
||
- Attach the `no-internet` network to the **Tor** container so that our _air-gapped_ container can access it.
|
||
|
||
Let's get to work.
|
||
|
||
```yaml
|
||
---
|
||
version: '3.9'
|
||
services:
|
||
|
||
torproxy:
|
||
image: dperson/torproxy
|
||
container_name: torproxy
|
||
restart: unless-stopped
|
||
networks:
|
||
- no-internet
|
||
- internet
|
||
|
||
air-gapped:
|
||
image: ubuntu
|
||
container_name: air-gapped
|
||
restart: unless-stopped
|
||
command:
|
||
- bash
|
||
- -c
|
||
- sleep infinity
|
||
networks:
|
||
- no-internet
|
||
|
||
networks:
|
||
no-internet:
|
||
driver: bridge
|
||
internal: true
|
||
internet:
|
||
driver: bridge
|
||
internal: false
|
||
```
|
||
|
||
Run everything.
|
||
|
||
```bash
|
||
docker-compose up -d
|
||
```
|
||
|
||
Yes, this will run it in the background and there is **no** need for you to open another terminal.
|
||
It's always _good_ to know **both** ways. Anyway, let's test.
|
||
|
||
let's `exec` into the container.
|
||
|
||
```bash
|
||
docker exec -it air-gapped bash
|
||
```
|
||
|
||
Then we configure `apt` to use our `torproxy` service.
|
||
|
||
```bash
|
||
echo 'Acquire::http::Proxy "http://torproxy:8118/";' > /etc/apt/apt.conf.d/proxy
|
||
echo "export HTTP_PROXY=http://torproxy:8118/" >> ~/.bashrc
|
||
echo "export HTTPS_PROXY=http://torproxy:8118/" >> ~/.bashrc
|
||
export HTTP_PROXY=http://torproxy:8118/
|
||
export HTTPS_PROXY=http://torproxy:8118/
|
||
apt-get update
|
||
apt-get upgrade -y
|
||
DEBIAN_FRONTEND=noninteractive apt-get install -y curl
|
||
```
|
||
|
||
|
||
## Harvesting the fruits of our labour {#harvesting-the-fruits-of-our-labour}
|
||
|
||
First, we **always** check if everything is set correctly.
|
||
|
||
While inside the container, we check the _environment variables_.
|
||
|
||
```bash
|
||
env | grep HTTP
|
||
```
|
||
|
||
You should see.
|
||
|
||
```text
|
||
HTTPS_PROXY=http://torproxy:8118/
|
||
HTTP_PROXY=http://torproxy:8118/
|
||
```
|
||
|
||
Then, we curl our **IP**.
|
||
|
||
```bash
|
||
curl https://jsonip.com/
|
||
```
|
||
|
||
And that is also not your **IP**.
|
||
|
||
It works !
|
||
|
||
|
||
## Conclusion {#conclusion}
|
||
|
||
Is it possible to route a container through another **Tor** container ?
|
||
|
||
The answer is _obviously_ **Yes** and this is the way to do it. Enjoy.
|