语境
我有一个带有 nginx 服务器和 Passenger 的 Rails 应用程序。
应用程序根据请求 URL 动态生成页面:如果数据库中存在 URL,则应用程序呈现相应的页面。如果数据库中不存在 URL,则应用程序呈现 404 页面。
问题
许多爬虫程序正在尝试寻找漏洞并请求大量的 URL(.git、admin/config.php、wp-login.php 等...)
每个请求都会到达 Rails 应用程序,从而在数据库中产生点击。
解决方案
我正在寻找一种方法来做到这一点:
- 第一次请求“不存在”的 URL 时,它会通过 Rails 应用程序进行处理,并返回 404
- nginx 缓存并记住此 URL
- 下次请求相同的 URL 时,nginx 直接响应 404 状态,而不通过 Rails 应用
另外,当 Rails 应用程序重新启动时(通过 Passenger),应该清除该缓存。
特里斯
- 我尝试添加
fastcgi_cache_valid 404 10m;
服务器块,但没有作用。 - 也尝试过
proxy_cache_valid 404 10m;
您可能已经猜到了,我是 nginx 新手。感谢您的帮助。
Nginx 配置
server {
listen ...;
server_name ...;
root /path/to/rails/app;
error_page 404 /404;
error_page 500 502 503 504 /500;
# First I tried this, no success so I removed it
fastcgi_cache_valid 404 10m;
# Then I tried this, no success so I removed it also
proxy_cache_valid 404 10m;
location / {
gzip_static on;
etag off;
charset utf-8;
add_header Cache-Control "max-age=0, private, must-revalidate";
add_header Referrer-Policy strict-origin-when-cross-origin;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options deny;
add_header X-XSS-Protection "1; mode=block";
location = / {
try_files /cached/index.html @rails;
}
location / {
try_files /cached$uri.html /cached$uri $uri @rails;
}
}
location @rails {
passenger_enabled on;
passenger_ruby /path/to/ruby;
passenger_app_env production;
}
}
答案1
我最熟悉反向代理环境中的缓存,因此我会采用这种方法。幸运的是,Nginx 能够相当轻松地为自己进行代理:
# define your cache
proxy_cache_path /path/to/cache levels=1:2 keys_zone=cacheName:[metaDataSize] max_size=[maxCacheSize] inactive=60m use_temp_path=off;
http {
server {
# Any TLS, caching, or gzipping on this virtual server
listen ...;
server_name [Actual Domain];
location / {
proxy_pass http://127.0.0.1:80;
proxy_set_header Host [domain.passenger];
# Activate and configure caching here
proxy_cache cacheName;
proxy_cache_valid 404 10m;
...any other proxy settings you want.
# Forward original request info
proxy_set_header X-Original-Host $http_host;
proxy_set_header X-Original-Scheme $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
# Gzip if you want
gzip on;
gzip_proxied any;
...etc
}
}
server {
# Any Rails/Passenger configuration on this virtual server
listen 80;
server_name [domain.passenger];
# Don't log requests twice
access_log off;
# Only allow local requests
allow 127.0.0.1;
deny all;
location / {
passenger_enabled on;
passenger_ruby /path/to/ruby;
passenger_app_env production;
}
}
}
清除缓存只需要运行rm -rf /path/to/cache/*
,因此您可以按照自己最喜欢的方式将其编写到 Rails 重启过程中。