სისადმინის ბლოგი

Icon

Übermensch

Network security part.1 – syn* attack

პოსტის მიზანია დავიცვათ საკუთარი ვებ სერვერი syn flood პირდაპირი შეტევებისგან, (iptables-ის  დონეზე) და რამოდენიმე რჩევა syn spoofing ის დროს ასეთი შეტევების ძირითადი მიზანია Dos -ის მიღწევა.

ეს შეტევა დაფუძვნებულია TCP კავშირის დამყარების პრინციპზე, როდესაც თქვენ შედიხართ ბროუზერით ვებ-გვერდზე – თქვენ აგზავნით SYN (synchronize) პაკეტს სერვერზე, სერვერი კი ამ დროს იმყოფება Listening რეჟიმში და უსმენს კონკრეტულ პორტს, როდესაც სერვერი მიიღებს თქვენს SYN პაკეტს ის პასუხობს SYN-ACK (synchronize acknowledged) პაკეტით და გიგზავნით ისევ თქვენ, რაც ნიშნავს, რომ მოთხოვნა სინქრონიზაციაზე მიღებულია, ამის შემდეგ თქვენ აგზავნით პროცედურის დამასრულებელ პაკეტს – ACK (acknowledge) სერვერთან და ნანატრი TCP კავშირი დგება თქვენს და დაშორებულ სერვერს შორის, სინამდვილეში ეს ისე სწრაფად ხდება, რომ თქვენ გაანალიზებას ვერ ასწრებთ გვერდი ისე იტვირთება თქვენს ბოუზერში. სწორედ ამას ეწოდება “TCP 3-Way Handshake” კავშირი ან ქართულად “სამგზის კავშირი” :), ამ სამგიზს კავშირიდან თითოეული პროცესი ექვემდებარება გარკვეულ კრიტრერიუმებს მაგ: განსაზღვრულია კავშირის ვადა (time-out).

1. client——-syn——->>web server
2. client<<—syn-ack—–web server
3. client——-syn——>> web server

SYN შეტევებში არსებობს  2 ტიპის შეტევა syn-flooding, როდესაც სერვერს ვალოდინებთ პასუხის გაცემაზე და syn-spoofing ამ დროს პასუხის მიღებისას “ვემალებით” სერვერს. ანუ ვცვლით სორს მისამართს და აგონიაში მყოფი სერვერი აგზავნის პაკეტებს არარსებულ იპ მისამართებზე.

I syn-flooding (direct attack)

განვიხილოთ ჩვეულებრივი syn-flood-ის სცენარი. (შედარებით მარტივი განსახორციელებელია)
წარმოიდგინეთ რა მოხდება თუ გავუგზავნით სერვერს  SYN პაკეტს შემდეგ სერევრი გამოგიგზავნით  SYN-ACK -ს და თქვენ აღარ გაუგზავნით დამასრულებელ ACK, ამ დროს ამოქმედდება პარამეტრი fin_timeout რომელიც დაელოდება მინიჭებულ მიშვნელობას მაგ 60 და 60 წამის გასვლის შემდეგ დახურავს ნახევრად ღია კავშირს. აქ კიდევ ერთი ფაქტორია დასაზუსტებელი, კავშირის დამყარების დროს ხდება ამ კავშირის მიერ TCP ბუფერის მეხსიერების რაღაც გარკველული ნაწილის დაკავება. ეხლა უფრო კონკრეტულად შეგვიძლია წარმოვიდგინოთ თუ რა მოხდება როდესაც უამრავ ასეთ ნახევრად-ღია კავშირებს დავამყარებთ? საბოლოოდ გადაივსება backlog, somaxconn, max_syn_backlog  კერნელის პარამეტრები და სერვერი ახალი კავშირის მოთხოვნებს (connection requests) ან რიგში ჩააყენებს (TIME_WAIT) ან სერთოდ ვერ უპასუხებს (Connect TIME_OUT() ).
მაგ: შემტევი ჯუმბერი და მისი მეგობრები აგზავნიან სერვერთან ძალიან დიდი რაოდენობით SYN კავშირებს სანამ არ გადაივსება კერნელის პარამეტრი backlog -ი (ეს პარამეტრი უზრუნველყოფს “ნახევრად-ღია” half-opened კავშირების რიგში ჩაყენებას), როდესაც backlog სავსეა (მას მეხსიერების რაღაც ზომა აქვს გამოყოფილი და ეს პარამეტრი “ტუნინგს” ექვემდებარება და ამას ქვევით განვიხილავთ ) ის სერვერი ვეღარ უმკლავდება ახალ კავშირებს თუნდაც ნორმალურს, შემდეგ უკვე გააჩნია სერვერის კონფიგურაციას, შესაძლებელია კერნელის ქრეშიც, httpd პროცესის გარდაცვალება, ან საიტის დროებით გაჩერება სანამ ნახევრად-ღია კავშირებს ვადა არ გაუვა.

II syn-spoofing

როგორც ზემოთ ავღნიშნეთ ამ დროს სერვერს ეგზავნება syn პაკეტი არარსებული იპ მისამართიდან და სერვერიც ცდილობას უპასუხოს ამ მისამართს, მაგრამ მათ შორის ეს ინტიმური კავშირი არასდროს დამყარდება. ასე რომ კიდევ გარკვეული დროის მონაკვეთი და გარკვეული რესურსის დაკავებით წინ მიიწევს შემტევი ჯუმბერი სანამ სერვერზე არ მოხდება რესურსების გადავსება და შემდეგ მისი თანმხლები პროცესები. ეს არის ყველაზე პრობლემური შეტევა და საკამოდ რთულად განსახორციელებელიც, არსებობს რამოდენიმე მათემატიკური პრობლემა პრობლემა TCP პაკეტის ფორმირებაში და სწორედ ეს არის სორსის “სპუfინგის” არსებობსის გამართლება. თუმცა გამოსავალი ყველაფრიდან არსებოს, syn-spoofing-ის შემთხვევაში ცოტა რთულია software firewall სთხოვო დაგიცვას :) ეფექტურ გამოსავლად შეიძლება ჩაითვალოს უკუღმართი პროქსი :D არ დაიბნეთ revers-proxy -ის თარგმანი გავიფიქრე ხმამაღლა. თუ გავითვალისწინებთ იმას, რომ რევერს პროქსის შეუძლია TCP კავშირი შუაზე “გახლიჩოს”  და ერთი კავშირისგან მიიღოს ორი, ანუ კლიენტს ცალკე კავშირით ელაპარაკოს და სერვერს ცალკე TCP კავშირით; გამოდის, რომ იტისკება პქოქსი – და რა ვებ სერვერი, ეს ნორმალურია TCP კავშირების ჩავვარდნაზე პროქსის 90 პროცენტით ნაკლები რესური ეხარჯება ვიდრე დაუშვად HTTPD სერვერს თავისი თრედებით, შვილობილი პროცესებით და ზარმაცი პროგრამერების გამო მიბმული php ზოოპარკით.
თვალი გადაავლედ შემდეგ მაგალითს და მიხვდებით რა სასარგებლო საქმის გაკეთება შეუძლია რევერს პროქსის content caching ის გარდა, სერვერამდე ვერ აღწევს ვერცერთი spoofed პაკეტი:

attcker—–spoofed-syn———->>proxy
|უსასრულობა|<<—-syn-ack—–proxy——-syn——->>web server
———————————————proxy<<—syn-ack—–web server
———————————————proxy——-ack——->>web server

პრინციპში ჩემი აზრით რევერს პროქსი ყველა ვარიანტში გამართლებული საშუალებაა ვებისთვის.

თუ გავითვალისწინებთ რომ spoofing-ის დროს ხდება ლოკლარი IP  მისამართების გამოყენება , შესაძლებელია წინასწარ განვსაზღვროთ ასეთი დაპაზონები (ძირითადად ესენია ლოკალრი ქსელის მისამართები და სერვერის IP  -ის დიაპაზონიდან) და დავბლოკოთ ნაგულისხმევად მათგან წამოსული ნებისმიერი პაკეტი. ასევე რთული განსახორციელებელია სპუფინგი, როდესაც სერვერი NAT-ის უკან დგას.

როგორ გავიგო შეტევა ?

გავიგოთ კავშირების რაოდენობა 80-ე პორტზე, განურჩევლად მისი მდგომარეობისა:

 netstat -n | grep :80 | wc -l

გავიგოთ SYN_RECV მდგომარეობაში მყოფი კავშირების რაოდენობა, ეს მნიშვნელოვანია ამ მდგომარეობაში არ უნდა იყვეს ბევრი კავშირი, მაგ:  1000  კლიენტის ერთდროული შემოსვლის დროს ეს პარამეტრი არ უნდა იყვეს 10 ზე მეტი 1 წთ განმავლობაში.

 netstat -n -p | grep SYN_RECV | wc -l 

თუ გვინდა ვუყუროთ  ასეთი კავშირების ცვლილებას რეალურ დროში :

 watch -n0 "netstat -n -p | grep SYN_RECV | wc -l" 

თუ გვინდა ვნახოთ, რომელ IP მისამართს რამდენი კავშირი აქვს გახსნილი სერვერთან აკრიფეთ შემდეგი:

 netstat -ntu | tail -n +3 | awk '{print $5}' | sed -e 's/::ffff://g' \
|cut -d: -f1 | sort | uniq -c | sort -n 

syn flood ingყურადღება მიაქციეთ თითოეულ IP მისამართზე კავშირების რაიოდენობას, არ უნდა იყვეს საეჭვოზე მეტი, როგორც მარცხნივ სურათზეა ნაჩვენები, 1 IP მისამართისთვის 5610 კავშირი ძალიან ბევრია, თუ თქვენ ვებ გვერდს არ სტუმრობს, რომელიღაც პატარა ჩინური კორპორციის პროქსი სერვერი, რომლის უკან 5000 შრომისმოყვარე ცინელს, რატომღაც ერთდროულად გაუჩნდა თქვენი ვებ გვერდის მონახულების სურვილი. :P

SYN cookies (დაცვა ბირთვის დონეზე)

არსებობს რამოდენიმე დაცვა 2.6.xx კერნელში, რომლებიც გვიცავს ასეთი შეტევებისგან მაგალითად ერთ-ერთი SYN cookies. მისი იდეა მდგომარეობს შემდეგში: როდესაც კლინტი აგზავნის SYN პაკეტს სერვერთან, სერვერი უგავნის SYN + cookies, ანუ პლიუს კიდევ ერთ cookies პაკეტს, და გაგზავნისთანავე წყვეტს კავშირს კლინტთან, შედეგად აღარ არსებობს ნახევრად ღია კავშირები სერვერზე) ანუ აღარ ელოდება შემდეგ საფეხურებს კილინტისგან კავშირის დასამყარებლად. დამატებითი cookies პაკეტი წარმოადგენს, კლინტის მისამართს, კლინტის პორტს, კლინტის თანმიმდევრობას*, სერვერის მისამართს, სერვერის პორტს და + საიდუმლო ჰეშს.

თუ ამის შემდეგ კლინტი გამოაგზავნის ACK პაკეტს, სერვერი თავიდან გამოითვლის cookies მიმდევრობებს  და შეადრებს ემთხვევა თუ არა ძველ გაგაზავნილ SYN-ACK მოთხოვნას. თუ ემთხვევა კავშირი დადგება. რეალურად როგოც ჟღეს ისე ვერ ამართლებს ეს მეთოდი, ამ გამოთვლებსაც ჭირდება cpu რესურსები, და დრო, ბევრ Linux დისტროში ეს პარამეტრი გამორთულია, მაგრამ Feddora 1x -ში ნაგულისხმევად ჩართულია, თუ გადაწყვეტთ ამ პარამეტრის ჩართვას, მოახდინეთ შემდეგი ცვლილებები:

echo "1" > /proc/sys/net/ipv4/tcp_syncookies 

#დროებითი ჩართვა,

ან დაამატეთ ჩანაწერი /etc/sysctl.conf #მუდმივი ჩართვა
net.ipv4.tcp_syncookies = 1

თავდაცვა I -  network tuning

ნაგულსიხმევად კერნელის კონფიგურაციაში არის  უამრავი პარამეტრი, რომლებიც ტუნინგს ანუ ქართულად რომ ვთქვათ მომართვას ექვემდებარებიან.  ქვემოთ ჩამოთვლილი იქნება რამოდენიმე პარამეტრი, რომლეთა მნიშვნელობა უნდა განსაზღვროთ თქვენი აპარატურული შესაძლებლობების მიხევით, ამ პარამეტრების მნიშვენლობები არ წარმოადგენს მაგიურ ციფრებს, თუ სწორად მოვმართავთ რამოდენიმე Newtork პარამეტრს შესაძელბელია :

1.ნახევრად ღია კავშირების რაოდენობის გაზრდა;
2.ESTABLISHED მდგომარეობაში მყოფი კავშირებსი გაზრდა;
3.ნახევრად-ღია კავშირების ადრე დახურვა; (time-out შემცირება);
4.ლოკალური პორტების დიაპაზონის გაზრდა;
5.TCP ნაკადის მეხსიერბეის ბუფერის გაზრდა;

ვხსნით საყვარელ ტექსტურ რედაქტორში ფაილს: /etc/sysctl.conf
შეგვყავს ქვემოთ ჩამოთვლილი პარამეტრები, ვანიჭებთ სასურველ მნიშვნელობას ან ვტოვებთ უცვლელად.
(ეს პარამეტრები ოპტიმიზირებულია სერვერისთვის, რომლის მეხსიერბა არის 8GB და CPU არის 8-ბირთვიანი)


net.ipv4.ip_local_port_range = 1024 61000
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 16384 16777216
net.ipv4.tcp_fin_timeout = 40
net.core.netdev_max_backlog = 5000
net.core.somaxconn = 10000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_max_syn_backlog = 6144
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_sack = 0
net.ipv4.tcp_syncookies = 0

ვინახავთ და თუ არ გვსურს გადატვირთვა ვუშვებთ ბრძანებას:
sysctl -p
ამის შემდეგ ახალი მნიშვნელობები შევა ძალაში.

თავდაცვა II -  iptables rules

syn-flooding  პირდაპირი შეტევების  დროს,  როდესაც რეალური სორსიდან ცდილობენ შეტევას ამ შეთხვევაში ძალიან ეფექტურია  iptables  თავისი recent და hashlimit მოდულებით, იდეა შემდეგია: თუ შემტევი დაამაყარებს 200 კავშირს სერვერთან ერთი წამის განმავლობაში, მაქსიმალური საწყისი პაკეტების რაოდენობა, რომლებიც დაემთხვევა ამ წესს და ტოლი იქნება 4-ის  დაიდროპება 15 წუთის განმავლობაში, ასევე დალოგირდება შემტევის IP მისამართები.

iptables -N LOGDROP
iptables -A LOGDROP -j LOG --log-prefix "SYN Flood Detected:"  --log-level 7
iptables -A LOGDROP -j DROP
iptables -A INPUT -i eth0  -m recent --name blacklist --rcheck --seconds 900 -j DROP
iptables -A INPUT -i eth0 -p tcp --syn  -m hashlimit  --hashlimit 200/sec \
--hashlimit-burst 4 --hashlimit-htable-expire 300000 --hashlimit-mode srcip \
--hashlimit-name testlimit -j ACCEPT
iptables -A INPUT -i eth0 -m recent --name blacklist --set -j LOGDROP

ამ დროს იბლიოკება მხოლოდ ის IP მისამართები საიდანაც შეტევის მცდელობები იყო განხორციელებული, ჩვეულებრივი IP  მისამართებისთვის სერვერი განაგრძობს მომსახურებას შეუფერხებლად.

დასკვნა

რეალურად თავდაცვის პირველი სცენარიდან გამომდინარე ჩვენ ვზრდით ქსელის გამტარუნარიანობას სერვერზე და შესაბამისად საჭიროა უფრიო მეტი შემტევი რესურსი სერვერის გასაჩერებლად, მეორე ვარიანტი არის თავდაცვა პროგრამული ფაირვოლის დონეზე, რომლიც იმახსოვრებს შემტევის მისამართებს და ბლოკავს მათ გარკვეული ვადით. იყო კიდევ მესამე ვარიანტი – რევერს პროქსი, რომელიც არანაკლებე ეფექტურია spoofing -ის დროს, არ შეიძლება ვინმემ ზუსტად თქვას რომელი ვარინატი ჯობია, ისინი ერთმანეთს არ გამორიცხავენ – შესაძლელებლია სამივე ვარიანტის კომბინაცია და თუ ეს ყველაფერი მძლავს ქსელურ აპარატურასთანა ჰარმონიაში ასეთ შემთხვევაში თქვენ შეგიძლიათ უფრო ეფექტურად გაუმკლავდეთ ამგავარ შეტევებს და გქონდეთ ნაკლები downtime-ი.

Category: attacks, iptables, kernel, Linux, Networking, Security

Tagged:

3 Responses

  1. Misha ამბობს:

    და ეს ყველაფერი შენი მოგონილია? :)

  2. admin ამბობს:

    კონკრეტულად რას გულისხმობ?
    თუ TCP პროტოკოლის გამოგონებას – არა :)

  3. Guliver ამბობს:

    საინტერესო რამეები კი იყო, მაგრამ დიდი არაფერია. გიწვალია და არ გავაკრიტიკებ :D
    part 2 როდის იქნება?

Leave a Reply

ღრუბელიზატორი

networking public key SQUID ssh attacks (1)
iptables (2)
kernel (1)
Linux (4)
Net Tools (1)
Networking (4)
partitioning (1)
revers-proxy (1)
Security (3)
Sys Tools (2)
Uncategorized (1)

WP Cumulus Flash tag cloud by Roy Tanck and Luke Morton requires Flash Player 9 or better.

ბლოგროლი