Hello,
I’m currently working on a blogpost to detail how to use docker containers from inside whonix workstation, but i’m facing the problem of how to make the docker container connect to the internet like how it would be on a regular debian VM.
Here’s my docker-compose.yml file:
[workstation user ~]% cat docker-compose.yml
services:
myalpine:
image: alpine
tty: true
network_mode: host
environment:
- 'HTTP_PROXY=socks5://host.docker.internal:9050'
- 'HTTPS_PROXY=socks5://host.docker.internal:9050'
extra_hosts:
- host.docker.internal:host-gateway
so i do docker-compose up to create the container:
[workstation user ~]% sudo docker-compose down ; sudo docker-compose up -d
Stopping user_myalpine_1 ... done
Removing user_myalpine_1 ... done
Creating user_myalpine_1 ... done
[workstation user ~]% sudo docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0752ecb83c6b alpine "/bin/sh" 43 seconds ago Up 42 seconds user_myalpine_1
[workstation user ~]% sudo docker exec -it 0752 sh
[workstation user ~]% sudo docker exec -it 0752 sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP qlen 1000
link/ether 52:54:00:e8:c3:50 brd ff:ff:ff:ff:ff:ff
inet 10.152.152.11/18 brd 10.152.191.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fee8:c350/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:8c:ad:6a:cd brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:8cff:fead:6acd/64 scope link
valid_lft forever preferred_lft forever
15: br-973a58a1c943: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:35:83:6e:bc brd ff:ff:ff:ff:ff:ff
inet 172.19.0.1/16 brd 172.19.255.255 scope global br-973a58a1c943
valid_lft forever preferred_lft forever
inet6 fe80::42:35ff:fe83:6ebc/64 scope link
valid_lft forever preferred_lft forever
/ # nc 10.152.152.11 -p 9050
nc: bind: Address in use
I made the docker-compose.yml use the network_mode: host
to try and make sure it’s as close to the whonix workstation networking as possible, using a NAT/bridge mode is also possible, however i didnt try that yet (lmk if i should)
But the problem is that once in the docker container i see that it is unable to contact the internet:
/ # apk update
fetch https://dl-cdn.alpinelinux.org/alpine/v3.22/main/x86_64/APKINDEX.tar.gz
WARNING: updating and opening https://dl-cdn.alpinelinux.org/alpine/v3.22/main: temporary error (try again later)
fetch https://dl-cdn.alpinelinux.org/alpine/v3.22/community/x86_64/APKINDEX.tar.gz
WARNING: updating and opening https://dl-cdn.alpinelinux.org/alpine/v3.22/community: temporary error (try again later)
4 unavailable, 0 stale; 16 distinct packages available
/ # wget 1.1.1.1 -O -
Connecting to 1.1.1.1 (1.1.1.1:80)
wget: can't connect to remote host (1.1.1.1): Operation timed out
any idea on what i should do to make sure that the container can reach the internet ?
after testing the command that was suggested in that other thread:
sudo docker run --rm -it --network=host debian:bookworm bash -c “apt-get update”
it doesnt seem to resolve DNS unlike in that other thread. Also when failing to connect to 1.1.1.1 using wget hints to me that this is a network routing problem, since dns is not involved in that test
I have the current latest whonix version, so its a different environment.
What part of the whonix firewall should I change to make it work exactly ?
Unknown. Unsupported.
Short of that, the only thing you can try is disable Whonix-Workstation firewall entirely.
Documentation how to do so and implications of that, see:
just posting an update in here for others that want to try that setup, i think someone in my community might’ve found how to get it to work:
http://git.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/nihilist/blog-contributions/issues/352
Just need to follow http://www.dds6qkxpwdeubwucdiaord2xgbbeyds25rbsgr73tbfpqpt4a6vjwsyd.onion/wiki/Whonix-Workstation_Firewall#Additional_User_Custom_Firewall_Rules, adding the following rules to the /usr/bin/user-firewall-script file:
#!/bin/bash
set -euo pipefail
# Allow Docker to access the Internet via Tor
nft insert rule inet filter forward index 0 oifname docker0 counter accept
nft insert rule inet filter forward index 0 iifname docker0 counter accept
apparently this works as intended, but i didnt test it myself yet
Let’s see what we can do to improve this situation.
I would appreciate if someone could test if this is working.
A) We could always unconditionally allow the traffic on the docker0
network interface. (Not very flexible if the using multiple docker interfaces docker1
, docker2
, etc.)
B) Wildcard allow all docker*
.
add rule inet filter input iifname "docker*" counter accept
add rule inet filter output oifname "docker*" counter accept
(https://unix.stackexchange.com/questions/606874/is-there-a-sort-of-wildcards-in-)
Is there any reason against allowing all docker loopback traffic by default?
- Then all containers might be able talk to each other by default. This might be unwanted in some advanced use cases.
- Compromised container might be able to scan the system running docker.
- Dunno what else.
C) We could add support for a list of network interfaces to be declared using a Whonix firewall configuration drop-in snippet.
(iiftype bridge
- does not exist.)
Will be documented here:
https://www.whonix.org/wiki/Docker
I’m not sure what we’re doing differently, but over here at least the Docker example you give “just works”, without having to do anything special to the firewall:
[workstation user ~/alpine-proj]% ls
docker-compose.yml
[workstation user ~/alpine-proj]% cat docker-compose.yml
services:
myalpine:
image: alpine
tty: true
network_mode: host
environment:
- 'HTTP_PROXY=socks5://host.docker.internal:9050'
- 'HTTPS_PROXY=socks5://host.docker.internal:9050'
extra_hosts:
- host.docker.internal:host-gateway
[workstation user ~/alpine-proj]% sudo docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e452ff98502b alpine "/bin/sh" 2 minutes ago Up 2 minutes alpine-proj_myalpine_1
[workstation user ~/alpine-proj]% sudo docker exec -it e452 sh
/ # wget 1.1.1.1
Connecting to 1.1.1.1 (1.1.1.1:80)
Connecting to 1.1.1.1 (1.1.1.1:443)
Connecting to one.one.one.one (1.1.1.1:443)
saving to 'index.html'
index.html 100% |*****************************************************************| 56614 0:00:00 ETA
'index.html' saved
apk update
also works, and I can also download the index.html
page from torproject.org with wget
. Confusingly, wget https://check.torproject.org
fails with wget: bad address 'check.torproject.org'
under Alpine, but in a Debian container, apt
works, I can install wget
, wget https://check.torproject.org
works, and the downloaded page tells me “Congratulations. This browser is configured to use Tor.”
So… either I have some weird configuration opening things up more than normal on my system, or maybe you have some config on your system that is closing things more than normal?
1 Like