Hero Image
Shell脚本学习笔记

Shell 脚本学习笔记 执行算术运算 val=`expr $a + $b` 运算符 符号 说明 示例 ! 非运算 [ ! false ] -o 或运算 [ $a -lt 20 -o $b -gt 20 ] -a 与运算 [ $a -lt 20 -a $b -gt 20 ] = 相等检测 [ $a = $b ] != 不相等检测 [ $a != $b ] -z 字符串长度是否为 0,为 0 则返回 true [ -z $a ] -n 字符串长度不为 0, 不为 0 返回 true [ -n $a ] str 检测字符串是否为空,不为空返回 true [ $a ] -b 检测文件是否是块设备文件 [ -b $file ] -c 检测文件是否是字符设备 .. -d 检测文件是否为目录 [ -d $file ] -f 检测文件是否为普通文件 [ -f $file ] -r 检测文件是否可读 .. -w 检测文件是否可写 .. -x 检测文件是否可执行 .. -s 检测文件是否为空 .. -e 检测文件是否存在 .. 特殊变量 变量 含义 $0 当前脚本的文件名 $n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数 $# 传递给脚本或函数的参数个数 $* 传递给脚本或函数的所有参数,所有参数被当做一个词,例如 “1 2 3” $@ 传递给脚本或函数的所有参数,每个参数当做一个词,用双引号包含,例如"1" “2” “3” $? 上个命令的退出状态,或函数的返回值 $$ 当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID POSIX 程序退出状态 状态码 含义 0 命令成功退出 > 0 在重定向或者单词展开期间(~、变量、命令、算术展开以及单词切割)失败 1 - 125 命令不成功退出。特定的退出值的含义,有各个命令自行定义 126 命令找到了,但是文件无法执行 127 命令没有找到 > 128 命令因收到信号而死亡 输入输出重定向 命令 说明 command > file 将输出重定向到 file。 command > file 将输出以追加的方式重定向到 file。 n > file 将文件描述符为 n 的文件重定向到 file。 n » file 将文件描述符为 n 的文件以追加的方式重定向到 file。 n >& m 将输出文件 m 和 n 合并。 n <& m 将输入文件 m 和 n 合并。 « tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 文件包含 使用.或者source包含文件

Hero Image
openresty+redis拦截高频访问IP

openresty+redis 拦截高频访问 IP init_by_lua_block { redis = require "redis" client = redis.connect('127.0.0.1', 6379) } server { listen 8080; location / { access_by_lua_file /usr/local/nginx/conf/lua/block.lua; proxy_pass http://192.168.1.102:8000; } } -- Redis-based IP rate limiting / blocking for OpenResty (ngx_lua) -- NOTE: -- This script assumes a global `client` variable is used/stored. -- Make sure `redis` module is available and `client` is initialized somewhere. local function isConnected() return client:ping() end local function createRedisConnection() return redis.connect("127.0.0.1", 6379) end -- 如果发生 redis 连接失败,将停止拦截(直接放行) if pcall(isConnected) then -- already connected (or ping succeeded) else -- not connected; try reconnect if pcall(createRedisConnection) then -- 断开重连:会导致每次访问都需要重连 redis -- 访问量大时建议:关闭重连逻辑(pcall 不执行),直接 ngx.exit 放行/终止 client = createRedisConnection() else ngx.exit(ngx.OK) end end local ttl = 60 -- 监测周期(秒) local bktimes = 30 -- 在监测周期内达到触发拦截的访问量 local block_ttl = 600 -- 触发拦截后拦截时间(秒) local ip = ngx.var.remote_addr local ipvtimes = client:get(ip) if ipvtimes then if ipvtimes == "-1" then -- blocked return ngx.exit(403) else local last_ttl = client:ttl(ip) -- ngx.say("key exist.ttl is ", last_ttl) if last_ttl == -1 then client:set(ip, 0) client:expire(ip, ttl) -- ngx.say("ttl & vtimes recount") return ngx.exit(ngx.OK) end local vtimes = tonumber(client:get(ip)) + 1 if vtimes < bktimes then client:set(ip, vtimes) client:expire(ip, last_ttl) -- ngx.say(ip, " view ", vtimes, " times") return ngx.exit(ngx.OK) else -- ngx.say(ip, " will be block next time.") client:set(ip, -1) client:expire(ip, block_ttl) return ngx.exit(ngx.OK) end end else -- key does not exist client:set(ip, 1) -- ngx.say(ip, " view 1 times") client:expire(ip, ttl) return ngx.exit(ngx.OK) end

Hero Image
設定 Haproxy 以防止 DDOS 攻擊

設定 Haproxy 以防止 DDOS 攻擊 TCP syn flood attacks vi /etc/sysctl.conf # Protection from SYN flood net.ipv4.tcp_syncookies = 1 net.ipv4.conf.all.rp_filter = 1 net.ipv4.tcp_max_syn_backlog = 1024 Slowloris like attacks defaults option http-server-close timeout http-request 5s timeout connect 5s timeout client 30s timeout server 10s timeout tunnel 1h 限制每一個 user 的連線數量 普通用戶瀏覽網站的網頁,或是從網站下載東西時,瀏覽器一般會建立 5-7 個 TCP 鏈接。當一個惡意 client 打開了大量 TCP 連線時,耗費大量資源,因此我們必須要限制同一個用戶的連線數量。 但如果有很多使用者,是從某一個私有網段,透過 NAT 的方式連線到 Server 時,且實際上我們也不知道,到底哪一個會是 NAT 的轉址後的 IP,不知道該將哪個 IP 設定為白名單,這樣的限制就會造成問題,因此我們認為實際的環境,這樣的設定應該要保留不處理。 以下是一個設定的範例,最重要的地方是在 frontend ft_web 區塊的設定。 global stats socket ./haproxy.stats level admin defaults option http-server-close mode http timeout http-request 5s timeout connect 5s timeout server 10s timeout client 30s listen stats bind 0.0.0.0:8880 stats enable stats hide-version stats uri / stats realm HAProxy Statistics stats auth admin:admin frontend ft_web bind 0.0.0.0:8080 # Table definition stick-table type ip size 100k expire 30s store conn_cur # Allow clean known IPs to bypass the filter tcp-request connection accept if { src -f /etc/haproxy/whitelist.lst } # Shut the new connection as long as the client has already 10 opened tcp-request connection reject if { src_conn_cur ge 10 } tcp-request connection track-sc1 src # Split static and dynamic traffic since these requests have different impacts on the servers use_backend bk_web_static if { path_end .jpg .png .gif .css .js } default_backend bk_web # Dynamic part of the application backend bk_web balance roundrobin cookie MYSRV insert indirect nocache server srv1 192.168.1.2:80 check cookie srv1 maxconn 100 server srv2 192.168.1.3:80 check cookie srv2 maxconn 100 # Static objects backend bk_web_static balance roundrobin server srv1 192.168.1.2:80 check maxconn 1000 server srv2 192.168.1.3:80 check maxconn 1000 限制每個 user 產生新連線的速率 Limiting the connection rate per user 惡意的使用者會在短時間內建立很多連線,但如果產生新連線的速度太高,就會消耗掉過多的資源服務一個使用者。

Hero Image
Nginx请求处理流程你了解吗?

Nginx 请求处理流程你了解吗? 11 个处理阶段 1)NGX_HTTP_POST_READ_PHASE: 接收到完整的 HTTP 头部后处理的阶段,它位于 uri 重写之前,实际上很少有模块会注册在该阶段,默认的情况下,该阶段被跳过。 2)NGX_HTTP_SERVER_REWRITE_PHASE: URI 与 location 匹配前,修改 URI 的阶段,用于重定向,也就是该阶段执行处于 server 块内,location 块外的重写指令,在读取请求头的过程中 nginx 会根据 host 及端口找到对应的虚拟主机配置。 3)NGX_HTTP_FIND_CONFIG_PHASE: 根据 URI 寻找匹配的 location 块配置项阶段,该阶段使用重写之后的 uri 来查找对应的 location,值得注意的是该阶段可能会被执行多次,因为也可能有 location 级别的重写指令。 4)NGX_HTTP_REWRITE_PHASE: 上一阶段找到 location 块后再修改 URI,location 级别的 uri 重写阶段,该阶段执行 location 基本的重写指令,也可能会被执行多次。 5)NGX_HTTP_POST_REWRITE_PHASE: 防止重写 URL 后导致的死循环,location 级别重写的后一阶段,用来检查上阶段是否有 uri 重写,并根据结果跳转到合适的阶段。 6)NGX_HTTP_PREACCESS_PHASE: 下一阶段之前的准备,访问权限控制的前一阶段,该阶段在权限控制阶段之前,一般也用于访问控制,比如限制访问频率,链接数等。 7)NGX_HTTP_ACCESS_PHASE: 让 HTTP 模块判断是否允许这个请求进入 Nginx 服务器,访问权限控制阶段,比如基于 ip 黑白名单的权限控制,基于用户名密码的权限控制等。 8)NGX_HTTP_POST_ACCESS_PHASE: 访问权限控制的后一阶段,该阶段根据权限控制阶段的执行结果进行相应处理,向用户发送拒绝服务的错误码,用来响应上一阶段的拒绝。 9)NGX_HTTP_TRY_FILES_PHASE: 为访问静态文件资源而设置,try_files 指令的处理阶段,如果没有配置 try_files 指令,则该阶段被跳过。 10)NGX_HTTP_CONTENT_PHASE: