İçeriğe geç
Approvalens

Rehberler · 7 dk okuma

Yeni Ubuntu VPS'te SSH ve UFW Güvenliği: Kilitlenmeden Kurulum

SSH anahtarı, şifreyle girişi kapatma (Ubuntu'daki sshd_config.d tuzağıyla), sonra doğru sırayla UFW. Docker portlarının UFW'yi neden atladığı da burada.

Approvalens ekibi

Yeni bir VPS genelde SSH'ı herkese açık ve şifreyle girişe izinli olarak gelir. Sunucu genel IP'sini aldıktan birkaç dakika sonra botlar 22. porttan şifre denemeye başlar. Bunun neredeyse tamamını iki değişiklik keser: şifre yerine anahtarla gir ve yayınlamak istemediğin her şeyin önüne bir güvenlik duvarı koy. İkisi de on dakikalık iş. İkisi de yanlış sırayla yapılırsa seni kendi sunucunun dışında bırakabilir.

Aşağıdaki sıra seni dışarıda bırakmaz.

Sırayla altı adım: 1 anahtar oluştur ve sunucuya kopyala, 2 yeni bir terminalde anahtarla giriş yap, 3 o oturumu açık tut, 4 şifreleri bir drop-in dosyasında kapat ve sshd -T ile kontrol et, 5 ufw'de OpenSSH'a izin ver sonra etkinleştir, 6 hiçbir şeyi kapatmadan önce sıfırdan yeni bir girişi test et
Her adımın arkasındaki kural: ikinci bir giriş yolunu test etmeden, giriş yolunu değiştirme.

adım: anahtar oluştur ve sunucuya koy

Sunucuda değil, kendi bilgisayarında:

ssh-keygen -t ed25519 -C "laptop-2026"

Varsayılan yolu kabul et ve bir parola (passphrase) belirle. Ubuntu'nun OpenSSH sunucu belgesi ed25519'u daha kısa anahtar boyutu ve daha düşük işlem yükü nedeniyle öneriyor. Sonra şifreyle giriş hâlâ çalışırken anahtarın açık yarısını sunucuya kopyala:

ssh-copy-id ubuntu@203.0.113.10

Hangi kullanıcıyla giriyorsan onu yaz (birçok VPS firmasında root, Ubuntu bulut imajlarında ubuntu). Bilgisayarında ssh-copy-id yoksa ~/.ssh/id_ed25519.pub dosyasının içeriğini sunucudaki ~/.ssh/authorized_keys dosyasına yeni bir satır olarak yapıştır. Ubuntu belgesi, dosyanın grup ya da herkes tarafından yazılabilir olmamasını da istiyor: chmod go-w ~/.ssh/authorized_keys.

adım: anahtarın çalıştığını kanıtla ve o oturumu açık tut

Yeni bir terminal aç ve yalnızca anahtarla girmeyi zorla:

ssh -o PasswordAuthentication=no ubuntu@203.0.113.10

Komut satırına düştüysen anahtar çalışıyor. Bu oturumu iş bitene kadar kapatma; sonraki bir adım ters giderse geri dönüş yolun bu. sshd'yi yeniden başlatmak zaten açık olan oturumları kapatmaz. (ufw'nin kılavuzu, etkinleştirmenin mevcut bağlantıları düşürebileceği konusunda uyarıyor; bu yüzden son çare, yazının sonunda anlattığımız sağlayıcı web konsolu.)

adım: şifreyle girişi kapat (ve drop-in klasörüne bak)

Tuzak şurada. Ubuntu'da /etc/ssh/sshd_config dosyası /etc/ssh/sshd_config.d/*.conf için bir Include satırıyla başlıyor ve Ubuntu belgesine göre bu klasördeki ayarlar ana dosyanın önüne geçiyor. Nedenini sshd_config kılavuzu açıklıyor: "for each keyword, the first obtained value will be used", yani her ayar için okunan ilk değer geçerli; eklenen dosyalar da alfabetik sırayla okunuyor.

Birçok Ubuntu kurulumunda bu klasörde zaten PasswordAuthentication yes içeren bir 50-cloud-init.conf var; cloud-init'in ssh_pwauth ayarı yazıyor. Ubuntu'nun #2088207 numaralı hata kaydı tam olarak bunu yaşayanların kaydı: sshd_config içinde PasswordAuthentication no yazıyorlar, yeniden başlatıyorlar, şifre hâlâ çalışıyor. Sunucuda cloud-init'in kendisi hata veriyorsa cloud-init hatası rehberi kaydı nasıl okuyacağını anlatıyor.

O yüzden önce bak:

sudo grep -riE '^\s*(passwordauthentication|kbdinteractiveauthentication|permitrootlogin)' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/
İki sshd ayar dosyası yan yana: PasswordAuthentication no içeren 00-hardening.conf ilk okunuyor ve kazanıyor; PasswordAuthentication yes içeren 50-cloud-init.conf ikinci okunuyor ve yok sayılıyor; ana sshd_config satırı en son okunuyor; altta sshd -T çıktısı passwordauthentication no gösteriyor
sshd okuduğu ilk değeri tutar. 00-… adlı dosya 50-cloud-init.conf'u geçer; 99-… adlı dosya ona yenilir.

Sonra ayarlarını, adı 50-cloud-init.conf'tan önce sıralanan bir drop-in dosyasına yaz. Birçok anlatım "en son okunsun diye" büyük bir numara vermeni söylüyor. sshd'de bu tam tersi: en son okunan kaybeder.

sudo tee /etc/ssh/sshd_config.d/00-hardening.conf >/dev/null <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
EOF

prohibit-password root için zaten varsayılan (kılavuz "The default is prohibit-password" diyor) ama açıkça yazmak ayarı görünür kılar. sudo yetkili normal bir kullanıcıyla giriyorsan PermitRootLogin no kullan. İstersen 50-cloud-init.conf içindeki satırı da no yapabilir, ileride kuracağın sunucular için sağlayıcının user-data alanına ssh_pwauth: false ekleyebilirsin (cloud-init set passwords modülü).

Ayarı test et, sonra sshd'ye gerçekte ne kullanacağını sor:

sudo sshd -t
sudo sshd -T | grep -E 'passwordauthentication|kbdinteractiveauthentication|permitrootlogin'

Söz dizimi doğruysa sshd -t hiçbir şey yazmaz. sshd -T bütün include'lardan sonraki geçerli değerleri basar. Görmek istediğin:

permitrootlogin prohibit-password
passwordauthentication no
kbdinteractiveauthentication no

Ancak bundan sonra, Ubuntu belgesindeki komutla yeniden başlat:

sudo systemctl restart ssh.service

Üçüncü bir terminalden şifrenin reddedildiğini doğrula:

ssh -o PubkeyAuthentication=no ubuntu@203.0.113.10
ubuntu@203.0.113.10: Permission denied (publickey).

Sondaki (publickey), sunucunun artık yalnızca anahtar kabul ettiğini gösterir.

adım: UFW'yi doğru sırayla aç

ufw kılavuzu: "On installation, ufw is disabled with a default incoming policy of deny, a default forward policy of deny, and a default outgoing policy of allow." Yani kurulumda kapalı geliyor ama gelen trafik için varsayılanı "reddet". Etkinleştirdiğin anda kuralı olmayan her gelen bağlantı düşer, SSH dahil. Aynı sayfa, ufw'nin etkinleştirmeden önce kural eklemeyi desteklediğini söylüyor. Bütün numara bu: önce kurallar, sonra etkinleştirme.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

OpenSSH, SSH sunucusuyla gelen bir uygulama profili (sudo ufw app list sende hangi profillerin olduğunu gösterir). SSH'ı başka bir porta taşıdıysan, etkinleştirmeden önce o porta izin ver, örneğin sudo ufw allow 2222/tcp.

enable komutunu SSH üzerinden çalıştırınca ufw önce sorar:

Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

Sonuca bak:

sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp (OpenSSH)           ALLOW IN    Anywhere
80/tcp                     ALLOW IN    Anywhere
443/tcp                    ALLOW IN    Anywhere
22/tcp (OpenSSH (v6))      ALLOW IN    Anywhere (v6)
80/tcp (v6)                ALLOW IN    Anywhere (v6)
443/tcp (v6)               ALLOW IN    Anywhere (v6)

Şimdi bir yeni terminal daha aç ve giriş yap. Çalışıyorsa 2. adımdaki güvenlik oturumunu kapatabilirsin.

İki isteğe bağlı ek. sudo ufw limit OpenSSH, düz izni hız sınırıyla değiştirir; kılavuza göre bir IP 30 saniye içinde 6 ya da daha fazla bağlantı başlatırsa ufw reddeder. İşe yarar ama yalnızca anahtar kabul eden bir sunucuda tahmin denemeleri zaten bir yere varmaz. Evde ya da ofiste sabit IP'n varsa SSH'ı yalnızca o adrese açabilirsin (sudo ufw allow from 198.51.100.7 to any port 22 proto tcp); yalnız IP'nin değiştiği gün için sağlayıcının web konsolunu aklında tut.

Sağlayıcın panelinde ayrıca bir bulut güvenlik duvarı da sunabilir. Bu, sunucunun önünde ayrı bir katman; bir port ufw'de açık ama orada kapalıysa yine kapalıdır.

Docker, yayınlanan portlarda UFW'yi dinlemez

Bu, ufw kurulu sunucuda Docker çalıştıran hemen herkesin başına gelir. Docker'ın packet filtering and firewalls sayfası: "Docker and ufw use firewall rules in ways that make them incompatible with each other." Devamında, bir konteynerin portunu yayınladığında o konteynere giden trafiğin ufw ayarlarından geçmeden yönlendirildiğini anlatıyor.

Yani docker run -p 8080:80 … ya da Compose'ta ports: - "8080:80", ufw status hiç bahsetmese bile 8080 portunu internete açar. Docker'ın port yayınlama belgesi bunu açıkça söylüyor: "Publishing container ports is insecure by default."

Önünde nginx ya da başka bir proxy varsa çözüm, portu yalnızca loopback'e yayınlamak. Docker'a göre yayınlama ayarına 127.0.0.1 (ya da ::1) eklersen yayınlanan konteyner portuna yalnızca Docker sunucusu erişebilir:

ports:
  - "127.0.0.1:8080:80"

Neyin hangi adreste dinlediğine bak:

sudo ss -tlnp

0.0.0.0:8080 ya da [::]:8080 içeren satır herkese açık. 127.0.0.1:8080 yalnızca yerel. Asıl dikkat edilecekler veritabanları: 0.0.0.0 üzerinde yayınlanmış bir MySQL ya da Redis konteynerine herkes ulaşabilir.

Dışarıda kaldıysan

Her VPS sağlayıcısının SSH'tan ve güvenlik duvarından geçmeyen bir web konsolu (VNC, seri konsol ya da "kurtarma konsolu") vardır. Oraya kullanıcının şifresiyle gir (ya da panelden sıfırla), sonra son adımı geri al: güvenlik duvarıysa sudo ufw allow OpenSSH, anahtarsa drop-in dosyasını kenara çek (sudo mv /etc/ssh/sshd_config.d/00-hardening.conf /root/) ve ssh'ı yeniden başlat. Ardından 2. adıma dön.

Sırada ne var?

Sıkılaştırılmış SSH şifre tahminini durdurur; web uygulamalarına dokunmaz. Giriş formu için fail2ban kurulumu rehberine bak. Sunucuda CUPS 631 portu açık rehberi de kimsenin yayınlamak istemediği bir portun iyi bir örneği; ss sana tuhaf bir şey gösterdiyse oradaki kontroller her port için geçerli. Sitenin tarayıcıya bakan tarafı için blog için güvenlik başlıkları rehberi var.

Gözünü üstünde tut

Approvalens sunucu ajanı saatte bir SSH'ın şifre ya da root girişi kabul edip etmediğine ve güvenlik duvarının açık olup olmadığına bakar, yeni bir port dinlemeye başlayınca sana e-posta atar.

Sık sorulan sorular

PasswordAuthentication no yazdım ama şifre hâlâ çalışıyor. Neden?

/etc/ssh/sshd_config.d/ içindeki bir dosya bunu yes yapıyor ve senin satırından önce okunuyor. Geçerli değeri görmek için sudo sshd -T | grep passwordauthentication çalıştır, sonra ayarını ilk sıralanan bir drop-in dosyasına (örneğin 00-hardening.conf) yaz.

SSH portunu 22'den başka bir porta taşımalı mıyım?

Yalnızca 22'yi deneyen botların log'daki gürültüsünü azaltır. Tek başına koruma değildir; koruma anahtardır. Taşıyacaksan ssh'ı yeniden başlatmadan önce yeni porta ufw'de ve sağlayıcının güvenlik duvarında izin ver, yeni bir oturumda test et.

Sağlayıcımın bulut güvenlik duvarı varsa ufw'ye gerek var mı?

En az bir çalışan güvenlik duvarı şart. ufw kullanışlı, çünkü sunucuyla birlikte taşınıyor ve kabuktan kontrol edebiliyorsun. Hiçbirinin, 127.0.0.1'e bağlamadığın (ufw için) ya da sağlayıcıda kapatmadığın Docker portlarını durdurmadığını unutma.

ufw enable komutunu SSH üzerinden çalıştırmak güvenli mi?

Önce sudo ufw allow OpenSSH (ya da özel portun) çalıştırdıysan evet. SSH ile bağlıyken ufw seni uyarır. İzin kuralı yoksa, etkinleştirdiğin anda yeni SSH bağlantıları düşer.

Eskimiş ya da yanlış bir şey mi gördün? Bize yaz, düzeltelim.

Bu rehberi İngilizce oku →

Ücretsiz tarama

Kendi siteni kontrol et

Ücretsiz tarama ilk 50 sayfayı okur; puanını ve bulduğu tüm sorunları gösterir.

İlk 50 sayfa ücretsiz · üyelik yok · kart gerekmez

Tüm rehberler