- Bir SSH oturumunda tek bir tuş vuruşunda yüzlerce paketin gönderildiği durum fark edildi ve nedeni iz sürülerek bulundu
tcpdump analizi, paketlerin çoğunun 36 baytlık tekrarlayan mesajlardan oluştuğunu ve yaklaşık 20 ms aralıklarla ortaya çıktığını gösterdi
- Nedenin, 2023’te SSH’ye eklenen “tuş vuruşu zamanlaması bulanıklaştırma (keystroke timing obfuscation)” özelliği olduğu anlaşıldı; bu özellik kullanıcının giriş zamanlamasını gizlemek için çok sayıda “chaff” paketi (SSH2_MSG_PING) gönderiyor
- Bu özellik devre dışı bırakıldığında veya sunucu
[email protected] uzantısını duyurmayacak şekilde değiştirildiğinde CPU kullanımı ve bant genişliği yarıdan fazla azalıyor
- Bu, SSH’nin güvenlik özelliğinin gerçek zamanlı performansın kritik olduğu uygulamalarda (ör. oyunlar) büyük bir yük oluşturabileceğini gösteren bir örnek
Sorunun fark edilmesi
- SSH üzerinden çalışan yüksek performanslı bir oyunun TUI’si test edilirken, tek bir tuş vuruşunda bile 270 paket oluştuğu görüldü
tcpdump sonucunda bunun %66’sının 36 baytlık mesajlar, %33’ünün TCP ACK, kalanının ise az miktarda diğer veriler olduğu görüldü
- Ortalama 90 paket/sn ile yaklaşık 11 ms aralıklarla veri iletimi vardı
- Test sırasında sunucu yanlışlıkla yalnızca “your screen is too small” mesajı gönderecek şekilde ayarlanmıştı; bu durumda CPU ve bant genişliği kullanımı yarıya düştü
- Oyun verisi gönderilmediğinden CPU kullanımının %0’a yakın olması gerekirken hâlâ yaklaşık %50 seviyesinde kaldı
- Bu da SSH’nin kendisindeki iletişim ek yükü ihtimalini gündeme getirdi
İnceleme süreci
tcpdump kullanılarak normal çalışma ile hata durumundaki SSH trafiği karşılaştırıldı
- Hata durumunda da 36 baytlık paketlerin 20 ms aralıklarla sürekli oluştuğu görüldü
- macOS’in varsayılan SSH istemcisinde de aynı desen doğrulandı
- Claude Code ile pcap dosyası analiz edildiğinde
- Toplam 413.703 paketin %66’sının 36 bayt, %34’ünün ise 0 baytlık ACK olduğu görüldü
- Paketleri esas olarak SSH istemcisinin ürettiği anlaşıldı
Kök neden
Çözüm yöntemi
- İstemci tarafında
ObscureKeystrokeTiming=no seçeneğiyle özellik devre dışı bırakılabiliyor
- Uygulandıktan sonra CPU kullanımı ve bant genişliği belirgin biçimde düştü, veri iletimi normal kaldı
- Sunucu tarafındaki çözüm için Go’nun SSH kütüphanesinde
[email protected] uzantısının duyurulması kaldırıldı
- İlgili commit geri alındıktan sonra yapılan testte
- CPU kullanımı %29,9 → %11,6,
sistem çağrıları 3.10s → 0.66s,
şifreleme işlemleri 1.6s → 0.11s,
bant genişliği 6.5Mbit/s → 3Mbit/s
- Performans %50’den fazla iyileşti
LLM ile hata ayıklama deneyimi
- Claude Code kullanılarak
tcpdump ve tshark analizi otomatikleştirildi ve sorunun nedeni hızla daraltıldı
- Komutların çalıştırılma süreci gerçek zamanlı izlenerek zihinsel modelin korunması mümkün oldu
- ChatGPT’nin SSH davranışını yanlışlıkla “normal” olarak değerlendirmesi gibi modeller arası farklar da gözlendi
- LLM’ler sorun çözme sürecinin tamamının yerini almasa da, yardımcı analiz aracı olarak yüksek verimlilik sundu
- İnsan muhakemesi ile LLM analizinin birleştirilmesi sayesinde karmaşık ağ performansı sorunlarının çözüldüğü bir örnek ortaya çıktı
1 yorum
Hacker News görüşleri
Go'nun crypto kütüphanesini fork etmek biraz ürkütücü geliyor
Küçük yamamı güvenli biçimde nasıl koruyabileceğimi düşünüyorum
Aslında böyle bir özelliğin ssh kütüphanesinin bir seçeneği olarak upstream edilmesi gerektiğini düşünüyorum
Güvenilmeyen ortamlarda chaff (gürültü) paketleri göndermek varsayılan olarak iyi, ama bant genişliğinden tasarruf etmek isteyeceğiniz pek çok durum da var
Sunucunun istemciye “gerek yok” sinyali gönderebildiği bir seçenek eklemek ve istemcinin bunu kabul etmesi ya da uyarı vermesi doğru çözüm olur
Yalnızca TTY oturumlarında geçerli ve istemci bunu devre dışı bırakabiliyor
Ancak bu vakada istisnai olan şey, sunucunun bunun önceden önemsiz bir bağlantı olduğunu bilmesiydi
Çoğu durumda istemci ObscureKeystrokeTiming ayarının korunmasını bekler
crypto kütüphanesi çok güçlü görüşlere sahip bir kod tabanı; öyle ki TLS cipher suite sırasını bile değiştirmenize izin vermiyor
Bu, SSH'in oldukça özel bir kullanım senaryosu gibi görünüyor
Fazla geniş açılırsa “ayarla ve unut” durumuna dönüşüp güvenliği zayıflatabilir
1200bps modemlerle haberleştiğimiz zamanlar da oldu, 56K modemler ise fiilen abartıydı
1994 civarında Birleşik Krallık'ta bir askerî kolejde çalışırken WWW ile ilk kez karşılaştım ve o zaman “pek iyi değilmiş” diye düşünmüştüm
Geriye dönüp bakınca zamanın değişimi gerçekten şaşırtıcı
Bu obfuscation özelliğini ilk kez duyuyorum, ilginçmiş
ssh'in davranışını debug ederken “None” cipher'ını yamalayıp paket içeriğini doğrudan görmek de iyi bir yöntem
Güvenliğin önemli olmadığı, performansın önemli olduğu bir terminal oyunu için doğrudan telnet kullanmak da düşünülebilir
SSH'in böyle bir şey yaptığını bilmiyordum
Varsayılan olarak açık olmasını anlıyorum ama benim ortamımda kapatmak daha doğru gibi
Bu yüzden
ObscureKeystrokeTiming=noayarlamayı düşünüyorum. Bunu yapmamam için bir neden var mı?(1) İnsanların ne zaman sır girdiğini her zaman ayırt etmek zordur ve tüm etkinlik örüntü analizi ile analiz edilebilir
(2) Bu, üniversite laboratuvarı düzeyinde bile yapılabilen bir saldırıdır — USENIX makalesi ve araştırma örneği
(3) İnternet trafiğine video hâkimken birkaç bayt tuş vuruşu verisi kazanmak için güvenlikten vazgeçmenin anlamı yok
Bir saldırgan tuş vuruşu zamanlamasını analiz ederek komutları ve şifrelenmiş parola desenini tahmin edebilir
Elbette oturum anahtarı her seferinde değiştiği için şifre çözmek zor olur ama ihtimal var
Ben de çoğu parolayı parola yöneticisinden kopyalayıp yapıştırıyorum
Çoğu insan SSH'in güvenlik özelliklerini kapatıp da sorun yaşamadığını düşünür, ama bu sadece şanslı oldukları anlamına gelir
Gerçekten performans gerekiyorsa Telnet, gerçekten güvenlik gerekiyorsa ContainerSSH + OAuth2 kombinasyonu daha iyi olur
2004'te SSH oturumlarında tuş vuruşları arasındaki gecikmeyi analiz ederek komut tahmini üzerine araştırma yapmıştım
O dönemki analiz notları
2023 yaması sonunda bu sorunu çözmüş oldu
Sunum metni
Zaman gerçekten çok hızlı geçiyor
Claude'un debug sürecinde gerçekten yardımcı olup olmadığından emin değilim
Yazar zaten yönü biliyordu, Claude ise sadece onaylamış gibi geldi
Claude'un “Holy Cow!” gibi şeyler söylemesi biraz sinir bozucu
Ben de Claude ile sistem davranışlarını debug ederken, doğrudan bir cevap vermese bile anlayışı netleştirmeye ve motivasyonu korumaya yardımcı olduğunu görüyorum
Rubber Duck Debugging wiki
Yazarın “holy cow” tepkisini sevip bloga koyduğuna bakılırsa Claude ortamın havasını iyi okumuş
TCP_CORK kullanırsanız gecikme eklemeden paket sayısını azaltabilirsiniz
TCP_NODELAY'i kapatmak da bir yöntem ama bunun bedeli artan gecikme olur
Soketi cork edince çekirdek veriyi tamponlar, uncork edilince ya da MSS'e ulaşınca gönderir
Yani paketleri gruplayarak gönderme yaklaşımıdır
Referans
Ping'i yine alırım ama pong gönderme sayısını azaltabilirim gibi
TCP_NODELAY'i daha önce kullandım ama gecikmeyi artırdığı için oyunum için uygun değildi
Önceki HN gönderisi
Obfuscation amacı gereği coalescing yapmak mümkün görünmüyor
“The smoking gun!” ifadesi komikti
Ana dili İngilizce olmayan biri olarak bunu Claude'un sık kullanması sayesinde ilk kez öğrendim
Artık gerçekten yaygın bir kalıp hâline geliyor
LLM'e bu kadar bağımlı olunması üzücü
Bu muhtemelen sadece Wireshark ile paket yakalamaya bakılarak daha hızlı çözülebilirdi
SSH dissector'ı oldukça olgun
tcpdump ile tek bir tuş vuruşunu yakalasanız bile yüzlerce şifreli paket çıkıyor
Sonuçta LLM sayesinde yazar ilginç bir şey öğrenip paylaşmış, yani bunun bir değeri var
NEWKEYS mesajından sonra ayrıştırma yapamıyor ve
noneşifrelemesine yamalasanız bile akışı tamamen yorumlayamıyorGeliştirme payı var
Araçları kullanarak öğrenmenin de yeterince değeri var
Basit bir paket yakalama ile anlamlı bilgi elde etmek zor
Bunun neden kötü bir şey sayıldığını anlamıyorum
2023'te SSH, tuş vuruşu zamanlamasını gizleme özelliği ekledi
Karakterler yazma hızından tahmin edilebildiği için SSH araya chaff paketleri karıştırarak saldırganın ayırt etmesini zorlaştırıyor
Ama bu yanlış bir yaklaşım gibi görünüyor
Gerçekten istenirse tüm tuş vuruşları 50ms aralıklarla gönderilebilir
Mevcut uygulama 20ms birimlerle gruplayıp, bir süre giriş olmazsa chaff göndermeyi durduruyor
SSH'in özü güvenlik ama güvenlik gerekmiyorsa neden SSH kullandığınız sorgulanabilir
Örneğin netcat (nc) çoğu platformda varsayılan olarak yüklü geliyor
SSH'te performans, kullanım kolaylığı gibi başka değerlendirmeler de var
Yazar sadece tuş vuruşu gizleme (privacy) özelliğini gereksiz bulduğunu söylüyor
Şifreleme ya da bütünlük güvencesini yine de korumak isteyebilir
Yani SSH'in çoğu güvenlik özelliğini bırakıp sadece bir kısmını kapatma tercihinden söz ediyoruz