Catalogue
Nginx - Block Direct IP Access & Configure LB Health Checks

Nginx - Block Direct IP Access & Configure LB Health Checks

🌐 日本語で読む

Here is a summary of how I commonly configure Nginx configuration files to route requests based on the request origin.

1
LB → Nginx → Rails

Nginx Configuration

  • conf.d/default.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# cannot allow ip direct
server {
listen 80;
server_name _;
return 444;
}

# healthcheck from LB
server {
listen 80 default_server;
listen [::]:80 default_server;
root /work/app/public;

location = /healthcheck.html {
access_log off;
proxy_pass https://puma;
}
}

server {
listen 80;
server_name example.com;
...

Blocking Direct IP Access

By setting server_name _, we target direct IP access.

1
2
3
4
5
server {
listen 80;
server_name _;
return 444;
}

Health Checks from the LB

By setting the target of the LB’s health checks as default_sever, the health checks reference this server directive.

1
2
3
4
5
6
7
8
9
10
server {
listen 80 default_server;
listen [::]:80 default_server;
root /work/app/public;

location = /healthcheck.html {
access_log off;
proxy_pass https://puma;
}
}

In the config file above, the AWS ALB health check path is set to /healthcheck.html, and its target is the Rails puma server.

On the Rails side, you can either point it to the ok_computer gem as shown below, or return your own custom response.

1
get 'healthcheck.html', to: 'ok_computer/ok_computer#index'

Specifying a Domain

This server directive is referenced when accessed via example.com.

1
2
3
4
server {
listen 80;
server_name example.com;
...

A Bad Example of Specifying a Domain

Previously, I handled direct IP access and health checks by specifying the configuration as follows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 80;
server_name example.com;

if ($host != "example.com") {
return 444;
}

location = /healthcheck.html {
access_log off;
proxy_pass https://puma;
}
...
}

Of course, this works too. However, the readability is somewhat poor.

When supporting multiple domains with direct IP access disabled, this if statement keeps getting longer and longer.

For that reason, I found that splitting things into small server {} blocks according to the intended target leads to higher readability and better maintainability in actual operation.

That’s all.
I hope this is helpful.

Nginx - Block Direct IP Access & Configure LB Health Checks

https://kenzo0107.github.io/en/2019/04/24/nginx-ip-lb/

Author

Kenzo Tanaka

Posted on

2019-04-24

Licensed under