skip to Main Content

I’d like to set up a private cloud network using docker-compose that is only accessible via WireGuard. The private network contains multiple services but no service should be accessible from the internet and containers internal to the network should not have internet access. The only port exposed for this network is 51820 for WireGuard.

I have everything working exactly how I want except for one problem: the containers in the private network have internet access. If I block container internet access by specifying internal: true on the custom private network, it breaks access to the wireguard network for all peers/clients.

Here is my docker-compose file:

version: "2.1"
services:
  wireguard:
    image: lscr.io/linuxserver/wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      - PUID=1000
      - PGID=1000
      - SERVERPORT=51820
      - PEERS=1
      - PEERDNS=192.168.100.254
      - INTERNAL_SUBNET=10.10.0.0
      - ALLOWEDIPS=10.10.0.0/16,192.168.100.0/24
    volumes:
      - /root/wireguard/config:/config
      - /lib/modules:/lib/modules
    ports:
      - 51820:51820/udp
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    networks:
      private:
        ipv4_address: 192.168.100.10
    restart: unless-stopped
  unbound:
    image: "mvance/unbound:latest"
    volumes:
      - ./unbound:/opt/unbound/etc/unbound/
    networks:
      private:
        ipv4_address: 192.168.100.254
  nginx:
    image: nginx
    networks:
      private:
        ipv4_address: 192.168.100.20


networks:
  private:
#    internal: true # Breaks WireGuard for all clients if uncommented
    ipam:
      driver: default
      config:
        - subnet: 192.168.100.0/24

I’d like to avoid custom iptables rules but I’m open to any suggestions.

2

Answers


  1. I think you want two networks: an internal one to isolate the service containers, and an external one to provide the wireguard container with external access. Somethinglike:

    version: "2.1"
    services:
      wireguard:
        image: lscr.io/linuxserver/wireguard
        cap_add:
          - NET_ADMIN
          - SYS_MODULE
        environment:
          - PUID=1000
          - PGID=1000
          - SERVERPORT=51820
          - PEERS=1
          - PEERDNS=192.168.100.254
          - INTERNAL_SUBNET=10.10.0.0
          - ALLOWEDIPS=10.10.0.0/16,192.168.100.0/24
        volumes:
          - /root/wireguard/config:/config
          - /lib/modules:/lib/modules
        ports:
          - 51820:51820/udp
        sysctls:
          - net.ipv4.conf.all.src_valid_mark=1
        networks:
          outside:
          private:
            ipv4_address: 192.168.100.10
        restart: unless-stopped
      unbound:
        image: "mvance/unbound:latest"
        volumes:
          - ./unbound:/opt/unbound/etc/unbound/
        networks:
          private:
            ipv4_address: 192.168.100.254
      nginx:
        image: nginx
        networks:
          private:
            ipv4_address: 192.168.100.10
    
    
    networks:
      outside:
      private:
        internal: true
        ipam:
          driver: default
          config:
            - subnet: 192.168.100.0/24
    

    This is only a partial solution; you’ll need to arrange for your
    service containers to route through the wireguard container; as
    currently configured, your containers have a default route of
    192.168.100.1, which probably isn’t useful.

    Also note that you’ve assigned the same ip address to your wireguard container and to the nginx container (192.168.100.10), which is probably a typo.

    Login or Signup to reply.
  2. Because I think I’m doing something similar to you (for now, I heard of other softwares I could use), I am going to presume I am either close to your intent, or in the same camp. You want to use your Wireguard VPN service to provide a DHCP network across your VPN users. This is, in many ways, similar to having one computer out on the internet try to join your docker swarm. You want to deny access to them, you’d at least want them within your local net.

    In your case, now that your first correct answer tells you that you need TWO docker networks to make an internal docker network, the SECOND correct answer needs to tell you that your existing internal network configurations are incorrect. Since this answer’s almost a year outdated, there’s no telling if an upgraded version value would change your YML to my answer. So here goes.

    For clients attached via your VPN, you do have to route them internally using a docker overlay network. You need gateway for the network these ipam IPs are on to be set to the Wireguard host. In other words, your config would look like this, including @larsks answer:
    (As a note, I reduced your allowed hosts on the subnet VPN but not the docker network. The Docker Network is still large spanning .10, .20, .254, and .100 therefore weighing a constraint on the overlay, see the docker network documentation later on overlay network sizes. )

    version: "2.1"
    services:
      wireguard:
        image: lscr.io/linuxserver/wireguard
        cap_add:
          - NET_ADMIN
          - SYS_MODULE
        environment:
          - PUID=1000
          - PGID=1000
          - SERVERPORT=51820
          - PEERS=1
          - PEERDNS=192.168.100.254
          - INTERNAL_SUBNET=10.10.0.0
          - ALLOWEDIPS=10.10.0.0/25,192.168.100.0/24
        volumes:
          - /root/wireguard/config:/config
          - /lib/modules:/lib/modules
        ports:
          - 51820:51820/udp
        sysctls:
          - net.ipv4.conf.all.src_valid_mark=1
        networks:
          outside:
          private:
            ipv4_address: 192.168.100.10
        restart: unless-stopped
      unbound:
        image: "mvance/unbound:latest"
        volumes:
          - ./unbound:/opt/unbound/etc/unbound/
        networks:
          private:
            ipv4_address: 192.168.100.254
      nginx:
        image: nginx
        networks:
          private:
            ipv4_address: 192.168.100.20
    
    
    networks:
      outside:
      private:
        internal: true
        ipam:
          driver: overlay
          config:
            - subnet: 192.168.100.0/24
            - subnet: 10.10.0.0/25
            - allocate-ip: 192.168.100.0/24
            - gateway: 192.168.100.10
            - gateway: 10.10.0.1
    

    I intend that the above configuration makes…

    1. WireGuard start up on 10.10.0.1 as the VPN Subnet gateway, with the Docker network granting WireGuard the access to both the wild internet as a default bridge, and access to the local docker intranet/overlay network.
    2. It makes this docker container an overlay network with a gateway for the local docker network and a gateway for the VPN network, assigning IPs to the local docker network
    3. And sets the Docker network reservation for its 192.160.100.10 IP to be the VPN container on the 192.168.100.0/24 network, equal to the VPN’s gateway on this subnet

    Take a look at the Docker Networking Tutorials for both the Commandline Create:
    https://docs.docker.com/engine/reference/commandline/network_create/
    And joining a docker swarm with an Overlay docker network:
    https://docs.docker.com/network/network-tutorial-overlay/

    Also, I didn’t move driver: overlay out above the ipam block. These VML versions can be a bit confusing, see here: What is the purpose of the "ipam" key in a Docker Compose config?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search