Nginx को समझना शुरू करना
नमस्ते, शीर्षक उस चीज़ का एक पैरोडी है। यह बस एक गाना है जो मुझे अचानक याद आ गया।
हाल ही में लेखों के अपडेट असामान्य रूप से अधिक होने का कारण यह है कि एक बार जब मैं किसी चीज़ के बारे में उत्सुक हो जाता हूँ, तो मैं रुक नहीं पाता, और यह बस वही समय है।
Nginx
अब तक, मैंने इसे अस्थायी रूप से रिवर्स प्रॉक्सी और कैश सर्वर के रूप में बनाया था, लेकिन IPv6 सपोर्ट के साथ-साथ मुझे इसकी चिंता होने लगी, इसलिए मैंने रिफैक्टरिंग सहित सेटिंग्स की समीक्षा की।
फ़ाइल संरचना
कुछ हिस्से छिपे हुए हैं, लेकिन यह कुछ इस तरह दिखता है
├── http.d
│ ├── bot_rate_limit.conf
│ ├── gzip.conf
│ ├── proxy_cache_zones.conf
│ └── proxy_common.conf
├── mime.types
├── mime.types-dist
├── nginx.conf
├── scgi_params
├── selfsigned.crt
├── selfsigned.key
├── sites-enabled
│ ├── 1btc.love.conf
│ ├── btclol.xyz.conf
│ ├── damepo.jp.conf
│ ├── git.soulminingrig.com.conf
│ ├── soulminingrig.com.conf
│ ├── starlink.soulminingrig.com.conf
│ ├── stg.api.1btc.love.conf
├── snippets
│ ├── common_error_pages.conf
│ ├── proxy_headers.conf
│ └── ssl_common.conf
├── uwsgi_params
└── win-utf
मैं थोड़ा उलझन में था कि location डायरेक्टिव के आधार पर लोड की गई conf फ़ाइलों को किस नाम के फ़ोल्डर में प्रबंधित किया जाए, लेकिन ChatGPT से परामर्श करने के बाद, यह इस तरह बन गया। http.d वे फ़ाइलें हैं जिन्हें nginx.conf के http डायरेक्टिव से include किया गया है, इसलिए यह काफी तर्कसंगत लगा।
हालाँकि, snippets का उपयोग करना थोड़ा अजीब लगा, लेकिन ठीक है।
आइए प्रत्येक सेटिंग आइटम को देखें।
http.d/bot_rate_limit.conf
मेटा के क्रॉलर बहुत अधिक थे, इसलिए मैंने न केवल fail2ban बल्कि UA के आधार पर भी सीमाएं लगाने का फैसला किया।
इसके अलावा, feed/RSS के संबंध में, मुझे विनम्रतापूर्वक सूचित किया गया था, लेकिन इसे लागू करने का कोई मतलब नहीं है क्योंकि यह ज्यादातर कैश से उत्तर देता है और ओरिजिन (Origin) पर लोड नहीं डालता है, इसलिए मैंने इसके लिए अपवाद (hole) बनाया है।
# केवल बॉट और लिंक विस्तार क्रॉलर के लिए दर सीमा (rate limit) लागू करें
map $http_user_agent $is_bot {
default 0;
~*bot 1;
~*crawler 1;
~*spider 1;
~*facebookexternalhit 1;
~*slackbot 1;
~*discordbot 1;
~*twitterbot 1;
~*linkedinbot 1;
~*embedly 1;
~*quora 1;
~*skypeuripreview 1;
~*whatsapp 1;
~*telegrambot 1;
~*applebot 1;
~*pingdom 1;
~*uptimerobot 1;
}
# stg.api.1btc.love सत्यापन उद्देश्यों के लिए है, इसलिए बॉट होने पर भी इसे दर सीमा से बाहर रखा गया है
# यदि key एक खाली स्ट्रिंग है, तो इसे limit_req_zone में नहीं गिना जाएगा
map $server_name $bot_limit_host_key {
stg.api.1btc.love "";
default $binary_remote_addr;
}
# feed.xml / feed.json को बॉट होने पर भी दर सीमा से बाहर रखा गया है
map $uri $is_feed_path {
default 0;
~*feed\.(xml|json)$ 1;
}
# केवल तभी IP-आधारित key का उपयोग करें जब वह बॉट हो और feed.xml / feed.json न हो
map "$is_bot:$is_feed_path" $bot_limit_key {
default "";
"1:0" $bot_limit_host_key;
}
limit_req_zone $bot_limit_key zone=bot:10m rate=1r/s;
limit_req_status 429;
limit_req zone=bot burst=5 nodelay;
बेशक, चूंकि यह http डायरेक्टिव पर लागू होता है, यह मूल रूप से सभी पर लागू होता है, लेकिन मैंने इसे इस तरह बनाया है कि कम से कम अपवाद बनाए जा सकें। मैंने निर्णय लिया है कि इसे डिफ़ॉल्ट रूप से सक्षम होना चाहिए।
यदि कोई UA को गलत बताकर या ब्राउज़र का भेष बदलकर स्पष्ट रूप से DoS हमला करता है, तो उसे fail2ban द्वारा ब्लॉक कर दिया जाएगा और drop के रूप में माना जाएगा, जिससे वे कुछ समय के लिए अनुरोध नहीं भेज पाएंगे, इसलिए यह एक दो-स्तरीय सुरक्षा है।
http.d/gzip.conf
पहले मैं brotli सपोर्ट का उपयोग करता था, लेकिन इसे अलग से बिल्ड करना वर्ज़न अपडेट करते समय परेशानी भरा होता है, इसलिए मैंने इसे बंद कर दिया। pkg/apt के माध्यम से अपडेट करने में सक्षम होने का लाभ बहुत बड़ा है।
gzip on;
gzip_vary off;
gzip_proxied any;
gzip_min_length 1024;
gzip_comp_level 7;
gzip_http_version 1.1;
gzip_types text/plain
text/xml
text/css
text/javascript
image/gif
image/png
image/svg+xml
application/javascript
application/json
application/xml
application/x-javascript
application/font-woff
application/font-woff2
application/font-ttf
application/octet-stream;
कहने के लिए बहुत कुछ नहीं है, मैंने इसे पहले शामिल नहीं किया था, लेकिन कुछ साल पहले मैंने gzip_min_length को शामिल करना शुरू किया। यह तब था जब मैंने सोचा कि अक्षम संपीड़न करना बेकार है और इसे ठीक से शामिल करने का प्रयास किया।
http.d/proxy_cache_zones.conf
ऐसा लग सकता है कि इंडेंटेशन थोड़ा खराब है, लेकिन यह फॉर्मेटर की सीमा है।
अनावश्यक चीजों को हटाने के बाद, zone 4 से शुरू हो रहे हैं या बिखरे हुए हैं, लेकिन ठीक है...
inactive के संबंध में, यदि 7 दिनों तक कोई हिट नहीं होती है, तो यह हटा दिया जाता है, और use_temp_path के संबंध में, यह सीधे कैश पथ पर कैश करने के लिए सेट है। proxy_temp_path /tmp/nginx; जैसी सेटिंग होने पर भी, यह उसके माध्यम से जाए बिना कैश करता है, जिससे यह तेज़ हो जाता है।
proxy_cache_path /tmp/nginx/zone4 levels=1:2 keys_zone=zone4:10m
inactive=7d
max_size=3g
use_temp_path=off;proxy_cache_path /tmp/nginx/posts levels=1:2 keys_zone=posts:10m
inactive=7d
max_size=2g
use_temp_path=off;
proxy_cache_path /tmp/nginx/git levels=1:2 keys_zone=git:10m
inactive=7d
max_size=2g
use_temp_path=off;
proxy_cache_path /tmp/nginx/static levels=1:2 keys_zone=static_cache:10m
inactive=7d
max_size=1g
use_temp_path=off;
proxy_cache_path /tmp/nginx/1btc_cache levels=1:2 keys_zone=1btc_cache:10m
inactive=7d
max_size=512m
use_temp_path=off;
http.d/proxy_common.conf
मैंने proxy_cache_valid को एक सामान्य नियम के रूप में सेट किया है, और बाकी को location डायरेक्टिव की तरफ से ओवरराइट करने के लिए संचालित किया जाता है।
इस तरह, आप कैश सेटिंग्स के बिना भी कैश संचालन कर सकते हैं।
proxy_cache_bypass $http_cookie सेट करने से, यह कुकीज़ वाले अनुरोधों को रोकता है, जैसे कि लॉगिन करने के बाद भी लॉगिन से पहले वाली स्क्रीन दिखने की संभावना को।
इसके अलावा, रीडायरेक्ट, एरर और any के लिए कैश रिस्पॉन्स देना हमलों के खिलाफ एक सुरक्षा उपाय है। ऐसा करने से, कम से कम एक कैश रिस्पॉन्स दिया जाता है, जिससे ओरिजिन (Origin) तक असामान्य पहुँच को रोका जा सकता है।
proxy_temp_path के लिए आदर्श रूप से एक ऐसा पाथ होना चाहिए जिसे स्थायी बनाया जा सके, लेकिन मूल रूप से मेरे उपयोग के मामले में ऐसी कोई स्थिति नहीं है, इसलिए मैंने इसे /tmp पर सेट किया है। यदि आप इसे पर्याप्त ट्रैफ़िक वाली साइट पर करते हैं, तो सर्वर रीस्टार्ट होने पर सारा कैश गायब हो सकता है और ओरिजिन पर लोड बढ़ सकता है, जिससे विफलता का जोखिम हो सकता है।
proxy_buffering on;
proxy_cache_bypass $http_cookie;
proxy_cache_background_update on;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_revalidate on;
proxy_cache_use_stale updating;
proxy_connect_timeout 60;
proxy_no_cache $http_cookie;
proxy_read_timeout 90;
proxy_send_timeout 60;
proxy_temp_path /tmp/nginx;
proxy_cache_valid 200 201 60s;
proxy_cache_valid 301 1d;
proxy_cache_valid 302 3h;
proxy_cache_valid 304 1d;
proxy_cache_valid 404 1m;
proxy_cache_valid any 5s;
proxy_cache_lock on;
nginx.conf
मैंने बस इसे इस तरह सेट किया है कि यदि A रिकॉर्ड के IP को सीधे एक्सेस किया जाता है, तो यह एक विशिष्ट एरर लौटाता है, इसलिए कहने के लिए बहुत कुछ नहीं है।
मैंने multi_accept को ऑन रखा है क्योंकि मेरा रिवर्स प्रॉक्सी और कैश सर्वर एक कम स्पेसिफिकेशन वाला छोटा इंस्टेंस है।
जो सेटिंग्स मूल रूप से सीधे http डायरेक्टिव में लिखी गई थीं, उन्हें अब उद्देश्य के अनुसार include किया गया है, जिससे स्पष्टता काफी बढ़ गई है।
worker_processes auto;
worker_cpu_affinity auto;
worker_rlimit_nofile 65535;
events {
multi_accept on;
worker_connections 65535;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
types_hash_max_size 4096;
client_max_body_size 16M;
# MINE
include mime.types;
default_type application/octet-stream;
include ./http.d/bot_rate_limit.conf;
include ./http.d/proxy_common.conf;
include ./http.d/proxy_cache_zones.conf;
include ./http.d/gzip.conf;
server {
listen 80;
listen [::]:80;
server_name 163.44.113.145 91.98.169.80 2400:8500:2002:3317:163:44:113:145;
include snippets/common_error_pages.conf;
return 444;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name 163.44.113.145 91.98.169.80 2400:8500:2002:3317:163:44:113:145;
ssl_certificate ./selfsigned.crt;
ssl_certificate_key ./selfsigned.key;
include snippets/common_error_pages.conf;
# IPアドレスへのアクセスを拒否
return 444;
}
### Damepo.jp
include ./sites-enabled/damepo.jp.conf;
### Soulminingrig My Blog
include ./sites-enabled/soulminingrig.com.conf;
# ~~~略~~~~
}
sites-enabled/soulminingrig.com.conf
मैं site-enabled के तहत उदाहरण के तौर पर केवल एक ही दिखाऊंगा। यह इस साइट की सेटिंग है।
साथ ही, मैंने सिम्बोलिक लिंक का उपयोग नहीं किया है क्योंकि मैं बस अनावश्यक चीजों को जल्दी से हटाने में सक्षम होना चाहता हूँ।
वास्तव में, कुछ हिस्से अभी भी हार्ड-कोडेड हैं, लेकिन कृपया ध्यान दें कि मैं अभी भी उनमें सुधार कर रहा हूँ।
वैसे, मैंने हाल ही में इसे www.soulminingrig.com में बदल दिया है, लेकिन इससे पहले मैं इसे बिना www वाले रूट डोमेन पर डिलीवर कर रहा था, इसलिए वर्तमान में मैं अभी भी रूट डोमेन को बिना रीडायरेक्ट किए स्वीकार कर रहा हूँ।
सत्यापन अवधि के रूप में, मैंने हेडर रिस्पॉन्स को इस तरह सेट किया है कि यह पहचानना आसान हो जाए कि सर्वर कैश ने रिस्पॉन्स दिया है या क्लाइंट कैश ने।
और, मैं सोच रहा हूँ कि क्या इमेज, फॉन्ट, CSS आदि के लिए कैश नियमों के बारे में कुछ और किया जा सकता है... क्या इसके बारे में कुछ नहीं किया जा सकता...? यह...।
मैंने upstream को इसलिए सेट किया है ताकि बैकएंड की संख्या बढ़ने पर मैं तुरंत प्रतिक्रिया दे सकूँ। खैर, वर्तमान में केवल एक ही है, लेकिन इसे सबसे ऊपर रखने से यह समझना आसान हो जाता है कि सेटिंग किस बैकएंड की ओर इशारा कर रही है।
upstream backend_sm {
server 10.1.0.228:8888 max_fails=3 fail_timeout=3s;
keepalive 16;
keepalive_timeout 30s;
}
map $uri $static_cache {
~\.(jpg|jpeg|png|webp|gif|mp4|css|js|ico|woff2)(\?.*)?$ "public, max-age=604800";
~\.html$ "public, max-age=600";
default "public, max-age=600";
}
map $upstream_cache_status $server_cache_status {
default $upstream_cache_status;
"" "NONE";
}
map "$http_if_none_match:$http_if_modified_since" $client_cache_request {
default "MISS";
"~.+:.+" "REVALIDATE";
"~.+:" "REVALIDATE";
"~:.+" "REVALIDATE";
}
server {
listen 80;
listen [::]:80;
server_name soulminingrig.com www.soulminingrig.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl reuseport backlog=65535 rcvbuf=256k sndbuf=256k fastopen=256 so_keepalive=on;
listen [::]:443 ssl reuseport backlog=65535 rcvbuf=256k sndbuf=256k fastopen=256 so_keepalive=on ipv6only=on;
listen 443 quic reuseport;
listen [::]:443 quic reuseport;
http2 on;
http3 on;
server_name soulminingrig.com www.soulminingrig.com;
client_max_body_size 50M;
location ~* \.(jpg|jpeg|png|webp|gif|ico|mp4|js|css|woff2)(\?.*)?$ {
proxy_pass http://backend_sm;
include snippets/proxy_headers.conf;
proxy_http_version 1.1;
proxy_redirect off;
proxy_cache static_cache;
proxy_cache_valid 200 301 302 7d;
proxy_cache_valid 404 1m;
proxy_cache_revalidate on;
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
proxy_connect_timeout 3s;
proxy_read_timeout 15s;
expires 7d;
add_header X-Cache-Status $upstream_cache_status always;
add_header X-Server-Cache-Status $server_cache_status always;
add_header X-Client-Cache-Request $client_cache_request always;
add_header X-Client-Cache-Policy "public, max-age=604800" always;
add_header Cache-Control "public, max-age=604800" always;
}
location / {
proxy_pass http://backend_sm/;
include snippets/proxy_headers.conf;
proxy_http_version 1.1;
proxy_redirect off;
proxy_cache posts;
proxy_cache_key $scheme$host$request_uri;
proxy_cache_valid 200 10m;
proxy_cache_valid 301 1h;
proxy_cache_valid 404 1m;
proxy_cache_revalidate on;
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504 http_403 http_404;
proxy_cache_background_update on;
proxy_cache_lock on;
proxy_connect_timeout 3s;
proxy_read_timeout 15s;
expires $static_cache;
add_header X-Cache-Status $upstream_cache_status always;
add_header X-Server-Cache-Status $server_cache_status always;
add_header X-Client-Cache-Request $client_cache_request always;
add_header X-Client-Cache-Policy $static_cache always;
add_header Cache-Control $static_cache always;
}
include snippets/common_error_pages.conf;
include snippets/ssl_common.conf;
ssl_certificate /hoge/fullchain.pem; # Certbot द्वारा प्रबंधित
ssl_certificate_key /hoge/oulminingrig.com/privkey.pem;
# Certbot द्वारा प्रबंधित
}
बोनस: nginxfmt.py
यह वास्तव में बहुत अच्छा है।
यह एक फॉर्मेटर है, लेकिन मुझे लगता है कि इसकी गुणवत्ता सबसे अधिक है।
यह AUR में उपलब्ध है।
yay -S nginx-config-formatter
उपयोग करने के लिए, nginxfmt.py example.conf इसे फॉर्मेट कर देगा, इसलिए
find . -name "*conf" | xargs -I{} nginxfmt.py {}
यह एक साथ सभी को फॉर्मेट कर देता है।
कुछ समय पहले तक मैं nginxbeautifier का उपयोग कर रहा था, लेकिन इसने रीडायरेक्ट के आसपास के सिंटैक्स को खराब कर दिया, इसलिए मैंने इसे बदल दिया।