How can you make a docker container inside whonix workstation connect to the internet?

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 ?

Duplicate of DNS Docker Temporary failure resolving Whonix 17.3 - same answers apply.

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