NGINX設定ファイル
NGINXをリバースプロキシまたはウェブサーバとして使用するための設定ティップス。サーバセキュリティ、ロードバランサーとしての機能も併せ持つため、サーバ導入時には欠かせないオープンソースのサーバアプリです。
NGINXをリバースプロキシまたはウェブサーバとして使用するための設定ティップス。サーバセキュリティ、ロードバランサーとしての機能も併せ持つため、サーバ導入時には欠かせないオープンソースのサーバアプリです。
以下の例では、ロケーションで指定したディレクトリ内で、URIで表示された文字列を、まず初めにファイルとして検索、そのファイルが存在しない場合にはフォルダとして検索します。結果が一致した時点でその内容を返し、共に一致しなければ404を返します。
location / {
try_files $uri $uri/ $uri.html =404;
}
ファイル、フォルダ名共にURIと一致しない場合、以下のようにプロキシーサーバに飛ばすことも出来ます。
location / {
try_files $uri $uri/ @backend;
}
location @backend {
proxy_pass http://backend.example.com;
}
Regular Expression正規表現参考
NGINX uses Perl Compatible Regular Expressions (PCRE).
Location blocks generally take the following form:
location optional_modifier location_match {
. . .
}
The location_match
in the above defines what Nginx should check the request URI against. The existence or nonexistence of the modifier in the above example affects the way that the Nginx attempts to match the location block. The modifiers below will cause the associated location block to be interpreted as follows:
=
: If an equal sign is used, this block will be considered a match if the request URI exactly matches the location given.~
: If a tilde modifier is present, this location will be interpreted as a case-sensitive regular expression match.~*
: If a tilde and asterisk modifier is used, the location block will be interpreted as a case-insensitive regular expression match.^~
: If a carat and tilde modifier is present, and if this block is selected as the best non-regular expression match, regular expression matching will not take place.http://nginx.org/en/docs/http/ngx_http_core_module.html#alias
rootディレクティブ
location /static/ {
root /var/www/app/;
autoindex off;
}
rootで指定したディレクトリにlocationのディレクトリが追加されます。
/var/www/app/static
aliasディレクティブ
location /static/ {
alias /var/www/app/static/;
autoindex off;
}
locationのディレクトリがaliasのディレクトリを表します。
/var/www/app/static
/etc/nginx/fastcgi_params
ファイル内で以下設定項目を確認すること。特にphpスクリプトを実行する上で、以下の設定がポイントとなります。(404が返ってきた場合はここを見直します)
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param HTTPS $https;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
fastcgi_paramの設定については以下も参考にして下さい。
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
or
fastcgi_param SCRIPT_FILENAME $request_filename;
You get the request /info/
and have the following configuration:
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/www/scripts/php$fastcgi_script_name;
SCRIPT_FILENAME
would equal /home/www/scripts/php/info/index.php
, but using $request_filename
it would just be /home/www/scripts/php/info/
.
The configuration of fastcgi_split_path_info
is important as well. See here for further help: Module ngx_http_fastcgi_module
ヘッダー読み取りエラー
デフォルトでNginxはアンダースコア"_"を含むヘッダーは読み込まない。
Nginxの設定ファイルに “underscores_in_headers on;” を追加。
underscores_in_headers
https://nginx.org/en/docs/http/ngx_http_core_module.html#underscores_in_headers
Ex)
https://gist.github.com/zeroed/8554827
upstream foo_app {
server 127.0.0.1:3000;
}
server {
listen 80;
# listen [::]:80 default_server ipv6only=on;
root /home/user/foo/foo_web/public;
server_name foo.it www.foo.it;
underscores_in_headers on;
client_max_body_size 4g;
location ~ ^/(assets)/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_connect_timeout 300;
proxy_read_timeout 300;
proxy_pass_request_headers on;
proxy_pass http://foo_app;
}
}
NginxにおけるApacheのgetallheaders()代替案
https://www.php.net/manual/en/function.getallheaders.php#84262
<?php
if (!function_exists('getallheaders'))
{
function getallheaders()
{
$headers = [];
foreach ($_SERVER as $name => $value)
{
if (substr($name, 0, 5) == 'HTTP_')
{
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
}
}
return $headers;
}
}
?>
https://www.cyberciti.biz/faq/linux-unix-bsd-nginx-413-request-entity-too-large/
/etc/nginx/conf.d/dfault.conf内のlocationブロックで以下指定
client_max_body_size 20M;
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
root /var/www/html;
index index.php index.js index.html index.htm index.nginx-debian.html;
server_name domain.com www.domain.com;
ssl_certificate /ssl/domain.com.chained.crt;
ssl_certificate_key /ssl/domain.com.key;
location / {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location /wordpress {
proxy_pass http://localhost:8090;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
https://nginx.org/en/docs/http/ngx_http_map_module.html
例1) mapモジュールによるリダイレクト
map により /old.html を /index.html に対応させ、それが真(1)の時にリダイレクト
. . .
# Default server configuration
#
# Old website redirect map
#
map $uri $new_uri {
/old.html /index.html;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
# Old website redirect
if ($new_uri) {
rewrite ^ $new_uri permanent;
}
. . .
例2) mapによる国別のサイトへのアクセス制限
以下の設定ファイルを作成し、国データを指定。
/etc/nginx/conf.d/geoip.conf
https://nginx.org/en/docs/http/ngx_http_geoip_module.html
. . .
# GeoIP database path
#
geoip_country /usr/share/GeoIP/GeoIP.dat;
制限する国コードを指定(AFとAL)
. . .
# Default server configuration
#
# Allowed countries
#
map $geoip_country_code $allowed_country {
default no;
AF yes;
AL yes;
}
# Old website redirect map
#
map $uri $new_uri {
/old.html /index.html;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
# Disallow access based on GeoIP
if ($allowed_country = no) {
return 444;
}
# Old website redirect
if ($new_uri) {
rewrite ^ $new_uri permanent;
}
. . .
サーバディレクトリ毎に設定を細かく指定する Location(Nginxコアモジュール) についてのメモ。
Nginxコアモジュール
https://nginx.org/en/docs/http/ngx_http_core_module.html
Location
https://nginx.org/en/docs/http/ngx_http_core_module.html#location
Syntax: location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
Default: —
Context: server, location
= 一致した場合
~ 大文字・小文字を区別(正規表現)
~* 大文字・小文字を区別しない(正規表現)
^~ 一致したら正規表現(~,~*)の条件を適用しない
@name 他の設定からのリダイレクト先を名前により指定する場合に使用
ディレクトリが / の場合、configuration Aを適用
location = / {
[ configuration A ]
}
ディレクトリが / を含む場合、configuration Bを適用
location / {
[ configuration B ]
}
ディレクトリが /documents/ を含む場合、configuration Cを適用
location /documents/ {
[ configuration C ]
}
ディレクトリが /images/ を含む場合、configuration Dを適用
location ^~ /images/ {
[ configuration D ]
}
ファイル名に gif.jpg,jpeg の拡張子を含む場合、configuration Eを適用
location ~* \.(gif|jpg|jpeg)$ {
[ configuration E ]
}
# --------------------------------------------------------------------------------------------------------------------------------------------
# Search-Order Modifier Description Match-Type Stops-search-on-match
# --------------------------------------------------------------------------------------------------------------------------------------------
# 1st = The URI must match the specified pattern exactly Simple-string Yes
# 2nd ^~ The URI must begin with the specified pattern Simple-string Yes
# 3rd (None) The URI must begin with the specified pattern Simple-string No
# 4th ~ The URI must be a case-sensitive match to the specified Rx Perl-Compatible-Rx Yes (first match)
# 4th ~* The URI must be a case-insensitive match to the specified Rx Perl-Compatible-Rx Yes (first match)
# N/A @ Defines a named location block. Simple-string Yes
# --------------------------------------------------------------------------------------------------------------------------------------------
phpmyadminなどサブディレクトリを指定したページアクセスにファイルの絶対パス ( ex) /var/www/html)
が追加されてしまうエラーについて。
https://serverfault.com/questions/417357/nginx-appends-the-path-given-in-the-uri
location
ディレクティブの内部で location
ディレクティブを指定した場合、その両方に root
または alias
を指定すること。
root
の場合
location /phpmyadmin {
root /usr/share/;
try_files $uri $uri/ /index.php;
location ~ ^/phpmyadmin(.+\.php)$ {
root /usr/share/;
fastcgi_pass 127.0.0.1:9000;
include fastcgi.conf;
fastcgi_intercept_errors on;
}
}
alias
の場合
location /pma {
alias /usr/share/phpmyadmin/;
try_files $uri $uri/ /index.php;
location ~ ^/pma(.+\.php)$ {
alias /usr/share/phpmyadmin$1;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME /usr/share/phpmyadmin$1;
include fastcgi_params;
fastcgi_intercept_errors on;
}
}
https://nginx.org/en/docs/http/ngx_http_core_module.html#variables
location / {
try_files $uri /index.php$is_args$args;
}
$args
arguments in the request line
$is_args
“?
” if a request line has arguments, or an empty string otherwise
https://nginx.org/en/docs/http/ngx_http_core_module.html#try_files
https://nginx.org/en/docs/http/ngx_http_proxy_module.html
キャッシュ設定ファイル例(リバースプロキシ)
http {
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=STATIC:10m
inactive=24h max_size=1g;
server {
location / {
proxy_pass http://1.2.3.4;
proxy_set_header Host $host;
proxy_buffering on;
proxy_cache STATIC;
proxy_cache_valid 200 1d;
proxy_cache_use_stale error timeout invalid_header updating
http_500 http_502 http_503 http_504;
}
}
}
以下 Nginx
の -V
コマンドオプションでキャッシュディレクトリなどのコンパイル時の条件が確認できます。# nginx -V
DockerコンテナのNginx(Alpine)
# nginx -V
nginx version: nginx/1.19.6
built by gcc 9.3.0 (Alpine 9.3.0)
built with OpenSSL 1.1.1g 21 Apr 2020 (running with OpenSSL 1.1.1i 8 Dec 2020)
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --with-perl_modules_path=/usr/lib/perl5/vendor_perl --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-Os -fomit-frame-pointer' --with-ld-opt=-Wl,--as-needed
proxy_cache_path
alpineベースのnginxコンテナでは、Nginxのドキュメントの中で例示されている /data/nginx/cache
ディレクトリが存在しないため、 /var/cache/nginx
を指定します。
以下 http, server, location
何れかのセクションにブロックするIPを指定
http{
...
deny 45.43.23.21;
...
}
server{
...
deny 45.43.23.21;
...
}
location / {
deny 45.43.23.21;
}
または /etc/nginx/conf.d/blacklist_ips.conf
を作成してブロックするIPを指定
( /etc/nginx/conf.d/*.conf
は /etc/nginx/nginx.conf
によりデフォルトで読み込まれるよう設定されています)
以下 amazonaws
を悪用したサイトからのアクセス禁止した例
deny 34.208.0.0/12;
deny 35.160.0.0/13;
deny 54.184.0.0/13;
deny 54.200.0.0/15;
allow all;
iptables
でも特定IPからのアクセスはブロックできます。
AWSの仮想サーバインスタンスに付与されるIP ( ec2-xx-xxx-xxx-xxx.us-west-2.compute.amazonaws.com
etc…) からアクセス拒否する場合、AWSから提供されているIPアドレス範囲一覧から(排除する)IP範囲を特定します。
AWS提供IP範囲
IPリスト
https://ip-ranges.amazonaws.com/ip-ranges.json
JSONフォーマットによるデータで情報量が多いため、以下のアプリでフィルタリングして必要な情報を抜き出します。
jq
https://stedolan.github.io/jq/
各OSに対応しています。
Ubuntuでのインストール
$ sudo apt-get install jq
AWSのサービスとリージョンを指定したIP範囲の抽出
ダウンロードしたデータ ip-ranges.json
から AWSのEC2でリージョンが us-west-2
のIPアドレス一覧を抽出します。
$ jq -r '.prefixes[] | select(.region=="us-west-2") | select(.service=="EC2") | .ip_prefix' < ip-ranges.json
142.4.160.56/29
15.220.252.0/22
54.148.0.0/15
99.77.130.0/24
99.150.56.0/21
15.193.7.0/24
18.236.0.0/15
161.188.148.0/23
54.200.0.0/15
64.252.72.0/24
3.4.3.0/24
52.94.249.64/28
161.188.156.0/23
15.181.253.0/24
70.224.192.0/18
54.245.0.0/16
99.77.152.0/24
35.160.0.0/13
54.68.0.0/14
54.212.0.0/15
142.4.160.64/29
52.95.230.0/24
99.77.253.0/24
3.4.6.0/24
35.80.0.0/12
52.12.0.0/15
52.75.0.0/16
54.218.0.0/16
3.5.76.0/22
15.181.0.0/20
54.244.0.0/16
44.224.0.0/11
64.252.73.0/24
52.95.255.112/28
100.20.0.0/14
15.220.0.0/20
15.220.16.0/20
161.188.134.0/23
54.214.0.0/16
34.208.0.0/12
35.71.64.0/22
52.36.0.0/14
15.220.226.0/24
54.202.0.0/15
15.181.128.0/20
15.181.245.0/24
52.95.247.0/24
50.112.0.0/16
15.181.64.0/20
142.4.160.16/29
52.94.116.0/22
15.181.248.0/24
15.253.0.0/16
15.181.252.0/24
52.46.180.0/22
15.181.16.0/20
162.222.148.0/22
52.24.0.0/14
64.252.65.0/24
18.246.0.0/16
3.5.80.0/21
161.188.138.0/23
52.88.0.0/15
142.4.160.104/29
161.188.152.0/23
15.177.80.0/24
15.254.0.0/16
52.40.0.0/14
64.252.70.0/24
52.32.0.0/14
54.184.0.0/13
142.4.160.96/29
15.181.251.0/24
142.4.160.32/29
161.188.160.0/23
64.252.71.0/24
35.155.0.0/16
52.10.0.0/15
3.4.4.0/24
15.181.116.0/22
15.220.224.0/23
15.181.250.0/24
52.94.248.96/28
99.77.186.0/24
上記IP範囲を参考にブロックするIP範囲を nginx
の設定ファイルに書き込みます。
コマンドラインによるIP計算機
$ ipcalc 34.208.0.0/12
Address: 34.208.0.0 00100010.1101 0000.00000000.00000000
Netmask: 255.240.0.0 = 12 11111111.1111 0000.00000000.00000000
Wildcard: 0.15.255.255 00000000.0000 1111.11111111.11111111
=>
Network: 34.208.0.0/12 00100010.1101 0000.00000000.00000000
HostMin: 34.208.0.1 00100010.1101 0000.00000000.00000001
HostMax: 34.223.255.254 00100010.1101 1111.11111111.11111110
Broadcast: 34.223.255.255 00100010.1101 1111.11111111.11111111
Hosts/Net: 1048574 Class A
$ sipcalc 34.208.0.0/12
-[ipv4 : 34.208.0.0/12] - 0
[CIDR]
Host address - 34.208.0.0
Host address (decimal) - 584056832
Host address (hex) - 22D00000
Network address - 34.208.0.0
Network mask - 255.240.0.0
Network mask (bits) - 12
Network mask (hex) - FFF00000
Broadcast address - 34.223.255.255
Cisco wildcard - 0.15.255.255
Addresses in network - 1048576
Network range - 34.208.0.0 - 34.223.255.255
Usable range - 34.208.0.1 - 34.223.255.254
-
$ subnetcalc 34.208.0.0/12
Address = 34.208.0.0
00100010 . 11010000 . 00000000 . 00000000
Network = 34.208.0.0 / 12
Netmask = 255.240.0.0
Broadcast = 34.223.255.255
Wildcard Mask = 0.15.255.255
Hosts Bits = 20
Max. Hosts = 1048574 (2^20 - 2)
Host Range = { 34.208.0.1 - 34.223.255.254 }
Properties =
- 34.208.0.0 is a NETWORK address
- Class A
GeoIP Country = United States (US)
DNS Hostname = ec2-34-208-0-0.us-west-2.compute.amazonaws.com
以下のコマンドでビルド時の条件を確認し --with-http_gzip_static_module
があればgzipモジュールはインストールされています。
# nginx -V
nginx version: nginx/1.21.6
built by gcc 10.3.1 20211027 (Alpine 10.3.1_git20211027)
built with OpenSSL 1.1.1l 24 Aug 2021
TLS SNI support enabled
configure arguments: ..................... --with-http_gzip_static_module ....................
....................
gzipを有効にし、必要な条件を追加します。
/etc/nginx/nginx.conf
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types
application/atom+xml
application/geo+json
application/javascript
application/x-javascript
application/json
application/ld+json
application/manifest+json
application/rdf+xml
application/rss+xml
application/xhtml+xml
application/xml
font/eot
font/otf
font/ttf
image/svg+xml
text/css
text/javascript
text/plain
text/xml;
ドメイン名でのみでアクセス許可した外部 Nginx
サーバ(バックエンド)へのプロキシ(フロントエンド)設定。
簡単に言うとフロントエンドで受けたドメイン名をバックエンドへ引継ぐための設定です。
リバースプロキシ側(フロントエンド)で、下記 proxy_set_header
で指定したヘッダー情報を外部サーバ(バックエンド)へ受け渡します。
Note) ホスト名を明示 proxy_set_header Host test.example.com;
しないとプロキシパスのアドレス(とポート)が受け渡されてしまいます。
/etc/nginx/conf.d/default.conf
server {
server_name test.example.com;
location / {
proxy_pass http://12.34.56.78:8888;
proxy_set_header Host test.example.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
.....
フロントエンドで受けたクライアントIPを外部サーバ(バックエンド)で引継ぐ場合は、下記バックエンドの Nginx
の設定でフロントエンドサーバのIPアドレス(グローバルIP)を明示して下さい。
設定する上で、以下のモジュールが必要です。$ nginx -V
コマンドでコンパイル条件を確認して下さい。
https://nginx.org/en/docs/http/ngx_http_realip_module.html
/etc/nginx/nginx.conf
http {
....
set_real_ip_from xx.xx.xx.xx; ← フロントエンドのIPアドレスを入力
real_ip_header X-Forwarded-For;
real_ip_recursive on;
.....
}