
Yeni bir VPS'i ilk saatte sertleştir
Herkese açık bir IPv4 adresi, ilk paketinden itibaren dakikalar içinde, sizi hiç duymamış ve hiç duymayacak makineler tarafından yoklanmaya başlar. Bu aslında iyi bir haber: yeni bir sunucuyu hedef alan neredeyse her şey jeneriktir ve bilinçle geçirilen tek bir saat bunların neredeyse tamamını etkisiz kılar. Aynı saat, yanlış sırayla uygulanırsa, sizin adınıza kimsenin giriş yapamayacağı bir makinede sizi dışarıda bırakır.
Ödeme onaylandıktan yaklaşık 47 saniye sonra size bir root kabuğu teslim ediyoruz ve ardından, bilinçli olarak, orada duruyoruz. Bir ajan kurmuyoruz, güvenlik duvarınızı yönetmiyoruz ve kimlik bilgilerinizin bir kopyasını tutmuyoruz — elimizde tuttuğumuz bir anahtar, üretmeye zorlanabileceğimiz bir anahtardır ve bu ilke platformun tamamına sinmiştir. Sonucu basit ve açıkça söylenmeye değer: sunucunuzun güvenliği, onu ilk saatte bıraktığınız durumdur.
Aşağıda anlatılan, Debian 13 ve Ubuntu 24.04 üzerinde bu saati bizim de fiilen uyguladığımız sırayla ele alıyor. İşin çoğunu iki ayar görüyor. Bu sayfanın geri kalanı, doğru görünen, her rehberin son kontrolünden geçen ama sessizce yanlış olan üç şey yüzünden var: sessizce geçersiz kılınan bir drop-in SSH yapılandırması, socket ile etkinleştirilen bir sshd'nin yok saydığı bir port ayarı ve güvenlik duvarınızın altından port yayınlayan bir konteyner çalışma zamanı. Her biri, geri kalan her şeyi doğru yapmış birini bir kez ısırdı.
Kapıyı gerçekte kim çalıyor
Bir saattir çevrimiçi olan bir sunucuda journalctl -u ssh komutunu izleyin; ilk gördüğünüzde hacim endişe verici gelecektir. Aslında öyle olmamalı. Gördüğünüz şey internetin fon gürültüsüdür: bazıları akademik, bazıları ticari, bazıları suç amaçlı bir avuç tarama operasyonu, tüm IPv4 uzayını kesintisiz olarak numaralandırır ve sonuçları kimlik bilgisi tahmin eden botlara teslim eder. Adresinize ulaşılmasının nedeni, sayısal sırada var olmasıdır ve siz ne yaparsanız yapın birkaç saat içinde tekrar ulaşılacaktır.
Bu, sorunun şeklini kullanışlı bir biçimde değiştirir. Sizi seçmiş ve uyum sağlayacak bir düşmana karşı değil, sabit bir repertuara sahip bir betiğe karşı savunma yapıyorsunuz — root, admin, ubuntu, test, git, oracle, postgres ve sızıntı dökümlerinde ortaya çıkmış yirmi bin parola. Bunun sabrı yoktur, yaratıcılığı yoktur ve ilk denemede yanıt vermeyen bir makineyle hiç ilgilenmez. Parola kimlik doğrulamasını kapatmak bu saldırganı yavaşlatmaz. Onu tahtadan tamamen kaldırır.
Bilinmesi gereken iki ayrıntı var. Birincisi, IPv6 çarpıcı biçimde daha sessizdir, çünkü bir /64 tümüyle taranamaz — ama AAAA kaydınız herkese açık olduğu ya da makinenizin adresi bir e-posta başlığında veya bir certificate-transparency günlüğünde göründüğü an bu sessizlik biter. IPv6'yı asla bir saklanma yeri olarak görmeyin; daha küçük bir saman yığını olarak görün. İkincisi, bir IPv4 adresinin bir geçmişi vardır. Sizden önce bir kiracısı olmuştur ve o kiracı bir posta sunucusunu kötü yönettiyse ya da listeye giren bir şey barındırdıysa, itibarı o silinene kadar siz devralırsınız. E-posta sizin için önemliyse, üzerine bir şey inşa etmeden önce adresi alışılagelmiş kara listelerde kontrol edin — bu, beş dakikalık bir kontrol, iki haftalık teslim edilebilirlik hata ayıklamasından tasarruf ettirir.
İşin yüzde 90'ını yapan iki ayar
Küçük bir sunucunun neredeyse her gerçek ele geçirilme vakası şu iki yerden birinde başlar: tahmin edilebilecek bir parola veya dinlemede olmaması gereken halde dinlemede olan bir servis. Bunlara karşılık gelen düzeltmeler PasswordAuthentication no ve varsayılan politikası drop olan bir güvenlik duvarıdır. Gösterişsizdirler, ikisi birlikte on beş dakika sürer ve bu sayfadaki diğer tüm önlemlerin toplamından daha değerlidirler.
Bunun nedeni istatistiksel değil yapısaldır. İkisi de varsayılan olarak kapalıdır — güvenli tarafa doğru başarısız olurlar. Sadece anahtarla çalışan bir sshd, kaç deneme gelirse gelsin kaba kuvvetle kırılamaz, çünkü kodda parola kabul eden bir yol yoktur. Varsayılan reddet bir güvenlik duvarı, henüz kurmadığınız servisleri de korur — üç ay sonra ekleyip localhost'a bağlamayı unutacağınız veritabanı dahil. Bir sertleştirme kontrol listesindeki geri kalan her şey kötülüklerin bir dökümüdür: kapatılacak belirli şeylerin bir listesi, ki bu da yalnızca listenin kendisi kadar eksiksiz olabilir.
Bu yüzden tek bir bölüm okuyup sekmeyi kapatacaksanız, bunu okuyun, aşağıdaki 2'den 5'e kadar olan adımları uygulayın ve saati iyi harcanmış sayın. Geri kalanı gerçekten faydalı ve gerçekten ikincildir.
SSH yapılandırması artık nerede yaşıyor ve içindeki tuzak
Debian 13 ve Ubuntu 24.04'te /etc/ssh/sshd_config, bir Include /etc/ssh/sshd_config.d/*.conf satırıyla başlar ve cloud imajları bu dizine — genellikle 50-cloud-init.conf adıyla — PasswordAuthentication'ı zaten ayarlayan bir dosya koyar. Ana dosyayı düzenleyip kendi direktiflerinizi en alta eklemek doğal gelir, ama söylediğini yapmayan bir yapılandırma üretir.
Kural, sshd hakkında neredeyse herkesi şaşırtan tek şeydir: her anahtar kelime için elde edilen ilk değer geçerli olur. Bu, kullandığınız hemen hemen her diğer yapılandırma birleştirme sisteminin tam tersidir. Include ana dosyanın en üstüne yakın durur, bu yüzden bir drop-in, sshd_config'in gövdesinden önce okunur — ve drop-in'ler arasında alfabetik sıra belirleyicidir. 10-hardening.conf adlı bir dosya, 50-cloud-init.conf'u geride bırakır. 60-hardening.conf adlı bir dosyaysa ona sessizce kaybeder ve bunu başarı raporu veren bir yeniden başlatmadan öğrenemezsiniz.
Bu yüzden az önce yazdığınız dosyaya asla güvenmeyin. Daemon'a gerçekte neyi çözümlediğini sorun:
sshd -t # syntax check — silence means valid
sshd -T | grep -Ei '^(permitrootlogin|passwordauthentication|pubkeyauthentication|kbdinteractive|allowusers|port) 'sshd -T, her include, geçersiz kılma ve varsayılan çözümlendikten sonraki etkin yapılandırmayı yazdırır. Bu çıktı passwordauthentication yes diyorsa, diskteki herhangi bir dosyanın ne iddia ettiğinden bağımsız olarak parola kimlik doğrulaması açıktır. Başka hiçbir şey doğrulama sayılmaz.
İkinci tuzak da aynı aileden. Ubuntu 24.04, sshd'yi socket etkinleştirmesi (socket activation) yoluyla başlatır: dinleme portunun sahibi ssh.socket'tir ve sshd_config içindeki Port tamamen yok sayılır. systemctl is-enabled ssh.socket ile kontrol edin; etkinse ve farklı bir port istiyorsanız, bunu sshd_config içinde değil — orada ayar doğru görünüp hiçbir işe yaramaz — systemctl edit ssh.socket ile ve bir ListenStream= geçersiz kılmasıyla değiştirin.
Port 22'den taşınmak: tiyatro, ama ucuz bir tiyatro
Bu konuda dürüst olalım, çünkü internet dürüst değil. sshd'yi port 2222'ye veya 47000'e taşımak, yetkin hiçbir saldırganı durdurmaz. Tek bir hostun tam bir TCP taraması saniyeler sürer, servis kendini banner'da ele verir ve özellikle sizi hedef almaya karar vermiş biri, kahvesini bitirmeden onu bulur.
Yaptığı şey, kimlik doğrulama günlüğünüzü kabaca yüzde 95 azaltmaktır ve bunun gerçek bir değeri vardır: göz gezdirdiğiniz günlüklerle gerçekten okuduğunuz günlükler arasındaki farktır. Görebildiğiniz sinyal, gömdüğünüz sinyalden üstündür. Herhangi bir şeyi izliyorsanız, sessiz bir auth.log bir anomaliyi görünür kılmanın en ucuz yoludur.
Maliyetler küçüktür ama gerçektir ve bunu önerilen değil isteğe bağlı olarak nitelendirmemizin nedeni de budur. Sekiz ay sonra geri döndüğünüzde portu unutacaksınız. 1024 üzerindeki standart olmayan bir port, sshd herhangi bir an dinlemiyor olursa, prensip olarak ayrıcalıksız bir süreç tarafından ele geçirilebilir. İstemci ağlarındaki kısıtlayıcı giden güvenlik duvarları alışılmadık portları engeller, bu yüzden zaman zaman bir ofisten veya bir otelden kendi sunucunuza ulaşamazsınız. Ve socket ile etkinleştirilen bir sistemde bunu, bir önceki bölüme göre doğru yerde değiştirmeniz gerekir. Sessiz günlükler sizin için önemliyse yapın. Yapıp da kendinizi güvende hissetmeyin ve bunu asla sadece-anahtar kimlik doğrulamasının yerine yapmayın.
Varsayılan reddet ve fiilen çalıştırdığımız kural seti
Neyi engelleyeceğini listeleyen bir güvenlik duvarı bir dosyalama sistemidir. Neye izin vereceğini listeleyen bir güvenlik duvarıysa bir güvenlik önlemidir. Bu ayrım işin tamamıdır, çünkü yalnızca ikincisi gelecek ay kuracağınız servisi, bir cuma günü açtığınız debug portunu ve kendini dışarı açmaya karar veren konteyneri de kapsar.
Platformumuzda iki katman vardır ve birbirlerinden bağımsızdırlar. Kenar filtresi isteğe bağlıdır, panelden sunucu başına yapılandırılır ve hipervizör üzerinde uygulanır; böylece engellenen trafik guest'inize hiç ulaşmaz — çekirdeğinizin bir döngüsünü harcamasından önce uygulanmasını istediğiniz katman-4 kuralları için ve ele geçirilmiş bir guest'i siz üzerinde çalışırken erişilemez tutmak için kullanışlıdır. Guest güvenlik duvarı tamamen sizindir: nftables, iptables, pf, imajınız ne getiriyorsa. Biz ona asla dokunmayız. Makine önemliyse ikisini birden kullanın; en azından ikincisini her zaman kullanın.
5. adımdaki kural setinde iki şey açıklanmayı hak ediyor, çünkü kopyala-yapıştır kural setlerinin çoğu bunları yanlış yapıyor. Tüm ICMP'yi düşürmeyin (drop). Bu düzenli hissettirir ama path-MTU keşfini bozar, ki bu da olabilecek en kötü hata sınıfını üretir: küçük istekler çalışır, büyük yanıtlar takılır ve günlüklerinizde güvenlik duvarından söz eden hiçbir şey yoktur. En azından destination-unreachable, time-exceeded ve parameter-problem'i kabul edin. Listeyi bilmiyorsanız ICMPv6'yı türe göre filtrelemeyin. IPv6, komşu keşfi ve yönlendirici duyurusu için ICMPv6'ya bağımlıdır; onu geniş kapsamlı engellerseniz IPv6 bağlantınız bir yönlendirme sorunu gibi görünen bir şekilde ölür. Tek bir host üzerinde tüm ICMPv6'yı kabul etmek makul bir değiş tokuştur ve aşağıdaki kural seti tam olarak bunu yapar.
flush ruleset'i çalıştırmadan önce bir uyarı: Docker kuruluysa, bu satır Docker'ın yazdığı NAT ve filter kurallarını kaldırır ve systemctl restart docker onları geri koyana kadar konteyner ağı durur. Önce kural setinizi yükleyin, sonra Docker'ı yeniden başlatın ve tek bir konteyner portu bile yayınlamadan önce bir sonraki bölümü okuyun.
Açık olduğunu bilmediğiniz portlar
Makineye neyi dinlediğini sorun. Ne kurduğunuzu sandığınızı değil — şu anda neyin bağlı olduğunu:
ss -tulpn | grep -vE '127\.0\.0\.1|\[::1\]'Bu filtreden sağ çıkan her şey, makinenin kendisi dışında bir yerden erişilebilir demektir. Standart bir imajda alışılagelmiş bulgular, 111 portundaki rpcbind (çalıştırdığınız hiçbir şey buna ihtiyaç duymaz), temel kurulumdan kalma bir exim4 dinleyicisi ve loopback üzerinde zararsız olan ama öyle değilse açık bir resolver'a dönüşen bir systemd-resolved stub'ıdır. Tehlikeli olanlar daha sonra, bilerek kurduğunuz yazılımlarla gelir: bir rehber listen_addresses'ı düzenlemeyi söylediği için 0.0.0.0:5432 üzerinde PostgreSQL; Redis, ömrünün büyük bölümünde varsayılan olarak parolası olmadığı için parolasız Redis; bir Elasticsearch düğümü; bir Prometheus exporter'ı; bir Jupyter notebook. Bunların her biri, gerçek bir ihlalin ilk adımı olmuştur, hem de defalarca.
Şimdi dikkatli insanları bile yakalayan tuzak. Docker, güvenlik duvarınızdan izin istemez. -p 5432:5432 yazdığınızda, Docker nat tablosunun PREROUTING zincirine DNAT kuralları ekler; çekirdek bunu, input zinciniz paketi görmeden önce değerlendirir; trafik ardından konteynere yönlendirilir. Varsayılan reddet input politikanıza hiç danışılmaz, ufw status portu kapalı gösterir ve veritabanı herkese açık internettedir. Bu, belgelenmiş bir Docker davranışıdır, on yıldır bu şekildedir ve çok sayıda veritabanını açığa çıkarmıştır.
Düzeltme tek bir dizedir ve edinilmeye değer alışkanlık da budur:
# wrong — reachable from the entire internet, whatever your firewall says
docker run -p 5432:5432 postgres
# right — bound to loopback, reachable only through an SSH tunnel or a proxy
docker run -p 127.0.0.1:5432:5432 postgresSon olarak, dışarıdan bir görüş alın. Sunucudan yapılan bir port taraması size çekirdeğin ne düşündüğünü söyler; başka bir yerden yapılan bir tarama ise size dünyanın ne gördüğünü söyler, ki önemli olan tek sayı da budur. nmap -Pn -p- <your-ip> komutunu makineden değil dizüstü bilgisayarınızdan çalıştırın ve sonucu beklediğiniz listeyle karşılaştırın.
Otomatik güncellemeler: açın ve gerçekten uygulayın
Küçük sunucuların ele geçirilmesine yol açan pencere, zero-day değildir. Çalışan bir proof-of-concept'le birlikte bir CVE'nin kamuya açıklanmasıyla sizin bir sonraki girişiniz arasındaki dört haftadır. Saldırı araçları yeni bir uzaktan açığı günler içinde özümser; “sırası gelince” yamalayacağınız bir makine bu aralığın tamamı boyunca açıkta kalır ve dürüst her operatör bu aralığın gerçekte ne kadar uzun olduğunu bilir.
Otomatik güncellemelere yönelik itiraz, bir şeylerin bozulması korkusudur ve bunu ciddiye almakta fayda var — ardından kapsamını daraltmakta. Otomasyonu, bakımcıların yeni upstream sürümleri göndermek yerine düzeltmeleri paketlenmiş sürüme geri taşıdığı (backport) dağıtımınızın security bölümüyle sınırlayın. openssl'e yapılan bir Debian güvenlik güncellemesi, zaten çalıştırdığınız sürümün yamalı bir derlemesidir; davranışını değiştirme riski, uzaktan bir açığı bir ay boyunca açık bırakma riskinden çok daha küçüktür. Özellik yükseltmeleri ise ait oldukları yerde, elle yapılan işlemler olarak kalır.
İnsanların atladığı kısım, yeniden başlatmadır. Diskteki yamalı bir libssl, başlangıçta eski olanı belleğe eşlemiş süreç için hiçbir şey ifade etmez ve bir çekirdek güncellemesi, siz onunla yeniden başlatana kadar hiçbir işe yaramaz. Ya seçtiğiniz bir zaman aralığında gözetimsiz bir yeniden başlatmayı kabul edin ya da needrestart'ı kurup hangi servislerin silinmiş kütüphanelere karşı çalıştığını size söylemesine izin verin — ama ikisinden birini yapın. uptime 340 gün gösterirken “otomatik güncellemeler açık” demek rahatlatıcı bir yanılsamadır ve gördüğümüz en yaygın yanılsama da budur.
fail2ban, CrowdSec, ya da hiçbiri
fail2ban günlüklerinizi okur, bir adresten gelen tekrarlanan başarısızlıkları fark eder ve o adresi bir süreliğine yasaklar. CrowdSec da aynısını yapar ve kararları katılımcılardan oluşan bir ağ genelinde paylaşır; böylece başka bir yerde kötü davranmış bir adresi o size ulaşmadan önce engelleyebilirsiniz. İkisi de iyi yazılımdır. Ama sadece anahtarla çalışan bir SSH sunucusunda ikisi de çoğu insanın sandığı şeyi yapmaz.
PasswordAuthentication, no olduğunda bir SSH kaba kuvvet saldırısı başarılı olamaz. “Başarılı olması olası değildir” değil — ortada bir kod yolu yoktur. Bu yüzden beş başarısızlıktan sonra bir adresi yasaklamak hiçbir şeyi önlemez; sadece günlük hacmini ve önemsiz miktarda CPU'yu azaltır. Bu gerçek bir faydadır, sadece bir güvenlik faydası değildir ve bu değiş tokuş bedava da değildir: yanlış günlüğü izleyen kötü yazılmış bir jail, saldırganları dışarıda bırakmaktan çok daha fazla yöneticiyi kendi sunucularının dışında bırakmıştır.
Bu araçların gerçekten yerini bulduğu yer, bir katman yukarısı, gerçekten dışarı açtığınız servislerdir: bir giriş formu, bir WordPress admin paneli, hız sınırlı bir API, SMTP AUTH kullanan bir posta sunucusu. Bunlar parola kabul eder, kaba kuvvetle kırılabilir ve bir yasaklama listesi tam olarak doğru önlemdir. Dolayısıyla kararımız dar ve nettir. SSH jail'ini atlayın. CrowdSec veya fail2ban'ı parola alanı olan şeyin önüne koyun. Ve hangisini seçerseniz seçin, önce kendi yönetim adresinizi beyaz listeye alın — ignoreip, aksi halde yanlış nedenlerle hatırlayacağınız akşam için vardır.
Makineye, değiştiğinde size söyletmek
Önleme, bir saat içinde yapabileceğiniz şeydir. Tespit ise size o saatin yeterli olmadığını söyleyen şeydir. Karmaşık olması gerekmez; tek bir sunucuda üç ucuz önlem işin çoğunu kapsar.
Günlükleri saklayın. Birçok imajda journal, /run içinde yaşar ve yeniden başlatmada buharlaşır; bu da bir olayın kaydının, onu izleyen yeniden başlatmada kaybolması demektir. /var/log/journal'ı oluşturmak tek satırlık bir düzeltmedir ve bu bölümdeki en değerli şeydir.
Girişlerden haberdar olun. Her oturum başlangıcında logger'ı tetikleyen /etc/ssh/sshrc içindeki bir satır hiçbir şeye mal olmaz ve size sshd'nin kendi gevezeliğinden ayrı, temiz, grep'lenebilir bir kayıt verir. İnsanları yakalayan bir uyarı var: kullanıcının kendi ~/.ssh/rc dosyası varsa sshd, /etc/ssh/sshrc yerine onu çalıştırır; yani sistem geneli dosya, tam olarak özelleştirilmiş bir dotfile'a sahip olma ihtimali en yüksek hesap için atlanır. Gölgelenemeyecek bir hook'a ihtiyacınız varsa bunun yerine pam_exec kullanın.
Dosya sisteminin ilk günde nasıl göründüğünü bilin. AIDE, ikili dosyalarınızın, kütüphanelerinizin ve unit dosyalarınızın hash'lerini kaydeder ve o zamandan beri neyin değiştiğini raporlar. Buradaki sorun temel bir sorundur ve genellikle göz ardı edilir: izlediği makinede saklanan bir veritabanı, makineyi ele geçiren kişi tarafından yeniden oluşturulabilir ve bundan sonra kontrol sonsuza kadar “değişiklik yok” raporlar. Veritabanını kutunun dışına kopyalayın, ya da en azından hash'ini başka bir yerde kaydedin; ancak o zaman araç yirmi dakikasına değer hale gelir. Yerinde bırakıldığında sadece bir teselli battaniyesidir.
Genel ilke, tek başına belirtilmeye değer: güvenemeyeceğiniz günlük, ele geçirilmiş makinedeki günlüktür. Gerçekten güvenmeyi düşündüğünüz her şeyin — bir journal, bir bütünlük veritabanı, bir yedek — aynı saldırganın kontrol etmediği bir yerde bir kopyası olmalıdır. Başka bir yargı bölgesindeki ikinci, küçük bir sunucu buna meşru bir cevaptır ve beş dolarlık biri bile yeterlidir.
Bunun yapmadığı şeyler
Yukarıdakilerin tamamı çevre güvenliği çalışmasıdır ve kilitli bir ön kapıyı bir kasayla karıştırmamanız için sınırı net bir şekilde belirtmekte fayda var.
Çalışan bir makinedeki veriyi korumaz. Sertleştirilmiş bir çekirdek ve kapalı bir güvenlik duvarı, hipervizör erişimi olan biri için ve makine açıkken RAM'in içeriği için önemsizdir. Derdiniz sunucu kapalıyken, el konulmuşken ya da hizmet dışı bırakılmışken diskse, bu disk şifrelemedir ve farklı bir başarısızlık moduna sahip farklı bir prosedürdür — bkz. LUKS ile VPS diskini şifreleme.
Sizi anonim yapmaz. Bir sunucu kusursuzca sertleştirilmiş olabilir ve yine de bir WHOIS kaydı, yeniden kullanılmış bir SSH anahtarı, bir analitik etiketi, evden bir sıçrama noktası olmadan bağlanan bir SSH istemcisi ya da iki kimliği birbirine bağlayan bir sertifika aracılığıyla kime ait olduğunu ilan edebilir. Monero ile ödeme yapıp ardından kendi adresinizden giriş yapmak, o ödemeyi boşa çıkarır. Bu başarısızlık modunun kendi sayfası var: sizi deşifre eden hatalar.
Uygulamanızı düzeltmez. Bir SQL injection, kimlik doğrulaması olmayan bir admin endpoint'i ya da içinde backdoor bulunan bir bağımlılık, sshd ayarlarınızı umursamaz. İyi yönetilen sunucuların çoğu ele geçirilme vakası, bilerek ve isteyerek açtığınız, yazdığınız veya kurduğunuz bir servise ait porttan gelir.
Bir yedek değildir. Fidye yazılımı, değişkeni boş kalmış bir rm -rf ve başarısız bir yükseltme hepsi aynı şekilde biter. Bir kopya alın, başka bir yere koyun ve ihtiyacınız olmadan önce bir kez ondan geri yükleyin — başka bir sunucuya taşınmayı atlatılabilir kılan aynı disiplin, kötü geçen bir Salı gününü de atlatılabilir kılar.
Bunların hiçbiri o saate karşı bir argüman değildir. Bu, o saatin size tam olarak ne kazandırdığını bilmeniz gerektiğine dair bir argümandır.
- Bir anahtarla devreye alın, asla bir parolayla değil
Anahtar çiftini kendi makinenizde oluşturun ve ortak yarısını devreye alma formuna yapıştırın; imaj bunu kuracak ve kaybedecek bir root parolanız hiç olmayacak.
cloud-initolarak işaretlenmiş bir imajdan devreye alıyorsanız, ilk saatin yapılandırmasının tamamını bunun yerine user-data olarak geçebilirsiniz — 64 KiB'a kadar — ve makine zaten sertleştirilmiş şekilde ayağa kalkar.# on your laptop, not on the server ssh-keygen -t ed25519 -a 100 -C "$(whoami)@laptop-cvh" cat ~/.ssh/id_ed25519.pub # paste this into the deploy formAraç zincirinizdeki bir şey onu reddetmediği sürece ed25519 kullanın; reddederse 4096 bit RSA da uygundur. Özel anahtarı bir parolayla koruyun ve bir agent'a yükleyin; dizüstü bilgisayarda parolasız bir anahtar dosyası, monitöre yazılmış bir parola gibidir. Aynı anahtar seti kurtarma moduna da eklenir; 4. adımı kurtarılabilir kılan da budur.
- Herhangi bir şeye dokunmadan önce ikinci oturumu açın
Bu isteğe bağlı değildir ve bu paranoya da değildir. Buradan itibaren, üzerinden bağlandığınız daemon'ı ve ona ulaşmanızı sağlayan güvenlik duvarını değiştireceksiniz. Makineye geri dönüş halatı olarak bir oturumu açık ve boşta tutun, her değişikliği ayrı bir oturumda yapın. Bir değişiklik yanlış giderse, açık oturum hâlâ kimlik doğrulamasından geçmiştir ve onu geri alabilir; yeni bir bağlantı ise reddedilir.
# terminal A — the rope. Log in and leave it alone. ssh -i ~/.ssh/id_ed25519 root@<server-ip> # terminal B — where every command below runs. ssh -i ~/.ssh/id_ed25519 root@<server-ip>Her değişikliği üçüncü bir bağlantı açarak test edin, asla üzerinde çalıştığınız bağlantıyı yeniden bağlayarak değil. Üçüncü bağlantı başarısız olursa, yine de çalışan iki kabuğunuz olur ve elinizde bir kriz değil, bir sorun kalır.
- Gerçekte kullanacağınız hesabı oluşturun
SSH üzerinden root, tam olarak bir saatliğine kullanışlıdır. Ondan sonra, sudo yetkisine sahip adlandırılmış bir hesap size bir denetim izi verir, yanlış yazılmış bir komutun tam yetkiyle çalışmasına karşı sizi korur ve makineyi devre dışı bırakmadan ele geçirilmiş bir hesabı devre dışı bırakmanızı sağlar.
adduser --disabled-password --gecos "" deploy install -d -m 0700 -o deploy -g deploy /home/deploy/.ssh cp /root/.ssh/authorized_keys /home/deploy/.ssh/authorized_keys chown deploy:deploy /home/deploy/.ssh/authorized_keys chmod 0600 /home/deploy/.ssh/authorized_keys usermod -aG sudo deploy # a long random password, stored in your manager, used only by sudo passwd deployBu parolayı ayarlayın. Parolası hiç ayarlanmamış bir sudo hesabı sudo'yu kullanamaz ve bunu root girişini devre dışı bıraktıktan sonra fark etmek, her dosya doğruyken kendinizi dışarıda bırakmanın klasik yoludur. Devam etmeden önce doğrulayın: yeni bir terminalden
ssh deploy@<server-ip>, ardındansudo -v. İkisi de çalışmalıdır. - SSH drop-in'ini yazın, ardından daemon'a ne okuduğunu sorun
Yukarıdaki sıralama kuralına göre, erken sıralanan numaralı bir drop-in, cloud imajının getirdiği her şeyi geride bırakır. Onu yazın, sözdizimini doğrulayın, etkin yapılandırmayı geri okuyun ve ancak ondan sonra reload edin.
cat > /etc/ssh/sshd_config.d/10-hardening.conf <<'EOF' PermitRootLogin no PasswordAuthentication no KbdInteractiveAuthentication no PubkeyAuthentication yes AuthenticationMethods publickey PermitEmptyPasswords no AllowUsers deploy MaxAuthTries 3 LoginGraceTime 20 X11Forwarding no AllowAgentForwarding no AllowTcpForwarding no # remove this line if you use ssh -L / -D tunnels ClientAliveInterval 300 ClientAliveCountMax 2 EOF chmod 0644 /etc/ssh/sshd_config.d/10-hardening.conf sshd -t # silence means the syntax is valid sshd -T | grep -Ei '^(permitrootlogin|passwordauthentication|allowusers) ' systemctl reload sshO
sshd -Tçıktısını reload etmeden önce okuyun, sonra değil.permitrootlogin novepasswordauthentication noyazmalıdır. Yazmıyorsa, dosyanız daha erken sıralanan biri tarafından geçersiz kılınıyordur —ls /etc/ssh/sshd_config.d/yapın ve kendinizinkini daha düşük bir sıraya yeniden adlandırın. Şimdi üçüncü bir terminal açın vedeployolarak giriş yapın. Halatı ancak bu çalıştığında kapatın. - Varsayılan reddet bir güvenlik duvarı yükleyin
nftables her iki dağıtımla birlikte gelir ve iptables kural setinin yerini tek, okunabilir bir dosyayla alır. Kabul edilen portları gerçekte çalıştırdığınız servislere göre ayarlayın — aşağıdaki liste yalnızca SSH ve bir web sunucusu olduğunu varsayar, başka hiçbir şey değil.
apt install -y nftables cat > /etc/nftables.conf <<'EOF' #!/usr/sbin/nft -f flush ruleset table inet filter { chain input { type filter hook input priority filter; policy drop; ct state established,related accept ct state invalid drop iif lo accept # ICMP must live: dropping it blackholes path-MTU discovery. ip protocol icmp icmp type { echo-request, echo-reply, destination-unreachable, time-exceeded, parameter-problem } accept ip6 nexthdr icmpv6 accept tcp dport 22 ct state new accept tcp dport { 80, 443 } ct state new accept limit rate 5/minute burst 5 packets log prefix "nft-drop: " level info } chain forward { type filter hook forward priority filter; policy drop; } chain output { type filter hook output priority filter; policy accept; } } EOF nft -c -f /etc/nftables.conf # check before you commit to it systemctl enable --now nftables nft list ruleset | head -40Docker kuruluysa,
flush rulesetDocker'ın kurallarını da kaldırır: ardındansystemctl restart dockerçalıştırın ve konteynerlerinizin hâlâ yanıt verdiğini doğrulayın. Sonra, dizüstü bilgisayarınızdannmap -Pn -p- <server-ip>çalıştırın ve açık listenin, az önce izin verdiğiniz portlarla eşleştiğini kontrol edin — ne fazla, ne eksik. - Gözetimsiz güvenlik güncellemelerini açın
Sadece security bölümü, sürekli erteleyeceğiniz bir zaman yerine sizin seçtiğiniz bir yeniden başlatma penceresiyle. Kullanıcılarınız için sakin olan ve tam saat başı olmayan bir saat seçin, böylece herkesin cron'uyla çakışmazsınız.
apt install -y unattended-upgrades needrestart cat > /etc/apt/apt.conf.d/51-cvh-auto <<'EOF' // Debian. On Ubuntu, replace the two Origins-Pattern lines with: // "${distro_id}:${distro_codename}-security"; Unattended-Upgrade::Origins-Pattern { "origin=Debian,codename=${distro_codename}-security,label=Debian-Security"; "origin=Debian,codename=${distro_codename},label=Debian-Security"; }; Unattended-Upgrade::Automatic-Reboot "true"; Unattended-Upgrade::Automatic-Reboot-WithUsers "false"; Unattended-Upgrade::Automatic-Reboot-Time "04:17"; Unattended-Upgrade::Remove-Unused-Kernel-Packages "true"; APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1"; EOF unattended-upgrade --dry-run --debug | tail -25 systemctl status unattended-upgrades --no-pagerGözetimsiz bir yeniden başlatma gerçekten kabul edilemezse, bunu
"false"olarak ayarlayın veneedrestart -b'nin hangi servislerin silinmiş kütüphanelere karşı çalıştığını ve daha yeni bir çekirdeğin kurulu olup olmadığını raporlamasına izin verin — sonra buna göre hareket edin. Kabul edilemeyecek olan, ikisini de yapmamaktır. - Dinlemede olanı kapatın ve dışarıdan kontrol edin
Loopback dışında bir şeye bağlı olanları listeleyin, kullanmadıklarınızı kaldırın ve sonucu bu makine olmayan başka bir makineden doğrulayın.
ss -tulpn | grep -vE '127\.0\.0\.1|\[::1\]' # the usual leftovers on a base image systemctl disable --now rpcbind.socket rpcbind 2>/dev/null apt purge -y exim4-base exim4-config exim4-daemon-light 2>/dev/null apt autoremove --purge -y # what each running unit is allowed to reach systemd-analyze security --no-pager | head -20Çalışmaya devam etmesi gereken ama seyirciye ihtiyacı olmayan her şey için — bir veritabanı, bir önbellek, bir admin paneli, bir metrik exporter'ı — bunu kendi yapılandırmasında
127.0.0.1'e bağlayın ve bir SSH tüneli üzerinden erişin:ssh -L 5432:127.0.0.1:5432 deploy@<server-ip>. Bu, bir portu açıp servisin kendi kimlik doğrulamasının sağlam olmasını ummaktan kesinlikle daha iyidir ve varsayılan olarak başvurulacak örüntü budur. - Referans noktasını kaydedin ve alarmları kurun
Yalnızca bir şeylerin ters gittiği gün karşılığını veren on dakika — ki o gün, hiçbirini hafızanızdan yeniden kuramayacağınız gündür.
# persistent journal, so a reboot stops erasing the evidence mkdir -p /var/log/journal systemd-tmpfiles --create --prefix /var/log/journal systemctl restart systemd-journald # a clean, greppable line per SSH session cat > /etc/ssh/sshrc <<'EOF' logger -t ssh-login "user=$USER from=${SSH_CONNECTION%% *} tty=${SSH_TTY:-none}" EOF # file-integrity baseline — then get the database off the machine apt install -y aide aideinit mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db sha256sum /var/lib/aide/aide.db # copy this hash somewhere else last -n 20 ; lastb -n 20 # who got in, and who triedSon olarak, sunucunun dışında dört şeyi yazıya dökün:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pubkomutundan alınan SSH host anahtarı parmak izi, yukarıdaki AIDE hash'i, bilerek açtığınız portlar ve özel anahtarın nerede durduğu. O not, kötü bir sabahı bir soruşturma yerine bir kontrol listesine dönüştüren şeydir.
Önlemler, gerçekte size ne kazandırdıklarına göre sıralandı
| Önlem | Neyi durdurur | Neyi durdurmaz | Maliyet | Sonuç |
|---|---|---|---|---|
| Sadece anahtarla SSH (PasswordAuthentication no) | İnternetteki her kimlik bilgisi tahmin eden botu, kalıcı olarak ve yapısı gereği | Özel anahtarınızı elinde bulunduran birini ya da sshd'nin kendisindeki bir açığı | 5 dakika, tek seferlik | Tartışmaya kapalı |
| Varsayılan reddet güvenlik duvarı (nftables) | Dinlemede olduğunu unuttuğunuz servisleri ve daha sonra yanlışlıkla kurduğunuz her servisi | Bilerek açtığınız portlara yönelik saldırıları | 10 dakika, tek seferlik | Tartışmaya kapalı |
| Gözetimsiz güvenlik güncellemeleri | n-gün penceresini — herkese açık bir exploit ile bir sonraki girişiniz arasındaki haftaları | Zero-day'leri ve hiç planlamadığınız bir yeniden başlatma gerektiren her şeyi | 5 dakika artı bir yeniden başlatma penceresi | Tartışmaya kapalı |
| Root yerine sudo yetkili adlandırılmış kullanıcı | Tam yetkiyle çalışan yanlış yazılmış komutları ve nedensiz yere root olarak çalışan süreçleri | Zaten içeride olan birinin elindeki yerel bir yetki yükseltmeyi | 3 dakika | Değer |
| Dosya bütünlüğü referans noktası (AIDE) | Sistem ikili dosyalarında, kütüphanelerinde ve unit dosyalarında yapılan sessiz değişiklikleri | Veritabanı izlediği makinede kalırsa, hiçbir şeyi | 20 dakika artı kutu dışında depolama | Kutu önemliyse değer |
| SSH'yi port 22'den taşımak | Kimlik doğrulama günlüğü hacminizin kabaca yüzde 95'ini | Bir port taraması çalıştıran herkesi, ki önemli olan herkes budur | 2 dakika, artı portu unutacağınız akşam | İsteğe bağlı, sessiz günlükler için |
| sshd üzerinde fail2ban / CrowdSec | Tekrar suçluları ve sizde harcadıkları CPU'yu | Parola kimlik doğrulaması kapatıldıktan sonra hiçbir şeyi | 10 dakika, artı gerçek bir kilitlenme riski | SSH'de atlayın; uygulamanızda kullanın |
Yanıtlanmaya değer sorular
Devreye almadan ne kadar sonra tarama başlar?
Genellikle dakikalar içinde. İnternet genelindeki tarayıcılar tüm IPv4 uzayını kesintisiz tarar, bu yüzden yepyeni bir adrese, üzerinde ne çalıştığından bağımsız olarak bir sonraki geçişte ulaşılır. Makine ilk paketine yanıt verdiği andan itibaren yoklandığınızı varsayın — sertleştirmenin ilk hafta sonunda değil ilk saatte yapılmasının nedeni de budur.
Parola ile giriş devre dışıysa yine de fail2ban'a ihtiyacım var mı?
SSH'de hayır. PasswordAuthentication no ile kaba kuvvetin kazanabileceği bir kod yolu yoktur, bu yüzden beş başarısızlıktan sonra yasaklamak hiçbir şeyi önlemez — sadece günlük gürültüsünü azaltır, ki bunun da bir değeri vardır ama güvenlik değildir. Bu araçların gerçekten ait olduğu yer, gerçekten parola kabul eden her şeyin önüdür: bir web giriş formu, bir admin paneli, SMTP AUTH. Birini kurarsanız, önce kendi adresinizi beyaz listeye alın.
ufw mü, firewalld mı, yoksa nftables mı?
Varsayılan politika drop olduğu ve neyi devreye aldığınızı anladığınız sürece hangisi olursa olsun. ufw en kullanıcı dostu olanıdır ve güncel Debian ile Ubuntu'da altta nftables kuralları yazar. Sade nftables, diff'leyebileceğiniz ve versiyon kontrolüne alabileceğiniz tek, okunabilir bir dosyadır; onu kullanmamızın nedeni de budur. Seçim, varsayılan politikadan çok daha az önemlidir — ve üçünden hiçbiri, Docker'ın hepsinin altından port yayınladığı gerçeğini değiştirmez.
SSH'yi port 22'den taşımalı mıyım?
Sadece daha sessiz günlükler için. Yetkin hiçbir saldırganı durdurmaz — tam bir tarama saniyeler sürer ve banner servisi ele verir. Ama kimlik doğrulama günlüğünüzdeki gürültünün çoğunu gerçekten kaldırır, bu da gerçek anomalileri görünür kılar. Bunu bir önlem olarak değil, günlük hijyeni olarak görün ve değiştirmeden önce sshd'nizin socket ile etkinleştirilip etkinleştirilmediğini kontrol edin: Ubuntu 24.04'te sshd_config içindeki Port direktifi yok sayılır ve port ssh.socket'e aittir.
Otomatik güncellemeler sitemi sabahın dördünde bozar mı?
Security bölümüyle sınırlandırıldığında, çok nadiren. O paketler, yeni upstream sürümleri değil, zaten çalıştırdığınız sürüme geri taşınmış (backport) düzeltmelerdir. Gerçekçi risk yama değil, yeniden başlatmadır — bu yüzden pencereyi kendiniz seçin, biri giriş yapmışken beklemesi için Automatic-Reboot-WithUsers'ı false yapın ve servis gerçekten gözetimsiz yeniden başlayamıyorsa, needrestart -b'yi bir programa bağlayıp raporladığına göre hareket edin. Savunulamayacak tek pozisyon, yıllarla ölçülen bir uptime'la birlikte otomatik güncellemelerdir.
Kendimi dışarıda bıraktım. Ne seçeneklerim var?
Sunucuyu panelden kurtarma moduna önyükleyin. Bu, hesabınızla aynı SSH anahtarlarına sahip ve diskiniz /dev/vda'da bağlanmamış halde, RAM içinde bir Alpine ortamı başlatır; böylece onu bağlayabilir, sshd drop-in'ini veya güvenlik duvarı dosyasını düzeltebilir, ardından bağlantısını kesip yeniden başlatabilirsiniz. Kurtarma önyüklemesinin kendisi diskteki hiçbir şeye dokunmaz. Kurtarma host anahtarının parmak izi normal olanınızdan farklıdır — bu beklenen bir durumdur, bir müdahale değil.
Bunun yerine Lynis veya bir CIS sertleştirme betiği çalıştırmak iyi bir fikir mi?
Bir denetim olarak evet; bir yerine geçen olarak hayır. Lynis, gerçekten faydalı bir ikinci görüştür ve bu sayfanın bahsetmediği şeyleri bulacaktır. Otomatik CIS düzeltme betikleri farklı bir öneridir: kurumsal bir workstation filosu için tasarlanmış yüzlerce değişikliği uygular, bunlardan birkaçı bir sunucuyu haftalar sonra izi sürülmesi zor şekillerde bozar. Önce saati elle yapın, böylece makinenizin ne yaptığını anlarsınız, sonra bir denetleyici çalıştırın ve bulgularını teker teker okuyun.
Sertleştirme, sunucumu anonim yapar mı?
Hayır, ve ikisini birbirine karıştırmak yaygın ve maliyetli bir hatadır. Sertleştirme kimin girebileceğini kontrol eder; anonimlik ise kimin bunun size ait olduğunu anlayabileceğini kontrol eder. Mükemmelce kilitlenmiş bir sunucu bile bir WHOIS kaydı, yeniden kullanılmış bir SSH anahtarı, bir analitik etiketi ya da ev adresinizden yapılan bir admin girişi üzerinden sahipliğini sızdırabilir. Monero ile ödeme yapıp ardından doğrudan kendi bağlantınızdan bağlanmak, ödemeyi tamamen boşa çıkarır — bu konu sizi deşifre eden hatalar yazısında ele alınıyor.
Keep exploring
LUKS ile VPS diskini şifreleme
İşin diğer yarısı: bu sayfa ağı kapatır, o sayfa ise makine kapalıyken diski korur.
Sizi deşifre eden anonimlik hataları
Kusursuzca sertleştirilmiş ama yine de kime ait olduğunu herkese söyleyen bir sunucu. Bu hatalar teknik değil, davranışsaldır.
WireGuard VPS kurulumu
Az önce kurduğunuz güvenlik duvarının arkasına koymaya değer ilk servis — ve localhost'a bağladığınız her şeye açılan özel bir kapı.
Deploy your offshore server.
Bir bölge seçin. Bir plan seçin. Anahtar yapıştırın. Ödeyin. Sonraki 47 saniye bizden.