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 restartservice 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:カルマをありがとう、「情報セキュリティ」を転送しました

Source: https://habr.com/ru/post/J68301/


All Articles