Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docker socket proxy support #15

Open
Pingumania opened this issue Jan 6, 2022 · 8 comments
Open

Docker socket proxy support #15

Pingumania opened this issue Jan 6, 2022 · 8 comments
Labels
enhancement New feature or request

Comments

@Pingumania
Copy link

Would it be possible to implement support for Docker Socket Proxy?

This probably isn't possible if the host networking mode is required.

@kaysond kaysond added the enhancement New feature or request label Jan 7, 2022
@kaysond
Copy link
Owner

kaysond commented Jan 7, 2022

It should already be supported, actually. You just need to set the DOCKER_HOST env var, and the docker command in the container will automatically connect to whatever you set it to (i.e. the docker-socket-proxy tcp socket). It won't work in swarm, but it would be relatively easy to add.

I'm curious why you want to use dsp. Running trafficjam in a container is just a convenience. You could just as easily run the script as root on the host itself. Since the container isn't connected to the outside world, the risk of giving it access to the docker socket is essentially zero.

@Pingumania
Copy link
Author

Pingumania commented Jan 8, 2022

I'm curious why you want to use dsp. Running trafficjam in a container is just a convenience. You could just as easily run the script as root on the host itself. Since the container isn't connected to the outside world, the risk of giving it access to the docker socket is essentially zero.

Honestly just my OCD, all my services that require access to the docker socket use the dsp. I also don't see any security concerns.

I hadn't had the time to test DOCKER_HOST yet.

@kaysond
Copy link
Owner

kaysond commented Jan 8, 2022

Honestly just my OCD

I totally get it. I'm the same! I'm gonna close this but feel free to comment if you have trouble with the env var

@kaysond kaysond closed this as completed Jan 8, 2022
@Adito5393
Copy link

Hey @kaysond, thanks for sharing this cool, simple tool.
I have managed to run it behind the Docker socket proxy with only 2 permissions (CONTAINERS & NETWORKS). Unfortunately, it can only run if the proxy is also in network_mode: host. (or so, I thought..)

Here is the docker-compose.yml you want to give a try:

version: "3.9"

networks:
  traefik_net:
    external: true
  backend_traefik:
    external: false

services:
  traefik:
    container_name: traefik
    image: traefik:latest
    restart: always
    networks:
      - backend_traefik

  proxy-docker:
    image: tecnativa/docker-socket-proxy:0.1.1
    container_name: traefik_docker_socket_proxy
    restart: always
    networks:
      - backend_traefik
    privileged: true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - LOG_LEVEL=warning
      # Traefik ONLY!
      - CONTAINERS=1

  trafficjam-proxy-docker:
    image: tecnativa/docker-socket-proxy:0.1.1
    container_name: traefik_trafficjam_socket_proxy
    restart: always
    network_mode: host
    privileged: true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - LOG_LEVEL=warning
      - CONTAINERS=1
      - NETWORKS=1

  trafficjam:
    image: kaysond/trafficjam:v2.1.1
    container_name: traefik_trafficjam
    restart: always
    cap_add:
      - NET_ADMIN
    network_mode: host
    environment:
      - DOCKER_HOST=tcp://0.0.0.0:2375
      - TZ
      - NETWORK=traefik_net
      - WHITELIST_FILTER=ancestor=traefik:2.10
      - DEBUG=1

This setup, however, opens the docker tcp port on the host:

ss -tulpn | grep LISTEN
tcp   LISTEN 0      3000         0.0.0.0:2375      0.0.0.0:*    users:(("haproxy",pid=28169,fd=6))

Run the docker-socket-proxy on a dedicated network

Then, the issue is that I can't use the docker DNS for the tcp URL, e.g. DOCKER_HOST=tcp://traefik_trafficjam_socket_proxy:2375

traefik_trafficjam  | [2023-06-07 18:47:00] ERROR: Unexpected error while determining network driver: 
traefik_trafficjam  | error during connect: Get "http://trafficjam-proxy-docker:2375/v1.24/networks/traefik_net": dial tcp: lookup trafficjam-proxy-docker on 1.1.1.1:53: no such host

If I hard code the DOCKER_HOST to the trafficjam-proxy-docker located on it's dedicated subnetwork (DOCKER_HOST=tcp://172.22.0.2:2375), it works.

TLDR

How can I set automatically the env DOCKER_HOST to use the IP of a certain container?
On the host, I can infer it via:

docker container inspect -f '{{ .NetworkSettings.Networks.traefik_backend_trafficjam.IPAddress }}' traefik_trafficjam_socket_proxy
172.22.0.2

@kaysond
Copy link
Owner

kaysond commented Jun 8, 2023

How can I set automatically the env DOCKER_HOST to use the IP of a certain container?

I don't think you can, unfortunately.

Then, the issue is that I can't use the docker DNS for the tcp URL, e.g. DOCKER_HOST=tcp://traefik_trafficjam_socket_proxy:2375

This doesn't work because when you use network_mode: host, it uses the host DNS server by default. You might be able to play with some of the container dns options and get it to use the docker dns server instead: https://docs.docker.com/network/#dns-services

This setup, however, opens the docker tcp port on the host:

I don't really see this as a big problem, though you should probably configure it to bind to localhost (127.0.0.1) only, instead of 0.0.0.0. The proxy is set to read only anyways, so even if an attacker could access the port, they couldn't do anything permanent with it. They could get some information about your docker networks and containers, but realistically, if someone can access it, you're probably in bad shape anyways.

This does bring up a good point, though, that it's not trivial to get dsp working when you have to be on the host network namespace. I'll have to give it some more thought. There might be some tricks you can play with iptables and veth interfaces (which could be automated via the container).

@kaysond kaysond reopened this Jun 8, 2023
@kaysond
Copy link
Owner

kaysond commented Jun 8, 2023

In the meantime, though, you could set the dsp container to have a static ip: https://www.howtogeek.com/devops/how-to-assign-a-static-ip-to-a-docker-container/

@Adito5393
Copy link

Adito5393 commented Jun 16, 2023

Thanks @kaysond for the idea!
I will share here the complete working docker-compose.yml for others not to waste time figuring it out:

version: "3.9"

networks:
  traefik_net:
    external: true
  backend_traefik:
    external: false
  backend_trafficjam:
    external: false
    ipam:
      driver: default
      config:
        - subnet: 172.16.238.0/30

services:
  traefik:
    container_name: traefik
    image: traefik:2.10
    restart: always
    # ... rest of your config
    networks:
      - backend_traefik

  # Docker Socket Proxy - Security Enchanced Proxy for Docker Socket
  proxy-docker:
    image: custom-image/docker-socket-proxy:0.1.1
    container_name: traefik_docker_socket_proxy
    restart: always
    networks:
      - backend_traefik
    privileged: true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      # debug,info,notice,warning,err,crit,alert,emerg
      - LOG_LEVEL=warning
      # Traefik ONLY!
      - CONTAINERS=1

  trafficjam-proxy-docker:
    image: custom-image/docker-socket-proxy:0.1.1
    container_name: traefik_trafficjam_socket_proxy
    # restart: always
    privileged: true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      # debug,info,notice,warning,err,crit,alert,emerg
      - LOG_LEVEL=warning
      - CONTAINERS=1
      - NETWORKS=1
    networks:
      backend_trafficjam:
        ipv4_address: 172.16.238.2
    depends_on:
      - traefik

  trafficjam:
    image: kaysond/trafficjam:v2.1.1
    container_name: traefik_trafficjam
    # restart: always
    cap_add:
      - NET_ADMIN
    network_mode: host
    environment:
      - DOCKER_HOST=tcp://172.16.238.2:2375
      - TZ
      - NETWORK=traefik_net
      - WHITELIST_FILTER=ancestor=traefik:2.10
      - DEBUG=1
    depends_on:
      - trafficjam-proxy-docker

Pay special attention to the depends_on: part of the config.
FYI: the custom-image/docker-socket-proxy was created to fix the "Provider connection error unexpected EOF" as discussed in issue 21:

ARG TAG=0.1.1
FROM ghcr.io/tecnativa/docker-socket-proxy:$TAG

RUN apk add --no-cache curl

HEALTHCHECK --interval=9m --timeout=5s --retries=3 \
  CMD curl -f http://localhost:2375/_ping || exit 1

Feel free to link to this comment inside the README.md file (so people don't expect you to provide support for this type of configuration)

PS: I also get this warning (see issue 79 and 74) and everything seems to work as expected:
traefik_docker_socket_proxy | [WARNING] 166/085731 (1) : Can't open server state file '/var/lib/haproxy/server-state': No such file or directory

@Adito5393
Copy link

For future users, I've switched to CetusGuard for better API rules support and these are the rules that work for me:

  trafficjam-proxy-docker:
    image: docker.io/hectorm/cetusguard:v1.0.11
    container_name: traefik_trafficjam_socket_proxy
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      CETUSGUARD_BACKEND_ADDR: "unix:///var/run/docker.sock"
      CETUSGUARD_FRONTEND_ADDR: "tcp://:2375"
      CETUSGUARD_RULES: |
        ! List containers
        GET %API_PREFIX_CONTAINERS%/json
        ! Inspect a container
        GET %API_PREFIX_CONTAINERS%/%CONTAINER_ID%/json
        ! Inspect a network
        GET %API_PREFIX_NETWORKS%/%NETWORK_NAME%
      # Warning = 4 and Debug = 7
      CETUSGUARD_LOG_LEVEL: "4"
    networks:
      backend_trafficjam:
        ipv4_address: 172.16.238.2
    depends_on:
      - traefik

The rest of the yml is the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants