მარ 4, 2011
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
ყურადღება მიაქციეთ თითოეულ 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-ი.
და ეს ყველაფერი შენი მოგონილია? :)
კონკრეტულად რას გულისხმობ?
თუ TCP პროტოკოლის გამოგონებას – არა :)
საინტერესო რამეები კი იყო, მაგრამ დიდი არაფერია. გიწვალია და არ გავაკრიტიკებ :D
part 2 როდის იქნება?