Nginx: How to allow only localhost (or specific IPs) to POST to controller endpoints?

Greetings,

I have a couple of login controllers that receive only POST requests on urls, for example:

https://app.mysite.com/ex/users/login

My current Nginx configuration for app.mysite.com is set up like this:

upstream app {
  server 127.0.0.1:4000 max_fails=5 fail_timeout=60s;
}
server {
  server_name app.mysite.com;

  listen [::]:443 ssl; # managed by Certbot
  listen 443 ssl; # managed by Certbot

  location / {
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Cluster-Client-Ip $remote_addr;

    # The Important Websocket Bits!
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    proxy_pass http://app;
  }
}

My router.ex is set up like the following:

scope "/ex", ExchatWeb do
    pipe_through :api

    post "/users/login", UserController, :login
    post "/users/anon-login", UserController, :anon_login
  end

Basically, I would only like the local host 127.0.0.1 (or specified IP addresses) to be able to post to those endpoints in the router. How can I set this up in Nginx?

I’ve tried adding the following to the Nginx server blocks (and other variations + before/after root location block, etc), but it’s not working. The Nginx server location configs are always a bit tricky for me, I’m sure there is a simple solution.

location = /ex/user/login { #attempt to restrict endpoint to localhost only
    allow 127.0.0.1;
    deny all;
}

and:

location ^~ /ex/user/ { # attempt to restrict entire /ex/user endpoint folder to localhost only
    allow 127.0.0.1;
    deny all;
}

Thanks

1 Like

Getting back to developing again, still would like help on this.

When I use:

location = /ex/user/login { #attempt to restrict endpoint to localhost only
    allow 127.0.0.1;
    deny all;
}

This blocks access through the browser (as intended). But when I use cURL in my PHP script, it won’t pass the arguments through to Phoenix:

  $data = array("user" => array("id" =>1));
  $postdata = json_encode($data);
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL,"https://app.mysite.com/ex/users/login");
  curl_setopt($ch, CURLOPT_POST, 1);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
  $server_output = curl_exec($ch);
  curl_close($ch);

It seems that Nginx is not truly allowing the localhost 127.0.0.1 to pass this cURL request to Phoenix, and I’m not sure why. Note: PHP and Phoenix are both running on the same machine.