Troubleshooting traffic routing with Dante Proxy in Docker containers

Hello,

I am seeking assistance in this matter, as I have exhausted my options and lack the necessary knowledge to resolve the issue I am facing.

Disclaimer

I am primarily a graphic designer, with my technical knowledge limited to front-end development (HTML, SCSS, JS) and basic router configuration. So I might be unfamiliar with some basic concepts that are evident to others, for which I apologize in advance.

Objective

TL;DR
My goal is to operate two VPNs – currently just one – simultaneously in separate containers, directing traffic to different browsers through a SOCKS5 proxy, while the rest of the system’s traffic remains direct.


Due to various needs, I operate my personal MacBook M1 both at work and remotely, often needing to access corporate network resources. I prefer not to install Palo Alto GlobalProtect (VPN) software on my personal device. Additionally, I use a private VPN (Mullvad) on networks outside my home to maintain my privacy. I also aim to avoid directing all my device’s traffic through VPNs to ensure smooth streaming (via Safari) and gaming (on Steam).

Having heard about Docker from my colleagues, I decided to utilize it to create separate containers: one for the corporate VPN and another for private internet use, each configured with OpenConnect/OpenVPN and proxy servers. This setup would enable me to connect designated browsers or apps through a SOCKS5 proxy on my macOS, thus accessing specific resources like the corporate network without compromising other activities.

For the private VPN, I intended to use Gluetun, but have yet to proceed as I’ve encountered difficulties with the PaloAlto implementation.

Action taken

I succeeded in setting up a container using OpenConnect that effectively connects to the VPN server. Additionally, I incorporated a Dante proxy server to facilitate traffic routing from the container to the system.

I turned to the insights of more experienced individuals and found a project by ducmthai.

However, this approach ultimately led to the same issue I was initially facing.

Problem

TL;DR VPN operates inside the container but does not allow external traffic.


Within the container, I can access services on the corporate network. However, attempts to transmit external traffic fail; ports are visible yet unresponsive, as confirmed by unsuccessful attempts with ‘curl’ and Firefox through SOCKS5 (the proxy server disconnects or exceeds connection time limits).

The tests were performed on two devices: a MacBook M1 and a brand-new MacBook M3, both running macOS Sonoma 14.4.1 with firewalls turned off and Docker version 4.29.0 installed. Only Firefox, Brew, and Docker have been set up on the M3. Both machines yielded identical results from the tests.


Details (logs, configuration, commands)

Ports

In a container

root@cb0c4ae24961:/# netstat -tulnp | grep 8888
tcp        0      0 0.0.0.0:**8888**         0.0.0.0:*               LISTEN      69/danted           

In the system

ganymede@macbook ~ % nc -v 127.0.0.1 8888
Connection to 127.0.0.1 port 8888 [tcp/ndl-aas] succeeded

Connection

In a container

ganymede@macbook vpn-proxy % docker exec -it vpn_proxy /bin/bash 
ff153b881395:/# ping google.com
PING google.com (142.250.203.142): 56 data bytes
64 bytes from 142.250.203.142: seq=0 ttl=115 time=106.399 ms
64 bytes from 142.250.203.142: seq=1 ttl=115 time=125.724 ms
64 bytes from 142.250.203.142: seq=2 ttl=115 time=110.234 ms
^C
--- google.com ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 106.399/114.119/125.724 ms
ff153b881395:/# ping service.company.com
PING service.company.com (XXX.18.0.XXX): 56 data bytes
64 bytes from XXX.18.0.XXX: seq=0 ttl=61 time=53.767 ms
64 bytes from XXX.18.0.XXX: seq=1 ttl=61 time=49.910 ms
64 bytes from XXX.18.0.XXX: seq=2 ttl=61 time=63.906 ms
64 bytes from XXX.18.0.XXX: seq=3 ttl=61 time=84.899 ms
^C
--- service.company.com ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 49.910/63.120/84.899 ms
ff153b881395:/

Curl also worked.

In the system

ganymede@macbook ~ % curl -v -x socks5h://127.0.0.1:8888 http://www.google.com
*   Trying 127.0.0.1:8888...
* Connected to 127.0.0.1 (127.0.0.1) port 8888
* Recv failure: Connection reset by peer
* SOCKS4: Failed receiving initial SOCKS5 response: Failure when receiving data from the peer
* Closing connection
curl: (97) Recv failure: Connection reset by peer

ganymede@macbook ~ % curl -v -x socks5://127.0.0.1:8888 http://www.google.com
*   Trying 127.0.0.1:8888...
* Connected to 127.0.0.1 (127.0.0.1) port 8888
* Recv failure: Connection reset by peer
* SOCKS4: Failed receiving initial SOCKS5 response: Failure when receiving data from the peer
* Closing connection
curl: (97) Recv failure: Connection reset by peer

Firefox

  • Host SOCKS: 127.0.0.1, Port: 8888
  • SOCKS v5
  • Proxy DNS checked

Logs

Docker

2024-05-12 01:27:16 POST https://vpn.company.com/ssl-vpn/prelogin.esp?tmp=tmp&clientVer=4100&clientos=Linux
2024-05-12 01:27:16 Connected to XXX.XXX.XX.XXX:443
2024-05-12 01:27:16 Client certificate has expired at: Sat, 13 Apr 2024 13:06:44 GMT
2024-05-12 01:27:16 Using client certificate 'Name Surname'
2024-05-12 01:27:16 SSL negotiation with vpn.company.com
2024-05-12 01:27:16 Connected to HTTPS on vpn.company.com
2024-05-12 01:27:16 Enter login credentials
2024-05-12 01:27:16 POST https://vpn.company.com/ssl-vpn/login.esp
2024-05-12 01:27:17 GlobalProtect login returned authentication-source=EXTERNAL_CI_ldap-auth_profile
2024-05-12 01:27:17 POST https://vpn.company.com/ssl-vpn/getconfig.esp
2024-05-12 01:27:17 Session will expire after 43200 minutes.
2024-05-12 01:27:17 Tunnel timeout (rekey interval) is 180 minutes.
2024-05-12 01:27:17 Idle timeout is 180 minutes.
2024-05-12 01:27:17 Potential IPv6-related GlobalProtect config tag <ipv6-connection>: no
2024-05-12 01:27:17 This build does not support GlobalProtect IPv6 due to a lack of
2024-05-12 01:27:17 of information on how it is configured. Please report this
2024-05-12 01:27:17 to <openconnect-devel@lists.infradead.org>.
2024-05-12 01:27:17 No MTU received. Calculated 65454 for ESP tunnel
2024-05-12 01:27:17 POST https://vpn.company.com/ssl-vpn/hipreportcheck.esp
2024-05-12 01:27:17 Connected as 10.XX.XXX.XXX, using SSL, with ESP in progress
2024-05-12 01:27:17 ESP session established with server
2024-05-12 01:27:17 ESP tunnel connected; exiting HTTPS mainloop.
2024-05-12 01:27:27 May 11 23:27:27 (1715470047.136295) danted[69]: info: Dante/server[1/1] v1.4.2 running

Current configuration

Dockerfile

# Use a specific version of the Ubuntu base image to avoid mismatches
FROM ubuntu:20.04

# Set a non-interactive front-end for easier Docker building
ENV DEBIAN_FRONTEND=noninteractive

# Install network utilities including ping
RUN apt-get update && apt-get install -y \
    iputils-ping \
    traceroute \
    curl

# Update and install necessary packages
RUN apt-get update && \
    apt-get -y upgrade && \
    apt-get install -y openconnect iproute2 dante-server --fix-missing

# List all files installed by the dante-server
RUN dpkg -L dante-server

# Verify if dante-server installed successfully
RUN which dante-server || echo "Dante-server binary location not found"

# Attempt to locate the sockd binary
RUN which sockd || find / -name sockd -type f || echo "sockd binary not found"

# Clean up to reduce image size
RUN apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# Copy the configurations and scripts
COPY certificate.pem /etc/openconnect/
COPY private-key.pem /etc/openconnect/
COPY sockd.conf /etc/
COPY entrypoint.sh /entrypoint.sh

# Ensure the entrypoint script is executable
RUN chmod +x /entrypoint.sh

EXPOSE 8888

# Execute the entrypoint script on container start
ENTRYPOINT ["/entrypoint.sh"]
CMD ["sleep", "infinity"]

entrypoint.sh (VPN)

#!/bin/bash

# Start the OpenConnect VPN connection (in background)
echo '********************' | openconnect \
    --protocol=gp \
    --verbose \
    --user=name.surname@company.com \
    --passwd-on-stdin \
    --certificate=/etc/openconnect/certificate.pem \
    --sslkey=/etc/openconnect/private-key.pem \
    https://vpn.company.com/gateway &

# Delay to ensure connection stability
sleep 10

# Start the Dante SOCKS server using the correct binary name
/usr/sbin/danted -f /etc/sockd.conf

# Keep the script running
wait $!

sockd.conf (Dante)

logoutput: stderr
# debug: 1

internal: 0.0.0.0 port = 8888
external: eth0

clientmethod: none
socksmethod: none
user.privileged: root
user.unprivileged: nobody

client pass {
    from: 0.0.0.0/0 to: 0.0.0.0/0
    log: connect disconnect
}

socks pass {
    from: 0.0.0.0/0 to: 0.0.0.0/0
    log: connect disconnect
    command: bind connect udpassociate
}

Docker run

docker run -it --rm --privileged --cap-add=NET_ADMIN --name=myvpn -p 8888:8888 openconnect-socks
1 Like

@auganymede Have you figured it out ?