Restrict access to nginx server location to a specific Docker container with "allow" directive

Viewed 7422

Edit: Tarun's answer does exactly what I asked for. Eugen's answer is also a very good solution. I ended up accepting Tarun's answer as correct, but using Eugen's. If you have a similar issue and are worried about other containers accessing the nginx status server, use Tarun's answer. If you'd rather stick to Docker's normal hostname scheme, use Eugen's.

+++ Original Question +++

I have an application that I build with docker-compose. I am trying to integrate monitoring through DataDog. I'm using DataDog's Agent container, and so far everything is working. I am trying to get nginx monitoring up and running by adapting this tutorial.

My application is defined in a docker-compose file like this:

version: '2'
services:
  flask:
    restart: always
    image: me/flask-app
    command: /home/app/flask/start_app.sh
    expose:
      - "8080"

  nginx:
    restart: always
    build: ./nginx
    command: /runtime/start_nginx.sh
    ports:
      - "80:80"
      - "443:443"
    expose:
      - "81"
    volumes:
      - app-static:/app-static:ro
    links:
      - flask:flask

  datadog-agent:
    image: me/datadog-agent
    env_file: ./datadog-agent/dev.env
    links:
        - flask
        - nginx
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /proc/mounts:/host/proc/mounts:ro
      - /sys/fs/cgroup:/host/sys/fs/cgroup:ro

Per the tutorial, I've added a server block to nginx that looks like this:

server {
  listen 81;

  location /nginx_status {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    deny all;
  }
}

With this configuration, I can check the nginx status from within the nginx container. So far, so good. Now I would like to change the "allow" directive in the location block to allow access to the datadog-agent service only. However, I don't know the IP of the datadog-agent. When configuring access to the Flask uwsgi server, I was able to use directives like this:

location / {
    uwsgi_pass: flask:8080;
}

But this doesn't seem to work for allow directives; if I try:

location /nginx_status {
    ...
    allow datadog-agent;
    ...
}

I get the following error:

nginx: [emerg] invalid parameter "datadog-agent" in /etc/nginx/sites-enabled/nginx-status:8

How can I safely expose the nginx status to my monitoring container?

3 Answers

There are two (easier) ways to go about it.

First one is docker-compose but since I already have a setup running since 2 years which doesn't use docker-compose, I went for the 2nd way.

Second way is Allow Directive with a range of IPs.

Eg:

    location /stub_status {
        stub_status;

        allow 172.18.0.0/16;   # This is my local docker IP range
        allow 192.168.0.0/16;  $ This is my production server IP range
        deny all;              # deny all other hosts   
 }

I am not security expert, but mostly 192.168.* IP range is for local networks, not sure about 172.18.* range though.

To get more idea about this IP range thing and CIDR stuff, refer below links http://nginx.org/en/docs/http/ngx_http_access_module.html

https://www.ripe.net/about-us/press-centre/understanding-ip-addressing

Related