棣栭〉   娉ㄥ唽   鐧诲綍
V2EX = way to explore
V2EX 鏄竴涓叧浜庡垎浜拰鎺㈢储鐨勫湴鏂�
鐜板湪娉ㄥ唽
宸叉敞鍐岀敤鎴疯  鐧诲綍
Distributions
鈥� Ubuntu
鈥� Fedora
鈥� CentOS
涓枃璧勬簮绔�
鈥� 缃戞槗寮€婧愰暅鍍忕珯
V2EX  鈥�  Linux

鍩轰簬 Nginx && Lua 鐨勭畝鏄� CC 闃叉姢鏂规

  •  
  •   knownsec200 路 54 鍒嗛挓鍓� 路 142 娆$偣鍑�

    0脳00 鍓嶈█

    1.CC 鏀诲嚮绠€杩�
    	CC 鏀诲嚮(Challenge Collapsar)鏄父瑙佺綉绔欏簲鐢ㄥ眰鏀诲嚮鐨勪竴绉嶏紝鐩殑鏄秷鑰楁湇鍔″櫒璧勬簮锛岄檷浣庝笟鍔″搷搴旀晥鐜囷紱鏋佺鎯呭喌浼氳绔欑偣鏃犳硶姝e父鎻愪緵鏈嶅姟锛�
    2.鏈枃瑕佺偣
    	鏃ㄥ湪鎻忚堪锛岄€氳繃 ngx_lua 妯″潡寮€鍙戝苟闆嗘垚鍩轰簬浠ょ墝妗剁畻娉曠殑绠€鏄� IP 闄愰€熷姛鑳斤紝瀹炵幇 CC 鏀诲嚮鐨勯槻鎶わ紱
    3.鏈枃闈㈠悜鐨勪汉缇�
    	鏈変竴瀹氱殑杩愮淮銆佸紑鍙戝熀纭€鐨勪汉缇わ紱
    	
    

    0脳01 鏈嶅姟閮ㄧ讲

    0.鐜
    	a.绯荤粺
    		CentOS Linux release 7.5.1804 (Core)锛�
    		
    	b.璧勬簮瀛樻斁鐩綍
    		mkdir /root/ngx_lua
    		
    	c.瑕佹眰
    		鍚勭缂栬瘧瀹夎鐩稿叧渚濊禆鍜屾姤閿欒 google 瑙e喅锛�
    		
    	d.NGX_LUA 瀹樻枃
    		https://github.com/openresty/lua-nginx-module#installation
    		
    	e.鍑嗗
    		cd /root/ngx_lua
    	
    1.Lua
    	wget http://www.lua.org/ftp/lua-5.3.4.tar.gz
    	tar zxf lua-5.3.4.tar.gz
    	cd lua-5.3.4
    	make linux test
    	cd ..
    	
    2.LuaJIT 2.1
    	wget http://luajit.org/download/LuaJIT-2.1.0-beta3.tar.gz
    	tar zxvf LuaJIT-2.1.0-beta3.tar.gz
    	cd LuaJIT-2.1.0-beta3
    	
    	#鎸囧畾瀹夎鐩綍
    	make PREFIX=/usr/local/luajit2
    	make install PREFIX=/usr/local/luajit2
    	cd ..
    	
    3.NDK
    	wget https://github.com/simplresty/ngx_devel_kit/archive/v0.3.1rc1.tar.gz
    	tar zxvf v0.3.1rc1.tar.gz
    	
    4.LUA_NGX
    	wget https://github.com/openresty/lua-nginx-module/archive/v0.10.13.tar.gz
    	tar zxvf v0.10.13.tar.gz
    	
    5.LUA_RESTY_REDIS
    	wget -O "lua-resty-redis-master.zip" https://codeload.github.com/openresty/lua-resty-redis/zip/master
    	unzip lua-resty-redis-master.zip
    	cd lua-resty-redis-master
    	make install PREFIX=/usr/local/lua-redis
    	cd ..
    	
    5.REDIS
    	wget http://download.redis.io/releases/redis-4.0.9.tar.gz
    	tar zxvf redis-4.0.9.tar.gz
    	cd redis-4.0.9
    	
    	#澶嶅埗閰嶇疆鏂囦欢妯℃澘
    	cp redis.conf /etc/
    	
    	#缂栬瘧瀹夎
    	make PREFIX=/usr/local/redis
    	make install PREFIX=/usr/local/redis
    	
    	#灏濊瘯杩愯锛屽彲浠ヨ€冭檻鎵撳寘涓哄悗鍙版湇鍔℃垨鎵樼缁� supervisor锛屾湰鏂囩暐锛�
    	cd /usr/local/redis/bin
    	./redis-server /etc/redis.conf
    	
    6.Nginx
    	#娣诲姞 NGINX 鐢ㄦ埛
    	useradd -s /sbin/nologin www
    	
    	#涓嬭浇銆佽В鍘嬪苟杩涘叆鐩綍
    	wget http://nginx.org/download/nginx-1.13.12.tar.gz
    	tar zxvf nginx-1.13.12.tar.gz
    	cd nginx-1.13.12
    	
    	# 澧炲姞鐜鍙橀噺
    	export LUAJIT_LIB=/usr/local/luajit2/lib
    	export LUAJIT_INC=/usr/local/luajit2/include/luajit-2.1
    	
    	# 缂栬瘧瀹夎
    	./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_gzip_static_module --with-http_sub_module  --with-ld-opt="-Wl,-rpath,/usr/local/luajit2/lib" --add-dynamic-module=/root/ngx_lua/ngx_devel_kit-0.3.1rc1 --add-dynamic-module=/root/ngx_lua/lua-nginx-module-0.10.13
    	make && make test
    	
    	# 缂栬緫涓婚厤缃枃浠朵娇鍏舵敮鎸� NGX_LUA
    	vim /usr/local/nginx/conf/nginx.conf
    		
    		# 鎸囧畾涓哄叾鍒涘缓鐨勭敤鎴�
    		user www www;
    		
    		# 鎸囧畾杩涚▼鏁板強灏嗚繘绋嬬粦瀹氳嚦 CPU 鏍稿績锛�
    		worker_processes  auto;
    		worker_cpu_affinity auto;
    
    		pid        logs/nginx.pid;
    		
    		# 鎵撳紑鏂囦欢鏁�
    		worker_rlimit_nofile    65535;
    		
    		# 姝ゅ鍔犺浇 LUA 鐩稿叧妯″潡
    		load_module modules/ndk_http_module.so;
    		load_module modules/ngx_http_lua_module.so;
    		
    		events {
    			use epoll;
    			worker_connections  65535;
    			accept_mutex off;
    			multi_accept on;
    		}
    
    
    		http {
    			include       mime.types;
    			default_type  application/octet-stream;
    
    			server_names_hash_bucket_size       128;
    			client_header_buffer_size   64k;
    			large_client_header_buffers 4       32k;
    			client_max_body_size        512m;
    			
    			# lua redis 渚濊禆鍖�
    			lua_package_path "/usr/local/lua-redis/lib/lua/?.lua;;";
    			
    			sendfile  on;
    			keepalive_timeout  60;
    
    			server_tokens       off;
    			log_format access '$remote_addr - $remote_user [$time_local] "$request" '
    							  '$status $body_bytes_sent "$http_referer" '
    							  '"$http_user_agent" "$http_x_forwarded_for"';
    
    			include conf.d/*.conf;
    		}
    	:wq
    	nginx -t && nginx
    

    0脳02 寮€鍙� LUA 鍝嶅簲浣撳強寤虹珛 VHOST

    1.寤虹珛 lua 鑴氭湰瀛樻斁鐩綍
    	mkdir /usr/local/nginx/conf/lua
    	
    2.寮€鍙戠敤浜庡搷搴斿唴瀹圭殑 lua 鑴氭湰
    	vim /usr/local/nginx/conf/lua/content.lua
    		--鑾峰彇璇锋眰鐨� HEADER
    		local headers = ngx.req.get_headers()
    		
    		--渚濇閫氳繃 x_real_ip锛寈_forwarded_for锛宺emote_addr 鑾峰彇瀹㈡埛绔� IP
    		local clientip = headers["X-Real-IP"]
    		if clientip == nil then
    		   clientip = headers["x_forwarded_for"]
    		end
    		if clientip == nil then
    		   clientip = ngx.var.remote_addr
    		end
    		
    		--鎸囧畾鍝嶅簲鍐呭
    		ngx.say("Your Ip Adress is ",clientip,", WelCome!")
    	:wq
    	
    3.鎼缓鐢ㄤ簬娴嬭瘯鐨� VHOST
    	a.鏂板缓閰嶇疆鏂囦欢
    		vim /usr/local/nginx/conf/conf.d/luatest.conf
    			server
    			{
    				#鎸囧畾鐩戝惉绔彛鍙婁富鏈哄悕
    				listen 80;
    				server_name www.knownsec.com;
    				
    				#寤虹珛娴嬭瘯鍦板潃
    				location /lua_test
    				{
    						# 鎸囧畾鍝嶅簲鐨勯粯璁� MIME 绫诲瀷
    						default_type "text/html";
    
    						# 閫氳繃 lua 鍝嶅簲鍐呭
    						content_by_lua_file conf/lua/index.lua;
    				}
    
    				error_log  /home/log/ngx/error.log;
    				access_log  /home/log/ngx/access access;
    			}
    		:wq
    		
    	b.娴嬭瘯骞堕噸杞介厤缃�
    	nginx -t
    	nginx -s reload
    	
    4.娴嬭瘯璁块棶
    	curl --resolve www.knownsec.com:80:192.168.0.196 http://www.knownsec.com/lua_test
    	Your Ip Adress is 192.168.0.196, WelCome!
    

    0脳03 IP 闄愰€熷疄鐜板師鐞�

    1.璇锋眰澶勭悊杩囩▼
    	a.NGINX 鐨勮姹傚鐞嗚繃绋嬩竴鍏卞垝鍒嗕负 11 涓樁娈碉紝鍒嗗埆鏄細post-read銆乻erver-rewrite銆乫ind-config銆乺ewrite銆乸ost-rewrite銆乸reaccess銆乤ccess銆乸ost-access銆乼ry-files銆乧ontent銆乴og.锛堝弬鑰冿細 https://github.com/nginx/nginx/blob/master/src/http/ngx_http_core_module.h 锛�
    	b.鍦� nginx 瀹樻柟鏂囨。(鍙傝€冿細 https://www.nginx.com/resources/wiki/modules/lua/)涓紝鍙鐞嗛樁娈靛潎鏈夌浉搴旂殑 lua 鎸囦护锛涘氨鏈枃鐨勭洰鐨勮€岃█锛岃闂檺閫熸帶鍒跺浜� access 闃舵锛屾墍浠ラ渶瑕佷娇鐢ㄧ殑鎸囦护涓� access_by_lua 锛�
    	c.涓轰簡鏂逛究璋冭瘯鍜岀鐞嗭紝鍙互浣跨敤 access_by_lua_file 鎸囦护鐩存帴鍔犺浇鎸囧畾璺緞涓嬬殑 lua 鏂囦欢鏉ュ access 杩囩▼杩涜澶勭悊锛�
    
    2.鍩轰簬浠ょ墝妗剁畻娉曠殑閫昏緫
    	a.浠ょ墝妗剁畻娉曞彲鎺у埗璇锋眰鐨勬暟閲忥紝骞跺厑璁哥獊鍙戝ぇ閲忚姹傜殑鎯呭喌銆�
    	b.褰撶敤鎴疯姹� Nginx 鏃讹紝鍒ゆ柇璇� location 鏄惁闇€瑕侀檺鍒舵祦閲忥紱
    	c.鑻ラ渶瑕侊紝鍒欐鏌ュ綋鍓� IP 鏄惁宸叉湁浠ょ墝妗讹紝鑻ユ棤鍒欎娇鐢� setex 寰€ redis 涓斁鍏ヤ护鐗屾《锛屽苟鎸囧畾鐨勪护鐗屾暟閲忓強鈥滄《鈥濊繃鏈熸椂闂达紱璁惧畾鍗曚綅鏃堕棿鍐呭厑璁歌闂鏁帮紝姣斿 1 鍒嗛挓鍏佽 10 娆★紝鍒欎护鐗屾暟閲忎负 9(褰撳墠璇锋眰绠椾綔棣栨娑堣€�)锛岃繃鏈熸椂闂� 60s
    	d.鑻ュ凡鏈変护鐗屾《锛屽苟涓斾护鐗屾暟閲忓ぇ浜� 0锛屽垯浣跨敤 decr 浣垮叾鍊煎噺 1(娑堣€椾护鐗�)骞舵斁琛岋紱
    	e.鑻ヤ护鐗屾暟閲忎负 0锛屽垯鎷︽埅锛�
    	
    3.浠g爜瀹炵幇
    	vim /usr/local/lua-redis/lib/lua/LimitRate.lua
    	
    		--鍔犺浇 REDIS 妯″潡
    		local r_md = require "resty.redis"
    		
    		--鑾峰彇褰撳墠璇锋眰鐨� HEADER
    		local headers = ngx.req.get_headers()
    		
    		--鎸囧畾 REDIS 鐨勫湴鍧€鍜岀鍙�
    		local redis_ip = "127.0.0.1"
    		local redis_port = "9600"
    		
    		--寤虹珛 redis 瀹炰緥
    		local redis = r_md:new()
    		
    		--鎸囧畾鍗曚綅鏃堕棿
    		local qtrange = 60
    		
    		--鍏佽璁块棶鐨勬鏁�
    		local qcount = 10
    
    		--灏濊瘯鏍规嵁 HTTP 澶撮亗绾ц幏鍙� IP
    		local clientip = headers["X-Real-IP"]
    		if clientip == nil then
    		   clientip = headers["x_forwarded_for"]
    		end
    		if clientip == nil then
    		   clientip = ngx.var.remote_addr
    		end
    
    		--閲婃斁 redis 杩炴帴鐨勫嚱鏁�
    		local function redis_close(red)
    
    			--閲婃斁杩炴帴锛屼娇鐢� set_keepalive 鎸囦护灏嗗綋鍓嶈繛鎺ユ斁鍏ュ綋鍓嶈繘绋嬬殑杩炴帴姹犱腑寰呯敤锛岄渶瑕佹寚瀹氳繛鎺ユ睜鐨勫ぇ灏忓強鍏朵腑鍚勪釜杩炴帴鐨勭┖闂茶秴鏃舵椂闂达紱
    			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_log(ngx_ERR, "set redis keepalive error : ", err)
    			end
    		end
    		
    		--鎸囧畾鎵€鏈� REDIS 鎿嶄綔鐨勮秴鏃舵椂闂达紝鍏朵腑鍖呭惈浜嗚繛鎺ヨ秴鏃�
    		redis:set_timeout(1000)
    		
    		寤虹珛杩炴帴锛岃嫢寮傚父鍒欓噴鏀捐繛鎺ワ紱
    		local ok, wrong = redis:connect(redis_ip,redis_port)
    		if not ok then
    				redis_close(redis)
    		end
    
    		--寤虹珛闄愰€熺被
    		LimitIpRate = {}
    
    		--闄愰€熸柟娉曪紝浠ょ墝妗堕檺閫熼€昏緫瀹炵幇
    		function LimitIpRate:is_limited()
    		
    				--灏濊瘯鑾峰彇褰撳墠 IP 鐨勪护鐗屾《锛屼护鐗屾《鍛藉悕涓衡€� x.x.x.x|pool 鈥�
    				local res, err = redis:get(clientip.."|pool")
    				if not res then
    						ngx.log(ngx.ERR,"lua error: ",err)
    				end
    
    				--濡傛灉 res 涓嶄负绌哄苟涓旂被鍨嬩负 string锛屽垯浠h〃鑾峰彇鍒颁簡瀵瑰簲鐨勪护鐗屾《
    				if type(res) == "string" then
    				
    						--鍙敤浠ょ墝鏁伴噺涓� 0 鍒欐嫤鎴�
    						if tonumber(res) == 0 then
    								ngx.exit(ngx.HTTP_FORBIDDEN)
    								
    						--鍙嶄箣鏀捐骞惰浠ょ墝鏁伴噺鍑忓皯 1
    						else
    								add,err = redis:decr(clientip.."|pool")
    								if not add then
    										ngx.log(ngx.ERR,"lua error: ",err)
    								end
    						end
    				
    				--濡傛灉 res 涓嶄负绌哄苟涓旂被鍨嬩负 userdata锛屽垯浠h〃 redis 涓病鏈夊搴斾护鐗屾《
    				elseif type(res) == "userdata" then
    						
    						--寰€ redis 涓斁鍏ユ寚瀹氬悕绉般€佽繃鏈熸椂闂淬€佸€肩殑閿€煎
    						ini, err = redis:setex(clientip.."|pool", qtrange, (qcount-1))
    						if not ini then
    								ngx.log(ngx.ERR,"lua error: ",err)
    						end
    				end
    		end
    		
    		--璋冪敤闄愰€熸柟娉�
    		LimitIpRate.is_limited()
    			
    	:wq
    	
    4.灏� LimitRate.lua 闆嗘垚杩� NGINX 閰嶇疆鏂囦欢
    	a.缂栬緫閰嶇疆鏂囦欢锛屽姞鍏ユ寚浠�
    		vim /usr/local/nginx/conf/conf.d/luatest.conf
    			server
    			{
    				#鎸囧畾鐩戝惉绔彛鍙婁富鏈哄悕
    				listen 80;
    				server_name www.knownsec.com;
    				
    				#寤虹珛娴嬭瘯鍦板潃
    				location /lua_test
    				{
    						# 鎸囧畾鍝嶅簲鐨勯粯璁� MIME 绫诲瀷
    						default_type "text/html";
    						
    						# 閫氳繃 lua 瀵� access 杩涜杩囨护
    						access_by_lua_file "conf/lua/LimitRate.lua";
    						
    						# 閫氳繃 lua 杩斿洖鍝嶅簲鍐呭
    						content_by_lua_file conf/lua/index.lua;
    				}
    
    				error_log  /home/log/ngx/error.log;
    				access_log  /home/log/ngx/access access;
    			}
    		:wq
    	b.娴嬭瘯骞堕噸杞介厤缃�
    		nginx -t
    		nginx -s reload
    	
    5.闄愰€熸祴璇�
    	for i in {1..12}; do curl -s --resolve www.knownsec.com:80:192.168.0.196 http://www.knownsec.com/lua_test -o /dev/null -w %{http_code};echo ;done
    	200
    	200
    	200
    	200
    	200
    	200
    	200
    	200
    	200
    	200
    	403
    	403
    

    0脳04 鎬荤粨

    a.鍦ㄩ渶瑕佺殑 location 浣跨敤 ngx_lua 鎸囧畾鍔犺浇 LimitRate.lua 锛屽苟鎸囧畾鍗曚綅鏃堕棿鍜屽崟浣嶆椂闂翠腑鍏佽鐨勮姹傛鏁帮紱鍒欏彲瀹炵幇瀵硅 location 璇锋眰鐨� IP 闄愰€燂紱
    b.鎴鐩墠锛屼粎鏄畝鍗曞湴鎻忚堪浜嗗浣曞疄鐜� IP 闄愰€熸帶鍒讹紝杩橀渶瑕佺粨鍚堟洿澶氱殑涓氬姟鐜鏉ュ紑鍙戜笉鍚岀殑闇€姹傦紝鎵嶈兘閫愭笎鏋勫缓鐩稿鎴愮啛鐨� CC 闃叉姢浣撶郴锛�
    c.鏀婚槻涔嬫牴鏈嵆涓烘敾闃插弻鏂瑰鎴愭湰鐨勬姇鍏ワ紱
    d.鑻ラ渶鎴愮啛瑙e喅鏂规锛屽彲閫夋嫨鎶� D 淇濃€斺€旀敾鍑绘墦涓嶆锛屼笓鎺ラ槻涓嶄綇锛�
    
    3 鍥炲  |  鐩村埌 2018-05-31 12:29:17 +08:00
        1
    AlexaZhou   10 鍒嗛挓鍓�
    VeryNginx 娆㈣繋浜嗚В涓�
        2
    0312birdzhang   8 鍒嗛挓鍓�
    HttpGuard 娆㈣繋浜嗚В涓€涓嬶紙
        3
    xiaoz   7 鍒嗛挓鍓� via Android
    @AlexaZhou 鑰佸摜锛屽睆钄� ip 娈电殑鍔熻兘鍑烘潵娌℃湁锛�
    鍏充簬     FAQ     API     鎴戜滑鐨勬効鏅�     骞垮憡鎶曟斁     楦h阿     2577 浜哄湪绾�   鏈€楂樿褰� 3541    
    鍒涙剰宸ヤ綔鑰呬滑鐨勭ぞ鍖�
    World is powered by solitude
    VERSION: 3.9.8.1 路 15ms 路 UTC 04:36 路 PVG 12:36 路 LAX 21:36 路 JFK 00:36
    鈾� Do have faith in what you're doing.
    娌狪CP澶�16043287鍙�-1