1、进入nginx配置文件中
cd /usr/local/openresty/nginx/conf
vi nginx.conf
user www;
worker_processes 2;
worker_cpu_affinity auto;
error_log /data/nginx/error.log;
worker_rlimit_nofile 65535;
pid /data/nginx/nginx.pid;
events {
worker_connections 10240;
use epoll;
multi_accept on;
}
http {
include mime.types;
default_type application/octet-stream;
map $time_iso8601 $logdate {
'~^(?<ymd>\\d{4}-\\d{2}-\\d{2})' $ymd;
default 'date-not-found';
}
map $time_iso8601 $request_times {
'~^(?<ymdhms>\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2})' $ymdhms;
default 'date-not-found';
}
log_format access-upstream '{"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_times,'
'"http_host":"$host",'
'"url":"$uri",'
'"agent":"$http_user_agent",'
'"status":"$status"}';
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_names_hash_bucket_size 128;
server_names_hash_max_size 512;
keepalive_timeout 1000s;
client_header_timeout 15s;
client_body_timeout 15s;
send_timeout 1000s;
proxy_cache_path /data/nginx levels=1:2 keys_zone=nginx-cache:20m max_size=50g inactive=168h;
client_body_buffer_size 512k;
client_header_buffer_size 256k;
client_max_body_size 1024m;
large_client_header_buffers 2 8k;
proxy_connect_timeout 1000s;
proxy_send_timeout 1000s;
proxy_read_timeout 1000s;
proxy_buffer_size 128k;
proxy_buffers 8 256k;
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
proxy_next_upstream http_502 http_504 http_404 error timeout invalid_header;
fastcgi_intercept_errors on;
fastcgi_ignore_client_abort on;
fastcgi_connect_timeout 1000s;
fastcgi_send_timeout 1000s;
fastcgi_read_timeout 1000s;
fastcgi_buffer_size 128k;
fastcgi_buffers 8 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 32k;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_vary on;
gzip_disable "MSIE [1-6].";
include vhost/*.conf;
}
2、创建vhost目录及配置
mkdir vhost
mkdir -p /data/{nginx,wwwroot}
mkdir -p /data/wwwroot/error
将index.html上传到/data/wwwroot目录下面
将403.html、404.html、50x.html上传到/data/wwwroot/error
cd vhost/
touch localhost_80.conf
vi localhost_80.conf
server {
listen 80 default_server;
server_name _;
error_log /data/nginx/localhost_error.log crit;
access_log /data/nginx/localhost_acess_$logdate.log access-upstream;
error_page 401 /401.html;
error_page 403 /403.html;
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location / {
return 401;
}
location = /401.html {
root "/data/wwwroot/error";
}
location = /403.html {
root "/data/wwwroot/error";
}
location = /404.html {
root "/data/wwwroot/error";
}
location = /50x.html {
root "/data/wwwroot/error";
}
}
3、创建用户及授权
groupadd www
useradd -g www -s /sbin/nologin -M www
chown -R www:www /data/wwwroot
chown -R www:www /data/nginx
chown -R www:www /usr/local/openresty
我们为了解决后端rsa数据验证压力,此步骤需要放入openresty这块解决压力更加
4、安装rsa依赖
wget https://github.com/spacewander/lua-resty-rsa/archive/refs/tags/v1.1.0.tar.gz
tar -zxf lua-resty-rsa-1.1.0.tar.gz
cd lua-resty-rsa-1.1.0/lib/resty
cp rsa.lua /usr/local/openresty/lualib/resty/
5、/usr/local/openresty/nginx/conf/vhost/www.testrsaredislua.com_80.conf配置文件修改
upstream api {
server 192.168.0.191:8888;
}
server {
listen 80;
server_name www.testrsaredislua.com;
error_log /data/nginx/www.testrsaredislua.com_error.log crit;
access_log /data/nginx/www.testrsaredislua.com_acess_$logdate.log access-upstream;
lua_code_cache off;
autoindex off;
server_tokens off;
error_page 401 /401.html;
location / {
proxy_set_header Host $host;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header Access-Control-Allow-Origin "$http_origin";
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Access-Token';
if ($request_method ~* OPTIONS) {
return 200;
}
add_header Cache-Control no-cache;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
access_by_lua_file /data/wwwroot/rsa-redis.lua;
proxy_pass http://api;
}
location = /401.html {
root "/data/wwwroot/error";
}
}
6、/usr/local/openresty/nginx/conf/vhost/www.testrsaredislua.com_8888.conf配置文件修改
server {
listen 8888;
root "/data/wwwroot/gpapi/public";
error_log /data/nginx/www.testrsaredislua.com8888_error.log crit;
access_log /data/nginx/www.testrsaredislua.com8888_acess_$logdate.log access-upstream;
error_page 403 /403.html;
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=/$1 last;
}
index index.php;
autoindex off;
}
location = /403.html {
root "/data/wwwroot/error";
}
location = /404.html {
root "/data/wwwroot/error";
}
location = /50x.html {
root "/data/wwwroot/error";
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
7、在/data/wwwroot/目录下创建rsa-redis.lua文件
--引入Redis
local redis = require "resty.redis";
--引入rsa
local rsa = require "resty.rsa";
--Redis链接ip
local ip = "192.168.0.191"
--Redis链接端口
local port = 6379
--Redis连接密码
local pass = "123456"
--鉴权Redis
local function connAuth()
local red = redis:new();
local connCount, err = red:connect(ip, port);
if not connCount then
ngx.say("failed to connect: ", err)
close_redis(red)
return
end
red:set_timeouts(2000);
local ok, err = red:auth(pass)
if not ok then
ngx.say("failed to auth: ", err)
close_redis(red)
return
end
return red
end
--关闭Redis
local function close_redis(red)
if not red then
return
end
--释放连接(连接池实现)
local pool_max_idle_time = 10000
local pool_size = 100
local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)
if not ok then
ngx.say("set keepalive error : ", err)
end
end
--获取请求者IP
local function getIp()
local clientIP = ngx.req.get_headers()["X-Real-IP"]
if clientIP == nil then
clientIP = ngx.req.get_headers()["x_forwarded_for"]
end
if clientIP == nil then
clientIP = ngx.var.remote_addr
end
return clientIP
end
--获取用户访问IP
local clientIP = getIp();
--封禁token时间(秒)
local token_block_time= 120
--指定token访问频率计数最大值(次)
local token_max_count = 3
--如果数据为空的情况下
local function is_empty(value)
if type(value) == "table" then
return next(value) == nil
elseif type(value) == "string" then
return #value == 0
elseif type(value) == "nil" then
return true
end
return false
end
--过滤特殊字符串(只保留字母与数字,字母不区分大小写)
local function filter_special_chars(s)
local ss = {}
local k = 1
while true do
if k > #s then break end
local c = string.byte(s,k)
if not c then break end
if c<192 then
if (c>=48 and c<=57) or (c>= 65 and c<=90) or (c>=97 and c<=122) then
table.insert(ss, string.char(c))
end
k = k + 1
end
end
return table.concat(ss)
end
--如果头部信息没有指定的参数或是指定参数的值无法解析,加入IP黑名单
--如果同样的头部参数键在封禁token时间内连续访问指定token访问频率计数最大值次以上,加入IP黑名单
local function set_blacklist()
local header = ngx.req.get_headers();
local red = connAuth();
local token, err = header["x-token"];
--如果参数为空的情况下
if not token then
local res, err = red:sismember('black-list', clientIP);
if res ~= 1 then
red:sadd('black-list', clientIP)
end
close_redis(red)
return ngx.exit(401)
else
--如果参数值为空的情况下
if is_empty(token) then
local res, err = red:sismember('black-list', clientIP);
if res ~= 1 then
red:sadd('black-list', clientIP)
end
close_redis(red)
return ngx.exit(401)
end
--如果同一个token键在封禁token时间内连续访问指定token访问频率计数最大值次
local outputToken = filter_special_chars(token)
local redToken, err = red:get(outputToken);
if redToken ~= ngx.null then
if tonumber(redToken) >= tonumber(token_max_count) then
local res, err = red:sismember('black-list', clientIP);
if res ~= 1 then
red:sadd('black-list', clientIP)
end
close_redis(red)
return ngx.exit(401)
else
red:incr(outputToken)
end
end
if redToken == ngx.null then
red:set(outputToken,1)
end
red:expire(outputToken,token_block_time)
--如果参数值采用base64解析不开的情况下
local encrypted, err = tostring(ngx.decode_base64(token))
if not encrypted then
local res, err = red:sismember('black-list', clientIP);
if res ~= 1 then
red:sadd('black-list', clientIP)
end
close_redis(red)
return ngx.exit(401)
end
--采用rsa技术解析token base64过后的值内容
local priv_key = '-----BEGIN PRIVATE KEY-----\n' ..red:get('priv_key')..'\n-----END PRIVATE KEY-----';
local priv, err = rsa:new({private_key = priv_key})
local dst, err = rsa.decrypt(priv, encrypted)
if not dst then
local res, err = red:sismember('black-list', clientIP);
if res ~= 1 then
red:sadd('black-list', clientIP)
end
close_redis(red)
return ngx.exit(401)
end
end
end
--查看是否在黑名单里面
local function get_blacklist()
local red = connAuth();
local res, err = red:sismember('black-list', clientIP);
if res == 1 then
close_redis(red);
return ngx.exit(401);
end
close_redis(red);
end
get_blacklist();
set_blacklist();