HTTP DDoSおよびその他のHabraの影響から身を守る

HTTP DDoSから保護する簡単な方法は、syn-cookieを有効にしてスカムバッグをブロックすることです。 しかし、5k〜10kのホストを攻撃し、さらに動的IPを使用した場合はどうでしょうか。 ここでは、中間キャッシングを備えたフロントエンド-バックエンドアーキテクチャが役立ちます。 中間キャッシュを使用する理由 私の場合、フロントエンドからのリクエストの急増により、バックエンドがシステムを奪い去っていたためです。



アクションのアルゴリズム:



したがって、複数のサーバーを使用できるため、複数のサーバーのみを含む構成バージョンが考慮されますが、これをすべて1つのサーバーにプッシュする必要はありません=)



お気に入りのWebサーバーのポートを変更する方法は、言う必要はないと思います。すぐにニスの設定に進むことをお勧めします。



パッケージ自体を実際にインストールします。

apt-get update && apt-get install varnish







次に、Cに似た構成ファイル(Ubuntuでは/etc/varnish/default.vcl )を提示します。

backend default {

.host = "1.1.1.1"; #IP backend'

.port = "2080"; #

.first_byte_timeout = 300s; # varnish backend'

}



acl purge {

"localhost"; #

}



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;

}

}









service varnish restart



service varnish restart







これで、frontend'a-lighttpdのインストールと構成を開始できます。

はここから lighttpdを取得することを好みますが、配布リポジトリからダウンロードすることを誰も気にしません( apt-get install lighttpd )。

そして、次の形式になるまで構成を編集します。

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 # 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 #



cache.enable = "enable" #

cache.bases = ("/var/spool/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 ), #

( "host" => "1.2.1.2", "port" => 6081 ), # varnish

( "host" => "1.2.1.3", "port" => 6081 ),

( "host" => "1.2.1.4", "port" => 6081 )

)

)

}

proxy.worked-with-mod-cache = "enable"









最後に、iptablesとシステムの少しの調整:



1つのIPから1秒あたり10接続を許可します。

iptables -I INPUT 1 -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





開いているファイルの数を増やします。

ulimit -n 5000





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








どのように機能しますか? lighttpdはクライアントからリクエストを受信し、特定の条件を満たしている場合(この場合、これは空のユーザーエージェントではなく、クライアントはhabrahabr.ruドメインをリクエストし、これは4番目の同時リクエストではありません)、ニスサーバーの1つにリクエストを送信します。 Varnishは、ユーザーが必要とするコンテンツのキャッシュをチェックし、キャッシュからコンテンツを提供するか、キャッシュにこのコンテンツがない場合や古くなっている場合は、バックエンドにリクエストを送信します。



UPD:カルマをありがとう、「情報セキュリティ」を転送しました



All Articles