{"id":215235,"date":"2014-03-10T14:35:09","date_gmt":"2014-03-10T10:35:09","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=215235"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=215235","title":{"rendered":"<span class=\"post_title\">LUA \u0432 nginx: \u0441\u043b\u0435\u0433\u043a\u0430 \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 firewall<\/span>"},"content":{"rendered":"<div class=\"content html_format\">   \t<img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/dec\/a7d\/146\/deca7d146accb628876bb6d464bf66d1.png\" align=\"right\"\/><br \/>  \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0441\u0442 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <a href=\"http:\/\/habrahabr.ru\/post\/215237\/\">\u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f lua \u0432 nginx<\/a>.<\/p>\n<p>  \u0422\u0430\u043c \u043e\u0431\u0441\u0443\u0436\u0434\u0430\u043b\u043e\u0441\u044c \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438, \u0430 \u0442\u0443\u0442 lua \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u044d\u0442\u0430\u043a\u043e\u0433\u043e \u0444\u0430\u0435\u0440\u0432\u043e\u043b\u0430 \u043d\u0430 nginx-\u0431\u0430\u043b\u0430\u043d\u0441\u0435\u0440\u0435. <a href=\"http:\/\/habrahabr.ru\/company\/2gis\/blog\/199504\/\">\u041d\u0435\u0447\u0442\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0435 \u0431\u044b\u043b\u043e \u0443 2GIS<\/a>. \u0423 \u043d\u0430\u0441 \u0441\u0432\u043e\u0439 \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434 \ud83d\ude42 \u0412 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u043a\u0443 \u0438 \u0441\u0442\u0430\u0442\u0438\u043a\u0443, \u0441\u0442\u0430\u0440\u0430\u0435\u043c\u0441\u044f \u0443\u0447\u0435\u0441\u0442\u044c NAT \u0438 \u0431\u0435\u043b\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a. \u0418, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0435\u0449\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438, \u0447\u0442\u043e \u043d\u0435 \u0432\u044b\u0439\u0434\u0435\u0442 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439.<br \/>  \u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0441\u0435\u0439\u0447\u0430\u0441 \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e \u0438 \u043d\u0435\u043d\u0430\u043f\u0440\u044f\u0436\u043d\u043e (\u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435 \u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 cpu) \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 1200 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432\/\u0441\u0435\u043a. \u041d\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u044b \u043d\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u043e\u0441\u044c. \u041f\u043e\u0436\u0430\u043b\u0443\u0439, \u043a \u0441\u0447\u0430\u0441\u0442\u044c\u044e \ud83d\ude42<br \/>  <a name=\"habracut\"><\/a><\/p>\n<p>  \u0425\u043e\u0447\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0441\u0440\u0430\u0437\u0443 \u043f\u043e \u043f\u043e\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044e, \u0430 \u043d\u0435 \u043f\u043e \u0444\u0430\u043a\u0442\u0443 \u0441\u0442\u0440\u043e\u0447\u043a\u0438 \u0432 access_log (\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0435\u0449\u0435 \u043d\u0435\u0431\u043e\u0441\u044c \u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d \u0434\u043b\u044f \u0442\u043e\u0439 \u0436\u0435 \u0441\u0442\u0430\u0442\u0438\u043a\u0438). \u041d\u0435 \u0432\u043e\u043f\u0440\u043e\u0441, \u0432\u0435\u0448\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e \u043d\u0430 \u0432\u0435\u0441\u044c http:  <\/p>\n<pre><code class=\"nginx\">http {     include lua\/req.conf; }  # \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 lua\/req.conf  # \u043f\u0430\u043c\u044f\u0442\u044c \u043f\u043e\u0434 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0441\u0447\u0435\u0442\u0447\u0438\u043a\u043e\u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 (\u043d\u0430\u0434\u043e \u043c\u043d\u043e\u0433\u043e, \u0445\u043e\u0442\u044f \u0432\u044b\u0442\u0435\u0441\u043d\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u0440\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u043f\u043e LRU \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e) lua_shared_dict req_limit 1024m; # \u043f\u0430\u043c\u044f\u0442\u044c \u043f\u043e\u0434 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0437\u0430\u0431\u0430\u043d\u0435\u043d\u043d\u044b\u0445 (\u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439, \u043d\u043e \u0432\u044b\u0442\u0435\u0441\u043d\u0435\u043d\u0438\u0435 \u043a\u0440\u0430\u0439\u043d\u0435 \u043d\u0435\u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e) lua_shared_dict ban_list 128m;  # \u0431\u0435\u043b\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a. \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f, \u0437\u0430\u0449\u0438\u0442\u043d\u0430\u044f \u043a\u0443\u043a\u0430 \u043d\u0435 \u0441\u0442\u0430\u0432\u0438\u0442\u0441\u044f geo $lua_req_whitelist {     default          0;     12.34.56.78\/24   1; }  # \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 init_by_lua '     -- \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u0430\u044f \u0441\u043e\u043b\u044c \u0434\u043b\u044f \u0437\u0430\u0449\u0438\u0442\u043d\u043e\u0439 \u043a\u0443\u043a\u0438     lua_req_priv_key    = &quot;secretpassphrase&quot;     -- \u0438\u043c\u044f \u0437\u0430\u0449\u0438\u0442\u043d\u043e\u0439 \u043a\u0443\u043a\u0438     lua_req_cookie_name = &quot;reqcookiename&quot;     -- \u043f\u0443\u0442\u044c \u0434\u043e \u0444\u0430\u0439\u043b\u0430 \u043b\u043e\u0433\u0430 \u0437\u0430\u0431\u0430\u043d\u0435\u043d\u043d\u044b\u0445     lua_req_ban_log     = &quot;\/path\/to\/log\/file&quot;      -- \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 \u043b\u0438\u043c\u0438\u0442\u044b \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u044b (\u0432 \u043c\u0438\u043d) -- \u0447\u0438\u0441\u043b\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430     lua_req_d_one = 42      -- \u0434\u0438\u043d\u0430\u043c\u0438\u043a\u0430 \u043d\u0430 \u043e\u0434\u0438\u043d URI     lua_req_d_mul = 84      -- \u0434\u0438\u043d\u0430\u043c\u0438\u043a\u0430 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 URI     lua_req_s_one = 100     -- \u0441\u0442\u0430\u0442\u0438\u043a\u0430 \u043d\u0430 \u043e\u0434\u0438\u043d URI     lua_req_s_mul = 200     -- \u0441\u0442\u0430\u0442\u0438\u043a\u0430 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 URI      lua_req_d_ip  = 200     -- \u0434\u0438\u043d\u0430\u043c\u0438\u043a\u0430 \u0441 \u043e\u0434\u043d\u043e\u0433\u043e IP     lua_req_s_ip  = 400     -- \u0441\u0442\u0430\u0442\u0438\u043a\u0430 \u0441 \u043e\u0434\u043d\u043e\u0433\u043e IP      -- \u0431\u0430\u043d \u043d\u0430 10 \u043c\u0438\u043d\u0443\u0442     lua_req_ban_ttl = 600      -- \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u043e\u0435     math.randomseed(math.floor(ngx.now()*1000)) ';  # \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0432 access \u0441\u0442\u0430\u0434\u0438\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 access_by_lua_file \/path\/to\/nginx\/lua\/req.lua; <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0432 nginx, \u043f\u0440\u043e\u0439\u0434\u0443\u0442 \u0447\u0435\u0440\u0435\u0437 \u043d\u0430\u0448 \u0441\u043a\u0440\u0438\u043f\u0442 req.lua.<br \/>  \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0434\u0432\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b req_limit \u0438 ban_list \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u0441\u043f\u0438\u0441\u043a\u0430 \u0443\u0436\u0435 \u0437\u0430\u0431\u0430\u043d\u0435\u043d\u043d\u044b\u0445 \u0441\u043e\u043e\u0442\u0432\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e (\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043d\u0438\u0436\u0435).<br \/>  \u0410 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 whitelist \u043f\u043e IP \u0432\u043c\u0435\u0441\u0442\u043e \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u043c\u043e\u0434\u0443\u043b\u044c geo nginx, \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 lua_req_whitelist, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:  <\/p>\n<pre><code class=\"lua\">if ngx.var.lua_req_whitelist ~= '1' then     -- IP \u043d\u0435 \u0438\u0437 \u0431\u0435\u043b\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 end <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u0442\u0430\u0442\u0438\u043a\u0430\/\u0434\u0438\u043d\u0430\u043c\u0438\u043a\u0430 (\u0437\u0430\u043f\u0440\u043e\u0441 \u0437\u0430 \u0444\u0430\u0439\u043b\u043e\u043c \u043d\u0430 \u0434\u0438\u0441\u043a\u0435\/backend \u0441\u0435\u0440\u0432\u0435\u0440\u0443) \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u0443\u044e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043f\u043e \u0438\u043c\u0435\u043d\u0438 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 (\u0442\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u043f\u043e\u0434\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044f\u0441\u044c \u043f\u043e\u0434 \u0441\u0432\u043e\u044e \u0431\u0438\u0437\u043d\u0435\u0441 \u043b\u043e\u0433\u0438\u043a\u0443):  <\/p>\n<pre><code class=\"lua\">function string.endswith(haystack, needle)     return (needle == '') or (needle == string.sub(haystack, -string.len(needle))) end  local function path_is_static(path)     local exts = {'js', 'css', 'png', 'jpg', 'jpeg', 'gif', 'xml', 'ico', 'swf'}      path = path:lower()      for _,ext in ipairs(exts) do         if path:endswith(ext) then             return true         end     end     return false end  local uri_path = ngx.var.request_uri if ngx.var.is_args == '?' then     uri_path = uri_path:gsub('^([^?]+)\\\\?.*$', '%1') end local is_static = path_is_static(uri_path) <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u0445\u043e\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 NAT, \u043a\u0440\u043e\u043c\u0435 IP \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u0442\u0430\u043a \u0436\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u0445 UserAgent \u0438 \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043f\u0435\u0446 \u043a\u0443\u043a\u0430. \u0412\u0441\u0435 \u0442\u0440\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0432 \u0446\u0435\u043b\u043e\u043c \u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0415\u0441\u043b\u0438 \u043d\u0435\u043a\u0438\u0439 \u0437\u043b\u043e\u0434\u0435\u0439 \u0434\u043e\u043b\u0431\u0438\u0442 \u0441\u0435\u0440\u0432\u0435\u0440, \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u0443\u044e \u043a\u0443\u043a\u0443, \u0442\u043e \u0432 \u0445\u0443\u0434\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0431\u0430\u043d\u0435\u043d \u0435\u0433\u043e IP\/\u043f\u043e\u0434\u0441\u0435\u0442\u044c. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0442\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0441 \u044d\u0442\u043e\u0439 \u043f\u043e\u0434\u0441\u0435\u0442\u0438, \u043a\u0442\u043e \u0443\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0440\u0430\u043d\u0435\u0435 \u043a\u0443\u043a\u0443, \u0431\u0443\u0434\u0443\u0442 \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435 (\u043a\u0440\u043e\u043c\u0435 \u0441\u043b\u0443\u0447\u0430\u044f \u0431\u0430\u043d\u0430 \u043f\u043e IP). \u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0435 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e\u0435, \u043d\u043e \u0432\u0441\u0435 \u0436\u0435 \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u043e\u043b\u0441\u0442\u0440\u0430\u043d\u044b\/\u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0437\u0430 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<br \/>  \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043a\u0443\u043a\u0438:  <\/p>\n<pre><code class=\"lua\">local function gen_cookie_rand()     return tostring(math.random(2147483647)) end  local function gen_cookie(prefix, rnd)     return ngx.encode_base64(         -- \u0434\u043b\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0434\u0432\u0443\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u0441 \u043e\u0434\u043d\u043e\u0433\u043e IP \u0438 \u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c\u0438 UserAgent, \u0432\u043c\u0435\u0448\u0438\u0432\u0430\u0435\u043c \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e         ngx.sha1_bin(ngx.today() .. prefix .. lua_req_priv_key .. rnd)     ) end  local uri = ngx.var.request_uri -- \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0439 URI local host = ngx.var.http_host -- \u043a \u043a\u0430\u043a\u043e\u043c\u0443 \u0434\u043e\u043c\u0435\u043d\u0443 \u043f\u0440\u0438\u0448\u0435\u043b \u0437\u0430\u043f\u0440\u043e\u0441 (\u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 nginx \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u043e\u043c\u0435\u043d\u043e\u0432) local ip = ngx.var.remote_addr local user_agent = ngx.var.http_user_agent or '' if user_agent:len() &gt; 0 then     user_agent = ngx.encode_base64(ngx.sha1_bin(user_agent)) end local key_prefix = ip .. ':' .. user_agent  -- \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0439 \u043a\u0443\u043a\u0438 local user_cookie = ngx.unescape_uri(ngx.var['cookie_' .. lua_req_cookie_name]) or '' local rnd = gen_cookie_rand()  local p = user_cookie:find('_') if p then     rnd = user_cookie:sub(p+1)     user_cookie = user_cookie:sub(1, p-1) end  local control_cookie = gen_cookie(key_prefix, rnd)  if user_cookie ~= control_cookie then     user_cookie = ''     rnd = gen_cookie_rand()     control_cookie = gen_cookie(key_prefix, rnd) end  key_prefix = key_prefix .. ':' .. user_cookie ngx.header['Set-Cookie'] = string.format('%s=%s; path=\/; expires=%s',     lua_req_cookie_name,     ngx.escape_uri(control_cookie .. '_' .. rnd),     ngx.cookie_time(ngx.time()+24*3600) ) <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0432 key_prefix \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0447\u0435\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043c\u044b \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c. \u0415\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u0443\u0436\u0435 \u0437\u0430\u0431\u0430\u043d\u0435\u043d, \u0442\u043e \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043d\u0435 \u043d\u0443\u0436\u043d\u0430:  <\/p>\n<pre><code class=\"lua\">local ban_key = key_prefix..':ban' if ban_list:get(ban_key) or ban_list:get(ip..':ban') then -- \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043a\u043b\u044e\u0447\u0430 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0431\u0430\u043d\u0430 \u0432\u043e\u043e\u0431\u0449\u0435 \u0432 \u0446\u0435\u043b\u043e\u043c \u043f\u043e IP     return ngx.exit(ngx.HTTP_FORBIDDEN) end <\/code><\/pre>\n<p>  \u041a\u043b\u044e\u0447 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438, \u0431\u0430\u043d \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043b\u0438, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u043d\u0435 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 \u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043a\u0430\u043a\u043e\u0439 \u0438\u0437 \u043b\u0438\u043c\u0438\u0442\u043e\u0432:  <\/p>\n<pre><code class=\"lua\">-- \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0431\u043e\u0438\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432: \u043d\u0430 \u043e\u0434\u0438\u043d URI \u0438 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 URI local limits = {     [false] = {         [false] = lua_req_d_mul,  -- \u0434\u0438\u043d\u0430\u043c\u0438\u043a\u0430 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 URI         [true]  = lua_req_d_one,  -- \u0434\u0438\u043d\u0430\u043c\u0438\u043a\u0430 \u043d\u0430 \u043e\u0434\u0438\u043d URI     },     [true] = {         [false] = lua_req_s_mul, -- \u0441\u0442\u0430\u0442\u0438\u043a\u0430 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 URI         [true]  = lua_req_s_one,  -- \u0441\u0442\u0430\u0442\u0438\u043a\u0430 \u043d\u0430 \u043e\u0434\u0438\u043d URI     } }  for _,one_path in ipairs({true, false}) do     local limit = limits[is_static][one_path]     local key = {key_prefix}      -- \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u0438\u043a\u0438 \u0438 \u0434\u0438\u043d\u0430\u043c\u0438\u043a\u0438 \u0432 \u0438\u043c\u0435\u043d\u0438 \u043a\u043b\u044e\u0447\u0430     if is_static then         table.insert(key, 'S')     else         table.insert(key, 'D')     end      -- \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u0438 \u0442\u043e\u043c\u0443 \u0436\u0435 \u043f\u0443\u0442\u0438 (\u0434\u043b\u044f \u0432\u0441\u044f\u043a\u0438\u0445 API \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u043f\u043e\u0434\u043e\u0439\u0442\u0438)     if one_path then         table.insert(key, host..uri)     end      -- \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043b\u044e\u0447 \u0432\u0438\u0434\u0430 &quot;12.34.56.78:useragentsha1base64:cookiesha1base64:S:site.com\/path\/to\/file&quot;     key = table.concat(key, ':')      local exaust = check_limit_exaust(key, limit, ban_ttl)     if exaust then         return ngx.exit(ngx.HTTP_FORBIDDEN)     end end <\/code><\/pre>\n<p>  \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c 4 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u0441\u0447\u0435\u0442\u0447\u0438\u043a\u043e\u0432: \u0441\u0442\u0430\u0442\u0438\u043a\u0430\/\u0434\u0438\u043d\u0430\u043c\u0438\u043a\u0430, \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u043f\u0443\u0442\u0438\/\u043f\u043e \u0440\u0430\u0437\u043d\u044b\u043c. \u041d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0432 check_limit_exaust():  <\/p>\n<pre><code class=\"lua\">local function check_limit_exaust(key, limit, cnt_ttl)     local key_ts = key..':ts'      local cnt, _ = req_limit:incr(key, 1)      -- \u0435\u0441\u043b\u0438 \u043a\u043b\u044e\u0447\u0430 \u043d\u0435\u0442, \u0442\u043e \u044d\u0442\u043e \u043f\u0435\u0440\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441     -- \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0447\u0435\u0442\u0447\u0438\u043a \u0438 \u043e\u0442\u043c\u0435\u0442\u043a\u0443 \u0441 \u0442\u0435\u043a\u0443\u0449\u0438\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c     if cnt == nil then         if req_limit:add(key, 1, cnt_ttl) then             req_limit:set(key_ts, ngx.now(), cnt_ttl)         end         return false     end      -- \u0435\u0441\u043b\u0438 \u043d\u0435 \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u043b\u0438 \u043b\u0438\u043c\u0438\u0442 (\u043f\u043e\u043a\u0430 \u0434\u0430\u0436\u0435 \u0431\u0435\u0437 \u0443\u0447\u0435\u0442\u0430 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u0432)     if cnt &lt;= limit then         return false     end      -- \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043f\u0440\u0435\u0432\u044b\u0448\u0435\u043d\u0438\u0435 \u043b\u0438\u043c\u0438\u0442\u0430 (\u0431\u0435\u0437 \u0443\u0447\u0435\u0442\u0430 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u0432),     --   \u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u043e\u0442\u043c\u0435\u0442\u043a\u0443 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043b\u0438\u043c\u0438\u0442 \u0443\u0436\u0435 \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430      local key_lock = key..':lock'     local key_lock_ttl = 0.5     local ts      local try_until = ngx.now() + key_lock_ttl     local locked      while true do         locked = req_limit:add(key_lock, 1, key_lock_ttl)         cnt = req_limit:get(key)         ts = req_limit:get(key_ts)         if locked or (try_until &lt; ngx.now()) then             break         end         ngx.sleep(0.01)     end      -- \u0435\u0441\u043b\u0438 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043b\u043e\u043a \u043d\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 - \u043a\u0440\u0438\u043a\u0438, \u043f\u0430\u043d\u0438\u043a\u0430, \u0437\u0430\u043f\u0440\u0435\u0449\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441.     -- \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0439 IP \u0432 blacklist     -- \u0443 \u0432\u0430\u0441 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430     if (not locked) and ((not cnt) or (not ts)) then         return true, 'lock_failed'     end      -- \u0437\u0430 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 (\u0432 \u0441\u0435\u043a) \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d \u0441\u0447\u0435\u0442\u0447\u0438\u043a     local ts_diff = math.max(0.001, ngx.now() - ts)     -- \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0447\u0435\u0442\u0447\u0438\u043a\u0430 \u043d\u0430 \u0441\u0435\u043a\u0443\u043d\u0434\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b     local cnt_norm = math.floor(cnt \/ ts_diff)      -- \u0435\u0441\u043b\u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0435 \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u043b\u043e \u043b\u0438\u043c\u0438\u0442     if cnt_norm &lt;= limit then         -- \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u043a\u0430 ts \u0438 cnt (\u0435\u0441\u043b\u0438 \u0447\u0442\u043e \u0432 \u044d\u0442\u0438\u0445 set'\u0430\u0445 \u043f\u043e\u043b\u043e\u043c\u0430\u0435\u0442\u0441\u044f - \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0442\u043e\u043c \u0435\u0449\u0435 \u0440\u0430\u0437 \u043f\u043e\u043f\u0430\u0434\u0435\u043c \u0432 \u044d\u0442\u0443 \u0432\u0435\u0442\u043a\u0443)         req_limit:set(key, cnt_norm, cnt_ttl)         req_limit:set(key_ts, ngx.now() - 1, cnt_ttl)          -- \u043b\u043e\u043a \u0441\u043d\u0438\u043c\u0430\u0435\u043c; \u0432 blacklist \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c; \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u043c         if locked then             req_limit:delete(key_lock)         end         return false     end      -- \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u043b\u0438 \u043b\u0438\u043c\u0438\u0442. \u0431\u0430\u043d\u0438\u043c, \u0437\u0430\u043f\u0440\u043e\u0441 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u043c, \u043f\u0438\u0448\u0435\u043c \u0432 \u043b\u043e\u0433     req_limit:delete(key)     req_limit:delete(key_ts)      if locked then         req_limit:delete(key_lock)     end      return true, cnt_norm end <\/code><\/pre>\n<p>  \u041a\u0440\u043e\u043c\u0435 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0431\u0430\u043d\u0430 \u043d\u0430 lua_req_ban_ttl \u0441\u0435\u043a\u0443\u043d\u0434, \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435, \u0430 \u0437\u0430\u043e\u0434\u043d\u043e \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0442\u044c \u043b\u043e\u0433\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043f\u0440\u043e\u0431\u0440\u043e\u0441 \u0437\u0430\u0431\u0430\u043d\u0435\u043d\u043d\u044b\u0445 \u043f\u043e IP \u0432 iptables\/\u0430\u043d\u0430\u043b\u043e\u0433\u0438. \u042d\u0442\u043e \u0443\u0436\u0435 \u0432\u043d\u0435 \u0442\u0435\u043c\u044b \u043f\u043e\u0441\u0442\u0430.<\/p>\n<p>  \u0412\u0441\u0435 \u044d\u0442\u043e, \u0441\u0430\u043c\u043e \u0441\u043e\u0431\u043e\u0439, \u043b\u0438\u0448\u044c \u043f\u0440\u0438\u043c\u0435\u0440, \u0430 \u043d\u0435 \u0441\u0435\u0440\u0435\u0431\u0440\u044f\u043d\u043d\u0430\u044f \u043f\u0443\u043b\u044f-\u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442\u0430. \u0422\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u0447\u0438\u0441\u043b\u0430 \u043b\u0438\u043c\u0438\u0442\u043e\u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u0441 \u043f\u043e\u0442\u043e\u043b\u043a\u0430.<\/p>\n<p>  <i>\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432 \u0448\u0430\u043f\u043a\u0435 \u0432\u0437\u044f\u0442\u043e <a href=\"http:\/\/kaspersky.proguide.vn\/kinh-nghiem-thu-thuat\/tu-bao-ve-khi-dung-wi-fi-cong-cong\/\">\u043e\u0442\u0441\u044e\u0434\u0430<\/a>.<\/i>    \t<\/p>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/215235\/\"> http:\/\/habrahabr.ru\/post\/215235\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\">   \t<img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/dec\/a7d\/146\/deca7d146accb628876bb6d464bf66d1.png\" align=\"right\"\/><br \/>  \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0441\u0442 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <a href=\"http:\/\/habrahabr.ru\/post\/215237\/\">\u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f lua \u0432 nginx<\/a>.<\/p>\n<p>  \u0422\u0430\u043c \u043e\u0431\u0441\u0443\u0436\u0434\u0430\u043b\u043e\u0441\u044c \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438, \u0430 \u0442\u0443\u0442 lua \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u044d\u0442\u0430\u043a\u043e\u0433\u043e \u0444\u0430\u0435\u0440\u0432\u043e\u043b\u0430 \u043d\u0430 nginx-\u0431\u0430\u043b\u0430\u043d\u0441\u0435\u0440\u0435. <a href=\"http:\/\/habrahabr.ru\/company\/2gis\/blog\/199504\/\">\u041d\u0435\u0447\u0442\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0435 \u0431\u044b\u043b\u043e \u0443 2GIS<\/a>. \u0423 \u043d\u0430\u0441 \u0441\u0432\u043e\u0439 \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434 \ud83d\ude42 \u0412 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u043a\u0443 \u0438 \u0441\u0442\u0430\u0442\u0438\u043a\u0443, \u0441\u0442\u0430\u0440\u0430\u0435\u043c\u0441\u044f \u0443\u0447\u0435\u0441\u0442\u044c NAT \u0438 \u0431\u0435\u043b\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a. \u0418, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0435\u0449\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438, \u0447\u0442\u043e \u043d\u0435 \u0432\u044b\u0439\u0434\u0435\u0442 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439.<br \/>  \u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0441\u0435\u0439\u0447\u0430\u0441 \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e \u0438 \u043d\u0435\u043d\u0430\u043f\u0440\u044f\u0436\u043d\u043e (\u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435 \u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 cpu) \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 1200 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432\/\u0441\u0435\u043a. \u041d\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u044b \u043d\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u043e\u0441\u044c. \u041f\u043e\u0436\u0430\u043b\u0443\u0439, \u043a \u0441\u0447\u0430\u0441\u0442\u044c\u044e \ud83d\ude42  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-215235","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/215235","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=215235"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/215235\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=215235"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=215235"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=215235"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}