Bir altyapı büyüdükçe, tek bir sunucuya SSH ile bağlanmak yerine on, yirmi, bazen yüzlerce makineyi yönetmeye başlarsınız. Bu makinelerin çoğu veritabanı sunucusu, uygulama sunucusu ya da iç servis olur ve bunların internete doğrudan açık olmasını istemezsiniz. Peki her birine ayrı ayrı bağlanmak yerine, hepsine güvenli ve denetlenebilir tek bir kapıdan girmenin bir yolu var mı? İşte bu sorunun cevabı bastion sunucu, yani jump host mimarisidir. Bastion, iç ağa açılan tek ve iyi korunan bir geçit kapısıdır; dışarıdan sadece bu kapıya bağlanabilir, arkasındaki tüm sunuculara ise bu kapının içinden atlarsınız.
Bu rehberde bastion mimarisinin neden bu kadar güvenli olduğunu, ssh -J bayrağı ile ve ~/.ssh/config dosyasındaki ProxyJump yönergesiyle nasıl atlama yapacağınızı, birden fazla sunucu üzerinden geçen çok atlamalı zincirleri nasıl kuracağınızı adım adım göreceksiniz. Ayrıca agent forwarding'in cazip ama tehlikeli tarafına da değineceğiz; çünkü yanlış yapılandırılmış bir bastion, güvenlik kazandırmak yerine tüm ağınızı tek noktadan ele geçirilebilir hale getirebilir. Amacımız, kıdemli bir sistem yöneticisinin bir ekip arkadaşına anlattığı gibi, hem çalışan komutlar hem de arkasındaki mantık ile konuyu netleştirmek.
Bastion Sunucu Nedir ve Neden Kullanılır#
Bastion sunucu, iç ağınıza dışarıdan erişim için ayrılmış, sadece bu iş için var olan sade bir Linux makinesidir. Üzerinde web sunucusu, veritabanı ya da uygulama çalışmaz; tek görevi SSH bağlantılarını karşılayıp yetkili kullanıcıların arkadaki özel ağa geçmesine izin vermektir. "Bastion" kelimesi kale burcu anlamına gelir ve bu isim tesadüf değildir: kalenin tek kapısı gibi, tüm giriş trafiği bu makineden geçer.
Bu mimarinin en büyük kazancı saldırı yüzeyini daraltmasıdır. İç ağdaki veritabanı sunucunuzun 22 numaralı portu internete açık olsaydı, dünyanın her yerinden gelen otomatik tarama botları ona kaba kuvvet denemesi yapardı. Bastion modelinde ise sadece tek bir makinenin portu dışarı bakar. Onu sertleştirir, sıkı izler, güncel tutarsınız; arkadaki onlarca sunucu ise özel IP aralığında, dış dünyaya tamamen kapalı yaşar.
İkinci büyük kazanç denetimdir. Herkes içeri girmek için bastion'dan geçmek zorunda olduğundan, "kim, ne zaman, hangi sunucuya bağlandı" sorusunun cevabı tek bir yerde toplanır. Kullanıcı bir ekibi terk ettiğinde tek bir makineden anahtarını kaldırmanız yeterli olur. Aşağıdaki tablo, klasik doğrudan erişim ile bastion modelini karşılaştırıyor.
| Ölçüt | Doğrudan Erişim | Bastion / Jump Host |
|---|---|---|
| İnternete açık SSH portu | Her sunucuda | Sadece bastion'da |
| Saldırı yüzeyi | Geniş | Tek makineye indirgenmiş |
| Erişim kaydı | Dağınık, sunucu başına | Merkezî, tek noktada |
| Kullanıcı iptali | Her sunucudan tek tek | Tek noktadan |
| Yönetim maliyeti | Yüksek | Düşük |
Bastion mantığı, SSH güvenliğinin genel prensipleriyle iç içedir; anahtar tabanlı kimlik doğrulama ve sağlam yapılandırma temelini pekiştirmek için SSH bağlantısı ve güvenliği rehberimizi de yanınıza almanızı öneririm.
ssh -J ile Hızlı Atlama#
En temel atlama yöntemi -J (jump) bayrağıdır ve OpenSSH 7.3 ve sonrasında gelir. Mantığı basittir: "önce şu bastion'a git, oradan asıl hedefe bağlan." Diyelim ki bastion sunucunuz bastion.ornek.com, ulaşmak istediğiniz iç sunucu ise 10.0.1.20 özel IP'sinde. Şu tek komut işi görür:
ssh -J [email protected] [email protected]
Burada önemli bir ayrıntı var: 10.0.1.20 adresi sizin bilgisayarınızdan çözülmez veya erişilemez, ama bastion'ın bakış açısından erişilebilir. SSH, hedef adresi bastion üzerinden çözer ve bağlantıyı orada kurar. Yani iç ağın adresleme mantığını hedef makine tarafından değerlendirir. Bu, VPN kurmadan özel ağa el uzatmanın en zarif yollarından biridir.
Farklı kullanıcı adları ve portlar da mümkündür. Bastion'a yonetici olarak 2222 portundan, hedefe ise deploy olarak standart porttan bağlanmak isterseniz:
ssh -J [email protected]:2222 [email protected]
-J bayrağının güzelliği, ara bağlantıyı şeffaf yönetmesidir. Eski günlerde insanlar bunun için ssh -t bastion ssh hedef gibi iç içe komutlar ya da netcat tabanlı ProxyCommand numaraları kullanırdı. Bu yöntemlerde anahtarınız bastion'a kopyalanmak zorunda kalır veya terminal içinde terminal açılırdı. -J ile bağlantı uçtan uca sizin makinenizden hedefe şifreli tünel içinde kurulur; bastion sadece trafiği taşır, anahtarınızı görmez.
~/.ssh/config ile ProxyJump Kullanımı#
Her seferinde uzun -J komutu yazmak yorucu olur. Asıl güç, ~/.ssh/config dosyasına yazacağınız ProxyJump yönergesindedir. Bu dosya bir kez düzenlendiğinde, ssh db1 gibi kısa bir isimle tüm atlama zinciri otomatik çalışır. Örnek bir yapılandırma:
# ~/.ssh/config
Host bastion
HostName bastion.ornek.com
User yonetici
Port 22
IdentityFile ~/.ssh/id_ed25519
Host db1
HostName 10.0.1.20
User deploy
ProxyJump bastion
Host app1
HostName 10.0.1.30
User deploy
ProxyJump bastion
Bu dosyayı kaydettikten sonra artık tek yapmanız gereken şudur:
ssh db1
SSH arka planda önce bastion tanımını okur, oraya bağlanır, sonra 10.0.1.20 adresine atlar. Kullanıcı, port ve anahtar bilgileri her host için ayrı tanımlıdır, yani karışıklık olmaz. Bu yaklaşımın bir başka güzel yanı, config dosyasını ekip içinde paylaşabilmenizdir: yeni bir ekip üyesi hazır config ile gelir ve iç ağın topolojisini ezberlemek zorunda kalmaz.
ProxyJump yönergesi joker karakterlerle daha da ölçeklenir. Diyelim ki tüm iç sunucularınızın adı 10.0.1. ile başlıyor ve hepsine aynı bastion'dan geçiliyor. Tek bir kural yeter:
Host 10.0.1.*
User deploy
ProxyJump bastion
IdentityFile ~/.ssh/id_ed25519
Böylece ssh 10.0.1.45, ssh 10.0.1.99 gibi her adres otomatik olarak bastion üzerinden atlar. Yüzlerce sunucu için tek tek Host tanımı yazmaktan kurtulursunuz. ProxyJump, çoğu senaryoda ProxyCommand ile netcat kombinasyonunun modern ve okunaklı yerine geçmiştir; artık elle tünel açmaya gerek yok.
Çok Atlamalı Zincirler#
Bazı ağlarda tek bir bastion yetmez. Örneğin dış bastion internete bakar, iç bastion ise sadece belirli bir alt ağa erişebilir ve asıl hedef en derinde durur. SSH bu tür çok katmanlı geçişleri virgülle ayrılmış zincir olarak destekler. Komut satırında:
ssh -J [email protected],[email protected] [email protected]
SSH bu zinciri soldan sağa işler: önce dış bastion, sonra iç bastion, en sonda hedef. Her adım bir öncekinin içinden tünellenir, dolayısıyla trafik uçtan uca korunur. Aynı zinciri config dosyasında da tanımlayabilirsiniz ve bu genellikle daha okunaklı olur:
Host dis-bastion
HostName dis-bastion.ornek.com
User kullanici
Host ic-bastion
HostName ic-bastion.local
User kullanici
ProxyJump dis-bastion
Host derin-sunucu
HostName 10.0.2.50
User deploy
ProxyJump ic-bastion
Burada güzel olan şey, ProxyJump ic-bastion yazdığınızda SSH'ın ic-bastion'ın kendi ProxyJump dis-bastion kuralını da özyinelemeli olarak takip etmesidir. Yani ssh derin-sunucu dediğinizde arka planda üç aşamalı zincir otomatik kurulur. Katman ne kadar derin olursa olsun, siz sadece son hedefin adını yazarsınız.
Çok atlamalı yapıların bir maliyeti gecikmedir; her ek atlama bağlantıya biraz gecikme ekler. Bu yüzden zinciri gerçekten ihtiyaç kadar tutun. Ayrıca bağlantıyı hızlandırmak için ControlMaster ile bağlantı çoğullama kullanabilirsiniz; böylece aynı bastion'a ikinci kez bağlandığınızda mevcut tünel yeniden kullanılır:
Host *
ControlMaster auto
ControlPath ~/.ssh/cm-%r@%h:%p
ControlPersist 10m
Bu ayar, kısa aralıklarla defalarca sunucuya girip çıktığınız deploy senaryolarında ciddi zaman kazandırır.
Agent Forwarding Riskleri#
Bastion üzerinden hedefe bağlanırken karşınıza çıkan doğal soru şudur: hedef sunucuya kimlik doğrulaması yaparken özel anahtarım nerede duracak? Kolay ama tehlikeli cevap ssh -A, yani agent forwarding'dir. Bu bayrak, yerel makinenizdeki SSH agent soketini bastion'a "yönlendirir" ve bastion, sizin anahtarınızı kullanarak sonraki bağlantıyı yapar. Kulağa pratik gelir, fakat ciddi bir risk taşır.
Agent forwarding açıkken, bağlandığınız bastion'da root yetkisine sahip bir saldırgan (ya da ele geçirilmiş bir süreç) sizin yönlendirilen agent soketinizi kullanarak sizin adınıza başka sunuculara bağlanabilir. Yani anahtarınızı çalmasa bile, siz bağlıyken onu kullanabilir. Bastion güvendiğiniz kadar güçlüdür ve tam da bu yüzden bastion'lar sıkı korunur; ama yine de tek noktaya bu kadar güven yüklemek istemezsiniz.
İşin iyi yanı, ProxyJump bu sorunu kökten çözer. -J veya ProxyJump kullandığınızda anahtar kimlik doğrulaması uçtan uca sizin makinenizde gerçekleşir; bastion sadece şifreli trafiği taşıyan bir boru gibidir, anahtarınızı hiç görmez. Dolayısıyla agent forwarding'e çoğu senaryoda hiç ihtiyacınız kalmaz. Pratik kural nettir:
# Tercih edilen: anahtar bastion'a asla dokunmaz
ssh -J kullanici@bastion kullanici@hedef
# Kaçınılması gereken: anahtar agent'ı bastion'a yönlenir
ssh -A kullanici@bastion
Eğer bir gerçekten agent forwarding'e mecbur kalırsanız, en azından ssh-agent'ı onay istemeli (ssh-add -c) modda kullanın; böylece her anahtar kullanımı için yerel makinenizde bir doğrulama penceresi açılır ve arka planda sessizce kötüye kullanım zorlaşır. Ayrıca bastion'ın sshd_config dosyasında AllowAgentForwarding no ayarını değerlendirin; ekibinizin bu riskli yola sapmasını en baştan engeller. Genel sunucu sertleştirme yaklaşımı için sunucu güvenliği temelleri rehberimiz iyi bir başlangıç noktasıdır.
Bastion Sunucuyu Sertleştirme#
Bastion tüm ağınızın kapısı olduğu için, onu sertleştirmek pazarlık konusu değildir. İlk kural parola girişini tamamen kapatmaktır; sadece anahtar tabanlı kimlik doğrulamaya izin verin. Bastion'ın /etc/ssh/sshd_config dosyasında şu ayarlar iyi bir temel oluşturur:
# /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AllowAgentForwarding no
X11Forwarding no
AllowTcpForwarding yes
MaxAuthTries 3
LoginGraceTime 20
AllowTcpForwarding yes satırı önemlidir; ProxyJump çalışabilmesi için bastion'ın port yönlendirmesine izin vermesi gerekir. Fakat bunun ötesinde bastion üzerinde interaktif kabuk açma imkânını kısıtlamak isterseniz, kullanıcıları sadece "geçiş" yapmakla sınırlayabilirsiniz. Aşağıdaki Match bloğu belirli bir grubu sadece atlama amaçlı kullanmaya zorlar; bastion üzerinde komut çalıştıramazlar, ama üzerinden geçebilirler:
Match Group atlama
ForceCommand /usr/sbin/nologin
PermitTTY no
AllowTcpForwarding yes
Buna ek olarak bastion'a erişebilen IP aralığını daraltın. Örneğin ofisinizin ya da VPN'inizin sabit IP bloğu dışından bağlantıyı güvenlik duvarında engelleyin. Böylece "internetten herkes deneyebilir" senaryosunu "sadece bilinen ağlardan denenebilir"e indirirsiniz. Yönetilen bir altyapıda bu tür sertleştirmeleri ekibimizle birlikte kurmak isterseniz sunucu yönetimi hizmetimiz devreye girebilir.
Son olarak günlüğe yazmayı ciddiye alın. Bastion, kim ne zaman geçti sorusunun cevabının bulunduğu yer olduğundan, journalctl -u ssh çıktısını merkezî bir log toplayıcıya gönderin. Bir olay incelemesinde tek bir makinenin logları size tüm erişim resmini verir. Bu merkezîliğin denetim gücü, bastion modelinin belki de en değerli yanıdır.
Yaygın Sorunlar ve Çözümleri#
Uygulamada en sık karşılaşılan sorun, hedefe atlarken "connection refused" ya da "no route to host" hatasıdır. Bunun nedeni genellikle hedef adresin sizin makinenizden değil, bastion'dan çözülmesi gerektiğini unutmaktır. -J kullandığınızda hedef adres bastion'ın gözünden değerlendirilir; yani 10.0.1.20 bastion'ın erişebildiği bir adres olmalıdır. Bunu doğrulamak için önce sadece bastion'a bağlanıp oradan ping 10.0.1.20 ya da nc -vz 10.0.1.20 22 deneyin.
İkinci sık sorun anahtar zinciridir. Bastion'a bir anahtar, hedefe başka bir anahtar gerekiyorsa, config dosyasında her Host için doğru IdentityFile satırını tanımlamalısınız. Aksi halde SSH varsayılan anahtarı her yerde denemeye çalışır ve "too many authentication failures" hatası alırsınız. IdentitiesOnly yes satırı, SSH'ı sadece belirttiğiniz anahtarı kullanmaya zorlayarak bu karmaşayı önler:
Host db1
HostName 10.0.1.20
User deploy
ProxyJump bastion
IdentityFile ~/.ssh/deploy_ed25519
IdentitiesOnly yes
Bağlantıyı ayrıntılı görmek için -v, hatta -vvv bayrağını ekleyin. Çıktı, hangi adımda takıldığınızı, hangi anahtarın denendiğini ve bastion'a mı yoksa hedefe mi ulaşamadığınızı net biçimde gösterir. Sorun giderirken en değerli aracınız budur:
ssh -vvv -J kullanici@bastion [email protected]
Bir başka pratik nokta da known_hosts yönetimidir. İç sunucular sık sık yeniden kurulduğunda host anahtarları değişir ve SSH güvenlik uyarısı verir. Otomatik deploy ortamlarında bu bir engel olabilir; ama körü körüne StrictHostKeyChecking no yapmak yerine, bilinen iç ağ için ayrı bir UserKnownHostsFile tutmak daha güvenli bir dengedir.
Sıkça Sorulan Sorular#
Bastion sunucu ile VPN arasındaki fark nedir#
Her ikisi de iç ağa güvenli erişim sağlar ama farklı katmanlarda çalışır. VPN, cihazınızı ağ seviyesinde iç ağa dahil eder ve tüm protokoller (HTTP, veritabanı, SSH) bu tünelden akar. Bastion ise sadece SSH bağlantılarına odaklanır ve uygulama seviyesinde tek bir geçit görevi görür. Bastion daha sade ve denetlenebilirdir; sadece SSH erişimi gerektiğinde VPN'in tüm karmaşasına girmeden aynı güvenliği sunar. Birçok ekip ikisini birlikte de kullanır.
ssh -J ile ProxyCommand arasındaki fark nedir#
ProxyCommand, atlama işini netcat gibi harici bir araçla elle tanımlamanız gereken eski yöntemdir ve okunması zordur. -J bayrağı ile eşdeğeri olan ProxyJump yönergesi ise OpenSSH'a yerleşik, temiz ve kısa bir söz dizimi sunar. Çoğu modern senaryoda ProxyJump her açıdan daha iyidir; sadece çok özel tünelleme ihtiyaçlarında ProxyCommand'a inmeniz gerekir. Yeni bir kurulumda doğrudan ProxyJump ile başlamanızı öneririm.
Bastion üzerinden dosya kopyalayabilir miyim#
Evet, scp ve sftp araçları da atlama zincirini destekler. scp için -o ProxyJump=kullanici@bastion seçeneğini ekleyebilir ya da doğrudan config dosyanızdaki host tanımını kullanabilirsiniz. Örneğin config'de db1 tanımlıysa, scp dosya.txt db1:/tmp/ komutu dosyayı bastion üzerinden hedefe kopyalar. rsync da aynı config'i otomatik okuduğu için ek ayara gerek kalmadan atlama üzerinden senkronizasyon yapar.
Agent forwarding gerçekten bu kadar riskli mi#
Kontrolsüz kullanıldığında evet. Yönlendirilmiş agent soketi, bağlandığınız makinede yetki sahibi birinin siz bağlıyken sizin anahtarınızı kullanmasına imkân verir. Ancak ProxyJump kullandığınızda agent forwarding'e hiç ihtiyacınız kalmaz, çünkü kimlik doğrulama uçtan uca sizin makinenizde gerçekleşir. Bu yüzden pratik tavsiye nettir: atlama için -A yerine -J kullanın ve agent forwarding'i yalnızca başka çareniz kalmadığında, onay istemeli modda açın.
Küçük bir işletme için bastion kurmak abartı mı olur#
Hayır, ölçeğe göre uyarlanabilir bir yaklaşımdır. Tek bir küçük VPS'i bile bastion olarak ayırıp arkadaki veritabanı ve uygulama sunucularının SSH portlarını dışarıya kapatmak, saldırı yüzeyinizi anında küçültür. Kurulum maliyeti düşük, kazanılan güvenlik yüksektir. İki üç sunucusu olan bir işletme bile bu modelden fayda görür; ilerledikçe aynı yapı yüz sunucuya kadar sorunsuz ölçeklenir.
Kapanış#
Bastion sunucu mimarisi, karmaşık gibi görünse de aslında tek bir sade fikre dayanır: iç ağa açılan tek ve iyi korunan bir kapı. ssh -J ile hızlı atlamayı, ~/.ssh/config içindeki ProxyJump ile kalıcı ve okunaklı yapılandırmayı, çok atlamalı zincirlerle derin ağlara ulaşmayı ve agent forwarding tuzağından kaçınmayı öğrendiğinizde, hem daha güvenli hem de daha denetlenebilir bir altyapıya sahip olursunuz. Tek noktadan geçiş, tek noktadan denetim ve tek noktadan iptal; bu üç kazanç, bastion modelini büyüyen her ekip için doğal bir tercih yapar.
Bu mimariyi kurmak için sağlam bir zemine ihtiyacınız var. Bastion ve arkasındaki iş yükleri için performanslı ve tam yetkili sunucular arıyorsanız VDS sunucu ve sanal sunucu seçeneklerimize göz atın; kurulum ve sertleştirmeyi bizim üstlenmemizi isterseniz sunucu yönetimi hizmetimiz devrede. Web tarafındaki iş yükleriniz için hosting paketlerimizi ve ek koruma için WAF ile DDoS koruma çözümlerimizi incelemenizi öneririm. Güvenli bir altyapı, tek bir iyi tasarlanmış kapıyla başlar.