[SOLVED] Can't run gui applications under security constraints

Expected behavior

Need to be able to run GUI applications inside a docker container without upsetting Network Security or having to set the user in the container to have the same UID / GID as the host user.

Actual behavior

I keep upsetting Network Security.

Information

  • the output of:
    • pinata diagnose -u on OSX
      OS X: version 10.10.5 (build: 14F1808)
      Docker.app: version v1.11.1-beta12
      Running diagnostic tests:
      [OK] Moby booted
      [OK] driver.amd64-linux
      [OK] vmnetd
      [OK] osxfs
      [OK] db
      [OK] slirp
      [OK] menubar
      [OK] environment
      [OK] Docker
      [OK] VT-x
      Docker logs are being collected into /tmp/20160524-172235.tar.gz
      Most specific failure is: No error was detected
      Your unique id is: A9BC238C-F4F7-4328-ACB3-4189FD004E89

    • a reproducible case if this is a bug, Dockerfiles FTW

    • page URL if this is a docs issue or the name of a man page

    • host distribution and version ( OSX 10.10.x, OSX 10.11.x, Windows, etc )
      OSX 10.10.5

Steps to reproduce the behavior

  1. Follow the instructions (ish) at http://kartoza.com/how-to-run-a-linux-gui-application-on-osx-using-docker/
  2. Do X-y stuff.
  3. Wait for Network Security to block my machine due to an open port 6000.

I understand that the issue is the socat line, viz:

socat TCP-LISTEN:6000,reuseaddr,fork UNIX-CLIENT:\"$DISPLAY\"

where the container is configured to send to DISPLAY=<IP-of-host's-primary-interface>:0.

What I’d like to do is ensure that socat is only listening to the address from whence my container will be contacting the host. Problem is, I can’t discover what that is. I’ve tried running in short bursts and trying to work out what’s going on with tcpdump. I’ve tried setting socat’s range=172.16.0.0/12 and/or the container’s DISPLAY to 172.17.0.1, to no avail. Ideas at this point would be appreciated.

I believe adding ,bind=127.0.0.1 to the end of your TCP-LISTEN argument should restrict the exposure of the port.

Could you please elaborate on what you mean by

having to set the user in the container to have the same UID / GID as the host user.

? I don’t see how this relates to your X remoting use case.

Thanks for participating in the Docker for Mac Beta!

David

Thanks for your suggestion and questions.

I added the bind argument, as you suggest, so we have:

`+ socat TCP-LISTEN:6000,reuseaddr,fork,bind=127.0.0.1 ‘UNIX-CLIENT:“/private/tmp/com.apple.launchd.oKWPfKG9jM/org.macosforge.xquartz:0”’

  • exec docker run -e DISPLAY=192.168.1.113:0 --rm -it fnalart/hdf5_larsoftobj`

Running an X application gives (e.g.) Error: Can't open display: 192.168.1.113:0
From the host:
$ netstat -an | grep 6000 tcp4 0 0 127.0.0.1.6000 *.* LISTEN

Note that without the bind= option, my X application works just fine, but if I’m at work rather than at home I run into the aforementioned security problems.

As for your other question, I mentioned

having to set the user in the container to have the same UID / GID as the host user.

as an indicator that I was aware of a different way of getting X applications to display from a docker container but I was trying to avoid it if possible because it seems so heavyweight and restricting.

After some research and experimentation, it appears that the correct solution is to use the socat option range=<primary-IP>/32. Since this may change as one moves around with one’s laptop, I have scripted lock control and interface discovery:

LOCKFILE=/tmp/${USER}_docker-xrun.pid
if [[ -f "$LOCKFILE" ]]; then
  echo "INFO: Removing old instance of socat at pid $(cat "${LOCKFILE}")" 1>&2;
  kill -TERM $(cat "${LOCKFILE}")
  sleep 2
  if [[ -f "${LOCKFILE}" ]]; then
    cat 1>&2 <<EOF
ERROR: Unable to remove socat lockfile "${LOCKFILE}" for pid $(cat "${LOCKFILE}")
       Investigate and kill / remove manually as appropriate.
EOF
    exit 1
  fi
fi
export MYHOSTIP=$(NETWORK_INTERFACE 2>/dev/null) # Docker in
# VirtualBox.  XHive (with Docker for Mac Beta): select IP address of
# current primary interface.
interface=$(route -n get 0.0.0.0 | sed -ne '/interface/s&^.* &&p')
#  interface="en0"
[[ -n "${MYHOSTIP}" ]] || \
  MYHOSTIP=$(ifconfig "${interface}" 2>/dev/null | \
                  grep inet | tail -1 | cut -d' ' -f 2)
# Not clever enough to try anything else.
[[ -n "${MYHOSTIP}" ]] || \
  { echo "ERROR: Unable to ascertain host IP!" 1>&2; exit 1; }

export ARGS_DISPLAY="-e DISPLAY=${MYHOSTIP}:0"
open -a XQuartz

### The next must be run in the background. Note the range may be
### different on VirtualBox but is known to work on docker for Mac
### Beta.
socat -L"${LOCKFILE}" \
      TCP-LISTEN:6000,reuseaddr,fork,range=${MYHOSTIP}/32 \
      UNIX-CLIENT:\"$DISPLAY\" &

# Start the docker container.
exec docker run $ARGS_DISPLAY "$@"
1 Like

This has worked for a long time, but recently, I can no longer connect to the X Display.
Not sure if anyone else has come across the same issue?

From my container, I can no longer ping or connect to port 6000 on the host.

Any ideas?

EDIT: as it turns out, seems like it’s related to the docker network which gets created by docker-compose. It doesn’t like it when I start going to the 192.168.0.0 class of networks. (My internal IP address is 192.168.1.x) Worked fine once I started to remove some unused network and re-used the 172.17.x.x space.