12:47 Defend ourselves from http ddos ??and other habraeffektov | |
A simple way to protect against HTTP DDoS - enable syn-cookies and block the bastards. But what to do if attacked by 5k-10k hosts so even with dynamic IP? Here we come to the aid frontend-backend architecture c intermediate caching! Why with an intermediate cache? And because in my case from the barrage of requests from the frontend backend died carrying for a system. So the algorithm of action:
So, like I was in the presence of multiple servers, it will be reviewed version of the configuration is a multi-server, but no one is stopping you all this stuff on one server =) How to change port of your favorite Web server, I think talking is not necessary, propose to move immediately to configure Varnish. Actually install the package: apt-get update & & apt-get install varnish The following is a C-like configuration file (in Ubuntu it / etc / varnish / default.vcl) approximately to the form: backend default { .host = "1.1.1.1"; # IP of our backend .port = "2080"; # port .first_byte_timeout = 300s; # without this timeout varnish did not want to take content from a backend } acl purge { "localhost"; # allow cache cleaning only lokalhosta } sub vcl_recv { if (req.request == "GET" & & req.url ~ "\. (jpg | jpeg | gif | ico) $") { lookup; } if (req.request == "GET" & & req.url ~ "\. (css | js) $") { lookup; } if (req.request == "GET" & & req.url ~ "\. (pdf | xls | vsd | doc | ppt | iso) $") { lookup; } if (req.request == "POST") { pipe; } if (req.request! = "GET" & & req.request! = "HEAD") { if (req.request == "PURGE") { if (! client.ip ~ purge) { error 405 "Not allowed."; } lookup; } pipe; } if (req.http.Expect) { pipe; } if (req.http. If-None-Match) { pass; } if (req.http.Authenticate | | req.http.Authorization) { pass; } lookup; } sub vcl_hit { if (req.request == "PURGE") { set obj.ttl = 0s; error 200 "Purged."; } } sub vcl_miss { if (req.http.If-Modified-Since) { pass; } if (req.request == "PURGE") { error 404 "Not in cache."; } } sub vcl_fetch { if (obj.http.x-accel-redirect ~ ".*") { set req.url = obj.http.x-accel-redirect; restart; } } Restart the varnish: service varnish restart Now you are ready to install and configure our frontend - lighttpd. I prefer to take lighttpd here, but nobody prevents you download it from the repositories distribution (apt-get install lighttpd). And right configuration so long until it will look as follows: server.modules = ( "mod_cache", "mod_proxy", "mod_access" , "mod_evasive" ) server.network-backend = "writev" server.max-keep-alive-requests = 4 server.max-keep -alive-idle = 4 server.max-read-idle = 10 server.max-write-idle = 30 server.event-handler = "linux-sysepoll" server.stat-cache-engine = "disable" server.protocol-http11 = "enable" server.max-worker = 2 # If you have one processor, or you're running on one server then is set to 1 server.max-fds = 10000 server.max-connections = 5000 server.port = 80 server.document-root = "/ var / www" server.errorlog = "/ var / log / lighttpd / error.log" server.pid-file = "/ var / run / lighttpd.pid" server.username = "www -data " server.groupname =" www-data " etag.use-inode =" enable " etag.use-mtime =" enable " etag.use- size = "enable" server.dir-listing = "disable" evasive.max-conns-per-ip = 3 # Allow only three concurrent connections cache.enable = "enable" # Includes side caching lighty cache.bases = ("/ var / spool / cache") # Here, we wake up to keep the cache cache.max-memory-size = 40960 # 40Gb cache . lru-remove-count = 512 cache.support-queries = "enable" cache.dynamic-mode = "enable" cache.refresh-pattern = ( " \. (? i) (js | css | xml | po) $ "=>" 240 ", # update js / css / xml every 4 hours and on refresh requests " \. (? i) ( htm | html | shtml) $ "=>" 30 use-memory ", # update html / htm / shtml every 30 minutes and on refresh requests " \. (? i) (jpg | bmp | jpeg | gif | png) $ "=>" 2880 ", # update graphics files every 2 days " \. (? i) (rar | zip | wmv | iso | avi | mp3 | ape | rm | mpeg | mpg | wma | asf | rmvb | flv | mkv | ogg | ogm | swf | flac) $ "=>" 0 fetchall-for-range-request ", # cache media file forever ". (? i ) php $ "=>" 5 ", # update php request every 5 minutes ". "=>" 30 use-memory "# ) mimetype.use-xattr = "enable" include_shell "/ usr / share / lighttpd / create-mime.assign.pl" # Bad users go to hell $ HTTP ["useragent"] == "" { url.access-deny = ("") } $ HTTP ["host"] = ~ "(^ | \.) habrahabr \. ru $" { proxy.balance = "round-robin" proxy.server = ("/" => ( ("host" => "1.2.1.1", "port" = > 6081) # Sends a request ("host" => "1.2.1.2", "port" => 6081), # servers varnish ("host" => "1.2 .1.3 "," port "=> 6081), (" host "=>" 1.2.1.4 "," port "=> 6081) ) ) } proxy.worked-with-mod-cache = "enable" And finally, iptables, and a little tuning of the system: Allow 10 connections per second with a single IP: iptables 1-I INPUT-p tcp-m hashlimit - hashlimit-upto 10/sec - hashlimit-burst 10 - hashlimit-mode srcip - hashlimit-name HTTPD_DOS-m tcp - dport 80-m state - state NEW -j ACCEPT Increase the number of open files: ulimit-n 5000 Bun to sysctl.conf: vm.swappiness = 10 vm.vfs_cache_pressure = 10000 vm.dirty_ratio = 1 vm.dirty_background_ratio = 1 vm.dirty_writeback_centisecs = 250 vm.dirty_expire_centisecs = 3000 kernel.panic = 10 net.ipv4 . tcp_fin_timeout = 15 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_sack = 1 net.core.rmem_max = 16777216 net.core.rmem_default = 16777216 net.core.netdev_max_backlog = 262144 net.core.somaxconn = 262144 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_orphans = 262144 net.ipv4. tcp_max_syn_backlog = 262144 net.ipv4.tcp_synack_retries = 2 net.ipv4.tcp_syn_retries = 2 net.ipv4.netfilter.ip_conntrack_max = 1048576 net.nf_conntrack_max = 1048576 net.ipv4.icmp_echo_ignore_all = 1 net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 15 net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 15 net.ipv4.ip_local_port_range = 10000 65000 How does it work? lighttpd receives a request from the client and if it meets certain criteria (in our case this is not an empty User-agent, the client requests the domain habrahabr.ru and it's not the fourth synchronous request) sends a request to one of the servers varnish. Varnish checks its cache for the presence of the desired user-generated content gives it either from the cache or forwards the request to the backend, if the cache of the content is missing or outdated. UPD: Thank you for your karma, suffered "Information security» | |
|
Total comments: 0 | |