从0开始,开发WAF+(二)

本文说一下程序初始化相关代码和nginx配置

1:ngx lua的执行阶段需要大家先了解下。参考这篇博客http://www.mrhaoting.com/?p=157

2:OpenStar的waf.conf配置文件

#lua_socket_log_errors off;
#lua_package_cpath "/opt/openresty/openstar/lib/?.so;;";
#lua_need_request_body on; #开启post


lua_code_cache on; # 关闭lua_cache 缓存 用于调试, 线上需要开启 设置为on

lua_package_path "/opt/openresty/openstar/lib/?.lua;/opt/openresty/lualib/?.lua";
# 这里需要根据自己安装的OR的路径,建议将OpenStar放到OR根目录。

lua_regex_cache_max_entries 102400;

# 1m 存储约1000+条IP数据
lua_shared_dict token_list 20m;	   # token 存放
lua_shared_dict count_dict 1m;     # 用于计数数据的保存
lua_shared_dict config_dict 5m;    # 保存config中部分配置
lua_shared_dict ip_dict 30m;       # 用于记录黑、白名单ip
lua_shared_dict limit_ip_dict 50m;   # 用于URL HOST IP 访问计数

more_set_headers 'Server: OpenStar';

# 暂时没有用nginx 自带的限速功能
#limit_req_zone  $binary_remote_addr zone=allips:50m rate=15r/s;
#limit_conn_zone $binary_remote_addr zone=addr:50m;

init_by_lua_file  /opt/openresty/openstar/init.lua;
# init 就是程序初始化阶段

#rewrite_by_lua_file /opt/openresty/openstar/rewrite.lua;
# rewrite 阶段暂时没有用上

access_by_lua_file /opt/openresty/openstar/access_all.lua;
# 主要的访问控制阶段

body_filter_by_lua_file /opt/openresty/openstar/body.lua;
# 返回内容替换阶段

3:nginx.conf配置

需要在nginx.conf的http节点下引用waf.conf即可。

user nobody nobody;

# CPU 的亲源等
    worker_processes  auto;
    #worker_cpu_affinity  0001 0010 0100 1000;

    worker_rlimit_nofile 100000;

#错误日志处理
    #error_log logs/error.log crit;
    #error_log logs/error.log debug;
    #error_log  logs/error.log notice;
    error_log  logs/error.log;
    #error_log  logs/error.log  info;

events {
    use epoll;
    accept_mutex off;   #关闭惊群
    worker_connections 10240; #根据你的机器配置
    multi_accept on;
}

http {  

    #引用waf配置
    include waf.conf;

    ### log处理
        log_format  main
            '$remote_addr - $remote_user [$time_local] $request '
            '"$status" $body_bytes_sent "$http_referer" '
            '"$http_user_agent" "$http_x_forwarded_for"';
        access_log off;

    ### 业务相关 ###
        include       mime.types;
        default_type text/html;
        charset utf-8;
        #resolver 8.8.8.8;
        error_page   404 400        /40x.html;
        error_page   500 502 503 504     /50x.html;
        #error_page   500 502 503 504  http://www.baidu.com;

    ###   IO相关
    
        # 建议和打开文件数一致,inactive 是指经过多长时间文件没被请求后删除缓存
        open_file_cache max=65535 inactive=60s;
        # 在inactive时间 1 次没有请求就删除
        open_file_cache_min_uses 1;
        # 这个是指多长时间检查一次缓存的有效信息
        open_file_cache_valid 60s;
        open_file_cache_errors on;
        tcp_nopush on;
        tcp_nodelay on;
        server_tokens off;
        sendfile on;
        


        # time相关
        keepalive_timeout 30;
        client_header_timeout 30;
        client_body_timeout 30;
        reset_timedout_connection on;
        send_timeout 30;

        # gzip
        #include gzip.conf;

        # 缓存相关
        client_max_body_size 10m;
        client_header_buffer_size 4k;
        server_names_hash_bucket_size 128;
        large_client_header_buffers 10 4k;


    ###   反向代理缓存处理
        #proxy_cache_path /mnt/ngx_cache/ levels=1:2 keys_zone=my_cache:300m max_size=2g inactive=60m;
        #proxy_buffer_size 128k;
        #proxy_buffers 4 128k;
        #proxy_busy_buffers_size 1024k;
        #proxy_temp_file_write_size 1024k;

    # http
    server {
        listen  80;
        server_name localhost;        
        root html;
        
        #lua执行的主目录
        set $lua_path "/opt/openresty/openstar/";
        #根目录
        location / {
            #limit_req zone=allips nodelay;
            default_type text/html;
        }

        location ~ ^/api/([-_a-zA-Z0-9/]+) {

            #limit_req zone=allips nodelay;

            # 重写阶段
            #rewrite_by_lua_file "${lua_path}api_rewrite.lua"

            # 准入阶段完成参数验证
            #access_by_lua_file  "${lua_path}api_access.lua";

            #内容生成阶段
            content_by_lua_file "${lua_path}api/$1.lua";

            #内容替换阶段
            #body_filter_by_lua_file "${lua_path}api_body.lua";

            #日志处理阶段
            #log_by_lua_file "${lua_path}api/api_log.lua";
        }
                   
        location ~* \.(gif|jpg|png|jpeg|bmp|css|js|flv|ico|swf|zip|txt)$ {             
            access_log off;
            proxy_redirect off;           
            proxy_cache_valid 200 302 6h;  
            proxy_cache_valid 301 1d;  
            proxy_cache_valid any 1m;  
            expires 30d;  
            }

    }

    # ssl
        #   server {
        #        listen 443;
        #        server_name  localhost;
        #        root html;
        #        access_log off;
        #        #access_log  logs/access_https.log main;
        #
        #        ssl on;
        #        ssl_certificate  /opt/openresty/nginx/ssl/server.crt;
        #        ssl_certificate_key  /opt/openresty/nginx/ssl/server_nopwd.key;
        #
        #        location / {
        #            limit_req zone=allips nodelay;
        #            default_type text/html;
        #            #content_by_lua_file "/opt/openresty/openstar/index/index.lua";
        #        }
        #
        #        location ~* \.(gif|jpg|png|jpeg|bmp|css|js|flv|ico|swf|zip|txt){             
        #            access_log off;
        #            proxy_redirect off;           
        #            proxy_cache_valid 200 302 6h;  
        #            proxy_cache_valid 301 1d;  
        #            proxy_cache_valid any 1m;  
        #            expires 30d;  
        #            }
        #        }

include our.conf;
# 自己的业务相关配置

}

上面我配置的nginx一些可以参考下, 使用:

  • 配置nginx.conf 在http节点,引用waf.conf。注:原ngx相关配置基本不用修改,该优化优化、该做CPU亲缘绑定继续、该动静分离还继续、该IO、TIME等优化继续不要停。
  • 配置waf.conf 修改lua_package_path,使用正确的路径即可
  • 设置目录权限 OpenStar目录建议放到OR下,方便操作,该目录ngx运行用户有读写执行权限即可。因为要写日志,暂时没有用ngx.log,后续可能会改动。
  • lua文件修改 在init.lua中,修改conf_json参数,config.json文件绝对路径写好。
  • api使用 如果需要使用相关api,需要配置在某个servers下配置一个location,参照一下,配置比较简单,set $lua_path 根据实际情况配置即可

 

初始化阶段lua代码

在前面的我们执行流程图中,分层对请求进行处理,那么就需要一个基础的配置文件,然后在有规则列表配置文件进行分开。那么我就定义了主配置文件


{
    // 注释 线上不要有
	"redis_Mod" : {"state":"off","ip":"127.0.0.1","Port" : 6379,"Password":"yesorno@123"},
    // redis_Mod 配置的是需要连接的redis相关配置, 这个主要是用于集群操作时使用,把配置和拦截计数放到redis

	"realIpFrom_Mod" : "on",
    // 表示是否开启从http头取用户真实ip

	"ip_Mod" : "on",
    // 表示是否开启ip 黑白名单

	"host_method_Mod" : "on",
    // 表示是否启用 host method 白名单 (用于host准入和method过滤)

	"app_Mod" : "on",
    // 表示是否启用 自定义规则 这里面的规则用法灵活
	
	"referer_Mod" : "on",
    // 表示是否开启referer 白名单

	"url_Mod" : "on",
    // 表示是否开启 url 的黑白名单

	"header_Mod" : "on",
    // 表示是否开启 header 黑名单

	"agent_Mod" : "on",
    // 表示是否开启useragent 黑名单

	"cookie_Mod" : "on",
    // 表示是否开启 cookie 黑名单

	"args_Mod" : "on",
    // 表示是否开启 get 参数过滤 黑名单

	"post_Mod" : "on",
    // 表示是否开启 post 参数过滤 黑名单

	"network_Mod" : "on",
    // 表示是否开启 网络层访问频率限速 频率黑名单

	"replace_Mod" : "off",
    // 表示是否开启 返回内容过滤

	"debug_Mod" : true,
    // 表示是否开启 debug 记录log

	"baseDir" : "/opt/openresty/openstar/",
    // baseDir 程序根目录

	"logPath" : "/opt/openresty/openstar/logs/",
    // logPath 配置log保存路径

	"jsonPath" : "/opt/openresty/openstar/conf_json/",
    // jsonPath 配置规则json文件路径

	"htmlPath" : "/opt/openresty/openstar/index/",
    // htmlPath 配置程序静态文件存放路径

	"sayHtml" : "request error!"
    // sayHtml 配置应用层deny 返回的内容

}

init阶段进行初始化(主配置文件,过滤规则配置文件)

直接在代码段里说啦。

local Config = {}

-- 引用json库
local cjson_safe = require "cjson.safe"

--- config.json 文件绝对路径(需要根据自己的情况进行配置)
local config_json = "/opt/openresty/openstar/config.json"

--- 读取文件(全部读取)
local function readfile(filepath)
	local fd = io.open(filepath,"r")
	if fd == nil then return end -- 文件读取错误返回
    local str = fd:read("*a") --- 全部内容读取
    fd:close()
    return str
end

--- 载入JSON文件
local function loadjson(_path_name)
	local x = readfile(_path_name)
	local json = cjson_safe.decode(x) or {} --- json decode 失败返回一个空table
	return json
end

--- 载入config.json全局基础配置
function loadConfig()
	local _jsonConfig = loadjson(config_json)
	Config.base = _jsonConfig
	local _basedir = Config.base.jsonPath
	Config.realIpFrom_Mod = loadjson(_basedir.."realIpFrom_Mod.json")
	Config.ip_Mod = loadjson(_basedir.."ip_Mod.json")
	Config.host_method_Mod = loadjson(_basedir.."host_method_Mod.json")
	Config.app_Mod = loadjson(_basedir.."app_Mod.json")
	Config.referer_Mod = loadjson(_basedir.."referer_Mod.json")
	Config.url_Mod = loadjson(_basedir.."url_Mod.json")	
	Config.header_Mod = loadjson(_basedir.."header_Mod.json")	
	Config.useragent_Mod = loadjson(_basedir.."useragent_Mod.json")	
	Config.cookie_Mod = loadjson(_basedir.."cookie_Mod.json")
	Config.args_Mod = loadjson(_basedir.."args_Mod.json")
	Config.post_Mod = loadjson(_basedir.."post_Mod.json")	
	Config.network_Mod = loadjson(_basedir.."network_Mod.json")
	Config.replace_Mod = loadjson(_basedir.."replace_Mod.json")
	--- 将全局配置参数存放到共享内存(config_dict)中
	local config_dict = ngx.shared.config_dict
	for k,v in pairs(Config) do
		if type(v) == "table" then
			v = cjson_safe.encode(v)
		end
		config_dict:safe_set(k,v,0)
	end
end

-- 读取所有配置信息(全局配置文件、规则配置文件)
loadConfig()

--- 初始化ip_mod列表
--- 将规则文件ip_Mod中的黑白名单ip读取到dict中
local function set_ip_mod()
	local tb_ip_mod = Config.ip_Mod
	local _dict = ngx.shared["ip_dict"]
	for i,v in ipairs(tb_ip_mod) do
		if v.action == "allow" then
			_dict:safe_set(v.ip,"allow",0)
		elseif v.action == "deny" then
			_dict:safe_set(v.ip,"ip_mod deny",0)
		else
		end
	end
end

if Config.base["ip_Mod"] == "on" then
	set_ip_mod()
end

init阶段其实还有些其他代码,这里没有说明,用到的时候在说吧

转载于:https://my.oschina.net/u/1458760/blog/687613

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值