ღია და დავიწყებული პორტი სერვერში შეღწევის კლასიკური გზაა: მონაცემთა ბაზა საჯარო მისამართზე, გამართვის პანელი, კონტეინერი, რომელმაც პორტი გამოაქვეყნა, თუმცა ეს არავის უნდოდა. შემოწმებას ერთი წუთი სჭირდება, თუ ორი ბრძანება და ერთი ხაფანგი იცით. ყველაფერი, რაც ქვემოთაა, შევასრულეთ ჩვენი იმიჯიდან ახალ Ubuntu 24.04 სერვერზე და მეორე მანქანიდან დავასკანერეთ, ასე რომ გამოტანა ისეთივე იქნება, როგორსაც თქვენს სერვერზე ნახავთ.
1. რა უსმენს
ბრძანებაა ss. ასოები ნიშნავს: TCP, UDP, მოსმენის სოკეტები, პორტების ნომრები და პროცესის სახელი:
sudo ss -tulpn
ახალ სერვერზე ის ექვს ხაზს ბეჭდავს:
Netid State Local Address:Port Process
udp UNCONN 127.0.0.54:53 systemd-resolve
udp UNCONN 127.0.0.53%lo:53 systemd-resolve
tcp LISTEN 127.0.0.54:53 systemd-resolve
tcp LISTEN 127.0.0.53%lo:53 systemd-resolve
tcp LISTEN 0.0.0.0:22 sshd
tcp LISTEN [::]:22 sshd
მთავარი სვეტია Local Address. ის გეუბნებათ, ვის შეუძლია დაკავშირება:
| მისამართი | ვინ მიწვდება |
|---|---|
127.0.0.1:… ან 127.0.0.53 | მხოლოდ ამ სერვერზე მყოფი პროგრამები |
0.0.0.0:… | ყველა IPv4-ით, თუ ფაირვოლი არ ბლოკავს |
[::]:… | ყველა IPv6-ით (ჩვეულებრივ IPv4-ითაც) |
10.0.0.5:… (კონკრეტული მისამართი) | ყველა, ვინც ამ მისამართს მიწვდება |
ანუ ახალი სერვერი გარეთ ზუსტად ერთ რამეს აჩენს: SSH-ს 22-ე პორტზე, IPv4-ითა და IPv6-ით. DNS რეზოლვერი 127.0.0.53-ზე პირადია.
რომ მხოლოდ ის ნახოთ, რისი დანახვაც ინტერნეტს შეუძლია, გაფილტრეთ loopback მისამართები:
sudo ss -tlnp | awk 'NR>1 && $4 !~ /^(127\.|\[::1\])/ {print $4, $6}'
გაუშვით ეს ყოველი ინსტალაციის შემდეგ. დავაყენეთ nginx, Docker და ერთი პატარა Python აპლიკაცია, და სია 2 ხაზიდან 10-მდე გაიზარდა, მათ შორის docker-proxy 0.0.0.0:8081-ზე და containerd-ის სოკეტი შემთხვევით localhost პორტზე.
2. რომელმა პროცესმა დაიკავა პორტი
როცა პორტი დაკავებულია და გინდათ გაიგოთ, ვის მიერ:
sudo lsof -i :80 -P -n
sudo fuser 80/tcp
sudo ss -tlnp 'sport = :80'
lsof ყველაზე ადვილად იკითხება. nginx-ისთვის მან აჩვენა ერთი მთავარი პროცესი root-ით და worker www-data-თი, ორივე *:80-ზე, IPv4-ისა და IPv6-ისთვის. fuser მხოლოდ PID-ებს ბეჭდავს — სკრიპტებში მოსახერხებელია. თუ პორტის გათავისუფლება გჭირდებათ, გააჩერეთ სერვისი და არა PID-ის მოკვლა, თორემ systemd მას ხელახლა გაუშვებს: sudo systemctl stop nginx.
3. რას ხედავს ინტერნეტი
ss სერვერის თვალით აჩვენებს. ინტერნეტის ხედვა შეიძლება განსხვავდებოდეს: შუაში ფაირვოლი დგას ან სერვისი 127.0.0.1-ზეა მიბმული. რეალური სურათის სანახავად დაასკანერეთ სერვერი სხვა მანქანიდან — ლეპტოპიდან ან მეორე სერვერიდან. ხელსაწყოა nmap (apt install nmap, Windows-სა და macOS-ზე კი ინსტალერი nmap.org-იდან).
nmap your-server-ip
nmap -p- your-server-ip
nmap -p 22,80,443,3306 your-server-ip
პირველი ფორმა ამოწმებს 1000 ყველაზე გავრცელებულ პორტს, მეორე — ყველა 65 535-ს, მესამე — სიას. ჩვენს ახალ სერვერზე, ყოველგვარ ფაირვოლამდე:
Not shown: 999 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
Nmap done: 1 IP address (1 host up) scanned in 6.83 seconds
65 535 პორტის სრულ სკანირებას 8,9 წამი დასჭირდა და იგივე ერთადერთი პორტი იპოვა. დახურული პორტები მაშინვე reset-ით პასუხობენ, ამიტომ მათი სკანირება სწრაფია.
მნიშვნელოვანია სამი მდგომარეობა:
- open: პროგრამამ კავშირი მიიღო. ეს თქვენი თავდასხმის ზედაპირია.
- closed: სერვერმა უპასუხა, რომ აქ არაფერი უსმენს. უსაფრთხოა, მაგრამ ადასტურებს, რომ სერვერი არსებობს და რა არ მუშაობს მასზე.
- filtered: პასუხი არ არის. ფაირვოლმა პაკეტი გადააგდო. სკანერმა არ იცის, დგას თუ არა მის უკან სერვისი.
ერთი პორტისთვის არაფრის დაყენების გარეშე nc -zv სერვერის-ip 443 გიპასუხებთ succeeded ან refused, ხოლო filtered პორტზე ტაიმაუტამდე ელოდება. UDP-სთვის nmap-ს დაუმატეთ -sU და მოემზადეთ ლოდინისთვის; ჩვენს სერვერზე სამი გავრცელებული UDP პორტი — 53, 123 და 161 — closed იყო.
შენიშვნა NAT ტარიფებისთვის: ინტერნეტიდან მხოლოდ ის SSH პორტია ხელმისაწვდომი, რომელიც თქვენთვის გადავამისამართეთ. საერთო მისამართის სკანირება ჩვენს საზღვარს აჩვენებს და არა თქვენს სერვერს, ხოლო დანარჩენი პორტები მიუწვდომელია, რაც არ უნდა უსმენდეს მათ. საკუთარი IPv4 მისამართის მქონე ტარიფზე ყოველ ღია პორტს თავად მართავთ.
4. დახურეთ ზედმეტი
სამი გზა — საუკეთესოდან ყველაზე ფართომდე.
მიაბით localhost-ს. თუ სერვისს მხოლოდ სერვერზე მყოფი პროგრამები იყენებენ, მოუსმინოს 127.0.0.1-ს. პატარა ვებაპლიკაცია გავუშვით --bind 127.0.0.1 8080-ით: ss-მა ის 127.0.0.1:8080-ზე აჩვენა, nmap-მა კი გარედან 8080/tcp closed დააბრუნა. მონაცემთა ბაზებისთვის ეს სწორი ნაგულისხმევია: Redis, MySQL და PostgreSQL Ubuntu-ზე თავიდანვე localhost-ს უსმენენ, და ჩვენი სახელმძღვანელოები Redis-სა და MySQL-ისთვის ასე ტოვებს.
გააჩერეთ სერვისი. sudo systemctl disable --now სახელი მსმენელს სამუდამოდ აშორებს. ss-ით შეამოწმეთ, რომ გაქრა.
ჩართეთ ფაირვოლი. ჯერ დაუშვით SSH, შემდეგ ის, რასაც აწვდით, შემდეგ ჩართეთ:
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw enable
sudo ufw status verbose
გარედან სკანირება მთლიანად შეიცვალა:
Not shown: 997 filtered tcp ports (no-response)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
8081/tcp open blackice-icecap
Nmap done: 1 IP address (1 host up) scanned in 10.18 seconds
ყოველი დაუშვებელი პორტი closed-იდან filtered-ში გადავიდა, ხოლო 65 535 პორტის სრულ სკანირებას ახლა 8,9-ის ნაცვლად 110 წამი დასჭირდა. სკანერისთვის მეტი დრო თითო პორტზე, თქვენს სერვერზე ნაკლები ინფორმაცია. ჩვენი UFW-ის სახელმძღვანელო განიხილავს სიხშირის შეზღუდვას, ერთი IP-ის დაშვებას და IPv6-ს.
მაგრამ შეხედეთ მესამე ხაზს.
5. Docker-ის სიურპრიზი
პორტი 8081 ღია დარჩა ჩართული ფაირვოლის დროს და ისე, რომ მის დამშვებ წესს არ ვქონდით. ეს პორტი ეკუთვნის კონტეინერს, რომელიც docker run -p 8081:80 nginx:alpine-ით გავუშვით. Docker ბირთვის ფაირვოლში საკუთარ წესებს ამატებს და ისინი ufw-ის წესებზე ადრე მოწმდება. წესი, რომელიც მან ჩვენს სერვერზე ჩაწერა:
-A DOCKER ! -i docker0 -p tcp --dport 8081 -j DNAT --to-destination 172.17.0.2:80
8081 პორტზე მისული ნებისმიერი პაკეტი კონტეინერში გადამისამართდება, სანამ ufw სიტყვას იტყვის. ასე იქცევა ყოველი კონტეინერი -p-ით ან ports:-ის ჩანაწერით, და ss ამას პატიოსნად აჩვენებს როგორც docker-proxy 0.0.0.0:8081-ზე.
გამოსწორება — პორტის გამოქვეყნება მხოლოდ localhost-ზე:
docker rm -f web
docker run -d --name web -p 127.0.0.1:8081:80 nginx:alpine
Compose-ში ports:-ში ჩაწერეთ "127.0.0.1:8081:80". ცვლილების შემდეგ ss-მა აჩვენა 127.0.0.1:8081, Docker-ის წესს დაემატა -d 127.0.0.1/32, ხოლო გარედან სკანირებამ 8081/tcp filtered დააბრუნა. საჯარო მხარისთვის წინ დააყენეთ nginx როგორც reverse proxy HTTPS-ით, რომ სერვერზე ღია იყოს მხოლოდ 22, 80 და 443 პორტები.
შემოწმების სია ყოველი ცვლილების შემდეგ
sudo ss -tulpn:0.0.0.0-ის ან[::]-ის შემცველი ყოველი ხაზი ის არის, რისი გახსნაც გინდოდათ?nmap სერვერის-ipლეპტოპიდან: ემთხვევა ღია პორტები?- მონაცემთა ბაზა, ქეში ან ადმინ-პანელი საჯარო მისამართზე: დღესვე გადაიტანეთ
127.0.0.1-ზე ან ფაირვოლის უკან. - Docker-ის ყოველი
ports:ჩანაწერი: იწყება127.0.0.1:-ით, თუ ის საჯარო ვებპორტი არ არის? - SSH ყველასთვის ღიაა: დაამატეთ fail2ban ან შესვლა მხოლოდ გასაღებით.
Windows Server-ზე იგივე შემოწმებაა Get-NetTCPConnection -State Listen, ხოლო წესები Windows-ის ფაირვოლშია. ყოველ Linux ტარიფს, Nano-დან $3-ად დაწყებული, აქვს ვერსია საკუთარი IPv4 მისამართით, და იქ ის, რასაც ss-ში ხედავთ, მთელი სამყარო ხედავს — გარდა იმისა, რასაც თქვენი ფაირვოლი აჩერებს.
კომენტარები
ჯერ არ არის კომენტარები. იყავით პირველი.